diff options
505 files changed, 26092 insertions, 14172 deletions
diff --git a/.editorconfig b/.editorconfig index f9d819623d..15d6cbeab1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,7 @@ insert_final_newline = true # The settings for C (*.c and *.h) files are mirrored in .clang-format. Keep # them in sync. -[*.{c,h,sh,perl,pl,pm,txt}] +[{*.{c,h,sh,perl,pl,pm,txt},config.mak.*,Makefile}] indent_style = tab tab_width = 8 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7bacb322e4..3428773b09 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -159,7 +159,7 @@ jobs: if: failure() && env.FAILED_TEST_ARTIFACTS != '' uses: actions/upload-artifact@v4 with: - name: failed-tests-windows + name: failed-tests-windows-${{ matrix.nr }} path: ${{env.FAILED_TEST_ARTIFACTS}} vs-build: name: win+VS build @@ -250,7 +250,7 @@ jobs: if: failure() && env.FAILED_TEST_ARTIFACTS != '' uses: actions/upload-artifact@v4 with: - name: failed-tests-windows + name: failed-tests-windows-vs-${{ matrix.nr }} path: ${{env.FAILED_TEST_ARTIFACTS}} regular: name: ${{matrix.vector.jobname}} (${{matrix.vector.pool}}) @@ -266,6 +266,9 @@ jobs: - jobname: linux-sha256 cc: clang pool: ubuntu-latest + - jobname: linux-reftable + cc: clang + pool: ubuntu-latest - jobname: linux-gcc cc: gcc cc_package: gcc-8 @@ -277,6 +280,9 @@ jobs: - jobname: osx-clang cc: clang pool: macos-13 + - jobname: osx-reftable + cc: clang + pool: macos-13 - jobname: osx-gcc cc: gcc cc_package: gcc-13 @@ -287,6 +293,9 @@ jobs: - jobname: linux-leaks cc: gcc pool: ubuntu-latest + - jobname: linux-reftable-leaks + cc: gcc + pool: ubuntu-latest - jobname: linux-asan-ubsan cc: clang pool: ubuntu-latest diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43bfbd8834..c0fa2fe90b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,6 +26,9 @@ test:linux: - jobname: linux-sha256 image: ubuntu:latest CC: clang + - jobname: linux-reftable + image: ubuntu:latest + CC: clang - jobname: linux-gcc image: ubuntu:20.04 CC: gcc @@ -40,6 +43,9 @@ test:linux: - jobname: linux-leaks image: ubuntu:latest CC: gcc + - jobname: linux-reftable-leaks + image: ubuntu:latest + CC: gcc - jobname: linux-asan-ubsan image: ubuntu:latest CC: clang @@ -79,6 +85,9 @@ test:osx: - jobname: osx-clang image: macos-13-xcode-14 CC: clang + - jobname: osx-reftable + image: macos-13-xcode-14 + CC: clang artifacts: paths: - t/failed-test-artifacts @@ -152,6 +152,7 @@ Lars Doelle <lars.doelle@on-line ! de> Lars Doelle <lars.doelle@on-line.de> Lars Noschinski <lars@public.noschinski.de> <lars.noschinski@rwth-aachen.de> Li Hong <leehong@pku.edu.cn> +Linus Arver <linus@ucla.edu> <linusa@google.com> Linus Torvalds <torvalds@linux-foundation.org> <torvalds@evo.osdl.org> Linus Torvalds <torvalds@linux-foundation.org> <torvalds@g5.osdl.org> Linus Torvalds <torvalds@linux-foundation.org> <torvalds@osdl.org> diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index 578587a471..1d92b2da03 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -188,6 +188,22 @@ For shell scripts specifically (not exhaustive): hopefully nobody starts using "local" before they are reimplemented in C ;-) + - Some versions of shell do not understand "export variable=value", + so we write "variable=value" and then "export variable" on two + separate lines. + + - Some versions of dash have broken variable assignment when prefixed + with "local", "export", and "readonly", in that the value to be + assigned goes through field splitting at $IFS unless quoted. + + (incorrect) + local variable=$value + local variable=$(command args) + + (correct) + local variable="$value" + local variable="$(command args)" + - 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. @@ -446,12 +462,41 @@ For C programs: detail. - The first #include in C files, except in platform specific compat/ - implementations and sha1dc/, must be either "git-compat-util.h" or - one of the approved headers that includes it first for you. (The - approved headers currently include "builtin.h", - "t/helper/test-tool.h", "xdiff/xinclude.h", or - "reftable/system.h".) You do not have to include more than one of - these. + implementations and sha1dc/, must be <git-compat-util.h>. This + header file insulates other header files and source files from + platform differences, like which system header files must be + included in what order, and what C preprocessor feature macros must + be defined to trigger certain features we expect out of the system. + A collorary to this is that C files should not directly include + system header files themselves. + + There are some exceptions, because certain group of files that + implement an API all have to include the same header file that + defines the API and it is convenient to include <git-compat-util.h> + there. Namely: + + - the implementation of the built-in commands in the "builtin/" + directory that include "builtin.h" for the cmd_foo() prototype + definition, + + - the test helper programs in the "t/helper/" directory that include + "t/helper/test-tool.h" for the cmd__foo() prototype definition, + + - the xdiff implementation in the "xdiff/" directory that includes + "xdiff/xinclude.h" for the xdiff machinery internals, + + - the unit test programs in "t/unit-tests/" directory that include + "t/unit-tests/test-lib.h" that gives them the unit-tests + framework, and + + - the source files that implement reftable in the "reftable/" + directory that include "reftable/system.h" for the reftable + internals, + + are allowed to assume that they do not have to include + <git-compat-util.h> themselves, as it is included as the first + '#include' in these header files. These headers must be the first + header file to be "#include"d in them, though. - A C file must directly include the header files that declare the functions and the types it uses, except for the functions and types @@ -612,15 +657,15 @@ Writing Documentation: - Prefer succinctness and matter-of-factly describing functionality in the abstract. E.g. - --short:: Emit output in the short-format. + `--short`:: Emit output in the short-format. and avoid something like these overly verbose alternatives: - --short:: Use this to emit output in the short-format. - --short:: You can use this to get output in the short-format. - --short:: A user who prefers shorter output could.... - --short:: Should a person and/or program want shorter output, he - she/they/it can... + `--short`:: Use this to emit output in the short-format. + `--short`:: You can use this to get output in the short-format. + `--short`:: A user who prefers shorter output could.... + `--short`:: Should a person and/or program want shorter output, he + she/they/it can... This practice often eliminates the need to involve human actors in your description, but it is a good practice regardless of the @@ -630,12 +675,12 @@ Writing Documentation: addressing the hypothetical user, and possibly "we" when discussing how the program might react to the user. E.g. - You can use this option instead of --xyz, but we might remove + You can use this option instead of `--xyz`, but we might remove support for it in future versions. while keeping in mind that you can probably be less verbose, e.g. - Use this instead of --xyz. This option might be removed in future + Use this instead of `--xyz`. This option might be removed in future versions. - If you still need to refer to an example person that is @@ -653,63 +698,118 @@ Writing Documentation: The same general rule as for code applies -- imitate the existing conventions. - A few commented examples follow to provide reference when writing or - modifying command usage strings and synopsis sections in the manual - pages: - Placeholders are spelled in lowercase and enclosed in angle brackets: - <file> - --sort=<key> - --abbrev[=<n>] +Markup: + + Literal parts (e.g. use of command-line options, command names, + branch names, URLs, pathnames (files and directories), configuration and + environment variables) must be typeset as verbatim (i.e. wrapped with + backticks): + `--pretty=oneline` + `git rev-list` + `remote.pushDefault` + `http://git.example.com` + `.git/config` + `GIT_DIR` + `HEAD` + `umask`(2) + + An environment variable must be prefixed with "$" only when referring to its + value and not when referring to the variable itself, in this case there is + nothing to add except the backticks: + `GIT_DIR` is specified + `$GIT_DIR/hooks/pre-receive` + + Word phrases enclosed in `backtick characters` are rendered literally + and will not be further expanded. The use of `backticks` to achieve the + previous rule means that literal examples should not use AsciiDoc + escapes. + Correct: + `--pretty=oneline` + Incorrect: + `\--pretty=oneline` + + Placeholders are spelled in lowercase and enclosed in + angle brackets surrounded by underscores: + _<file>_ + _<commit>_ If a placeholder has multiple words, they are separated by dashes: - <new-branch-name> - --template=<template-directory> + _<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++ + + caveat: ++ unconstrained format is not verbatim and may expand + content. Use Asciidoc escapes inside them. + +Synopsis Syntax + + Syntax grammar is formatted neither as literal nor as placeholder. + + 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>] + ++--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 @@ -720,37 +820,6 @@ Writing Documentation: the user would type into a shell and use 'Git' (uppercase first letter) when talking about the version control system and its properties. - A few commented examples follow to provide reference when writing or - modifying paragraphs or option/command explanations that contain options - or commands: - - Literal examples (e.g. use of command-line options, command names, - branch names, URLs, pathnames (files and directories), configuration and - environment variables) must be typeset in monospace (i.e. wrapped with - backticks): - `--pretty=oneline` - `git rev-list` - `remote.pushDefault` - `http://git.example.com` - `.git/config` - `GIT_DIR` - `HEAD` - - An environment variable must be prefixed with "$" only when referring to its - value and not when referring to the variable itself, in this case there is - nothing to add except the backticks: - `GIT_DIR` is specified - `$GIT_DIR/hooks/pre-receive` - - Word phrases enclosed in `backtick characters` are rendered literally - and will not be further expanded. The use of `backticks` to achieve the - previous rule means that literal examples should not use AsciiDoc - escapes. - Correct: - `--pretty=oneline` - Incorrect: - `\--pretty=oneline` - If some place in the documentation needs to typeset a command usage example with inline substitutions, it is fine to use +monospaced and inline substituted text+ instead of `monospaced literal text`, and with diff --git a/Documentation/MyFirstObjectWalk.txt b/Documentation/MyFirstObjectWalk.txt index c68cdb11b9..dec8afe5b1 100644 --- a/Documentation/MyFirstObjectWalk.txt +++ b/Documentation/MyFirstObjectWalk.txt @@ -210,13 +210,14 @@ We'll also need to include the `config.h` header: ... -static int git_walken_config(const char *var, const char *value, void *cb) +static int git_walken_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { /* * For now, we don't have any custom configuration, so fall back to * the default config. */ - return git_default_config(var, value, cb); + return git_default_config(var, value, ctx, cb); } ---- @@ -389,10 +390,11 @@ modifying `rev_info.grep_filter`, which is a `struct grep_opt`. First some setup. Add `grep_config()` to `git_walken_config()`: ---- -static int git_walken_config(const char *var, const char *value, void *cb) +static int git_walken_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) { - grep_config(var, value, cb); - return git_default_config(var, value, cb); + grep_config(var, value, ctx, cb); + return git_default_config(var, value, ctx, cb); } ---- @@ -523,7 +525,7 @@ about each one. We can base our work on an example. `git pack-objects` prepares all kinds of objects for packing into a bitmap or packfile. The work we are interested in -resides in `builtins/pack-objects.c:get_object_list()`; examination of that +resides in `builtin/pack-objects.c:get_object_list()`; examination of that function shows that the all-object walk is being performed by `traverse_commit_list()` or `traverse_commit_list_filtered()`. Those two functions reside in `list-objects.c`; examining the source shows that, despite @@ -732,8 +734,8 @@ walk we've just performed: } else { trace_printf( _("Filtered object walk with filterspec 'tree:1'.\n")); - CALLOC_ARRAY(rev->filter, 1); - parse_list_objects_filter(rev->filter, "tree:1"); + + parse_list_objects_filter(&rev->filter, "tree:1"); } traverse_commit_list(rev, walken_show_commit, walken_show_object, NULL); @@ -752,10 +754,12 @@ points to the same tree object as its grandparent.) === Counting Omitted Objects We also have the capability to enumerate all objects which were omitted by a -filter, like with `git log --filter=<spec> --filter-print-omitted`. Asking -`traverse_commit_list_filtered()` to populate the `omitted` list means that our -object walk does not perform any better than an unfiltered object walk; all -reachable objects are walked in order to populate the list. +filter, like with `git log --filter=<spec> --filter-print-omitted`. To do this, +change `traverse_commit_list()` to `traverse_commit_list_filtered()`, which is +able to populate an `omitted` list. Asking for this list of filtered objects +may cause performance degradations, however, because in this case, despite +filtering objects, the possibly much larger set of all reachable objects must +be processed in order to populate that list. First, add the `struct oidset` and related items we will use to iterate it: @@ -776,8 +780,9 @@ static void walken_object_walk( ... ---- -Modify the call to `traverse_commit_list_filtered()` to include your `omitted` -object: +Replace the call to `traverse_commit_list()` with +`traverse_commit_list_filtered()` and pass a pointer to the `omitted` oidset +defined and initialized above: ---- ... @@ -843,7 +848,7 @@ those lines without having to recompile. With only that change, run again (but save yourself some scrollback): ---- -$ GIT_TRACE=1 ./bin-wrappers/git walken | head -n 10 +$ GIT_TRACE=1 ./bin-wrappers/git walken 2>&1 | head -n 10 ---- Take a look at the top commit with `git show` and the object ID you printed; it @@ -871,7 +876,7 @@ of the first handful: ---- $ make -$ GIT_TRACE=1 ./bin-wrappers git walken | tail -n 10 +$ GIT_TRACE=1 ./bin-wrappers/git walken 2>&1 | tail -n 10 ---- The last commit object given should have the same OID as the one we saw at the diff --git a/Documentation/RelNotes/2.43.3.txt b/Documentation/RelNotes/2.43.3.txt new file mode 100644 index 0000000000..924f20594f --- /dev/null +++ b/Documentation/RelNotes/2.43.3.txt @@ -0,0 +1,12 @@ +Git 2.43.3 Release Notes +======================== + +Relative to Git 2.43.2, this release fixes one regression that +manifests while running "git commit -v --trailer". + +Fixes since Git 2.43.2 +---------------------- + + * "git commit -v --trailer=..." was broken with recent update and + placed the trailer _after_ the divider line, which has been + corrected. diff --git a/Documentation/RelNotes/2.45.0.txt b/Documentation/RelNotes/2.45.0.txt new file mode 100644 index 0000000000..fec193679f --- /dev/null +++ b/Documentation/RelNotes/2.45.0.txt @@ -0,0 +1,476 @@ +Git v2.45 Release Notes +======================= + +Backward Compatibility Notes + +UI, Workflows & Features + + * Integrate the reftable code into the refs framework as a backend. + 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 + for "HEAD". + + * Variants of vimdiff learned to honor mergetool.<variant>.layout + settings. + + * "git reflog" learned a "list" subcommand that enumerates known reflogs. + + * When a merge conflicted at a submodule, merge-ort backend used to + unconditionally give a lengthy message to suggest how to resolve + it. Now the message can be squelched as an advice message. + + * "git for-each-ref" learned "--include-root-refs" option to show + even the stuff outside the 'refs/' hierarchy. + + * "git rev-list --missing=print" has learned to optionally take + "--allow-missing-tips", which allows the objects at the starting + points to be missing. + + * "git merge-tree" has learned that the three trees involved in the + 3-way merge only need to be trees, not necessarily commits. + + * "git log --merge" learned to pay attention to CHERRY_PICK_HEAD and + other kinds of *_HEAD pseudorefs. + + * Platform specific tweaks for OS/390 has been added to + config.mak.uname. + + * Users with safe.bareRepository=explicit can still work from within + $GIT_DIR of a seconary worktree (which resides at .git/worktrees/$name/) + of the primary worktree without explicitly specifying the $GIT_DIR + environment variable or the --git-dir=<path> option. + + * The output format for dates "iso-strict" has been tweaked to show + a time in the Zulu timezone with "Z" suffix, instead of "+00:00". + + * "git diff" and friends learned two extra configuration variables, + diff.srcPrefix and diff.dstPrefix. + + * The status.showUntrackedFiles configuration variable had a name + that tempts users to set a Boolean value expressed in our usual + "false", "off", and "0", but it only took "no". This has been + corrected so "true" and its synonyms are taken as "normal", while + "false" and its synonyms are taken as "no". + + * Remove an ancient and not well maintained Hg-to-git migration + script from contrib/. + + * Hints that suggest what to do after resolving conflicts can now be + squelched by disabling advice.mergeConflict. + + * Allow git-cherry-pick(1) to automatically drop redundant commits via + a new `--empty` option, similar to the `--empty` options for + git-rebase(1) and git-am(1). Includes a soft deprecation of + `--keep-redundant-commits` as well as some related docs changes and + sequencer code cleanup. + + * "git config" learned "--comment=<message>" option to leave a + comment immediately after the "variable = value" on the same line + in the configuration file. + + * core.commentChar used to be limited to a single byte, but has been + updated to allow an arbitrary multi-byte sequence. + + * "git add -p" and other "interactive hunk selection" UI has learned to + skip showing the hunk immediately after it has already been shown, and + an additional action to explicitly ask to reshow the current hunk. + + * "git pack-refs" learned the "--auto" option, which defers the decision of + whether and how to pack to the ref backend. This is used by the reftable + backend to avoid repacking of an already-optimal ref database. The new mode + is triggered from "git gc --auto". + + * "git add -u <pathspec>" and "git commit [-i] <pathspec>" did not + diagnose a pathspec element that did not match any files in certain + situations, unlike "git add <pathspec>" did. + + * The userdiff patterns for C# has been updated. + + * Git writes a "waiting for your editor" message on an incomplete + line after launching an editor, and then append another error + message on the same line if the editor errors out. It now clears + the "waiting for..." line before giving the error message. + + * The filename used for rejected hunks "git apply --reject" creates + was limited to PATH_MAX, which has been lifted. + + * When "git bisect" reports the commit it determined to be the + culprit, we used to show it in a format that does not honor common + UI tweaks, like log.date and log.decorate. The code has been + taught to use "git show" to follow more customizations. + + +Performance, Internal Implementation, Development Support etc. + + * The code to iterate over refs with the reftable backend has seen + some optimization. + + * More tests that are marked as "ref-files only" have been updated to + improve test coverage of reftable backend. + + * Some parts of command line completion script (in contrib/) have + been micro-optimized. + + * The way placeholders are to be marked-up in documentation have been + specified; use "_<placeholder>_" to typeset the word inside a pair + of <angle-brackets> emphasized. + + * "git --no-lazy-fetch cmd" allows to run "cmd" while disabling lazy + fetching of objects from the promisor remote, which may be handy + for debugging. + + * The implementation in "git clean" that makes "-n" and "-i" ignore + clean.requireForce has been simplified, together with the + documentation. + + * Uses of xwrite() helper have been audited and updated for better + error checking and simpler code. + + * Some trace2 events that lacked def_param have learned to show it, + enriching the output. + + * The parse-options code that deals with abbreviated long option + names have been cleaned up. + + * The code in reftable backend that creates new table files works + better with the tempfile framework to avoid leaving cruft after a + failure. + + * The reftable code has its own custom binary search function whose + comparison callback has an unusual interface, which caused the + binary search to degenerate into a linear search, which has been + corrected. + + * The code to iterate over reflogs in the reftable has been optimized + to reduce memory allocation and deallocation. + + * Work to support a repository that work with both SHA-1 and SHA-256 + hash algorithms has started. + + * A new fuzz target that exercises config parsing code has been + added. + + * Fix the way recently added tests interpolate variables defined + outside them, and document the best practice to help future + developers. + + * Introduce an experimental protocol for contributors to propose the + topic description to be used in the "What's cooking" report, the + merge commit message for the topic, and in the release notes and + document it in the SubmittingPatches document. + + * The t/README file now gives a hint on running individual tests in + the "t/" directory with "make t<num>-*.sh t<num>-*.sh". + (merge 8d383806fc pb/test-scripts-are-build-targets later to maint). + + * The "hint:" messages given by the advice mechanism, when given a + message with a blank line, left a line with trailing whitespace, + which has been cleansed. + + * Documentation rules has been explicitly described how to mark-up + literal parts and a few manual pages have been updated as examples. + + * The .editorconfig file has been taught that a Makefile uses HT + indentation. + + * t-prio-queue test has been cleaned up by using C99 compound + literals; this is meant to also serve as a weather-balloon to smoke + out folks with compilers who have trouble compiling code that uses + the feature. + + * Windows binary used to decide the use of unix-domain socket at + build time, but it learned to make the decision at runtime instead. + + * The "shared repository" test in the t0610 reftable test failed + under restrictive umask setting (e.g. 007), which has been + corrected. + + * Document and apply workaround for a buggy version of dash that + mishandles "local var=val" construct. + + * The codepaths that reach date_mode_from_type() have been updated to + pass "struct date_mode" by value to make them thread safe. + + * The strategy to compact multiple tables of reftables after many + operations accumulate many entries has been improved to avoid + accumulating too many tables uncollected. + + * The code to iterate over reftable blocks has seen some optimization + to reduce memory allocation and deallocation. + + * The way "git fast-import" handles paths described in its input has + been tightened up and more clearly documented. + + * The cvsimport tests required that the platform understands + traditional timezone notations like CST6CDT, which has been + updated to work on those systems as long as they understand + POSIX notation with explicit tz transition dates. + + * The code to format trailers have been cleaned up. + + +Fixes since v2.44 +----------------- + + * "git apply" on a filesystem without filemode support have learned + to take a hint from what is in the index for the path, even when + not working with the "--index" or "--cached" option, when checking + the executable bit match what is required by the preimage in the + patch. + (merge 45b625142d cp/apply-core-filemode later to maint). + + * "git column" has been taught to reject negative padding value, as + it would lead to nonsense behaviour including division by zero. + (merge 76fb807faa kh/column-reject-negative-padding later to maint). + + * "git am --help" now tells readers what actions are available in + "git am --whitespace=<action>", in addition to saying that the + option is passed through to the underlying "git apply". + (merge a171dac734 jc/am-whitespace-doc later to maint). + + * "git tag --column" failed to check the exit status of its "git + column" invocation, which has been corrected. + (merge 92e66478fc rj/tag-column-fix later to maint). + + * Credential helper based on libsecret (in contrib/) has been updated + to handle an empty password correctly. + (merge 8f1f2023b7 mh/libsecret-empty-password-fix later to maint). + + * "git difftool --dir-diff" learned to honor the "--trust-exit-code" + option; it used to always exit with 0 and signalled success. + (merge eb84c8b6ce ps/difftool-dir-diff-exit-code later to maint). + + * The code incorrectly attempted to use textconv cache when asked, + even when we are not running in a repository, which has been + corrected. + (merge affe355fe7 jk/textconv-cache-outside-repo-fix later to maint). + + * Remove an empty file that shouldn't have been added in the first + place. + (merge 4f66942215 js/remove-cruft-files later to maint). + + * The logic to access reflog entries by date and number had ugly + corner cases at the boundaries, which have been cleaned up. + (merge 5edd126720 jk/reflog-special-cases-fix later to maint). + + * An error message from "git upload-pack", which responds to "git + fetch" requests, had a trailing NUL in it, which has been + corrected. + (merge 3f4c7a0805 sg/upload-pack-error-message-fix later to maint). + + * Clarify wording in the CodingGuidelines that requires <git-compat-util.h> + to be the first header file. + (merge 4e89f0e07c jc/doc-compat-util later to maint). + + * "git commit -v --cleanup=scissors" used to add the scissors line + twice in the log message buffer, which has been corrected. + (merge e90cc075cc jt/commit-redundant-scissors-fix later to maint). + + * A custom remote helper no longer cannot access the newly created + repository during "git clone", which is a regression in Git 2.44. + This has been corrected. + (merge 199f44cb2e ps/remote-helper-repo-initialization-fix later to maint). + + * Various parts of upload-pack have been updated to bound the resource + consumption relative to the size of the repository to protect from + abusive clients. + (merge 6cd05e768b jk/upload-pack-bounded-resources later to maint). + + * The upload-pack program, when talking over v2, accepted the + packfile-uris protocol extension from the client, even if it did + not advertise the capability, which has been corrected. + (merge a922bfa3b5 jk/upload-pack-v2-capability-cleanup later to maint). + + * Make sure failure return from merge_bases_many() is properly caught. + (merge 25fd20eb44 js/merge-base-with-missing-commit later to maint). + + * FSMonitor client code was confused when FSEvents were given in a + different case on a case-insensitive filesystem, which has been + corrected. + (merge 29c139ce78 jh/fsmonitor-icase-corner-case-fix later to maint). + + * The "core.commentChar" configuration variable only allows an ASCII + character, which was not clearly documented, which has been + corrected. + (merge fb7c556f58 kh/doc-commentchar-is-a-byte later to maint). + + * With release 2.44 we got rid of all uses of test_i18ngrep and there + is no in-flight topic that adds a new use of it. Make a call to + test_i18ngrep a hard failure, so that we can remove it at the end + of this release cycle. + (merge 381a83dfa3 jc/test-i18ngrep later to maint). + + * The command line completion script (in contrib/) learned to + complete "git reflog" better. + (merge 1284f9cc11 rj/complete-reflog later to maint). + + * The logic to complete the command line arguments to "git worktree" + subcommand (in contrib/) has been updated to correctly honor things + like "git -C dir" etc. + (merge 3574816d98 rj/complete-worktree-paths-fix later to maint). + + * When git refuses to create a branch because the proposed branch + name is not a valid refname, an advice message is given to refer + the user to exact naming rules. + (merge 8fbd903e58 kh/branch-ref-syntax-advice later to maint). + + * Code simplification by getting rid of code that sets an environment + variable that is no longer used. + (merge 72a8d3f027 pw/rebase-i-ignore-cherry-pick-help-environment later to maint). + + * The code to find the effective end of log messages can fall into an + endless loop, which has been corrected. + (merge 2541cba2d6 fs/find-end-of-log-message-fix later to maint). + + * Mark-up used in the documentation has been improved for + consistency. + (merge 45d5ed3e50 ja/doc-markup-fixes later to maint). + + * The status.showUntrackedFiles configuration variable was + incorrectly documented to accept "false", which has been corrected. + + * Leaks from "git restore" have been plugged. + (merge 2f64da0790 rj/restore-plug-leaks later to maint). + + * "git bugreport --no-suffix" was not supported and instead + segfaulted, which has been corrected. + (merge b3b57c69da js/bugreport-no-suffix-fix later to maint). + + * The documentation for "%(trailers[:options])" placeholder in the + "--pretty" option of commands in the "git log" family has been + updated. + (merge bff85a338c bl/doc-key-val-sep-fix later to maint). + + * "git checkout --conflict=bad" reported a bad conflictStyle as if it + were given to a configuration variable; it has been corrected to + report that the command line option is bad. + (merge 5a99c1ac1a pw/checkout-conflict-errorfix later to maint). + + * Code clean-up in the "git log" machinery that implements custom log + message formatting. + (merge 1c10b8e5b0 jk/pretty-subject-cleanup later to maint). + + * "git config" corrupted literal HT characters written in the + configuration file as part of a value, which has been corrected. + (merge e6895c3f97 ds/config-internal-whitespace-fix later to maint). + + * A unit test for reftable code tried to enumerate all files in a + directory after reftable operations and expected to see nothing but + the files it wanted to leave there, but was fooled by .nfs* cruft + files left, which has been corrected. + (merge 0068aa7946 ps/reftable-unit-test-nfs-workaround later to maint). + + * The implementation and documentation of "object-format" option + exchange between the Git itself and its remote helpers did not + quite match, which has been corrected. + + * The "--pretty=<shortHand>" option of the commands in the "git log" + family, defined as "[pretty] shortHand = <expansion>" should have + been looked up case insensitively, but was not, which has been + corrected. + (merge f999d5188b bl/pretty-shorthand-config-fix later to maint). + + * "git apply" failed to extract the filename the patch applied to, + when the change was about an empty file created in or deleted from + a directory whose name ends with a SP, which has been corrected. + (merge 776ffd1a30 jc/apply-parse-diff-git-header-names-fix later to maint). + + * Update a more recent tutorial doc. + (merge 95ab557b4b dg/myfirstobjectwalk-updates later to maint). + + * The test script had an incomplete and ineffective attempt to avoid + clobbering the testing user's real crontab (and its equivalents), + which has been completed. + (merge 73cb87773b es/test-cron-safety later to maint). + + * Use advice_if_enabled() API to rewrite a simple pattern to + call advise() after checking advice_enabled(). + (merge 6412d01527 rj/use-adv-if-enabled later to maint). + + * Another "set -u" fix for the bash prompt (in contrib/) script. + (merge d7805bc743 vs/complete-with-set-u-fix later to maint). + + * "git checkout/switch --detach foo", after switching to the detached + HEAD state, gave the tracking information for the 'foo' branch, + which was pointless. + + * "git apply" has been updated to lift the hardcoded pathname length + limit, which in turn allowed a mksnpath() function that is no + longer used. + (merge 708f7e0590 rs/apply-lift-path-length-limit later to maint). + + * A file descriptor leak in an error codepath, used when "git apply + --reject" fails to create the *.rej file, has been corrected. + (merge 2b1f456adf rs/apply-reject-fd-leakfix later to maint). + + * A config parser callback function fell through instead of returning + after recognising and processing a variable, wasting cycles, which + has been corrected. + (merge a816ccd642 ds/fetch-config-parse-microfix later to maint). + + * Fix was added to work around a regression in libcURL 8.7.0 (which has + already been fixed in their tip of the tree). + (merge 92a209bf24 jk/libcurl-8.7-regression-workaround later to maint). + + * The variable that holds the value read from the core.excludefile + configuration variable used to leak, which has been corrected. + (merge 0e0fefb29f jc/unleak-core-excludesfile later to maint). + + * vreportf(), which is used by error() and friends, has been taught + to give the error message printf-format string when its vsnprintf() + call fails, instead of showing nothing useful to identify the + nature of the error. + (merge c63adab961 rs/usage-fallback-to-show-message-format later to maint). + + * Adjust to an upcoming changes to GNU make that breaks our Makefiles. + (merge 227b8fd902 tb/make-indent-conditional-with-non-spaces later to maint). + + * Git 2.44 introduced a regression that makes the updated code to + barf in repositories with multi-pack index written by older + versions of Git, which has been corrected. + + * When .git/rr-cache/ rerere database gets corrupted or rerere is fed to + work on a file with conflicted hunks resolved incompletely, the rerere + machinery got confused and segfaulted, which has been corrected. + (merge 167395bb47 mr/rerere-crash-fix later to maint). + + * The "receive-pack" program (which responds to "git push") was not + converted to run "git maintenance --auto" when other codepaths that + used to run "git gc --auto" were updated, which has been corrected. + (merge 7bf3057d9c ps/run-auto-maintenance-in-receive-pack later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge f0e578c69c rs/use-xstrncmpz later to maint). + (merge 83e6eb7d7a ba/credential-test-clean-fix later to maint). + (merge 64562d784d jb/doc-interactive-singlekey-do-not-need-perl later to maint). + (merge c431a235e2 cp/t9146-use-test-path-helpers later to maint). + (merge 82d75402d5 ds/doc-send-email-capitalization later to maint). + (merge 41bff66e35 jc/doc-add-placeholder-fix later to maint). + (merge 6835f0efe9 jw/remote-doc-typofix later to maint). + (merge 244001aa20 hs/rebase-not-in-progress later to maint). + (merge 2ca6c07db2 jc/no-include-of-compat-util-from-headers later to maint). + (merge 87bd7fbb9c rs/fetch-simplify-with-starts-with later to maint). + (merge f39addd0d9 rs/name-rev-with-mempool later to maint). + (merge 9a97b43e03 rs/submodule-prefix-simplify later to maint). + (merge 40b8076462 ak/rebase-autosquash later to maint). + (merge 3223204456 eg/add-uflags later to maint). + (merge 5f78d52dce es/config-doc-sort-sections later to maint). + (merge 781fb7b4c2 as/option-names-in-messages later to maint). + (merge 51d41dc243 jk/doc-remote-helpers-markup-fix later to maint). + (merge e1aaf309db pb/ci-win-artifact-names-fix later to maint). + (merge ad538c61da jc/index-pack-fsck-levels later to maint). + (merge 67471bc704 ja/doc-formatting-fix later to maint). + (merge 86f9ce7dd6 bl/doc-config-fixes later to maint). + (merge 0d527842b7 az/grep-group-error-message-update later to maint). + (merge 7c43bdf07b rs/strbuf-expand-bad-format later to maint). + (merge 8b68b48d5c ds/typofix-core-config-doc later to maint). + (merge 39bb692152 rs/imap-send-use-xsnprintf later to maint). + (merge 8d320cec60 jc/t2104-style-fixes later to maint). + (merge b4454d5a7b pw/t3428-cleanup later to maint). + (merge 84a7c33a4b pf/commitish-committish later to maint). + (merge 8882ee9d68 la/mailmap-entry later to maint). + (merge 44bdba2fa6 rs/no-openssl-compilation-fix-on-macos later to maint). + (merge f412d72c19 yb/replay-doc-linkfix later to maint). + (merge 5da40be8d7 xx/rfc2822-date-format-in-doc later to maint). diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index e734a3f0f1..c647c7e1b4 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -459,6 +459,18 @@ an explanation of changes between each iteration can be kept in Git-notes and inserted automatically following the three-dash line via `git format-patch --notes`. +[[the-topic-summary]] +*This is EXPERIMENTAL*. + +When sending a topic, you can propose a one-paragraph summary that +should appear in the "What's cooking" report when it is picked up to +explain the topic. If you choose to do so, please write a 2-5 line +paragraph that will fit well in our release notes (see many bulleted +entries in the Documentation/RelNotes/* files for examples), and make +it the first paragraph of the cover letter. For a single-patch +series, use the space between the three-dash line and the diffstat, as +described earlier. + [[attachment]] Do not attach the patch as a MIME attachment, compressed or not. Do not let your e-mail client send quoted-printable. Do not let diff --git a/Documentation/config.txt b/Documentation/config.txt index e3a74dd1c1..70b448b132 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -22,9 +22,10 @@ multivalued. Syntax ~~~~~~ -The syntax is fairly flexible and permissive; whitespaces are mostly -ignored. The '#' and ';' characters begin comments to the end of line, -blank lines are ignored. +The syntax is fairly flexible and permissive. Whitespace characters, +which in this context are the space character (SP) and the horizontal +tabulation (HT), are mostly ignored. The '#' and ';' characters begin +comments to the end of line. Blank lines are ignored. The file consists of sections and variables. A section begins with the name of the section in square brackets and continues until the next @@ -63,16 +64,17 @@ the variable is the boolean "true"). The variable names are case-insensitive, allow only alphanumeric characters and `-`, and must start with an alphabetic character. -A line that defines a value can be continued to the next line by -ending it with a `\`; the backslash and the end-of-line are -stripped. Leading whitespaces after 'name =', the remainder of the -line after the first comment character '#' or ';', and trailing -whitespaces of the line are discarded unless they are enclosed in -double quotes. Internal whitespaces within the value are retained -verbatim. +Whitespace characters surrounding `name`, `=` and `value` are discarded. +Internal whitespace characters within 'value' are retained verbatim. +Comments starting with either `#` or `;` and extending to the end of line +are discarded. A line that defines a value can be continued to the next +line by ending it with a backslash (`\`); the backslash and the end-of-line +characters are discarded. -Inside double quotes, double quote `"` and backslash `\` characters -must be escaped: use `\"` for `"` and `\\` for `\`. +If `value` needs to contain leading or trailing whitespace characters, +it must be enclosed in double quotation marks (`"`). Inside double quotation +marks, double quote (`"`) and backslash (`\`) characters must be escaped: +use `\"` for `"` and `\\` for `\`. The following escape sequences (beside `\"` and `\\`) are recognized: `\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB) @@ -369,20 +371,18 @@ inventing new variables for use in your own tool, make sure their names do not conflict with those that are used by Git itself and other popular tools, and describe them in your documentation. -include::config/advice.txt[] - -include::config/attr.txt[] - -include::config/core.txt[] - include::config/add.txt[] +include::config/advice.txt[] + include::config/alias.txt[] include::config/am.txt[] include::config/apply.txt[] +include::config/attr.txt[] + include::config/blame.txt[] include::config/branch.txt[] @@ -405,10 +405,12 @@ include::config/commit.txt[] include::config/commitgraph.txt[] -include::config/credential.txt[] - include::config/completion.txt[] +include::config/core.txt[] + +include::config/credential.txt[] + include::config/diff.txt[] include::config/difftool.txt[] @@ -421,10 +423,10 @@ include::config/feature.txt[] include::config/fetch.txt[] -include::config/format.txt[] - include::config/filter.txt[] +include::config/format.txt[] + include::config/fsck.txt[] include::config/fsmonitor--daemon.txt[] @@ -435,10 +437,10 @@ include::config/gitcvs.txt[] include::config/gitweb.txt[] -include::config/grep.txt[] - include::config/gpg.txt[] +include::config/grep.txt[] + include::config/gui.txt[] include::config/guitool.txt[] @@ -519,10 +521,10 @@ include::config/splitindex.txt[] include::config/ssh.txt[] -include::config/status.txt[] - include::config/stash.txt[] +include::config/status.txt[] + include::config/submodule.txt[] include::config/tag.txt[] diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt index c7ea70f2e2..0e35ae5240 100644 --- a/Documentation/config/advice.txt +++ b/Documentation/config/advice.txt @@ -2,27 +2,27 @@ 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 do not need the help message by setting these to `false`: + -- addEmbeddedRepo:: - Advice on what to do when you've accidentally added one + Shown when the user accidentally adds one git repo inside of another. addEmptyPathspec:: - Advice shown if a user runs the add command without providing + Shown when the user runs `git add` without providing the pathspec parameter. addIgnoredFile:: - Advice shown if a user attempts to add an ignored file to + Shown when the user attempts to add an ignored file to the index. amWorkDir:: - Advice that shows the location of the patch file when - linkgit:git-am[1] fails to apply it. + Shown when linkgit:git-am[1] fails to apply a patch + file, to tell the user the location of the file. ambiguousFetchRefspec:: - Advice shown when a fetch refspec for multiple remotes maps to + Shown when a fetch refspec for multiple remotes maps to the same remote-tracking branch namespace and causes branch tracking set-up to fail. checkoutAmbiguousRemoteBranchName:: - Advice shown when the argument to + Shown when the argument to linkgit:git-checkout[1] and linkgit:git-switch[1] ambiguously resolves to a remote tracking branch on more than one remote in @@ -33,31 +33,33 @@ advice.*:: to be used by default in some situations where this advice would be printed. commitBeforeMerge:: - Advice shown when linkgit:git-merge[1] refuses to + Shown when linkgit:git-merge[1] refuses to merge to avoid overwriting local changes. detachedHead:: - Advice shown when you used + Shown when the user uses linkgit:git-switch[1] or linkgit:git-checkout[1] - to move to the detached HEAD state, to instruct how to - create a local branch after the fact. + to move to the detached HEAD state, to tell the user how + to create a local branch after the fact. diverging:: - Advice shown when a fast-forward is not possible. + Shown when a fast-forward is not possible. fetchShowForcedUpdates:: - Advice shown when linkgit:git-fetch[1] takes a long time + Shown when linkgit:git-fetch[1] takes a long time to calculate forced updates after ref updates, or to warn that the check is disabled. forceDeleteBranch:: - Advice shown when a user tries to delete a not fully merged + Shown when the user tries to delete a not fully merged branch without the force option set. ignoredHook:: - Advice shown if a hook is ignored because the hook is not + Shown when a hook is ignored because the hook is not set as executable. implicitIdentity:: - Advice on how to set your identity configuration when - your information is guessed from the system username and - domain name. + Shown when the user's information is guessed from the + system username and domain name, to tell the user how to + set their identity configuration. + mergeConflict:: + Shown when various commands stop because of conflicts. nestedTag:: - Advice shown if a user attempts to recursively tag a tag object. + Shown when a user attempts to recursively tag a tag object. pushAlreadyExists:: Shown when linkgit:git-push[1] rejects an update that does not qualify for fast-forwarding (e.g., a tag.) @@ -71,12 +73,12 @@ advice.*:: object that is not a commit-ish, or make the remote ref point at an object that is not a commit-ish. pushNonFFCurrent:: - Advice shown when linkgit:git-push[1] fails due to a + Shown when linkgit:git-push[1] fails due to a non-fast-forward update to the current branch. pushNonFFMatching:: - Advice shown when you ran linkgit:git-push[1] and pushed - 'matching refs' explicitly (i.e. you used ':', or - specified a refspec that isn't your current branch) and + Shown when the user ran linkgit:git-push[1] and pushed + "matching refs" explicitly (i.e. used `:`, or + specified a refspec that isn't the current branch) and it resulted in a non-fast-forward error. pushRefNeedsUpdate:: Shown when linkgit:git-push[1] rejects a forced update of @@ -87,25 +89,28 @@ advice.*:: guess based on the source and destination refs what remote ref namespace the source belongs in, but where we can still suggest that the user push to either - refs/heads/* or refs/tags/* based on the type of the + `refs/heads/*` or `refs/tags/*` based on the type of the source object. pushUpdateRejected:: - Set this variable to 'false' if you want to disable - 'pushNonFFCurrent', 'pushNonFFMatching', 'pushAlreadyExists', - 'pushFetchFirst', 'pushNeedsForce', and 'pushRefNeedsUpdate' + Set this variable to `false` if you want to disable + `pushNonFFCurrent`, `pushNonFFMatching`, `pushAlreadyExists`, + `pushFetchFirst`, `pushNeedsForce`, and `pushRefNeedsUpdate` simultaneously. + refSyntax:: + Shown when the user provides an illegal ref name, to + tell the user about the ref syntax documentation. resetNoRefresh:: - Advice to consider using the `--no-refresh` option to - linkgit:git-reset[1] when the command takes more than 2 seconds - to refresh the index after reset. + Shown when linkgit:git-reset[1] takes more than 2 + seconds to refresh the index after reset, to tell the user + that they can use the `--no-refresh` option. resolveConflict:: - Advice shown by various commands when conflicts + Shown by various commands when conflicts prevent the operation from being performed. rmHints:: - In case of failure in the output of linkgit:git-rm[1], - show directions on how to proceed from the current state. + Shown on failure in the output of linkgit:git-rm[1], to + give directions on how to proceed from the current state. sequencerInUse:: - Advice shown when a sequencer command is already in progress. + Shown when a sequencer command is already in progress. skippedCherryPicks:: Shown when linkgit:git-rebase[1] skips a commit that has already been cherry-picked onto the upstream branch. @@ -123,27 +128,30 @@ advice.*:: by linkgit:git-switch[1] or linkgit:git-checkout[1] when switching branches. statusUoption:: - Advise to consider using the `-u` option to linkgit:git-status[1] - when the command takes more than 2 seconds to enumerate untracked - files. + Shown when linkgit:git-status[1] takes more than 2 + seconds to enumerate untracked files, to tell the user that + they can use the `-u` option. submoduleAlternateErrorStrategyDie:: - Advice shown when a submodule.alternateErrorStrategy option + Shown when a submodule.alternateErrorStrategy option configured to "die" causes a fatal error. + submoduleMergeConflict:: + Advice shown when a non-trivial submodule merge conflict is + encountered. submodulesNotUpdated:: - Advice shown when a user runs a submodule command that fails + Shown when a user runs a submodule command that fails because `git submodule update --init` was not run. suggestDetachingHead:: - Advice shown when linkgit:git-switch[1] refuses to detach HEAD + Shown when linkgit:git-switch[1] refuses to detach HEAD without the explicit `--detach` option. updateSparsePath:: - Advice shown when either linkgit:git-add[1] or linkgit:git-rm[1] + Shown when either linkgit:git-add[1] or linkgit:git-rm[1] is asked to update index entries outside the current sparse checkout. waitingForEditor:: - Print a message to the terminal whenever Git is waiting for - editor input from the user. + Shown when Git is waiting for editor input. Relevant + when e.g. the editor is not launched inside the terminal. worktreeAddOrphan:: - Advice shown when a user tries to create a worktree from an - invalid reference, to instruct how to create a new unborn + Shown when the user tries to create a worktree from an + invalid reference, to tell the user how to create a new unborn branch instead. -- diff --git a/Documentation/config/clean.txt b/Documentation/config/clean.txt index f05b9403b5..c0188ead4e 100644 --- a/Documentation/config/clean.txt +++ b/Documentation/config/clean.txt @@ -1,3 +1,3 @@ clean.requireForce:: - A boolean to make git-clean do nothing unless given -f, - -i, or -n. Defaults to true. + A boolean to make git-clean refuse to delete files unless -f + is given. Defaults to true. diff --git a/Documentation/config/clone.txt b/Documentation/config/clone.txt index d037b57f72..0a10efd174 100644 --- a/Documentation/config/clone.txt +++ b/Documentation/config/clone.txt @@ -1,13 +1,23 @@ -clone.defaultRemoteName:: +`clone.defaultRemoteName`:: The name of the remote to create when cloning a repository. Defaults to - `origin`, and can be overridden by passing the `--origin` command-line + `origin`. +ifdef::git-clone[] + It can be overridden by passing the `--origin` command-line + option. +endif::[] +ifndef::git-clone[] + It can be overridden by passing the `--origin` command-line option to linkgit:git-clone[1]. +endif::[] -clone.rejectShallow:: +`clone.rejectShallow`:: Reject cloning a repository if it is a shallow one; this can be overridden by - passing the `--reject-shallow` option on the command line. See linkgit:git-clone[1] + passing the `--reject-shallow` option on the command line. +ifndef::git-clone[] + See linkgit:git-clone[1]. +endif::[] -clone.filterSubmodules:: +`clone.filterSubmodules`:: If a partial clone filter is provided (see `--filter` in linkgit:git-rev-list[1]) and `--recurse-submodules` is used, also apply the filter to submodules. diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt index 0e8c2832bf..93d65e1dfd 100644 --- a/Documentation/config/core.txt +++ b/Documentation/config/core.txt @@ -520,6 +520,7 @@ core.editor:: `GIT_EDITOR` is not set. See linkgit:git-var[1]. core.commentChar:: +core.commentString:: Commands such as `commit` and `tag` that let you edit messages consider a line that begins with this character commented, and removes them after the editor returns @@ -527,6 +528,20 @@ core.commentChar:: + If set to "auto", `git-commit` would select a character that is not the beginning character of any line in existing commit messages. ++ +Note that these two variables are aliases of each other, and in modern +versions of Git you are free to use a string (e.g., `//` or `â‘â•â‘`) with +`commentChar`. Versions of Git prior to v2.45.0 will ignore +`commentString` but will reject a value of `commentChar` that consists +of more than a single ASCII byte. If you plan to use your config with +older and newer versions of Git, you may want to specify both: ++ + [core] + # single character for older versions + commentChar = "#" + # string for newer versions (which will override commentChar + # because it comes later in the file) + commentString = "//" core.filesRefLockTimeout:: The length of time, in milliseconds, to retry when trying to @@ -688,7 +703,7 @@ core.createObject:: will not overwrite existing objects. + On some file system/operating system combinations, this is unreliable. -Set this config setting to 'rename' there; However, This will remove the +Set this config setting to 'rename' there; however, this will remove the check that makes sure that existing object files will not get overwritten. core.notesRef:: diff --git a/Documentation/config/diff.txt b/Documentation/config/diff.txt index bd5ae0c337..5ce7b91f1d 100644 --- a/Documentation/config/diff.txt +++ b/Documentation/config/diff.txt @@ -108,9 +108,15 @@ diff.mnemonicPrefix:: `git diff --no-index a b`;; compares two non-git things (1) and (2). -diff.noprefix:: +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.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 and show pathnames relative to the current directory. @@ -223,5 +229,5 @@ diff.colorMoved:: 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 66db0e15da..38dce3df35 100644 --- a/Documentation/config/extensions.txt +++ b/Documentation/config/extensions.txt @@ -7,6 +7,18 @@ 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 + are `sha1` and `sha256`. The value specified must be different from the + 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 + compatObjectFormat. As well as being able to use oids encoded in + compatObjectFormat in addition to oids encoded with objectFormat to + locally specify objects. + extensions.refStorage:: Specify the ref storage format to use. The acceptable values are: + diff --git a/Documentation/config/grep.txt b/Documentation/config/grep.txt index e521f20390..10041f27b0 100644 --- a/Documentation/config/grep.txt +++ b/Documentation/config/grep.txt @@ -24,5 +24,5 @@ grep.fullName:: If set to true, enable `--full-name` option by default. grep.fallbackToNoIndex:: - If set to true, fall back to git grep --no-index if git grep + If set to true, fall back to `git grep --no-index` if `git grep` is executed outside of a git repository. Defaults to false. diff --git a/Documentation/config/init.txt b/Documentation/config/init.txt index 79c79d6617..af03acdbcb 100644 --- a/Documentation/config/init.txt +++ b/Documentation/config/init.txt @@ -1,7 +1,10 @@ -init.templateDir:: - Specify the directory from which templates will be copied. - (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].) +:see-git-init: +ifndef::git-init[] +:see-git-init: (See the "TEMPLATE DIRECTORY" section of linkgit:git-init[1].) +endif::[] -init.defaultBranch:: +`init.templateDir`:: + Specify the directory from which templates will be copied. {see-git-init} +`init.defaultBranch`:: Allows overriding the default branch name e.g. when initializing a new repository. diff --git a/Documentation/config/interactive.txt b/Documentation/config/interactive.txt index a2d3c7ec44..5cc26555f1 100644 --- a/Documentation/config/interactive.txt +++ b/Documentation/config/interactive.txt @@ -4,9 +4,7 @@ interactive.singleKey:: Currently this is used by the `--patch` mode of linkgit:git-add[1], linkgit:git-checkout[1], linkgit:git-restore[1], linkgit:git-commit[1], - linkgit:git-reset[1], and linkgit:git-stash[1]. Note that this - setting is silently ignored if portable keystroke input - is not available; requires the Perl module Term::ReadKey. + linkgit:git-reset[1], and linkgit:git-stash[1]. interactive.diffFilter:: When an interactive command (such as `git add --patch`) shows diff --git a/Documentation/config/mergetool.txt b/Documentation/config/mergetool.txt index 294f61efd1..00bf665aa0 100644 --- a/Documentation/config/mergetool.txt +++ b/Documentation/config/mergetool.txt @@ -45,14 +45,21 @@ mergetool.meld.useAutoMerge:: value of `false` avoids using `--auto-merge` altogether, and is the default value. -mergetool.vimdiff.layout:: - The vimdiff backend uses this variable to control how its split - windows appear. Applies even if you are using Neovim (`nvim`) or - gVim (`gvim`) as the merge tool. See BACKEND SPECIFIC HINTS section +mergetool.<vimdiff variant>.layout:: + Configure the split window layout for vimdiff's `<variant>`, which is any of `vimdiff`, + `nvimdiff`, `gvimdiff`. + Upon launching `git mergetool` with `--tool=<variant>` (or without `--tool` + if `merge.tool` is configured as `<variant>`), Git will consult + `mergetool.<variant>.layout` to determine the tool's layout. If the + variant-specific configuration is not available, `vimdiff`'s is used as + fallback. If that too is not available, a default layout with 4 windows + will be used. To configure the layout, see the `BACKEND SPECIFIC HINTS` +ifdef::git-mergetool[] + section. +endif::[] ifndef::git-mergetool[] - in linkgit:git-mergetool[1]. + section in linkgit:git-mergetool[1]. endif::[] - for details. mergetool.hideResolved:: During a merge, Git will automatically resolve as many conflicts as diff --git a/Documentation/config/pack.txt b/Documentation/config/pack.txt index 9c630863e6..da527377fa 100644 --- a/Documentation/config/pack.txt +++ b/Documentation/config/pack.txt @@ -34,11 +34,10 @@ pack.allowPackReuse:: reachability bitmap is available, pack-objects will try to send parts of all packs in the MIDX. + - If only a single pack bitmap is available, and - `pack.allowPackReuse` is set to "multi", reuse parts of just the - bitmapped packfile. This can reduce memory and CPU usage to - serve fetches, but might result in sending a slightly larger - pack. Defaults to true. +If only a single pack bitmap is available, and `pack.allowPackReuse` +is set to "multi", reuse parts of just the bitmapped packfile. This +can reduce memory and CPU usage to serve fetches, but might result in +sending a slightly larger pack. Defaults to true. pack.island:: An extended regular expression configuring a set of delta diff --git a/Documentation/config/receive.txt b/Documentation/config/receive.txt index c77e55b1cd..36a1e6f2d2 100644 --- a/Documentation/config/receive.txt +++ b/Documentation/config/receive.txt @@ -8,7 +8,7 @@ receive.advertisePushOptions:: capability to its clients. False by default. receive.autogc:: - By default, git-receive-pack will run "git-gc --auto" after + By default, git-receive-pack will run "git maintenance run --auto" after receiving data from git-push and updating refs. You can stop it by setting this variable to false. diff --git a/Documentation/config/sendemail.txt b/Documentation/config/sendemail.txt index 7fc770ee9e..6a869d67eb 100644 --- a/Documentation/config/sendemail.txt +++ b/Documentation/config/sendemail.txt @@ -8,7 +8,7 @@ sendemail.smtpEncryption:: See linkgit:git-send-email[1] for description. Note that this setting is not subject to the 'identity' mechanism. -sendemail.smtpsslcertpath:: +sendemail.smtpSSLCertPath:: Path to ca-certificates (either a directory or a single file). Set it to an empty string to disable certificate verification. @@ -62,12 +62,12 @@ sendemail.chainReplyTo:: sendemail.envelopeSender:: sendemail.from:: sendemail.headerCmd:: -sendemail.signedoffbycc:: +sendemail.signedOffByCc:: sendemail.smtpPass:: -sendemail.suppresscc:: +sendemail.suppressCc:: sendemail.suppressFrom:: sendemail.to:: -sendemail.tocmd:: +sendemail.toCmd:: sendemail.smtpDomain:: sendemail.smtpServer:: sendemail.smtpServerPort:: @@ -81,8 +81,8 @@ sendemail.xmailer:: linkgit:git-send-email[1] command-line options. See its documentation for details. -sendemail.signedoffcc (deprecated):: - Deprecated alias for `sendemail.signedoffbycc`. +sendemail.signedOffCc (deprecated):: + Deprecated alias for `sendemail.signedOffByCc`. sendemail.smtpBatchSize:: Number of messages to be sent per connection, after that a relogin diff --git a/Documentation/config/status.txt b/Documentation/config/status.txt index 2ff8237f8f..8caf90f51c 100644 --- a/Documentation/config/status.txt +++ b/Documentation/config/status.txt @@ -57,6 +57,8 @@ status.showUntrackedFiles:: -- + If this variable is not specified, it defaults to 'normal'. +All usual spellings for Boolean value `true` are taken as `normal` +and `false` as `no`. This variable can be overridden with the -u|--untracked-files option of linkgit:git-status[1] and linkgit:git-commit[1]. diff --git a/Documentation/config/transfer.txt b/Documentation/config/transfer.txt index a9cbdb88a1..f1ce50f4a6 100644 --- a/Documentation/config/transfer.txt +++ b/Documentation/config/transfer.txt @@ -121,3 +121,7 @@ transfer.bundleURI:: information from the remote server (if advertised) and download bundles before continuing the clone through the Git protocol. Defaults to `false`. + +transfer.advertiseObjectInfo:: + When `true`, the `object-info` capability is advertised by + servers. Defaults to false. diff --git a/Documentation/date-formats.txt b/Documentation/date-formats.txt index 67645cae64..e24517c496 100644 --- a/Documentation/date-formats.txt +++ b/Documentation/date-formats.txt @@ -11,7 +11,7 @@ Git internal format:: For example CET (which is 1 hour ahead of UTC) is `+0100`. RFC 2822:: - The standard email format as described by RFC 2822, for example + The standard date format as described by RFC 2822, for example `Thu, 07 Apr 2005 22:13:13 +0200`. ISO 8601:: diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index aaaff0d46f..0e9456957e 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -865,8 +865,9 @@ endif::git-format-patch[] --default-prefix:: Use the default source and destination prefixes ("a/" and "b/"). - This is usually the default already, but may be used to override - config such as `diff.noprefix`. + This overrides configuration variables such as `diff.noprefix`, + `diff.srcPrefix`, `diff.dstPrefix`, and `diff.mnemonicPrefix` + (see `git-config`(1)). --line-prefix=<prefix>:: Prepend an additional prefix to every line of output. diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index 54ebb4452e..e22b217fba 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -202,7 +202,7 @@ endif::git-pull[] destination of an explicit refspec; see `--prune`). ifndef::git-pull[] ---recurse-submodules[=yes|on-demand|no]:: +--recurse-submodules[=(yes|on-demand|no)]:: This option controls if and under what conditions new commits of submodules should be fetched too. When recursing through submodules, `git fetch` always attempts to fetch "changed" submodules, that is, a diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 3d2e670716..aceaa025e3 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -63,7 +63,7 @@ OPTIONS to ignore removed files; use `--no-all` option if you want to add modified or new files but ignore removed ones. + -For more details about the <pathspec> syntax, see the 'pathspec' entry +For more details about the _<pathspec>_ syntax, see the 'pathspec' entry in linkgit:gitglossary[7]. -n:: @@ -119,10 +119,10 @@ apply to the index. See EDITING PATCHES below. -u:: --update:: Update the index just where it already has an entry matching - <pathspec>. This removes as well as modifies index entries to + _<pathspec>_. This removes as well as modifies index entries to match the working tree, but adds no new files. + -If no <pathspec> is given when `-u` option is used, all +If no _<pathspec>_ is given when `-u` option is used, all 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). @@ -131,11 +131,11 @@ subdirectories). --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 + matching _<pathspec>_ but also where the index already has an entry. This adds, modifies, and removes index entries to match the working tree. + -If no <pathspec> is given when `-A` option is used, all +If no _<pathspec>_ is given when `-A` option is used, all files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories). @@ -145,11 +145,11 @@ subdirectories). 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. + 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:: @@ -198,8 +198,8 @@ for "git add --no-all <pathspec>...", i.e. ignored removed files. unchanged. --pathspec-from-file=<file>:: - Pathspec is passed in `<file>` instead of commandline args. If - `<file>` is exactly `-` then standard input is used. Pathspec + 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 quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). See also `--pathspec-file-nul` and @@ -348,6 +348,7 @@ patch:: K - leave this hunk undecided, see previous hunk s - split the current hunk into smaller hunks e - manually edit the current hunk + p - print the current hunk ? - print help + After deciding the fate for all hunks, if there is any hunk diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index e080458d6c..624a6e6fe4 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -66,13 +66,19 @@ OPTIONS --quoted-cr=<action>:: This flag will be passed down to 'git mailinfo' (see linkgit:git-mailinfo[1]). ---empty=(stop|drop|keep):: - By default, or when the option is set to 'stop', the command - errors out on an input e-mail message lacking a patch - and stops in the middle of the current am session. When this - option is set to 'drop', skip such an e-mail message instead. - When this option is set to 'keep', create an empty commit, - recording the contents of the e-mail message as its log. +--empty=(drop|keep|stop):: + How to handle an e-mail message lacking a patch: ++ +-- +`drop`;; + The e-mail message will be skipped. +`keep`;; + An empty commit will be created, with the contents of the e-mail + message as its log. +`stop`;; + The command will fail, stopping in the middle of the current `am` + session. This is the default behavior. +-- -m:: --message-id:: @@ -128,6 +134,9 @@ include::rerere-options.txt[] These flags are passed to the 'git apply' (see linkgit:git-apply[1]) program that applies the patch. ++ +Valid <action> for the `--whitespace` option are: +`nowarn`, `warn`, `fix`, `error`, and `error-all`. --patch-format:: By default the command will try to detect the patch format diff --git a/Documentation/git-bugreport.txt b/Documentation/git-bugreport.txt index ca626f7fc6..112658b3c3 100644 --- a/Documentation/git-bugreport.txt +++ b/Documentation/git-bugreport.txt @@ -8,7 +8,8 @@ git-bugreport - Collect information for user to file a bug report SYNOPSIS -------- [verse] -'git bugreport' [(-o | --output-directory) <path>] [(-s | --suffix) <format>] +'git bugreport' [(-o | --output-directory) <path>] + [(-s | --suffix) <format> | --no-suffix] [--diagnose[=<mode>]] DESCRIPTION @@ -51,9 +52,12 @@ OPTIONS -s <format>:: --suffix <format>:: +--no-suffix:: Specify an alternate suffix for the bugreport name, to create a file named 'git-bugreport-<formatted-suffix>'. This should take the form of a strftime(3) format string; the current local time will be used. + `--no-suffix` disables the suffix and the file is just named + `git-bugreport` without any disambiguation measure. --no-diagnose:: --diagnose[=<mode>]:: diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index fdcad3d200..81ace900fc 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -131,20 +131,36 @@ effect to your index in a row. even without this option. Note also, that use of this option only keeps commits that were initially empty (i.e. the commit recorded the same tree as its parent). Commits which are made empty due to a - previous commit are dropped. To force the inclusion of those commits - use `--keep-redundant-commits`. + previous commit will cause the cherry-pick to fail. To force the + inclusion of those commits, use `--empty=keep`. --allow-empty-message:: By default, cherry-picking a commit with an empty message will fail. This option overrides that behavior, allowing commits with empty messages to be cherry picked. +--empty=(drop|keep|stop):: + How to handle commits being cherry-picked that are redundant with + changes already in the current history. ++ +-- +`drop`;; + The commit will be dropped. +`keep`;; + The commit will be kept. Implies `--allow-empty`. +`stop`;; + The cherry-pick will stop when the commit is applied, allowing + you to examine the commit. This is the default behavior. +-- ++ +Note that `--empty=drop` and `--empty=stop` only specify how to handle a +commit that was not initially empty, but rather became empty due to a previous +commit. Commits that were initially empty will still cause the cherry-pick to +fail unless one of `--empty=keep` or `--allow-empty` are specified. ++ + --keep-redundant-commits:: - If a commit being cherry picked duplicates a commit already in the - current history, it will become empty. By default these - redundant commits cause `cherry-pick` to stop so the user can - examine the commit. This option overrides that behavior and - creates an empty commit object. Implies `--allow-empty`. + Deprecated synonym for `--empty=keep`. --strategy=<strategy>:: Use the given merge strategy. Should only be used once. diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt index 69331e3f05..fd17165416 100644 --- a/Documentation/git-clean.txt +++ b/Documentation/git-clean.txt @@ -37,7 +37,7 @@ OPTIONS --force:: If the Git configuration variable clean.requireForce is not set to false, 'git clean' will refuse to delete files or directories - unless given -f or -i. Git will refuse to modify untracked + unless given -f. Git will refuse to modify untracked nested git repositories (directories with a .git subdirectory) unless a second -f is given. @@ -45,10 +45,14 @@ OPTIONS --interactive:: Show what would be done and clean files interactively. See ``Interactive mode'' for details. + Configuration variable `clean.requireForce` is ignored, as + this mode gives its own safety protection by going interactive. -n:: --dry-run:: Don't actually remove anything, just show what would be done. + Configuration variable `clean.requireForce` is ignored, as + nothing will be deleted anyway. -q:: --quiet:: diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 6e43eb9c20..5de18de2ab 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -9,15 +9,15 @@ 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-]single-branch] [--no-tags] - [--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules] - [--[no-]remote-submodules] [--jobs <n>] [--sparse] [--[no-]reject-shallow] - [--filter=<filter> [--also-filter-submodules]] [--] <repository> - [<directory>] +`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 ----------- @@ -31,7 +31,7 @@ currently active branch. After the clone, a plain `git fetch` without arguments will update all the remote-tracking branches, and a `git pull` without arguments will in addition merge the remote master branch into the -current master branch, if any (this is untrue when "--single-branch" +current master branch, if any (this is untrue when `--single-branch` is given; see below). This default configuration is achieved by creating references to @@ -42,12 +42,12 @@ configuration variables. OPTIONS ------- --l:: ---local:: +`-l`:: +`--local`:: When the repository to clone from is on a local machine, this flag bypasses the normal "Git aware" transport mechanism and clones the repository by making a copy of - HEAD and everything under objects and refs directories. + `HEAD` and everything under objects and refs directories. The files under `.git/objects/` directory are hardlinked to save space when possible. + @@ -67,14 +67,14 @@ links. source repository, similar to running `cp -r src dst` while modifying `src`. ---no-hardlinks:: +`--no-hardlinks`:: Force the cloning process from a repository on a local filesystem to copy the files under the `.git/objects` directory instead of using hardlinks. This may be desirable if you are trying to make a back-up of your repository. --s:: ---shared:: +`-s`:: +`--shared`:: When the repository to clone is on the local machine, instead of using hard links, automatically setup `.git/objects/info/alternates` to share the objects @@ -101,10 +101,10 @@ 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>:: - If the reference repository is on the local machine, +`--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 + obtain objects from the reference _<repository>_. Using an already existing repository as an alternate will require fewer objects to be copied from the repository being cloned, reducing network and local storage costs. @@ -115,7 +115,7 @@ objects from the source repository into a pack in the cloned repository. *NOTE*: see the NOTE for the `--shared` option, and also the `--dissociate` option. ---dissociate:: +`--dissociate`:: Borrow the objects from reference repositories specified with the `--reference` options only to reduce network transfer, and stop borrowing from them after a clone is made @@ -126,43 +126,43 @@ objects from the source repository into a pack in the cloned repository. same repository, and this option can be used to stop the borrowing. --q:: ---quiet:: +`-q`:: +`--quiet`:: Operate quietly. Progress is not reported to the standard error stream. --v:: ---verbose:: +`-v`:: +`--verbose`:: Run verbosely. Does not affect the reporting of progress status to the standard error stream. ---progress:: +`--progress`:: Progress status is reported on the standard error stream by default when it is attached to a terminal, unless `--quiet` 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. --n:: ---no-checkout:: +`-n`:: +`--no-checkout`:: No checkout of HEAD is performed after the clone is complete. ---[no-]reject-shallow:: +`--`[`no-`]`reject-shallow`:: Fail if the source repository is a shallow repository. - The 'clone.rejectShallow' configuration variable can be used to + The `clone.rejectShallow` configuration variable can be used to specify the default. ---bare:: +`--bare`:: Make a 'bare' Git repository. That is, instead of - creating `<directory>` and placing the administrative - files in `<directory>/.git`, make the `<directory>` + creating _<directory>_ and placing the administrative + 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 @@ -171,28 +171,28 @@ objects from the source repository into a pack in the cloned repository. used, neither remote-tracking branches nor the related configuration variables are created. ---sparse:: +`--sparse`:: Employ a sparse-checkout, with only files in the toplevel directory initially being present. The 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 + 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 - at least `<size>`. For more details on filter specifications, see + ++--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]. ---also-filter-submodules:: +`--also-filter-submodules`:: Also apply the partial clone filter to any submodules in the repository. Requires `--filter` and `--recurse-submodules`. This can be turned on by default by setting the `clone.filterSubmodules` config option. ---mirror:: +`--mirror`:: Set up a mirror of the source repository. This implies `--bare`. Compared to `--bare`, `--mirror` not only maps local branches of the source to local branches of the target, it maps all refs (including @@ -200,37 +200,37 @@ objects from the source repository into a pack in the cloned repository. that all these refs are overwritten by a `git remote update` in the target repository. --o <name>:: ---origin <name>:: +`-o` _<name>_:: +`--origin` _<name>_:: Instead of using the remote name `origin` to keep track of the upstream - repository, use `<name>`. Overrides `clone.defaultRemoteName` from the + repository, use _<name>_. Overrides `clone.defaultRemoteName` from the config. --b <name>:: ---branch <name>:: +`-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 + 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 in the resulting repository. --u <upload-pack>:: ---upload-pack <upload-pack>:: +`-u` _<upload-pack>_:: +`--upload-pack` _<upload-pack>_:: When given, and the repository to clone from is accessed 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 - files checked out. The key is in the same format as expected by + files checked out. The _<key>_ is in the same format as expected by linkgit:git-config[1] (e.g., `core.eol=true`). If multiple values are given for the same key, each value will be written to the config file. This makes it safe, for example, to add @@ -239,35 +239,35 @@ 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=++__<revision>__:: 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. Further fetches into the resulting repository will only update the remote-tracking branch for the branch this option was used for the - initial cloning. If the HEAD at the remote did not point at any + initial cloning. If the `HEAD` at the remote did not point at any branch when `--single-branch` clone was made, no remote-tracking branch is created. ---no-tags:: +`--no-tags`:: Don't clone any tags, and set `remote.<remote>.tagOpt=--no-tags` in the config, ensuring that future `git pull` and `git fetch` operations won't follow @@ -279,9 +279,9 @@ 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[=<pathspec>]:: +`--recurse-submodules`[`=`{empty}__<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 @@ -295,48 +295,48 @@ 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=<git-dir>:: +`--separate-git-dir=`{empty}__<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=<ref-format:: +`--ref-format=`{empty}__<ref-format>__:: Specify the given ref storage format for the repository. The valid values are: + include::ref-storage-format.txt[] --j <n>:: ---jobs <n>:: +`-j` _<n>_:: +`--jobs` _<n>_:: The number of submodules fetched at the same time. Defaults to the `submodule.fetchJobs` option. -<repository>:: - The (possibly remote) repository to clone from. See the +_<repository>_:: + The (possibly remote) _<repository>_ to clone from. See the <<URLS,GIT URLS>> section below for more information on specifying repositories. -<directory>:: +_<directory>_:: The name of a new directory to clone into. The "humanish" - part of the source repository is used if no directory is + part of the source repository is used if no _<directory>_ is explicitly given (`repo` for `/path/to/repo.git` and `foo` for `host.xz:foo/.git`). Cloning into an existing directory is only allowed if the directory is empty. ---bundle-uri=<uri>:: +`--bundle-uri=`{empty}__<uri>__:: Before fetching from the remote, fetch a bundle from the given - `<uri>` and unbundle the data into the local repository. The refs + _<uri>_ and unbundle the data into the local repository. The refs in the bundle will be stored under the hidden `refs/bundle/*` namespace. This option is incompatible with `--depth`, `--shallow-since`, and `--shallow-exclude`. diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index a6cef5d820..89ecfc63a8 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -347,6 +347,8 @@ The possible options are: - 'normal' - Shows untracked files and directories - 'all' - Also shows individual files in untracked directories. +All usual spellings for Boolean value `true` are taken as `normal` +and `false` as `no`. The default can be changed using the status.showUntrackedFiles configuration variable documented in linkgit:git-config[1]. -- diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index dff39093b5..ac61113fcc 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -9,9 +9,9 @@ git-config - Get and set repository or global options SYNOPSIS -------- [verse] -'git config' [<file-option>] [--type=<type>] [--fixed-value] [--show-origin] [--show-scope] [-z|--null] <name> [<value> [<value-pattern>]] -'git config' [<file-option>] [--type=<type>] --add <name> <value> -'git config' [<file-option>] [--type=<type>] [--fixed-value] --replace-all <name> <value> [<value-pattern>] +'git config' [<file-option>] [--type=<type>] [--comment=<message>] [--fixed-value] [--show-origin] [--show-scope] [-z|--null] <name> [<value> [<value-pattern>]] +'git config' [<file-option>] [--type=<type>] [--comment=<message>] --add <name> <value> +'git config' [<file-option>] [--type=<type>] [--comment=<message>] [--fixed-value] --replace-all <name> <value> [<value-pattern>] 'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--fixed-value] --get <name> [<value-pattern>] 'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--fixed-value] --get-all <name> [<value-pattern>] 'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--fixed-value] [--name-only] --get-regexp <name-regex> [<value-pattern>] @@ -87,6 +87,18 @@ OPTIONS values. This is the same as providing '^$' as the `value-pattern` in `--replace-all`. +--comment <message>:: + Append a comment at the end of new or modified lines. + + If _<message>_ begins with one or more whitespaces followed + by "#", it is used as-is. If it begins with "#", a space is + prepended before it is used. Otherwise, a string " # " (a + space followed by a hash followed by a space) is prepended + to it. And the resulting string is placed immediately after + the value defined for the variable. The _<message>_ must + not contain linefeed characters (no multi-line comments are + permitted). + --get:: Get the value for a given key (optionally filtered by a regex matching the value). Returns error code 1 if the key was not @@ -275,7 +287,8 @@ Valid `<type>`'s include: -e:: --edit:: Opens an editor to modify the specified config file; either - `--system`, `--global`, or repository (default). + `--system`, `--global`, `--local` (default), `--worktree`, or + `--file <config-file>`. --[no-]includes:: Respect `include.*` directives in config files when looking up @@ -285,7 +298,7 @@ Valid `<type>`'s include: --default <value>:: When using `--get`, and the requested variable is not found, behave as if - <value> were the value assigned to the that variable. + <value> were the value assigned to that variable. CONFIGURATION ------------- diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt index c05f97aca9..a616f8b2e6 100644 --- a/Documentation/git-difftool.txt +++ b/Documentation/git-difftool.txt @@ -105,7 +105,6 @@ instead. `--no-symlinks` is the default on Windows. `merge.tool` until a tool is found. --[no-]trust-exit-code:: - 'git-difftool' invokes a diff tool individually on each file. Errors reported by the diff tool are ignored by default. Use `--trust-exit-code` to make 'git-difftool' exit when an invoked diff tool returns a non-zero exit code. diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt index 4643ddbe68..752e4b9b01 100644 --- a/Documentation/git-fast-export.txt +++ b/Documentation/git-fast-export.txt @@ -48,7 +48,7 @@ When asking to 'abort' (which is the default), this program will die when encountering such a tag. With 'drop' it will omit such tags from the output. With 'rewrite', if the tagged object is a commit, it will rewrite the tag to tag an ancestor commit (via parent rewriting; see -linkgit:git-rev-list[1]) +linkgit:git-rev-list[1]). -M:: -C:: diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index b2607366b9..3d435157a6 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -303,7 +303,7 @@ and some sanity checks on the numeric values may also be performed. with e.g. bogus timezone values. `rfc2822`:: - This is the standard email format as described by RFC 2822. + This is the standard date format as described by RFC 2822. + An example value is ``Tue Feb 6 11:22:18 2007 -0500''. The Git parser is accurate, but a little on the lenient side. It is the @@ -630,18 +630,28 @@ in octal. Git only supports the following modes: In both formats `<path>` is the complete path of the file to be added (if not already existing) or modified (if already existing). -A `<path>` string must use UNIX-style directory separators (forward -slash `/`), may contain any byte other than `LF`, and must not -start with double quote (`"`). - -A path can use C-style string quoting; this is accepted in all cases -and mandatory if the filename starts with double quote or contains -`LF`. In C-style quoting, the complete name should be surrounded with -double quotes, and any `LF`, backslash, or double quote characters -must be escaped by preceding them with a backslash (e.g., -`"path/with\n, \\ and \" in it"`). - -The value of `<path>` must be in canonical form. That is it must not: +A `<path>` can be written as unquoted bytes or a C-style quoted string. + +When a `<path>` does not start with a double quote (`"`), it is an +unquoted string and is parsed as literal bytes without any escape +sequences. However, if the filename contains `LF` or starts with double +quote, it cannot be represented as an unquoted string and must be +quoted. Additionally, the source `<path>` in `filecopy` or `filerename` +must be quoted if it contains SP. + +When a `<path>` starts with a double quote (`"`), it is a C-style quoted +string, where the complete filename is enclosed in a pair of double +quotes and escape sequences are used. Certain characters must be escaped +by preceding them with a backslash: `LF` is written as `\n`, backslash +as `\\`, and double quote as `\"`. Some characters may optionally be +written with escape sequences: `\a` for bell, `\b` for backspace, `\f` +for form feed, `\n` for line feed, `\r` for carriage return, `\t` for +horizontal tab, and `\v` for vertical tab. Any byte can be written with +3-digit octal codes (e.g., `\033`). All filenames can be represented as +quoted strings. + +A `<path>` must use UNIX-style directory separators (forward slash `/`) +and its value must be in canonical form. That is it must not: * contain an empty directory component (e.g. `foo//bar` is invalid), * end with a directory separator (e.g. `foo/` is invalid), @@ -651,6 +661,7 @@ The value of `<path>` must be in canonical form. That is it must not: The root of the tree can be represented by an empty string as `<path>`. +`<path>` cannot contain NUL, either literally or escaped as `\000`. It is recommended that `<path>` always be encoded using UTF-8. `filedelete` diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index 3a9ad91b7a..c1dd12b93c 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -10,7 +10,7 @@ SYNOPSIS [verse] 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl] [(--sort=<key>)...] [--format=<format>] - [ --stdin | <pattern>... ] + [--include-root-refs] [ --stdin | <pattern>... ] [--points-at=<object>] [--merged[=<object>]] [--no-merged[=<object>]] [--contains[=<object>]] [--no-contains[=<object>]] @@ -105,6 +105,9 @@ TAB %(refname)`. any excluded pattern(s) are shown. Matching is done using the same rules as `<pattern>` above. +--include-root-refs:: + List root refs (HEAD and pseudorefs) apart from regular refs. + FIELD NAMES ----------- diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 0d0103c780..1e6d7b65c8 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -28,7 +28,7 @@ SYNOPSIS [-f <file>] [-e] <pattern> [--and|--or|--not|(|)|-e <pattern>...] [--recurse-submodules] [--parent-basename <basename>] - [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | <tree>...] + [ [--[no-]exclude-standard] [--cached | --untracked | --no-index] | <tree>...] [--] [<pathspec>...] DESCRIPTION @@ -45,13 +45,21 @@ OPTIONS Instead of searching tracked files in the working tree, search blobs registered in the index file. ---no-index:: - Search files in the current directory that is not managed by Git. - --untracked:: In addition to searching in the tracked files in the working tree, search also in untracked files. +--no-index:: + Search files in the current directory that is not managed by Git, + or by ignoring that the current directory is managed by Git. This + is rather similar to running the regular `grep(1)` utility with its + `-r` option specified, but with some additional benefits, such as + using pathspec patterns to limit paths; see the 'pathspec' entry + in linkgit:gitglossary[7] for more information. ++ +This option cannot be used together with `--cached` or `--untracked`. +See also `grep.fallbackToNoIndex` in 'CONFIGURATION' below. + --no-exclude-standard:: Also search in ignored files by not honoring the `.gitignore` mechanism. Only useful with `--untracked`. @@ -64,9 +72,9 @@ OPTIONS --recurse-submodules:: Recursively search in each submodule that is active and checked out in the repository. When used in combination with the - <tree> option the prefix of all submodule output will be the name of - the parent project's <tree> object. This option has no effect - if `--no-index` is given. + _<tree>_ option the prefix of all submodule output will be the name of + the parent project's _<tree>_ object. This option cannot be used together + with `--untracked`, and it has no effect if `--no-index` is specified. -a:: --text:: @@ -178,7 +186,7 @@ providing this option will cause it to die. Use \0 as the delimiter for pathnames in the output, and print them verbatim. Without this option, pathnames with "unusual" characters are quoted as explained for the configuration - variable core.quotePath (see linkgit:git-config[1]). + variable `core.quotePath` (see linkgit:git-config[1]). -o:: --only-matching:: @@ -248,8 +256,8 @@ providing this option will cause it to die. a non-zero status. --threads <num>:: - Number of grep worker threads to use. - See `grep.threads` in 'CONFIGURATION' for more information. + Number of `grep` worker threads to use. See 'NOTES ON THREADS' + and `grep.threads` in 'CONFIGURATION' for more information. -f <file>:: Read patterns from <file>, one per line. @@ -332,13 +340,13 @@ EXAMPLES NOTES ON THREADS ---------------- -The `--threads` option (and the grep.threads configuration) will be ignored when +The `--threads` option (and the `grep.threads` configuration) will be ignored when `--open-files-in-pager` is used, forcing a single-threaded execution. When grepping the object store (with `--cached` or giving tree objects), running -with multiple threads might perform slower than single threaded if `--textconv` -is given and there are too many text conversions. So if you experience low -performance in this case, it might be desirable to use `--threads=1`. +with multiple threads might perform slower than single-threaded if `--textconv` +is given and there are too many text conversions. Thus, if low performance is +experienced in this case, it might be desirable to use `--threads=1`. CONFIGURATION ------------- diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt index e8dc645bb5..daff93bd16 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.txt @@ -9,11 +9,11 @@ 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>] +`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 @@ -33,43 +33,43 @@ If the object storage directory is specified via the are created underneath; otherwise, the default `$GIT_DIR/objects` directory is used. -Running 'git init' in an existing repository is safe. It will not +Running `git init` in an existing repository is safe. It will not overwrite things that are already there. The primary reason for -rerunning 'git init' is to pick up newly added templates (or to move -the repository to another place if --separate-git-dir is given). +rerunning `git init` is to pick up newly added templates (or to move +the repository to another place if `--separate-git-dir` is given). OPTIONS ------- --q:: ---quiet:: +`-q`:: +`--quiet`:: Only print error and warning messages; all other output will be suppressed. ---bare:: +`--bare`:: 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. +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: +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 @@ -78,52 +78,56 @@ 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 the specified name for the initial branch in the newly created +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 -repository. When specified, the config variable "core.sharedRepository" is +repository. When specified, the config variable `core.sharedRepository` is set so that files and directories under `$GIT_DIR` are created with the requested permissions. When not specified, Git will use permissions reported -by umask(2). +by `umask`(2). + -The option can have the following values, defaulting to 'group' if no value +The option can have the following values, defaulting to `group` if no value is given: + -- -'umask' (or 'false'):: +`umask`:: +`false`:: -Use permissions reported by umask(2). The default, when `--shared` is not +Use permissions reported by `umask`(2). The default, when `--shared` is not specified. -'group' (or 'true'):: +`group`:: +`true`:: -Make the repository group-writable, (and g+sx, since the git group may not be +Make the repository group-writable, (and `g+sx`, since the git group may not be the primary group of all users). This is used to loosen the permissions of an -otherwise safe umask(2) value. Note that the umask still applies to the other -permission bits (e.g. if umask is '0022', using 'group' will not remove read -privileges from other (non-group) users). See '0xxx' for how to exactly specify +otherwise safe `umask`(2) value. Note that the umask still applies to the other +permission bits (e.g. if umask is `0022`, using `group` will not remove read +privileges from other (non-group) users). See `0xxx` for how to exactly specify the repository permissions. -'all' (or 'world' or 'everybody'):: +`all`:: +`world`:: +`everybody`:: -Same as 'group', but make the repository readable by all users. +Same as `group`, but make the repository readable by all users. -'<perm>':: +_<perm>_:: -'<perm>' is a 3-digit octal number prefixed with `0` and each file -will have mode '<perm>'. '<perm>' will override users' umask(2) -value (and not only loosen permissions as 'group' and 'all' -do). '0640' will create a repository which is group-readable, but -not group-writable or accessible to others. '0660' will create a repo +_<perm>_ is a 3-digit octal number prefixed with `0` and each file +will have mode _<perm>_. _<perm>_ will override users' `umask`(2) +value (and not only loosen permissions as `group` and `all` +do). `0640` will create a repository which is group-readable, but +not group-writable or accessible to others. `0660` will create a repo that is readable and writable to the current user and group, but inaccessible to others (directories and executable files get their `x` bit from the `r` bit for corresponding classes of users). @@ -133,7 +137,7 @@ By default, the configuration flag `receive.denyNonFastForwards` is enabled in shared repositories, so that you cannot force a non fast-forwarding push into it. -If you provide a 'directory', the command is run inside it. If this directory +If you provide a _<directory>_, the command is run inside it. If this directory does not exist, it will be created. TEMPLATE DIRECTORY @@ -172,7 +176,7 @@ $ git add . <2> $ git commit <3> ---------------- + -<1> Create a /path/to/my/codebase/.git directory. +<1> Create a `/path/to/my/codebase/.git` directory. <2> Add all existing files to the index. <3> Record the pristine state as the first commit in the history. @@ -181,6 +185,8 @@ CONFIGURATION include::includes/cmd-config-section-all.txt[] +:git-init: + include::config/init.txt[] GIT diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt index 418265f044..d9dfb75fef 100644 --- a/Documentation/git-interpret-trailers.txt +++ b/Documentation/git-interpret-trailers.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git interpret-trailers' [--in-place] [--trim-empty] - [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...] + [(--trailer (<key>|<key-alias>)[(=|:)<value>])...] [--parse] [<file>...] DESCRIPTION @@ -67,9 +67,9 @@ key: value This means that the trimmed <key> and <value> will be separated by `': '` (one colon followed by one space). -For convenience, a <keyAlias> can be configured to make using `--trailer` +For convenience, a <key-alias> can be configured to make using `--trailer` shorter to type on the command line. This can be configured using the -'trailer.<keyAlias>.key' configuration variable. The <keyAlias> must be a prefix +'trailer.<key-alias>.key' configuration variable. The <keyAlias> must be a prefix of the full <key> string, although case sensitivity does not matter. For example, if you have diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index b50acace3b..dd388fa21d 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -64,10 +64,13 @@ OPTIONS share no common history. This flag can be given to override that check and make the merge proceed anyway. ---merge-base=<commit>:: +--merge-base=<tree-ish>:: Instead of finding the merge-bases for <branch1> and <branch2>, specify a merge-base for the merge, and specifying multiple bases is currently not supported. This option is incompatible with `--stdin`. ++ +As the merge-base is provided directly, <branch1> and <branch2> do not need +to specify commits; trees are enough. [[OUTPUT]] OUTPUT diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.txt index 284956acb3..2dcabaf74c 100644 --- a/Documentation/git-pack-refs.txt +++ b/Documentation/git-pack-refs.txt @@ -8,7 +8,7 @@ git-pack-refs - Pack heads and tags for efficient repository access SYNOPSIS -------- [verse] -'git pack-refs' [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>] +'git pack-refs' [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude <pattern>] DESCRIPTION ----------- @@ -60,6 +60,19 @@ with many branches of historical interests. The command usually removes loose refs under `$GIT_DIR/refs` hierarchy after packing them. This option tells it not to. +--auto:: + +Pack refs as needed depending on the current state of the ref database. The +behavior depends on the ref format used by the repository and may change in the +future. ++ + - "files": No special handling for `--auto` has been implemented. ++ + - "reftable": Tables are compacted such that they form a geometric + sequence. For two tables N and N+1, where N+1 is newer, this + maintains the property that N is at least twice as big as N+1. Only + tables that violate this property are compacted. + --include <pattern>:: Pack refs based on a `glob(7)` pattern. Repetitions of this option diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index 0e14f8b5b2..b2ae496e48 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -87,7 +87,7 @@ OPTIONS --verbose:: Pass --verbose to git-fetch and git-merge. ---[no-]recurse-submodules[=yes|on-demand|no]:: +--[no-]recurse-submodules[=(yes|on-demand|no)]:: This option controls if new commits of populated submodules should be fetched, and if the working trees of active submodules should be updated, too (see linkgit:git-fetch[1], linkgit:git-config[1] and @@ -105,7 +105,7 @@ Options related to merging include::merge-options.txt[] -r:: ---rebase[=false|true|merges|interactive]:: +--rebase[=(false|true|merges|interactive)]:: When true, rebase the current branch on top of the upstream branch after fetching. If there is a remote-tracking branch corresponding to the upstream branch and the upstream branch diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 06206521fc..74df345f9e 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -12,7 +12,7 @@ SYNOPSIS [--onto <newbase> | --keep-base] [<upstream> [<branch>]] 'git rebase' [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>] --root [<branch>] -'git rebase' (--continue | --skip | --abort | --quit | --edit-todo | --show-current-patch) +'git rebase' (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch) DESCRIPTION ----------- @@ -289,17 +289,25 @@ See also INCOMPATIBLE OPTIONS below. + See also INCOMPATIBLE OPTIONS below. ---empty=(drop|keep|ask):: +--empty=(drop|keep|stop):: How to handle commits that are not empty to start and are not clean cherry-picks of any upstream commit, but which become empty after rebasing (because they contain a subset of already - upstream changes). With drop (the default), commits that - become empty are dropped. With keep, such commits are kept. - With ask (implied by `--interactive`), the rebase will halt when - an empty commit is applied allowing you to choose whether to - drop it, edit files more, or just commit the empty changes. - Other options, like `--exec`, will use the default of drop unless - `-i`/`--interactive` is explicitly specified. + upstream changes): ++ +-- +`drop`;; + The commit will be dropped. This is the default behavior. +`keep`;; + The commit will be kept. This option is implied when `--exec` is + specified unless `-i`/`--interactive` is also specified. +`stop`;; +`ask`;; + The rebase will halt when the commit is applied, allowing you to + choose whether to drop it, edit files more, or just commit the empty + changes. This option is implied when `-i`/`--interactive` is + specified. `ask` is a deprecated synonym of `stop`. +-- + Note that commits which start empty are kept (unless `--no-keep-empty` is specified), and commits which are clean cherry-picks (as determined @@ -607,7 +615,7 @@ The recommended way to create commits with squash markers is by using the linkgit:git-commit[1], which take the target commit as an argument and automatically fill in the subject line of the new commit from that. + -Settting configuration variable `rebase.autoSquash` to true enables +Setting configuration variable `rebase.autoSquash` to true enables auto-squashing by default for interactive rebase. The `--no-autosquash` option can be used to override that setting. + @@ -704,7 +712,7 @@ be dropped automatically with `--no-keep-empty`). Similar to the apply backend, by default the merge backend drops commits that become empty unless `-i`/`--interactive` is specified (in which case it stops and asks the user what to do). The merge backend -also has an `--empty=(drop|keep|ask)` option for changing the behavior +also has an `--empty=(drop|keep|stop)` option for changing the behavior of handling commits that become empty. Directory rename detection diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index ec64cbff4c..a929c52982 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -10,6 +10,7 @@ SYNOPSIS -------- [verse] 'git reflog' [show] [<log-options>] [<ref>] +'git reflog list' 'git reflog expire' [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...] @@ -39,6 +40,8 @@ actions, and in addition the `HEAD` reflog records branch switching. `git reflog show` is an alias for `git log -g --abbrev-commit --pretty=oneline`; see linkgit:git-log[1] for more information. +The "list" subcommand lists all refs which have a corresponding reflog. + The "expire" subcommand prunes older reflog entries. Entries older than `expire` time, or entries older than `expire-unreachable` time and not reachable from the current tip, are removed from the reflog. diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 1dec314834..932a5c3ea4 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -35,7 +35,7 @@ OPTIONS -v:: --verbose:: Be a little more verbose and show remote url after name. - For promisor remotes, also show which filter (`blob:none` etc.) + For promisor remotes, also show which filters (`blob:none` etc.) are configured. NOTE: This must be placed between `remote` and subcommand. diff --git a/Documentation/git-replay.txt b/Documentation/git-replay.txt index f6c269c62d..8f3300c683 100644 --- a/Documentation/git-replay.txt +++ b/Documentation/git-replay.txt @@ -46,7 +46,7 @@ the new commits (in other words, this mimics a cherry-pick operation). Range of commits to replay. More than one <revision-range> can be passed, but in `--advance <branch>` mode, they should have a single tip, so that it's clear where <branch> should point - to. See "Specifying Ranges" in linkgit:git-rev-parse and the + to. See "Specifying Ranges" in linkgit:git-rev-parse[1] and the "Commit Limiting" options below. include::rev-list-options.txt[] diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 546faf9017..f9d5a35fa0 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -9,7 +9,7 @@ git-rev-parse - Pick out and massage parameters SYNOPSIS -------- [verse] -'git rev-parse' [<options>] <args>... +'git rev-parse' [<options>] <arg>... DESCRIPTION ----------- @@ -130,7 +130,7 @@ for another option. 'git diff-{asterisk}'). In contrast to the `--sq-quote` option, the command input is still interpreted as usual. ---short[=length]:: +--short[=<length>]:: Same as `--verify` but shortens the object name to a unique prefix with at least `length` characters. The minimum length is 4, the default is the effective value of the `core.abbrev` @@ -159,15 +159,27 @@ for another option. unfortunately named tag "master"), and shows them as full refnames (e.g. "refs/heads/master"). +--output-object-format=(sha1|sha256|storage):: + + Allow oids to be input from any object format that the current + repository supports. + + Specifying "sha1" translates if necessary and returns a sha1 oid. + + Specifying "sha256" translates if necessary and returns a sha256 oid. + + Specifying "storage" translates if necessary and returns an oid in + encoded in the storage hash algorithm. + Options for Objects ~~~~~~~~~~~~~~~~~~~ --all:: Show all refs found in `refs/`. ---branches[=pattern]:: ---tags[=pattern]:: ---remotes[=pattern]:: +--branches[=<pattern>]:: +--tags[=<pattern>]:: +--remotes[=<pattern>]:: Show all branches, tags, or remote-tracking branches, respectively (i.e., refs found in `refs/heads`, `refs/tags`, or `refs/remotes`, respectively). @@ -176,7 +188,7 @@ If a `pattern` is given, only refs matching the given shell glob are shown. If the pattern does not contain a globbing character (`?`, `*`, or `[`), it is turned into a prefix match by appending `/*`. ---glob=pattern:: +--glob=<pattern>:: Show all refs matching the shell glob pattern `pattern`. If the pattern does not start with `refs/`, this is automatically prepended. If the pattern does not contain a globbing @@ -197,7 +209,7 @@ respectively, and they must begin with `refs/` when applied to `--glob` or `--all`. If a trailing '/{asterisk}' is intended, it must be given explicitly. ---exclude-hidden=[fetch|receive|uploadpack]:: +--exclude-hidden=(fetch|receive|uploadpack):: Do not include refs that would be hidden by `git-fetch`, `git-receive-pack` or `git-upload-pack` by consulting the appropriate `fetch.hideRefs`, `receive.hideRefs` or `uploadpack.hideRefs` @@ -314,17 +326,17 @@ The following options are unaffected by `--path-format`: Other Options ~~~~~~~~~~~~~ ---since=datestring:: ---after=datestring:: +--since=<datestring>:: +--after=<datestring>:: Parse the date string, and output the corresponding --max-age= parameter for 'git rev-list'. ---until=datestring:: ---before=datestring:: +--until=<datestring>:: +--before=<datestring>:: Parse the date string, and output the corresponding --min-age= parameter for 'git rev-list'. -<args>...:: +<arg>...:: Flags and parameters to be parsed. diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index d1ef6a204e..c5d664f451 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -9,7 +9,7 @@ git-send-email - Send a collection of patches as emails SYNOPSIS -------- [verse] -'git send-email' [<options>] <file|directory>... +'git send-email' [<options>] (<file>|<directory>)... 'git send-email' [<options>] <format-patch-options> 'git send-email' --dump-aliases @@ -138,7 +138,7 @@ Note that no attempts whatsoever are made to validate the encoding. --compose-encoding=<encoding>:: Specify encoding of compose message. Default is the value of the - 'sendemail.composeencoding'; if that is unspecified, UTF-8 is assumed. + 'sendemail.composeEncoding'; if that is unspecified, UTF-8 is assumed. --transfer-encoding=(7bit|8bit|quoted-printable|base64|auto):: Specify the transfer encoding to be used to send the message over SMTP. @@ -174,7 +174,7 @@ Sending Specify a command to run to send the email. The command should be sendmail-like; specifically, it must support the `-i` option. The command will be executed in the shell if necessary. Default - is the value of `sendemail.sendmailcmd`. If unspecified, and if + is the value of `sendemail.sendmailCmd`. If unspecified, and if --smtp-server is also unspecified, git-send-email will search for `sendmail` in `/usr/sbin`, `/usr/lib` and $PATH. @@ -269,7 +269,7 @@ must be used for each option. certificates concatenated together: see verify(1) -CAfile and -CApath for more information on these). Set it to an empty string to disable certificate verification. Defaults to the value of the - `sendemail.smtpsslcertpath` configuration variable, if set, or the + `sendemail.smtpSSLCertPath` configuration variable, if set, or the backing SSL library's compiled-in default otherwise (which should be the best choice on most platforms). @@ -278,7 +278,7 @@ must be used for each option. if a username is not specified (with `--smtp-user` or `sendemail.smtpUser`), then authentication is not attempted. ---smtp-debug=0|1:: +--smtp-debug=(0|1):: Enable (1) or disable (0) debug output. If enabled, SMTP commands and replies will be printed. Useful to debug TLS connection and authentication problems. @@ -301,7 +301,9 @@ must be used for each option. Automating ~~~~~~~~~~ ---no-[to|cc|bcc]:: +--no-to:: +--no-cc:: +--no-bcc:: Clears any list of "To:", "Cc:", "Bcc:" addresses previously set via config. @@ -313,7 +315,7 @@ Automating Specify a command to execute once per patch file which should generate patch file specific "To:" entries. Output of this command must be single email address per line. - Default is the value of 'sendemail.tocmd' configuration value. + Default is the value of 'sendemail.toCmd' configuration value. --cc-cmd=<command>:: Specify a command to execute once per patch file which @@ -348,19 +350,19 @@ Automating --[no-]signed-off-by-cc:: If this is set, add emails found in the `Signed-off-by` trailer or Cc: lines to the - cc list. Default is the value of `sendemail.signedoffbycc` configuration + cc list. Default is the value of `sendemail.signedOffByCc` configuration value; if that is unspecified, default to --signed-off-by-cc. --[no-]cc-cover:: If this is set, emails found in Cc: headers in the first patch of the series (typically the cover letter) are added to the cc list - for each email set. Default is the value of 'sendemail.cccover' + for each email set. Default is the value of 'sendemail.ccCover' configuration value; if that is unspecified, default to --no-cc-cover. --[no-]to-cover:: If this is set, emails found in To: headers in the first patch of the series (typically the cover letter) are added to the to list - for each email set. Default is the value of 'sendemail.tocover' + for each email set. Default is the value of 'sendemail.toCover' configuration value; if that is unspecified, default to --no-to-cover. --suppress-cc=<category>:: @@ -384,7 +386,7 @@ Automating - 'all' will suppress all auto cc values. -- + -Default is the value of `sendemail.suppresscc` configuration value; if +Default is the value of `sendemail.suppressCc` configuration value; if that is unspecified, default to 'self' if --suppress-from is specified, as well as 'body' if --no-signed-off-cc is specified. @@ -471,7 +473,7 @@ Information Instead of the normal operation, dump the shorthand alias names from the configured alias file(s), one per line in alphabetical order. Note that this only includes the alias name and not its expanded email addresses. - See 'sendemail.aliasesfile' for more information about aliases. + See 'sendemail.aliasesFile' for more information about aliases. CONFIGURATION diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 4dbb88373b..9a376886a5 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -79,6 +79,8 @@ Consider enabling untracked cache and split index if supported (see `git update-index --untracked-cache` and `git update-index --split-index`), Otherwise you can use `no` to have `git status` return more quickly without showing untracked files. +All usual spellings for Boolean value `true` are taken as `normal` +and `false` as `no`. The default can be changed using the status.showUntrackedFiles configuration variable documented in linkgit:git-config[1]. @@ -472,7 +474,7 @@ again, because your configuration may already be caching `git status` results, so it could be faster on subsequent runs. * The `--untracked-files=no` flag or the - `status.showUntrackedfiles=false` config (see above for both): + `status.showUntrackedFiles=no` config (see above for both): indicate that `git status` should not report untracked files. This is the fastest option. `git status` will not list the untracked files, so you need to be careful to remember if diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index 0561808cca..374a2ebd2b 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -8,21 +8,21 @@ git-update-ref - Update the object name stored in a ref safely SYNOPSIS -------- [verse] -'git update-ref' [-m <reason>] [--no-deref] (-d <ref> [<oldvalue>] | [--create-reflog] <ref> <newvalue> [<oldvalue>] | --stdin [-z]) +'git update-ref' [-m <reason>] [--no-deref] (-d <ref> [<old-oid>] | [--create-reflog] <ref> <new-oid> [<old-oid>] | --stdin [-z]) DESCRIPTION ----------- -Given two arguments, stores the <newvalue> in the <ref>, possibly +Given two arguments, stores the <new-oid> in the <ref>, possibly dereferencing the symbolic refs. E.g. `git update-ref HEAD -<newvalue>` updates the current branch head to the new object. +<new-oid>` updates the current branch head to the new object. -Given three arguments, stores the <newvalue> in the <ref>, +Given three arguments, stores the <new-oid> in the <ref>, possibly dereferencing the symbolic refs, after verifying that -the current value of the <ref> matches <oldvalue>. -E.g. `git update-ref refs/heads/master <newvalue> <oldvalue>` -updates the master branch head to <newvalue> only if its current -value is <oldvalue>. You can specify 40 "0" or an empty string -as <oldvalue> to make sure that the ref you are creating does +the current value of the <ref> matches <old-oid>. +E.g. `git update-ref refs/heads/master <new-oid> <old-oid>` +updates the master branch head to <new-oid> only if its current +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 @@ -56,15 +56,15 @@ 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 -still contains <oldvalue>. +still contains <old-oid>. With `--stdin`, update-ref reads instructions from standard input and performs all modifications together. Specify commands of the form: - update SP <ref> SP <newvalue> [SP <oldvalue>] LF - create SP <ref> SP <newvalue> LF - delete SP <ref> [SP <oldvalue>] LF - verify SP <ref> [SP <oldvalue>] LF + update SP <ref> SP <new-oid> [SP <old-oid>] LF + create SP <ref> SP <new-oid> LF + delete SP <ref> [SP <old-oid>] LF + verify SP <ref> [SP <old-oid>] LF option SP <opt> LF start LF prepare LF @@ -82,10 +82,10 @@ specify a missing value, omit the value and its preceding SP entirely. Alternatively, use `-z` to specify in NUL-terminated format, without quoting: - update SP <ref> NUL <newvalue> NUL [<oldvalue>] NUL - create SP <ref> NUL <newvalue> NUL - delete SP <ref> NUL [<oldvalue>] NUL - verify SP <ref> NUL [<oldvalue>] NUL + update SP <ref> NUL <new-oid> NUL [<old-oid>] NUL + create SP <ref> NUL <new-oid> NUL + delete SP <ref> NUL [<old-oid>] NUL + verify SP <ref> NUL [<old-oid>] NUL option SP <opt> NUL start NUL prepare NUL @@ -100,22 +100,22 @@ recognizes as an object name. Commands in any other format or a repeated <ref> produce an error. Command meanings are: update:: - Set <ref> to <newvalue> after verifying <oldvalue>, if given. - Specify a zero <newvalue> to ensure the ref does not exist - after the update and/or a zero <oldvalue> to make sure the + Set <ref> to <new-oid> after verifying <old-oid>, if given. + Specify a zero <new-oid> to ensure the ref does not exist + after the update and/or a zero <old-oid> to make sure the ref does not exist before the update. create:: - Create <ref> with <newvalue> after verifying it does not - exist. The given <newvalue> may not be zero. + Create <ref> with <new-oid> after verifying it does not + exist. The given <new-oid> may not be zero. delete:: - Delete <ref> after verifying it exists with <oldvalue>, if - given. If given, <oldvalue> may not be zero. + Delete <ref> after verifying it exists with <old-oid>, if + given. If given, <old-oid> may not be zero. verify:: - Verify <ref> against <oldvalue> but do not change it. If - <oldvalue> is zero or missing, the ref must not exist. + Verify <ref> against <old-oid> but do not change it. If + <old-oid> is zero or missing, the ref must not exist. option:: Modify the behavior of the next command naming a <ref>. @@ -141,7 +141,7 @@ abort:: Abort the transaction, releasing all locks if the transaction is in prepared state. -If all <ref>s can be locked with matching <oldvalue>s +If all <ref>s can be locked with matching <old-oid>s simultaneously, all modifications are performed. Otherwise, no modifications are performed. Note that while each individual <ref> is updated or deleted atomically, a concurrent reader may @@ -161,7 +161,7 @@ formatted as: Where "oldsha1" is the 40 character hexadecimal value previously stored in <ref>, "newsha1" is the 40 character hexadecimal value of -<newvalue> and "committer" is the committer's name, email address +<new-oid> and "committer" is the committer's name, email address and date in the standard Git committer ident format. Optionally with -m: diff --git a/Documentation/git.txt b/Documentation/git.txt index 0d25224c96..7a1b112a3e 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -174,8 +174,17 @@ If you just want to run git as if it was started in `<path>` then use directory. --no-replace-objects:: - Do not use replacement refs to replace Git objects. See - linkgit:git-replace[1] for more information. + Do not use replacement refs to replace Git objects. + This is equivalent to exporting the `GIT_NO_REPLACE_OBJECTS` + environment variable with any value. + See linkgit:git-replace[1] for more information. + +--no-lazy-fetch:: + Do not fetch missing objects from the promisor remote on + demand. Useful together with `git cat-file -e <object>` to + see if the object is locally available. + This is equivalent to setting the `GIT_NO_LAZY_FETCH` + environment variable to `1`. --literal-pathspecs:: Treat pathspecs literally (i.e. no globbing, no pathspec magic). @@ -872,6 +881,10 @@ for full details. header and packfile URIs. Set this Boolean environment variable to false to prevent this redaction. +`GIT_NO_REPLACE_OBJECTS`:: + Setting and exporting this environment variable tells Git to + ignore replacement refs and do not replace Git objects. + `GIT_LITERAL_PATHSPECS`:: Setting this Boolean environment variable to true will cause Git to treat all pathspecs literally, rather than as glob patterns. For example, @@ -893,6 +906,11 @@ for full details. Setting this Boolean environment variable to true will cause Git to treat all pathspecs as case-insensitive. +`GIT_NO_LAZY_FETCH`:: + Setting this Boolean environment variable to true tells Git + not to lazily fetch missing objects from the promisor remote + on demand. + `GIT_REFLOG_ACTION`:: When a ref is updated, reflog entries are created to keep track of the reason why the ref was updated (which is @@ -942,7 +960,7 @@ will never be returned from the commit-graph at the cost of performance. `GIT_PROTOCOL`:: For internal use only. Used in handshaking the wire protocol. Contains a colon ':' separated list of keys with optional values - 'key[=value]'. Presence of unknown keys and values must be + '<key>[=<value>]'. Presence of unknown keys and values must be ignored. + Note that servers may need to be configured to allow this variable to diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt index e5fac94322..7c709324ba 100644 --- a/Documentation/gitcli.txt +++ b/Documentation/gitcli.txt @@ -81,9 +81,6 @@ you will. Here are the rules regarding the "flags" that you should follow when you are scripting Git: - * It's preferred to use the non-dashed form of Git commands, which means that - you should prefer `git foo` to `git-foo`. - * Splitting short options to separate words (prefer `git foo -a -b` to `git foo -ab`, the latter may not even work). diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 37f91d5b50..ee9b92c90d 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -275,12 +275,12 @@ This hook executes once for the receive operation. It takes no arguments, but for each ref to be updated it receives on standard input a line of the format: - <old-value> SP <new-value> SP <ref-name> LF + <old-oid> SP <new-oid> SP <ref-name> LF -where `<old-value>` is the old object name stored in the ref, -`<new-value>` is the new object name to be stored in the ref and +where `<old-oid>` is the old object name stored in the ref, +`<new-oid>` is the new object name to be stored in the ref and `<ref-name>` is the full name of the ref. -When creating a new ref, `<old-value>` is the all-zeroes object name. +When creating a new ref, `<old-oid>` is the all-zeroes object name. If the hook exits with non-zero status, none of the refs will be updated. If the hook exits with zero, updating of individual refs can @@ -503,13 +503,13 @@ given reference transaction is in: For each reference update that was added to the transaction, the hook receives on standard input a line of the format: - <old-value> SP <new-value> SP <ref-name> LF + <old-oid> SP <new-oid> SP <ref-name> LF -where `<old-value>` is the old object name passed into the reference -transaction, `<new-value>` is the new object name to be stored in the +where `<old-oid>` is the old object name passed into the reference +transaction, `<new-oid>` is the new object name to be stored in the ref and `<ref-name>` is the full name of the ref. When force updating the reference regardless of its current value or when the reference is -to be created anew, `<old-value>` is the all-zeroes object name. To +to be created anew, `<old-oid>` is the all-zeroes object name. To distinguish these cases, you can inspect the current value of `<ref-name>` via `git rev-parse`. diff --git a/Documentation/gitprotocol-v2.txt b/Documentation/gitprotocol-v2.txt index 0b800abd56..414bc625d5 100644 --- a/Documentation/gitprotocol-v2.txt +++ b/Documentation/gitprotocol-v2.txt @@ -346,7 +346,8 @@ the 'wanted-refs' section in the server's response as explained below. want-ref <ref> Indicates to the server that the client wants to retrieve a particular ref, where <ref> is the full name of a ref on the - server. + server. It is a protocol error to send want-ref for the + same ref more than once. If the 'sideband-all' feature is advertised, the following argument can be included in the client's request: @@ -361,7 +362,8 @@ included in the client's request: If the 'packfile-uris' feature is advertised, the following argument can be included in the client's request as well as the potential addition of the 'packfile-uris' section in the server's response as -explained below. +explained below. Note that at most one `packfile-uris` line can be sent +to the server. packfile-uris <comma-separated-list-of-protocols> Indicates to the server that the client is willing to receive diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index ed8da428c9..d0be008e5e 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -479,14 +479,14 @@ set by Git if the remote helper has the 'option' capability. 'option depth' <depth>:: Deepens the history of a shallow repository. -'option deepen-since <timestamp>:: +'option deepen-since' <timestamp>:: Deepens the history of a shallow repository based on time. -'option deepen-not <ref>:: +'option deepen-not' <ref>:: Deepens the history of a shallow repository excluding ref. Multiple options add up. -'option deepen-relative {'true'|'false'}:: +'option deepen-relative' {'true'|'false'}:: Deepens the history of a shallow repository relative to current boundary. Only valid when used with "option depth". @@ -526,7 +526,7 @@ set by Git if the remote helper has the 'option' capability. 'option pushcert' {'true'|'false'}:: GPG sign pushes. -'option push-option <string>:: +'option push-option' <string>:: Transmit <string> as a push option. As the push option must not contain LF or NUL characters, the string is not encoded. @@ -542,13 +542,10 @@ set by Git if the remote helper has the 'option' capability. transaction. If successful, all refs will be updated, or none will. If the remote side does not support this capability, the push will fail. -'option object-format' {'true'|algorithm}:: - If 'true', indicate that the caller wants hash algorithm information +'option object-format true':: + Indicate that the caller wants hash algorithm information to be passed back from the remote. This mode is used when fetching refs. -+ -If set to an algorithm, indicate that the caller wants to interact with -the remote side using that algorithm. SEE ALSO -------- diff --git a/Documentation/howto/update-hook-example.txt b/Documentation/howto/update-hook-example.txt index 151ee84ceb..4e727deedd 100644 --- a/Documentation/howto/update-hook-example.txt +++ b/Documentation/howto/update-hook-example.txt @@ -100,7 +100,7 @@ info "The user is: '$username'" if test -f "$allowed_users_file" then - rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' | + rc=$(grep -Ev '^(#|$)' $allowed_users_file | while read heads user_patterns do # does this rule apply to us? @@ -138,7 +138,7 @@ info "'$groups'" if test -f "$allowed_groups_file" then - rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' | + rc=$(grep -Ev '^(#|$)' $allowed_groups_file | while read heads group_patterns do # does this rule apply to us? diff --git a/Documentation/mergetools/vimdiff.txt b/Documentation/mergetools/vimdiff.txt index d1a4c468e6..befa86d692 100644 --- a/Documentation/mergetools/vimdiff.txt +++ b/Documentation/mergetools/vimdiff.txt @@ -177,7 +177,8 @@ Instead of `--tool=vimdiff`, you can also use one of these other variants: When using these variants, in order to specify a custom layout you will have to set configuration variables `mergetool.gvimdiff.layout` and -`mergetool.nvimdiff.layout` instead of `mergetool.vimdiff.layout` +`mergetool.nvimdiff.layout` instead of `mergetool.vimdiff.layout` (though the +latter will be used as fallback if the variant-specific one is not set). In addition, for backwards compatibility with previous Git versions, you can also append `1`, `2` or `3` to either `vimdiff` or any of the variants (ex: diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index d38b4ab566..8ee940b6a4 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -316,9 +316,8 @@ multiple times, the last occurrence wins. `Reviewed-by`. ** 'only[=<bool>]': select whether non-trailer lines from the trailer block should be included. -** 'separator=<sep>': specify a separator inserted between trailer - lines. When this option is not given each trailer line is - terminated with a line feed character. The string <sep> may contain +** 'separator=<sep>': specify the separator inserted between trailer + lines. Defaults to a line feed character. The string <sep> may contain the literal formatting codes described above. To use comma as separator one must use `%x2C` as it would otherwise be parsed as next option. E.g., `%(trailers:key=Ticket,separator=%x2C )` @@ -329,10 +328,9 @@ multiple times, the last occurrence wins. `%(trailers:only,unfold=true)` unfolds and shows all trailer lines. ** 'keyonly[=<bool>]': only show the key part of the trailer. ** 'valueonly[=<bool>]': only show the value part of the trailer. -** 'key_value_separator=<sep>': specify a separator inserted between - trailer lines. When this option is not given each trailer key-value - pair is separated by ": ". Otherwise it shares the same semantics - as 'separator=<sep>' above. +** 'key_value_separator=<sep>': specify the separator inserted between + the key and value of each trailer. Defaults to ": ". Otherwise it + shares the same semantics as 'separator=<sep>' above. NOTE: Some placeholders may depend on other options given to the revision traversal engine. For example, the `%g*` reflog options will diff --git a/Documentation/ref-storage-format.txt b/Documentation/ref-storage-format.txt index 1a65cac468..14fff8a9c6 100644 --- a/Documentation/ref-storage-format.txt +++ b/Documentation/ref-storage-format.txt @@ -1 +1,3 @@ * `files` for loose files with packed-refs. This is the default. +* `reftable` for the reftable format. This format is experimental and its + internals are subject to change. diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index a583b52c61..00ccf68744 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -316,12 +316,12 @@ list. With `--pretty` format other than `oneline` and `reference` (for obvious reasons), this causes the output to have two extra lines of information taken from the reflog. The reflog designator in the output may be shown -as `ref@{Nth}` (where `Nth` is the reverse-chronological index in the -reflog) or as `ref@{timestamp}` (with the timestamp for that entry), +as `ref@{<Nth>}` (where _<Nth>_ is the reverse-chronological index in the +reflog) or as `ref@{<timestamp>}` (with the _<timestamp>_ for that entry), depending on a few rules: + -- -1. If the starting point is specified as `ref@{Nth}`, show the index +1. If the starting point is specified as `ref@{<Nth>}`, show the index format. + 2. If the starting point was specified as `ref@{now}`, show the @@ -341,8 +341,11 @@ See also linkgit:git-reflog[1]. Under `--pretty=reference`, this information will not be shown at all. --merge:: - After a failed merge, show refs that touch files having a - conflict and don't exist on all heads to merge. + Show commits touching conflicted paths in the range `HEAD...<other>`, + where `<other>` is the first existing pseudoref in `MERGE_HEAD`, + `CHERRY_PICK_HEAD`, `REVERT_HEAD` or `REBASE_HEAD`. Only works + when the index has unmerged entries. This option can be used to show + relevant commits when resolving conflicts from a 3-way merge. --boundary:: Output excluded boundary commits. Boundary commits are @@ -1019,6 +1022,10 @@ Unexpected missing objects will raise an error. + The form '--missing=print' is like 'allow-any', but will also print a list of the missing objects. Object IDs are prefixed with a ``?'' character. ++ +If some tips passed to the traversal are missing, they will be +considered as missing too, and the traversal will ignore them. In case +we cannot get their Object ID though, an error will be raised. --exclude-promisor-objects:: (For internal use only.) Prefilter object traversal at diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.txt index 27be3741e6..47281420fc 100644 --- a/Documentation/technical/repository-version.txt +++ b/Documentation/technical/repository-version.txt @@ -103,5 +103,6 @@ GIT_COMMON_DIR/worktrees/<id>/config.worktree) ==== `refStorage` -Specifies the file format for the ref database. The only valid value -is `files` (loose references with a packed-refs file). +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). diff --git a/Documentation/urls.txt b/Documentation/urls.txt index ce671f812d..7cec85aef1 100644 --- a/Documentation/urls.txt +++ b/Documentation/urls.txt @@ -15,14 +15,14 @@ should be used with caution on unsecured networks. The following syntaxes may be used with them: -- ssh://{startsb}user@{endsb}host.xz{startsb}:port{endsb}/path/to/repo.git/ -- git://host.xz{startsb}:port{endsb}/path/to/repo.git/ -- http{startsb}s{endsb}://host.xz{startsb}:port{endsb}/path/to/repo.git/ -- ftp{startsb}s{endsb}://host.xz{startsb}:port{endsb}/path/to/repo.git/ +- ++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>__ An alternative scp-like syntax may also be used with the ssh protocol: -- {startsb}user@{endsb}host.xz:path/to/repo.git/ +- {startsb}__<user>__++@++{endsb}__<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,40 +30,40 @@ 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.xz{startsb}:port{endsb}/~{startsb}user{endsb}/path/to/repo.git/ -- git://host.xz{startsb}:port{endsb}/~{startsb}user{endsb}/path/to/repo.git/ -- {startsb}user@{endsb}host.xz:/~{startsb}user{endsb}/path/to/repo.git/ +- ++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>__ For local repositories, also supported by Git natively, the following syntaxes may be used: -- /path/to/repo.git/ -- \file:///path/to/repo.git/ +- `/path/to/repo.git/` +- ++file:///path/to/repo.git/++ ifndef::git-clone[] These two syntaxes are mostly equivalent, except when cloning, when -the former implies --local option. See linkgit:git-clone[1] for +the former implies `--local` option. See linkgit:git-clone[1] for details. endif::git-clone[] ifdef::git-clone[] These two syntaxes are mostly equivalent, except the former implies ---local option. +`--local` option. endif::git-clone[] -'git clone', 'git fetch' and 'git pull', but not 'git push', will also +`git clone`, `git fetch` and `git pull`, but not `git push`, will also 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-<transport>' remote helper, if one +attempts to use the `remote-`{empty}__<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 +where _<address>_ may be a path, a server and path, or an arbitrary URL-like string recognized by the specific remote helper being invoked. See linkgit:gitremote-helpers[7] for details. @@ -72,10 +72,11 @@ you want to use a different format for them (such that the URLs you use will be rewritten into URLs that work), you can create a configuration section of the form: ------------- - [url "<actual-url-base>"] - insteadOf = <other-url-base> ------------- +[verse] +-- + [url "__<actual-url-base>__"] + insteadOf = _<other-url-base>_ +-- For example, with this: @@ -91,10 +92,11 @@ rewritten in any context that takes a URL to be "git://git.host.xz/repo.git". If you want to rewrite URLs for push only, you can create a configuration section of the form: ------------- - [url "<actual-url-base>"] - pushInsteadOf = <other-url-base> ------------- +[verse] +-- + [url "__<actual-url-base>__"] + pushInsteadOf = _<other-url-base>_ +-- For example, with this: diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 6433903491..90a4189358 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -4093,7 +4093,38 @@ that not only specifies their type, but also provides size information about the data in the object. It's worth noting that the SHA-1 hash that is used to name the object is the hash of the original data plus this header, so `sha1sum` 'file' does not match the object name -for 'file'. +for 'file' (the earliest versions of Git hashed slightly differently +but the conclusion is still the same). + +The following is a short example that demonstrates how these hashes +can be generated manually: + +Let's assume a small text file with some simple content: + +------------------------------------------------- +$ echo "Hello world" >hello.txt +------------------------------------------------- + +We can now manually generate the hash Git would use for this file: + +- The object we want the hash for is of type "blob" and its size is + 12 bytes. + +- Prepend the object header to the file content and feed this to + `sha1sum`: + +------------------------------------------------- +$ { printf "blob 12\0"; cat hello.txt; } | sha1sum +802992c4220de19a90767f3000a79a31b98d0df7 - +------------------------------------------------- + +This manually constructed hash can be verified using `git hash-object` +which of course hides the addition of the header: + +------------------------------------------------- +$ git hash-object hello.txt +802992c4220de19a90767f3000a79a31b98d0df7 +------------------------------------------------- As a result, the general consistency of an object can always be tested independently of the contents or the type of the object: all objects can @@ -4123,7 +4154,8 @@ $ git switch --detach e83c5163 ---------------------------------------------------- The initial revision lays the foundation for almost everything Git has -today, but is small enough to read in one sitting. +today (even though details may differ in a few places), but is small +enough to read in one sitting. Note that terminology has changed since that revision. For example, the README in that revision uses the word "changeset" to describe what we diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 6339941f8b..433cf41e59 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.44.0-rc2 +DEF_VER=v2.45.0 LF=' ' @@ -139,7 +139,7 @@ Issues of note: not need that functionality, use NO_CURL to build without it. - Git requires version "7.19.5" or later of "libcurl" to build + Git requires version "7.21.3" or later of "libcurl" to build without NO_CURL. This version requirement may be bumped in the future. @@ -757,6 +757,7 @@ ETAGS_TARGET = TAGS # runs in the future. 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-date.o FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o @@ -797,6 +798,7 @@ TEST_BUILTINS_OBJS += test-config.o TEST_BUILTINS_OBJS += test-crontab.o TEST_BUILTINS_OBJS += test-csprng.o TEST_BUILTINS_OBJS += test-date.o +TEST_BUILTINS_OBJS += test-delete-gpgsig.o TEST_BUILTINS_OBJS += test-delta.o TEST_BUILTINS_OBJS += test-dir-iterator.o TEST_BUILTINS_OBJS += test-drop-caches.o @@ -1060,6 +1062,7 @@ LIB_OBJS += list-objects-filter.o LIB_OBJS += list-objects.o LIB_OBJS += lockfile.o LIB_OBJS += log-tree.o +LIB_OBJS += loose.o LIB_OBJS += ls-refs.o LIB_OBJS += mailinfo.o LIB_OBJS += mailmap.o @@ -1072,6 +1075,7 @@ LIB_OBJS += merge-ort-wrappers.o LIB_OBJS += merge-recursive.o LIB_OBJS += merge.o LIB_OBJS += midx.o +LIB_OBJS += midx-write.o LIB_OBJS += name-hash.o LIB_OBJS += negotiator/default.o LIB_OBJS += negotiator/noop.o @@ -1080,6 +1084,7 @@ LIB_OBJS += notes-cache.o LIB_OBJS += notes-merge.o LIB_OBJS += notes-utils.o LIB_OBJS += notes.o +LIB_OBJS += object-file-convert.o LIB_OBJS += object-file.o LIB_OBJS += object-name.o LIB_OBJS += object.o @@ -1126,6 +1131,7 @@ LIB_OBJS += reflog.o LIB_OBJS += refs.o LIB_OBJS += refs/debug.o LIB_OBJS += refs/files-backend.o +LIB_OBJS += refs/reftable-backend.o LIB_OBJS += refs/iterator.o LIB_OBJS += refs/packed-backend.o LIB_OBJS += refs/ref-cache.o @@ -1552,23 +1558,23 @@ ifneq (,$(SOCKLEN_T)) endif ifeq ($(uname_S),Darwin) - ifndef NO_FINK - ifeq ($(shell test -d /sw/lib && echo y),y) + ifndef NO_FINK + ifeq ($(shell test -d /sw/lib && echo y),y) BASIC_CFLAGS += -I/sw/include BASIC_LDFLAGS += -L/sw/lib - endif - endif - ifndef NO_DARWIN_PORTS - ifeq ($(shell test -d /opt/local/lib && echo y),y) + endif + endif + ifndef NO_DARWIN_PORTS + ifeq ($(shell test -d /opt/local/lib && echo y),y) BASIC_CFLAGS += -I/opt/local/include BASIC_LDFLAGS += -L/opt/local/lib - endif - endif - ifndef NO_APPLE_COMMON_CRYPTO + endif + endif + ifndef NO_APPLE_COMMON_CRYPTO NO_OPENSSL = YesPlease APPLE_COMMON_CRYPTO = YesPlease COMPAT_CFLAGS += -DAPPLE_COMMON_CRYPTO - endif + endif PTHREAD_LIBS = endif @@ -1607,23 +1613,23 @@ ifdef NO_CURL REMOTE_CURL_NAMES = EXCLUDED_PROGRAMS += git-http-fetch git-http-push else - ifdef CURLDIR + ifdef CURLDIR # Try "-Wl,-rpath=$(CURLDIR)/$(lib)" in such a case. CURL_CFLAGS = -I$(CURLDIR)/include CURL_LIBCURL = $(call libpath_template,$(CURLDIR)/$(lib)) - else + else CURL_CFLAGS = CURL_LIBCURL = - endif + endif - ifndef CURL_LDFLAGS + ifndef CURL_LDFLAGS CURL_LDFLAGS = $(eval CURL_LDFLAGS := $$(shell $$(CURL_CONFIG) --libs))$(CURL_LDFLAGS) - endif + endif CURL_LIBCURL += $(CURL_LDFLAGS) - ifndef CURL_CFLAGS + ifndef CURL_CFLAGS CURL_CFLAGS = $(eval CURL_CFLAGS := $$(shell $$(CURL_CONFIG) --cflags))$(CURL_CFLAGS) - endif + endif BASIC_CFLAGS += $(CURL_CFLAGS) REMOTE_CURL_PRIMARY = git-remote-http$X @@ -1631,29 +1637,29 @@ else REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES) PROGRAM_OBJS += http-fetch.o PROGRAMS += $(REMOTE_CURL_NAMES) - ifndef NO_EXPAT + ifndef NO_EXPAT PROGRAM_OBJS += http-push.o - endif + endif curl_check := $(shell (echo 072200; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p) - ifeq "$(curl_check)" "072200" + ifeq "$(curl_check)" "072200" USE_CURL_FOR_IMAP_SEND = YesPlease - endif - ifdef USE_CURL_FOR_IMAP_SEND + endif + ifdef USE_CURL_FOR_IMAP_SEND BASIC_CFLAGS += -DUSE_CURL_FOR_IMAP_SEND IMAP_SEND_BUILDDEPS = http.o IMAP_SEND_LDFLAGS += $(CURL_LIBCURL) - endif - ifndef NO_EXPAT - ifdef EXPATDIR + endif + ifndef NO_EXPAT + ifdef EXPATDIR BASIC_CFLAGS += -I$(EXPATDIR)/include EXPAT_LIBEXPAT = $(call libpath_template,$(EXPATDIR)/$(lib)) -lexpat - else + else EXPAT_LIBEXPAT = -lexpat - endif - ifdef EXPAT_NEEDS_XMLPARSE_H + endif + ifdef EXPAT_NEEDS_XMLPARSE_H BASIC_CFLAGS += -DEXPAT_NEEDS_XMLPARSE_H - endif - endif + endif + endif endif IMAP_SEND_LDFLAGS += $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO) @@ -1665,15 +1671,15 @@ EXTLIBS += -lz ifndef NO_OPENSSL OPENSSL_LIBSSL = -lssl - ifdef OPENSSLDIR + ifdef OPENSSLDIR BASIC_CFLAGS += -I$(OPENSSLDIR)/include OPENSSL_LINK = $(call libpath_template,$(OPENSSLDIR)/$(lib)) - else + else OPENSSL_LINK = - endif - ifdef NEEDS_CRYPTO_WITH_SSL + endif + ifdef NEEDS_CRYPTO_WITH_SSL OPENSSL_LIBSSL += -lcrypto - endif + endif else BASIC_CFLAGS += -DNO_OPENSSL OPENSSL_LIBSSL = @@ -1691,18 +1697,18 @@ ifdef APPLE_COMMON_CRYPTO endif endif ifndef NO_ICONV - ifdef NEEDS_LIBICONV - ifdef ICONVDIR + ifdef NEEDS_LIBICONV + ifdef ICONVDIR BASIC_CFLAGS += -I$(ICONVDIR)/include ICONV_LINK = $(call libpath_template,$(ICONVDIR)/$(lib)) - else + else ICONV_LINK = - endif - ifdef NEEDS_LIBINTL_BEFORE_LIBICONV + endif + ifdef NEEDS_LIBINTL_BEFORE_LIBICONV ICONV_LINK += -lintl - endif + endif EXTLIBS += $(ICONV_LINK) -liconv - endif + endif endif ifdef ICONV_OMITS_BOM BASIC_CFLAGS += -DICONV_OMITS_BOM @@ -1823,10 +1829,10 @@ ifdef NO_MMAP COMPAT_CFLAGS += -DNO_MMAP COMPAT_OBJS += compat/mmap.o else - ifdef USE_WIN32_MMAP + ifdef USE_WIN32_MMAP COMPAT_CFLAGS += -DUSE_WIN32_MMAP COMPAT_OBJS += compat/win32mmap.o - endif + endif endif ifdef MMAP_PREVENTS_DELETE BASIC_CFLAGS += -DMMAP_PREVENTS_DELETE @@ -1951,11 +1957,11 @@ else BASIC_CFLAGS += -DSHA1_DC LIB_OBJS += sha1dc_git.o ifdef DC_SHA1_EXTERNAL - ifdef DC_SHA1_SUBMODULE - ifneq ($(DC_SHA1_SUBMODULE),auto) + ifdef DC_SHA1_SUBMODULE + ifneq ($(DC_SHA1_SUBMODULE),auto) $(error Only set DC_SHA1_EXTERNAL or DC_SHA1_SUBMODULE, not both) - endif - endif + endif + endif BASIC_CFLAGS += -DDC_SHA1_EXTERNAL EXTLIBS += -lsha1detectcoll else @@ -1 +1 @@ -Documentation/RelNotes/2.44.0.txt
\ No newline at end of file +Documentation/RelNotes/2.45.0.txt
\ No newline at end of file diff --git a/add-interactive.c b/add-interactive.c index 6bf87e7ae7..e17602b5e4 100644 --- a/add-interactive.c +++ b/add-interactive.c @@ -865,6 +865,7 @@ static int get_untracked_files(struct repository *r, } strbuf_release(&buf); + dir_clear(&dir); return 0; } diff --git a/add-patch.c b/add-patch.c index 79eda168eb..0997d4af73 100644 --- a/add-patch.c +++ b/add-patch.c @@ -1105,26 +1105,26 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk) size_t i; strbuf_reset(&s->buf); - strbuf_commented_addf(&s->buf, comment_line_char, + strbuf_commented_addf(&s->buf, comment_line_str, _("Manual hunk edit mode -- see bottom for " "a quick guide.\n")); render_hunk(s, hunk, 0, 0, &s->buf); - strbuf_commented_addf(&s->buf, comment_line_char, + strbuf_commented_addf(&s->buf, comment_line_str, _("---\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"), s->mode->is_reverse ? '+' : '-', s->mode->is_reverse ? '-' : '+', - comment_line_char); - strbuf_commented_addf(&s->buf, comment_line_char, "%s", + comment_line_str); + strbuf_commented_addf(&s->buf, comment_line_str, "%s", _(s->mode->edit_hunk_hint)); /* * TRANSLATORS: 'it' refers to the patch mentioned in the previous * messages. */ - strbuf_commented_addf(&s->buf, comment_line_char, + strbuf_commented_addf(&s->buf, comment_line_str, _("If it does not apply cleanly, you will be " "given an opportunity to\n" "edit again. If all lines of the hunk are " @@ -1139,7 +1139,7 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk) for (i = 0; i < s->buf.len; ) { size_t next = find_next_line(&s->buf, i); - if (s->buf.buf[i] != comment_line_char) + if (!starts_with(s->buf.buf + i, comment_line_str)) strbuf_add(&s->plain, s->buf.buf + i, next - i); i = next; } @@ -1388,13 +1388,14 @@ 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" "? - print help\n"); static int patch_update_file(struct add_p_state *s, struct file_diff *file_diff) { size_t hunk_index = 0; - ssize_t i, undecided_previous, undecided_next; + ssize_t i, undecided_previous, undecided_next, rendered_hunk_index = -1; struct hunk *hunk; char ch; struct child_process cp = CHILD_PROCESS_INIT; @@ -1447,8 +1448,11 @@ static int patch_update_file(struct add_p_state *s, strbuf_reset(&s->buf); if (file_diff->hunk_nr) { - render_hunk(s, hunk, 0, colored, &s->buf); - fputs(s->buf.buf, stdout); + if (rendered_hunk_index != hunk_index) { + render_hunk(s, hunk, 0, colored, &s->buf); + fputs(s->buf.buf, stdout); + rendered_hunk_index = hunk_index; + } strbuf_reset(&s->buf); if (undecided_previous >= 0) { @@ -1480,6 +1484,7 @@ static int patch_update_file(struct add_p_state *s, permitted |= ALLOW_EDIT; strbuf_addstr(&s->buf, ",e"); } + strbuf_addstr(&s->buf, ",p"); } if (file_diff->deleted) prompt_mode_type = PROMPT_DELETION; @@ -1641,16 +1646,19 @@ soft_increment: err(s, _("No hunk matches the given pattern")); break; } + regfree(®ex); hunk_index = i; } else if (s->answer.buf[0] == 's') { size_t splittable_into = hunk->splittable_into; - if (!(permitted & ALLOW_SPLIT)) + if (!(permitted & ALLOW_SPLIT)) { err(s, _("Sorry, cannot split this hunk")); - else if (!split_hunk(s, file_diff, - hunk - file_diff->hunk)) + } else if (!split_hunk(s, file_diff, + hunk - file_diff->hunk)) { color_fprintf_ln(stdout, s->s.header_color, _("Split into %d hunks."), (int)splittable_into); + rendered_hunk_index = -1; + } } else if (s->answer.buf[0] == 'e') { if (!(permitted & ALLOW_EDIT)) err(s, _("Sorry, cannot edit this hunk")); @@ -1658,6 +1666,8 @@ soft_increment: hunk->use = USE_HUNK; goto soft_increment; } + } else if (s->answer.buf[0] == 'p') { + rendered_hunk_index = -1; } else { const char *p = _(help_patch_remainder), *eol = p; @@ -1729,14 +1739,6 @@ int run_add_p(struct repository *r, enum add_p_mode mode, if (mode == ADD_P_STASH) s.mode = &patch_mode_stash; else if (mode == ADD_P_RESET) { - /* - * NEEDSWORK: Instead of comparing to the literal "HEAD", - * compare the commit objects instead so that other ways of - * saying the same thing (such as "@") are also handled - * appropriately. - * - * This applies to the cases below too. - */ if (!revision || !strcmp(revision, "HEAD")) s.mode = &patch_mode_reset_head; else @@ -57,6 +57,7 @@ static struct { [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated" }, [ADVICE_IGNORED_HOOK] = { "ignoredHook" }, [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity" }, + [ADVICE_MERGE_CONFLICT] = { "mergeConflict" }, [ADVICE_NESTED_TAG] = { "nestedTag" }, [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning" }, [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists" }, @@ -68,6 +69,7 @@ static struct { [ADVICE_PUSH_UNQUALIFIED_REF_NAME] = { "pushUnqualifiedRefName" }, [ADVICE_PUSH_UPDATE_REJECTED] = { "pushUpdateRejected" }, [ADVICE_PUSH_UPDATE_REJECTED_ALIAS] = { "pushNonFastForward" }, /* backwards compatibility */ + [ADVICE_REF_SYNTAX] = { "refSyntax" }, [ADVICE_RESET_NO_REFRESH_WARNING] = { "resetNoRefresh" }, [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict" }, [ADVICE_RM_HINTS] = { "rmHints" }, @@ -79,6 +81,7 @@ static struct { [ADVICE_STATUS_U_OPTION] = { "statusUoption" }, [ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated" }, [ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie" }, + [ADVICE_SUBMODULE_MERGE_CONFLICT] = { "submoduleMergeConflict" }, [ADVICE_SUGGEST_DETACHING_HEAD] = { "suggestDetachingHead" }, [ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath" }, [ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor" }, @@ -102,8 +105,9 @@ static void vadvise(const char *advice, int display_instructions, for (cp = buf.buf; *cp; cp = np) { np = strchrnul(cp, '\n'); - fprintf(stderr, _("%shint: %.*s%s\n"), + fprintf(stderr, _("%shint:%s%.*s%s\n"), advise_get_color(ADVICE_COLOR_HINT), + (np == cp) ? "" : " ", (int)(np - cp), cp, advise_get_color(ADVICE_COLOR_RESET)); if (*np) @@ -25,6 +25,7 @@ enum advice_type { ADVICE_GRAFT_FILE_DEPRECATED, ADVICE_IGNORED_HOOK, ADVICE_IMPLICIT_IDENTITY, + ADVICE_MERGE_CONFLICT, ADVICE_NESTED_TAG, ADVICE_OBJECT_NAME_WARNING, ADVICE_PUSH_ALREADY_EXISTS, @@ -36,6 +37,7 @@ enum advice_type { ADVICE_PUSH_UNQUALIFIED_REF_NAME, ADVICE_PUSH_UPDATE_REJECTED, ADVICE_PUSH_UPDATE_REJECTED_ALIAS, + ADVICE_REF_SYNTAX, ADVICE_RESET_NO_REFRESH_WARNING, ADVICE_RESOLVE_CONFLICT, ADVICE_RM_HINTS, @@ -47,6 +49,7 @@ enum advice_type { ADVICE_STATUS_U_OPTION, ADVICE_SUBMODULES_NOT_UPDATED, ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE, + ADVICE_SUBMODULE_MERGE_CONFLICT, ADVICE_SUGGEST_DETACHING_HEAD, ADVICE_UPDATE_SPARSE_PATH, ADVICE_WAITING_FOR_EDITOR, @@ -77,7 +77,8 @@ static int parse_whitespace_option(struct apply_state *state, const char *option return 0; } /* - * Please update $__git_whitespacelist in git-completion.bash + * Please update $__git_whitespacelist in git-completion.bash, + * Documentation/git-apply.txt, and Documentation/git-am.txt * when you add new options. */ return error(_("unrecognized whitespace option '%s'"), option); @@ -1291,8 +1292,15 @@ static char *git_header_name(int p_value, return NULL; /* no postimage name */ second = skip_tree_prefix(p_value, name + len + 1, line_len - (len + 1)); + /* + * If we are at the SP at the end of a directory, + * skip_tree_prefix() may return NULL as that makes + * it appears as if we have an absolute path. + * Keep going to find another SP. + */ if (!second) - return NULL; + continue; + /* * Does len bytes starting at "name" and "second" * (that are separated by one HT or SP we just @@ -2219,7 +2227,8 @@ static void reverse_patches(struct patch *p) struct fragment *frag = p->fragments; SWAP(p->new_name, p->old_name); - SWAP(p->new_mode, p->old_mode); + if (p->new_mode) + SWAP(p->new_mode, p->old_mode); SWAP(p->is_new, p->is_delete); SWAP(p->lines_added, p->lines_deleted); SWAP(p->old_oid_prefix, p->new_oid_prefix); @@ -3703,8 +3712,10 @@ static int apply_data(struct apply_state *state, struct patch *patch, fprintf(stderr, _("Falling back to direct application...\n")); /* Note: with --reject, apply_fragments() returns 0 */ - if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) + if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) { + clear_image(&image); return -1; + } } patch->result = image.buf; patch->resultsize = image.len; @@ -3777,8 +3788,17 @@ static int check_preimage(struct apply_state *state, return error_errno("%s", old_name); } - if (!state->cached && !previous) - st_mode = ce_mode_from_stat(*ce, st->st_mode); + if (!state->cached && !previous) { + if (*ce && !(*ce)->ce_mode) + BUG("ce_mode == 0 for path '%s'", old_name); + + if (trust_executable_bit) + st_mode = ce_mode_from_stat(*ce, st->st_mode); + else if (*ce) + st_mode = (*ce)->ce_mode; + else + st_mode = patch->old_mode; + } if (patch->is_new < 0) patch->is_new = 0; @@ -4430,6 +4450,7 @@ static int create_one_file(struct apply_state *state, const char *buf, unsigned long size) { + char *newpath = NULL; int res; if (state->cached) @@ -4491,24 +4512,26 @@ static int create_one_file(struct apply_state *state, unsigned int nr = getpid(); for (;;) { - char newpath[PATH_MAX]; - mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr); + newpath = mkpathdup("%s~%u", path, nr); res = try_create_file(state, newpath, mode, buf, size); if (res < 0) - return -1; + goto out; if (!res) { if (!rename(newpath, path)) - return 0; + goto out; unlink_or_warn(newpath); break; } if (errno != EEXIST) break; ++nr; + FREE_AND_NULL(newpath); } } - return error_errno(_("unable to write file '%s' mode %o"), - path, mode); + res = error_errno(_("unable to write file '%s' mode %o"), path, mode); +out: + free(newpath); + return res; } static int add_conflicted_stages_file(struct apply_state *state, @@ -4591,7 +4614,7 @@ static int write_out_one_result(struct apply_state *state, static int write_out_one_reject(struct apply_state *state, struct patch *patch) { FILE *rej; - char namebuf[PATH_MAX]; + char *namebuf; struct fragment *frag; int fd, cnt = 0; struct strbuf sb = STRBUF_INIT; @@ -4624,28 +4647,30 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch) say_patch_name(stderr, sb.buf, patch); strbuf_release(&sb); - cnt = strlen(patch->new_name); - if (ARRAY_SIZE(namebuf) <= cnt + 5) { - cnt = ARRAY_SIZE(namebuf) - 5; - warning(_("truncating .rej filename to %.*s.rej"), - cnt - 1, patch->new_name); - } - memcpy(namebuf, patch->new_name, cnt); - memcpy(namebuf + cnt, ".rej", 5); + namebuf = xstrfmt("%s.rej", patch->new_name); fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666); if (fd < 0) { - if (errno != EEXIST) - return error_errno(_("cannot open %s"), namebuf); - if (unlink(namebuf)) - return error_errno(_("cannot unlink '%s'"), namebuf); + if (errno != EEXIST) { + error_errno(_("cannot open %s"), namebuf); + goto error; + } + if (unlink(namebuf)) { + error_errno(_("cannot unlink '%s'"), namebuf); + goto error; + } fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666); - if (fd < 0) - return error_errno(_("cannot open %s"), namebuf); + if (fd < 0) { + error_errno(_("cannot open %s"), namebuf); + goto error; + } } rej = fdopen(fd, "w"); - if (!rej) - return error_errno(_("cannot open %s"), namebuf); + if (!rej) { + error_errno(_("cannot open %s"), namebuf); + close(fd); + goto error; + } /* Normal git tools never deal with .rej, so do not pretend * this is a git patch by saying --git or giving extended @@ -4669,6 +4694,8 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch) fputc('\n', rej); } fclose(rej); +error: + free(namebuf); return -1; } diff --git a/archive-tar.c b/archive-tar.c index f2a0ed7752..8ae30125f8 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -365,7 +365,7 @@ static struct archiver *find_tar_filter(const char *name, size_t len) int i; for (i = 0; i < nr_tar_filters; i++) { struct archiver *ar = tar_filters[i]; - if (!strncmp(ar->name, name, len) && !ar->name[len]) + if (!xstrncmpz(ar->name, name, len)) return ar; } return NULL; @@ -339,7 +339,8 @@ int write_archive_entries(struct archiver_args *args, opts.src_index = args->repo->index; opts.dst_index = args->repo->index; opts.fn = oneway_merge; - init_tree_desc(&t, args->tree->buffer, args->tree->size); + 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); @@ -836,10 +836,11 @@ static void handle_skipped_merge_base(const struct object_id *mb) static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int no_checkout) { enum bisect_error res = BISECT_OK; - struct commit_list *result; + struct commit_list *result = NULL; - result = repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1, - rev + 1); + if (repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1, + rev + 1, &result) < 0) + exit(128); for (; result; result = result->next) { const struct object_id *mb = &result->item->object.oid; @@ -945,23 +946,32 @@ static enum bisect_error check_good_are_ancestors_of_bad(struct repository *r, } /* - * This does "git diff-tree --pretty COMMIT" without one fork+exec. + * Display a commit summary to the user. */ -static void show_diff_tree(struct repository *r, - const char *prefix, - struct commit *commit) +static void show_commit(struct commit *commit) { - const char *argv[] = { - "diff-tree", "--pretty", "--stat", "--summary", "--cc", NULL - }; - struct rev_info opt; - - git_config(git_diff_ui_config, NULL); - repo_init_revisions(r, &opt, prefix); + struct child_process show = CHILD_PROCESS_INIT; - setup_revisions(ARRAY_SIZE(argv) - 1, argv, &opt, NULL); - log_tree_commit(&opt, commit); - release_revisions(&opt); + /* + * Call git show with --no-pager, as it would otherwise + * paginate the "git show" output only, not the output + * from bisect_next_all(); this can be fixed by moving + * it into a --format parameter, but that would override + * the user's default options for "git show", which we + * are trying to honour. + */ + strvec_pushl(&show.args, + "--no-pager", + "show", + "--stat", + "--summary", + "--no-abbrev-commit", + "--diff-merges=first-parent", + oid_to_hex(&commit->object.oid), NULL); + show.git_cmd = 1; + if (run_command(&show)) + die(_("unable to start 'show' for object '%s'"), + oid_to_hex(&commit->object.oid)); } /* @@ -1078,7 +1088,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) printf("%s is the first %s commit\n", oid_to_hex(bisect_rev), term_bad); - show_diff_tree(r, prefix, revs.commits->item); + show_commit(revs.commits->item); /* * This means the bisection process succeeded. * Using BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND (-10) @@ -370,8 +370,12 @@ 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)) - die(_("'%s' is not a valid branch name"), name); + if (strbuf_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`")); + exit(code); + } return ref_exists(ref->buf); } @@ -734,7 +738,7 @@ static int submodule_create_branch(struct repository *r, } void create_branches_recursively(struct repository *r, const char *name, - const char *start_commitish, + const char *start_committish, const char *tracking_name, int force, int reflog, int quiet, enum branch_track track, int dry_run) @@ -744,8 +748,8 @@ void create_branches_recursively(struct repository *r, const char *name, struct object_id super_oid; struct submodule_entry_list submodule_entry_list; - /* Perform dwim on start_commitish to get super_oid and branch_point. */ - dwim_branch_start(r, start_commitish, BRANCH_TRACK_NEVER, + /* Perform dwim on start_committish to get super_oid and branch_point. */ + dwim_branch_start(r, start_committish, BRANCH_TRACK_NEVER, &branch_point, &super_oid); /* @@ -768,7 +772,7 @@ void create_branches_recursively(struct repository *r, const char *name, submodule_entry_list.entries[i].submodule->name); if (advice_enabled(ADVICE_SUBMODULES_NOT_UPDATED)) advise(_("You may try updating the submodules using 'git checkout --no-recurse-submodules %s && git submodule update --init'"), - start_commitish); + start_committish); exit(code); } @@ -783,7 +787,7 @@ void create_branches_recursively(struct repository *r, const char *name, name); } - create_branch(r, name, start_commitish, force, 0, reflog, quiet, + create_branch(r, name, start_committish, force, 0, reflog, quiet, BRANCH_TRACK_NEVER, dry_run); if (dry_run) return; @@ -78,26 +78,26 @@ void create_branch(struct repository *r, * those of create_branch() except for start_name, which is represented * by two different parameters: * - * - start_commitish is the commit-ish, in repository r, that determines + * - start_committish is the commit-ish, in repository r, that determines * which commits the branches will point to. The superproject branch - * will point to the commit of start_commitish and the submodule - * branches will point to the gitlink commit oids in start_commitish's + * will point to the commit of start_committish and the submodule + * branches will point to the gitlink commit oids in start_committish's * tree. * * - tracking_name is the name of the ref, in repository r, that will be * used to set up tracking information. This value is propagated to * all submodules, which will evaluate the ref using their own ref - * stores. If NULL, this defaults to start_commitish. + * stores. If NULL, this defaults to start_committish. * - * When this function is called on the superproject, start_commitish + * When this function is called on the superproject, start_committish * can be any user-provided ref and tracking_name can be NULL (similar * to create_branches()). But when recursing through submodules, - * start_commitish is the plain gitlink commit oid. Since the oid cannot + * start_committish is the plain gitlink commit oid. Since the oid cannot * be used for tracking information, tracking_name is propagated and * used for tracking instead. */ void create_branches_recursively(struct repository *r, const char *name, - const char *start_commitish, + const char *start_committish, const char *tracking_name, int force, int reflog, int quiet, enum branch_track track, int dry_run); diff --git a/builtin/add.c b/builtin/add.c index ada7719561..b7d3ff1e28 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -115,7 +115,7 @@ static int refresh(int verbose, const struct pathspec *pathspec) int i, ret = 0; char *skip_worktree_seen = NULL; struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP; - int flags = REFRESH_IGNORE_SKIP_WORKTREE | + unsigned int flags = REFRESH_IGNORE_SKIP_WORKTREE | (verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET); seen = xcalloc(pathspec->nr, 1); @@ -150,7 +150,7 @@ static int refresh(int verbose, const struct pathspec *pathspec) int interactive_add(const char **argv, const char *prefix, int patch) { struct pathspec pathspec; - int unused; + int unused, ret; if (!git_config_get_bool("add.interactive.usebuiltin", &unused)) warning(_("the add.interactive.useBuiltin setting has been removed!\n" @@ -163,9 +163,12 @@ int interactive_add(const char **argv, const char *prefix, int patch) prefix, argv); if (patch) - return !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec); + ret = !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec); else - return !!run_add_i(the_repository, &pathspec); + ret = !!run_add_i(the_repository, &pathspec); + + clear_pathspec(&pathspec); + return ret; } static int edit_patch(int argc, const char **argv, const char *prefix) @@ -310,9 +313,9 @@ static void check_embedded_repo(const char *path) strbuf_strip_suffix(&name, "/"); warning(_("adding embedded git repository: %s"), name.buf); - if (!adviced_on_embedded_repo && - advice_enabled(ADVICE_ADD_EMBEDDED_REPO)) { - advise(embedded_advice, name.buf, name.buf); + if (!adviced_on_embedded_repo) { + advise_if_enabled(ADVICE_ADD_EMBEDDED_REPO, + embedded_advice, name.buf, name.buf); adviced_on_embedded_repo = 1; } @@ -328,10 +331,8 @@ static int add_files(struct dir_struct *dir, int flags) fprintf(stderr, _(ignore_error)); for (i = 0; i < dir->ignored_nr; i++) fprintf(stderr, "%s\n", dir->ignored[i]->name); - if (advice_enabled(ADVICE_ADD_IGNORED_FILE)) - advise(_("Use -f if you really want to add them.\n" - "Turn this message off by running\n" - "\"git config advice.addIgnoredFile false\"")); + advise_if_enabled(ADVICE_ADD_IGNORED_FILE, + _("Use -f if you really want to add them.")); exit_status = 1; } @@ -370,6 +371,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) int add_new_files; int require_pathspec; char *seen = NULL; + char *ps_matched = NULL; struct lock_file lock_file = LOCK_INIT; git_config(add_config, NULL); @@ -440,10 +442,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (require_pathspec && pathspec.nr == 0) { fprintf(stderr, _("Nothing specified, nothing added.\n")); - if (advice_enabled(ADVICE_ADD_EMPTY_PATHSPEC)) - advise( _("Maybe you wanted to say 'git add .'?\n" - "Turn this message off by running\n" - "\"git config advice.addEmptyPathspec false\"")); + advise_if_enabled(ADVICE_ADD_EMPTY_PATHSPEC, + _("Maybe you wanted to say 'git add .'?")); return 0; } @@ -549,12 +549,17 @@ int cmd_add(int argc, const char **argv, const char *prefix) begin_odb_transaction(); + ps_matched = xcalloc(pathspec.nr, 1); if (add_renormalize) exit_status |= renormalize_tracked_files(&pathspec, flags); else exit_status |= add_files_to_cache(the_repository, prefix, - &pathspec, include_sparse, - flags); + &pathspec, ps_matched, + include_sparse, flags); + + if (take_worktree_changes && !add_renormalize && !ignore_add_errors && + report_path_error(ps_matched, &pathspec)) + exit(128); if (add_new_files) exit_status |= add_files(&dir, flags); @@ -568,6 +573,7 @@ finish: COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("unable to write new index file")); + free(ps_matched); dir_clear(&dir); clear_pathspec(&pathspec); return exit_status; diff --git a/builtin/am.c b/builtin/am.c index d1990d7edc..022cae2e8d 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -1150,19 +1150,23 @@ static const char *msgnum(const struct am_state *state) static void NORETURN die_user_resolve(const struct am_state *state) { if (state->resolvemsg) { - printf_ln("%s", state->resolvemsg); + advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s", state->resolvemsg); } else { const char *cmdline = state->interactive ? "git am -i" : "git am"; + struct strbuf sb = STRBUF_INIT; - printf_ln(_("When you have resolved this problem, run \"%s --continue\"."), cmdline); - printf_ln(_("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline); + strbuf_addf(&sb, _("When you have resolved this problem, run \"%s --continue\".\n"), cmdline); + strbuf_addf(&sb, _("If you prefer to skip this patch, run \"%s --skip\" instead.\n"), cmdline); if (advice_enabled(ADVICE_AM_WORK_DIR) && is_empty_or_missing_file(am_path(state, "patch")) && !repo_index_has_changes(the_repository, NULL, NULL)) - printf_ln(_("To record the empty patch as an empty commit, run \"%s --allow-empty\"."), cmdline); + strbuf_addf(&sb, _("To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"), cmdline); - printf_ln(_("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline); + strbuf_addf(&sb, _("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline); + + advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s", sb.buf); + strbuf_release(&sb); } exit(128); @@ -1286,7 +1290,7 @@ static int parse_mail(struct am_state *state, const char *mail) strbuf_addstr(&msg, "\n\n"); strbuf_addbuf(&msg, &mi.log_message); - strbuf_stripspace(&msg, '\0'); + strbuf_stripspace(&msg, NULL); assert(!state->author_name); state->author_name = strbuf_detach(&author_name, NULL); @@ -1994,8 +1998,8 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset) opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0; opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */ opts.fn = twoway_merge; - init_tree_desc(&t[0], head->buffer, head->size); - init_tree_desc(&t[1], remote->buffer, remote->size); + init_tree_desc(&t[0], &head->object.oid, head->buffer, head->size); + init_tree_desc(&t[1], &remote->object.oid, remote->buffer, remote->size); if (unpack_trees(2, t, &opts)) { rollback_lock_file(&lock_file); @@ -2029,7 +2033,7 @@ static int merge_tree(struct tree *tree) opts.dst_index = &the_index; opts.merge = 1; opts.fn = oneway_merge; - init_tree_desc(&t[0], tree->buffer, tree->size); + init_tree_desc(&t[0], &tree->object.oid, tree->buffer, tree->size); if (unpack_trees(1, t, &opts)) { rollback_lock_file(&lock_file); diff --git a/builtin/blame.c b/builtin/blame.c index db1f56de61..9aa74680a3 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -316,7 +316,7 @@ static const char *format_time(timestamp_t time, const char *tz_str, size_t time_width; int tz; tz = atoi(tz_str); - time_str = show_date(time, tz, &blame_date_mode); + time_str = show_date(time, tz, blame_date_mode); strbuf_addstr(&time_buf, time_str); /* * Add space paddings to time_buf to display a fixed width @@ -1029,7 +1029,7 @@ parse_done: blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700"); break; case DATE_STRFTIME: - blame_date_width = strlen(show_date(0, 0, &blame_date_mode)) + 1; /* add the null */ + blame_date_width = strlen(show_date(0, 0, blame_date_mode)) + 1; /* add the null */ break; } blame_date_width -= 1; /* strip the null */ diff --git a/builtin/branch.c b/builtin/branch.c index cfb63cce5f..dd3e3a7dc0 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -158,6 +158,8 @@ static int branch_merged(int kind, const char *name, merged = reference_rev ? repo_in_merge_bases(the_repository, rev, reference_rev) : 0; + if (merged < 0) + exit(128); /* * After the safety valve is fully redefined to "check with @@ -166,9 +168,13 @@ static int branch_merged(int kind, const char *name, * any of the following code, but during the transition period, * a gentle reminder is in order. */ - if ((head_rev != reference_rev) && - (head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0) != merged) { - if (merged) + if (head_rev != reference_rev) { + int expect = head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0; + if (expect < 0) + exit(128); + if (expect == merged) + ; /* okay */ + else if (merged) warning(_("deleting branch '%s' that has been merged to\n" " '%s', but not yet merged to HEAD"), name, reference_name); @@ -576,8 +582,12 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int */ if (ref_exists(oldref.buf)) recovery = 1; - else - die(_("invalid branch name: '%s'"), oldname); + else { + int code = die_message(_("invalid branch name: '%s'"), oldname); + advise_if_enabled(ADVICE_REF_SYNTAX, + _("See `man git check-ref-format`")); + exit(code); + } } for (int i = 0; worktrees[i]; i++) { @@ -667,18 +677,18 @@ static int edit_branch_description(const char *branch_name) exists = !read_branch_desc(&buf, branch_name); if (!buf.len || buf.buf[buf.len-1] != '\n') strbuf_addch(&buf, '\n'); - strbuf_commented_addf(&buf, comment_line_char, + strbuf_commented_addf(&buf, comment_line_str, _("Please edit the description for the branch\n" " %s\n" - "Lines starting with '%c' will be stripped.\n"), - branch_name, comment_line_char); + "Lines starting with '%s' will be stripped.\n"), + branch_name, comment_line_str); write_file_buf(edit_description(), buf.buf, buf.len); strbuf_reset(&buf); if (launch_editor(edit_description(), &buf, NULL)) { strbuf_release(&buf); return -1; } - strbuf_stripspace(&buf, comment_line_char); + strbuf_stripspace(&buf, comment_line_str); strbuf_addf(&name, "branch.%s.description", branch_name); if (buf.len || exists) diff --git a/builtin/bugreport.c b/builtin/bugreport.c index 3106e56a13..25f860a0d9 100644 --- a/builtin/bugreport.c +++ b/builtin/bugreport.c @@ -64,7 +64,8 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit) } static const char * const bugreport_usage[] = { - N_("git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n" + N_("git bugreport [(-o | --output-directory) <path>]\n" + " [(-s | --suffix) <format> | --no-suffix]\n" " [--diagnose[=<mode>]]"), NULL }; @@ -138,8 +139,11 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix) strbuf_complete(&report_path, '/'); output_path_len = report_path.len; - strbuf_addstr(&report_path, "git-bugreport-"); - strbuf_addftime(&report_path, option_suffix, localtime_r(&now, &tm), 0, 0); + strbuf_addstr(&report_path, "git-bugreport"); + if (option_suffix) { + strbuf_addch(&report_path, '-'); + strbuf_addftime(&report_path, option_suffix, localtime_r(&now, &tm), 0, 0); + } strbuf_addstr(&report_path, ".txt"); switch (safe_create_leading_directories(report_path.buf)) { diff --git a/builtin/cat-file.c b/builtin/cat-file.c index bbf851138e..0c948f40fb 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -106,7 +106,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, struct object_info oi = OBJECT_INFO_INIT; struct strbuf sb = STRBUF_INIT; unsigned flags = OBJECT_INFO_LOOKUP_REPLACE; - unsigned get_oid_flags = GET_OID_RECORD_PATH | GET_OID_ONLY_TO_DIE; + unsigned get_oid_flags = + GET_OID_RECORD_PATH | + GET_OID_ONLY_TO_DIE | + GET_OID_HASH_ANY; const char *path = force_path; const int opt_cw = (opt == 'c' || opt == 'w'); if (!path && opt_cw) @@ -226,7 +229,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, die(_("unable to read %s"), oid_to_hex(&oid)); if (!skip_prefix(buffer, "object ", &target) || - get_oid_hex(target, &blob_oid)) + get_oid_hex_algop(target, &blob_oid, + &hash_algos[oid.algo])) die("%s not a valid tag", oid_to_hex(&oid)); free(buffer); } else @@ -310,8 +314,8 @@ static int is_atom(const char *atom, const char *s, int slen) return alen == slen && !memcmp(atom, s, alen); } -static void expand_atom(struct strbuf *sb, const char *atom, int len, - struct expand_data *data) +static int expand_atom(struct strbuf *sb, const char *atom, int len, + struct expand_data *data) { if (is_atom("objectname", atom, len)) { if (!data->mark_query) @@ -343,7 +347,8 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len, strbuf_addstr(sb, oid_to_hex(&data->delta_base_oid)); } else - die("unknown format element: %.*s", len, atom); + return 0; + return 1; } static void expand_format(struct strbuf *sb, const char *start, @@ -354,12 +359,11 @@ static void expand_format(struct strbuf *sb, const char *start, if (skip_prefix(start, "%", &start) || *start != '(') strbuf_addch(sb, '%'); - else if (!(end = strchr(start + 1, ')'))) - die("format element '%s' does not end in ')'", start); - else { - expand_atom(sb, start + 1, end - start - 1, data); + else if ((end = strchr(start + 1, ')')) && + expand_atom(sb, start + 1, end - start - 1, data)) start = end + 1; - } + else + strbuf_expand_bad_format(start, "cat-file"); } } @@ -517,7 +521,9 @@ static void batch_one_object(const char *obj_name, struct expand_data *data) { struct object_context ctx; - int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0; + int flags = + GET_OID_HASH_ANY | + (opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0); enum get_oid_result result; result = get_oid_with_context(the_repository, obj_name, diff --git a/builtin/checkout.c b/builtin/checkout.c index a6e30931b5..71e6036aab 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -91,7 +91,7 @@ struct checkout_opts { int new_branch_log; enum branch_track track; struct diff_options diff_options; - char *conflict_style; + int conflict_style; int branch_exists; const char *prefix; @@ -100,6 +100,8 @@ struct checkout_opts { struct tree *source_tree; }; +#define CHECKOUT_OPTS_INIT { .conflict_style = -1, .merge = -1 } + struct branch_info { char *name; /* The short name used */ char *path; /* The full name of a real branch */ @@ -251,7 +253,8 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos, } static int checkout_merged(int pos, const struct checkout *state, - int *nr_checkouts, struct mem_pool *ce_mem_pool) + int *nr_checkouts, struct mem_pool *ce_mem_pool, + int conflict_style) { struct cache_entry *ce = the_index.cache[pos]; const char *path = ce->name; @@ -262,7 +265,7 @@ static int checkout_merged(int pos, const struct checkout *state, mmbuffer_t result_buf; struct object_id threeway[3]; unsigned mode = 0; - struct ll_merge_options ll_opts; + struct ll_merge_options ll_opts = LL_MERGE_OPTIONS_INIT; int renormalize = 0; memset(threeway, 0, sizeof(threeway)); @@ -284,9 +287,9 @@ static int checkout_merged(int pos, const struct checkout *state, read_mmblob(&ours, &threeway[1]); read_mmblob(&theirs, &threeway[2]); - memset(&ll_opts, 0, sizeof(ll_opts)); git_config_get_bool("merge.renormalize", &renormalize); ll_opts.renormalize = renormalize; + ll_opts.conflict_style = conflict_style; merge_status = ll_merge(&result_buf, path, &ancestor, "base", &ours, "ours", &theirs, "theirs", state->istate, &ll_opts); @@ -417,7 +420,8 @@ static int checkout_worktree(const struct checkout_opts *opts, else if (opts->merge) errs |= checkout_merged(pos, &state, &nr_unmerged, - &ce_mem_pool); + &ce_mem_pool, + opts->conflict_style); pos = skip_same_name(ce, pos) - 1; } } @@ -704,8 +708,9 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o, init_checkout_metadata(&opts.meta, info->refname, info->commit ? &info->commit->object.oid : null_oid(), NULL); - parse_tree(tree); - init_tree_desc(&tree_desc, tree->buffer, tree->size); + if (parse_tree(tree) < 0) + return 128; + init_tree_desc(&tree_desc, &tree->object.oid, tree->buffer, tree->size); switch (unpack_trees(1, &tree_desc, &opts)) { case -2: *writeout_error = 1; @@ -783,9 +788,15 @@ static int merge_working_tree(const struct checkout_opts *opts, if (new_branch_info->commit) BUG("'switch --orphan' should never accept a commit as starting point"); new_tree = parse_tree_indirect(the_hash_algo->empty_tree); - } else + if (!new_tree) + BUG("unable to read empty tree"); + } else { new_tree = repo_get_commit_tree(the_repository, new_branch_info->commit); + if (!new_tree) + return error(_("unable to read tree (%s)"), + oid_to_hex(&new_branch_info->commit->object.oid)); + } if (opts->discard_changes) { ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info); if (ret) @@ -819,10 +830,13 @@ static int merge_working_tree(const struct checkout_opts *opts, die(_("unable to parse commit %s"), oid_to_hex(old_commit_oid)); - init_tree_desc(&trees[0], tree->buffer, tree->size); - parse_tree(new_tree); + init_tree_desc(&trees[0], &tree->object.oid, + tree->buffer, tree->size); + if (parse_tree(new_tree) < 0) + exit(128); tree = new_tree; - init_tree_desc(&trees[1], tree->buffer, tree->size); + init_tree_desc(&trees[1], &tree->object.oid, + tree->buffer, tree->size); ret = unpack_trees(2, trees, &topts); clear_unpack_trees_porcelain(&topts); @@ -868,7 +882,8 @@ static int merge_working_tree(const struct checkout_opts *opts, * entries in the index. */ - add_files_to_cache(the_repository, NULL, NULL, 0, 0); + add_files_to_cache(the_repository, NULL, NULL, NULL, 0, + 0); init_merge_options(&o, the_repository); o.verbosity = 0; work = write_in_core_index_as_tree(the_repository); @@ -887,6 +902,7 @@ static int merge_working_tree(const struct checkout_opts *opts, } o.branch1 = new_branch_info->name; o.branch2 = "local"; + o.conflict_style = opts->conflict_style; ret = merge_trees(&o, new_tree, work, @@ -1020,7 +1036,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts, remove_branch_state(the_repository, !opts->quiet); strbuf_release(&msg); if (!opts->quiet && - (new_branch_info->path || (!opts->force_detach && !strcmp(new_branch_info->name, "HEAD")))) + !opts->force_detach && + (new_branch_info->path || !strcmp(new_branch_info->name, "HEAD"))) report_tracking(new_branch_info); } @@ -1224,7 +1241,9 @@ static void setup_new_branch_info_and_source_tree( struct tree **source_tree = &opts->source_tree; struct object_id branch_rev; - new_branch_info->name = xstrdup(arg); + /* treat '@' as a shortcut for 'HEAD' */ + new_branch_info->name = !strcmp(arg, "@") ? xstrdup("HEAD") : + xstrdup(arg); setup_branch_path(new_branch_info); if (!check_refname_format(new_branch_info->path, 0) && @@ -1238,10 +1257,15 @@ static void setup_new_branch_info_and_source_tree( if (!new_branch_info->commit) { /* not a commit */ *source_tree = parse_tree_indirect(rev); + if (!*source_tree) + die(_("unable to read tree (%s)"), oid_to_hex(rev)); } else { parse_commit_or_die(new_branch_info->commit); *source_tree = repo_get_commit_tree(the_repository, new_branch_info->commit); + if (!*source_tree) + die(_("unable to read tree (%s)"), + oid_to_hex(&new_branch_info->commit->object.oid)); } } @@ -1617,6 +1641,24 @@ static int checkout_branch(struct checkout_opts *opts, return switch_branches(opts, new_branch_info); } +static int parse_opt_conflict(const struct option *o, const char *arg, int unset) +{ + struct checkout_opts *opts = o->value; + + if (unset) { + opts->conflict_style = -1; + return 0; + } + opts->conflict_style = parse_conflict_style_name(arg); + if (opts->conflict_style < 0) + return error(_("unknown conflict style '%s'"), arg); + /* --conflict overrides a previous --no-merge */ + if (!opts->merge) + opts->merge = -1; + + return 0; +} + static struct option *add_common_options(struct checkout_opts *opts, struct option *prevopts) { @@ -1627,8 +1669,9 @@ static struct option *add_common_options(struct checkout_opts *opts, PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater), OPT_BOOL(0, "progress", &opts->show_progress, N_("force progress reporting")), OPT_BOOL('m', "merge", &opts->merge, N_("perform a 3-way merge with the new branch")), - OPT_STRING(0, "conflict", &opts->conflict_style, N_("style"), - N_("conflict style (merge, diff3, or zdiff3)")), + OPT_CALLBACK(0, "conflict", opts, N_("style"), + N_("conflict style (merge, diff3, or zdiff3)"), + parse_opt_conflict), OPT_END() }; struct option *newopts = parse_options_concat(prevopts, options); @@ -1687,10 +1730,11 @@ static char cb_option = 'b'; static int checkout_main(int argc, const char **argv, const char *prefix, struct checkout_opts *opts, struct option *options, - const char * const usagestr[], - struct branch_info *new_branch_info) + const char * const usagestr[]) { int parseopt_flags = 0; + struct branch_info new_branch_info = { 0 }; + int ret; opts->overwrite_ignore = 1; opts->prefix = prefix; @@ -1719,15 +1763,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix, opts->show_progress = isatty(2); } - if (opts->conflict_style) { - struct key_value_info kvi = KVI_INIT; - struct config_context ctx = { - .kvi = &kvi, - }; - opts->merge = 1; /* implied */ - git_xmerge_config("merge.conflictstyle", opts->conflict_style, - &ctx, NULL); - } + /* --conflicts implies --merge */ + if (opts->merge == -1) + opts->merge = opts->conflict_style >= 0; + if (opts->force) { opts->discard_changes = 1; opts->ignore_unmerged_opt = "--force"; @@ -1806,7 +1845,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix, opts->track == BRANCH_TRACK_UNSPECIFIED && !opts->new_branch; int n = parse_branchname_arg(argc, argv, dwim_ok, - new_branch_info, opts, &rev); + &new_branch_info, opts, &rev); argv += n; argc -= n; } else if (!opts->accept_ref && opts->from_treeish) { @@ -1815,7 +1854,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix, if (repo_get_oid_mb(the_repository, opts->from_treeish, &rev)) die(_("could not resolve %s"), opts->from_treeish); - setup_new_branch_info_and_source_tree(new_branch_info, + setup_new_branch_info_and_source_tree(&new_branch_info, opts, &rev, opts->from_treeish); @@ -1835,7 +1874,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix, * Try to give more helpful suggestion. * new_branch && argc > 1 will be caught later. */ - if (opts->new_branch && argc == 1 && !new_branch_info->commit) + if (opts->new_branch && argc == 1 && !new_branch_info.commit) die(_("'%s' is not a commit and a branch '%s' cannot be created from it"), argv[0], opts->new_branch); @@ -1885,14 +1924,21 @@ static int checkout_main(int argc, const char **argv, const char *prefix, } if (opts->patch_mode || opts->pathspec.nr) - return checkout_paths(opts, new_branch_info); + ret = checkout_paths(opts, &new_branch_info); else - return checkout_branch(opts, new_branch_info); + ret = checkout_branch(opts, &new_branch_info); + + branch_info_release(&new_branch_info); + clear_pathspec(&opts->pathspec); + free(opts->pathspec_from_file); + free(options); + + return ret; } int cmd_checkout(int argc, const char **argv, const char *prefix) { - struct checkout_opts opts; + struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options; struct option checkout_options[] = { OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), @@ -1905,10 +1951,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode (default)")), OPT_END() }; - int ret; - struct branch_info new_branch_info = { 0 }; - memset(&opts, 0, sizeof(opts)); opts.dwim_new_local_branch = 1; opts.switch_branch_doing_nothing_is_ok = 1; opts.only_merge_on_switching_branches = 0; @@ -1936,18 +1979,13 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) options = add_common_switch_branch_options(&opts, options); options = add_checkout_path_options(&opts, options); - ret = checkout_main(argc, argv, prefix, &opts, - options, checkout_usage, &new_branch_info); - branch_info_release(&new_branch_info); - clear_pathspec(&opts.pathspec); - free(opts.pathspec_from_file); - FREE_AND_NULL(options); - return ret; + return checkout_main(argc, argv, prefix, &opts, options, + checkout_usage); } int cmd_switch(int argc, const char **argv, const char *prefix) { - struct checkout_opts opts; + struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options = NULL; struct option switch_options[] = { OPT_STRING('c', "create", &opts.new_branch, N_("branch"), @@ -1960,10 +1998,7 @@ int cmd_switch(int argc, const char **argv, const char *prefix) N_("throw away local modifications")), OPT_END() }; - int ret; - struct branch_info new_branch_info = { 0 }; - memset(&opts, 0, sizeof(opts)); opts.dwim_new_local_branch = 1; opts.accept_ref = 1; opts.accept_pathspec = 0; @@ -1980,16 +2015,13 @@ int cmd_switch(int argc, const char **argv, const char *prefix) cb_option = 'c'; - ret = checkout_main(argc, argv, prefix, &opts, - options, switch_branch_usage, &new_branch_info); - branch_info_release(&new_branch_info); - FREE_AND_NULL(options); - return ret; + return checkout_main(argc, argv, prefix, &opts, options, + switch_branch_usage); } int cmd_restore(int argc, const char **argv, const char *prefix) { - struct checkout_opts opts; + struct checkout_opts opts = CHECKOUT_OPTS_INIT; struct option *options; struct option restore_options[] = { OPT_STRING('s', "source", &opts.from_treeish, "<tree-ish>", @@ -2003,10 +2035,7 @@ int cmd_restore(int argc, const char **argv, const char *prefix) OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode")), OPT_END() }; - int ret; - struct branch_info new_branch_info = { 0 }; - memset(&opts, 0, sizeof(opts)); opts.accept_ref = 0; opts.accept_pathspec = 1; opts.empty_pathspec_ok = 0; @@ -2019,9 +2048,6 @@ int cmd_restore(int argc, const char **argv, const char *prefix) options = add_common_options(&opts, options); options = add_checkout_path_options(&opts, options); - ret = checkout_main(argc, argv, prefix, &opts, - options, restore_usage, &new_branch_info); - branch_info_release(&new_branch_info); - FREE_AND_NULL(options); - return ret; + return checkout_main(argc, argv, prefix, &opts, options, + restore_usage); } diff --git a/builtin/clean.c b/builtin/clean.c index d90766cad3..29efe84153 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -25,7 +25,7 @@ #include "help.h" #include "prompt.h" -static int force = -1; /* unset */ +static int require_force = -1; /* unset */ static int interactive; static struct string_list del_list = STRING_LIST_INIT_DUP; static unsigned int colopts; @@ -128,7 +128,7 @@ static int git_clean_config(const char *var, const char *value, } if (!strcmp(var, "clean.requireforce")) { - force = !git_config_bool(var, value); + require_force = git_config_bool(var, value); return 0; } @@ -920,7 +920,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) { int i, res; int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0; - int ignored_only = 0, config_set = 0, errors = 0, gone = 1; + int ignored_only = 0, force = 0, errors = 0, gone = 1; int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT; struct strbuf abs_path = STRBUF_INIT; struct dir_struct dir = DIR_INIT; @@ -946,22 +946,12 @@ int cmd_clean(int argc, const char **argv, const char *prefix) }; git_config(git_clean_config, NULL); - if (force < 0) - force = 0; - else - config_set = 1; argc = parse_options(argc, argv, prefix, options, builtin_clean_usage, 0); - if (!interactive && !dry_run && !force) { - if (config_set) - die(_("clean.requireForce set to true and neither -i, -n, nor -f given; " - "refusing to clean")); - else - die(_("clean.requireForce defaults to true and neither -i, -n, nor -f given;" - " refusing to clean")); - } + if (require_force != 0 && !force && !interactive && !dry_run) + die(_("clean.requireForce is true and -f not given: refusing to clean")); if (force > 1) rm_flags = 0; diff --git a/builtin/clone.c b/builtin/clone.c index bad1b70ce8..74ec14542e 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -116,7 +116,7 @@ static struct option builtin_clone_options[] = { OPT_HIDDEN_BOOL(0, "naked", &option_bare, N_("create a bare repository")), OPT_BOOL(0, "mirror", &option_mirror, - N_("create a mirror repository (implies bare)")), + N_("create a mirror repository (implies --bare)")), OPT_BOOL('l', "local", &option_local, N_("to clone from a local repository")), OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks, @@ -738,8 +738,9 @@ static int checkout(int submodule_progress, int filter_submodules) tree = parse_tree_indirect(&oid); if (!tree) die(_("unable to parse commit %s"), oid_to_hex(&oid)); - parse_tree(tree); - init_tree_desc(&t, tree->buffer, tree->size); + if (parse_tree(tree) < 0) + exit(128); + init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size); if (unpack_trees(1, &t, &opts) < 0) die(_("unable to checkout working tree")); @@ -926,6 +927,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) struct ref *mapped_refs = NULL; const struct ref *ref; struct strbuf key = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT; struct transport *transport = NULL; const char *src_ref_prefix = "refs/heads/"; @@ -1126,6 +1128,50 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } /* + * We have a chicken-and-egg situation between initializing the refdb + * and spawning transport helpers: + * + * - Initializing the refdb requires us to know about the object + * format. We thus have to spawn the transport helper to learn + * about it. + * + * - The transport helper may want to access the Git repository. But + * because the refdb has not been initialized, we don't have "HEAD" + * or "refs/". Thus, the helper cannot find the Git repository. + * + * Ideally, we would have structured the helper protocol such that it's + * mandatory for the helper to first announce its capabilities without + * yet assuming a fully initialized repository. Like that, we could + * have added a "lazy-refdb-init" capability that announces whether the + * helper is ready to handle not-yet-initialized refdbs. If any helper + * didn't support them, we would have fully initialized the refdb with + * the SHA1 object format, but later on bailed out if we found out that + * the remote repository used a different object format. + * + * But we didn't, and thus we use the following workaround to partially + * initialize the repository's refdb such that it can be discovered by + * Git commands. To do so, we: + * + * - Create an invalid HEAD ref pointing at "refs/heads/.invalid". + * + * - Create the "refs/" directory. + * + * - Set up the ref storage format and repository version as + * required. + * + * This is sufficient for Git commands to discover the Git directory. + */ + initialize_repository_version(GIT_HASH_UNKNOWN, + the_repository->ref_storage_format, 1); + + strbuf_addf(&buf, "%s/HEAD", git_dir); + write_file(buf.buf, "ref: refs/heads/.invalid"); + + strbuf_reset(&buf); + strbuf_addf(&buf, "%s/refs", git_dir); + safe_create_dir(buf.buf, 1); + + /* * additional config can be injected with -c, make sure it's included * after init_db, which clears the entire config environment. */ @@ -1453,6 +1499,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) free(remote_name); strbuf_release(&reflog_msg); strbuf_release(&branch_top); + strbuf_release(&buf); strbuf_release(&key); free_refs(mapped_refs); free_refs(remote_head_points_at); diff --git a/builtin/column.c b/builtin/column.c index e80218f81f..10ff7e0166 100644 --- a/builtin/column.c +++ b/builtin/column.c @@ -45,6 +45,8 @@ int cmd_column(int argc, const char **argv, const char *prefix) memset(&copts, 0, sizeof(copts)); copts.padding = 1; argc = parse_options(argc, argv, prefix, options, builtin_column_usage, 0); + if (copts.padding < 0) + die(_("%s must be non-negative"), "--padding"); if (argc) usage_with_options(builtin_column_usage, options); if (real_command || command) { diff --git a/builtin/commit.c b/builtin/commit.c index 6d1fa71676..6e1484446b 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -331,8 +331,9 @@ static void create_base_index(const struct commit *current_head) tree = parse_tree_indirect(¤t_head->object.oid); if (!tree) die(_("failed to unpack HEAD tree object")); - parse_tree(tree); - init_tree_desc(&t, tree->buffer, tree->size); + if (parse_tree(tree) < 0) + exit(128); + init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size); if (unpack_trees(1, &t, &opts)) exit(128); /* We've already reported the error, finish dying */ } @@ -440,16 +441,21 @@ static const char *prepare_index(const char **argv, const char *prefix, * (B) on failure, rollback the real index. */ if (all || (also && pathspec.nr)) { + char *ps_matched = xcalloc(pathspec.nr, 1); repo_hold_locked_index(the_repository, &index_lock, LOCK_DIE_ON_ERROR); add_files_to_cache(the_repository, also ? prefix : NULL, - &pathspec, 0, 0); + &pathspec, ps_matched, 0, 0); + if (!all && report_path_error(ps_matched, &pathspec)) + exit(128); + refresh_cache_or_die(refresh_flags); cache_tree_update(&the_index, WRITE_TREE_SILENT); if (write_locked_index(&the_index, &index_lock, 0)) die(_("unable to write new index file")); commit_style = COMMIT_NORMAL; ret = get_lock_file_path(&index_lock); + free(ps_matched); goto out; } @@ -684,9 +690,10 @@ static void adjust_comment_line_char(const struct strbuf *sb) char *candidate; const char *p; - comment_line_char = candidates[0]; - if (!memchr(sb->buf, comment_line_char, sb->len)) + if (!memchr(sb->buf, candidates[0], sb->len)) { + comment_line_str = xstrfmt("%c", candidates[0]); return; + } p = sb->buf; candidate = strchr(candidates, *p); @@ -705,7 +712,7 @@ 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_char = *p; + comment_line_str = xstrfmt("%c", *p); } static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, @@ -737,7 +744,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix, const char *hook_arg2 = NULL; int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE); int old_display_comment_prefix; - int merge_contains_scissors = 0; int invoked_hook; /* This checks and barfs if author is badly specified */ @@ -841,7 +847,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, wt_status_locate_end(sb.buf + merge_msg_start, sb.len - merge_msg_start) < sb.len - merge_msg_start) - merge_contains_scissors = 1; + s->added_cut_line = 1; } else if (!stat(git_path_squash_msg(the_repository), &statbuf)) { if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0) die_errno(_("could not read SQUASH_MSG")); @@ -889,7 +895,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, s->hints = 0; if (clean_message_contents) - strbuf_stripspace(&sb, '\0'); + strbuf_stripspace(&sb, NULL); if (signoff) append_signoff(&sb, ignored_log_message_bytes(sb.buf, sb.len), 0); @@ -909,24 +915,23 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct ident_split ci, ai; const char *hint_cleanup_all = allow_empty_message ? _("Please enter the commit message for your changes." - " Lines starting\nwith '%c' will be ignored.\n") : + " Lines starting\nwith '%s' will be ignored.\n") : _("Please enter the commit message for your changes." - " Lines starting\nwith '%c' will be ignored, and an empty" + " Lines starting\nwith '%s' will be ignored, and an empty" " message aborts the commit.\n"); const char *hint_cleanup_space = allow_empty_message ? _("Please enter the commit message for your changes." " Lines starting\n" - "with '%c' will be kept; you may remove them" + "with '%s' will be kept; you may remove them" " yourself if you want to.\n") : _("Please enter the commit message for your changes." " Lines starting\n" - "with '%c' will be kept; you may remove them" + "with '%s' will be kept; you may remove them" " yourself if you want to.\n" "An empty message aborts the commit.\n"); if (whence != FROM_COMMIT) { - if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS && - !merge_contains_scissors) - wt_status_add_cut_line(s->fp); + if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) + wt_status_add_cut_line(s); status_printf_ln( s, GIT_COLOR_NORMAL, whence == FROM_MERGE ? @@ -944,12 +949,12 @@ static int prepare_to_commit(const char *index_file, const char *prefix, fprintf(s->fp, "\n"); if (cleanup_mode == COMMIT_MSG_CLEANUP_ALL) - status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_all, comment_line_char); + status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_all, comment_line_str); else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) { - if (whence == FROM_COMMIT && !merge_contains_scissors) - wt_status_add_cut_line(s->fp); + if (whence == FROM_COMMIT) + wt_status_add_cut_line(s); } else /* COMMIT_MSG_CLEANUP_SPACE, that is. */ - status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_space, comment_line_char); + status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_space, comment_line_str); /* * These should never fail because they come from our own @@ -1158,22 +1163,45 @@ static void handle_ignored_arg(struct wt_status *s) die(_("Invalid ignored mode '%s'"), ignored_arg); } -static void handle_untracked_files_arg(struct wt_status *s) +static enum untracked_status_type parse_untracked_setting_name(const char *u) { - if (!untracked_files_arg) - ; /* default already initialized */ - else if (!strcmp(untracked_files_arg, "no")) - s->show_untracked_files = SHOW_NO_UNTRACKED_FILES; - else if (!strcmp(untracked_files_arg, "normal")) - s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; - else if (!strcmp(untracked_files_arg, "all")) - s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES; /* * Please update $__git_untracked_file_modes in * git-completion.bash when you add new options */ + switch (git_parse_maybe_bool(u)) { + case 0: + u = "no"; + break; + case 1: + u = "normal"; + break; + default: + break; + } + + if (!strcmp(u, "no")) + return SHOW_NO_UNTRACKED_FILES; + else if (!strcmp(u, "normal")) + return SHOW_NORMAL_UNTRACKED_FILES; + else if (!strcmp(u, "all")) + return SHOW_ALL_UNTRACKED_FILES; else - die(_("Invalid untracked files mode '%s'"), untracked_files_arg); + return SHOW_UNTRACKED_FILES_ERROR; +} + +static void handle_untracked_files_arg(struct wt_status *s) +{ + enum untracked_status_type u; + + if (!untracked_files_arg) + return; /* default already initialized */ + + u = parse_untracked_setting_name(untracked_files_arg); + if (u == SHOW_UNTRACKED_FILES_ERROR) + die(_("Invalid untracked files mode '%s'"), + untracked_files_arg); + s->show_untracked_files = u; } static const char *read_commit_message(const char *name) @@ -1456,16 +1484,12 @@ static int git_status_config(const char *k, const char *v, return 0; } if (!strcmp(k, "status.showuntrackedfiles")) { - if (!v) - return config_error_nonbool(k); - else if (!strcmp(v, "no")) - s->show_untracked_files = SHOW_NO_UNTRACKED_FILES; - else if (!strcmp(v, "normal")) - s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; - else if (!strcmp(v, "all")) - s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES; - else + enum untracked_status_type u; + + u = parse_untracked_setting_name(v); + if (u == SHOW_UNTRACKED_FILES_ERROR) return error(_("Invalid untracked files mode '%s'"), v); + s->show_untracked_files = u; return 0; } if (!strcmp(k, "diff.renamelimit")) { diff --git a/builtin/config.c b/builtin/config.c index b55bfae7d6..0015620dde 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -44,6 +44,7 @@ static struct config_options config_options; static int show_origin; static int show_scope; static int fixed_value; +static const char *comment; #define ACTION_GET (1<<0) #define ACTION_GET_ALL (1<<1) @@ -173,6 +174,7 @@ static struct option builtin_config_options[] = { OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")), OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")), OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")), + OPT_STRING(0, "comment", &comment, N_("value"), N_("human-readable comment string (# will be prepended as needed)")), OPT_END(), }; @@ -797,6 +799,12 @@ int cmd_config(int argc, const char **argv, const char *prefix) usage_builtin_config(); } + if (comment && + !(actions & (ACTION_ADD|ACTION_SET|ACTION_SET_ALL|ACTION_REPLACE_ALL))) { + error(_("--comment is only applicable to add/set/replace operations")); + usage_builtin_config(); + } + /* check usage of --fixed-value */ if (fixed_value) { int allowed_usage = 0; @@ -833,6 +841,8 @@ int cmd_config(int argc, const char **argv, const char *prefix) flags |= CONFIG_FLAGS_FIXED_VALUE; } + comment = git_config_prepare_comment_string(comment); + if (actions & PAGING_ACTIONS) setup_auto_pager("config", 1); @@ -880,7 +890,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) check_write(); check_argc(argc, 2, 2); value = normalize_value(argv[0], argv[1], &default_kvi); - ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value); + ret = git_config_set_in_file_gently(given_config_source.file, argv[0], comment, value); if (ret == CONFIG_NOTHING_SET) error(_("cannot overwrite multiple values with a single value\n" " Use a regexp, --add or --replace-all to change %s."), argv[0]); @@ -891,7 +901,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, argv[2], - flags); + comment, flags); } else if (actions == ACTION_ADD) { check_write(); @@ -900,7 +910,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, CONFIG_REGEX_NONE, - flags); + comment, flags); } else if (actions == ACTION_REPLACE_ALL) { check_write(); @@ -908,7 +918,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) value = normalize_value(argv[0], argv[1], &default_kvi); ret = git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], value, argv[2], - flags | CONFIG_FLAGS_MULTI_REPLACE); + comment, flags | CONFIG_FLAGS_MULTI_REPLACE); } else if (actions == ACTION_GET) { check_argc(argc, 1, 2); @@ -936,17 +946,17 @@ int cmd_config(int argc, const char **argv, const char *prefix) if (argc == 2) return git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], NULL, argv[1], - flags); + NULL, flags); else return git_config_set_in_file_gently(given_config_source.file, - argv[0], NULL); + argv[0], NULL, NULL); } else if (actions == ACTION_UNSET_ALL) { check_write(); check_argc(argc, 1, 2); return git_config_set_multivar_in_file_gently(given_config_source.file, argv[0], NULL, argv[1], - flags | CONFIG_FLAGS_MULTI_REPLACE); + NULL, flags | CONFIG_FLAGS_MULTI_REPLACE); } else if (actions == ACTION_RENAME_SECTION) { check_write(); diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c index 3a6a750a8e..17f929dede 100644 --- a/builtin/credential-cache--daemon.c +++ b/builtin/credential-cache--daemon.c @@ -294,6 +294,8 @@ int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, usage, 0); socket_path = argv[0]; + if (!have_unix_sockets()) + die(_("credential-cache--daemon unavailable; no unix socket support")); if (!socket_path) usage_with_options(usage, options); diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c index bba96d4ffd..bef120b537 100644 --- a/builtin/credential-cache.c +++ b/builtin/credential-cache.c @@ -149,6 +149,9 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix) usage_with_options(usage, options); op = argv[0]; + if (!have_unix_sockets()) + die(_("credential-cache unavailable; no unix socket support")); + if (!socket_path) socket_path = get_socket_path(); if (!socket_path) diff --git a/builtin/fast-export.c b/builtin/fast-export.c index f18f0809f9..4693d18cc9 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -136,8 +136,7 @@ static int anonymized_entry_cmp(const void *cmp_data UNUSED, a = container_of(eptr, const struct anonymized_entry, hash); if (keydata) { const struct anonymized_entry_key *key = keydata; - int equal = !strncmp(a->orig, key->orig, key->orig_len) && - !a->orig[key->orig_len]; + int equal = !xstrncmpz(a->orig, key->orig, key->orig_len); return !equal; } diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 92eda20683..dc5a9d32dd 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -1236,20 +1236,6 @@ static void *gfi_unpack_entry( return unpack_entry(the_repository, p, oe->idx.offset, &type, sizep); } -static const char *get_mode(const char *str, uint16_t *modep) -{ - unsigned char c; - uint16_t mode = 0; - - while ((c = *str++) != ' ') { - if (c < '0' || c > '7') - return NULL; - mode = (mode << 3) + (c - '0'); - } - *modep = mode; - return str; -} - static void load_tree(struct tree_entry *root) { struct object_id *oid = &root->versions[1].oid; @@ -1287,7 +1273,7 @@ static void load_tree(struct tree_entry *root) t->entries[t->entry_count++] = e; e->tree = NULL; - c = get_mode(c, &e->versions[1].mode); + c = parse_mode(c, &e->versions[1].mode); if (!c) die("Corrupt mode in %s", oid_to_hex(oid)); e->versions[0].mode = e->versions[1].mode; @@ -1625,6 +1611,7 @@ static int update_branch(struct branch *b) oidclr(&old_oid); if (!force_update && !is_null_oid(&old_oid)) { struct commit *old_cmit, *new_cmit; + int ret; old_cmit = lookup_commit_reference_gently(the_repository, &old_oid, 0); @@ -1633,7 +1620,10 @@ static int update_branch(struct branch *b) if (!old_cmit || !new_cmit) return error("Branch %s is missing commits.", b->name); - if (!repo_in_merge_bases(the_repository, old_cmit, new_cmit)) { + ret = repo_in_merge_bases(the_repository, old_cmit, new_cmit); + if (ret < 0) + exit(128); + if (!ret) { warning("Not updating %s" " (new tip %s does not contain %s)", b->name, oid_to_hex(&b->oid), @@ -2220,7 +2210,7 @@ static int parse_mapped_oid_hex(const char *hex, struct object_id *oid, const ch * * idnum ::= ':' bigint; * - * Return the first character after the value in *endptr. + * Update *endptr to point to the first character after the value. * * Complain if the following character is not what is expected, * either a space or end of the string. @@ -2253,8 +2243,8 @@ static uintmax_t parse_mark_ref_eol(const char *p) } /* - * Parse the mark reference, demanding a trailing space. Return a - * pointer to the space. + * Parse the mark reference, demanding a trailing space. Update *p to + * point to the first character after the space. */ static uintmax_t parse_mark_ref_space(const char **p) { @@ -2268,15 +2258,67 @@ static uintmax_t parse_mark_ref_space(const char **p) return mark; } +/* + * Parse the path string into the strbuf. The path can either be quoted with + * escape sequences or unquoted without escape sequences. Unquoted strings may + * contain spaces only if `is_last_field` is nonzero; otherwise, it stops + * parsing at the first space. + */ +static void parse_path(struct strbuf *sb, const char *p, const char **endp, + int is_last_field, const char *field) +{ + if (*p == '"') { + if (unquote_c_style(sb, p, endp)) + die("Invalid %s: %s", field, command_buf.buf); + if (strlen(sb->buf) != sb->len) + die("NUL in %s: %s", field, command_buf.buf); + } else { + /* + * Unless we are parsing the last field of a line, + * SP is the end of this field. + */ + *endp = is_last_field + ? p + strlen(p) + : strchrnul(p, ' '); + strbuf_add(sb, p, *endp - p); + } +} + +/* + * Parse the path string into the strbuf, and complain if this is not the end of + * the string. Unquoted strings may contain spaces. + */ +static void parse_path_eol(struct strbuf *sb, const char *p, const char *field) +{ + const char *end; + + parse_path(sb, p, &end, 1, field); + if (*end) + die("Garbage after %s: %s", field, command_buf.buf); +} + +/* + * Parse the path string into the strbuf, and ensure it is followed by a space. + * Unquoted strings may not contain spaces. Update *endp to point to the first + * character after the space. + */ +static void parse_path_space(struct strbuf *sb, const char *p, + const char **endp, const char *field) +{ + parse_path(sb, p, endp, 0, field); + if (**endp != ' ') + die("Missing space after %s: %s", field, command_buf.buf); + (*endp)++; +} + static void file_change_m(const char *p, struct branch *b) { - static struct strbuf uq = STRBUF_INIT; - const char *endp; + static struct strbuf path = STRBUF_INIT; struct object_entry *oe; struct object_id oid; uint16_t mode, inline_data = 0; - p = get_mode(p, &mode); + p = parse_mode(p, &mode); if (!p) die("Corrupt mode: %s", command_buf.buf); switch (mode) { @@ -2308,16 +2350,12 @@ static void file_change_m(const char *p, struct branch *b) die("Missing space after SHA1: %s", command_buf.buf); } - strbuf_reset(&uq); - if (!unquote_c_style(&uq, p, &endp)) { - if (*endp) - die("Garbage after path in: %s", command_buf.buf); - p = uq.buf; - } + strbuf_reset(&path); + parse_path_eol(&path, p, "path"); /* Git does not track empty, non-toplevel directories. */ - if (S_ISDIR(mode) && is_empty_tree_oid(&oid) && *p) { - tree_content_remove(&b->branch_tree, p, NULL, 0); + if (S_ISDIR(mode) && is_empty_tree_oid(&oid) && *path.buf) { + tree_content_remove(&b->branch_tree, path.buf, NULL, 0); return; } @@ -2338,10 +2376,6 @@ static void file_change_m(const char *p, struct branch *b) if (S_ISDIR(mode)) die("Directories cannot be specified 'inline': %s", command_buf.buf); - if (p != uq.buf) { - strbuf_addstr(&uq, p); - p = uq.buf; - } while (read_next_command() != EOF) { const char *v; if (skip_prefix(command_buf.buf, "cat-blob ", &v)) @@ -2367,74 +2401,48 @@ static void file_change_m(const char *p, struct branch *b) command_buf.buf); } - if (!*p) { + if (!*path.buf) { tree_content_replace(&b->branch_tree, &oid, mode, NULL); return; } - tree_content_set(&b->branch_tree, p, &oid, mode, NULL); + tree_content_set(&b->branch_tree, path.buf, &oid, mode, NULL); } static void file_change_d(const char *p, struct branch *b) { - static struct strbuf uq = STRBUF_INIT; - const char *endp; + static struct strbuf path = STRBUF_INIT; - strbuf_reset(&uq); - if (!unquote_c_style(&uq, p, &endp)) { - if (*endp) - die("Garbage after path in: %s", command_buf.buf); - p = uq.buf; - } - tree_content_remove(&b->branch_tree, p, NULL, 1); + strbuf_reset(&path); + parse_path_eol(&path, p, "path"); + tree_content_remove(&b->branch_tree, path.buf, NULL, 1); } -static void file_change_cr(const char *s, struct branch *b, int rename) +static void file_change_cr(const char *p, struct branch *b, int rename) { - const char *d; - static struct strbuf s_uq = STRBUF_INIT; - static struct strbuf d_uq = STRBUF_INIT; - const char *endp; + static struct strbuf source = STRBUF_INIT; + static struct strbuf dest = STRBUF_INIT; struct tree_entry leaf; - strbuf_reset(&s_uq); - if (!unquote_c_style(&s_uq, s, &endp)) { - if (*endp != ' ') - die("Missing space after source: %s", command_buf.buf); - } else { - endp = strchr(s, ' '); - if (!endp) - die("Missing space after source: %s", command_buf.buf); - strbuf_add(&s_uq, s, endp - s); - } - s = s_uq.buf; - - endp++; - if (!*endp) - die("Missing dest: %s", command_buf.buf); - - d = endp; - strbuf_reset(&d_uq); - if (!unquote_c_style(&d_uq, d, &endp)) { - if (*endp) - die("Garbage after dest in: %s", command_buf.buf); - d = d_uq.buf; - } + strbuf_reset(&source); + parse_path_space(&source, p, &p, "source"); + strbuf_reset(&dest); + parse_path_eol(&dest, p, "dest"); memset(&leaf, 0, sizeof(leaf)); if (rename) - tree_content_remove(&b->branch_tree, s, &leaf, 1); + tree_content_remove(&b->branch_tree, source.buf, &leaf, 1); else - tree_content_get(&b->branch_tree, s, &leaf, 1); + tree_content_get(&b->branch_tree, source.buf, &leaf, 1); if (!leaf.versions[1].mode) - die("Path %s not in branch", s); - if (!*d) { /* C "path/to/subdir" "" */ + die("Path %s not in branch", source.buf); + if (!*dest.buf) { /* C "path/to/subdir" "" */ tree_content_replace(&b->branch_tree, &leaf.versions[1].oid, leaf.versions[1].mode, leaf.tree); return; } - tree_content_set(&b->branch_tree, d, + tree_content_set(&b->branch_tree, dest.buf, &leaf.versions[1].oid, leaf.versions[1].mode, leaf.tree); @@ -2442,7 +2450,6 @@ static void file_change_cr(const char *s, struct branch *b, int rename) static void note_change_n(const char *p, struct branch *b, unsigned char *old_fanout) { - static struct strbuf uq = STRBUF_INIT; struct object_entry *oe; struct branch *s; struct object_id oid, commit_oid; @@ -2507,10 +2514,6 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa die("Invalid ref name or SHA1 expression: %s", p); if (inline_data) { - if (p != uq.buf) { - strbuf_addstr(&uq, p); - p = uq.buf; - } read_next_command(); parse_and_store_blob(&last_blob, &oid, 0); } else if (oe) { @@ -3162,6 +3165,7 @@ static void print_ls(int mode, const unsigned char *hash, const char *path) static void parse_ls(const char *p, struct branch *b) { + static struct strbuf path = STRBUF_INIT; struct tree_entry *root = NULL; struct tree_entry leaf = {NULL}; @@ -3178,17 +3182,9 @@ static void parse_ls(const char *p, struct branch *b) root->versions[1].mode = S_IFDIR; load_tree(root); } - if (*p == '"') { - static struct strbuf uq = STRBUF_INIT; - const char *endp; - strbuf_reset(&uq); - if (unquote_c_style(&uq, p, &endp)) - die("Invalid path: %s", command_buf.buf); - if (*endp) - die("Garbage after path in: %s", command_buf.buf); - p = uq.buf; - } - tree_content_get(root, p, &leaf, 1); + strbuf_reset(&path); + parse_path_eol(&path, p, "path"); + tree_content_get(root, path.buf, &leaf, 1); /* * A directory in preparation would have a sha1 of zero * until it is saved. Save, for simplicity. @@ -3196,7 +3192,7 @@ static void parse_ls(const char *p, struct branch *b) if (S_ISDIR(leaf.versions[1].mode)) store_tree(&leaf); - print_ls(leaf.versions[1].mode, leaf.versions[1].oid.hash, p); + print_ls(leaf.versions[1].mode, leaf.versions[1].oid.hash, path.buf); if (leaf.tree) release_tree_content_recursive(leaf.tree); if (!b || root != &b->branch_tree) diff --git a/builtin/fetch.c b/builtin/fetch.c index 3aedfd1bb6..5857d860db 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -138,6 +138,7 @@ static int git_fetch_config(const char *k, const char *v, int r = git_config_bool(k, v) ? RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF; fetch_config->recurse_submodules = r; + return 0; } if (!strcmp(k, "submodule.fetchjobs")) { @@ -448,9 +449,8 @@ static void filter_prefetch_refspec(struct refspec *rs) continue; if (!rs->items[i].dst || (rs->items[i].src && - !strncmp(rs->items[i].src, - ref_namespace[NAMESPACE_TAGS].ref, - strlen(ref_namespace[NAMESPACE_TAGS].ref)))) { + starts_with(rs->items[i].src, + ref_namespace[NAMESPACE_TAGS].ref))) { int j; free(rs->items[i].src); @@ -982,6 +982,8 @@ static int update_local_ref(struct ref *ref, uint64_t t_before = getnanotime(); fast_forward = repo_in_merge_bases(the_repository, current, updated); + if (fast_forward < 0) + exit(128); forced_updates_ms += (getnanotime() - t_before) / 1000000; } else { fast_forward = 1; diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 3885a9c28e..919282e12a 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -20,10 +20,10 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; - int icase = 0; + int icase = 0, include_root_refs = 0, from_stdin = 0; struct ref_filter filter = REF_FILTER_INIT; struct ref_format format = REF_FORMAT_INIT; - int from_stdin = 0; + unsigned int flags = FILTER_REFS_REGULAR; struct strvec vec = STRVEC_INIT; struct option opts[] = { @@ -53,6 +53,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")), OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")), OPT_BOOL(0, "stdin", &from_stdin, N_("read reference patterns from stdin")), + OPT_BOOL(0, "include-root-refs", &include_root_refs, N_("also include HEAD ref and pseudorefs")), OPT_END(), }; @@ -96,8 +97,11 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) filter.name_patterns = argv; } + if (include_root_refs) + flags |= FILTER_REFS_ROOT_REFS; + filter.match_as_path = 1; - filter_and_format_refs(&filter, FILTER_REFS_ALL, sorting, &format); + filter_and_format_refs(&filter, flags, sorting, &format); ref_filter_clear(&filter); ref_sorting_release(sorting); diff --git a/builtin/fsck.c b/builtin/fsck.c index a7cf94f67e..f892487c9b 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -509,9 +509,7 @@ static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid return 0; } -static int fsck_handle_reflog(const char *logname, - const struct object_id *oid UNUSED, - int flag UNUSED, void *cb_data) +static int fsck_handle_reflog(const char *logname, void *cb_data) { struct strbuf refname = STRBUF_INIT; diff --git a/builtin/gc.c b/builtin/gc.c index cb80ced6cb..d187cec1ea 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -180,13 +180,51 @@ static void gc_config(void) git_config(git_default_config, NULL); } -struct maintenance_run_opts; +enum schedule_priority { + SCHEDULE_NONE = 0, + SCHEDULE_WEEKLY = 1, + SCHEDULE_DAILY = 2, + SCHEDULE_HOURLY = 3, +}; + +static enum schedule_priority parse_schedule(const char *value) +{ + if (!value) + return SCHEDULE_NONE; + if (!strcasecmp(value, "hourly")) + return SCHEDULE_HOURLY; + if (!strcasecmp(value, "daily")) + return SCHEDULE_DAILY; + if (!strcasecmp(value, "weekly")) + return SCHEDULE_WEEKLY; + return SCHEDULE_NONE; +} + +struct maintenance_run_opts { + int auto_flag; + int quiet; + enum schedule_priority schedule; +}; + +static int pack_refs_condition(void) +{ + /* + * The auto-repacking logic for refs is handled by the ref backends and + * exposed via `git pack-refs --auto`. We thus always return truish + * here and let the backend decide for us. + */ + return 1; +} + static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts) { struct child_process cmd = CHILD_PROCESS_INIT; cmd.git_cmd = 1; strvec_pushl(&cmd.args, "pack-refs", "--all", "--prune", NULL); + if (opts->auto_flag) + strvec_push(&cmd.args, "--auto"); + return run_command(&cmd); } @@ -547,7 +585,7 @@ done: return ret; } -static void gc_before_repack(void) +static void gc_before_repack(struct maintenance_run_opts *opts) { /* * We may be called twice, as both the pre- and @@ -558,7 +596,7 @@ static void gc_before_repack(void) if (done++) return; - if (pack_refs && maintenance_task_pack_refs(NULL)) + if (pack_refs && maintenance_task_pack_refs(opts)) die(FAILED_RUN, "pack-refs"); if (prune_reflogs) { @@ -574,7 +612,6 @@ static void gc_before_repack(void) int cmd_gc(int argc, const char **argv, const char *prefix) { int aggressive = 0; - int auto_gc = 0; int quiet = 0; int force = 0; const char *name; @@ -583,6 +620,7 @@ 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 option builtin_gc_options[] = { OPT__QUIET(&quiet, N_("suppress progress reporting")), @@ -593,7 +631,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) OPT_MAGNITUDE(0, "max-cruft-size", &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", &auto_gc, N_("enable auto-gc mode"), + OPT_BOOL_F(0, "auto", &opts.auto_flag, N_("enable auto-gc mode"), PARSE_OPT_NOCOMPLETE), OPT_BOOL_F(0, "force", &force, N_("force running gc even if there may be another gc running"), @@ -638,7 +676,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (quiet) strvec_push(&repack, "-q"); - if (auto_gc) { + if (opts.auto_flag) { /* * Auto-gc should be least intrusive as possible. */ @@ -663,7 +701,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (lock_repo_for_gc(force, &pid)) return 0; - gc_before_repack(); /* dies on failure */ + gc_before_repack(&opts); /* dies on failure */ delete_tempfile(&pidfile); /* @@ -688,7 +726,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) name = lock_repo_for_gc(force, &pid); if (name) { - if (auto_gc) + if (opts.auto_flag) return 0; /* be quiet on --auto */ die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"), name, (uintmax_t)pid); @@ -703,7 +741,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) atexit(process_log_file_at_exit); } - gc_before_repack(); + gc_before_repack(&opts); if (!repository_format_precious_objects) { struct child_process repack_cmd = CHILD_PROCESS_INIT; @@ -758,7 +796,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0, NULL); - if (auto_gc && too_many_loose_objects()) + if (opts.auto_flag && too_many_loose_objects()) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); @@ -773,26 +811,6 @@ static const char *const builtin_maintenance_run_usage[] = { NULL }; -enum schedule_priority { - SCHEDULE_NONE = 0, - SCHEDULE_WEEKLY = 1, - SCHEDULE_DAILY = 2, - SCHEDULE_HOURLY = 3, -}; - -static enum schedule_priority parse_schedule(const char *value) -{ - if (!value) - return SCHEDULE_NONE; - if (!strcasecmp(value, "hourly")) - return SCHEDULE_HOURLY; - if (!strcasecmp(value, "daily")) - return SCHEDULE_DAILY; - if (!strcasecmp(value, "weekly")) - return SCHEDULE_WEEKLY; - return SCHEDULE_NONE; -} - static int maintenance_opt_schedule(const struct option *opt, const char *arg, int unset) { @@ -809,12 +827,6 @@ static int maintenance_opt_schedule(const struct option *opt, const char *arg, return 0; } -struct maintenance_run_opts { - int auto_flag; - int quiet; - enum schedule_priority schedule; -}; - /* Remember to update object flag allocation in object.h */ #define SEEN (1u<<0) @@ -1296,7 +1308,7 @@ static struct maintenance_task tasks[] = { [TASK_PACK_REFS] = { "pack-refs", maintenance_task_pack_refs, - NULL, + pack_refs_condition, }, }; @@ -1553,7 +1565,7 @@ static int maintenance_register(int argc, const char **argv, const char *prefix) die(_("$HOME not set")); rc = git_config_set_multivar_in_file_gently( config_file, "maintenance.repo", maintpath, - CONFIG_REGEX_NONE, 0); + CONFIG_REGEX_NONE, NULL, 0); free(global_config_file); if (rc) @@ -1620,7 +1632,7 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi if (!config_file) die(_("$HOME not set")); rc = git_config_set_multivar_in_file_gently( - config_file, key, NULL, maintpath, + config_file, key, NULL, maintpath, NULL, CONFIG_FLAGS_MULTI_REPLACE | CONFIG_FLAGS_FIXED_VALUE); free(global_config_file); diff --git a/builtin/grep.c b/builtin/grep.c index 982bcfc4b1..5777ba82a9 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -527,7 +527,7 @@ static int grep_submodule(struct grep_opt *opt, strbuf_addstr(&base, filename); strbuf_addch(&base, '/'); - init_tree_desc(&tree, data, size); + init_tree_desc(&tree, oid, data, size); hit = grep_tree(&subopt, pathspec, &tree, &base, base.len, object_type == OBJ_COMMIT); strbuf_release(&base); @@ -573,7 +573,7 @@ static int grep_cache(struct grep_opt *opt, &type, &size); if (!data) die(_("unable to read tree %s"), oid_to_hex(&ce->oid)); - init_tree_desc(&tree, data, size); + init_tree_desc(&tree, &ce->oid, data, size); hit |= grep_tree(opt, pathspec, &tree, &name, 0, 0); strbuf_setlen(&name, name_base_len); @@ -669,7 +669,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, oid_to_hex(&entry.oid)); strbuf_addch(base, '/'); - init_tree_desc(&sub, data, size); + init_tree_desc(&sub, &entry.oid, data, size); hit |= grep_tree(opt, pathspec, &sub, base, tn_len, check_attr); free(data); @@ -713,7 +713,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, strbuf_add(&base, name, len); strbuf_addch(&base, ':'); } - init_tree_desc(&tree, data, size); + init_tree_desc(&tree, &obj->oid, data, size); hit = grep_tree(opt, pathspec, &tree, &base, base.len, obj->type == OBJ_COMMIT); strbuf_release(&base); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index a3a37bd215..856428fef9 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1524,14 +1524,12 @@ static void final(const char *final_pack_name, const char *curr_pack_name, struct strbuf pack_name = STRBUF_INIT; struct strbuf index_name = STRBUF_INIT; struct strbuf rev_index_name = STRBUF_INIT; - int err; if (!from_stdin) { close(input_fd); } else { fsync_component_or_die(FSYNC_COMPONENT_PACK, output_fd, curr_pack_name); - err = close(output_fd); - if (err) + if (close(output_fd)) die_errno(_("error while closing pack file")); } @@ -1566,17 +1564,8 @@ static void final(const char *final_pack_name, const char *curr_pack_name, write_or_die(1, buf.buf, buf.len); strbuf_release(&buf); - /* - * Let's just mimic git-unpack-objects here and write - * the last part of the input buffer to stdout. - */ - while (input_len) { - err = xwrite(1, input_buffer + input_offset, input_len); - if (err <= 0) - break; - input_len -= err; - input_offset += err; - } + /* Write the last part of the buffer to stdout */ + write_in_full(1, input_buffer + input_offset, input_len); } strbuf_release(&rev_index_name); diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c index 033bd1556c..8768bfea3c 100644 --- a/builtin/interpret-trailers.c +++ b/builtin/interpret-trailers.c @@ -9,12 +9,13 @@ #include "gettext.h" #include "parse-options.h" #include "string-list.h" +#include "tempfile.h" #include "trailer.h" #include "config.h" static const char * const git_interpret_trailers_usage[] = { N_("git interpret-trailers [--in-place] [--trim-empty]\n" - " [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n" + " [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n" " [--parse] [<file>...]"), NULL }; @@ -91,6 +92,102 @@ static int parse_opt_parse(const struct option *opt, const char *arg, return 0; } +static struct tempfile *trailers_tempfile; + +static FILE *create_in_place_tempfile(const char *file) +{ + struct stat st; + struct strbuf filename_template = STRBUF_INIT; + const char *tail; + FILE *outfile; + + if (stat(file, &st)) + die_errno(_("could not stat %s"), file); + if (!S_ISREG(st.st_mode)) + die(_("file %s is not a regular file"), file); + if (!(st.st_mode & S_IWUSR)) + die(_("file %s is not writable by user"), file); + + /* Create temporary file in the same directory as the original */ + tail = strrchr(file, '/'); + if (tail) + strbuf_add(&filename_template, file, tail - file + 1); + strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX"); + + trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode); + strbuf_release(&filename_template); + outfile = fdopen_tempfile(trailers_tempfile, "w"); + if (!outfile) + die_errno(_("could not open temporary file")); + + return outfile; +} + +static void read_input_file(struct strbuf *sb, const char *file) +{ + if (file) { + if (strbuf_read_file(sb, file, 0) < 0) + die_errno(_("could not read input file '%s'"), file); + } else { + if (strbuf_read(sb, fileno(stdin), 0) < 0) + die_errno(_("could not read from stdin")); + } +} + +static void interpret_trailers(const struct process_trailer_options *opts, + struct list_head *new_trailer_head, + const char *file) +{ + LIST_HEAD(head); + struct strbuf sb = STRBUF_INIT; + struct strbuf trailer_block = STRBUF_INIT; + struct trailer_info info; + FILE *outfile = stdout; + + trailer_config_init(); + + read_input_file(&sb, file); + + if (opts->in_place) + outfile = create_in_place_tempfile(file); + + parse_trailers(opts, &info, sb.buf, &head); + + /* Print the lines before the trailers */ + if (!opts->only_trailers) + fwrite(sb.buf, 1, info.trailer_block_start, outfile); + + if (!opts->only_trailers && !info.blank_line_before_trailer) + fprintf(outfile, "\n"); + + + if (!opts->only_input) { + LIST_HEAD(config_head); + LIST_HEAD(arg_head); + parse_trailers_from_config(&config_head); + parse_trailers_from_command_line_args(&arg_head, new_trailer_head); + list_splice(&config_head, &arg_head); + process_trailers_lists(&head, &arg_head); + } + + /* Print trailer block. */ + format_trailers(opts, &head, &trailer_block); + free_trailers(&head); + fwrite(trailer_block.buf, 1, trailer_block.len, outfile); + strbuf_release(&trailer_block); + + /* Print the lines after the trailers as is */ + if (!opts->only_trailers) + fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile); + trailer_info_release(&info); + + if (opts->in_place) + if (rename_tempfile(&trailers_tempfile, file)) + die_errno(_("could not rename temporary file to %s"), file); + + strbuf_release(&sb); +} + int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; @@ -132,11 +229,11 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix) if (argc) { int i; for (i = 0; i < argc; i++) - process_trailers(argv[i], &opts, &trailers); + interpret_trailers(&opts, &trailers, argv[i]); } else { if (opts.in_place) die(_("no input file given for in-place editing")); - process_trailers(NULL, &opts, &trailers); + interpret_trailers(&opts, &trailers, NULL); } new_trailers_clear(&trailers); diff --git a/builtin/log.c b/builtin/log.c index db1808d7c1..c0a8bb95e9 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1297,7 +1297,7 @@ static void prepare_cover_text(struct pretty_print_context *pp, subject = subject_sb.buf; do_pp: - pp_title_line(pp, &subject, sb, encoding, need_8bit_cte); + pp_email_subject(pp, &subject, sb, encoding, need_8bit_cte); pp_remainder(pp, &body, sb, 0); strbuf_release(&description_sb); @@ -1364,13 +1364,13 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file, pp.fmt = CMIT_FMT_EMAIL; pp.date_mode.type = DATE_RFC2822; pp.rev = rev; - pp.print_email_subject = 1; pp.encode_email_headers = rev->encode_email_headers; pp_user_info(&pp, NULL, &sb, committer, encoding); prepare_cover_text(&pp, description_file, branch_name, &sb, encoding, need_8bit_cte); fprintf(rev->diffopt.file, "%s\n", sb.buf); + free(pp.after_subject); strbuf_release(&sb); shortlog_init(&log); @@ -1625,7 +1625,7 @@ static struct commit *get_base_commit(const char *base_commit, { struct commit *base = NULL; struct commit **rev; - int i = 0, rev_nr = 0, auto_select, die_on_failure; + int i = 0, rev_nr = 0, auto_select, die_on_failure, ret; switch (auto_base) { case AUTO_BASE_NEVER: @@ -1658,7 +1658,7 @@ static struct commit *get_base_commit(const char *base_commit, struct branch *curr_branch = branch_get(NULL); const char *upstream = branch_get_upstream(curr_branch, NULL); if (upstream) { - struct commit_list *base_list; + struct commit_list *base_list = NULL; struct commit *commit; struct object_id oid; @@ -1669,11 +1669,12 @@ static struct commit *get_base_commit(const char *base_commit, return NULL; } commit = lookup_commit_or_die(&oid, "upstream base"); - base_list = repo_get_merge_bases_many(the_repository, - commit, total, - list); - /* There should be one and only one merge base. */ - if (!base_list || base_list->next) { + if (repo_get_merge_bases_many(the_repository, + commit, total, + list, + &base_list) < 0 || + /* There should be one and only one merge base. */ + !base_list || base_list->next) { if (die_on_failure) { die(_("could not find exact merge base")); } else { @@ -1704,11 +1705,11 @@ static struct commit *get_base_commit(const char *base_commit, */ while (rev_nr > 1) { for (i = 0; i < rev_nr / 2; i++) { - struct commit_list *merge_base; - merge_base = repo_get_merge_bases(the_repository, - rev[2 * i], - rev[2 * i + 1]); - if (!merge_base || merge_base->next) { + struct commit_list *merge_base = NULL; + if (repo_get_merge_bases(the_repository, + rev[2 * i], + rev[2 * i + 1], &merge_base) < 0 || + !merge_base || merge_base->next) { if (die_on_failure) { die(_("failed to find exact merge base")); } else { @@ -1725,7 +1726,10 @@ static struct commit *get_base_commit(const char *base_commit, rev_nr = DIV_ROUND_UP(rev_nr, 2); } - if (!repo_in_merge_bases(the_repository, base, rev[0])) { + ret = repo_in_merge_bases(the_repository, base, rev[0]); + if (ret < 0) + exit(128); + if (!ret) { if (die_on_failure) { die(_("base commit should be the ancestor of revision list")); } else { diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 92f94e65bf..6eeb5cba78 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -266,7 +266,6 @@ static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, struct strbuf sb = STRBUF_INIT; while (strbuf_expand_step(&sb, &format)) { - const char *end; size_t len; struct stat st; @@ -274,12 +273,6 @@ static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, strbuf_addch(&sb, '%'); else if ((len = strbuf_expand_literal(&sb, format))) format += len; - else if (*format != '(') - die(_("bad ls-files format: element '%s' " - "does not start with '('"), format); - else if (!(end = strchr(format + 1, ')'))) - die(_("bad ls-files format: element '%s' " - "does not end in ')'"), format); else if (skip_prefix(format, "(objectmode)", &format)) strbuf_addf(&sb, "%06o", ce->ce_mode); else if (skip_prefix(format, "(objectname)", &format)) @@ -308,8 +301,7 @@ static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, else if (skip_prefix(format, "(path)", &format)) write_name_to_buf(&sb, fullname); else - die(_("bad ls-files format: %%%.*s"), - (int)(end - format + 1), format); + strbuf_expand_bad_format(format, "ls-files"); } strbuf_addch(&sb, line_terminator); fwrite(sb.buf, sb.len, 1, stdout); diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index e4a891337c..7bf84b235c 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -100,19 +100,12 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, return 0; while (strbuf_expand_step(&sb, &format)) { - const char *end; size_t len; if (skip_prefix(format, "%", &format)) strbuf_addch(&sb, '%'); else if ((len = strbuf_expand_literal(&sb, format))) format += len; - else if (*format != '(') - die(_("bad ls-tree format: element '%s' " - "does not start with '('"), format); - else if (!(end = strchr(format + 1, ')'))) - die(_("bad ls-tree format: element '%s' " - "does not end in ')'"), format); else if (skip_prefix(format, "(objectmode)", &format)) strbuf_addf(&sb, "%06o", mode); else if (skip_prefix(format, "(objecttype)", &format)) @@ -135,8 +128,7 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, strbuf_setlen(base, baselen); strbuf_release(&sbuf); } else - die(_("bad ls-tree format: %%%.*s"), - (int)(end - format + 1), format); + strbuf_expand_bad_format(format, "ls-tree"); } strbuf_addch(&sb, options->null_termination ? '\0' : '\n'); fwrite(sb.buf, sb.len, 1, stdout); @@ -375,6 +367,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) OPT_END() }; struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format; + struct object_context obj_context; int ret; git_config(git_default_config, NULL); @@ -406,7 +399,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) ls_tree_usage, ls_tree_options); if (argc < 1) usage_with_options(ls_tree_usage, ls_tree_options); - if (repo_get_oid(the_repository, argv[0], &oid)) + if (get_oid_with_context(the_repository, argv[0], + GET_OID_HASH_ANY, &oid, + &obj_context)) die("Not a valid object name %s", argv[0]); /* diff --git a/builtin/merge-base.c b/builtin/merge-base.c index d26e8fbf6f..5a8e729502 100644 --- a/builtin/merge-base.c +++ b/builtin/merge-base.c @@ -10,10 +10,13 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all) { - struct commit_list *result, *r; + struct commit_list *result = NULL, *r; - result = repo_get_merge_bases_many_dirty(the_repository, rev[0], - rev_nr - 1, rev + 1); + if (repo_get_merge_bases_many_dirty(the_repository, rev[0], + rev_nr - 1, rev + 1, &result) < 0) { + free_commit_list(result); + return -1; + } if (!result) return 1; @@ -74,13 +77,17 @@ static int handle_independent(int count, const char **args) static int handle_octopus(int count, const char **args, int show_all) { struct commit_list *revs = NULL; - struct commit_list *result, *rev; + struct commit_list *result = NULL, *rev; int i; for (i = count - 1; i >= 0; i--) commit_list_insert(get_commit_reference(args[i]), &revs); - result = get_octopus_merge_bases(revs); + if (get_octopus_merge_bases(revs, &result) < 0) { + free_commit_list(revs); + free_commit_list(result); + return 128; + } free_commit_list(revs); reduce_heads_replace(&result); @@ -100,12 +107,16 @@ static int handle_octopus(int count, const char **args, int show_all) static int handle_is_ancestor(int argc, const char **argv) { struct commit *one, *two; + int ret; if (argc != 2) die("--is-ancestor takes exactly two commits"); one = get_commit_reference(argv[0]); two = get_commit_reference(argv[1]); - if (repo_in_merge_bases(the_repository, one, two)) + ret = repo_in_merge_bases(the_repository, one, two); + if (ret < 0) + exit(128); + if (ret) return 0; else return 1; diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 3bdec53fbe..8bdb439131 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -429,41 +429,56 @@ static int real_merge(struct merge_tree_options *o, struct merge_options opt; copy_merge_options(&opt, &o->merge_options); - parent1 = get_merge_parent(branch1); - if (!parent1) - help_unknown_ref(branch1, "merge-tree", - _("not something we can merge")); - - parent2 = get_merge_parent(branch2); - if (!parent2) - help_unknown_ref(branch2, "merge-tree", - _("not something we can merge")); - opt.show_rename_progress = 0; opt.branch1 = branch1; opt.branch2 = branch2; if (merge_base) { - struct commit *base_commit; struct tree *base_tree, *parent1_tree, *parent2_tree; - base_commit = lookup_commit_reference_by_name(merge_base); - if (!base_commit) - die(_("could not lookup commit '%s'"), merge_base); + /* + * We actually only need the trees because we already + * have a merge base. + */ + struct object_id base_oid, head_oid, merge_oid; + + if (repo_get_oid_treeish(the_repository, merge_base, &base_oid)) + die(_("could not parse as tree '%s'"), merge_base); + base_tree = parse_tree_indirect(&base_oid); + if (!base_tree) + die(_("unable to read tree (%s)"), oid_to_hex(&base_oid)); + if (repo_get_oid_treeish(the_repository, branch1, &head_oid)) + die(_("could not parse as tree '%s'"), branch1); + parent1_tree = parse_tree_indirect(&head_oid); + if (!parent1_tree) + die(_("unable to read tree (%s)"), oid_to_hex(&head_oid)); + if (repo_get_oid_treeish(the_repository, branch2, &merge_oid)) + die(_("could not parse as tree '%s'"), branch2); + parent2_tree = parse_tree_indirect(&merge_oid); + if (!parent2_tree) + die(_("unable to read tree (%s)"), oid_to_hex(&merge_oid)); opt.ancestor = merge_base; - base_tree = repo_get_commit_tree(the_repository, base_commit); - parent1_tree = repo_get_commit_tree(the_repository, parent1); - parent2_tree = repo_get_commit_tree(the_repository, parent2); merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result); } else { + parent1 = get_merge_parent(branch1); + if (!parent1) + help_unknown_ref(branch1, "merge-tree", + _("not something we can merge")); + + parent2 = get_merge_parent(branch2); + if (!parent2) + help_unknown_ref(branch2, "merge-tree", + _("not something we can merge")); + /* * Get the merge bases, in reverse order; see comment above * merge_incore_recursive in merge-ort.h */ - merge_bases = repo_get_merge_bases(the_repository, parent1, - parent2); + if (repo_get_merge_bases(the_repository, parent1, + parent2, &merge_bases) < 0) + exit(128); if (!merge_bases && !o->allow_unrelated_histories) die(_("refusing to merge unrelated histories")); merge_bases = reverse_commit_list(merge_bases); @@ -548,7 +563,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) PARSE_OPT_NONEG), OPT_STRING(0, "merge-base", &merge_base, - N_("commit"), + N_("tree-ish"), N_("specify a merge-base for the merge")), OPT_STRVEC('X', "strategy-option", &xopts, N_("option=value"), N_("option for selected merge strategy")), diff --git a/builtin/merge.c b/builtin/merge.c index 8f819781cc..6f4fec87fc 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -192,8 +192,7 @@ static struct strategy *get_strategy(const char *name) int j, found = 0; struct cmdname *ent = main_cmds.names[i]; for (j = 0; !found && j < ARRAY_SIZE(all_strategy); j++) - if (!strncmp(ent->name, all_strategy[j].name, ent->len) - && !all_strategy[j].name[ent->len]) + if (!xstrncmpz(all_strategy[j].name, ent->name, ent->len)) found = 1; if (!found) add_cmdname(¬_strategies, ent->name, ent->len); @@ -678,7 +677,8 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head, cache_tree_free(&the_index.cache_tree); for (i = 0; i < nr_trees; i++) { parse_tree(trees[i]); - init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); + init_tree_desc(t+i, &trees[i]->object.oid, + trees[i]->buffer, trees[i]->size); } if (unpack_trees(nr_trees, t, &opts)) return -1; @@ -822,7 +822,7 @@ static const char scissors_editor_comment[] = N_("An empty message aborts the commit.\n"); static const char no_scissors_editor_comment[] = -N_("Lines starting with '%c' will be ignored, and an empty message aborts\n" +N_("Lines starting with '%s' will be ignored, and an empty message aborts\n" "the commit.\n"); static void write_merge_heads(struct commit_list *); @@ -853,16 +853,16 @@ static void prepare_to_commit(struct commit_list *remoteheads) strbuf_addch(&msg, '\n'); if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) { wt_status_append_cut_line(&msg); - strbuf_commented_addf(&msg, comment_line_char, "\n"); + strbuf_commented_addf(&msg, comment_line_str, "\n"); } - strbuf_commented_addf(&msg, comment_line_char, + strbuf_commented_addf(&msg, comment_line_str, _(merge_editor_comment)); if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) - strbuf_commented_addf(&msg, comment_line_char, + strbuf_commented_addf(&msg, comment_line_str, _(scissors_editor_comment)); else - strbuf_commented_addf(&msg, comment_line_char, - _(no_scissors_editor_comment), comment_line_char); + strbuf_commented_addf(&msg, comment_line_str, + _(no_scissors_editor_comment), comment_line_str); } if (signoff) append_signoff(&msg, ignored_log_message_bytes(msg.buf, msg.len), 0); @@ -1514,13 +1514,20 @@ int cmd_merge(int argc, const char **argv, const char *prefix) if (!remoteheads) ; /* already up-to-date */ - else if (!remoteheads->next) - common = repo_get_merge_bases(the_repository, head_commit, - remoteheads->item); - else { + else if (!remoteheads->next) { + if (repo_get_merge_bases(the_repository, head_commit, + remoteheads->item, &common) < 0) { + ret = 2; + goto done; + } + } else { struct commit_list *list = remoteheads; commit_list_insert(head_commit, &list); - common = get_octopus_merge_bases(list); + if (get_octopus_merge_bases(list, &common) < 0) { + free(list); + ret = 2; + goto done; + } free(list); } @@ -1627,7 +1634,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) struct commit_list *j; for (j = remoteheads; j; j = j->next) { - struct commit_list *common_one; + struct commit_list *common_one = NULL; struct commit *common_item; /* @@ -1635,9 +1642,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * merge_bases again, otherwise "git merge HEAD^ * HEAD^^" would be missed. */ - common_one = repo_get_merge_bases(the_repository, - head_commit, - j->item); + if (repo_get_merge_bases(the_repository, head_commit, + j->item, &common_one) < 0) + exit(128); + common_item = common_one->item; free_commit_list(common_one); if (!oideq(&common_item->object.oid, &j->item->object.oid)) { diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 2dd1807c4e..ad9930c831 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -15,6 +15,7 @@ #include "commit-slab.h" #include "commit-graph.h" #include "wildmatch.h" +#include "mem-pool.h" /* * One day. See the 'name a rev shortly after epoch' test in t6120 when @@ -155,30 +156,25 @@ static struct rev_name *create_or_update_name(struct commit *commit, return name; } -static char *get_parent_name(const struct rev_name *name, int parent_number) +static char *get_parent_name(const struct rev_name *name, int parent_number, + struct mem_pool *string_pool) { - struct strbuf sb = STRBUF_INIT; size_t len; strip_suffix(name->tip_name, "^0", &len); if (name->generation > 0) { - strbuf_grow(&sb, len + - 1 + decimal_width(name->generation) + - 1 + decimal_width(parent_number)); - strbuf_addf(&sb, "%.*s~%d^%d", (int)len, name->tip_name, - name->generation, parent_number); + return mem_pool_strfmt(string_pool, "%.*s~%d^%d", + (int)len, name->tip_name, + name->generation, parent_number); } else { - strbuf_grow(&sb, len + - 1 + decimal_width(parent_number)); - strbuf_addf(&sb, "%.*s^%d", (int)len, name->tip_name, - parent_number); + return mem_pool_strfmt(string_pool, "%.*s^%d", + (int)len, name->tip_name, parent_number); } - return strbuf_detach(&sb, NULL); } static void name_rev(struct commit *start_commit, const char *tip_name, timestamp_t taggerdate, - int from_tag, int deref) + int from_tag, int deref, struct mem_pool *string_pool) { struct prio_queue queue; struct commit *commit; @@ -195,9 +191,10 @@ static void name_rev(struct commit *start_commit, if (!start_name) return; if (deref) - start_name->tip_name = xstrfmt("%s^0", tip_name); + start_name->tip_name = mem_pool_strfmt(string_pool, "%s^0", + tip_name); else - start_name->tip_name = xstrdup(tip_name); + start_name->tip_name = mem_pool_strdup(string_pool, tip_name); memset(&queue, 0, sizeof(queue)); /* Use the prio_queue as LIFO */ prio_queue_put(&queue, start_commit); @@ -235,7 +232,8 @@ static void name_rev(struct commit *start_commit, if (parent_number > 1) parent_name->tip_name = get_parent_name(name, - parent_number); + parent_number, + string_pool); else parent_name->tip_name = name->tip_name; ALLOC_GROW(parents_to_queue, @@ -415,7 +413,7 @@ static int name_ref(const char *path, const struct object_id *oid, return 0; } -static void name_tips(void) +static void name_tips(struct mem_pool *string_pool) { int i; @@ -428,7 +426,7 @@ static void name_tips(void) struct tip_table_entry *e = &tip_table.table[i]; if (e->commit) { name_rev(e->commit, e->refname, e->taggerdate, - e->from_tag, e->deref); + e->from_tag, e->deref, string_pool); } } } @@ -561,6 +559,7 @@ static void name_rev_line(char *p, struct name_ref_data *data) int cmd_name_rev(int argc, const char **argv, const char *prefix) { + struct mem_pool string_pool; struct object_array revs = OBJECT_ARRAY_INIT; int all = 0, annotate_stdin = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0; struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP }; @@ -587,6 +586,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) OPT_END(), }; + mem_pool_init(&string_pool, 0); init_commit_rev_name(&rev_names); git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0); @@ -648,7 +648,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) adjust_cutoff_timestamp_for_slop(); for_each_ref(name_ref, &data); - name_tips(); + name_tips(&string_pool); if (annotate_stdin) { struct strbuf sb = STRBUF_INIT; @@ -676,6 +676,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) always, allow_undefined, data.name_only); } + UNLEAK(string_pool); UNLEAK(revs); return 0; } diff --git a/builtin/notes.c b/builtin/notes.c index caf20fd5bd..cb011303e6 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -179,7 +179,7 @@ static void write_commented_object(int fd, const struct object_id *object) if (strbuf_read(&buf, show.out, 0) < 0) die_errno(_("could not read 'show' output")); - strbuf_add_commented_lines(&cbuf, buf.buf, buf.len, comment_line_char); + strbuf_add_commented_lines(&cbuf, buf.buf, buf.len, comment_line_str); write_or_die(fd, cbuf.buf, cbuf.len); strbuf_release(&cbuf); @@ -207,10 +207,10 @@ static void prepare_note_data(const struct object_id *object, struct note_data * copy_obj_to_fd(fd, old_note); strbuf_addch(&buf, '\n'); - strbuf_add_commented_lines(&buf, "\n", strlen("\n"), comment_line_char); + strbuf_add_commented_lines(&buf, "\n", strlen("\n"), comment_line_str); strbuf_add_commented_lines(&buf, _(note_template), strlen(_(note_template)), - comment_line_char); - strbuf_add_commented_lines(&buf, "\n", strlen("\n"), comment_line_char); + comment_line_str); + strbuf_add_commented_lines(&buf, "\n", strlen("\n"), comment_line_str); write_or_die(fd, buf.buf, buf.len); write_commented_object(fd, object); @@ -223,7 +223,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data * die(_("please supply the note contents using either -m or -F option")); } if (d->stripspace) - strbuf_stripspace(&d->buf, comment_line_char); + strbuf_stripspace(&d->buf, comment_line_str); } } @@ -264,7 +264,7 @@ static void concat_messages(struct note_data *d) if ((d->stripspace == UNSPECIFIED && d->messages[i]->stripspace == STRIPSPACE) || d->stripspace == STRIPSPACE) - strbuf_stripspace(&d->buf, 0); + strbuf_stripspace(&d->buf, NULL); strbuf_reset(&msg); } strbuf_release(&msg); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 329aeac804..baf0090fc8 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1826,7 +1826,8 @@ static void add_pbase_object(struct tree_desc *tree, tree = pbase_tree_get(&entry.oid); if (!tree) return; - init_tree_desc(&sub, tree->tree_data, tree->tree_size); + init_tree_desc(&sub, &tree->oid, + tree->tree_data, tree->tree_size); add_pbase_object(&sub, down, downlen, fullname); pbase_tree_put(tree); @@ -1886,7 +1887,8 @@ static void add_preferred_base_object(const char *name) } else { struct tree_desc tree; - init_tree_desc(&tree, it->pcache.tree_data, it->pcache.tree_size); + init_tree_desc(&tree, &it->pcache.oid, + it->pcache.tree_data, it->pcache.tree_size); add_pbase_object(&tree, name, cmplen, name); } } diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index bcf383cac9..db40825666 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -7,24 +7,28 @@ #include "revision.h" static char const * const pack_refs_usage[] = { - N_("git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude <pattern>]"), + N_("git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude <pattern>]"), NULL }; int cmd_pack_refs(int argc, const char **argv, const char *prefix) { - unsigned int flags = PACK_REFS_PRUNE; - static struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; - static struct string_list included_refs = STRING_LIST_INIT_NODUP; - struct pack_refs_opts pack_refs_opts = { .exclusions = &excludes, - .includes = &included_refs, - .flags = flags }; - static struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP; + struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; + struct string_list included_refs = STRING_LIST_INIT_NODUP; + struct pack_refs_opts pack_refs_opts = { + .exclusions = &excludes, + .includes = &included_refs, + .flags = PACK_REFS_PRUNE, + }; + struct string_list option_excluded_refs = STRING_LIST_INIT_NODUP; struct string_list_item *item; + int pack_all = 0; + int ret; struct option opts[] = { - OPT_BIT(0, "all", &pack_refs_opts.flags, N_("pack everything"), PACK_REFS_ALL), + OPT_BOOL(0, "all", &pack_all, N_("pack everything")), OPT_BIT(0, "prune", &pack_refs_opts.flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE), + OPT_BIT(0, "auto", &pack_refs_opts.flags, N_("auto-pack refs as needed"), PACK_REFS_AUTO), OPT_STRING_LIST(0, "include", pack_refs_opts.includes, N_("pattern"), N_("references to include")), OPT_STRING_LIST(0, "exclude", &option_excluded_refs, N_("pattern"), @@ -38,11 +42,16 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix) for_each_string_list_item(item, &option_excluded_refs) add_ref_exclusion(pack_refs_opts.exclusions, item->string); - if (pack_refs_opts.flags & PACK_REFS_ALL) + if (pack_all) string_list_append(pack_refs_opts.includes, "*"); if (!pack_refs_opts.includes->nr) string_list_append(pack_refs_opts.includes, "refs/tags/*"); - return refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); + ret = refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); + + clear_ref_exclusions(&excludes); + string_list_clear(&included_refs, 0); + string_list_clear(&option_excluded_refs, 0); + return ret; } diff --git a/builtin/pull.c b/builtin/pull.c index 73a68b75b0..72cbb76d52 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -815,7 +815,7 @@ static int get_octopus_merge_base(struct object_id *merge_base, const struct object_id *merge_head, const struct object_id *fork_point) { - struct commit_list *revs = NULL, *result; + struct commit_list *revs = NULL, *result = NULL; commit_list_insert(lookup_commit_reference(the_repository, curr_head), &revs); @@ -825,7 +825,8 @@ static int get_octopus_merge_base(struct object_id *merge_base, commit_list_insert(lookup_commit_reference(the_repository, fork_point), &revs); - result = get_octopus_merge_bases(revs); + if (get_octopus_merge_bases(revs, &result) < 0) + exit(128); free_commit_list(revs); reduce_heads_replace(&result); @@ -926,6 +927,8 @@ static int get_can_ff(struct object_id *orig_head, merge_head = lookup_commit_reference(the_repository, orig_merge_head); ret = repo_is_descendant_of(the_repository, merge_head, list); free_commit_list(list); + if (ret < 0) + exit(128); return ret; } @@ -950,6 +953,8 @@ static int already_up_to_date(struct object_id *orig_head, commit_list_insert(theirs, &list); ok = repo_is_descendant_of(the_repository, ours, list); free_commit_list(list); + if (ok < 0) + exit(128); if (!ok) return 0; } diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 20e7db1973..6f89cec0fb 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -261,8 +261,9 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) cache_tree_free(&the_index.cache_tree); for (i = 0; i < nr_trees; i++) { struct tree *tree = trees[i]; - parse_tree(tree); - init_tree_desc(t+i, tree->buffer, tree->size); + if (parse_tree(tree) < 0) + return 128; + init_tree_desc(t+i, &tree->object.oid, tree->buffer, tree->size); } if (unpack_trees(nr_trees, t, &opts)) return 128; diff --git a/builtin/rebase.c b/builtin/rebase.c index 5b086f651a..891f28468e 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -58,7 +58,7 @@ enum empty_type { EMPTY_UNSPECIFIED = -1, EMPTY_DROP, EMPTY_KEEP, - EMPTY_ASK + EMPTY_STOP }; enum action { @@ -204,7 +204,7 @@ static int edit_todo_file(unsigned flags) if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0) return error_errno(_("could not read '%s'."), todo_file); - strbuf_stripspace(&todo_list.buf, comment_line_char); + strbuf_stripspace(&todo_list.buf, comment_line_str); res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags); if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file, NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS))) @@ -567,13 +567,6 @@ static int move_to_original_branch(struct rebase_options *opts) return ret; } -static const char *resolvemsg = -N_("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\"."); - static int run_am(struct rebase_options *opts) { struct child_process am = CHILD_PROCESS_INIT; @@ -587,7 +580,7 @@ static int run_am(struct rebase_options *opts) opts->reflog_action); if (opts->action == ACTION_CONTINUE) { strvec_push(&am.args, "--resolved"); - strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg); + strvec_pushf(&am.args, "--resolvemsg=%s", rebase_resolvemsg); if (opts->gpg_sign_opt) strvec_push(&am.args, opts->gpg_sign_opt); status = run_command(&am); @@ -598,7 +591,7 @@ static int run_am(struct rebase_options *opts) } if (opts->action == ACTION_SKIP) { strvec_push(&am.args, "--skip"); - strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg); + strvec_pushf(&am.args, "--resolvemsg=%s", rebase_resolvemsg); status = run_command(&am); if (status) return status; @@ -617,7 +610,7 @@ static int run_am(struct rebase_options *opts) status = error_errno(_("could not open '%s' for writing"), rebased_patches); free(rebased_patches); - strvec_clear(&am.args); + child_process_clear(&am); return status; } @@ -645,7 +638,7 @@ static int run_am(struct rebase_options *opts) struct reset_head_opts ropts = { 0 }; unlink(rebased_patches); free(rebased_patches); - strvec_clear(&am.args); + child_process_clear(&am); ropts.oid = &opts->orig_head->object.oid; ropts.branch = opts->head_name; @@ -666,13 +659,13 @@ static int run_am(struct rebase_options *opts) status = error_errno(_("could not open '%s' for reading"), rebased_patches); free(rebased_patches); - strvec_clear(&am.args); + child_process_clear(&am); return status; } strvec_pushv(&am.args, opts->git_am_opts.v); strvec_push(&am.args, "--rebasing"); - strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg); + strvec_pushf(&am.args, "--resolvemsg=%s", rebase_resolvemsg); strvec_push(&am.args, "--patch-format=mboxrd"); if (opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE) strvec_push(&am.args, "--rerere-autoupdate"); @@ -700,7 +693,6 @@ static int run_specific_rebase(struct rebase_options *opts) if (opts->type == REBASE_MERGE) { /* Run sequencer-based rebase */ - setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1); if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) setenv("GIT_SEQUENCE_EDITOR", ":", 1); if (opts->gpg_sign_opt) { @@ -867,7 +859,8 @@ static int can_fast_forward(struct commit *onto, struct commit *upstream, if (!upstream) goto done; - merge_bases = repo_get_merge_bases(the_repository, upstream, head); + if (repo_get_merge_bases(the_repository, upstream, head, &merge_bases) < 0) + exit(128); if (!merge_bases || merge_bases->next) goto done; @@ -886,8 +879,9 @@ static void fill_branch_base(struct rebase_options *options, { struct commit_list *merge_bases = NULL; - merge_bases = repo_get_merge_bases(the_repository, options->onto, - options->orig_head); + if (repo_get_merge_bases(the_repository, options->onto, + options->orig_head, &merge_bases) < 0) + exit(128); if (!merge_bases || merge_bases->next) oidcpy(branch_base, null_oid()); else @@ -951,10 +945,14 @@ static enum empty_type parse_empty_value(const char *value) return EMPTY_DROP; else if (!strcasecmp(value, "keep")) return EMPTY_KEEP; - else if (!strcasecmp(value, "ask")) - return EMPTY_ASK; + else if (!strcasecmp(value, "stop")) + return EMPTY_STOP; + else if (!strcasecmp(value, "ask")) { + warning(_("--empty=ask is deprecated; use '--empty=stop' instead.")); + return EMPTY_STOP; + } - die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value); + die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"stop\"."), value); } static int parse_opt_keep_empty(const struct option *opt, const char *arg, @@ -1133,7 +1131,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) "instead of ignoring them"), 1, PARSE_OPT_HIDDEN), OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate), - OPT_CALLBACK_F(0, "empty", &options, "(drop|keep|ask)", + OPT_CALLBACK_F(0, "empty", &options, "(drop|keep|stop)", N_("how to handle commits that become empty"), PARSE_OPT_NONEG, parse_opt_empty), OPT_CALLBACK_F('k', "keep-empty", &options, NULL, @@ -1254,7 +1252,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point"); if (options.action != ACTION_NONE && !in_progress) - die(_("No rebase in progress?")); + die(_("no rebase in progress")); if (options.action == ACTION_EDIT_TODO && !is_merge(&options)) die(_("The --edit-todo action can only be used during " @@ -1550,7 +1548,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) if (options.empty == EMPTY_UNSPECIFIED) { if (options.flags & REBASE_INTERACTIVE_EXPLICIT) - options.empty = EMPTY_ASK; + options.empty = EMPTY_STOP; else if (options.exec.nr > 0) options.empty = EMPTY_KEEP; else diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index db65607485..e8d7df14b6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1526,6 +1526,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) starts_with(name, "refs/heads/")) { struct object *old_object, *new_object; struct commit *old_commit, *new_commit; + int ret2; old_object = parse_object(the_repository, old_oid); new_object = parse_object(the_repository, new_oid); @@ -1539,7 +1540,10 @@ static const char *update(struct command *cmd, struct shallow_info *si) } old_commit = (struct commit *)old_object; new_commit = (struct commit *)new_object; - if (!repo_in_merge_bases(the_repository, old_commit, new_commit)) { + ret2 = repo_in_merge_bases(the_repository, old_commit, new_commit); + if (ret2 < 0) + exit(128); + if (!ret2) { rp_error("denying non-fast-forward %s" " (you should pull first)", name); ret = "non-fast-forward"; @@ -2581,17 +2585,16 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) if (auto_gc) { struct child_process proc = CHILD_PROCESS_INIT; - proc.no_stdin = 1; - proc.stdout_to_stderr = 1; - proc.err = use_sideband ? -1 : 0; - proc.git_cmd = proc.close_object_store = 1; - strvec_pushl(&proc.args, "gc", "--auto", "--quiet", - NULL); - - if (!start_command(&proc)) { - if (use_sideband) - copy_to_sideband(proc.err, -1, NULL); - finish_command(&proc); + if (prepare_auto_maintenance(1, &proc)) { + proc.no_stdin = 1; + proc.stdout_to_stderr = 1; + proc.err = use_sideband ? -1 : 0; + + if (!start_command(&proc)) { + if (use_sideband) + copy_to_sideband(proc.err, -1, NULL); + finish_command(&proc); + } } } if (auto_update_server_info) diff --git a/builtin/reflog.c b/builtin/reflog.c index a5a4099f61..060eb3377e 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -7,11 +7,15 @@ #include "wildmatch.h" #include "worktree.h" #include "reflog.h" +#include "refs.h" #include "parse-options.h" #define BUILTIN_REFLOG_SHOW_USAGE \ N_("git reflog [show] [<log-options>] [<ref>]") +#define BUILTIN_REFLOG_LIST_USAGE \ + N_("git reflog list") + #define BUILTIN_REFLOG_EXPIRE_USAGE \ N_("git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" \ " [--rewrite] [--updateref] [--stale-fix]\n" \ @@ -29,6 +33,11 @@ static const char *const reflog_show_usage[] = { NULL, }; +static const char *const reflog_list_usage[] = { + BUILTIN_REFLOG_LIST_USAGE, + NULL, +}; + static const char *const reflog_expire_usage[] = { BUILTIN_REFLOG_EXPIRE_USAGE, NULL @@ -46,6 +55,7 @@ static const char *const reflog_exists_usage[] = { static const char *const reflog_usage[] = { BUILTIN_REFLOG_SHOW_USAGE, + BUILTIN_REFLOG_LIST_USAGE, BUILTIN_REFLOG_EXPIRE_USAGE, BUILTIN_REFLOG_DELETE_USAGE, BUILTIN_REFLOG_EXISTS_USAGE, @@ -60,8 +70,7 @@ struct worktree_reflogs { struct string_list reflogs; }; -static int collect_reflog(const char *ref, const struct object_id *oid UNUSED, - int flags UNUSED, void *cb_data) +static int collect_reflog(const char *ref, void *cb_data) { struct worktree_reflogs *cb = cb_data; struct worktree *worktree = cb->worktree; @@ -96,8 +105,7 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len) reflog_expire_cfg_tail = &reflog_expire_cfg; for (ent = reflog_expire_cfg; ent; ent = ent->next) - if (!strncmp(ent->pattern, pattern, len) && - ent->pattern[len] == '\0') + if (!xstrncmpz(ent->pattern, pattern, len)) return ent; FLEX_ALLOC_MEM(ent, pattern, pattern, len); @@ -239,6 +247,29 @@ static int cmd_reflog_show(int argc, const char **argv, const char *prefix) return cmd_log_reflog(argc, argv, prefix); } +static int show_reflog(const char *refname, void *cb_data UNUSED) +{ + printf("%s\n", refname); + return 0; +} + +static int cmd_reflog_list(int argc, const char **argv, const char *prefix) +{ + struct option options[] = { + OPT_END() + }; + struct ref_store *ref_store; + + argc = parse_options(argc, argv, prefix, options, reflog_list_usage, 0); + if (argc) + return error(_("%s does not accept arguments: '%s'"), + "list", argv[0]); + + ref_store = get_main_ref_store(the_repository); + + return refs_for_each_reflog(ref_store, show_reflog, NULL); +} + static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) { struct cmd_reflog_expire_cb cmd = { 0 }; @@ -418,6 +449,7 @@ int cmd_reflog(int argc, const char **argv, const char *prefix) parse_opt_subcommand_fn *fn = NULL; struct option options[] = { OPT_SUBCOMMAND("show", &fn, cmd_reflog_show), + OPT_SUBCOMMAND("list", &fn, cmd_reflog_list), OPT_SUBCOMMAND("expire", &fn, cmd_reflog_expire), OPT_SUBCOMMAND("delete", &fn, cmd_reflog_delete), OPT_SUBCOMMAND("exists", &fn, cmd_reflog_exists), diff --git a/builtin/remote.c b/builtin/remote.c index d91bbe728d..8412d12fa5 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -150,7 +150,7 @@ static int parse_mirror_opt(const struct option *opt, const char *arg, int not) else if (!strcmp(arg, "push")) *mirror = MIRROR_PUSH; else - return error(_("unknown mirror argument: %s"), arg); + return error(_("unknown --mirror argument: %s"), arg); return 0; } diff --git a/builtin/repack.c b/builtin/repack.c index ede36328a3..15e4cccc45 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -314,8 +314,9 @@ static int write_oid(const struct object_id *oid, die(_("could not start pack-objects to repack promisor objects")); } - xwrite(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz); - xwrite(cmd->in, "\n", 1); + 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 promisor objects to pack-objects")); return 0; } diff --git a/builtin/reset.c b/builtin/reset.c index 8390bfe4c4..1d62ff6332 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -116,6 +116,10 @@ static int reset_index(const char *ref, const struct object_id *oid, int reset_t if (reset_type == MIXED || reset_type == HARD) { tree = parse_tree_indirect(oid); + if (!tree) { + error(_("unable to read tree (%s)"), oid_to_hex(oid)); + goto out; + } prime_cache_tree(the_repository, the_repository->index, tree); } @@ -281,7 +285,9 @@ static void parse_args(struct pathspec *pathspec, verify_filename(prefix, argv[0], 1); } } - *rev_ret = rev; + + /* treat '@' as a shortcut for 'HEAD' */ + *rev_ret = !strcmp("@", rev) ? "HEAD" : rev; parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL | diff --git a/builtin/rev-list.c b/builtin/rev-list.c index b3f4783858..77803727e0 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -219,6 +219,7 @@ static void show_commit(struct commit *commit, void *data) ctx.fmt = revs->commit_format; ctx.output_encoding = get_log_output_encoding(); ctx.color = revs->diffopt.use_color; + ctx.rev = revs; pretty_print_commit(&ctx, commit, &buf); if (buf.len) { if (revs->commit_format != CMIT_FMT_ONELINE) @@ -545,6 +546,18 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) * * Let "--missing" to conditionally set fetch_if_missing. */ + /* + * NEEDSWORK: These loops that attempt to find presence of + * options without understanding that the options they are + * skipping are broken (e.g., it would not know "--grep + * --exclude-promisor-objects" is not triggering + * "--exclude-promisor-objects" option). We really need + * setup_revisions() to have a mechanism to allow and disallow + * some sets of options for different commands (like rev-list, + * replay, etc). Such a mechanism should do an early parsing + * of options and be able to manage the `--missing=...` and + * `--exclude-promisor-objects` options below. + */ for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--exclude-promisor-objects")) { @@ -753,8 +766,12 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (arg_print_omitted) oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE); - if (arg_missing_action == MA_PRINT) + if (arg_missing_action == MA_PRINT) { oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE); + /* Add missing tips */ + oidset_insert_from_set(&missing_objects, &revs.missing_commits); + oidset_clear(&revs.missing_commits); + } traverse_commit_list_filtered( &revs, show_commit, show_object, &info, diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index d08987646a..624182e507 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -25,6 +25,7 @@ #include "submodule.h" #include "commit-reach.h" #include "shallow.h" +#include "object-file-convert.h" #define DO_REVS 1 #define DO_NOREV 2 @@ -297,7 +298,7 @@ static int try_difference(const char *arg) show_rev(NORMAL, &end_oid, end); show_rev(symmetric ? NORMAL : REVERSED, &start_oid, start); if (symmetric) { - struct commit_list *exclude; + struct commit_list *exclude = NULL; struct commit *a, *b; a = lookup_commit_reference(the_repository, &start_oid); b = lookup_commit_reference(the_repository, &end_oid); @@ -305,7 +306,8 @@ static int try_difference(const char *arg) *dotdot = '.'; return 0; } - exclude = repo_get_merge_bases(the_repository, a, b); + if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0) + exit(128); while (exclude) { struct commit *commit = pop_commit(&exclude); show_rev(REVERSED, &commit->object.oid, NULL); @@ -675,6 +677,8 @@ static void print_path(const char *path, const char *prefix, enum format_type fo int cmd_rev_parse(int argc, const char **argv, const char *prefix) { int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0; + const struct git_hash_algo *output_algo = NULL; + const struct git_hash_algo *compat = NULL; int did_repo_setup = 0; int has_dashdash = 0; int output_prefix = 0; @@ -746,6 +750,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; + compat = the_repository->compat_hash_algo; } if (!strcmp(arg, "--")) { @@ -833,6 +838,22 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) flags |= GET_OID_QUIETLY; continue; } + if (opt_with_value(arg, "--output-object-format", &arg)) { + if (!arg) + die(_("no object format specified")); + if (!strcmp(arg, the_hash_algo->name) || + !strcmp(arg, "storage")) { + flags |= GET_OID_HASH_ANY; + output_algo = the_hash_algo; + continue; + } + else if (compat && !strcmp(arg, compat->name)) { + flags |= GET_OID_HASH_ANY; + output_algo = compat; + continue; + } + else die(_("unsupported object format: %s"), arg); + } if (opt_with_value(arg, "--short", &arg)) { filter &= ~(DO_FLAGS|DO_NOREV); verify = 1; @@ -882,7 +903,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (skip_prefix(arg, "--disambiguate=", &arg)) { - repo_for_each_abbrev(the_repository, arg, + repo_for_each_abbrev(the_repository, arg, the_hash_algo, show_abbrev, NULL); continue; } @@ -1090,6 +1111,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } if (!get_oid_with_context(the_repository, name, flags, &oid, &unused)) { + if (output_algo) + repo_oid_to_algop(the_repository, &oid, + output_algo, &oid); if (verify) revs_count++; else diff --git a/builtin/revert.c b/builtin/revert.c index 89821bab95..53935d2c68 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -43,6 +43,31 @@ static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts) return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage; } +enum empty_action { + EMPTY_COMMIT_UNSPECIFIED = -1, + STOP_ON_EMPTY_COMMIT, /* output errors and stop in the middle of a cherry-pick */ + DROP_EMPTY_COMMIT, /* skip with a notice message */ + KEEP_EMPTY_COMMIT, /* keep recording as empty commits */ +}; + +static int parse_opt_empty(const struct option *opt, const char *arg, int unset) +{ + int *opt_value = opt->value; + + BUG_ON_OPT_NEG(unset); + + if (!strcmp(arg, "stop")) + *opt_value = STOP_ON_EMPTY_COMMIT; + else if (!strcmp(arg, "drop")) + *opt_value = DROP_EMPTY_COMMIT; + else if (!strcmp(arg, "keep")) + *opt_value = KEEP_EMPTY_COMMIT; + else + return error(_("invalid value for '%s': '%s'"), "--empty", arg); + + return 0; +} + static int option_parse_m(const struct option *opt, const char *arg, int unset) { @@ -85,6 +110,7 @@ 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; + enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED; int cmd = 0; struct option base_options[] = { OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'), @@ -114,7 +140,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, OPT_BOOL(0, "ff", &opts->allow_ff, N_("allow fast-forward")), OPT_BOOL(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")), OPT_BOOL(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")), - OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")), + OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("deprecated: use --empty=keep instead")), + OPT_CALLBACK_F(0, "empty", &empty_opt, "(stop|drop|keep)", + N_("how to handle commits that become empty"), + PARSE_OPT_NONEG, parse_opt_empty), OPT_END(), }; options = parse_options_concat(options, cp_extra); @@ -134,6 +163,11 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, prepare_repo_settings(the_repository); the_repository->settings.command_requires_full_index = 0; + if (opts->action == REPLAY_PICK) { + opts->drop_redundant_commits = (empty_opt == DROP_EMPTY_COMMIT); + opts->keep_redundant_commits = opts->keep_redundant_commits || (empty_opt == KEEP_EMPTY_COMMIT); + } + /* implies allow_empty */ if (opts->keep_redundant_commits) opts->allow_empty = 1; @@ -167,6 +201,8 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, "--ff", opts->allow_ff, "--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE, "--no-rerere-autoupdate", opts->allow_rerere_auto == RERERE_NOAUTOUPDATE, + "--keep-redundant-commits", opts->keep_redundant_commits, + "--empty", empty_opt != EMPTY_COMMIT_UNSPECIFIED, NULL); } diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 1307ed2b88..3c7cd2d6ef 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -245,7 +245,6 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit) ctx.fmt = CMIT_FMT_USERFORMAT; ctx.abbrev = log->abbrev; - ctx.print_email_subject = 1; ctx.date_mode = log->date_mode; ctx.output_encoding = get_log_output_encoding(); diff --git a/builtin/stash.c b/builtin/stash.c index 7fb355bff0..062be1fbc0 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -284,7 +284,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset) if (parse_tree(tree)) return -1; - init_tree_desc(t, tree->buffer, tree->size); + init_tree_desc(t, &tree->object.oid, tree->buffer, tree->size); opts.head_idx = 1; opts.src_index = &the_index; @@ -870,7 +870,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op tree[i] = parse_tree_indirect(oid[i]); if (parse_tree(tree[i]) < 0) die(_("failed to parse tree")); - init_tree_desc(&tree_desc[i], tree[i]->buffer, tree[i]->size); + init_tree_desc(&tree_desc[i], &tree[i]->object.oid, + tree[i]->buffer, tree[i]->size); } unpack_tree_opt.head_idx = -1; diff --git a/builtin/stripspace.c b/builtin/stripspace.c index 7b700a9fb1..e5626e5126 100644 --- a/builtin/stripspace.c +++ b/builtin/stripspace.c @@ -13,7 +13,7 @@ static void comment_lines(struct strbuf *buf) size_t len; msg = strbuf_detach(buf, &len); - strbuf_add_commented_lines(buf, msg, len, comment_line_char); + strbuf_add_commented_lines(buf, msg, len, comment_line_str); free(msg); } @@ -59,7 +59,7 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix) if (mode == STRIP_DEFAULT || mode == STRIP_COMMENTS) strbuf_stripspace(&buf, - mode == STRIP_COMMENTS ? comment_line_char : '\0'); + mode == STRIP_COMMENTS ? comment_line_str : NULL); else comment_lines(&buf); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index fda50f2af1..e4e18adb57 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1283,7 +1283,7 @@ static void sync_submodule(const char *path, const char *prefix, submodule_to_gitdir(&sb, path); strbuf_addstr(&sb, "/config"); - if (git_config_set_in_file_gently(sb.buf, remote_key, sub_origin_url)) + if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url)) die(_("failed to update remote for submodule '%s'"), path); diff --git a/builtin/tag.c b/builtin/tag.c index 37473ac21f..9a33cb50b4 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -27,6 +27,7 @@ #include "ref-filter.h" #include "date.h" #include "write-or-die.h" +#include "object-file-convert.h" static const char * const git_tag_usage[] = { N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" @@ -151,18 +152,52 @@ static int verify_tag(const char *name, const char *ref UNUSED, return 0; } -static int do_sign(struct strbuf *buffer) +static int do_sign(struct strbuf *buffer, struct object_id **compat_oid, + struct object_id *compat_oid_buf) { - return sign_buffer(buffer, buffer, get_signing_key()) ? -1 : 0; + 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(); + int ret = -1; + + if (sign_buffer(buffer, &sig, keyid)) + return -1; + + if (compat) { + const struct git_hash_algo *algo = the_repository->hash_algo; + + if (convert_object_file(&compat_buf, algo, compat, + buffer->buf, buffer->len, OBJ_TAG, 1)) + goto out; + if (sign_buffer(&compat_buf, &compat_sig, keyid)) + goto out; + add_header_signature(&compat_buf, &sig, algo); + strbuf_addbuf(&compat_buf, &compat_sig); + hash_object_file(compat, compat_buf.buf, compat_buf.len, + OBJ_TAG, compat_oid_buf); + *compat_oid = compat_oid_buf; + } + + if (compat_sig.len) + add_header_signature(buffer, &compat_sig, compat); + + strbuf_addbuf(buffer, &sig); + ret = 0; +out: + strbuf_release(&sig); + strbuf_release(&compat_sig); + strbuf_release(&compat_buf); + return ret; } static const char tag_template[] = N_("\nWrite a message for tag:\n %s\n" - "Lines starting with '%c' will be ignored.\n"); + "Lines starting with '%s' will be ignored.\n"); static const char tag_template_nocleanup[] = N_("\nWrite a message for tag:\n %s\n" - "Lines starting with '%c' will be kept; you may remove them" + "Lines starting with '%s' will be kept; you may remove them" " yourself if you want to.\n"); static int git_tag_config(const char *var, const char *value, @@ -226,9 +261,11 @@ static void write_tag_body(int fd, const struct object_id *oid) static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result) { - if (sign && do_sign(buf) < 0) + struct object_id *compat_oid = NULL, compat_oid_buf; + if (sign && do_sign(buf, &compat_oid, &compat_oid_buf) < 0) return error(_("unable to sign the tag")); - if (write_object_file(buf->buf, buf->len, OBJ_TAG, result) < 0) + if (write_object_file_flags(buf->buf, buf->len, OBJ_TAG, result, + compat_oid, 0) < 0) return error(_("unable to write tag file")); return 0; } @@ -291,11 +328,11 @@ static void create_tag(const struct object_id *object, const char *object_ref, struct strbuf buf = STRBUF_INIT; strbuf_addch(&buf, '\n'); if (opt->cleanup_mode == CLEANUP_ALL) - strbuf_commented_addf(&buf, comment_line_char, - _(tag_template), tag, comment_line_char); + strbuf_commented_addf(&buf, comment_line_str, + _(tag_template), tag, comment_line_str); else - strbuf_commented_addf(&buf, comment_line_char, - _(tag_template_nocleanup), tag, comment_line_char); + strbuf_commented_addf(&buf, comment_line_str, + _(tag_template_nocleanup), tag, comment_line_str); write_or_die(fd, buf.buf, buf.len); strbuf_release(&buf); } @@ -310,7 +347,7 @@ static void create_tag(const struct object_id *object, const char *object_ref, if (opt->cleanup_mode != CLEANUP_NONE) strbuf_stripspace(buf, - opt->cleanup_mode == CLEANUP_ALL ? comment_line_char : '\0'); + opt->cleanup_mode == CLEANUP_ALL ? comment_line_str : NULL); if (!opt->message_given && !buf->len) die(_("no tag message?")); @@ -530,7 +567,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) struct column_options copts; memset(&copts, 0, sizeof(copts)); copts.padding = 2; - run_column_filter(colopts, &copts); + if (run_column_filter(colopts, &copts)) + die(_("could not start 'git column'")); } filter.name_patterns = argv; ret = list_tags(&filter, sorting, &format); diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index e0a701f2b3..f1c85a00ae 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -679,13 +679,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED) use(the_hash_algo->rawsz); /* Write the last part of the buffer to stdout */ - while (len) { - int ret = xwrite(1, buffer + offset, len); - if (ret <= 0) - break; - len -= ret; - offset += ret; - } + write_in_full(1, buffer + offset, len); /* All done */ return has_errors; diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 61338a01ec..e46afbc46d 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -9,8 +9,8 @@ #include "repository.h" static const char * const git_update_ref_usage[] = { - N_("git update-ref [<options>] -d <refname> [<old-val>]"), - N_("git update-ref [<options>] <refname> <new-val> [<old-val>]"), + N_("git update-ref [<options>] -d <refname> [<old-oid>]"), + N_("git update-ref [<options>] <refname> <new-oid> [<old-oid>]"), N_("git update-ref [<options>] --stdin [-z]"), NULL }; @@ -77,14 +77,14 @@ static char *parse_refname(const char **next) } /* - * The value being parsed is <oldvalue> (as opposed to <newvalue>; the + * The value being parsed is <old-oid> (as opposed to <new-oid>; the * difference affects which error messages are generated): */ #define PARSE_SHA1_OLD 0x01 /* * For backwards compatibility, accept an empty string for update's - * <newvalue> in binary mode to be equivalent to specifying zeros. + * <new-oid> in binary mode to be equivalent to specifying zeros. */ #define PARSE_SHA1_ALLOW_EMPTY 0x02 @@ -140,7 +140,7 @@ static int parse_next_oid(const char **next, const char *end, goto invalid; } else if (flags & PARSE_SHA1_ALLOW_EMPTY) { /* With -z, treat an empty value as all zeros: */ - warning("%s %s: missing <newvalue>, treating as zero", + warning("%s %s: missing <new-oid>, treating as zero", command, refname); oidclr(oid); } else { @@ -158,14 +158,14 @@ static int parse_next_oid(const char **next, const char *end, invalid: die(flags & PARSE_SHA1_OLD ? - "%s %s: invalid <oldvalue>: %s" : - "%s %s: invalid <newvalue>: %s", + "%s %s: invalid <old-oid>: %s" : + "%s %s: invalid <new-oid>: %s", command, refname, arg.buf); eof: die(flags & PARSE_SHA1_OLD ? - "%s %s: unexpected end of input when reading <oldvalue>" : - "%s %s: unexpected end of input when reading <newvalue>", + "%s %s: unexpected end of input when reading <old-oid>" : + "%s %s: unexpected end of input when reading <new-oid>", command, refname); } @@ -194,7 +194,7 @@ static void parse_cmd_update(struct ref_transaction *transaction, if (parse_next_oid(&next, end, &new_oid, "update", refname, PARSE_SHA1_ALLOW_EMPTY)) - die("update %s: missing <newvalue>", refname); + die("update %s: missing <new-oid>", refname); have_old = !parse_next_oid(&next, end, &old_oid, "update", refname, PARSE_SHA1_OLD); @@ -225,10 +225,10 @@ static void parse_cmd_create(struct ref_transaction *transaction, die("create: missing <ref>"); if (parse_next_oid(&next, end, &new_oid, "create", refname, 0)) - die("create %s: missing <newvalue>", refname); + die("create %s: missing <new-oid>", refname); if (is_null_oid(&new_oid)) - die("create %s: zero <newvalue>", refname); + die("create %s: zero <new-oid>", refname); if (*next != line_termination) die("create %s: extra input: %s", refname, next); @@ -260,7 +260,7 @@ static void parse_cmd_delete(struct ref_transaction *transaction, have_old = 0; } else { if (is_null_oid(&old_oid)) - die("delete %s: zero <oldvalue>", refname); + die("delete %s: zero <old-oid>", refname); have_old = 1; } diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c index 9b021ef026..15afb97260 100644 --- a/builtin/upload-pack.c +++ b/builtin/upload-pack.c @@ -8,6 +8,7 @@ #include "replace-object.h" #include "upload-pack.h" #include "serve.h" +#include "commit.h" static const char * const upload_pack_usage[] = { N_("git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n" @@ -37,6 +38,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix) packet_trace_identity("upload-pack"); disable_replace_refs(); + save_commit_buffer = 0; argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0); diff --git a/builtin/worktree.c b/builtin/worktree.c index 9c76b62b02..7c6c72536b 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -365,12 +365,12 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir) if (!git_configset_get_bool(&cs, "core.bare", &bare) && bare && git_config_set_multivar_in_file_gently( - to_file, "core.bare", NULL, "true", 0)) + to_file, "core.bare", NULL, "true", NULL, 0)) error(_("failed to unset '%s' in '%s'"), "core.bare", to_file); if (!git_configset_get(&cs, "core.worktree") && git_config_set_in_file_gently(to_file, - "core.worktree", NULL)) + "core.worktree", NULL, NULL)) error(_("failed to unset '%s' in '%s'"), "core.worktree", to_file); @@ -657,7 +657,7 @@ static int can_use_local_refs(const struct add_opts *opts) strbuf_add_real_path(&path, get_worktree_git_dir(NULL)); strbuf_addstr(&path, "/HEAD"); strbuf_read_file(&contents, path.buf, 64); - strbuf_stripspace(&contents, 0); + strbuf_stripspace(&contents, NULL); strbuf_strip_suffix(&contents, "\n"); warning(_("HEAD points to an invalid (or orphaned) reference.\n" diff --git a/cache-tree.c b/cache-tree.c index 64678fe199..387c0a3e5b 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -447,7 +447,7 @@ static int update_one(struct cache_tree *it, hash_object_file(the_hash_algo, buffer.buf, buffer.len, OBJ_TREE, &it->oid); } else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE, - &it->oid, flags & WRITE_TREE_SILENT + &it->oid, NULL, flags & WRITE_TREE_SILENT ? HASH_SILENT : 0)) { strbuf_release(&buffer); return -1; @@ -769,7 +769,7 @@ static void prime_cache_tree_rec(struct repository *r, oidcpy(&it->oid, &tree->object.oid); - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); cnt = 0; while (tree_entry(&desc, &entry)) { if (!S_ISDIR(entry.mode)) @@ -778,8 +778,8 @@ static void prime_cache_tree_rec(struct repository *r, struct cache_tree_sub *sub; struct tree *subtree = lookup_tree(r, &entry.oid); - if (!subtree->object.parsed) - parse_tree(subtree); + if (parse_tree(subtree) < 0) + exit(128); sub = cache_tree_sub(it, entry.path); sub->cache_tree = cache_tree(); @@ -367,7 +367,7 @@ linux-musl) MAKEFLAGS="$MAKEFLAGS NO_REGEX=Yes ICONV_OMITS_BOM=Yes" MAKEFLAGS="$MAKEFLAGS GIT_TEST_UTF8_LOCALE=C.UTF-8" ;; -linux-leaks) +linux-leaks|linux-reftable-leaks) export SANITIZE=leak export GIT_TEST_PASSING_SANITIZE_LEAK=true export GIT_TEST_SANITIZE_LEAK_LOG=true diff --git a/ci/run-build-and-minimal-fuzzers.sh b/ci/run-build-and-minimal-fuzzers.sh index 8ba486f659..a51076d18d 100755 --- a/ci/run-build-and-minimal-fuzzers.sh +++ b/ci/run-build-and-minimal-fuzzers.sh @@ -12,7 +12,7 @@ group "Build fuzzers" make \ LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \ fuzz-all -for fuzzer in commit-graph date pack-headers pack-idx ; do +for fuzzer in commit-graph config date pack-headers pack-idx ; 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 7a1466b868..c192bd613c 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -37,6 +37,9 @@ linux-clang) linux-sha256) export GIT_TEST_DEFAULT_HASH=sha256 ;; +linux-reftable|linux-reftable-leaks|osx-reftable) + export GIT_TEST_DEFAULT_REF_FORMAT=reftable + ;; pedantic) # Don't run the tests; we only care about whether Git can be # built. @@ -182,6 +182,8 @@ void print_columns(const struct string_list *list, unsigned int colopts, { struct column_options nopts; + if (opts && (0 > opts->padding)) + BUG("padding must be non-negative"); if (!list->nr) return; assert((colopts & COL_ENABLE_MASK) != COL_AUTO); @@ -361,6 +363,8 @@ int run_column_filter(int colopts, const struct column_options *opts) { struct strvec *argv; + if (opts && (0 > opts->padding)) + BUG("padding must be non-negative"); if (fd_out != -1) return -1; diff --git a/commit-reach.c b/commit-reach.c index ecc913fc99..8f9b008f87 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -49,13 +49,14 @@ static int queue_has_nonstale(struct prio_queue *queue) } /* all input commits in one and twos[] must have been parsed! */ -static struct commit_list *paint_down_to_common(struct repository *r, - struct commit *one, int n, - struct commit **twos, - timestamp_t min_generation) +static int paint_down_to_common(struct repository *r, + struct commit *one, int n, + struct commit **twos, + timestamp_t min_generation, + int ignore_missing_commits, + struct commit_list **result) { struct prio_queue queue = { compare_commits_by_gen_then_commit_date }; - struct commit_list *result = NULL; int i; timestamp_t last_gen = GENERATION_NUMBER_INFINITY; @@ -64,8 +65,8 @@ static struct commit_list *paint_down_to_common(struct repository *r, one->object.flags |= PARENT1; if (!n) { - commit_list_append(one, &result); - return result; + commit_list_append(one, result); + return 0; } prio_queue_put(&queue, one); @@ -93,7 +94,7 @@ static struct commit_list *paint_down_to_common(struct repository *r, if (flags == (PARENT1 | PARENT2)) { if (!(commit->object.flags & RESULT)) { commit->object.flags |= RESULT; - commit_list_insert_by_date(commit, &result); + commit_list_insert_by_date(commit, result); } /* Mark parents of a found merge stale */ flags |= STALE; @@ -104,67 +105,97 @@ static struct commit_list *paint_down_to_common(struct repository *r, parents = parents->next; if ((p->object.flags & flags) == flags) continue; - if (repo_parse_commit(r, p)) - return NULL; + if (repo_parse_commit(r, p)) { + clear_prio_queue(&queue); + free_commit_list(*result); + *result = NULL; + /* + * At this stage, we know that the commit is + * missing: `repo_parse_commit()` uses + * `OBJECT_INFO_DIE_IF_CORRUPT` and therefore + * corrupt commits would already have been + * dispatched with a `die()`. + */ + if (ignore_missing_commits) + return 0; + return error(_("could not parse commit %s"), + oid_to_hex(&p->object.oid)); + } p->object.flags |= flags; prio_queue_put(&queue, p); } } clear_prio_queue(&queue); - return result; + return 0; } -static struct commit_list *merge_bases_many(struct repository *r, - struct commit *one, int n, - struct commit **twos) +static int merge_bases_many(struct repository *r, + struct commit *one, int n, + struct commit **twos, + struct commit_list **result) { struct commit_list *list = NULL; - struct commit_list *result = NULL; int i; for (i = 0; i < n; i++) { - if (one == twos[i]) + if (one == twos[i]) { /* * We do not mark this even with RESULT so we do not * have to clean it up. */ - return commit_list_insert(one, &result); + *result = commit_list_insert(one, result); + return 0; + } } + if (!one) + return 0; if (repo_parse_commit(r, one)) - return NULL; + return error(_("could not parse commit %s"), + oid_to_hex(&one->object.oid)); for (i = 0; i < n; i++) { + if (!twos[i]) + return 0; if (repo_parse_commit(r, twos[i])) - return NULL; + return error(_("could not parse commit %s"), + oid_to_hex(&twos[i]->object.oid)); } - list = paint_down_to_common(r, one, n, twos, 0); + if (paint_down_to_common(r, one, n, twos, 0, 0, &list)) { + free_commit_list(list); + return -1; + } while (list) { struct commit *commit = pop_commit(&list); if (!(commit->object.flags & STALE)) - commit_list_insert_by_date(commit, &result); + commit_list_insert_by_date(commit, result); } - return result; + return 0; } -struct commit_list *get_octopus_merge_bases(struct commit_list *in) +int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result) { - struct commit_list *i, *j, *k, *ret = NULL; + struct commit_list *i, *j, *k; if (!in) - return ret; + return 0; - commit_list_insert(in->item, &ret); + commit_list_insert(in->item, result); for (i = in->next; i; i = i->next) { struct commit_list *new_commits = NULL, *end = NULL; - for (j = ret; j; j = j->next) { - struct commit_list *bases; - bases = repo_get_merge_bases(the_repository, i->item, - j->item); + for (j = *result; j; j = j->next) { + struct commit_list *bases = NULL; + if (repo_get_merge_bases(the_repository, i->item, + j->item, &bases) < 0) { + free_commit_list(bases); + free_commit_list(*result); + *result = NULL; + return -1; + } if (!new_commits) new_commits = bases; else @@ -172,10 +203,10 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in) for (k = bases; k; k = k->next) end = k; } - free_commit_list(ret); - ret = new_commits; + free_commit_list(*result); + *result = new_commits; } - return ret; + return 0; } static int remove_redundant_no_gen(struct repository *r, @@ -193,7 +224,7 @@ static int remove_redundant_no_gen(struct repository *r, for (i = 0; i < cnt; i++) repo_parse_commit(r, array[i]); for (i = 0; i < cnt; i++) { - struct commit_list *common; + struct commit_list *common = NULL; timestamp_t min_generation = commit_graph_generation(array[i]); if (redundant[i]) @@ -209,8 +240,16 @@ static int remove_redundant_no_gen(struct repository *r, if (curr_generation < min_generation) min_generation = curr_generation; } - common = paint_down_to_common(r, array[i], filled, - work, min_generation); + if (paint_down_to_common(r, array[i], filled, + work, min_generation, 0, &common)) { + clear_commit_marks(array[i], all_flags); + clear_commit_marks_many(filled, work, all_flags); + free_commit_list(common); + free(work); + free(redundant); + free(filled_index); + return -1; + } if (array[i]->object.flags & PARENT2) redundant[i] = 1; for (j = 0; j < filled; j++) @@ -375,69 +414,77 @@ static int remove_redundant(struct repository *r, struct commit **array, int cnt return remove_redundant_no_gen(r, array, cnt); } -static struct commit_list *get_merge_bases_many_0(struct repository *r, - struct commit *one, - int n, - struct commit **twos, - int cleanup) +static int get_merge_bases_many_0(struct repository *r, + struct commit *one, + int n, + struct commit **twos, + int cleanup, + struct commit_list **result) { struct commit_list *list; struct commit **rslt; - struct commit_list *result; int cnt, i; - result = merge_bases_many(r, one, n, twos); + if (merge_bases_many(r, one, n, twos, result) < 0) + return -1; for (i = 0; i < n; i++) { if (one == twos[i]) - return result; + return 0; } - if (!result || !result->next) { + if (!*result || !(*result)->next) { if (cleanup) { clear_commit_marks(one, all_flags); clear_commit_marks_many(n, twos, all_flags); } - return result; + return 0; } /* There are more than one */ - cnt = commit_list_count(result); + cnt = commit_list_count(*result); CALLOC_ARRAY(rslt, cnt); - for (list = result, i = 0; list; list = list->next) + for (list = *result, i = 0; list; list = list->next) rslt[i++] = list->item; - free_commit_list(result); + free_commit_list(*result); + *result = NULL; clear_commit_marks(one, all_flags); clear_commit_marks_many(n, twos, all_flags); cnt = remove_redundant(r, rslt, cnt); - result = NULL; + if (cnt < 0) { + free(rslt); + return -1; + } for (i = 0; i < cnt; i++) - commit_list_insert_by_date(rslt[i], &result); + commit_list_insert_by_date(rslt[i], result); free(rslt); - return result; + return 0; } -struct commit_list *repo_get_merge_bases_many(struct repository *r, - struct commit *one, - int n, - struct commit **twos) +int repo_get_merge_bases_many(struct repository *r, + struct commit *one, + int n, + struct commit **twos, + struct commit_list **result) { - return get_merge_bases_many_0(r, one, n, twos, 1); + return get_merge_bases_many_0(r, one, n, twos, 1, result); } -struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r, - struct commit *one, - int n, - struct commit **twos) +int repo_get_merge_bases_many_dirty(struct repository *r, + struct commit *one, + int n, + struct commit **twos, + struct commit_list **result) { - return get_merge_bases_many_0(r, one, n, twos, 0); + return get_merge_bases_many_0(r, one, n, twos, 0, result); } -struct commit_list *repo_get_merge_bases(struct repository *r, - struct commit *one, - struct commit *two) +int repo_get_merge_bases(struct repository *r, + struct commit *one, + struct commit *two, + struct commit_list **result) { - return get_merge_bases_many_0(r, one, 1, &two, 1); + return get_merge_bases_many_0(r, one, 1, &two, 1, result); } /* @@ -460,11 +507,13 @@ int repo_is_descendant_of(struct repository *r, } else { while (with_commit) { struct commit *other; + int ret; other = with_commit->item; with_commit = with_commit->next; - if (repo_in_merge_bases_many(r, other, 1, &commit)) - return 1; + ret = repo_in_merge_bases_many(r, other, 1, &commit, 0); + if (ret) + return ret; } return 0; } @@ -474,17 +523,18 @@ int repo_is_descendant_of(struct repository *r, * Is "commit" an ancestor of one of the "references"? */ int repo_in_merge_bases_many(struct repository *r, struct commit *commit, - int nr_reference, struct commit **reference) + int nr_reference, struct commit **reference, + int ignore_missing_commits) { - struct commit_list *bases; + struct commit_list *bases = NULL; int ret = 0, i; timestamp_t generation, max_generation = GENERATION_NUMBER_ZERO; if (repo_parse_commit(r, commit)) - return ret; + return ignore_missing_commits ? 0 : -1; for (i = 0; i < nr_reference; i++) { if (repo_parse_commit(r, reference[i])) - return ret; + return ignore_missing_commits ? 0 : -1; generation = commit_graph_generation(reference[i]); if (generation > max_generation) @@ -495,10 +545,11 @@ int repo_in_merge_bases_many(struct repository *r, struct commit *commit, if (generation > max_generation) return ret; - bases = paint_down_to_common(r, commit, - nr_reference, reference, - generation); - if (commit->object.flags & PARENT2) + if (paint_down_to_common(r, commit, + nr_reference, reference, + generation, ignore_missing_commits, &bases)) + ret = -1; + else if (commit->object.flags & PARENT2) ret = 1; clear_commit_marks(commit, all_flags); clear_commit_marks_many(nr_reference, reference, all_flags); @@ -551,6 +602,10 @@ struct commit_list *reduce_heads(struct commit_list *heads) } } num_head = remove_redundant(the_repository, array, num_head); + if (num_head < 0) { + free(array); + return NULL; + } for (i = 0; i < num_head; i++) tail = &commit_list_insert(array[i], tail)->next; free(array); @@ -593,6 +648,8 @@ int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid) commit_list_insert(old_commit, &old_commit_list); ret = repo_is_descendant_of(the_repository, new_commit, old_commit_list); + if (ret < 0) + exit(128); free_commit_list(old_commit_list); return ret; } diff --git a/commit-reach.h b/commit-reach.h index 35c4da4948..bf63cc468f 100644 --- a/commit-reach.h +++ b/commit-reach.h @@ -9,18 +9,21 @@ struct ref_filter; struct object_id; struct object_array; -struct commit_list *repo_get_merge_bases(struct repository *r, - struct commit *rev1, - struct commit *rev2); -struct commit_list *repo_get_merge_bases_many(struct repository *r, - struct commit *one, int n, - struct commit **twos); +int repo_get_merge_bases(struct repository *r, + struct commit *rev1, + struct commit *rev2, + struct commit_list **result); +int repo_get_merge_bases_many(struct repository *r, + struct commit *one, int n, + struct commit **twos, + struct commit_list **result); /* To be used only when object flags after this call no longer matter */ -struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r, - struct commit *one, int n, - struct commit **twos); +int repo_get_merge_bases_many_dirty(struct repository *r, + struct commit *one, int n, + struct commit **twos, + struct commit_list **result); -struct commit_list *get_octopus_merge_bases(struct commit_list *in); +int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result); int repo_is_descendant_of(struct repository *r, struct commit *commit, @@ -30,7 +33,8 @@ int repo_in_merge_bases(struct repository *r, struct commit *reference); int repo_in_merge_bases_many(struct repository *r, struct commit *commit, - int nr_reference, struct commit **reference); + int nr_reference, struct commit **reference, + int ignore_missing_commits); /* * Takes a list of commits and returns a new list where those @@ -27,6 +27,7 @@ #include "tree.h" #include "hook.h" #include "parse.h" +#include "object-file-convert.h" static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **); @@ -1052,7 +1053,7 @@ struct commit *get_fork_point(const char *refname, struct commit *commit) { struct object_id oid; struct rev_collect revs; - struct commit_list *bases; + struct commit_list *bases = NULL; int i; struct commit *ret = NULL; char *full_refname; @@ -1077,8 +1078,9 @@ struct commit *get_fork_point(const char *refname, struct commit *commit) for (i = 0; i < revs.nr; i++) revs.commit[i]->object.flags &= ~TMP_MARK; - bases = repo_get_merge_bases_many(the_repository, commit, revs.nr, - revs.commit); + if (repo_get_merge_bases_many(the_repository, commit, revs.nr, + revs.commit, &bases) < 0) + exit(128); /* * There should be one and only one merge base, when we found @@ -1112,12 +1114,11 @@ static const char *gpg_sig_headers[] = { "gpgsig-sha256", }; -int sign_with_header(struct strbuf *buf, const char *keyid) +int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct git_hash_algo *algo) { - struct strbuf sig = STRBUF_INIT; int inspos, copypos; const char *eoh; - const char *gpg_sig_header = gpg_sig_headers[hash_algo_by_ptr(the_hash_algo)]; + const char *gpg_sig_header = gpg_sig_headers[hash_algo_by_ptr(algo)]; int gpg_sig_header_len = strlen(gpg_sig_header); /* find the end of the header */ @@ -1127,15 +1128,8 @@ int sign_with_header(struct strbuf *buf, const char *keyid) else inspos = eoh - buf->buf + 1; - if (!keyid || !*keyid) - keyid = get_signing_key(); - if (sign_buffer(buf, &sig, keyid)) { - strbuf_release(&sig); - return -1; - } - - for (copypos = 0; sig.buf[copypos]; ) { - const char *bol = sig.buf + copypos; + for (copypos = 0; sig->buf[copypos]; ) { + const char *bol = sig->buf + copypos; const char *eol = strchrnul(bol, '\n'); int len = (eol - bol) + !!*eol; @@ -1148,11 +1142,17 @@ int sign_with_header(struct strbuf *buf, const char *keyid) inspos += len; copypos += len; } - strbuf_release(&sig); return 0; } - +static int sign_commit_to_strbuf(struct strbuf *sig, struct strbuf *buf, const char *keyid) +{ + if (!keyid || !*keyid) + keyid = get_signing_key(); + if (sign_buffer(buf, sig, keyid)) + return -1; + return 0; +} int parse_signed_commit(const struct commit *commit, struct strbuf *payload, struct strbuf *signature, @@ -1368,6 +1368,39 @@ void append_merge_tag_headers(struct commit_list *parents, } } +static int convert_commit_extra_headers(struct commit_extra_header *orig, + struct commit_extra_header **result) +{ + const struct git_hash_algo *compat = the_repository->compat_hash_algo; + const struct git_hash_algo *algo = the_repository->hash_algo; + struct commit_extra_header *extra = NULL, **tail = &extra; + struct strbuf out = STRBUF_INIT; + while (orig) { + struct commit_extra_header *new; + CALLOC_ARRAY(new, 1); + if (!strcmp(orig->key, "mergetag")) { + if (convert_object_file(&out, algo, compat, + orig->value, orig->len, + OBJ_TAG, 1)) { + free(new); + free_commit_extra_headers(extra); + return -1; + } + new->key = xstrdup("mergetag"); + new->value = strbuf_detach(&out, &new->len); + } else { + new->key = xstrdup(orig->key); + new->len = orig->len; + new->value = xmemdupz(orig->value, orig->len); + } + *tail = new; + tail = &new->next; + orig = orig->next; + } + *result = extra; + return 0; +} + static void add_extra_header(struct strbuf *buffer, struct commit_extra_header *extra) { @@ -1611,70 +1644,169 @@ N_("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" "variable i18n.commitEncoding to the encoding your project uses.\n"); -int commit_tree_extended(const char *msg, size_t msg_len, - const struct object_id *tree, - struct commit_list *parents, struct object_id *ret, - const char *author, const char *committer, - const char *sign_commit, - struct commit_extra_header *extra) +static void write_commit_tree(struct strbuf *buffer, const char *msg, size_t msg_len, + const struct object_id *tree, + const struct object_id *parents, size_t parents_len, + const char *author, const char *committer, + struct commit_extra_header *extra) { - int result; int encoding_is_utf8; - struct strbuf buffer; - - assert_oid_type(tree, OBJ_TREE); - - if (memchr(msg, '\0', msg_len)) - return error("a NUL byte in commit log message not allowed."); + size_t i; /* Not having i18n.commitencoding is the same as having utf-8 */ encoding_is_utf8 = is_encoding_utf8(git_commit_encoding); - strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */ - strbuf_addf(&buffer, "tree %s\n", oid_to_hex(tree)); + strbuf_grow(buffer, 8192); /* should avoid reallocs for the headers */ + strbuf_addf(buffer, "tree %s\n", oid_to_hex(tree)); /* * NOTE! This ordering means that the same exact tree merged with a * different order of parents will be a _different_ changeset even * if everything else stays the same. */ - while (parents) { - struct commit *parent = pop_commit(&parents); - strbuf_addf(&buffer, "parent %s\n", - oid_to_hex(&parent->object.oid)); - } + for (i = 0; i < parents_len; i++) + strbuf_addf(buffer, "parent %s\n", oid_to_hex(&parents[i])); /* Person/date information */ if (!author) author = git_author_info(IDENT_STRICT); - strbuf_addf(&buffer, "author %s\n", author); + strbuf_addf(buffer, "author %s\n", author); if (!committer) committer = git_committer_info(IDENT_STRICT); - strbuf_addf(&buffer, "committer %s\n", committer); + strbuf_addf(buffer, "committer %s\n", committer); if (!encoding_is_utf8) - strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding); + strbuf_addf(buffer, "encoding %s\n", git_commit_encoding); while (extra) { - add_extra_header(&buffer, extra); + add_extra_header(buffer, extra); extra = extra->next; } - strbuf_addch(&buffer, '\n'); + strbuf_addch(buffer, '\n'); /* And add the comment */ - strbuf_add(&buffer, msg, msg_len); + strbuf_add(buffer, msg, msg_len); +} - /* And check the encoding */ - if (encoding_is_utf8 && !verify_utf8(&buffer)) - fprintf(stderr, _(commit_utf8_warn)); +int commit_tree_extended(const char *msg, size_t msg_len, + const struct object_id *tree, + struct commit_list *parents, struct object_id *ret, + const char *author, const char *committer, + const char *sign_commit, + struct commit_extra_header *extra) +{ + struct repository *r = the_repository; + int result = 0; + int encoding_is_utf8; + struct strbuf buffer = STRBUF_INIT, compat_buffer = STRBUF_INIT; + struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT; + struct object_id *parent_buf = NULL, *compat_oid = NULL; + struct object_id compat_oid_buf; + size_t i, nparents; + + /* Not having i18n.commitencoding is the same as having utf-8 */ + encoding_is_utf8 = is_encoding_utf8(git_commit_encoding); + + assert_oid_type(tree, OBJ_TREE); - if (sign_commit && sign_with_header(&buffer, sign_commit)) { + if (memchr(msg, '\0', msg_len)) + return error("a NUL byte in commit log message not allowed."); + + nparents = commit_list_count(parents); + CALLOC_ARRAY(parent_buf, nparents); + i = 0; + while (parents) { + struct commit *parent = pop_commit(&parents); + oidcpy(&parent_buf[i++], &parent->object.oid); + } + + write_commit_tree(&buffer, msg, msg_len, tree, parent_buf, nparents, author, committer, extra); + if (sign_commit && sign_commit_to_strbuf(&sig, &buffer, sign_commit)) { result = -1; goto out; } + if (r->compat_hash_algo) { + struct commit_extra_header *compat_extra = NULL; + struct object_id mapped_tree; + struct object_id *mapped_parents; + + CALLOC_ARRAY(mapped_parents, nparents); - result = write_object_file(buffer.buf, buffer.len, OBJ_COMMIT, ret); + if (repo_oid_to_algop(r, tree, r->compat_hash_algo, &mapped_tree)) { + result = -1; + free(mapped_parents); + goto out; + } + for (i = 0; i < nparents; i++) + if (repo_oid_to_algop(r, &parent_buf[i], r->compat_hash_algo, &mapped_parents[i])) { + result = -1; + free(mapped_parents); + goto out; + } + if (convert_commit_extra_headers(extra, &compat_extra)) { + result = -1; + free(mapped_parents); + goto out; + } + write_commit_tree(&compat_buffer, msg, msg_len, &mapped_tree, + mapped_parents, nparents, author, committer, compat_extra); + free_commit_extra_headers(compat_extra); + free(mapped_parents); + + if (sign_commit && sign_commit_to_strbuf(&compat_sig, &compat_buffer, sign_commit)) { + result = -1; + goto out; + } + } + + if (sign_commit) { + struct sig_pairs { + struct strbuf *sig; + const struct git_hash_algo *algo; + } bufs [2] = { + { &compat_sig, r->compat_hash_algo }, + { &sig, r->hash_algo }, + }; + int i; + + /* + * We write algorithms in the order they were implemented in + * Git to produce a stable hash when multiple algorithms are + * used. + */ + if (r->compat_hash_algo && hash_algo_by_ptr(bufs[0].algo) > hash_algo_by_ptr(bufs[1].algo)) + SWAP(bufs[0], bufs[1]); + + /* + * We traverse each algorithm in order, and apply the signature + * to each buffer. + */ + for (i = 0; i < ARRAY_SIZE(bufs); i++) { + if (!bufs[i].algo) + continue; + add_header_signature(&buffer, bufs[i].sig, bufs[i].algo); + if (r->compat_hash_algo) + add_header_signature(&compat_buffer, bufs[i].sig, bufs[i].algo); + } + } + + /* And check the encoding. */ + if (encoding_is_utf8 && (!verify_utf8(&buffer) || !verify_utf8(&compat_buffer))) + fprintf(stderr, _(commit_utf8_warn)); + + if (r->compat_hash_algo) { + hash_object_file(r->compat_hash_algo, compat_buffer.buf, compat_buffer.len, + OBJ_COMMIT, &compat_oid_buf); + compat_oid = &compat_oid_buf; + } + + result = write_object_file_flags(buffer.buf, buffer.len, OBJ_COMMIT, + ret, compat_oid, 0); out: + free(parent_buf); strbuf_release(&buffer); + strbuf_release(&compat_buffer); + strbuf_release(&sig); + strbuf_release(&compat_sig); return result; } @@ -1796,7 +1928,8 @@ size_t ignored_log_message_bytes(const char *buf, size_t len) else next_line++; - if (buf[bol] == comment_line_char || buf[bol] == '\n') { + if (starts_with_mem(buf + bol, cutoff - bol, comment_line_str) || + buf[bol] == '\n') { /* is this the first of the run of comments? */ if (!boc) boc = bol; @@ -370,5 +370,6 @@ int parse_buffer_signed_by_header(const char *buffer, struct strbuf *payload, struct strbuf *signature, const struct git_hash_algo *algop); +int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct git_hash_algo *algo); #endif /* COMMIT_H */ diff --git a/compat/compiler.h b/compat/compiler.h index 10dbb65937..e9ad9db84f 100644 --- a/compat/compiler.h +++ b/compat/compiler.h @@ -1,7 +1,6 @@ #ifndef COMPILER_H #define COMPILER_H -#include "git-compat-util.h" #include "strbuf.h" #ifdef __GLIBC__ diff --git a/compat/disk.h b/compat/disk.h index 6c979c27d8..23bc1bef86 100644 --- a/compat/disk.h +++ b/compat/disk.h @@ -1,7 +1,6 @@ #ifndef COMPAT_DISK_H #define COMPAT_DISK_H -#include "git-compat-util.h" #include "abspath.h" #include "gettext.h" diff --git a/compat/mingw.c b/compat/mingw.c index 320fb99a90..4876344b5b 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -3158,3 +3158,22 @@ int uname(struct utsname *buf) "%u", (v >> 16) & 0x7fff); return 0; } + +int mingw_have_unix_sockets(void) +{ + SC_HANDLE scm, srvc; + SERVICE_STATUS_PROCESS status; + DWORD bytes; + int ret = 0; + scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); + if (scm) { + srvc = OpenServiceA(scm, "afunix", SERVICE_QUERY_STATUS); + if (srvc) { + if(QueryServiceStatusEx(srvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &bytes)) + ret = status.dwCurrentState == SERVICE_RUNNING; + CloseServiceHandle(srvc); + } + CloseServiceHandle(scm); + } + return ret; +} diff --git a/compat/mingw.h b/compat/mingw.h index 6aec50e412..27b61284f4 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -631,3 +631,9 @@ void open_in_gdb(void); * Used by Pthread API implementation for Windows */ int err_win_to_posix(DWORD winerr); + +#ifndef NO_UNIX_SOCKETS +int mingw_have_unix_sockets(void); +#undef have_unix_sockets +#define have_unix_sockets mingw_have_unix_sockets +#endif @@ -817,7 +817,8 @@ static int get_next_char(struct config_source *cs) static char *parse_value(struct config_source *cs) { - int quote = 0, comment = 0, space = 0; + int quote = 0, comment = 0; + size_t trim_len = 0; strbuf_reset(&cs->value); for (;;) { @@ -827,13 +828,17 @@ static char *parse_value(struct config_source *cs) cs->linenr--; return NULL; } + if (trim_len) + strbuf_setlen(&cs->value, trim_len); return cs->value.buf; } if (comment) continue; if (isspace(c) && !quote) { + if (!trim_len) + trim_len = cs->value.len; if (cs->value.len) - space++; + strbuf_addch(&cs->value, c); continue; } if (!quote) { @@ -842,8 +847,8 @@ static char *parse_value(struct config_source *cs) continue; } } - for (; space; space--) - strbuf_addch(&cs->value, ' '); + if (trim_len) + trim_len = 0; if (c == '\\') { c = get_next_char(cs); switch (c) { @@ -869,7 +874,7 @@ static char *parse_value(struct config_source *cs) continue; } if (c == '"') { - quote = 1-quote; + quote = 1 - quote; continue; } strbuf_addch(&cs->value, c); @@ -1560,24 +1565,29 @@ static int git_default_core_config(const char *var, const char *value, if (!strcmp(var, "core.editor")) return git_config_string(&editor_program, var, value); - if (!strcmp(var, "core.commentchar")) { + if (!strcmp(var, "core.commentchar") || + !strcmp(var, "core.commentstring")) { if (!value) return config_error_nonbool(var); else if (!strcasecmp(value, "auto")) auto_comment_line_char = 1; - else if (value[0] && !value[1]) { - comment_line_char = value[0]; + else if (value[0]) { + if (strchr(value, '\n')) + return error(_("%s cannot contain newline"), var); + comment_line_str = xstrdup(value); auto_comment_line_char = 0; } else - return error(_("core.commentChar should only be one ASCII character")); + return error(_("%s must have at least one character"), var); return 0; } if (!strcmp(var, "core.askpass")) return git_config_string(&askpass_program, var, value); - if (!strcmp(var, "core.excludesfile")) + if (!strcmp(var, "core.excludesfile")) { + free((char *)excludes_file); return git_config_pathname(&excludes_file, var, value); + } if (!strcmp(var, "core.whitespace")) { if (!value) @@ -3001,6 +3011,7 @@ static ssize_t write_section(int fd, const char *key, } static ssize_t write_pair(int fd, const char *key, const char *value, + const char *comment, const struct config_store_data *store) { int i; @@ -3041,7 +3052,11 @@ static ssize_t write_pair(int fd, const char *key, const char *value, strbuf_addch(&sb, value[i]); break; } - strbuf_addf(&sb, "%s\n", quote); + + if (comment) + strbuf_addf(&sb, "%s%s\n", quote, comment); + else + strbuf_addf(&sb, "%s\n", quote); ret = write_in_full(fd, sb.buf, sb.len); strbuf_release(&sb); @@ -3130,9 +3145,9 @@ static void maybe_remove_section(struct config_store_data *store, } int git_config_set_in_file_gently(const char *config_filename, - const char *key, const char *value) + const char *key, const char *comment, const char *value) { - return git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, 0); + return git_config_set_multivar_in_file_gently(config_filename, key, value, NULL, comment, 0); } void git_config_set_in_file(const char *config_filename, @@ -3153,7 +3168,7 @@ int repo_config_set_worktree_gently(struct repository *r, 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, 0); + file, key, value, NULL, NULL, 0); free(file); return ret; } @@ -3168,6 +3183,62 @@ void git_config_set(const char *key, const char *value) } /* + * The ownership rule is that the caller will own the string + * if it receives a piece of memory different from what it passed + * as the parameter. + */ +const char *git_config_prepare_comment_string(const char *comment) +{ + size_t leading_blanks; + + if (!comment) + return NULL; + + if (strchr(comment, '\n')) + die(_("no multi-line comment allowed: '%s'"), comment); + + /* + * If it begins with one or more leading whitespace characters + * followed by '#", the comment string is used as-is. + * + * If it begins with '#', a SP is inserted between the comment + * and the value the comment is about. + * + * Otherwise, the value is followed by a SP followed by '#' + * followed by SP and then the comment string comes. + */ + + leading_blanks = strspn(comment, " \t"); + if (leading_blanks && comment[leading_blanks] == '#') + ; /* use it as-is */ + else if (comment[0] == '#') + comment = xstrfmt(" %s", comment); + else + comment = xstrfmt(" # %s", comment); + + return comment; +} + +static void validate_comment_string(const char *comment) +{ + size_t leading_blanks; + + if (!comment) + return; + /* + * The front-end must have massaged the comment string + * properly before calling us. + */ + if (strchr(comment, '\n')) + BUG("multi-line comments are not permitted: '%s'", comment); + + leading_blanks = strspn(comment, " \t"); + if (!leading_blanks || comment[leading_blanks] != '#') + BUG("comment must begin with one or more SP followed by '#': '%s'", + comment); +} + +/* * If value==NULL, unset in (remove from) config, * if value_pattern!=NULL, disregard key/value pairs where value does not match. * if value_pattern==CONFIG_REGEX_NONE, do not match any existing values @@ -3195,6 +3266,7 @@ void git_config_set(const char *key, const char *value) 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 fd = -1, in_fd = -1; @@ -3205,6 +3277,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, size_t contents_sz; struct config_store_data store = CONFIG_STORE_INIT; + validate_comment_string(comment); + /* parse-key returns negative; flip the sign to feed exit(3) */ ret = 0 - git_config_parse_key(key, &store.key, &store.baselen); if (ret) @@ -3245,7 +3319,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, free(store.key); store.key = xstrdup(key); if (write_section(fd, key, &store) < 0 || - write_pair(fd, key, value, &store) < 0) + write_pair(fd, key, value, comment, &store) < 0) goto write_err_out; } else { struct stat st; @@ -3399,7 +3473,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, if (write_section(fd, key, &store) < 0) goto write_err_out; } - if (write_pair(fd, key, value, &store) < 0) + if (write_pair(fd, key, value, comment, &store) < 0) goto write_err_out; } @@ -3444,7 +3518,7 @@ void git_config_set_multivar_in_file(const char *config_filename, const char *value_pattern, unsigned flags) { if (!git_config_set_multivar_in_file_gently(config_filename, key, value, - value_pattern, flags)) + value_pattern, NULL, flags)) return; if (value) die(_("could not set '%s' to '%s'"), key, value); @@ -3467,7 +3541,7 @@ int repo_config_set_multivar_gently(struct repository *r, const char *key, int res = git_config_set_multivar_in_file_gently(file, key, value, value_pattern, - flags); + NULL, flags); free(file); return res; } @@ -290,7 +290,7 @@ int git_config_pathname(const 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 *); +int git_config_set_in_file_gently(const char *, const char *, const char *, const char *); /** * write config values to a specific config file, takes a key/value pair as @@ -336,7 +336,9 @@ int git_config_parse_key(const char *, char **, size_t *); 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 *, unsigned); +int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned); + +const char *git_config_prepare_comment_string(const char *); /** * takes four parameters: diff --git a/config.mak.uname b/config.mak.uname index dacc95172d..a7607a5676 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -65,9 +65,9 @@ ifeq ($(uname_S),Linux) HAVE_PLATFORM_PROCINFO = YesPlease COMPAT_OBJS += compat/linux/procinfo.o # centos7/rhel7 provides gcc 4.8.5 and zlib 1.2.7. - ifneq ($(findstring .el7.,$(uname_R)),) + ifneq ($(findstring .el7.,$(uname_R)),) BASIC_CFLAGS += -std=c99 - endif + endif endif ifeq ($(uname_S),GNU/kFreeBSD) HAVE_ALLOCA_H = YesPlease @@ -95,13 +95,13 @@ ifeq ($(uname_S),UnixWare) NO_MEMMEM = YesPlease endif ifeq ($(uname_S),SCO_SV) - ifeq ($(uname_R),3.2) + ifeq ($(uname_R),3.2) CFLAGS = -O2 - endif - ifeq ($(uname_R),5) + endif + ifeq ($(uname_R),5) CC = cc BASIC_CFLAGS += -Kthread - endif + endif NEEDS_SOCKET = YesPlease NEEDS_NSL = YesPlease NEEDS_SSL_WITH_CRYPTO = YesPlease @@ -124,19 +124,19 @@ ifeq ($(uname_S),Darwin) # - MacOS 10.0.* and MacOS 10.1.0 = Darwin 1.* # - MacOS 10.x.* = Darwin (x+4).* for (1 <= x) # i.e. "begins with [15678] and a dot" means "10.4.* or older". - ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2) + ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2) OLD_ICONV = UnfortunatelyYes NO_APPLE_COMMON_CRYPTO = YesPlease - endif - ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2) + endif + ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2) NO_STRLCPY = YesPlease - endif - ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -ge 11 && echo 1),1) + endif + ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -ge 11 && echo 1),1) HAVE_GETDELIM = YesPlease - endif - ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -ge 20 && echo 1),1) + endif + ifeq ($(shell test "`expr "$(uname_R)" : '\([0-9][0-9]*\)\.'`" -ge 20 && echo 1),1) OPEN_RETURNS_EINTR = UnfortunatelyYes - endif + endif NO_MEMMEM = YesPlease USE_ST_TIMESPEC = YesPlease HAVE_DEV_TTY = YesPlease @@ -152,12 +152,12 @@ ifeq ($(uname_S),Darwin) # Workaround for `gettext` being keg-only and not even being linked via # `brew link --force gettext`, should be obsolete as of # https://github.com/Homebrew/homebrew-core/pull/53489 - ifeq ($(shell test -d /usr/local/opt/gettext/ && echo y),y) + ifeq ($(shell test -d /usr/local/opt/gettext/ && echo y),y) BASIC_CFLAGS += -I/usr/local/include -I/usr/local/opt/gettext/include BASIC_LDFLAGS += -L/usr/local/lib -L/usr/local/opt/gettext/lib - ifeq ($(shell test -x /usr/local/opt/gettext/bin/msgfmt && echo y),y) + ifeq ($(shell test -x /usr/local/opt/gettext/bin/msgfmt && echo y),y) MSGFMT = /usr/local/opt/gettext/bin/msgfmt - endif + endif # On newer ARM-based machines the default installation path has changed to # /opt/homebrew. Include it in our search paths so that the user does not # have to configure this manually. @@ -165,22 +165,22 @@ ifeq ($(uname_S),Darwin) # Note that we do not employ the same workaround as above where we manually # add gettext. The issue was fixed more than three years ago by now, and at # that point there haven't been any ARM-based Macs yet. - else ifeq ($(shell test -d /opt/homebrew/ && echo y),y) + else ifeq ($(shell test -d /opt/homebrew/ && echo y),y) BASIC_CFLAGS += -I/opt/homebrew/include BASIC_LDFLAGS += -L/opt/homebrew/lib - ifeq ($(shell test -x /opt/homebrew/bin/msgfmt && echo y),y) + ifeq ($(shell test -x /opt/homebrew/bin/msgfmt && echo y),y) MSGFMT = /opt/homebrew/bin/msgfmt - endif - endif + endif + endif # The builtin FSMonitor on MacOS builds upon Simple-IPC. Both require # Unix domain sockets and PThreads. - ifndef NO_PTHREADS - ifndef NO_UNIX_SOCKETS + ifndef NO_PTHREADS + ifndef NO_UNIX_SOCKETS FSMONITOR_DAEMON_BACKEND = darwin FSMONITOR_OS_SETTINGS = darwin - endif - endif + endif + endif BASIC_LDFLAGS += -framework CoreServices endif @@ -196,7 +196,7 @@ ifeq ($(uname_S),SunOS) NO_REGEX = YesPlease NO_MSGFMT_EXTENDED_OPTIONS = YesPlease HAVE_DEV_TTY = YesPlease - ifeq ($(uname_R),5.6) + ifeq ($(uname_R),5.6) SOCKLEN_T = int NO_HSTRERROR = YesPlease NO_IPV6 = YesPlease @@ -206,8 +206,8 @@ ifeq ($(uname_S),SunOS) NO_STRLCPY = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp - endif - ifeq ($(uname_R),5.7) + endif + ifeq ($(uname_R),5.7) NEEDS_RESOLV = YesPlease NO_IPV6 = YesPlease NO_SOCKADDR_STORAGE = YesPlease @@ -216,25 +216,25 @@ ifeq ($(uname_S),SunOS) NO_STRLCPY = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp - endif - ifeq ($(uname_R),5.8) + endif + ifeq ($(uname_R),5.8) NO_UNSETENV = YesPlease NO_SETENV = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp - endif - ifeq ($(uname_R),5.9) + endif + ifeq ($(uname_R),5.9) NO_UNSETENV = YesPlease NO_SETENV = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp - endif + endif INSTALL = /usr/ucb/install TAR = gtar BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ endif ifeq ($(uname_O),Cygwin) - ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4) + ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4) NO_D_TYPE_IN_DIRENT = YesPlease NO_STRCASESTR = YesPlease NO_MEMMEM = YesPlease @@ -245,9 +245,9 @@ ifeq ($(uname_O),Cygwin) # On some boxes NO_MMAP is needed, and not so elsewhere. # Try commenting this out if you suspect MMAP is more efficient NO_MMAP = YesPlease - else + else NO_REGEX = UnfortunatelyYes - endif + endif HAVE_ALLOCA_H = YesPlease NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes @@ -263,25 +263,25 @@ ifeq ($(uname_S),FreeBSD) NEEDS_LIBICONV = YesPlease # Versions up to 10.1 require OLD_ICONV; 10.2 and beyond don't. # A typical version string looks like "10.2-RELEASE". - ifeq ($(shell expr "$(uname_R)" : '[1-9]\.'),2) + ifeq ($(shell expr "$(uname_R)" : '[1-9]\.'),2) OLD_ICONV = YesPlease - endif - ifeq ($(firstword $(subst -, ,$(uname_R))),10.0) + endif + ifeq ($(firstword $(subst -, ,$(uname_R))),10.0) OLD_ICONV = YesPlease - endif - ifeq ($(firstword $(subst -, ,$(uname_R))),10.1) + endif + ifeq ($(firstword $(subst -, ,$(uname_R))),10.1) OLD_ICONV = YesPlease - endif + endif NO_MEMMEM = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease USE_ST_TIMESPEC = YesPlease - ifeq ($(shell expr "$(uname_R)" : '4\.'),2) + ifeq ($(shell expr "$(uname_R)" : '4\.'),2) PTHREAD_LIBS = -pthread NO_UINTMAX_T = YesPlease NO_STRTOUMAX = YesPlease - endif + endif PYTHON_PATH = /usr/local/bin/python PERL_PATH = /usr/local/bin/perl HAVE_PATHS_H = YesPlease @@ -317,9 +317,9 @@ ifeq ($(uname_S),MirBSD) CSPRNG_METHOD = arc4random endif ifeq ($(uname_S),NetBSD) - ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2) + ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2) NEEDS_LIBICONV = YesPlease - endif + endif BASIC_CFLAGS += -I/usr/pkg/include BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib USE_ST_TIMESPEC = YesPlease @@ -343,14 +343,14 @@ ifeq ($(uname_S),AIX) BASIC_CFLAGS += -D_LARGE_FILES FILENO_IS_A_MACRO = UnfortunatelyYes NEED_ACCESS_ROOT_HANDLER = UnfortunatelyYes - ifeq ($(shell expr "$(uname_V)" : '[1234]'),1) + ifeq ($(shell expr "$(uname_V)" : '[1234]'),1) NO_PTHREADS = YesPlease - else + else PTHREAD_LIBS = -lpthread - endif - ifeq ($(shell expr "$(uname_V).$(uname_R)" : '5\.1'),3) + endif + ifeq ($(shell expr "$(uname_V).$(uname_R)" : '5\.1'),3) INLINE = '' - endif + endif GIT_TEST_CMP = cmp endif ifeq ($(uname_S),GNU) @@ -410,29 +410,29 @@ ifeq ($(uname_S),HP-UX) NO_SYS_SELECT_H = YesPlease SNPRINTF_RETURNS_BOGUS = YesPlease NO_NSEC = YesPlease - ifeq ($(uname_R),B.11.00) + ifeq ($(uname_R),B.11.00) NO_INET_NTOP = YesPlease NO_INET_PTON = YesPlease - endif - ifeq ($(uname_R),B.10.20) + endif + ifeq ($(uname_R),B.10.20) # Override HP-UX 11.x setting: INLINE = SOCKLEN_T = size_t NO_PREAD = YesPlease NO_INET_NTOP = YesPlease NO_INET_PTON = YesPlease - endif + endif GIT_TEST_CMP = cmp endif ifeq ($(uname_S),Windows) GIT_VERSION := $(GIT_VERSION).MSVC pathsep = ; # Assume that this is built in Git for Windows' SDK - ifeq (MINGW32,$(MSYSTEM)) + ifeq (MINGW32,$(MSYSTEM)) prefix = /mingw32 - else + else prefix = /mingw64 - endif + endif # Prepend MSVC 64-bit tool-chain to PATH. # # A regular Git Bash *does not* have cl.exe in its $PATH. As there is a @@ -447,7 +447,6 @@ ifeq ($(uname_S),Windows) NO_POLL = YesPlease NO_SYMLINK_HEAD = YesPlease NO_IPV6 = YesPlease - NO_UNIX_SOCKETS = YesPlease NO_SETENV = YesPlease NO_STRCASESTR = YesPlease NO_STRLCPY = YesPlease @@ -550,16 +549,16 @@ ifeq ($(uname_S),Interix) NO_MKDTEMP = YesPlease NO_STRTOUMAX = YesPlease NO_NSEC = YesPlease - ifeq ($(uname_R),3.5) + ifeq ($(uname_R),3.5) NO_INET_NTOP = YesPlease NO_INET_PTON = YesPlease NO_SOCKADDR_STORAGE = YesPlease - endif - ifeq ($(uname_R),5.2) + endif + ifeq ($(uname_R),5.2) NO_INET_NTOP = YesPlease NO_INET_PTON = YesPlease NO_SOCKADDR_STORAGE = YesPlease - endif + endif endif ifeq ($(uname_S),Minix) NO_IPV6 = YesPlease @@ -579,12 +578,12 @@ ifeq ($(uname_S),NONSTOP_KERNEL) # still not compile in c89 mode, due to non-const array initializations. CC = cc -c99 # Build down-rev compatible objects that don't use our new getopt_long. - ifeq ($(uname_R).$(uname_V),J06.21) + ifeq ($(uname_R).$(uname_V),J06.21) CC += -WRVU=J06.20 - endif - ifeq ($(uname_R).$(uname_V),L17.02) + endif + ifeq ($(uname_R).$(uname_V),L17.02) CC += -WRVU=L16.05 - endif + endif # Disable all optimization, seems to result in bad code, with -O or -O2 # or even -O1 (default), /usr/local/libexec/git-core/git-pack-objects # abends on "git push". Needs more investigation. @@ -638,10 +637,22 @@ ifeq ($(uname_S),NONSTOP_KERNEL) SANE_TOOL_PATH = /usr/coreutils/bin:/usr/local/bin SHELL_PATH = /usr/coreutils/bin/bash endif +ifeq ($(uname_S),OS/390) + NO_SYS_POLL_H = YesPlease + NO_STRCASESTR = YesPlease + NO_REGEX = YesPlease + NO_MMAP = YesPlease + NO_NSEC = YesPlease + NO_STRLCPY = YesPlease + NO_MEMMEM = YesPlease + NO_GECOS_IN_PWENT = YesPlease + HAVE_STRINGS_H = YesPlease + NEEDS_MODE_TRANSLATION = YesPlease +endif ifeq ($(uname_S),MINGW) - ifeq ($(shell expr "$(uname_R)" : '1\.'),2) + ifeq ($(shell expr "$(uname_R)" : '1\.'),2) $(error "Building with MSys is no longer supported") - endif + endif pathsep = ; HAVE_ALLOCA_H = YesPlease NO_PREAD = YesPlease @@ -649,7 +660,6 @@ ifeq ($(uname_S),MINGW) NO_LIBGEN_H = YesPlease NO_POLL = YesPlease NO_SYMLINK_HEAD = YesPlease - NO_UNIX_SOCKETS = YesPlease NO_SETENV = YesPlease NO_STRCASESTR = YesPlease NO_STRLCPY = YesPlease @@ -700,22 +710,22 @@ ifeq ($(uname_S),MINGW) # Enable DEP BASIC_LDFLAGS += -Wl,--nxcompat # Enable ASLR (unless debugging) - ifneq (,$(findstring -O,$(filter-out -O0 -Og,$(CFLAGS)))) + ifneq (,$(findstring -O,$(filter-out -O0 -Og,$(CFLAGS)))) BASIC_LDFLAGS += -Wl,--dynamicbase - endif - ifeq (MINGW32,$(MSYSTEM)) + endif + ifeq (MINGW32,$(MSYSTEM)) prefix = /mingw32 HOST_CPU = i686 BASIC_LDFLAGS += -Wl,--pic-executable,-e,_mainCRTStartup - endif - ifeq (MINGW64,$(MSYSTEM)) + endif + ifeq (MINGW64,$(MSYSTEM)) prefix = /mingw64 HOST_CPU = x86_64 BASIC_LDFLAGS += -Wl,--pic-executable,-e,mainCRTStartup - else + else COMPAT_CFLAGS += -D_USE_32BIT_TIME_T BASIC_LDFLAGS += -Wl,--large-address-aware - endif + endif CC = gcc COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY \ -fstack-protector-strong @@ -727,11 +737,11 @@ ifeq ($(uname_S),MINGW) USE_GETTEXT_SCHEME = fallthrough USE_LIBPCRE = YesPlease USE_NED_ALLOCATOR = YesPlease - ifeq (/mingw64,$(subst 32,64,$(prefix))) + ifeq (/mingw64,$(subst 32,64,$(prefix))) # Move system config into top-level /etc/ ETC_GITCONFIG = ../etc/gitconfig ETC_GITATTRIBUTES = ../etc/gitattributes - endif + endif endif ifeq ($(uname_S),QNX) COMPAT_CFLAGS += -DSA_RESTART=0 diff --git a/contrib/coccinelle/xstrncmpz.cocci b/contrib/coccinelle/xstrncmpz.cocci new file mode 100644 index 0000000000..ccb39e2bc0 --- /dev/null +++ b/contrib/coccinelle/xstrncmpz.cocci @@ -0,0 +1,28 @@ +@@ +expression S, T, L; +@@ +( +- strncmp(S, T, L) || S[L] ++ !!xstrncmpz(S, T, L) +| +- strncmp(S, T, L) || S[L] != '\0' ++ !!xstrncmpz(S, T, L) +| +- strncmp(S, T, L) || T[L] ++ !!xstrncmpz(T, S, L) +| +- strncmp(S, T, L) || T[L] != '\0' ++ !!xstrncmpz(T, S, L) +| +- !strncmp(S, T, L) && !S[L] ++ !xstrncmpz(S, T, L) +| +- !strncmp(S, T, L) && S[L] == '\0' ++ !xstrncmpz(S, T, L) +| +- !strncmp(S, T, L) && !T[L] ++ !xstrncmpz(T, S, L) +| +- !strncmp(S, T, L) && T[L] == '\0' ++ !xstrncmpz(T, S, L) +) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 444b3efa63..75193ded4b 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -454,16 +454,18 @@ fi # This function is equivalent to # -# __gitcomp "$(git xxx --git-completion-helper) ..." +# ___git_resolved_builtins=$(git xxx --git-completion-helper) # -# except that the output is cached. Accept 1-3 arguments: +# except that the result of the execution is cached. +# +# Accept 1-3 arguments: # 1: the git command to execute, this is also the cache key +# (use "_" when the command contains spaces, e.g. "remote add" +# becomes "remote_add") # 2: extra options to be added on top (e.g. negative forms) # 3: options to be excluded -__gitcomp_builtin () +__git_resolve_builtins () { - # spaces must be replaced with underscore for multi-word - # commands, e.g. "git remote add" becomes remote_add. local cmd="$1" local incl="${2-}" local excl="${3-}" @@ -489,7 +491,24 @@ __gitcomp_builtin () eval "$var=\"$options\"" fi - __gitcomp "$options" + ___git_resolved_builtins="$options" +} + +# This function is equivalent to +# +# __gitcomp "$(git xxx --git-completion-helper) ..." +# +# except that the output is cached. Accept 1-3 arguments: +# 1: the git command to execute, this is also the cache key +# (use "_" when the command contains spaces, e.g. "remote add" +# becomes "remote_add") +# 2: extra options to be added on top (e.g. negative forms) +# 3: options to be excluded +__gitcomp_builtin () +{ + __git_resolve_builtins "$1" "$2" "$3" + + __gitcomp "$___git_resolved_builtins" } # Variation of __gitcomp_nl () that appends to the existing list of @@ -556,6 +575,26 @@ __gitcomp_file () true } +# Find the current subcommand for commands that follow the syntax: +# +# git <command> <subcommand> +# +# 1: List of possible subcommands. +# 2: Optional subcommand to return when none is found. +__git_find_subcommand () +{ + local subcommand subcommands="$1" default_subcommand="$2" + + for subcommand in $subcommands; do + if [ "$subcommand" = "${words[__git_cmd_idx+1]}" ]; then + echo $subcommand + return + fi + done + + echo $default_subcommand +} + # Execute 'git ls-files', unless the --committable option is specified, in # which case it runs 'git diff-index' to find out the files that can be # committed. It return paths relative to the directory specified in the first @@ -2471,13 +2510,30 @@ _git_rebase () _git_reflog () { - local subcommands="show delete expire" - local subcommand="$(__git_find_on_cmdline "$subcommands")" + local subcommands subcommand - if [ -z "$subcommand" ]; then - __gitcomp "$subcommands" - else - __git_complete_refs + __git_resolve_builtins "reflog" + + subcommands="$___git_resolved_builtins" + subcommand="$(__git_find_subcommand "$subcommands" "show")" + + case "$subcommand,$cur" in + show,--*) + __gitcomp " + $__git_log_common_options + " + return + ;; + $subcommand,--*) + __gitcomp_builtin "reflog_$subcommand" + return + ;; + esac + + __git_complete_refs + + if [ $((cword - __git_cmd_idx)) -eq 1 ]; then + __gitcompappend "$subcommands" "" "$cur" " " fi } @@ -2673,7 +2729,8 @@ __git_compute_first_level_config_vars_for_section () __git_compute_config_vars local this_section="__git_first_level_config_vars_for_section_${section}" test -n "${!this_section}" || - printf -v "__git_first_level_config_vars_for_section_${section}" %s "$(echo "$__git_config_vars" | grep -E "^${section}\.[a-z]" | awk -F. '{print $2}')" + printf -v "__git_first_level_config_vars_for_section_${section}" %s \ + "$(echo "$__git_config_vars" | awk -F. "/^${section}\.[a-z]/ { print \$2 }")" } __git_compute_second_level_config_vars_for_section () @@ -2682,7 +2739,8 @@ __git_compute_second_level_config_vars_for_section () __git_compute_config_vars_all local this_section="__git_second_level_config_vars_for_section_${section}" test -n "${!this_section}" || - printf -v "__git_second_level_config_vars_for_section_${section}" %s "$(echo "$__git_config_vars_all" | grep -E "^${section}\.<" | awk -F. '{print $3}')" + printf -v "__git_second_level_config_vars_for_section_${section}" %s \ + "$(echo "$__git_config_vars_all" | awk -F. "/^${section}\.</ { print \$3 }")" } __git_config_sections= @@ -3571,7 +3629,7 @@ __git_complete_worktree_paths () # Generate completion reply from worktree list skipping the first # entry: it's the path of the main worktree, which can't be moved, # removed, locked, etc. - __gitcomp_nl "$(git worktree list --porcelain | + __gitcomp_nl "$(__git worktree list --porcelain | sed -n -e '2,$ s/^worktree //p')" } diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh index 71f179cba3..5330e769a7 100644 --- a/contrib/completion/git-prompt.sh +++ b/contrib/completion/git-prompt.sh @@ -141,7 +141,7 @@ __git_ps1_show_upstream () # parse configuration values local option - for option in ${GIT_PS1_SHOWUPSTREAM}; do + for option in ${GIT_PS1_SHOWUPSTREAM-}; do case "$option" in git|svn) upstream_type="$option" ;; verbose) verbose=1 ;; @@ -528,7 +528,7 @@ __git_ps1 () fi local conflict="" # state indicator for unresolved conflicts - if [[ "${GIT_PS1_SHOWCONFLICTSTATE}" == "yes" ]] && + if [[ "${GIT_PS1_SHOWCONFLICTSTATE-}" == "yes" ]] && [[ $(git ls-files --unmerged 2>/dev/null) ]]; then conflict="|CONFLICT" fi diff --git a/contrib/coverage-diff.sh b/contrib/coverage-diff.sh index 4ec419f900..6ce9603568 100755 --- a/contrib/coverage-diff.sh +++ b/contrib/coverage-diff.sh @@ -74,8 +74,7 @@ do sort >uncovered_lines.txt comm -12 uncovered_lines.txt new_lines.txt | - sed -e 's/$/\)/' | - sed -e 's/^/ /' >uncovered_new_lines.txt + sed -e 's/$/\)/' -e 's/^/ /' >uncovered_new_lines.txt grep -q '[^[:space:]]' <uncovered_new_lines.txt && echo $file >>coverage-data.txt && @@ -91,11 +90,7 @@ cat coverage-data.txt echo "Commits introducing uncovered code:" -commit_list=$(cat coverage-data.txt | - grep -E '^[0-9a-f]{7,} ' | - awk '{print $1;}' | - sort | - uniq) +commit_list=$(awk '/^[0-9a-f]{7,}/ { print $1 }' coverage-data.txt | sort -u) ( for commit in $commit_list diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c index 215a81d8ba..90034d0cf1 100644 --- a/contrib/credential/libsecret/git-credential-libsecret.c +++ b/contrib/credential/libsecret/git-credential-libsecret.c @@ -164,6 +164,9 @@ static int keyring_get(struct credential *c) if (g_strv_length(parts) >= 1) { g_free(c->password); c->password = g_strdup(parts[0]); + } else { + g_free(c->password); + c->password = g_strdup(""); } for (int i = 1; i < g_strv_length(parts); i++) { if (g_str_has_prefix(parts[i], "password_expiry_utc=")) { diff --git a/contrib/credential/osxkeychain/Makefile b/contrib/credential/osxkeychain/Makefile index 4b3a08a2ba..238f5f8c36 100644 --- a/contrib/credential/osxkeychain/Makefile +++ b/contrib/credential/osxkeychain/Makefile @@ -8,7 +8,8 @@ CFLAGS = -g -O2 -Wall -include ../../../config.mak git-credential-osxkeychain: git-credential-osxkeychain.o - $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -Wl,-framework -Wl,Security + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) \ + -framework Security -framework CoreFoundation git-credential-osxkeychain.o: git-credential-osxkeychain.c $(CC) -c $(CFLAGS) $< diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c index 5f2e5f16c8..6a40917b1e 100644 --- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c +++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c @@ -3,14 +3,51 @@ #include <stdlib.h> #include <Security/Security.h> -static SecProtocolType protocol; -static char *host; -static char *path; -static char *username; -static char *password; -static UInt16 port; - -__attribute__((format (printf, 1, 2))) +#define ENCODING kCFStringEncodingUTF8 +static CFStringRef protocol; /* Stores constant strings - not memory managed */ +static CFStringRef host; +static CFNumberRef port; +static CFStringRef path; +static CFStringRef username; +static CFDataRef password; +static CFDataRef password_expiry_utc; +static CFDataRef oauth_refresh_token; + +static void clear_credential(void) +{ + if (host) { + CFRelease(host); + host = NULL; + } + if (port) { + CFRelease(port); + port = NULL; + } + if (path) { + CFRelease(path); + path = NULL; + } + if (username) { + CFRelease(username); + username = NULL; + } + if (password) { + CFRelease(password); + password = NULL; + } + if (password_expiry_utc) { + CFRelease(password_expiry_utc); + password_expiry_utc = NULL; + } + if (oauth_refresh_token) { + CFRelease(oauth_refresh_token); + oauth_refresh_token = NULL; + } +} + +#define STRING_WITH_LENGTH(s) s, sizeof(s) - 1 + +__attribute__((format (printf, 1, 2), __noreturn__)) static void die(const char *err, ...) { char msg[4096]; @@ -19,70 +56,199 @@ static void die(const char *err, ...) vsnprintf(msg, sizeof(msg), err, params); fprintf(stderr, "%s\n", msg); va_end(params); + clear_credential(); exit(1); } -static void *xstrdup(const char *s1) +static void *xmalloc(size_t len) { - void *ret = strdup(s1); + void *ret = malloc(len); if (!ret) die("Out of memory"); return ret; } -#define KEYCHAIN_ITEM(x) (x ? strlen(x) : 0), x -#define KEYCHAIN_ARGS \ - NULL, /* default keychain */ \ - KEYCHAIN_ITEM(host), \ - 0, NULL, /* account domain */ \ - KEYCHAIN_ITEM(username), \ - KEYCHAIN_ITEM(path), \ - port, \ - protocol, \ - kSecAuthenticationTypeDefault - -static void write_item(const char *what, const char *buf, int len) +static CFDictionaryRef create_dictionary(CFAllocatorRef allocator, ...) +{ + va_list args; + const void *key; + CFMutableDictionaryRef result; + + result = CFDictionaryCreateMutable(allocator, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + + va_start(args, allocator); + while ((key = va_arg(args, const void *)) != NULL) { + const void *value; + value = va_arg(args, const void *); + if (value) + CFDictionarySetValue(result, key, value); + } + va_end(args); + + return result; +} + +#define CREATE_SEC_ATTRIBUTES(...) \ + create_dictionary(kCFAllocatorDefault, \ + kSecClass, kSecClassInternetPassword, \ + kSecAttrServer, host, \ + kSecAttrAccount, username, \ + kSecAttrPath, path, \ + kSecAttrPort, port, \ + kSecAttrProtocol, protocol, \ + kSecAttrAuthenticationType, \ + kSecAttrAuthenticationTypeDefault, \ + __VA_ARGS__); + +static void write_item(const char *what, const char *buf, size_t len) { printf("%s=", what); fwrite(buf, 1, len, stdout); putchar('\n'); } -static void find_username_in_item(SecKeychainItemRef item) +static void find_username_in_item(CFDictionaryRef item) { - SecKeychainAttributeList list; - SecKeychainAttribute attr; + CFStringRef account_ref; + char *username_buf; + CFIndex buffer_len; - list.count = 1; - list.attr = &attr; - attr.tag = kSecAccountItemAttr; + account_ref = CFDictionaryGetValue(item, kSecAttrAccount); + if (!account_ref) + { + write_item("username", "", 0); + return; + } - if (SecKeychainItemCopyContent(item, NULL, &list, NULL, NULL)) + username_buf = (char *)CFStringGetCStringPtr(account_ref, ENCODING); + if (username_buf) + { + write_item("username", username_buf, strlen(username_buf)); return; + } - write_item("username", attr.data, attr.length); - SecKeychainItemFreeContent(&list, NULL); + /* If we can't get a CString pointer then + * we need to allocate our own buffer */ + buffer_len = CFStringGetMaximumSizeForEncoding( + CFStringGetLength(account_ref), ENCODING) + 1; + username_buf = xmalloc(buffer_len); + if (CFStringGetCString(account_ref, + username_buf, + buffer_len, + ENCODING)) { + write_item("username", username_buf, buffer_len - 1); + } + free(username_buf); } -static void find_internet_password(void) +static OSStatus find_internet_password(void) { - void *buf; - UInt32 len; - SecKeychainItemRef item; + CFDictionaryRef attrs; + CFDictionaryRef item; + CFDataRef data; + OSStatus result; - if (SecKeychainFindInternetPassword(KEYCHAIN_ARGS, &len, &buf, &item)) - return; + attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitOne, + kSecReturnAttributes, kCFBooleanTrue, + kSecReturnData, kCFBooleanTrue, + NULL); + result = SecItemCopyMatching(attrs, (CFTypeRef *)&item); + if (result) { + goto out; + } + + data = CFDictionaryGetValue(item, kSecValueData); - write_item("password", buf, len); + write_item("password", + (const char *)CFDataGetBytePtr(data), + CFDataGetLength(data)); if (!username) find_username_in_item(item); - SecKeychainItemFreeContent(NULL, buf); + CFRelease(item); + +out: + CFRelease(attrs); + + /* We consider not found to not be an error */ + if (result == errSecItemNotFound) + result = errSecSuccess; + + return result; +} + +static OSStatus delete_ref(const void *itemRef) +{ + CFArrayRef item_ref_list; + CFDictionaryRef delete_query; + OSStatus result; + + item_ref_list = CFArrayCreate(kCFAllocatorDefault, + &itemRef, + 1, + &kCFTypeArrayCallBacks); + delete_query = create_dictionary(kCFAllocatorDefault, + kSecClass, kSecClassInternetPassword, + kSecMatchItemList, item_ref_list, + NULL); + + if (password) { + /* We only want to delete items with a matching password */ + CFIndex capacity; + CFMutableDictionaryRef query; + CFDataRef data; + + capacity = CFDictionaryGetCount(delete_query) + 1; + query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, + capacity, + delete_query); + CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); + result = SecItemCopyMatching(query, (CFTypeRef *)&data); + if (!result) { + CFDataRef kc_password; + const UInt8 *raw_data; + const UInt8 *line; + + /* Don't match appended metadata */ + raw_data = CFDataGetBytePtr(data); + line = memchr(raw_data, '\n', CFDataGetLength(data)); + if (line) + kc_password = CFDataCreateWithBytesNoCopy( + kCFAllocatorDefault, + raw_data, + line - raw_data, + kCFAllocatorNull); + else + kc_password = data; + + if (CFEqual(kc_password, password)) + result = SecItemDelete(delete_query); + + if (line) + CFRelease(kc_password); + CFRelease(data); + } + + CFRelease(query); + } else { + result = SecItemDelete(delete_query); + } + + CFRelease(delete_query); + CFRelease(item_ref_list); + + return result; } -static void delete_internet_password(void) +static OSStatus delete_internet_password(void) { - SecKeychainItemRef item; + CFDictionaryRef attrs; + CFArrayRef refs; + OSStatus result; /* * Require at least a protocol and host for removal, which is what git @@ -90,25 +256,69 @@ static void delete_internet_password(void) * Keychain manager. */ if (!protocol || !host) - return; + return -1; - if (SecKeychainFindInternetPassword(KEYCHAIN_ARGS, 0, NULL, &item)) - return; + attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitAll, + kSecReturnRef, kCFBooleanTrue, + NULL); + result = SecItemCopyMatching(attrs, (CFTypeRef *)&refs); + CFRelease(attrs); + + if (!result) { + for (CFIndex i = 0; !result && i < CFArrayGetCount(refs); i++) + result = delete_ref(CFArrayGetValueAtIndex(refs, i)); - SecKeychainItemDelete(item); + CFRelease(refs); + } + + /* We consider not found to not be an error */ + if (result == errSecItemNotFound) + result = errSecSuccess; + + return result; } -static void add_internet_password(void) +static OSStatus add_internet_password(void) { + CFMutableDataRef data; + CFDictionaryRef attrs; + OSStatus result; + /* Only store complete credentials */ if (!protocol || !host || !username || !password) - return; + return -1; - if (SecKeychainAddInternetPassword( - KEYCHAIN_ARGS, - KEYCHAIN_ITEM(password), - NULL)) - return; + data = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, password); + if (password_expiry_utc) { + CFDataAppendBytes(data, + (const UInt8 *)STRING_WITH_LENGTH("\npassword_expiry_utc=")); + CFDataAppendBytes(data, + CFDataGetBytePtr(password_expiry_utc), + CFDataGetLength(password_expiry_utc)); + } + if (oauth_refresh_token) { + CFDataAppendBytes(data, + (const UInt8 *)STRING_WITH_LENGTH("\noauth_refresh_token=")); + CFDataAppendBytes(data, + CFDataGetBytePtr(oauth_refresh_token), + CFDataGetLength(oauth_refresh_token)); + } + + attrs = CREATE_SEC_ATTRIBUTES(kSecValueData, data, + NULL); + + result = SecItemAdd(attrs, NULL); + if (result == errSecDuplicateItem) { + CFDictionaryRef query; + query = CREATE_SEC_ATTRIBUTES(NULL); + result = SecItemUpdate(query, attrs); + CFRelease(query); + } + + CFRelease(data); + CFRelease(attrs); + + return result; } static void read_credential(void) @@ -131,36 +341,60 @@ static void read_credential(void) if (!strcmp(buf, "protocol")) { if (!strcmp(v, "imap")) - protocol = kSecProtocolTypeIMAP; + protocol = kSecAttrProtocolIMAP; else if (!strcmp(v, "imaps")) - protocol = kSecProtocolTypeIMAPS; + protocol = kSecAttrProtocolIMAPS; else if (!strcmp(v, "ftp")) - protocol = kSecProtocolTypeFTP; + protocol = kSecAttrProtocolFTP; else if (!strcmp(v, "ftps")) - protocol = kSecProtocolTypeFTPS; + protocol = kSecAttrProtocolFTPS; else if (!strcmp(v, "https")) - protocol = kSecProtocolTypeHTTPS; + protocol = kSecAttrProtocolHTTPS; else if (!strcmp(v, "http")) - protocol = kSecProtocolTypeHTTP; + protocol = kSecAttrProtocolHTTP; else if (!strcmp(v, "smtp")) - protocol = kSecProtocolTypeSMTP; - else /* we don't yet handle other protocols */ + protocol = kSecAttrProtocolSMTP; + else { + /* we don't yet handle other protocols */ + clear_credential(); exit(0); + } } else if (!strcmp(buf, "host")) { char *colon = strchr(v, ':'); if (colon) { + UInt16 port_i; *colon++ = '\0'; - port = atoi(colon); + port_i = atoi(colon); + port = CFNumberCreate(kCFAllocatorDefault, + kCFNumberShortType, + &port_i); } - host = xstrdup(v); + host = CFStringCreateWithCString(kCFAllocatorDefault, + v, + ENCODING); } else if (!strcmp(buf, "path")) - path = xstrdup(v); + path = CFStringCreateWithCString(kCFAllocatorDefault, + v, + ENCODING); else if (!strcmp(buf, "username")) - username = xstrdup(v); + username = CFStringCreateWithCString( + kCFAllocatorDefault, + v, + ENCODING); else if (!strcmp(buf, "password")) - password = xstrdup(v); + password = CFDataCreate(kCFAllocatorDefault, + (UInt8 *)v, + strlen(v)); + else if (!strcmp(buf, "password_expiry_utc")) + password_expiry_utc = CFDataCreate(kCFAllocatorDefault, + (UInt8 *)v, + strlen(v)); + else if (!strcmp(buf, "oauth_refresh_token")) + oauth_refresh_token = CFDataCreate(kCFAllocatorDefault, + (UInt8 *)v, + strlen(v)); /* * Ignore other lines; we don't know what they mean, but * this future-proofs us when later versions of git do @@ -173,6 +407,7 @@ static void read_credential(void) int main(int argc, const char **argv) { + OSStatus result = 0; const char *usage = "usage: git credential-osxkeychain <get|store|erase>"; @@ -182,12 +417,17 @@ int main(int argc, const char **argv) read_credential(); if (!strcmp(argv[1], "get")) - find_internet_password(); + result = find_internet_password(); else if (!strcmp(argv[1], "store")) - add_internet_password(); + result = add_internet_password(); else if (!strcmp(argv[1], "erase")) - delete_internet_password(); + result = delete_internet_password(); /* otherwise, ignore unknown action */ + if (result) + die("failed to %s: %d", argv[1], (int)result); + + clear_credential(); + return 0; } diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py deleted file mode 100755 index 7eb1b24cc7..0000000000 --- a/contrib/hg-to-git/hg-to-git.py +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/env python - -""" hg-to-git.py - A Mercurial to GIT converter - - Copyright (C)2007 Stelian Pop <stelian@popies.net> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. -""" - -import os, os.path, sys -import tempfile, pickle, getopt -import re - -if sys.hexversion < 0x02030000: - # The behavior of the pickle module changed significantly in 2.3 - sys.stderr.write("hg-to-git.py: requires Python 2.3 or later.\n") - sys.exit(1) - -# Maps hg version -> git version -hgvers = {} -# List of children for each hg revision -hgchildren = {} -# List of parents for each hg revision -hgparents = {} -# Current branch for each hg revision -hgbranch = {} -# Number of new changesets converted from hg -hgnewcsets = 0 - -#------------------------------------------------------------------------------ - -def usage(): - - print("""\ -%s: [OPTIONS] <hgprj> - -options: - -s, --gitstate=FILE: name of the state to be saved/read - for incrementals - -n, --nrepack=INT: number of changesets that will trigger - a repack (default=0, -1 to deactivate) - -v, --verbose: be verbose - -required: - hgprj: name of the HG project to import (directory) -""" % sys.argv[0]) - -#------------------------------------------------------------------------------ - -def getgitenv(user, date): - env = '' - elems = re.compile('(.*?)\s+<(.*)>').match(user) - if elems: - env += 'export GIT_AUTHOR_NAME="%s" ;' % elems.group(1) - env += 'export GIT_COMMITTER_NAME="%s" ;' % elems.group(1) - env += 'export GIT_AUTHOR_EMAIL="%s" ;' % elems.group(2) - env += 'export GIT_COMMITTER_EMAIL="%s" ;' % elems.group(2) - else: - env += 'export GIT_AUTHOR_NAME="%s" ;' % user - env += 'export GIT_COMMITTER_NAME="%s" ;' % user - env += 'export GIT_AUTHOR_EMAIL= ;' - env += 'export GIT_COMMITTER_EMAIL= ;' - - env += 'export GIT_AUTHOR_DATE="%s" ;' % date - env += 'export GIT_COMMITTER_DATE="%s" ;' % date - return env - -#------------------------------------------------------------------------------ - -state = '' -opt_nrepack = 0 -verbose = False - -try: - opts, args = getopt.getopt(sys.argv[1:], 's:t:n:v', ['gitstate=', 'tempdir=', 'nrepack=', 'verbose']) - for o, a in opts: - if o in ('-s', '--gitstate'): - state = a - state = os.path.abspath(state) - if o in ('-n', '--nrepack'): - opt_nrepack = int(a) - if o in ('-v', '--verbose'): - verbose = True - if len(args) != 1: - raise Exception('params') -except: - usage() - sys.exit(1) - -hgprj = args[0] -os.chdir(hgprj) - -if state: - if os.path.exists(state): - if verbose: - print('State does exist, reading') - f = open(state, 'r') - hgvers = pickle.load(f) - else: - print('State does not exist, first run') - -sock = os.popen('hg tip --template "{rev}"') -tip = sock.read() -if sock.close(): - sys.exit(1) -if verbose: - print('tip is', tip) - -# Calculate the branches -if verbose: - print('analysing the branches...') -hgchildren["0"] = () -hgparents["0"] = (None, None) -hgbranch["0"] = "master" -for cset in range(1, int(tip) + 1): - hgchildren[str(cset)] = () - prnts = os.popen('hg log -r %d --template "{parents}"' % cset).read().strip().split(' ') - prnts = map(lambda x: x[:x.find(':')], prnts) - if prnts[0] != '': - parent = prnts[0].strip() - else: - parent = str(cset - 1) - hgchildren[parent] += ( str(cset), ) - if len(prnts) > 1: - mparent = prnts[1].strip() - hgchildren[mparent] += ( str(cset), ) - else: - mparent = None - - hgparents[str(cset)] = (parent, mparent) - - if mparent: - # For merge changesets, take either one, preferably the 'master' branch - if hgbranch[mparent] == 'master': - hgbranch[str(cset)] = 'master' - else: - hgbranch[str(cset)] = hgbranch[parent] - else: - # Normal changesets - # For first children, take the parent branch, for the others create a new branch - if hgchildren[parent][0] == str(cset): - hgbranch[str(cset)] = hgbranch[parent] - else: - hgbranch[str(cset)] = "branch-" + str(cset) - -if "0" not in hgvers: - print('creating repository') - os.system('git init') - -# loop through every hg changeset -for cset in range(int(tip) + 1): - - # incremental, already seen - if str(cset) in hgvers: - continue - hgnewcsets += 1 - - # get info - log_data = os.popen('hg log -r %d --template "{tags}\n{date|date}\n{author}\n"' % cset).readlines() - tag = log_data[0].strip() - date = log_data[1].strip() - user = log_data[2].strip() - parent = hgparents[str(cset)][0] - mparent = hgparents[str(cset)][1] - - #get comment - (fdcomment, filecomment) = tempfile.mkstemp() - csetcomment = os.popen('hg log -r %d --template "{desc}"' % cset).read().strip() - os.write(fdcomment, csetcomment) - os.close(fdcomment) - - print('-----------------------------------------') - print('cset:', cset) - print('branch:', hgbranch[str(cset)]) - print('user:', user) - print('date:', date) - print('comment:', csetcomment) - if parent: - print('parent:', parent) - if mparent: - print('mparent:', mparent) - if tag: - print('tag:', tag) - print('-----------------------------------------') - - # checkout the parent if necessary - if cset != 0: - if hgbranch[str(cset)] == "branch-" + str(cset): - print('creating new branch', hgbranch[str(cset)]) - os.system('git checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent])) - else: - print('checking out branch', hgbranch[str(cset)]) - os.system('git checkout %s' % hgbranch[str(cset)]) - - # merge - if mparent: - if hgbranch[parent] == hgbranch[str(cset)]: - otherbranch = hgbranch[mparent] - else: - otherbranch = hgbranch[parent] - print('merging', otherbranch, 'into', hgbranch[str(cset)]) - os.system(getgitenv(user, date) + 'git merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch)) - - # remove everything except .git and .hg directories - os.system('find . \( -path "./.hg" -o -path "./.git" \) -prune -o ! -name "." -print | xargs rm -rf') - - # repopulate with checkouted files - os.system('hg update -C %d' % cset) - - # add new files - os.system('git ls-files -x .hg --others | git update-index --add --stdin') - # delete removed files - os.system('git ls-files -x .hg --deleted | git update-index --remove --stdin') - - # commit - os.system(getgitenv(user, date) + 'git commit --allow-empty --allow-empty-message -a -F %s' % filecomment) - os.unlink(filecomment) - - # tag - if tag and tag != 'tip': - os.system(getgitenv(user, date) + 'git tag %s' % tag) - - # delete branch if not used anymore... - if mparent and len(hgchildren[str(cset)]): - print("Deleting unused branch:", otherbranch) - os.system('git branch -d %s' % otherbranch) - - # retrieve and record the version - vvv = os.popen('git show --quiet --pretty=format:%H').read() - print('record', cset, '->', vvv) - hgvers[str(cset)] = vvv - -if hgnewcsets >= opt_nrepack and opt_nrepack != -1: - os.system('git repack -a -d') - -# write the state for incrementals -if state: - if verbose: - print('Writing state') - f = open(state, 'w') - pickle.dump(hgvers, f) - -# vim: et ts=8 sw=4 sts=4 diff --git a/contrib/hg-to-git/hg-to-git.txt b/contrib/hg-to-git/hg-to-git.txt deleted file mode 100644 index 91f8fe6410..0000000000 --- a/contrib/hg-to-git/hg-to-git.txt +++ /dev/null @@ -1,21 +0,0 @@ -hg-to-git.py is able to convert a Mercurial repository into a git one, -and preserves the branches in the process (unlike tailor) - -hg-to-git.py can probably be greatly improved (it's a rather crude -combination of shell and python) but it does already work quite well for -me. Features: - - supports incremental conversion - (for keeping a git repo in sync with a hg one) - - supports hg branches - - converts hg tags - -Note that the git repository will be created 'in place' (at the same -location as the source hg repo). You will have to manually remove the -'.hg' directory after the conversion. - -Also note that the incremental conversion uses 'simple' hg changesets -identifiers (ordinals, as opposed to SHA-1 ids), and since these ids -are not stable across different repositories the hg-to-git.py state file -is forever tied to one hg repository. - -Stelian Pop <stelian@popies.net> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index ca4df5be83..c3bd2a58b9 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -63,7 +63,7 @@ test_create_pre2_32_repo () { git -C "$1" log -1 --format=%B HEAD^2 >msg && test_commit -C "$1-sub" --annotate sub2 && git clone --no-local "$1" "$1-clone" && - new_commit=$(cat msg | sed -e "s/$commit/$tag/" | git -C "$1-clone" commit-tree HEAD^2^{tree}) && + new_commit=$(sed -e "s/$commit/$tag/" msg | git -C "$1-clone" commit-tree HEAD^2^{tree}) && git -C "$1-clone" replace HEAD^2 $new_commit } diff --git a/contrib/vscode/init.sh b/contrib/vscode/init.sh index 521d303722..f2d61bb0e6 100755 --- a/contrib/vscode/init.sh +++ b/contrib/vscode/init.sh @@ -92,7 +92,6 @@ cat >.vscode/settings.json.new <<\EOF || "isexe", "iskeychar", "kompare", - "mksnpath", "mktag", "mktree", "mmblob", diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir index 888c34a521..989197aace 100755 --- a/contrib/workdir/git-new-workdir +++ b/contrib/workdir/git-new-workdir @@ -79,7 +79,7 @@ trap cleanup $siglist # create the links to the original repo. explicitly exclude index, HEAD and # logs/HEAD from the list since they are purely related to the current working # directory, and should not be shared. -for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn +for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn reftable do # create a containing directory if needed case $x in @@ -1028,7 +1028,7 @@ static int read_convert_config(const char *var, const char *value, if (parse_config_key(var, "filter", &name, &namelen, &key) < 0 || !name) return 0; for (drv = user_convert; drv; drv = drv->next) - if (!strncmp(drv->name, name, namelen) && !drv->name[namelen]) + if (!xstrncmpz(drv->name, name, namelen)) break; if (!drv) { CALLOC_ARRAY(drv, 1); @@ -207,13 +207,13 @@ void show_date_relative(timestamp_t time, struct strbuf *timebuf) (diff + 183) / 365); } -struct date_mode *date_mode_from_type(enum date_mode_type type) +struct date_mode date_mode_from_type(enum date_mode_type type) { - static struct date_mode mode = DATE_MODE_INIT; + struct date_mode mode = DATE_MODE_INIT; if (type == DATE_STRFTIME) BUG("cannot create anonymous strftime date_mode struct"); mode.type = type; - return &mode; + return mode; } static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm, int tz, struct tm *human_tm, int human_tz, int local) @@ -283,7 +283,7 @@ static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm strbuf_addf(buf, " %+05d", tz); } -const char *show_date(timestamp_t time, int tz, const struct date_mode *mode) +const char *show_date(timestamp_t time, int tz, struct date_mode mode) { struct tm *tm; struct tm tmbuf = { 0 }; @@ -291,13 +291,13 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode) int human_tz = -1; static struct strbuf timebuf = STRBUF_INIT; - if (mode->type == DATE_UNIX) { + if (mode.type == DATE_UNIX) { strbuf_reset(&timebuf); strbuf_addf(&timebuf, "%"PRItime, time); return timebuf.buf; } - if (mode->type == DATE_HUMAN) { + if (mode.type == DATE_HUMAN) { struct timeval now; get_time(&now); @@ -306,22 +306,22 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode) human_tz = local_time_tzoffset(now.tv_sec, &human_tm); } - if (mode->local) + if (mode.local) tz = local_tzoffset(time); - if (mode->type == DATE_RAW) { + if (mode.type == DATE_RAW) { strbuf_reset(&timebuf); strbuf_addf(&timebuf, "%"PRItime" %+05d", time, tz); return timebuf.buf; } - if (mode->type == DATE_RELATIVE) { + if (mode.type == DATE_RELATIVE) { strbuf_reset(&timebuf); show_date_relative(time, &timebuf); return timebuf.buf; } - if (mode->local) + if (mode.local) tm = time_to_tm_local(time, &tmbuf); else tm = time_to_tm(time, tz, &tmbuf); @@ -331,35 +331,39 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode) } strbuf_reset(&timebuf); - if (mode->type == DATE_SHORT) + if (mode.type == DATE_SHORT) strbuf_addf(&timebuf, "%04d-%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); - else if (mode->type == DATE_ISO8601) + else if (mode.type == DATE_ISO8601) strbuf_addf(&timebuf, "%04d-%02d-%02d %02d:%02d:%02d %+05d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tz); - else if (mode->type == DATE_ISO8601_STRICT) { - char sign = (tz >= 0) ? '+' : '-'; - tz = abs(tz); - strbuf_addf(&timebuf, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", + else if (mode.type == DATE_ISO8601_STRICT) { + strbuf_addf(&timebuf, "%04d-%02d-%02dT%02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, - sign, tz / 100, tz % 100); - } else if (mode->type == DATE_RFC2822) + tm->tm_hour, tm->tm_min, tm->tm_sec); + if (tz == 0) { + strbuf_addch(&timebuf, 'Z'); + } else { + strbuf_addch(&timebuf, tz >= 0 ? '+' : '-'); + tz = abs(tz); + strbuf_addf(&timebuf, "%02d:%02d", tz / 100, tz % 100); + } + } else if (mode.type == DATE_RFC2822) strbuf_addf(&timebuf, "%.3s, %d %.3s %d %02d:%02d:%02d %+05d", weekday_names[tm->tm_wday], tm->tm_mday, month_names[tm->tm_mon], tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, tz); - else if (mode->type == DATE_STRFTIME) - strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz, - !mode->local); + else if (mode.type == DATE_STRFTIME) + strbuf_addftime(&timebuf, mode.strftime_fmt, tm, tz, + !mode.local); else - show_date_normal(&timebuf, time, tm, tz, &human_tm, human_tz, mode->local); + show_date_normal(&timebuf, time, tm, tz, &human_tm, human_tz, mode.local); return timebuf.buf; } @@ -22,8 +22,8 @@ enum date_mode_type { struct date_mode { enum date_mode_type type; - const char *strftime_fmt; int local; + const char *strftime_fmt; }; #define DATE_MODE_INIT { \ @@ -36,14 +36,14 @@ struct date_mode { * show_date(t, tz, DATE_MODE(NORMAL)); */ #define DATE_MODE(t) date_mode_from_type(DATE_##t) -struct date_mode *date_mode_from_type(enum date_mode_type type); +struct date_mode date_mode_from_type(enum date_mode_type type); /** * Format <'time', 'timezone'> into static memory according to 'mode' * and return it. The mode is an initialized "struct date_mode" * (usually from the DATE_MODE() macro). */ -const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode); +const char *show_date(timestamp_t time, int timezone, struct date_mode mode); /** * Parse a date format for later use with show_date(). diff --git a/delta-islands.c b/delta-islands.c index ee2318d45a..f7e079425f 100644 --- a/delta-islands.c +++ b/delta-islands.c @@ -284,7 +284,7 @@ void resolve_tree_islands(struct repository *r, if (!tree || parse_tree(tree) < 0) die(_("bad tree object %s"), oid_to_hex(&ent->idx.oid)); - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { struct object *obj; diff --git a/diff-lib.c b/diff-lib.c index 6c8df04273..683f11e509 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -127,7 +127,16 @@ void run_diff_files(struct rev_info *revs, unsigned int option) if (diff_can_quit_early(&revs->diffopt)) break; - if (!ce_path_match(istate, ce, &revs->prune_data, NULL)) + /* + * NEEDSWORK: + * Here we filter with pathspec but the result is further + * filtered out when --relative is in effect. To end-users, + * a pathspec element that matched only to paths outside the + * current directory is like not matching anything at all; + * the handling of ps_matched[] here may become problematic + * if/when we add the "--error-unmatch" option to "git diff". + */ + if (!ce_path_match(istate, ce, &revs->prune_data, revs->ps_matched)) continue; if (revs->diffopt.prefix && @@ -562,7 +571,7 @@ static int diff_cache(struct rev_info *revs, opts.pathspec = &revs->diffopt.pathspec; opts.pathspec->recursive = 1; - init_tree_desc(&t, tree->buffer, tree->size); + init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size); return unpack_trees(1, &t, &opts); } @@ -570,7 +579,7 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb) { int i; struct commit *mb_child[2] = {0}; - struct commit_list *merge_bases; + struct commit_list *merge_bases = NULL; for (i = 0; i < revs->pending.nr; i++) { struct object *obj = revs->pending.objects[i].item; @@ -597,7 +606,8 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb) mb_child[1] = lookup_commit_reference(the_repository, &oid); } - merge_bases = repo_get_merge_bases(the_repository, mb_child[0], mb_child[1]); + if (repo_get_merge_bases(the_repository, mb_child[0], mb_child[1], &merge_bases) < 0) + exit(128); if (!merge_bases) die(_("no merge base found")); if (merge_bases->next) @@ -62,6 +62,8 @@ static const char *diff_order_file_cfg; int diff_auto_refresh_index = 1; static int diff_mnemonic_prefix; static int diff_no_prefix; +static const char *diff_src_prefix = "a/"; +static const char *diff_dst_prefix = "b/"; static int diff_relative; static int diff_stat_name_width; static int diff_stat_graph_width; @@ -408,6 +410,12 @@ int git_diff_ui_config(const char *var, const char *value, diff_no_prefix = git_config_bool(var, value); return 0; } + if (!strcmp(var, "diff.srcprefix")) { + return git_config_string(&diff_src_prefix, var, value); + } + if (!strcmp(var, "diff.dstprefix")) { + return git_config_string(&diff_dst_prefix, var, value); + } if (!strcmp(var, "diff.relative")) { diff_relative = git_config_bool(var, value); return 0; @@ -3425,8 +3433,8 @@ void diff_set_noprefix(struct diff_options *options) void diff_set_default_prefix(struct diff_options *options) { - options->a_prefix = "a/"; - options->b_prefix = "b/"; + options->a_prefix = diff_src_prefix; + options->b_prefix = diff_dst_prefix; } struct userdiff_driver *get_textconv(struct repository *r, @@ -5362,6 +5370,8 @@ static int diff_opt_default_prefix(const struct option *opt, BUG_ON_OPT_NEG(unset); BUG_ON_OPT_ARG(optarg); + diff_src_prefix = "a/"; + diff_dst_prefix = "b/"; diff_set_default_prefix(options); return 0; } diff --git a/dir-iterator.c b/dir-iterator.c index 278b04243a..de619846f2 100644 --- a/dir-iterator.c +++ b/dir-iterator.c @@ -2,11 +2,20 @@ #include "dir.h" #include "iterator.h" #include "dir-iterator.h" +#include "string-list.h" struct dir_iterator_level { DIR *dir; /* + * The directory entries of the current level. This list will only be + * populated when the iterator is ordered. In that case, `dir` will be + * set to `NULL`. + */ + struct string_list entries; + size_t entries_idx; + + /* * The length of the directory part of path at this level * (including a trailing '/'): */ @@ -43,6 +52,31 @@ struct dir_iterator_int { unsigned int flags; }; +static int next_directory_entry(DIR *dir, const char *path, + struct dirent **out) +{ + struct dirent *de; + +repeat: + errno = 0; + de = readdir(dir); + if (!de) { + if (errno) { + warning_errno("error reading directory '%s'", + path); + return -1; + } + + return 1; + } + + if (is_dot_or_dotdot(de->d_name)) + goto repeat; + + *out = de; + return 0; +} + /* * Push a level in the iter stack and initialize it with information from * the directory pointed by iter->base->path. It is assumed that this @@ -72,6 +106,35 @@ static int push_level(struct dir_iterator_int *iter) return -1; } + string_list_init_dup(&level->entries); + level->entries_idx = 0; + + /* + * When the iterator is sorted we read and sort all directory entries + * directly. + */ + if (iter->flags & DIR_ITERATOR_SORTED) { + struct dirent *de; + + while (1) { + int ret = next_directory_entry(level->dir, iter->base.path.buf, &de); + if (ret < 0) { + if (errno != ENOENT && + iter->flags & DIR_ITERATOR_PEDANTIC) + return -1; + continue; + } else if (ret > 0) { + break; + } + + string_list_append(&level->entries, de->d_name); + } + string_list_sort(&level->entries); + + closedir(level->dir); + level->dir = NULL; + } + return 0; } @@ -88,21 +151,22 @@ static int pop_level(struct dir_iterator_int *iter) warning_errno("error closing directory '%s'", iter->base.path.buf); level->dir = NULL; + string_list_clear(&level->entries, 0); return --iter->levels_nr; } /* * Populate iter->base with the necessary information on the next iteration - * entry, represented by the given dirent de. Return 0 on success and -1 + * entry, represented by the given name. Return 0 on success and -1 * otherwise, setting errno accordingly. */ static int prepare_next_entry_data(struct dir_iterator_int *iter, - struct dirent *de) + const char *name) { int err, saved_errno; - strbuf_addstr(&iter->base.path, de->d_name); + strbuf_addstr(&iter->base.path, name); /* * We have to reset these because the path strbuf might have * been realloc()ed at the previous strbuf_addstr(). @@ -139,27 +203,34 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) struct dirent *de; struct dir_iterator_level *level = &iter->levels[iter->levels_nr - 1]; + const char *name; strbuf_setlen(&iter->base.path, level->prefix_len); - errno = 0; - de = readdir(level->dir); - if (!de) { - if (errno) { - warning_errno("error reading directory '%s'", - iter->base.path.buf); + if (level->dir) { + int ret = next_directory_entry(level->dir, iter->base.path.buf, &de); + if (ret < 0) { if (iter->flags & DIR_ITERATOR_PEDANTIC) goto error_out; - } else if (pop_level(iter) == 0) { - return dir_iterator_abort(dir_iterator); + continue; + } else if (ret > 0) { + if (pop_level(iter) == 0) + return dir_iterator_abort(dir_iterator); + continue; } - continue; - } - if (is_dot_or_dotdot(de->d_name)) - continue; + name = de->d_name; + } else { + if (level->entries_idx >= level->entries.nr) { + if (pop_level(iter) == 0) + return dir_iterator_abort(dir_iterator); + continue; + } - if (prepare_next_entry_data(iter, de)) { + name = level->entries.items[level->entries_idx++].string; + } + + if (prepare_next_entry_data(iter, name)) { if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) goto error_out; continue; @@ -188,6 +259,8 @@ int dir_iterator_abort(struct dir_iterator *dir_iterator) warning_errno("error closing directory '%s'", iter->base.path.buf); } + + string_list_clear(&level->entries, 0); } free(iter->levels); diff --git a/dir-iterator.h b/dir-iterator.h index 479e1ec784..6d438809b6 100644 --- a/dir-iterator.h +++ b/dir-iterator.h @@ -54,8 +54,11 @@ * and ITER_ERROR is returned immediately. In both cases, a meaningful * warning is emitted. Note: ENOENT errors are always ignored so that * the API users may remove files during iteration. + * + * - DIR_ITERATOR_SORTED: sort directory entries alphabetically. */ #define DIR_ITERATOR_PEDANTIC (1 << 0) +#define DIR_ITERATOR_SORTED (1 << 1) struct dir_iterator { /* The current path: */ @@ -3918,6 +3918,26 @@ void untracked_cache_invalidate_path(struct index_state *istate, path, strlen(path)); } +void untracked_cache_invalidate_trimmed_path(struct index_state *istate, + const char *path, + int safe_path) +{ + size_t len = strlen(path); + + if (!len) + BUG("untracked_cache_invalidate_trimmed_path given zero length path"); + + if (path[len - 1] != '/') { + untracked_cache_invalidate_path(istate, path, safe_path); + } else { + struct strbuf tmp = STRBUF_INIT; + + strbuf_add(&tmp, path, len - 1); + untracked_cache_invalidate_path(istate, tmp.buf, safe_path); + strbuf_release(&tmp); + } +} + void untracked_cache_remove_from_index(struct index_state *istate, const char *path) { @@ -576,6 +576,13 @@ int cmp_dir_entry(const void *p1, const void *p2); int check_dir_entry_contains(const struct dir_entry *out, const struct dir_entry *in); void untracked_cache_invalidate_path(struct index_state *, const char *, int safe_path); +/* + * Invalidate the untracked-cache for this path, but first strip + * off a trailing slash, if present. + */ +void untracked_cache_invalidate_trimmed_path(struct index_state *, + const char *path, + int safe_path); void untracked_cache_remove_from_index(struct index_state *, const char *); void untracked_cache_add_to_index(struct index_state *, const char *); @@ -104,16 +104,15 @@ static int launch_specified_editor(const char *editor, const char *path, sigchain_pop(SIGQUIT); if (sig == SIGINT || sig == SIGQUIT) raise(sig); - if (ret) - return error("There was a problem with the editor '%s'.", - editor); - if (print_waiting_for_editor && !is_terminal_dumb()) /* * Erase the entire line to avoid wasting the * vertical space. */ term_clear_line(); + if (ret) + return error("there was a problem with the editor '%s'", + editor); } if (!buffer) diff --git a/environment.c b/environment.c index 90632a39bc..a73ba9c12c 100644 --- a/environment.c +++ b/environment.c @@ -110,7 +110,7 @@ int protect_ntfs = PROTECT_NTFS_DEFAULT; * The character that begins a commented line in user-editable file * that is subject to stripspace. */ -char comment_line_char = '#'; +const char *comment_line_str = "#"; int auto_comment_line_char; /* Parallel index stat data preload? */ @@ -207,6 +207,9 @@ void setup_git_env(const char *git_dir) 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) diff --git a/environment.h b/environment.h index e5351c9dd9..05fd94d7be 100644 --- a/environment.h +++ b/environment.h @@ -8,7 +8,7 @@ struct strvec; * The character that begins a commented line in user-editable file * that is subject to stripspace. */ -extern char comment_line_char; +extern const char *comment_line_str; extern int auto_comment_line_char; /* @@ -36,6 +36,7 @@ const char *getenv_safe(struct strvec *argv, const char *name); #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS" #define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE" +#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH" #define GITATTRIBUTES_FILE ".gitattributes" #define INFOATTRIBUTES_FILE "info/attributes" #define ATTRIBUTE_MACRO_PREFIX "[attr]" diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c index 66e47449a0..ae201e21db 100644 --- a/fmt-merge-msg.c +++ b/fmt-merge-msg.c @@ -321,7 +321,7 @@ static void credit_people(struct strbuf *out, skip_prefix(me, them->items->string, &me) && starts_with(me, " <"))) return; - strbuf_addf(out, "\n%c %s ", comment_line_char, label); + strbuf_addf(out, "\n%s %s ", comment_line_str, label); add_people_count(out, them); } @@ -510,7 +510,7 @@ static void fmt_tag_signature(struct strbuf *tagbuf, if (sig->len) { strbuf_addch(tagbuf, '\n'); strbuf_add_commented_lines(tagbuf, sig->buf, sig->len, - comment_line_char); + comment_line_str); } } @@ -557,7 +557,7 @@ static void fmt_merge_msg_sigs(struct strbuf *out) strbuf_add_commented_lines(&tagline, origins.items[first_tag].string, strlen(origins.items[first_tag].string), - comment_line_char); + comment_line_str); strbuf_insert(&tagbuf, 0, tagline.buf, tagline.len); strbuf_release(&tagline); @@ -566,7 +566,7 @@ static void fmt_merge_msg_sigs(struct strbuf *out) strbuf_add_commented_lines(&tagbuf, origins.items[i].string, strlen(origins.items[i].string), - comment_line_char); + comment_line_str); fmt_tag_signature(&tagbuf, &sig, buf, len); } strbuf_release(&payload); @@ -327,7 +327,8 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op return -1; name = fsck_get_object_name(options, &tree->object.oid); - if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0)) + if (init_tree_desc_gently(&desc, &tree->object.oid, + tree->buffer, tree->size, 0)) return -1; while (tree_entry_gently(&desc, &entry)) { struct object *obj; @@ -598,7 +599,8 @@ static int fsck_tree(const struct object_id *tree_oid, const char *o_name; struct name_stack df_dup_candidates = { NULL }; - if (init_tree_desc_gently(&desc, buffer, size, TREE_DESC_RAW_MODES)) { + if (init_tree_desc_gently(&desc, tree_oid, buffer, size, + TREE_DESC_RAW_MODES)) { retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); diff --git a/fsmonitor.c b/fsmonitor.c index f670c50937..2b17d60bbb 100644 --- a/fsmonitor.c +++ b/fsmonitor.c @@ -5,6 +5,7 @@ #include "ewah/ewok.h" #include "fsmonitor.h" #include "fsmonitor-ipc.h" +#include "name-hash.h" #include "run-command.h" #include "strbuf.h" #include "trace2.h" @@ -183,79 +184,282 @@ static int query_fsmonitor_hook(struct repository *r, return result; } -static void fsmonitor_refresh_callback(struct index_state *istate, char *name) +/* + * Invalidate the FSM bit on this CE. This is like mark_fsmonitor_invalid() + * but we've already handled the untracked-cache, so let's not repeat that + * work. This also lets us have a different trace message so that we can + * see everything that was done as part of the refresh-callback. + */ +static void invalidate_ce_fsm(struct cache_entry *ce) { - int i, len = strlen(name); - int pos = index_name_pos(istate, name, len); + if (ce->ce_flags & CE_FSMONITOR_VALID) { + trace_printf_key(&trace_fsmonitor, + "fsmonitor_refresh_callback INV: '%s'", + ce->name); + ce->ce_flags &= ~CE_FSMONITOR_VALID; + } +} + +static size_t handle_path_with_trailing_slash( + struct index_state *istate, const char *name, int pos); + +/* + * Use the name-hash to do a case-insensitive cache-entry lookup with + * the pathname and invalidate the cache-entry. + * + * Returns the number of cache-entries that we invalidated. + */ +static size_t handle_using_name_hash_icase( + struct index_state *istate, const char *name) +{ + struct cache_entry *ce = NULL; + + ce = index_file_exists(istate, name, strlen(name), 1); + if (!ce) + return 0; + /* + * A case-insensitive search in the name-hash using the + * observed pathname found a cache-entry, so the observed path + * is case-incorrect. Invalidate the cache-entry and use the + * correct spelling from the cache-entry to invalidate the + * untracked-cache. Since we now have sparse-directories in + * the index, the observed pathname may represent a regular + * file or a sparse-index directory. + * + * Note that we should not have seen FSEvents for a + * sparse-index directory, but we handle it just in case. + * + * Either way, we know that there are not any cache-entries for + * children inside the cone of the directory, so we don't need to + * do the usual scan. + */ trace_printf_key(&trace_fsmonitor, - "fsmonitor_refresh_callback '%s' (pos %d)", - name, pos); + "fsmonitor_refresh_callback MAP: '%s' '%s'", + name, ce->name); - if (name[len - 1] == '/') { - /* - * The daemon can decorate directory events, such as - * moves or renames, with a trailing slash if the OS - * FS Event contains sufficient information, such as - * MacOS. - * - * Use this to invalidate the entire cone under that - * directory. - * - * We do not expect an exact match because the index - * does not normally contain directory entries, so we - * start at the insertion point and scan. - */ - if (pos < 0) - pos = -pos - 1; + /* + * NEEDSWORK: We used the name-hash to find the correct + * case-spelling of the pathname in the cache-entry[], so + * 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 + * do this. For now, I'm going to be conservative and always + * do it; we can revisit this later. + */ + untracked_cache_invalidate_trimmed_path(istate, ce->name, 0); - /* Mark all entries for the folder invalid */ - for (i = pos; i < istate->cache_nr; i++) { - if (!starts_with(istate->cache[i]->name, name)) - break; - istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID; - } + invalidate_ce_fsm(ce); + return 1; +} + +/* + * Use the dir-name-hash to find the correct-case spelling of the + * directory. Use the canonical spelling to invalidate all of the + * cache-entries within the matching cone. + * + * Returns the number of cache-entries that we invalidated. + */ +static size_t handle_using_dir_name_hash_icase( + struct index_state *istate, const char *name) +{ + struct strbuf canonical_path = STRBUF_INIT; + int pos; + size_t len = strlen(name); + size_t nr_in_cone; + + if (name[len - 1] == '/') + len--; + + if (!index_dir_find(istate, name, len, &canonical_path)) + return 0; /* name is untracked */ + if (!memcmp(name, canonical_path.buf, canonical_path.len)) { + strbuf_release(&canonical_path); /* - * We need to remove the traling "/" from the path - * for the untracked cache. + * NEEDSWORK: Our caller already tried an exact match + * and failed to find one. They called us to do an + * ICASE match, so we should never get an exact match, + * so we could promote this to a BUG() here if we + * wanted to. It doesn't hurt anything to just return + * 0 and go on because we should never get here. Or we + * could just get rid of the memcmp() and this "if" + * clause completely. */ - name[len - 1] = '\0'; - } else if (pos >= 0) { + BUG("handle_using_dir_name_hash_icase(%s) did not exact match", + name); + } + + trace_printf_key(&trace_fsmonitor, + "fsmonitor_refresh_callback MAP: '%s' '%s'", + name, canonical_path.buf); + + /* + * The dir-name-hash only tells us the corrected spelling of + * the prefix. We have to use this canonical path to do a + * lookup in the cache-entry array so that we repeat the + * original search using the case-corrected spelling. + */ + strbuf_addch(&canonical_path, '/'); + pos = index_name_pos(istate, canonical_path.buf, + canonical_path.len); + nr_in_cone = handle_path_with_trailing_slash( + istate, canonical_path.buf, pos); + strbuf_release(&canonical_path); + return nr_in_cone; +} + +/* + * The daemon sent an observed pathname without a trailing slash. + * (This is the normal case.) We do not know if it is a tracked or + * untracked file, a sparse-directory, or a populated directory (on a + * platform such as Windows where FSEvents are not qualified). + * + * The pathname contains the observed case reported by the FS. We + * do not know it is case-correct or -incorrect. + * + * Assume it is case-correct and try an exact match. + * + * Return the number of cache-entries that we invalidated. + */ +static size_t handle_path_without_trailing_slash( + struct index_state *istate, const char *name, int pos) +{ + /* + * Mark the untracked cache dirty for this path (regardless of + * whether or not we find an exact match for it in the index). + * Since the path is unqualified (no trailing slash hint in the + * FSEvent), it may refer to a file or directory. So we should + * not assume one or the other and should always let the untracked + * cache decide what needs to invalidated. + */ + untracked_cache_invalidate_trimmed_path(istate, name, 0); + + if (pos >= 0) { /* - * We have an exact match for this path and can just - * invalidate it. + * An exact match on a tracked file. We assume that we + * do not need to scan forward for a sparse-directory + * cache-entry with the same pathname, nor for a cone + * at that directory. (That is, assume no D/F conflicts.) */ - istate->cache[pos]->ce_flags &= ~CE_FSMONITOR_VALID; + invalidate_ce_fsm(istate->cache[pos]); + return 1; } else { + size_t nr_in_cone; + struct strbuf work_path = STRBUF_INIT; + /* - * The path is not a tracked file -or- it is a - * directory event on a platform that cannot - * distinguish between file and directory events in - * the event handler, such as Windows. - * - * Scan as if it is a directory and invalidate the - * cone under it. (But remember to ignore items - * between "name" and "name/", such as "name-" and - * "name.". + * The negative "pos" gives us the suggested insertion + * point for the pathname (without the trailing slash). + * We need to see if there is a directory with that + * prefix, but there can be lots of pathnames between + * "foo" and "foo/" like "foo-" or "foo-bar", so we + * don't want to do our own scan. */ + strbuf_add(&work_path, name, strlen(name)); + strbuf_addch(&work_path, '/'); + pos = index_name_pos(istate, work_path.buf, work_path.len); + nr_in_cone = handle_path_with_trailing_slash( + istate, work_path.buf, pos); + strbuf_release(&work_path); + return nr_in_cone; + } +} + +/* + * The daemon can decorate directory events, such as a move or rename, + * by adding a trailing slash to the observed name. Use this to + * explicitly invalidate the entire cone under that directory. + * + * The daemon can only reliably do that if the OS FSEvent contains + * sufficient information in the event. + * + * macOS FSEvents have enough information. + * + * Other platforms may or may not be able to do it (and it might + * depend on the type of event (for example, a daemon could lstat() an + * observed pathname after a rename, but not after a delete)). + * + * If we find an exact match in the index for a path with a trailing + * slash, it means that we matched a sparse-index directory in a + * cone-mode sparse-checkout (since that's the only time we have + * directories in the index). We should never see this in practice + * (because sparse directories should not be present and therefore + * not generating FS events). Either way, we can treat them in the + * same way and just invalidate the cache-entry and the untracked + * cache (and in this case, the forward cache-entry scan won't find + * anything and it doesn't hurt to let it run). + * + * Return the number of cache-entries that we invalidated. We will + * use this later to determine if we need to attempt a second + * case-insensitive search on case-insensitive file systems. That is, + * if the search using the observed-case in the FSEvent yields any + * results, we assume the prefix is case-correct. If there are no + * matches, we still don't know if the observed path is simply + * untracked or case-incorrect. + */ +static size_t handle_path_with_trailing_slash( + struct index_state *istate, const char *name, int pos) +{ + int i; + size_t nr_in_cone = 0; + + /* + * Mark the untracked cache dirty for this directory path + * (regardless of whether or not we find an exact match for it + * in the index or find it to be proper prefix of one or more + * files in the index), since the FSEvent is hinting that + * there may be changes on or within the directory. + */ + untracked_cache_invalidate_trimmed_path(istate, name, 0); + + if (pos < 0) pos = -pos - 1; - for (i = pos; i < istate->cache_nr; i++) { - if (!starts_with(istate->cache[i]->name, name)) - break; - if ((unsigned char)istate->cache[i]->name[len] > '/') - break; - if (istate->cache[i]->name[len] == '/') - istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID; - } + /* Mark all entries for the folder invalid */ + for (i = pos; i < istate->cache_nr; i++) { + if (!starts_with(istate->cache[i]->name, name)) + break; + invalidate_ce_fsm(istate->cache[i]); + nr_in_cone++; } + return nr_in_cone; +} + +static void fsmonitor_refresh_callback(struct index_state *istate, char *name) +{ + int len = strlen(name); + int pos = index_name_pos(istate, name, len); + size_t nr_in_cone; + + trace_printf_key(&trace_fsmonitor, + "fsmonitor_refresh_callback '%s' (pos %d)", + name, pos); + + if (name[len - 1] == '/') + nr_in_cone = handle_path_with_trailing_slash(istate, name, pos); + else + nr_in_cone = handle_path_without_trailing_slash(istate, name, pos); + /* - * Mark the untracked cache dirty even if it wasn't found in the index - * as it could be a new untracked file. + * If we did not find an exact match for this pathname or any + * cache-entries with this directory prefix and we're on a + * case-insensitive file system, try again using the name-hash + * and dir-name-hash. */ - untracked_cache_invalidate_path(istate, name, 0); + if (!nr_in_cone && ignore_case) { + nr_in_cone = handle_using_name_hash_icase(istate, name); + if (!nr_in_cone) + nr_in_cone = handle_using_dir_name_hash_icase( + istate, name); + } + + if (nr_in_cone) + trace_printf_key(&trace_fsmonitor, + "fsmonitor_refresh_callback CNT: %d", + (int)nr_in_cone); } /* diff --git a/git-compat-util.h b/git-compat-util.h index 7c2a6538e5..ca7678a379 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -218,6 +218,18 @@ struct strbuf; #define GIT_WINDOWS_NATIVE #endif +#if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE) +static inline int _have_unix_sockets(void) +{ +#if defined(NO_UNIX_SOCKETS) + return 0; +#else + return 1; +#endif +} +#define have_unix_sockets _have_unix_sockets +#endif + #include <unistd.h> #include <stdio.h> #include <sys/stat.h> @@ -391,6 +403,7 @@ char *gitdirname(char *); #ifndef NO_OPENSSL #ifdef __APPLE__ +#undef __AVAILABILITY_MACROS_USES_AVAILABILITY #define __AVAILABILITY_MACROS_USES_AVAILABILITY 0 #include <AvailabilityMacros.h> #undef DEPRECATED_ATTRIBUTE diff --git a/git-curl-compat.h b/git-curl-compat.h index fd96b3cdff..e1d0bdd273 100644 --- a/git-curl-compat.h +++ b/git-curl-compat.h @@ -127,6 +127,15 @@ #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. + */ +#if LIBCURL_VERSION_NUM < 0x074200 +#define GIT_CURL_NEED_TRANSFER_ENCODING_HEADER +#endif + +/** * CURLOPT_PROTOCOLS_STR and CURLOPT_REDIR_PROTOCOLS_STR were added in 7.85.0, * released in August 2022. */ diff --git a/git-difftool--helper.sh b/git-difftool--helper.sh index e4e820e680..dd0c9a5b7f 100755 --- a/git-difftool--helper.sh +++ b/git-difftool--helper.sh @@ -91,6 +91,19 @@ then # ignore the error from the above --- run_merge_tool # will diagnose unusable tool by itself run_merge_tool "$merge_tool" false + + status=$? + if test $status -ge 126 + then + # Command not found (127), not executable (126) or + # exited via a signal (>= 128). + exit $status + fi + + if test "$GIT_DIFFTOOL_TRUST_EXIT_CODE" = true + then + exit $status + fi else # Launch the merge tool on each path provided by 'git diff' while test $# -gt 6 diff --git a/git-gui/.gitattributes b/git-gui/.gitattributes index 59cd41dbff..118d56cfbd 100644 --- a/git-gui/.gitattributes +++ b/git-gui/.gitattributes @@ -3,3 +3,4 @@ git-gui.sh encoding=UTF-8 /po/*.po encoding=UTF-8 /GIT-VERSION-GEN eol=lf +Makefile whitespace=!indent,trail,space diff --git a/git-gui/Makefile b/git-gui/Makefile index 3f80435436..667c39ed56 100644 --- a/git-gui/Makefile +++ b/git-gui/Makefile @@ -107,12 +107,12 @@ endif ifeq ($(uname_S),Darwin) TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app - ifeq ($(shell echo "$(uname_R)" | awk -F. '{if ($$1 >= 9) print "y"}')_$(shell test -d $(TKFRAMEWORK) || echo n),y_n) + ifeq ($(shell echo "$(uname_R)" | awk -F. '{if ($$1 >= 9) print "y"}')_$(shell test -d $(TKFRAMEWORK) || echo n),y_n) TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish.app - ifeq ($(shell test -d $(TKFRAMEWORK) || echo n),n) + ifeq ($(shell test -d $(TKFRAMEWORK) || echo n),n) TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app - endif - endif + endif + endif TKEXECUTABLE = $(shell basename "$(TKFRAMEWORK)" .app) endif @@ -143,9 +143,9 @@ ifeq ($(exedir),$(gg_libdir)) endif gg_libdir_sed_in := $(gg_libdir) ifeq ($(uname_S),Darwin) - ifeq ($(shell test -d $(TKFRAMEWORK) && echo y),y) + ifeq ($(shell test -d $(TKFRAMEWORK) && echo y),y) GITGUI_MACOSXAPP := YesPlease - endif + endif endif ifneq (,$(findstring MINGW,$(uname_S))) ifeq ($(shell expr "$(uname_R)" : '1\.'),2) @@ -220,9 +220,9 @@ ifdef NO_MSGFMT MSGFMT ?= $(TCL_PATH) po/po2msg.sh else MSGFMT ?= msgfmt - ifneq ($(shell $(MSGFMT) --tcl -l C -d . /dev/null 2>/dev/null; echo $$?),0) + ifneq ($(shell $(MSGFMT) --tcl -l C -d . /dev/null 2>/dev/null; echo $$?),0) MSGFMT := $(TCL_PATH) po/po2msg.sh - endif + endif endif msgsdir = $(gg_libdir)/msgs diff --git a/git-quiltimport.sh b/git-quiltimport.sh index e3d3909743..eb34cda409 100755 --- a/git-quiltimport.sh +++ b/git-quiltimport.sh @@ -148,7 +148,7 @@ do if [ -z "$dry_run" ] ; then git apply --index -C1 ${level:+"$level"} "$tmp_patch" && tree=$(git write-tree) && - commit=$( (echo "$SUBJECT"; echo; cat "$tmp_msg") | git commit-tree $tree -p $commit) && + commit=$( { echo "$SUBJECT"; echo; cat "$tmp_msg"; } | git commit-tree $tree -p $commit) && git update-ref -m "quiltimport: $patch_name" HEAD $commit || exit 4 fi done 3<"$QUILT_SERIES" @@ -4,6 +4,7 @@ #include "exec-cmd.h" #include "gettext.h" #include "help.h" +#include "object-file.h" #include "pager.h" #include "read-cache-ll.h" #include "run-command.h" @@ -186,6 +187,11 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) use_pager = 0; if (envchanged) *envchanged = 1; + } else if (!strcmp(cmd, "--no-lazy-fetch")) { + fetch_if_missing = 0; + setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1); + if (envchanged) + *envchanged = 1; } else if (!strcmp(cmd, "--no-replace-objects")) { disable_replace_refs(); setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1); @@ -373,8 +379,6 @@ static int handle_alias(int *argcp, const char ***argv) strvec_pushv(&child.args, (*argv) + 1); trace2_cmd_alias(alias_command, child.args.v); - trace2_cmd_list_config(); - trace2_cmd_list_env_vars(); trace2_cmd_name("_run_shell_alias_"); ret = run_command(&child); @@ -411,8 +415,6 @@ static int handle_alias(int *argcp, const char ***argv) COPY_ARRAY(new_argv + count, *argv + 1, *argcp); trace2_cmd_alias(alias_command, new_argv); - trace2_cmd_list_config(); - trace2_cmd_list_env_vars(); *argv = new_argv; *argcp += count - 1; @@ -462,8 +464,6 @@ 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); - trace2_cmd_list_config(); - trace2_cmd_list_env_vars(); validate_cache_entries(the_repository->index); status = p->fn(argc, argv, prefix); diff --git a/gitk-git/Makefile b/gitk-git/Makefile index 5bdd52a6eb..e1f0aff4a1 100644 --- a/gitk-git/Makefile +++ b/gitk-git/Makefile @@ -33,9 +33,9 @@ ifdef NO_MSGFMT MSGFMT ?= $(TCL_PATH) po/po2msg.sh else MSGFMT ?= msgfmt - ifneq ($(shell $(MSGFMT) --tcl -l C -d . /dev/null 2>/dev/null; echo $$?),0) + ifneq ($(shell $(MSGFMT) --tcl -l C -d . /dev/null 2>/dev/null; echo $$?),0) MSGFMT := $(TCL_PATH) po/po2msg.sh - endif + endif endif PO_TEMPLATE = po/gitk.pot diff --git a/gpg-interface.c b/gpg-interface.c index 95e764acb1..1ff94266d2 100644 --- a/gpg-interface.c +++ b/gpg-interface.c @@ -483,7 +483,7 @@ static int verify_ssh_signed_buffer(struct signature_check *sigc, if (sigc->payload_timestamp) strbuf_addf(&verify_time, "-Overify-time=%s", - show_date(sigc->payload_timestamp, 0, &verify_date_mode)); + show_date(sigc->payload_timestamp, 0, verify_date_mode)); /* Find the principal from the signers */ strvec_pushl(&ssh_keygen.args, fmt->program, @@ -586,8 +586,8 @@ static int verify_ssh_signed_buffer(struct signature_check *sigc, } } - strbuf_stripspace(&ssh_keygen_out, '\0'); - strbuf_stripspace(&ssh_keygen_err, '\0'); + strbuf_stripspace(&ssh_keygen_out, NULL); + strbuf_stripspace(&ssh_keygen_err, NULL); /* Add stderr outputs to show the user actual ssh-keygen errors */ strbuf_add(&ssh_keygen_out, ssh_principals_err.buf, ssh_principals_err.len); strbuf_add(&ssh_keygen_out, ssh_keygen_err.buf, ssh_keygen_err.len); @@ -621,7 +621,7 @@ static struct grep_expr *compile_pattern_atom(struct grep_pat **list) *list = p->next; x = compile_pattern_or(list); if (!*list || (*list)->token != GREP_CLOSE_PAREN) - die("unmatched parenthesis"); + die("unmatched ( for expression group"); *list = (*list)->next; return x; default: @@ -792,7 +792,7 @@ void compile_grep_patterns(struct grep_opt *opt) if (p) opt->pattern_expression = compile_pattern_expr(&p); if (p) - die("incomplete pattern expression: %s", p->pattern); + die("incomplete pattern expression group: %s", p->pattern); if (opt->no_body_match && opt->pattern_expression) opt->pattern_expression = grep_not_expr(opt->pattern_expression); @@ -145,6 +145,7 @@ struct object_id { #define GET_OID_RECORD_PATH 0200 #define GET_OID_ONLY_TO_DIE 04000 #define GET_OID_REQUIRE_PATH 010000 +#define GET_OID_HASH_ANY 020000 #define GET_OID_DISAMBIGUATORS \ (GET_OID_COMMIT | GET_OID_COMMITTISH | \ @@ -73,10 +73,15 @@ static inline void oidclr(struct object_id *oid) oid->algo = hash_algo_by_ptr(the_hash_algo); } +static inline void oidread_algop(struct object_id *oid, const unsigned char *hash, const struct git_hash_algo *algop) +{ + memcpy(oid->hash, hash, algop->rawsz); + oid->algo = hash_algo_by_ptr(algop); +} + static inline void oidread(struct object_id *oid, const unsigned char *hash) { - memcpy(oid->hash, hash, the_hash_algo->rawsz); - oid->algo = hash_algo_by_ptr(the_hash_algo); + oidread_algop(oid, hash, the_hash_algo); } static inline int is_empty_blob_sha1(const unsigned char *sha1) diff --git a/http-push.c b/http-push.c index 12d1113741..1fe51226fd 100644 --- a/http-push.c +++ b/http-push.c @@ -1307,7 +1307,7 @@ static struct object_list **process_tree(struct tree *tree, obj->flags |= SEEN; p = add_one_object(obj, p); - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) switch (object_type(entry.mode)) { @@ -1575,8 +1575,11 @@ static int verify_merge_base(struct object_id *head_oid, struct ref *remote) struct commit *head = lookup_commit_or_die(head_oid, "HEAD"); struct commit *branch = lookup_commit_or_die(&remote->old_oid, remote->name); + int ret = repo_in_merge_bases(the_repository, branch, head); - return repo_in_merge_bases(the_repository, branch, head); + if (ret < 0) + exit(128); + return ret; } static int delete_remote_branch(const char *pattern, int force) @@ -1452,6 +1452,7 @@ struct active_request_slot *get_active_slot(void) curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, NULL); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL); + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, -1L); curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0); curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1); diff --git a/imap-send.c b/imap-send.c index f2e1947e63..0afd088d8a 100644 --- a/imap-send.c +++ b/imap-send.c @@ -68,23 +68,6 @@ static void imap_warn(const char *, ...); static char *next_arg(char **); -__attribute__((format (printf, 3, 4))) -static int nfsnprintf(char *buf, int blen, const char *fmt, ...); - -static int nfvasprintf(char **strp, const char *fmt, va_list ap) -{ - int len; - char tmp[8192]; - - len = vsnprintf(tmp, sizeof(tmp), fmt, ap); - if (len < 0) - die("Fatal: Out of memory"); - if (len >= sizeof(tmp)) - die("imap command overflow!"); - *strp = xmemdupz(tmp, len); - return len; -} - struct imap_server_conf { const char *name; const char *tunnel; @@ -500,30 +483,17 @@ static char *next_arg(char **s) return ret; } -__attribute__((format (printf, 3, 4))) -static int nfsnprintf(char *buf, int blen, const char *fmt, ...) -{ - int ret; - va_list va; - - va_start(va, fmt); - if (blen <= 0 || (unsigned)(ret = vsnprintf(buf, blen, fmt, va)) >= (unsigned)blen) - BUG("buffer too small. Please report a bug."); - va_end(va); - return ret; -} - static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx, struct imap_cmd_cb *cb, const char *fmt, va_list ap) { struct imap *imap = ctx->imap; struct imap_cmd *cmd; - int n, bufl; - char buf[1024]; + int n; + struct strbuf buf = STRBUF_INIT; cmd = xmalloc(sizeof(struct imap_cmd)); - nfvasprintf(&cmd->cmd, fmt, ap); + cmd->cmd = xstrvfmt(fmt, ap); cmd->tag = ++imap->nexttag; if (cb) @@ -535,27 +505,30 @@ static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx, get_cmd_result(ctx, NULL); if (!cmd->cb.data) - bufl = nfsnprintf(buf, sizeof(buf), "%d %s\r\n", cmd->tag, cmd->cmd); + strbuf_addf(&buf, "%d %s\r\n", cmd->tag, cmd->cmd); else - bufl = nfsnprintf(buf, sizeof(buf), "%d %s{%d%s}\r\n", - cmd->tag, cmd->cmd, cmd->cb.dlen, - CAP(LITERALPLUS) ? "+" : ""); + strbuf_addf(&buf, "%d %s{%d%s}\r\n", cmd->tag, cmd->cmd, + cmd->cb.dlen, CAP(LITERALPLUS) ? "+" : ""); + if (buf.len > INT_MAX) + die("imap command overflow!"); if (0 < verbosity) { if (imap->num_in_progress) printf("(%d in progress) ", imap->num_in_progress); if (!starts_with(cmd->cmd, "LOGIN")) - printf(">>> %s", buf); + printf(">>> %s", buf.buf); else printf(">>> %d LOGIN <user> <pass>\n", cmd->tag); } - if (socket_write(&imap->buf.sock, buf, bufl) != bufl) { + if (socket_write(&imap->buf.sock, buf.buf, buf.len) != buf.len) { free(cmd->cmd); free(cmd); if (cb) free(cb->data); + strbuf_release(&buf); return NULL; } + strbuf_release(&buf); if (cmd->cb.data) { if (CAP(LITERALPLUS)) { n = socket_write(&imap->buf.sock, cmd->cb.data, cmd->cb.dlen); diff --git a/list-objects-filter.c b/list-objects-filter.c index da287cc8e0..4346f8da45 100644 --- a/list-objects-filter.c +++ b/list-objects-filter.c @@ -711,15 +711,6 @@ static void filter_combine__free(void *filter_data) free(d); } -static void add_all(struct oidset *dest, struct oidset *src) { - struct oidset_iter iter; - struct object_id *src_oid; - - oidset_iter_init(src, &iter); - while ((src_oid = oidset_iter_next(&iter)) != NULL) - oidset_insert(dest, src_oid); -} - static void filter_combine__finalize_omits( struct oidset *omits, void *filter_data) @@ -728,7 +719,7 @@ static void filter_combine__finalize_omits( size_t sub; for (sub = 0; sub < d->nr; sub++) { - add_all(omits, &d->sub[sub].omits); + oidset_insert_from_set(omits, &d->sub[sub].omits); oidset_clear(&d->sub[sub].omits); } } diff --git a/list-objects.c b/list-objects.c index f39b68faf5..11ad8be411 100644 --- a/list-objects.c +++ b/list-objects.c @@ -102,7 +102,7 @@ static void process_tree_contents(struct traversal_context *ctx, enum interesting match = ctx->revs->diffopt.pathspec.nr == 0 ? all_entries_interesting : entry_not_interesting; - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (match != all_entries_interesting) { diff --git a/lockfile.h b/lockfile.h index 90af4e66b2..1bb9926497 100644 --- a/lockfile.h +++ b/lockfile.h @@ -321,11 +321,11 @@ static inline int commit_lock_file_to(struct lock_file *lk, const char *path) * Roll back `lk`: close the file descriptor and/or file pointer and * remove the lockfile. It is a NOOP to call `rollback_lock_file()` * for a `lock_file` object that has already been committed or rolled - * back. + * back. No error will be returned in this case. */ -static inline void rollback_lock_file(struct lock_file *lk) +static inline int rollback_lock_file(struct lock_file *lk) { - delete_tempfile(&lk->tempfile); + return delete_tempfile(&lk->tempfile); } #endif /* LOCKFILE_H */ diff --git a/log-tree.c b/log-tree.c index 337b9334cd..16031b44e7 100644 --- a/log-tree.c +++ b/log-tree.c @@ -470,16 +470,19 @@ void fmt_output_email_subject(struct strbuf *sb, struct rev_info *opt) } void log_write_email_headers(struct rev_info *opt, struct commit *commit, - const char **extra_headers_p, + char **extra_headers_p, int *need_8bit_cte_p, int maybe_multipart) { - const char *extra_headers = opt->extra_headers; + struct strbuf headers = STRBUF_INIT; const char *name = oid_to_hex(opt->zero_commit ? null_oid() : &commit->object.oid); *need_8bit_cte_p = 0; /* unknown */ + if (opt->extra_headers && *opt->extra_headers) + strbuf_addstr(&headers, opt->extra_headers); + fprintf(opt->diffopt.file, "From %s Mon Sep 17 00:00:00 2001\n", name); graph_show_oneline(opt->graph); if (opt->message_id) { @@ -496,16 +499,13 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, graph_show_oneline(opt->graph); } if (opt->mime_boundary && maybe_multipart) { - static struct strbuf subject_buffer = STRBUF_INIT; static struct strbuf buffer = STRBUF_INIT; struct strbuf filename = STRBUF_INIT; *need_8bit_cte_p = -1; /* NEVER */ - strbuf_reset(&subject_buffer); strbuf_reset(&buffer); - strbuf_addf(&subject_buffer, - "%s" + strbuf_addf(&headers, "MIME-Version: 1.0\n" "Content-Type: multipart/mixed;" " boundary=\"%s%s\"\n" @@ -516,10 +516,8 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, "Content-Type: text/plain; " "charset=UTF-8; format=fixed\n" "Content-Transfer-Encoding: 8bit\n\n", - extra_headers ? extra_headers : "", mime_boundary_leader, opt->mime_boundary, mime_boundary_leader, opt->mime_boundary); - extra_headers = subject_buffer.buf; if (opt->numbered_files) strbuf_addf(&filename, "%d", opt->nr); @@ -539,7 +537,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, opt->diffopt.stat_sep = buffer.buf; strbuf_release(&filename); } - *extra_headers_p = extra_headers; + *extra_headers_p = headers.len ? strbuf_detach(&headers, NULL) : NULL; } static void show_sig_lines(struct rev_info *opt, int status, const char *bol) @@ -678,7 +676,6 @@ void show_log(struct rev_info *opt) struct log_info *log = opt->loginfo; struct commit *commit = log->commit, *parent = log->parent; int abbrev_commit = opt->abbrev_commit ? opt->abbrev : the_hash_algo->hexsz; - const char *extra_headers = opt->extra_headers; struct pretty_print_context ctx = {0}; opt->loginfo = NULL; @@ -739,10 +736,9 @@ void show_log(struct rev_info *opt) */ if (cmit_fmt_is_mail(opt->commit_format)) { - log_write_email_headers(opt, commit, &extra_headers, + log_write_email_headers(opt, commit, &ctx.after_subject, &ctx.need_8bit_cte, 1); ctx.rev = opt; - ctx.print_email_subject = 1; } else if (opt->commit_format != CMIT_FMT_USERFORMAT) { fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), opt->diffopt.file); if (opt->commit_format != CMIT_FMT_ONELINE) @@ -777,7 +773,7 @@ void show_log(struct rev_info *opt) */ show_reflog_message(opt->reflog_info, opt->commit_format == CMIT_FMT_ONELINE, - &opt->date_mode, + opt->date_mode, opt->date_mode_explicit); if (opt->commit_format == CMIT_FMT_ONELINE) return; @@ -808,7 +804,6 @@ void show_log(struct rev_info *opt) ctx.date_mode = opt->date_mode; ctx.date_mode_explicit = opt->date_mode_explicit; ctx.abbrev = opt->diffopt.abbrev; - ctx.after_subject = extra_headers; ctx.preserve_subject = opt->preserve_subject; ctx.encode_email_headers = opt->encode_email_headers; ctx.reflog_info = opt->reflog_info; @@ -857,6 +852,7 @@ void show_log(struct rev_info *opt) strbuf_release(&msgbuf); free(ctx.notes_message); + free(ctx.after_subject); if (cmit_fmt_is_mail(ctx.fmt) && opt->idiff_oid1) { struct diff_queue_struct dq; @@ -1011,7 +1007,7 @@ static int do_remerge_diff(struct rev_info *opt, struct object_id *oid) { struct merge_options o; - struct commit_list *bases; + struct commit_list *bases = NULL; struct merge_result res = {0}; struct pretty_print_context ctx = {0}; struct commit *parent1 = parents->item; @@ -1036,7 +1032,8 @@ static int do_remerge_diff(struct rev_info *opt, /* Parse the relevant commits and get the merge bases */ parse_commit_or_die(parent1); parse_commit_or_die(parent2); - bases = repo_get_merge_bases(the_repository, parent1, parent2); + if (repo_get_merge_bases(the_repository, parent1, parent2, &bases) < 0) + exit(128); /* Re-merge the parents */ merge_incore_recursive(&o, bases, parent1, parent2, &res); diff --git a/log-tree.h b/log-tree.h index 41c776fea5..94978e2c83 100644 --- a/log-tree.h +++ b/log-tree.h @@ -29,7 +29,7 @@ void format_decorations(struct strbuf *sb, const struct commit *commit, int use_color, const struct decoration_options *opts); void show_decorations(struct rev_info *opt, struct commit *commit); void log_write_email_headers(struct rev_info *opt, struct commit *commit, - const char **extra_headers_p, + char **extra_headers_p, int *need_8bit_cte_p, int maybe_multipart); void load_ref_decorations(struct decoration_filter *filter, int flags); diff --git a/loose.c b/loose.c new file mode 100644 index 0000000000..f6faa6216a --- /dev/null +++ b/loose.c @@ -0,0 +1,259 @@ +#include "git-compat-util.h" +#include "hash.h" +#include "path.h" +#include "object-store.h" +#include "hex.h" +#include "wrapper.h" +#include "gettext.h" +#include "loose.h" +#include "lockfile.h" +#include "oidtree.h" + +static const char *loose_object_header = "# loose-object-idx\n"; + +static inline int should_use_loose_object_map(struct repository *repo) +{ + return repo->compat_hash_algo && repo->gitdir; +} + +void loose_object_map_init(struct loose_object_map **map) +{ + struct loose_object_map *m; + m = xmalloc(sizeof(**map)); + m->to_compat = kh_init_oid_map(); + m->to_storage = kh_init_oid_map(); + *map = m; +} + +static int insert_oid_pair(kh_oid_map_t *map, const struct object_id *key, const struct object_id *value) +{ + khiter_t pos; + int ret; + struct object_id *stored; + + pos = kh_put_oid_map(map, *key, &ret); + + /* This item already exists in the map. */ + if (ret == 0) + return 0; + + stored = xmalloc(sizeof(*stored)); + oidcpy(stored, value); + kh_value(map, pos) = stored; + return 1; +} + +static int insert_loose_map(struct object_directory *odb, + const struct object_id *oid, + const struct object_id *compat_oid) +{ + struct loose_object_map *map = odb->loose_map; + int inserted = 0; + + inserted |= insert_oid_pair(map->to_compat, oid, compat_oid); + inserted |= insert_oid_pair(map->to_storage, compat_oid, oid); + if (inserted) + oidtree_insert(odb->loose_objects_cache, compat_oid); + + return inserted; +} + +static int load_one_loose_object_map(struct repository *repo, struct object_directory *dir) +{ + struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT; + FILE *fp; + + if (!dir->loose_map) + loose_object_map_init(&dir->loose_map); + if (!dir->loose_objects_cache) { + ALLOC_ARRAY(dir->loose_objects_cache, 1); + oidtree_init(dir->loose_objects_cache); + } + + insert_loose_map(dir, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree); + insert_loose_map(dir, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob); + insert_loose_map(dir, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid); + + strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + fp = fopen(path.buf, "rb"); + if (!fp) { + strbuf_release(&path); + return 0; + } + + errno = 0; + if (strbuf_getwholeline(&buf, fp, '\n') || strcmp(buf.buf, loose_object_header)) + goto err; + while (!strbuf_getline_lf(&buf, fp)) { + const char *p; + struct object_id oid, compat_oid; + if (parse_oid_hex_algop(buf.buf, &oid, &p, repo->hash_algo) || + *p++ != ' ' || + parse_oid_hex_algop(p, &compat_oid, &p, repo->compat_hash_algo) || + p != buf.buf + buf.len) + goto err; + insert_loose_map(dir, &oid, &compat_oid); + } + + strbuf_release(&buf); + strbuf_release(&path); + return errno ? -1 : 0; +err: + strbuf_release(&buf); + strbuf_release(&path); + return -1; +} + +int repo_read_loose_object_map(struct repository *repo) +{ + struct object_directory *dir; + + if (!should_use_loose_object_map(repo)) + return 0; + + prepare_alt_odb(repo); + + for (dir = repo->objects->odb; dir; dir = dir->next) { + if (load_one_loose_object_map(repo, dir) < 0) { + return -1; + } + } + return 0; +} + +int repo_write_loose_object_map(struct repository *repo) +{ + kh_oid_map_t *map = repo->objects->odb->loose_map->to_compat; + struct lock_file lock; + int fd; + khiter_t iter; + struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT; + + if (!should_use_loose_object_map(repo)) + return 0; + + strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + fd = hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); + iter = kh_begin(map); + if (write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0) + goto errout; + + 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)) + 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) + goto errout; + strbuf_reset(&buf); + } + } + strbuf_release(&buf); + if (commit_lock_file(&lock) < 0) { + error_errno(_("could not write loose object index %s"), path.buf); + strbuf_release(&path); + return -1; + } + strbuf_release(&path); + return 0; +errout: + rollback_lock_file(&lock); + strbuf_release(&buf); + error_errno(_("failed to write loose object index %s\n"), path.buf); + strbuf_release(&path); + return -1; +} + +static int write_one_object(struct repository *repo, const struct object_id *oid, + const struct object_id *compat_oid) +{ + struct lock_file lock; + int fd; + struct stat st; + struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT; + + strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); + hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); + + fd = open(path.buf, O_WRONLY | O_CREAT | O_APPEND, 0666); + if (fd < 0) + goto errout; + if (fstat(fd, &st) < 0) + goto errout; + if (!st.st_size && write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0) + goto errout; + + strbuf_addf(&buf, "%s %s\n", oid_to_hex(oid), oid_to_hex(compat_oid)); + if (write_in_full(fd, buf.buf, buf.len) < 0) + goto errout; + if (close(fd)) + goto errout; + adjust_shared_perm(path.buf); + rollback_lock_file(&lock); + strbuf_release(&buf); + strbuf_release(&path); + return 0; +errout: + error_errno(_("failed to write loose object index %s\n"), path.buf); + close(fd); + rollback_lock_file(&lock); + strbuf_release(&buf); + strbuf_release(&path); + return -1; +} + +int repo_add_loose_object_map(struct repository *repo, const struct object_id *oid, + const struct object_id *compat_oid) +{ + int inserted = 0; + + if (!should_use_loose_object_map(repo)) + return 0; + + inserted = insert_loose_map(repo->objects->odb, oid, compat_oid); + if (inserted) + return write_one_object(repo, oid, compat_oid); + return 0; +} + +int repo_loose_object_map_oid(struct repository *repo, + const struct object_id *src, + const struct git_hash_algo *to, + struct object_id *dest) +{ + struct object_directory *dir; + kh_oid_map_t *map; + khiter_t pos; + + for (dir = repo->objects->odb; dir; dir = dir->next) { + struct loose_object_map *loose_map = dir->loose_map; + if (!loose_map) + continue; + map = (to == repo->compat_hash_algo) ? + loose_map->to_compat : + loose_map->to_storage; + pos = kh_get_oid_map(map, *src); + if (pos < kh_end(map)) { + oidcpy(dest, kh_value(map, pos)); + return 0; + } + } + return -1; +} + +void loose_object_map_clear(struct loose_object_map **map) +{ + struct loose_object_map *m = *map; + struct object_id *oid; + + if (!m) + return; + + kh_foreach_value(m->to_compat, oid, free(oid)); + kh_foreach_value(m->to_storage, oid, free(oid)); + kh_destroy_oid_map(m->to_compat); + kh_destroy_oid_map(m->to_storage); + free(m); + *map = NULL; +} diff --git a/loose.h b/loose.h new file mode 100644 index 0000000000..2c2957072c --- /dev/null +++ b/loose.h @@ -0,0 +1,22 @@ +#ifndef LOOSE_H +#define LOOSE_H + +#include "khash.h" + +struct loose_object_map { + kh_oid_map_t *to_compat; + kh_oid_map_t *to_storage; +}; + +void loose_object_map_init(struct loose_object_map **map); +void loose_object_map_clear(struct loose_object_map **map); +int repo_loose_object_map_oid(struct repository *repo, + const struct object_id *src, + const struct git_hash_algo *dest_algo, + struct object_id *dest); +int repo_add_loose_object_map(struct repository *repo, const struct object_id *oid, + const struct object_id *compat_oid); +int repo_read_loose_object_map(struct repository *repo); +int repo_write_loose_object_map(struct repository *repo); + +#endif diff --git a/match-trees.c b/match-trees.c index 0885ac681c..3412b6a140 100644 --- a/match-trees.c +++ b/match-trees.c @@ -63,7 +63,7 @@ static void *fill_tree_desc_strict(struct tree_desc *desc, die("unable to read tree (%s)", oid_to_hex(hash)); if (type != OBJ_TREE) die("%s is not a tree", oid_to_hex(hash)); - init_tree_desc(desc, buffer, size); + init_tree_desc(desc, hash, buffer, size); return buffer; } @@ -194,7 +194,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix, buf = repo_read_object_file(the_repository, oid1, &type, &sz); if (!buf) die("cannot read tree %s", oid_to_hex(oid1)); - init_tree_desc(&desc, buf, sz); + init_tree_desc(&desc, oid1, buf, sz); rewrite_here = NULL; while (desc.size) { diff --git a/mem-pool.c b/mem-pool.c index c7d6256020..a3ba38831d 100644 --- a/mem-pool.c +++ b/mem-pool.c @@ -4,6 +4,7 @@ #include "git-compat-util.h" #include "mem-pool.h" +#include "gettext.h" #define BLOCK_GROWTH_SIZE (1024 * 1024 - sizeof(struct mp_block)) @@ -107,6 +108,47 @@ void *mem_pool_alloc(struct mem_pool *pool, size_t len) return r; } +static char *mem_pool_strvfmt(struct mem_pool *pool, const char *fmt, + va_list ap) +{ + struct mp_block *block = pool->mp_block; + char *next_free = block ? block->next_free : NULL; + size_t available = block ? block->end - block->next_free : 0; + va_list cp; + int len, len2; + size_t size; + char *ret; + + va_copy(cp, ap); + len = vsnprintf(next_free, available, fmt, cp); + va_end(cp); + if (len < 0) + die(_("unable to format message: %s"), fmt); + + size = st_add(len, 1); /* 1 for NUL */ + ret = mem_pool_alloc(pool, size); + + /* Shortcut; relies on mem_pool_alloc() not touching buffer contents. */ + if (ret == next_free) + return ret; + + len2 = vsnprintf(ret, size, fmt, ap); + if (len2 != len) + BUG("your vsnprintf is broken (returns inconsistent lengths)"); + return ret; +} + +char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = mem_pool_strvfmt(pool, fmt, ap); + va_end(ap); + return ret; +} + void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size) { size_t len = st_mult(count, size); diff --git a/mem-pool.h b/mem-pool.h index fe7507f022..d1c66413ec 100644 --- a/mem-pool.h +++ b/mem-pool.h @@ -48,6 +48,11 @@ char *mem_pool_strdup(struct mem_pool *pool, const char *str); char *mem_pool_strndup(struct mem_pool *pool, const char *str, size_t len); /* + * Allocate memory from the memory pool and format a string into it. + */ +char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...); + +/* * Move the memory associated with the 'src' pool to the 'dst' pool. The 'src' * pool will be empty and not contain any memory. It still needs to be free'd * with a call to `mem_pool_discard`. diff --git a/merge-ll.c b/merge-ll.c index 5ffb045efb..bf1077ae09 100644 --- a/merge-ll.c +++ b/merge-ll.c @@ -128,7 +128,9 @@ static enum ll_merge_result ll_xdl_merge(const struct ll_merge_driver *drv_unuse xmp.level = XDL_MERGE_ZEALOUS; xmp.favor = opts->variant; xmp.xpp.flags = opts->xdl_opts; - if (git_xmerge_style >= 0) + if (opts->conflict_style >= 0) + xmp.style = opts->conflict_style; + else if (git_xmerge_style >= 0) xmp.style = git_xmerge_style; if (marker_size > 0) xmp.marker_size = marker_size; @@ -292,7 +294,7 @@ static int read_merge_config(const char *var, const char *value, * after seeing merge.<name>.var1. */ for (fn = ll_user_merge; fn; fn = fn->next) - if (!strncmp(fn->name, name, namelen) && !fn->name[namelen]) + if (!xstrncmpz(fn->name, name, namelen)) break; if (!fn) { CALLOC_ARRAY(fn, 1); @@ -401,7 +403,7 @@ enum ll_merge_result ll_merge(mmbuffer_t *result_buf, const struct ll_merge_options *opts) { struct attr_check *check = load_merge_attributes(); - static const struct ll_merge_options default_opts; + static const struct ll_merge_options default_opts = LL_MERGE_OPTIONS_INIT; const char *ll_driver_name = NULL; int marker_size = DEFAULT_CONFLICT_MARKER_SIZE; const struct ll_merge_driver *driver; diff --git a/merge-ll.h b/merge-ll.h index e4a20e81a3..d038ee0c1e 100644 --- a/merge-ll.h +++ b/merge-ll.h @@ -78,10 +78,15 @@ struct ll_merge_options { */ unsigned extra_marker_size; + /* Override the global conflict style. */ + int conflict_style; + /* Extra xpparam_t flags as defined in xdiff/xdiff.h. */ long xdl_opts; }; +#define LL_MERGE_OPTIONS_INIT { .conflict_style = -1 } + enum ll_merge_result { LL_MERGE_ERROR = -1, LL_MERGE_OK = 0, diff --git a/merge-ort.c b/merge-ort.c index 8617babee4..eaede6cead 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -18,6 +18,7 @@ #include "merge-ort.h" #include "alloc.h" +#include "advice.h" #include "attr.h" #include "cache-tree.h" #include "commit.h" @@ -542,6 +543,7 @@ enum conflict_and_info_types { CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, CONFLICT_SUBMODULE_NULL_MERGE_BASE, + CONFLICT_SUBMODULE_CORRUPT, /* Keep this entry _last_ in the list */ NB_CONFLICT_TYPES, @@ -594,7 +596,9 @@ static const char *type_short_descriptions[] = { [CONFLICT_SUBMODULE_MAY_HAVE_REWINDS] = "CONFLICT (submodule may have rewinds)", [CONFLICT_SUBMODULE_NULL_MERGE_BASE] = - "CONFLICT (submodule lacks merge base)" + "CONFLICT (submodule lacks merge base)", + [CONFLICT_SUBMODULE_CORRUPT] = + "CONFLICT (submodule corrupt)" }; struct logical_conflict_info { @@ -1657,12 +1661,14 @@ static int collect_merge_info(struct merge_options *opt, info.data = opt; info.show_all_errors = 1; - parse_tree(merge_base); - parse_tree(side1); - parse_tree(side2); - init_tree_desc(t + 0, merge_base->buffer, merge_base->size); - init_tree_desc(t + 1, side1->buffer, side1->size); - init_tree_desc(t + 2, side2->buffer, side2->size); + if (parse_tree(merge_base) < 0 || + parse_tree(side1) < 0 || + parse_tree(side2) < 0) + return -1; + init_tree_desc(t + 0, &merge_base->object.oid, + merge_base->buffer, merge_base->size); + init_tree_desc(t + 1, &side1->object.oid, side1->buffer, side1->size); + init_tree_desc(t + 2, &side2->object.oid, side2->buffer, side2->size); trace2_region_enter("merge", "traverse_trees", opt->repo); ret = traverse_trees(NULL, 3, t, &info); @@ -1708,7 +1714,14 @@ static int find_first_merges(struct repository *repo, die("revision walk setup failed"); while ((commit = get_revision(&revs)) != NULL) { struct object *o = &(commit->object); - if (repo_in_merge_bases(repo, b, commit)) + int ret = repo_in_merge_bases(repo, b, commit); + + if (ret < 0) { + object_array_clear(&merges); + release_revisions(&revs); + return ret; + } + if (ret > 0) add_object_array(o, NULL, &merges); } reset_revision_walk(); @@ -1723,9 +1736,17 @@ static int find_first_merges(struct repository *repo, contains_another = 0; for (j = 0; j < merges.nr; j++) { struct commit *m2 = (struct commit *) merges.objects[j].item; - if (i != j && repo_in_merge_bases(repo, m2, m1)) { - contains_another = 1; - break; + if (i != j) { + int ret = repo_in_merge_bases(repo, m2, m1); + if (ret < 0) { + object_array_clear(&merges); + release_revisions(&revs); + return ret; + } + if (ret > 0) { + contains_another = 1; + break; + } } } @@ -1747,7 +1768,7 @@ static int merge_submodule(struct merge_options *opt, { struct repository subrepo; struct strbuf sb = STRBUF_INIT; - int ret = 0; + int ret = 0, ret2; struct commit *commit_o, *commit_a, *commit_b; int parent_count; struct object_array merges; @@ -1794,8 +1815,28 @@ static int merge_submodule(struct merge_options *opt, } /* check whether both changes are forward */ - if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) || - !repo_in_merge_bases(&subrepo, commit_o, commit_b)) { + ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_a); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (ret2 > 0) + ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_b); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (!ret2) { path_msg(opt, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, 0, path, NULL, NULL, NULL, _("Failed to merge submodule %s " @@ -1805,7 +1846,17 @@ static int merge_submodule(struct merge_options *opt, } /* Case #1: a is contained in b or vice versa */ - if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) { + ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (ret2 > 0) { oidcpy(result, b); path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1, path, NULL, NULL, NULL, @@ -1814,7 +1865,17 @@ static int merge_submodule(struct merge_options *opt, ret = 1; goto cleanup; } - if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) { + ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a); + if (ret2 < 0) { + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + goto cleanup; + } + if (ret2 > 0) { oidcpy(result, a); path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1, path, NULL, NULL, NULL, @@ -1839,6 +1900,14 @@ static int merge_submodule(struct merge_options *opt, parent_count = find_first_merges(&subrepo, path, commit_a, commit_b, &merges); switch (parent_count) { + case -1: + path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0, + path, NULL, NULL, NULL, + _("Failed to merge submodule %s " + "(repository corrupt)"), + path); + ret = -1; + break; case 0: path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE, 0, path, NULL, NULL, NULL, @@ -1956,7 +2025,7 @@ static int merge_3way(struct merge_options *opt, mmbuffer_t *result_buf) { mmfile_t orig, src1, src2; - struct ll_merge_options ll_opts = {0}; + struct ll_merge_options ll_opts = LL_MERGE_OPTIONS_INIT; char *base, *name1, *name2; enum ll_merge_result merge_status; @@ -1966,6 +2035,7 @@ static int merge_3way(struct merge_options *opt, ll_opts.renormalize = opt->renormalize; ll_opts.extra_marker_size = extra_marker_size; ll_opts.xdl_opts = opt->xdl_opts; + ll_opts.conflict_style = opt->conflict_style; if (opt->priv->call_depth) { ll_opts.virtual_ancestor = 1; @@ -4376,10 +4446,12 @@ static int checkout(struct merge_options *opt, unpack_opts.verbose_update = (opt->verbosity > 2); unpack_opts.fn = twoway_merge; unpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */ - parse_tree(prev); - init_tree_desc(&trees[0], prev->buffer, prev->size); - parse_tree(next); - init_tree_desc(&trees[1], next->buffer, next->size); + if (parse_tree(prev) < 0) + return -1; + init_tree_desc(&trees[0], &prev->object.oid, prev->buffer, prev->size); + if (parse_tree(next) < 0) + return -1; + init_tree_desc(&trees[1], &next->object.oid, next->buffer, next->size); ret = unpack_trees(2, trees, &unpack_opts); clear_unpack_trees_porcelain(&unpack_opts); @@ -4556,7 +4628,7 @@ static void print_submodule_conflict_suggestion(struct string_list *csub) { " - commit the resulting index in the superproject\n"), tmp.buf, subs.buf); - printf("%s", msg.buf); + advise_if_enabled(ADVICE_SUBMODULE_MERGE_CONFLICT, "%s", msg.buf); strbuf_release(&subs); strbuf_release(&tmp); @@ -4982,6 +5054,9 @@ redo: if (result->clean >= 0) { result->tree = parse_tree_indirect(&working_tree_oid); + if (!result->tree) + die(_("unable to read tree (%s)"), + oid_to_hex(&working_tree_oid)); /* existence of conflicted entries implies unclean */ result->clean &= strmap_empty(&opt->priv->conflicted); } @@ -5007,7 +5082,11 @@ static void merge_ort_internal(struct merge_options *opt, struct strbuf merge_base_abbrev = STRBUF_INIT; if (!merge_bases) { - merge_bases = repo_get_merge_bases(the_repository, h1, h2); + if (repo_get_merge_bases(the_repository, h1, h2, + &merge_bases) < 0) { + result->clean = -1; + return; + } /* See merge-ort.h:merge_incore_recursive() declaration NOTE */ merge_bases = reverse_commit_list(merge_bases); } diff --git a/merge-recursive.c b/merge-recursive.c index a0c3e7a2d9..8ff29ed09e 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -405,8 +405,9 @@ static inline int merge_detect_rename(struct merge_options *opt) static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree) { - parse_tree(tree); - init_tree_desc(desc, tree->buffer, tree->size); + if (parse_tree(tree) < 0) + exit(128); + init_tree_desc(desc, &tree->object.oid, tree->buffer, tree->size); } static int unpack_trees_start(struct merge_options *opt, @@ -1047,13 +1048,14 @@ static int merge_3way(struct merge_options *opt, const int extra_marker_size) { mmfile_t orig, src1, src2; - struct ll_merge_options ll_opts = {0}; + struct ll_merge_options ll_opts = LL_MERGE_OPTIONS_INIT; char *base, *name1, *name2; enum ll_merge_result merge_status; ll_opts.renormalize = opt->renormalize; ll_opts.extra_marker_size = extra_marker_size; ll_opts.xdl_opts = opt->xdl_opts; + ll_opts.conflict_style = opt->conflict_style; if (opt->priv->call_depth) { ll_opts.virtual_ancestor = 1; @@ -1139,7 +1141,13 @@ static int find_first_merges(struct repository *repo, die("revision walk setup failed"); while ((commit = get_revision(&revs)) != NULL) { struct object *o = &(commit->object); - if (repo_in_merge_bases(repo, b, commit)) + int ret = repo_in_merge_bases(repo, b, commit); + if (ret < 0) { + object_array_clear(&merges); + release_revisions(&revs); + return ret; + } + if (ret) add_object_array(o, NULL, &merges); } reset_revision_walk(); @@ -1154,9 +1162,17 @@ static int find_first_merges(struct repository *repo, contains_another = 0; for (j = 0; j < merges.nr; j++) { struct commit *m2 = (struct commit *) merges.objects[j].item; - if (i != j && repo_in_merge_bases(repo, m2, m1)) { - contains_another = 1; - break; + if (i != j) { + int ret = repo_in_merge_bases(repo, m2, m1); + if (ret < 0) { + object_array_clear(&merges); + release_revisions(&revs); + return ret; + } + if (ret > 0) { + contains_another = 1; + break; + } } } @@ -1192,7 +1208,7 @@ static int merge_submodule(struct merge_options *opt, const struct object_id *b) { struct repository subrepo; - int ret = 0; + int ret = 0, ret2; struct commit *commit_base, *commit_a, *commit_b; int parent_count; struct object_array merges; @@ -1229,14 +1245,32 @@ static int merge_submodule(struct merge_options *opt, } /* check whether both changes are forward */ - if (!repo_in_merge_bases(&subrepo, commit_base, commit_a) || - !repo_in_merge_bases(&subrepo, commit_base, commit_b)) { + ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_a); + if (ret2 < 0) { + output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path); + ret = -1; + goto cleanup; + } + if (ret2 > 0) + ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_b); + if (ret2 < 0) { + output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path); + ret = -1; + goto cleanup; + } + if (!ret2) { output(opt, 1, _("Failed to merge submodule %s (commits don't follow merge-base)"), path); goto cleanup; } /* Case #1: a is contained in b or vice versa */ - if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) { + ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b); + if (ret2 < 0) { + output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path); + ret = -1; + goto cleanup; + } + if (ret2) { oidcpy(result, b); if (show(opt, 3)) { output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path); @@ -1249,7 +1283,13 @@ static int merge_submodule(struct merge_options *opt, ret = 1; goto cleanup; } - if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) { + ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a); + if (ret2 < 0) { + output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path); + ret = -1; + goto cleanup; + } + if (ret2) { oidcpy(result, a); if (show(opt, 3)) { output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path); @@ -1278,6 +1318,10 @@ static int merge_submodule(struct merge_options *opt, parent_count = find_first_merges(&subrepo, &merges, path, commit_a, commit_b); switch (parent_count) { + case -1: + output(opt, 1,_("Failed to merge submodule %s (repository corrupt)"), path); + ret = -1; + break; case 0: output(opt, 1, _("Failed to merge submodule %s (merge following commits not found)"), path); break; @@ -1392,11 +1436,14 @@ static int merge_mode_and_contents(struct merge_options *opt, /* FIXME: bug, what if modes didn't match? */ result->clean = (merge_status == 0); } else if (S_ISGITLINK(a->mode)) { - result->clean = merge_submodule(opt, &result->blob.oid, - o->path, - &o->oid, - &a->oid, - &b->oid); + int clean = merge_submodule(opt, &result->blob.oid, + o->path, + &o->oid, + &a->oid, + &b->oid); + if (clean < 0) + return -1; + result->clean = clean; } else if (S_ISLNK(a->mode)) { switch (opt->recursive_variant) { case MERGE_VARIANT_NORMAL: @@ -3597,7 +3644,9 @@ static int merge_recursive_internal(struct merge_options *opt, } if (!merge_bases) { - merge_bases = repo_get_merge_bases(the_repository, h1, h2); + if (repo_get_merge_bases(the_repository, h1, h2, + &merge_bases) < 0) + return -1; merge_bases = reverse_commit_list(merge_bases); } @@ -3899,6 +3948,8 @@ void init_merge_options(struct merge_options *opt, opt->renormalize = 0; + opt->conflict_style = -1; + merge_recursive_config(opt); merge_verbosity = getenv("GIT_MERGE_VERBOSITY"); if (merge_verbosity) diff --git a/merge-recursive.h b/merge-recursive.h index 3d3b3e3c29..e67d38c303 100644 --- a/merge-recursive.h +++ b/merge-recursive.h @@ -31,6 +31,7 @@ struct merge_options { /* xdiff-related options (patience, ignore whitespace, ours/theirs) */ long xdl_opts; + int conflict_style; enum { MERGE_VARIANT_NORMAL = 0, MERGE_VARIANT_OURS, @@ -77,8 +77,12 @@ int checkout_fast_forward(struct repository *r, return -1; } for (i = 0; i < nr_trees; i++) { - parse_tree(trees[i]); - init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); + if (parse_tree(trees[i]) < 0) { + rollback_lock_file(&lock_file); + return -1; + } + init_tree_desc(t+i, &trees[i]->object.oid, + trees[i]->buffer, trees[i]->size); } memset(&opts, 0, sizeof(opts)); diff --git a/mergetools/vimdiff b/mergetools/vimdiff index 06937acbf5..97e376329b 100644 --- a/mergetools/vimdiff +++ b/mergetools/vimdiff @@ -371,9 +371,17 @@ diff_cmd_help () { merge_cmd () { - layout=$(git config mergetool.vimdiff.layout) + TOOL=$1 - case "$1" in + layout=$(git config "mergetool.$TOOL.layout") + + # backward compatibility: + if test -z "$layout" + then + layout=$(git config mergetool.vimdiff.layout) + fi + + case "$TOOL" in *vimdiff) if test -z "$layout" then diff --git a/midx-write.c b/midx-write.c new file mode 100644 index 0000000000..65e69d2de7 --- /dev/null +++ b/midx-write.c @@ -0,0 +1,1525 @@ +#include "git-compat-util.h" +#include "abspath.h" +#include "config.h" +#include "hex.h" +#include "lockfile.h" +#include "packfile.h" +#include "object-file.h" +#include "hash-lookup.h" +#include "midx.h" +#include "progress.h" +#include "trace2.h" +#include "run-command.h" +#include "chunk-format.h" +#include "pack-bitmap.h" +#include "refs.h" +#include "revision.h" +#include "list-objects.h" + +#define PACK_EXPIRED UINT_MAX +#define BITMAP_POS_UNKNOWN (~((uint32_t)0)) +#define MIDX_CHUNK_FANOUT_SIZE (sizeof(uint32_t) * 256) +#define MIDX_CHUNK_LARGE_OFFSET_WIDTH (sizeof(uint64_t)) + +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); +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, + 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, num_chunks); + hashwrite_u8(f, 0); /* unused */ + hashwrite_be32(f, num_packs); + + return MIDX_HEADER_SIZE; +} + +struct pack_info { + uint32_t orig_pack_int_id; + char *pack_name; + struct packed_git *p; + + uint32_t bitmap_pos; + uint32_t bitmap_nr; + + unsigned expired : 1; +}; + +static void fill_pack_info(struct pack_info *info, + struct packed_git *p, const char *pack_name, + uint32_t orig_pack_int_id) +{ + memset(info, 0, sizeof(struct pack_info)); + + info->orig_pack_int_id = orig_pack_int_id; + info->pack_name = xstrdup(pack_name); + info->p = p; + info->bitmap_pos = BITMAP_POS_UNKNOWN; +} + +static int pack_info_compare(const void *_a, const void *_b) +{ + struct pack_info *a = (struct pack_info *)_a; + struct pack_info *b = (struct pack_info *)_b; + return strcmp(a->pack_name, b->pack_name); +} + +static int idx_or_pack_name_cmp(const void *_va, const void *_vb) +{ + const char *pack_name = _va; + const struct pack_info *compar = _vb; + + return cmp_idx_or_pack_name(pack_name, compar->pack_name); +} + +struct write_midx_context { + struct pack_info *info; + size_t nr; + size_t alloc; + struct multi_pack_index *m; + struct progress *progress; + unsigned pack_paths_checked; + + struct pack_midx_entry *entries; + size_t entries_nr; + + uint32_t *pack_perm; + uint32_t *pack_order; + unsigned large_offsets_needed:1; + uint32_t num_large_offsets; + + int preferred_pack_idx; + + struct string_list *to_include; +}; + +static void add_pack_to_midx(const char *full_path, size_t full_path_len, + const char *file_name, void *data) +{ + struct write_midx_context *ctx = data; + struct packed_git *p; + + if (ends_with(file_name, ".idx")) { + display_progress(ctx->progress, ++ctx->pack_paths_checked); + /* + * Note that at most one of ctx->m and ctx->to_include are set, + * so we are testing midx_contains_pack() and + * string_list_has_string() independently (guarded by the + * appropriate NULL checks). + * + * We could support passing to_include while reusing an existing + * MIDX, but don't currently since the reuse process drags + * forward all packs from an existing MIDX (without checking + * whether or not they appear in the to_include list). + * + * If we added support for that, these next two conditional + * should be performed independently (likely checking + * to_include before the existing MIDX). + */ + if (ctx->m && midx_contains_pack(ctx->m, file_name)) + return; + else if (ctx->to_include && + !string_list_has_string(ctx->to_include, file_name)) + return; + + ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc); + + p = add_packed_git(full_path, full_path_len, 0); + if (!p) { + warning(_("failed to add packfile '%s'"), + full_path); + return; + } + + if (open_pack_index(p)) { + warning(_("failed to open pack-index '%s'"), + full_path); + close_pack(p); + free(p); + return; + } + + fill_pack_info(&ctx->info[ctx->nr], p, file_name, ctx->nr); + ctx->nr++; + } +} + +struct pack_midx_entry { + struct object_id oid; + uint32_t pack_int_id; + time_t pack_mtime; + uint64_t offset; + unsigned preferred : 1; +}; + +static int midx_oid_compare(const void *_a, const void *_b) +{ + const struct pack_midx_entry *a = (const struct pack_midx_entry *)_a; + const struct pack_midx_entry *b = (const struct pack_midx_entry *)_b; + int cmp = oidcmp(&a->oid, &b->oid); + + if (cmp) + return cmp; + + /* Sort objects in a preferred pack first when multiple copies exist. */ + if (a->preferred > b->preferred) + return -1; + if (a->preferred < b->preferred) + return 1; + + if (a->pack_mtime > b->pack_mtime) + return -1; + else if (a->pack_mtime < b->pack_mtime) + return 1; + + return a->pack_int_id - b->pack_int_id; +} + +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) + return 1; + + nth_midxed_object_oid(&e->oid, m, pos); + e->pack_int_id = nth_midxed_pack_int_id(m, pos); + e->offset = nth_midxed_offset(m, pos); + + /* consider objects in midx to be from "old" packs */ + e->pack_mtime = 0; + return 0; +} + +static void fill_pack_entry(uint32_t pack_int_id, + struct packed_git *p, + uint32_t cur_object, + struct pack_midx_entry *entry, + int preferred) +{ + if (nth_packed_object_id(&entry->oid, p, cur_object) < 0) + die(_("failed to locate object %d in packfile"), cur_object); + + entry->pack_int_id = pack_int_id; + entry->pack_mtime = p->mtime; + + entry->offset = nth_packed_object_offset(p, cur_object); + entry->preferred = !!preferred; +} + +struct midx_fanout { + struct pack_midx_entry *entries; + size_t nr, alloc; +}; + +static void midx_fanout_grow(struct midx_fanout *fanout, size_t nr) +{ + if (nr < fanout->nr) + BUG("negative growth in midx_fanout_grow() (%"PRIuMAX" < %"PRIuMAX")", + (uintmax_t)nr, (uintmax_t)fanout->nr); + ALLOC_GROW(fanout->entries, nr, fanout->alloc); +} + +static void midx_fanout_sort(struct midx_fanout *fanout) +{ + QSORT(fanout->entries, fanout->nr, midx_oid_compare); +} + +static void midx_fanout_add_midx_fanout(struct midx_fanout *fanout, + struct multi_pack_index *m, + uint32_t cur_fanout, + int preferred_pack) +{ + uint32_t start = 0, end; + uint32_t cur_object; + + if (cur_fanout) + start = ntohl(m->chunk_oid_fanout[cur_fanout - 1]); + end = ntohl(m->chunk_oid_fanout[cur_fanout]); + + for (cur_object = start; cur_object < end; cur_object++) { + if ((preferred_pack > -1) && + (preferred_pack == nth_midxed_pack_int_id(m, cur_object))) { + /* + * Objects from preferred packs are added + * separately. + */ + continue; + } + + midx_fanout_grow(fanout, fanout->nr + 1); + nth_midxed_pack_midx_entry(m, + &fanout->entries[fanout->nr], + cur_object); + fanout->entries[fanout->nr].preferred = 0; + fanout->nr++; + } +} + +static void midx_fanout_add_pack_fanout(struct midx_fanout *fanout, + struct pack_info *info, + uint32_t cur_pack, + int preferred, + uint32_t cur_fanout) +{ + struct packed_git *pack = info[cur_pack].p; + uint32_t start = 0, end; + uint32_t cur_object; + + if (cur_fanout) + start = get_pack_fanout(pack, cur_fanout - 1); + end = get_pack_fanout(pack, cur_fanout); + + for (cur_object = start; cur_object < end; cur_object++) { + midx_fanout_grow(fanout, fanout->nr + 1); + fill_pack_entry(cur_pack, + info[cur_pack].p, + cur_object, + &fanout->entries[fanout->nr], + preferred); + fanout->nr++; + } +} + +/* + * It is possible to artificially get into a state where there are many + * duplicate copies of objects. That can create high memory pressure if + * we are to create a list of all objects before de-duplication. To reduce + * this memory pressure without a significant performance drop, automatically + * group objects by the first byte of their object id. Use the IDX fanout + * tables to group the data, copy to a local array, then sort. + * + * Copy only the de-duplicated entries (selected by most-recent modified time + * of a packfile containing the object). + */ +static struct pack_midx_entry *get_sorted_entries(struct multi_pack_index *m, + struct pack_info *info, + uint32_t nr_packs, + size_t *nr_objects, + int preferred_pack) +{ + uint32_t cur_fanout, cur_pack, cur_object; + size_t alloc_objects, total_objects = 0; + struct midx_fanout fanout = { 0 }; + struct pack_midx_entry *deduplicated_entries = NULL; + uint32_t start_pack = m ? m->num_packs : 0; + + for (cur_pack = start_pack; cur_pack < nr_packs; cur_pack++) + total_objects = st_add(total_objects, + info[cur_pack].p->num_objects); + + /* + * As we de-duplicate by fanout value, we expect the fanout + * slices to be evenly distributed, with some noise. Hence, + * allocate slightly more than one 256th. + */ + alloc_objects = fanout.alloc = total_objects > 3200 ? total_objects / 200 : 16; + + ALLOC_ARRAY(fanout.entries, fanout.alloc); + ALLOC_ARRAY(deduplicated_entries, alloc_objects); + *nr_objects = 0; + + for (cur_fanout = 0; cur_fanout < 256; cur_fanout++) { + fanout.nr = 0; + + if (m) + midx_fanout_add_midx_fanout(&fanout, m, cur_fanout, + preferred_pack); + + for (cur_pack = start_pack; cur_pack < nr_packs; cur_pack++) { + int preferred = cur_pack == preferred_pack; + midx_fanout_add_pack_fanout(&fanout, + info, cur_pack, + preferred, cur_fanout); + } + + if (-1 < preferred_pack && preferred_pack < start_pack) + midx_fanout_add_pack_fanout(&fanout, info, + preferred_pack, 1, + cur_fanout); + + midx_fanout_sort(&fanout); + + /* + * The batch is now sorted by OID and then mtime (descending). + * Take only the first duplicate. + */ + for (cur_object = 0; cur_object < fanout.nr; cur_object++) { + if (cur_object && oideq(&fanout.entries[cur_object - 1].oid, + &fanout.entries[cur_object].oid)) + continue; + + ALLOC_GROW(deduplicated_entries, st_add(*nr_objects, 1), + alloc_objects); + memcpy(&deduplicated_entries[*nr_objects], + &fanout.entries[cur_object], + sizeof(struct pack_midx_entry)); + (*nr_objects)++; + } + } + + free(fanout.entries); + return deduplicated_entries; +} + +static int write_midx_pack_names(struct hashfile *f, void *data) +{ + struct write_midx_context *ctx = data; + uint32_t i; + unsigned char padding[MIDX_CHUNK_ALIGNMENT]; + size_t written = 0; + + for (i = 0; i < ctx->nr; i++) { + size_t writelen; + + if (ctx->info[i].expired) + continue; + + if (i && strcmp(ctx->info[i].pack_name, ctx->info[i - 1].pack_name) <= 0) + BUG("incorrect pack-file order: %s before %s", + ctx->info[i - 1].pack_name, + ctx->info[i].pack_name); + + writelen = strlen(ctx->info[i].pack_name) + 1; + hashwrite(f, ctx->info[i].pack_name, writelen); + written += writelen; + } + + /* add padding to be aligned */ + i = MIDX_CHUNK_ALIGNMENT - (written % MIDX_CHUNK_ALIGNMENT); + if (i < MIDX_CHUNK_ALIGNMENT) { + memset(padding, 0, sizeof(padding)); + hashwrite(f, padding, i); + } + + return 0; +} + +static int write_midx_bitmapped_packs(struct hashfile *f, void *data) +{ + struct write_midx_context *ctx = data; + size_t i; + + for (i = 0; i < ctx->nr; i++) { + struct pack_info *pack = &ctx->info[i]; + if (pack->expired) + continue; + + if (pack->bitmap_pos == BITMAP_POS_UNKNOWN && pack->bitmap_nr) + BUG("pack '%s' has no bitmap position, but has %d bitmapped object(s)", + pack->pack_name, pack->bitmap_nr); + + hashwrite_be32(f, pack->bitmap_pos); + hashwrite_be32(f, pack->bitmap_nr); + } + return 0; +} + +static int write_midx_oid_fanout(struct hashfile *f, + void *data) +{ + struct write_midx_context *ctx = data; + struct pack_midx_entry *list = ctx->entries; + struct pack_midx_entry *last = ctx->entries + ctx->entries_nr; + uint32_t count = 0; + uint32_t i; + + /* + * Write the first-level table (the list is sorted, + * but we use a 256-entry lookup to be able to avoid + * having to do eight extra binary search iterations). + */ + for (i = 0; i < 256; i++) { + struct pack_midx_entry *next = list; + + while (next < last && next->oid.hash[0] == i) { + count++; + next++; + } + + hashwrite_be32(f, count); + list = next; + } + + return 0; +} + +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; + struct pack_midx_entry *list = ctx->entries; + uint32_t i; + + for (i = 0; i < ctx->entries_nr; i++) { + struct pack_midx_entry *obj = list++; + + if (i < ctx->entries_nr - 1) { + struct pack_midx_entry *next = list; + if (oidcmp(&obj->oid, &next->oid) >= 0) + BUG("OIDs not in order: %s >= %s", + oid_to_hex(&obj->oid), + oid_to_hex(&next->oid)); + } + + hashwrite(f, obj->oid.hash, (int)hash_len); + } + + return 0; +} + +static int write_midx_object_offsets(struct hashfile *f, + void *data) +{ + struct write_midx_context *ctx = data; + struct pack_midx_entry *list = ctx->entries; + uint32_t i, nr_large_offset = 0; + + for (i = 0; i < ctx->entries_nr; i++) { + struct pack_midx_entry *obj = list++; + + if (ctx->pack_perm[obj->pack_int_id] == PACK_EXPIRED) + BUG("object %s is in an expired pack with int-id %d", + oid_to_hex(&obj->oid), + obj->pack_int_id); + + hashwrite_be32(f, ctx->pack_perm[obj->pack_int_id]); + + if (ctx->large_offsets_needed && obj->offset >> 31) + hashwrite_be32(f, MIDX_LARGE_OFFSET_NEEDED | nr_large_offset++); + else if (!ctx->large_offsets_needed && obj->offset >> 32) + BUG("object %s requires a large offset (%"PRIx64") but the MIDX is not writing large offsets!", + oid_to_hex(&obj->oid), + obj->offset); + else + hashwrite_be32(f, (uint32_t)obj->offset); + } + + return 0; +} + +static int write_midx_large_offsets(struct hashfile *f, + void *data) +{ + struct write_midx_context *ctx = data; + struct pack_midx_entry *list = ctx->entries; + struct pack_midx_entry *end = ctx->entries + ctx->entries_nr; + uint32_t nr_large_offset = ctx->num_large_offsets; + + while (nr_large_offset) { + struct pack_midx_entry *obj; + uint64_t offset; + + if (list >= end) + BUG("too many large-offset objects"); + + obj = list++; + offset = obj->offset; + + if (!(offset >> 31)) + continue; + + hashwrite_be64(f, offset); + + nr_large_offset--; + } + + return 0; +} + +static int write_midx_revindex(struct hashfile *f, + void *data) +{ + struct write_midx_context *ctx = data; + uint32_t i; + + for (i = 0; i < ctx->entries_nr; i++) + hashwrite_be32(f, ctx->pack_order[i]); + + return 0; +} + +struct midx_pack_order_data { + uint32_t nr; + uint32_t pack; + off_t offset; +}; + +static int midx_pack_order_cmp(const void *va, const void *vb) +{ + const struct midx_pack_order_data *a = va, *b = vb; + if (a->pack < b->pack) + return -1; + else if (a->pack > b->pack) + return 1; + else if (a->offset < b->offset) + return -1; + else if (a->offset > b->offset) + return 1; + else + return 0; +} + +static uint32_t *midx_pack_order(struct write_midx_context *ctx) +{ + struct midx_pack_order_data *data; + uint32_t *pack_order; + uint32_t i; + + trace2_region_enter("midx", "midx_pack_order", the_repository); + + 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; + data[i].pack = ctx->pack_perm[e->pack_int_id]; + if (!e->preferred) + data[i].pack |= (1U << 31); + data[i].offset = e->offset; + } + + 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_nr++; + pack_order[i] = data[i].nr; + } + for (i = 0; i < ctx->nr; i++) { + struct pack_info *pack = &ctx->info[ctx->pack_perm[i]]; + if (pack->bitmap_pos == BITMAP_POS_UNKNOWN) + pack->bitmap_pos = 0; + } + free(data); + + trace2_region_leave("midx", "midx_pack_order", the_repository); + + return pack_order; +} + +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; + + trace2_region_enter("midx", "write_midx_reverse_index", the_repository); + + strbuf_addf(&buf, "%s-%s.rev", midx_name, hash_to_hex(midx_hash)); + + tmp_file = write_rev_file_order(NULL, ctx->pack_order, ctx->entries_nr, + midx_hash, WRITE_REV); + + if (finalize_object_file(tmp_file, buf.buf)) + die(_("cannot store reverse index file")); + + strbuf_release(&buf); + + trace2_region_leave("midx", "write_midx_reverse_index", the_repository); +} + +static void prepare_midx_packing_data(struct packing_data *pdata, + struct write_midx_context *ctx) +{ + uint32_t i; + + trace2_region_enter("midx", "prepare_midx_packing_data", the_repository); + + memset(pdata, 0, sizeof(struct packing_data)); + prepare_packing_data(the_repository, pdata); + + for (i = 0; i < ctx->entries_nr; i++) { + struct pack_midx_entry *from = &ctx->entries[ctx->pack_order[i]]; + 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); +} + +static int add_ref_to_pending(const char *refname, + const struct object_id *oid, + int flag, void *cb_data) +{ + struct rev_info *revs = (struct rev_info*)cb_data; + struct object_id peeled; + struct object *object; + + if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) { + warning("symbolic ref is dangling: %s", refname); + return 0; + } + + if (!peel_iterated_oid(oid, &peeled)) + oid = &peeled; + + object = parse_object_or_die(oid, refname); + if (object->type != OBJ_COMMIT) + return 0; + + add_pending_object(revs, object, ""); + if (bitmap_is_preferred_refname(revs->repo, refname)) + object->flags |= NEEDS_BITMAP; + return 0; +} + +struct bitmap_commit_cb { + struct commit **commits; + size_t commits_nr, commits_alloc; + + struct write_midx_context *ctx; +}; + +static const struct object_id *bitmap_oid_access(size_t index, + const void *_entries) +{ + const struct pack_midx_entry *entries = _entries; + return &entries[index].oid; +} + +static void bitmap_show_commit(struct commit *commit, void *_data) +{ + struct bitmap_commit_cb *data = _data; + int pos = oid_pos(&commit->object.oid, data->ctx->entries, + data->ctx->entries_nr, + bitmap_oid_access); + if (pos < 0) + return; + + ALLOC_GROW(data->commits, data->commits_nr + 1, data->commits_alloc); + data->commits[data->commits_nr++] = commit; +} + +static int read_refs_snapshot(const char *refs_snapshot, + struct rev_info *revs) +{ + struct strbuf buf = STRBUF_INIT; + struct object_id oid; + FILE *f = xfopen(refs_snapshot, "r"); + + while (strbuf_getline(&buf, f) != EOF) { + struct object *object; + int preferred = 0; + char *hex = buf.buf; + const char *end = NULL; + + if (buf.len && *buf.buf == '+') { + preferred = 1; + hex = &buf.buf[1]; + } + + if (parse_oid_hex(hex, &oid, &end) < 0) + die(_("could not parse line: %s"), buf.buf); + if (*end) + die(_("malformed line: %s"), buf.buf); + + object = parse_object_or_die(&oid, NULL); + if (preferred) + object->flags |= NEEDS_BITMAP; + + add_pending_object(revs, object, ""); + } + + fclose(f); + 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) +{ + struct rev_info revs; + struct bitmap_commit_cb cb = {0}; + + trace2_region_enter("midx", "find_commits_for_midx_bitmap", + the_repository); + + cb.ctx = ctx; + + repo_init_revisions(the_repository, &revs, NULL); + if (refs_snapshot) { + read_refs_snapshot(refs_snapshot, &revs); + } else { + setup_revisions(0, NULL, &revs, NULL); + for_each_ref(add_ref_to_pending, &revs); + } + + /* + * Skipping promisor objects here is intentional, since it only excludes + * them from the list of reachable commits that we want to select from + * when computing the selection of MIDX'd commits to receive bitmaps. + * + * Reachability bitmaps do require that their objects be closed under + * reachability, but fetching any objects missing from promisors at this + * point is too late. But, if one of those objects can be reached from + * an another object that is included in the bitmap, then we will + * complain later that we don't have reachability closure (and fail + * appropriately). + */ + fetch_if_missing = 0; + revs.exclude_promisor_objects = 1; + + if (prepare_revision_walk(&revs)) + die(_("revision walk setup failed")); + + traverse_commit_list(&revs, bitmap_show_commit, NULL, &cb); + if (indexed_commits_nr_p) + *indexed_commits_nr_p = cb.commits_nr; + + release_revisions(&revs); + + trace2_region_leave("midx", "find_commits_for_midx_bitmap", + the_repository); + + return cb.commits; +} + +static int write_midx_bitmap(const char *midx_name, + const unsigned char *midx_hash, + struct packing_data *pdata, + struct commit **commits, + uint32_t commits_nr, + uint32_t *pack_order, + unsigned flags) +{ + int ret, i; + uint16_t options = 0; + struct pack_idx_entry **index; + char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name, + hash_to_hex(midx_hash)); + + trace2_region_enter("midx", "write_midx_bitmap", the_repository); + + if (flags & MIDX_WRITE_BITMAP_HASH_CACHE) + options |= BITMAP_OPT_HASH_CACHE; + + if (flags & MIDX_WRITE_BITMAP_LOOKUP_TABLE) + options |= BITMAP_OPT_LOOKUP_TABLE; + + /* + * Build the MIDX-order index based on pdata.objects (which is already + * in MIDX order; c.f., 'midx_pack_order_cmp()' for the definition of + * this order). + */ + ALLOC_ARRAY(index, pdata->nr_objects); + for (i = 0; i < pdata->nr_objects; i++) + index[i] = &pdata->objects[i].idx; + + bitmap_writer_show_progress(flags & MIDX_PROGRESS); + bitmap_writer_build_type_index(pdata, index, pdata->nr_objects); + + /* + * bitmap_writer_finish expects objects in lex order, but pack_order + * gives us exactly that. use it directly instead of re-sorting the + * array. + * + * This changes the order of objects in 'index' between + * bitmap_writer_build_type_index and bitmap_writer_finish. + * + * The same re-ordering takes place in the single-pack bitmap code via + * write_idx_file(), which is called by finish_tmp_packfile(), which + * happens between bitmap_writer_build_type_index() and + * bitmap_writer_finish(). + */ + for (i = 0; i < pdata->nr_objects; i++) + index[pack_order[i]] = &pdata->objects[i].idx; + + bitmap_writer_select_commits(commits, commits_nr, -1); + ret = bitmap_writer_build(pdata); + if (ret < 0) + goto cleanup; + + bitmap_writer_set_checksum(midx_hash); + bitmap_writer_finish(index, pdata->nr_objects, bitmap_name, options); + +cleanup: + free(index); + free(bitmap_name); + + trace2_region_leave("midx", "write_midx_bitmap", the_repository); + + return ret; +} + +static struct multi_pack_index *lookup_multi_pack_index(struct repository *r, + const char *object_dir) +{ + struct multi_pack_index *result = NULL; + struct multi_pack_index *cur; + char *obj_dir_real = real_pathdup(object_dir, 1); + struct strbuf cur_path_real = STRBUF_INIT; + + /* Ensure the given object_dir is local, or a known alternate. */ + find_odb(r, obj_dir_real); + + for (cur = get_multi_pack_index(r); cur; cur = cur->next) { + strbuf_realpath(&cur_path_real, cur->object_dir, 1); + if (!strcmp(obj_dir_real, cur_path_real.buf)) { + result = cur; + goto cleanup; + } + } + +cleanup: + free(obj_dir_real); + strbuf_release(&cur_path_real); + return result; +} + +static int write_midx_internal(const char *object_dir, + struct string_list *packs_to_include, + struct string_list *packs_to_drop, + const char *preferred_pack_name, + const char *refs_snapshot, + unsigned flags) +{ + struct strbuf midx_name = STRBUF_INIT; + unsigned char midx_hash[GIT_MAX_RAWSZ]; + uint32_t i; + struct hashfile *f = NULL; + struct lock_file lk; + 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; + struct chunkfile *cf; + + trace2_region_enter("midx", "write_midx_internal", the_repository); + + get_midx_filename(&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 (ctx.m && !midx_checksum_valid(ctx.m)) { + warning(_("ignoring existing multi-pack-index; checksum mismatch")); + ctx.m = NULL; + } + + ctx.nr = 0; + ctx.alloc = ctx.m ? ctx.m->num_packs : 16; + ctx.info = NULL; + ALLOC_ARRAY(ctx.info, ctx.alloc); + + if (ctx.m) { + for (i = 0; i < ctx.m->num_packs; i++) { + ALLOC_GROW(ctx.info, ctx.nr + 1, ctx.alloc); + + if (flags & MIDX_WRITE_REV_INDEX) { + /* + * If generating a reverse index, need to have + * packed_git's loaded to compare their + * mtimes and object count. + */ + if (prepare_midx_pack(the_repository, ctx.m, i)) { + error(_("could not load pack")); + result = 1; + goto cleanup; + } + + 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++], ctx.m->packs[i], + ctx.m->pack_names[i], i); + } + } + + ctx.pack_paths_checked = 0; + if (flags & MIDX_PROGRESS) + ctx.progress = start_delayed_progress(_("Adding packfiles to multi-pack-index"), 0); + else + ctx.progress = NULL; + + ctx.to_include = packs_to_include; + + 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) && + !(packs_to_include || packs_to_drop)) { + struct bitmap_index *bitmap_git; + int bitmap_exists; + int want_bitmap = flags & MIDX_WRITE_BITMAP; + + bitmap_git = prepare_midx_bitmap_git(ctx.m); + bitmap_exists = bitmap_git && bitmap_is_midx(bitmap_git); + free_bitmap_index(bitmap_git); + + if (bitmap_exists || !want_bitmap) { + /* + * The correct MIDX already exists, and so does a + * corresponding bitmap (or one wasn't requested). + */ + if (!want_bitmap) + clear_midx_files_ext(object_dir, ".bitmap", + NULL); + goto cleanup; + } + } + + if (preferred_pack_name) { + ctx.preferred_pack_idx = -1; + + for (i = 0; i < ctx.nr; i++) { + if (!cmp_idx_or_pack_name(preferred_pack_name, + ctx.info[i].pack_name)) { + ctx.preferred_pack_idx = i; + break; + } + } + + if (ctx.preferred_pack_idx == -1) + warning(_("unknown preferred pack: '%s'"), + preferred_pack_name); + } else if (ctx.nr && + (flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP))) { + struct packed_git *oldest = ctx.info[ctx.preferred_pack_idx].p; + ctx.preferred_pack_idx = 0; + + if (packs_to_drop && packs_to_drop->nr) + BUG("cannot write a MIDX bitmap during expiration"); + + /* + * set a preferred pack when writing a bitmap to ensure that + * the pack from which the first object is selected in pseudo + * pack-order has all of its objects selected from that pack + * (and not another pack containing a duplicate) + */ + for (i = 1; i < ctx.nr; i++) { + struct packed_git *p = ctx.info[i].p; + + if (!oldest->num_objects || p->mtime < oldest->mtime) { + oldest = p; + ctx.preferred_pack_idx = i; + } + } + + if (!oldest->num_objects) { + /* + * If all packs are empty; unset the preferred index. + * This is acceptable since there will be no duplicate + * objects to resolve, so the preferred value doesn't + * matter. + */ + ctx.preferred_pack_idx = -1; + } + } else { + /* + * otherwise don't mark any pack as preferred to avoid + * interfering with expiration logic below + */ + ctx.preferred_pack_idx = -1; + } + + if (ctx.preferred_pack_idx > -1) { + struct packed_git *preferred = ctx.info[ctx.preferred_pack_idx].p; + if (!preferred->num_objects) { + error(_("cannot select preferred pack %s with no objects"), + preferred->pack_name); + result = 1; + goto cleanup; + } + } + + ctx.entries = get_sorted_entries(ctx.m, ctx.info, ctx.nr, &ctx.entries_nr, + ctx.preferred_pack_idx); + + ctx.large_offsets_needed = 0; + for (i = 0; i < ctx.entries_nr; i++) { + if (ctx.entries[i].offset > 0x7fffffff) + ctx.num_large_offsets++; + if (ctx.entries[i].offset > 0xffffffff) + ctx.large_offsets_needed = 1; + } + + QSORT(ctx.info, ctx.nr, pack_info_compare); + + if (packs_to_drop && packs_to_drop->nr) { + int drop_index = 0; + int missing_drops = 0; + + for (i = 0; i < ctx.nr && drop_index < packs_to_drop->nr; i++) { + int cmp = strcmp(ctx.info[i].pack_name, + packs_to_drop->items[drop_index].string); + + if (!cmp) { + drop_index++; + ctx.info[i].expired = 1; + } else if (cmp > 0) { + error(_("did not see pack-file %s to drop"), + packs_to_drop->items[drop_index].string); + drop_index++; + missing_drops++; + i--; + } else { + ctx.info[i].expired = 0; + } + } + + if (missing_drops) { + result = 1; + goto cleanup; + } + } + + /* + * pack_perm stores a permutation between pack-int-ids from the + * previous multi-pack-index to the new one we are writing: + * + * pack_perm[old_id] = new_id + */ + ALLOC_ARRAY(ctx.pack_perm, ctx.nr); + for (i = 0; i < ctx.nr; i++) { + if (ctx.info[i].expired) { + dropped_packs++; + ctx.pack_perm[ctx.info[i].orig_pack_int_id] = PACK_EXPIRED; + } else { + ctx.pack_perm[ctx.info[i].orig_pack_int_id] = i - dropped_packs; + } + } + + for (i = 0; i < ctx.nr; i++) { + if (ctx.info[i].expired) + continue; + pack_name_concat_len += strlen(ctx.info[i].pack_name) + 1; + bitmapped_packs_concat_len += 2 * sizeof(uint32_t); + } + + /* Check that the preferred pack wasn't expired (if given). */ + if (preferred_pack_name) { + struct pack_info *preferred = bsearch(preferred_pack_name, + ctx.info, ctx.nr, + sizeof(*ctx.info), + idx_or_pack_name_cmp); + if (preferred) { + uint32_t perm = ctx.pack_perm[preferred->orig_pack_int_id]; + if (perm == PACK_EXPIRED) + warning(_("preferred pack '%s' is expired"), + preferred_pack_name); + } + } + + if (pack_name_concat_len % MIDX_CHUNK_ALIGNMENT) + 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; + goto cleanup; + } + + if (!ctx.entries_nr) { + if (flags & MIDX_WRITE_BITMAP) + warning(_("refusing to write multi-pack .bitmap without any objects")); + flags &= ~(MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP); + } + + cf = init_chunkfile(f); + + add_chunk(cf, MIDX_CHUNKID_PACKNAMES, pack_name_concat_len, + write_midx_pack_names); + 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), + write_midx_oid_lookup); + add_chunk(cf, MIDX_CHUNKID_OBJECTOFFSETS, + st_mult(ctx.entries_nr, MIDX_CHUNK_OFFSET_WIDTH), + write_midx_object_offsets); + + if (ctx.large_offsets_needed) + add_chunk(cf, MIDX_CHUNKID_LARGEOFFSETS, + st_mult(ctx.num_large_offsets, + MIDX_CHUNK_LARGE_OFFSET_WIDTH), + write_midx_large_offsets); + + if (flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP)) { + ctx.pack_order = midx_pack_order(&ctx); + add_chunk(cf, MIDX_CHUNKID_REVINDEX, + st_mult(ctx.entries_nr, sizeof(uint32_t)), + write_midx_revindex); + add_chunk(cf, MIDX_CHUNKID_BITMAPPEDPACKS, + bitmapped_packs_concat_len, + write_midx_bitmapped_packs); + } + + write_midx_header(f, get_num_chunks(cf), ctx.nr - dropped_packs); + write_chunkfile(cf, &ctx); + + finalize_hashfile(f, midx_hash, FSYNC_COMPONENT_PACK_METADATA, + CSUM_FSYNC | CSUM_HASH_IN_STREAM); + free_chunkfile(cf); + + if (flags & MIDX_WRITE_REV_INDEX && + git_env_bool("GIT_TEST_MIDX_WRITE_REV", 0)) + write_midx_reverse_index(midx_name.buf, midx_hash, &ctx); + + if (flags & MIDX_WRITE_BITMAP) { + struct packing_data pdata; + struct commit **commits; + uint32_t commits_nr; + + if (!ctx.entries_nr) + BUG("cannot write a bitmap without any objects"); + + prepare_midx_packing_data(&pdata, &ctx); + + commits = find_commits_for_midx_bitmap(&commits_nr, refs_snapshot, &ctx); + + /* + * The previous steps translated the information from + * 'entries' into information suitable for constructing + * bitmaps. We no longer need that array, so clear it to + * reduce memory pressure. + */ + FREE_AND_NULL(ctx.entries); + ctx.entries_nr = 0; + + if (write_midx_bitmap(midx_name.buf, midx_hash, &pdata, + commits, commits_nr, ctx.pack_order, + flags) < 0) { + error(_("could not write multi-pack bitmap")); + result = 1; + clear_packing_data(&pdata); + free(commits); + goto cleanup; + } + + clear_packing_data(&pdata); + free(commits); + } + /* + * NOTE: Do not use ctx.entries beyond this point, since it might + * have been freed in the previous if block. + */ + + if (ctx.m) + close_object_store(the_repository->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); + +cleanup: + for (i = 0; i < ctx.nr; i++) { + if (ctx.info[i].p) { + close_pack(ctx.info[i].p); + free(ctx.info[i].p); + } + free(ctx.info[i].pack_name); + } + + free(ctx.info); + free(ctx.entries); + free(ctx.pack_perm); + free(ctx.pack_order); + strbuf_release(&midx_name); + + trace2_region_leave("midx", "write_midx_internal", the_repository); + + return result; +} + +int write_midx_file(const char *object_dir, + const char *preferred_pack_name, + const char *refs_snapshot, + unsigned flags) +{ + return write_midx_internal(object_dir, NULL, NULL, preferred_pack_name, + refs_snapshot, flags); +} + +int write_midx_file_only(const char *object_dir, + struct string_list *packs_to_include, + const char *preferred_pack_name, + const char *refs_snapshot, + unsigned flags) +{ + return write_midx_internal(object_dir, packs_to_include, NULL, + preferred_pack_name, refs_snapshot, flags); +} + +int expire_midx_packs(struct repository *r, const char *object_dir, unsigned flags) +{ + uint32_t i, *count, result = 0; + struct string_list packs_to_drop = STRING_LIST_INIT_DUP; + struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir); + struct progress *progress = NULL; + + if (!m) + return 0; + + CALLOC_ARRAY(count, m->num_packs); + + if (flags & MIDX_PROGRESS) + progress = start_delayed_progress(_("Counting referenced objects"), + m->num_objects); + for (i = 0; i < m->num_objects; i++) { + int pack_int_id = nth_midxed_pack_int_id(m, i); + count[pack_int_id]++; + display_progress(progress, i + 1); + } + stop_progress(&progress); + + if (flags & MIDX_PROGRESS) + progress = start_delayed_progress(_("Finding and deleting unreferenced packfiles"), + m->num_packs); + for (i = 0; i < m->num_packs; i++) { + char *pack_name; + display_progress(progress, i + 1); + + if (count[i]) + continue; + + if (prepare_midx_pack(r, m, i)) + continue; + + if (m->packs[i]->pack_keep || m->packs[i]->is_cruft) + continue; + + pack_name = xstrdup(m->packs[i]->pack_name); + close_pack(m->packs[i]); + + string_list_insert(&packs_to_drop, m->pack_names[i]); + unlink_pack_path(pack_name, 0); + free(pack_name); + } + stop_progress(&progress); + + free(count); + + if (packs_to_drop.nr) + result = write_midx_internal(object_dir, NULL, &packs_to_drop, NULL, NULL, flags); + + string_list_clear(&packs_to_drop, 0); + + return result; +} + +struct repack_info { + timestamp_t mtime; + uint32_t referenced_objects; + uint32_t pack_int_id; +}; + +static int compare_by_mtime(const void *a_, const void *b_) +{ + const struct repack_info *a, *b; + + a = (const struct repack_info *)a_; + b = (const struct repack_info *)b_; + + if (a->mtime < b->mtime) + return -1; + if (a->mtime > b->mtime) + return 1; + return 0; +} + +static int want_included_pack(struct repository *r, + struct multi_pack_index *m, + int pack_kept_objects, + uint32_t pack_int_id) +{ + struct packed_git *p; + if (prepare_midx_pack(r, m, pack_int_id)) + return 0; + p = m->packs[pack_int_id]; + if (!pack_kept_objects && p->pack_keep) + return 0; + if (p->is_cruft) + return 0; + if (open_pack_index(p) || !p->num_objects) + return 0; + return 1; +} + +static void fill_included_packs_all(struct repository *r, + struct multi_pack_index *m, + unsigned char *include_pack) +{ + uint32_t i; + int pack_kept_objects = 0; + + repo_config_get_bool(r, "repack.packkeptobjects", &pack_kept_objects); + + for (i = 0; i < m->num_packs; i++) { + if (!want_included_pack(r, m, pack_kept_objects, i)) + continue; + + include_pack[i] = 1; + } +} + +static void fill_included_packs_batch(struct repository *r, + struct multi_pack_index *m, + unsigned char *include_pack, + size_t batch_size) +{ + uint32_t i; + size_t total_size; + struct repack_info *pack_info; + int pack_kept_objects = 0; + + CALLOC_ARRAY(pack_info, m->num_packs); + + repo_config_get_bool(r, "repack.packkeptobjects", &pack_kept_objects); + + for (i = 0; i < m->num_packs; i++) { + pack_info[i].pack_int_id = i; + + if (prepare_midx_pack(r, m, i)) + continue; + + pack_info[i].mtime = m->packs[i]->mtime; + } + + for (i = 0; i < m->num_objects; i++) { + uint32_t pack_int_id = nth_midxed_pack_int_id(m, i); + pack_info[pack_int_id].referenced_objects++; + } + + QSORT(pack_info, m->num_packs, compare_by_mtime); + + total_size = 0; + for (i = 0; total_size < batch_size && i < m->num_packs; i++) { + int pack_int_id = pack_info[i].pack_int_id; + struct packed_git *p = m->packs[pack_int_id]; + size_t expected_size; + + if (!want_included_pack(r, m, pack_kept_objects, pack_int_id)) + continue; + + expected_size = st_mult(p->pack_size, + pack_info[i].referenced_objects); + expected_size /= p->num_objects; + + if (expected_size >= batch_size) + continue; + + total_size += expected_size; + include_pack[pack_int_id] = 1; + } + + free(pack_info); +} + +int midx_repack(struct repository *r, const char *object_dir, size_t batch_size, unsigned flags) +{ + int result = 0; + uint32_t i, packs_to_repack = 0; + unsigned char *include_pack; + struct child_process cmd = CHILD_PROCESS_INIT; + FILE *cmd_in; + struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir); + + /* + * When updating the default for these configuration + * variables in builtin/repack.c, these must be adjusted + * to match. + */ + int delta_base_offset = 1; + int use_delta_islands = 0; + + if (!m) + return 0; + + CALLOC_ARRAY(include_pack, m->num_packs); + + if (batch_size) + fill_included_packs_batch(r, m, include_pack, batch_size); + else + fill_included_packs_all(r, m, include_pack); + + for (i = 0; i < m->num_packs; i++) { + if (include_pack[i]) + packs_to_repack++; + } + if (packs_to_repack <= 1) + goto cleanup; + + repo_config_get_bool(r, "repack.usedeltabaseoffset", &delta_base_offset); + repo_config_get_bool(r, "repack.usedeltaislands", &use_delta_islands); + + strvec_pushl(&cmd.args, "pack-objects", "--stdin-packs", "--non-empty", + NULL); + + strvec_pushf(&cmd.args, "%s/pack/pack", object_dir); + + if (delta_base_offset) + strvec_push(&cmd.args, "--delta-base-offset"); + if (use_delta_islands) + strvec_push(&cmd.args, "--delta-islands"); + + if (flags & MIDX_PROGRESS) + strvec_push(&cmd.args, "--progress"); + else + strvec_push(&cmd.args, "-q"); + + cmd.git_cmd = 1; + cmd.in = cmd.out = -1; + + if (start_command(&cmd)) { + error(_("could not start pack-objects")); + result = 1; + goto cleanup; + } + + cmd_in = xfdopen(cmd.in, "w"); + for (i = 0; i < m->num_packs; i++) { + struct packed_git *p = m->packs[i]; + if (!p) + continue; + + if (include_pack[i]) + fprintf(cmd_in, "%s\n", pack_basename(p)); + else + fprintf(cmd_in, "^%s\n", pack_basename(p)); + } + fclose(cmd_in); + + if (finish_command(&cmd)) { + error(_("could not finish pack-objects")); + result = 1; + goto cleanup; + } + + result = write_midx_internal(object_dir, NULL, NULL, NULL, NULL, flags); + +cleanup: + free(include_pack); + return result; +} @@ -1,52 +1,22 @@ #include "git-compat-util.h" -#include "abspath.h" #include "config.h" -#include "csum-file.h" #include "dir.h" -#include "gettext.h" #include "hex.h" -#include "lockfile.h" #include "packfile.h" #include "object-file.h" -#include "object-store-ll.h" #include "hash-lookup.h" #include "midx.h" #include "progress.h" #include "trace2.h" -#include "run-command.h" -#include "repository.h" #include "chunk-format.h" -#include "pack.h" #include "pack-bitmap.h" -#include "refs.h" -#include "revision.h" -#include "list-objects.h" #include "pack-revindex.h" -#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */ -#define MIDX_VERSION 1 -#define MIDX_BYTE_FILE_VERSION 4 -#define MIDX_BYTE_HASH_VERSION 5 -#define MIDX_BYTE_NUM_CHUNKS 6 -#define MIDX_BYTE_NUM_PACKS 8 -#define MIDX_HEADER_SIZE 12 -#define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + the_hash_algo->rawsz) - -#define MIDX_CHUNK_ALIGNMENT 4 -#define MIDX_CHUNKID_PACKNAMES 0x504e414d /* "PNAM" */ -#define MIDX_CHUNKID_BITMAPPEDPACKS 0x42544d50 /* "BTMP" */ -#define MIDX_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */ -#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */ -#define MIDX_CHUNKID_OBJECTOFFSETS 0x4f4f4646 /* "OOFF" */ -#define MIDX_CHUNKID_LARGEOFFSETS 0x4c4f4646 /* "LOFF" */ -#define MIDX_CHUNKID_REVINDEX 0x52494458 /* "RIDX" */ -#define MIDX_CHUNK_FANOUT_SIZE (sizeof(uint32_t) * 256) -#define MIDX_CHUNK_OFFSET_WIDTH (2 * sizeof(uint32_t)) -#define MIDX_CHUNK_LARGE_OFFSET_WIDTH (sizeof(uint64_t)) -#define MIDX_CHUNK_BITMAPPED_PACKS_WIDTH (2 * sizeof(uint32_t)) -#define MIDX_LARGE_OFFSET_NEEDED 0x80000000 - -#define PACK_EXPIRED UINT_MAX +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); +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) { @@ -115,6 +85,8 @@ 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) { struct multi_pack_index *m = NULL; @@ -198,9 +170,10 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local pair_chunk(cf, MIDX_CHUNKID_LARGEOFFSETS, &m->chunk_large_offsets, &m->chunk_large_offsets_len); - pair_chunk(cf, MIDX_CHUNKID_BITMAPPEDPACKS, - (const unsigned char **)&m->chunk_bitmapped_packs, - &m->chunk_bitmapped_packs_len); + if (git_env_bool("GIT_TEST_MIDX_READ_BTMP", 1)) + pair_chunk(cf, MIDX_CHUNKID_BITMAPPEDPACKS, + (const unsigned char **)&m->chunk_bitmapped_packs, + &m->chunk_bitmapped_packs_len); if (git_env_bool("GIT_TEST_MIDX_READ_RIDX", 1)) pair_chunk(cf, MIDX_CHUNKID_REVINDEX, &m->chunk_revindex, @@ -294,6 +267,8 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t return 0; } +#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) { @@ -400,8 +375,8 @@ int fill_midx_entry(struct repository *r, } /* Match "foo.idx" against either "foo.pack" _or_ "foo.idx". */ -static int cmp_idx_or_pack_name(const char *idx_or_pack_name, - const char *idx_name) +int cmp_idx_or_pack_name(const char *idx_or_pack_name, + const char *idx_name) { /* Skip past any initial matching prefix. */ while (*idx_name && *idx_name == *idx_or_pack_name) { @@ -508,1262 +483,11 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i return 0; } -static size_t write_midx_header(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, num_chunks); - hashwrite_u8(f, 0); /* unused */ - hashwrite_be32(f, num_packs); - - return MIDX_HEADER_SIZE; -} - -#define BITMAP_POS_UNKNOWN (~((uint32_t)0)) - -struct pack_info { - uint32_t orig_pack_int_id; - char *pack_name; - struct packed_git *p; - - uint32_t bitmap_pos; - uint32_t bitmap_nr; - - unsigned expired : 1; -}; - -static void fill_pack_info(struct pack_info *info, - struct packed_git *p, const char *pack_name, - uint32_t orig_pack_int_id) -{ - memset(info, 0, sizeof(struct pack_info)); - - info->orig_pack_int_id = orig_pack_int_id; - info->pack_name = xstrdup(pack_name); - info->p = p; - info->bitmap_pos = BITMAP_POS_UNKNOWN; -} - -static int pack_info_compare(const void *_a, const void *_b) -{ - struct pack_info *a = (struct pack_info *)_a; - struct pack_info *b = (struct pack_info *)_b; - return strcmp(a->pack_name, b->pack_name); -} - -static int idx_or_pack_name_cmp(const void *_va, const void *_vb) -{ - const char *pack_name = _va; - const struct pack_info *compar = _vb; - - return cmp_idx_or_pack_name(pack_name, compar->pack_name); -} - -struct write_midx_context { - struct pack_info *info; - size_t nr; - size_t alloc; - struct multi_pack_index *m; - struct progress *progress; - unsigned pack_paths_checked; - - struct pack_midx_entry *entries; - size_t entries_nr; - - uint32_t *pack_perm; - uint32_t *pack_order; - unsigned large_offsets_needed:1; - uint32_t num_large_offsets; - - int preferred_pack_idx; - - struct string_list *to_include; -}; - -static void add_pack_to_midx(const char *full_path, size_t full_path_len, - const char *file_name, void *data) -{ - struct write_midx_context *ctx = data; - struct packed_git *p; - - if (ends_with(file_name, ".idx")) { - display_progress(ctx->progress, ++ctx->pack_paths_checked); - /* - * Note that at most one of ctx->m and ctx->to_include are set, - * so we are testing midx_contains_pack() and - * string_list_has_string() independently (guarded by the - * appropriate NULL checks). - * - * We could support passing to_include while reusing an existing - * MIDX, but don't currently since the reuse process drags - * forward all packs from an existing MIDX (without checking - * whether or not they appear in the to_include list). - * - * If we added support for that, these next two conditional - * should be performed independently (likely checking - * to_include before the existing MIDX). - */ - if (ctx->m && midx_contains_pack(ctx->m, file_name)) - return; - else if (ctx->to_include && - !string_list_has_string(ctx->to_include, file_name)) - return; - - ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc); - - p = add_packed_git(full_path, full_path_len, 0); - if (!p) { - warning(_("failed to add packfile '%s'"), - full_path); - return; - } - - if (open_pack_index(p)) { - warning(_("failed to open pack-index '%s'"), - full_path); - close_pack(p); - free(p); - return; - } - - fill_pack_info(&ctx->info[ctx->nr], p, file_name, ctx->nr); - ctx->nr++; - } -} - -struct pack_midx_entry { - struct object_id oid; - uint32_t pack_int_id; - time_t pack_mtime; - uint64_t offset; - unsigned preferred : 1; -}; - -static int midx_oid_compare(const void *_a, const void *_b) -{ - const struct pack_midx_entry *a = (const struct pack_midx_entry *)_a; - const struct pack_midx_entry *b = (const struct pack_midx_entry *)_b; - int cmp = oidcmp(&a->oid, &b->oid); - - if (cmp) - return cmp; - - /* Sort objects in a preferred pack first when multiple copies exist. */ - if (a->preferred > b->preferred) - return -1; - if (a->preferred < b->preferred) - return 1; - - if (a->pack_mtime > b->pack_mtime) - return -1; - else if (a->pack_mtime < b->pack_mtime) - return 1; - - return a->pack_int_id - b->pack_int_id; -} - -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) - return 1; - - nth_midxed_object_oid(&e->oid, m, pos); - e->pack_int_id = nth_midxed_pack_int_id(m, pos); - e->offset = nth_midxed_offset(m, pos); - - /* consider objects in midx to be from "old" packs */ - e->pack_mtime = 0; - return 0; -} - -static void fill_pack_entry(uint32_t pack_int_id, - struct packed_git *p, - uint32_t cur_object, - struct pack_midx_entry *entry, - int preferred) -{ - if (nth_packed_object_id(&entry->oid, p, cur_object) < 0) - die(_("failed to locate object %d in packfile"), cur_object); - - entry->pack_int_id = pack_int_id; - entry->pack_mtime = p->mtime; - - entry->offset = nth_packed_object_offset(p, cur_object); - entry->preferred = !!preferred; -} - -struct midx_fanout { - struct pack_midx_entry *entries; - size_t nr, alloc; -}; - -static void midx_fanout_grow(struct midx_fanout *fanout, size_t nr) -{ - if (nr < fanout->nr) - BUG("negative growth in midx_fanout_grow() (%"PRIuMAX" < %"PRIuMAX")", - (uintmax_t)nr, (uintmax_t)fanout->nr); - ALLOC_GROW(fanout->entries, nr, fanout->alloc); -} - -static void midx_fanout_sort(struct midx_fanout *fanout) -{ - QSORT(fanout->entries, fanout->nr, midx_oid_compare); -} - -static void midx_fanout_add_midx_fanout(struct midx_fanout *fanout, - struct multi_pack_index *m, - uint32_t cur_fanout, - int preferred_pack) -{ - uint32_t start = 0, end; - uint32_t cur_object; - - if (cur_fanout) - start = ntohl(m->chunk_oid_fanout[cur_fanout - 1]); - end = ntohl(m->chunk_oid_fanout[cur_fanout]); - - for (cur_object = start; cur_object < end; cur_object++) { - if ((preferred_pack > -1) && - (preferred_pack == nth_midxed_pack_int_id(m, cur_object))) { - /* - * Objects from preferred packs are added - * separately. - */ - continue; - } - - midx_fanout_grow(fanout, fanout->nr + 1); - nth_midxed_pack_midx_entry(m, - &fanout->entries[fanout->nr], - cur_object); - fanout->entries[fanout->nr].preferred = 0; - fanout->nr++; - } -} - -static void midx_fanout_add_pack_fanout(struct midx_fanout *fanout, - struct pack_info *info, - uint32_t cur_pack, - int preferred, - uint32_t cur_fanout) -{ - struct packed_git *pack = info[cur_pack].p; - uint32_t start = 0, end; - uint32_t cur_object; - - if (cur_fanout) - start = get_pack_fanout(pack, cur_fanout - 1); - end = get_pack_fanout(pack, cur_fanout); - - for (cur_object = start; cur_object < end; cur_object++) { - midx_fanout_grow(fanout, fanout->nr + 1); - fill_pack_entry(cur_pack, - info[cur_pack].p, - cur_object, - &fanout->entries[fanout->nr], - preferred); - fanout->nr++; - } -} - -/* - * It is possible to artificially get into a state where there are many - * duplicate copies of objects. That can create high memory pressure if - * we are to create a list of all objects before de-duplication. To reduce - * this memory pressure without a significant performance drop, automatically - * group objects by the first byte of their object id. Use the IDX fanout - * tables to group the data, copy to a local array, then sort. - * - * Copy only the de-duplicated entries (selected by most-recent modified time - * of a packfile containing the object). - */ -static struct pack_midx_entry *get_sorted_entries(struct multi_pack_index *m, - struct pack_info *info, - uint32_t nr_packs, - size_t *nr_objects, - int preferred_pack) -{ - uint32_t cur_fanout, cur_pack, cur_object; - size_t alloc_objects, total_objects = 0; - struct midx_fanout fanout = { 0 }; - struct pack_midx_entry *deduplicated_entries = NULL; - uint32_t start_pack = m ? m->num_packs : 0; - - for (cur_pack = start_pack; cur_pack < nr_packs; cur_pack++) - total_objects = st_add(total_objects, - info[cur_pack].p->num_objects); - - /* - * As we de-duplicate by fanout value, we expect the fanout - * slices to be evenly distributed, with some noise. Hence, - * allocate slightly more than one 256th. - */ - alloc_objects = fanout.alloc = total_objects > 3200 ? total_objects / 200 : 16; - - ALLOC_ARRAY(fanout.entries, fanout.alloc); - ALLOC_ARRAY(deduplicated_entries, alloc_objects); - *nr_objects = 0; - - for (cur_fanout = 0; cur_fanout < 256; cur_fanout++) { - fanout.nr = 0; - - if (m) - midx_fanout_add_midx_fanout(&fanout, m, cur_fanout, - preferred_pack); - - for (cur_pack = start_pack; cur_pack < nr_packs; cur_pack++) { - int preferred = cur_pack == preferred_pack; - midx_fanout_add_pack_fanout(&fanout, - info, cur_pack, - preferred, cur_fanout); - } - - if (-1 < preferred_pack && preferred_pack < start_pack) - midx_fanout_add_pack_fanout(&fanout, info, - preferred_pack, 1, - cur_fanout); - - midx_fanout_sort(&fanout); - - /* - * The batch is now sorted by OID and then mtime (descending). - * Take only the first duplicate. - */ - for (cur_object = 0; cur_object < fanout.nr; cur_object++) { - if (cur_object && oideq(&fanout.entries[cur_object - 1].oid, - &fanout.entries[cur_object].oid)) - continue; - - ALLOC_GROW(deduplicated_entries, st_add(*nr_objects, 1), - alloc_objects); - memcpy(&deduplicated_entries[*nr_objects], - &fanout.entries[cur_object], - sizeof(struct pack_midx_entry)); - (*nr_objects)++; - } - } - - free(fanout.entries); - return deduplicated_entries; -} - -static int write_midx_pack_names(struct hashfile *f, void *data) -{ - struct write_midx_context *ctx = data; - uint32_t i; - unsigned char padding[MIDX_CHUNK_ALIGNMENT]; - size_t written = 0; - - for (i = 0; i < ctx->nr; i++) { - size_t writelen; - - if (ctx->info[i].expired) - continue; - - if (i && strcmp(ctx->info[i].pack_name, ctx->info[i - 1].pack_name) <= 0) - BUG("incorrect pack-file order: %s before %s", - ctx->info[i - 1].pack_name, - ctx->info[i].pack_name); - - writelen = strlen(ctx->info[i].pack_name) + 1; - hashwrite(f, ctx->info[i].pack_name, writelen); - written += writelen; - } - - /* add padding to be aligned */ - i = MIDX_CHUNK_ALIGNMENT - (written % MIDX_CHUNK_ALIGNMENT); - if (i < MIDX_CHUNK_ALIGNMENT) { - memset(padding, 0, sizeof(padding)); - hashwrite(f, padding, i); - } - - return 0; -} - -static int write_midx_bitmapped_packs(struct hashfile *f, void *data) -{ - struct write_midx_context *ctx = data; - size_t i; - - for (i = 0; i < ctx->nr; i++) { - struct pack_info *pack = &ctx->info[i]; - if (pack->expired) - continue; - - if (pack->bitmap_pos == BITMAP_POS_UNKNOWN && pack->bitmap_nr) - BUG("pack '%s' has no bitmap position, but has %d bitmapped object(s)", - pack->pack_name, pack->bitmap_nr); - - hashwrite_be32(f, pack->bitmap_pos); - hashwrite_be32(f, pack->bitmap_nr); - } - return 0; -} - -static int write_midx_oid_fanout(struct hashfile *f, - void *data) -{ - struct write_midx_context *ctx = data; - struct pack_midx_entry *list = ctx->entries; - struct pack_midx_entry *last = ctx->entries + ctx->entries_nr; - uint32_t count = 0; - uint32_t i; - - /* - * Write the first-level table (the list is sorted, - * but we use a 256-entry lookup to be able to avoid - * having to do eight extra binary search iterations). - */ - for (i = 0; i < 256; i++) { - struct pack_midx_entry *next = list; - - while (next < last && next->oid.hash[0] == i) { - count++; - next++; - } - - hashwrite_be32(f, count); - list = next; - } - - return 0; -} - -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; - struct pack_midx_entry *list = ctx->entries; - uint32_t i; - - for (i = 0; i < ctx->entries_nr; i++) { - struct pack_midx_entry *obj = list++; - - if (i < ctx->entries_nr - 1) { - struct pack_midx_entry *next = list; - if (oidcmp(&obj->oid, &next->oid) >= 0) - BUG("OIDs not in order: %s >= %s", - oid_to_hex(&obj->oid), - oid_to_hex(&next->oid)); - } - - hashwrite(f, obj->oid.hash, (int)hash_len); - } - - return 0; -} - -static int write_midx_object_offsets(struct hashfile *f, - void *data) -{ - struct write_midx_context *ctx = data; - struct pack_midx_entry *list = ctx->entries; - uint32_t i, nr_large_offset = 0; - - for (i = 0; i < ctx->entries_nr; i++) { - struct pack_midx_entry *obj = list++; - - if (ctx->pack_perm[obj->pack_int_id] == PACK_EXPIRED) - BUG("object %s is in an expired pack with int-id %d", - oid_to_hex(&obj->oid), - obj->pack_int_id); - - hashwrite_be32(f, ctx->pack_perm[obj->pack_int_id]); - - if (ctx->large_offsets_needed && obj->offset >> 31) - hashwrite_be32(f, MIDX_LARGE_OFFSET_NEEDED | nr_large_offset++); - else if (!ctx->large_offsets_needed && obj->offset >> 32) - BUG("object %s requires a large offset (%"PRIx64") but the MIDX is not writing large offsets!", - oid_to_hex(&obj->oid), - obj->offset); - else - hashwrite_be32(f, (uint32_t)obj->offset); - } - - return 0; -} - -static int write_midx_large_offsets(struct hashfile *f, - void *data) -{ - struct write_midx_context *ctx = data; - struct pack_midx_entry *list = ctx->entries; - struct pack_midx_entry *end = ctx->entries + ctx->entries_nr; - uint32_t nr_large_offset = ctx->num_large_offsets; - - while (nr_large_offset) { - struct pack_midx_entry *obj; - uint64_t offset; - - if (list >= end) - BUG("too many large-offset objects"); - - obj = list++; - offset = obj->offset; - - if (!(offset >> 31)) - continue; - - hashwrite_be64(f, offset); - - nr_large_offset--; - } - - return 0; -} - -static int write_midx_revindex(struct hashfile *f, - void *data) -{ - struct write_midx_context *ctx = data; - uint32_t i; - - for (i = 0; i < ctx->entries_nr; i++) - hashwrite_be32(f, ctx->pack_order[i]); - - return 0; -} - -struct midx_pack_order_data { - uint32_t nr; - uint32_t pack; - off_t offset; -}; - -static int midx_pack_order_cmp(const void *va, const void *vb) -{ - const struct midx_pack_order_data *a = va, *b = vb; - if (a->pack < b->pack) - return -1; - else if (a->pack > b->pack) - return 1; - else if (a->offset < b->offset) - return -1; - else if (a->offset > b->offset) - return 1; - else - return 0; -} - -static uint32_t *midx_pack_order(struct write_midx_context *ctx) -{ - struct midx_pack_order_data *data; - uint32_t *pack_order; - uint32_t i; - - trace2_region_enter("midx", "midx_pack_order", the_repository); - - 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; - data[i].pack = ctx->pack_perm[e->pack_int_id]; - if (!e->preferred) - data[i].pack |= (1U << 31); - data[i].offset = e->offset; - } - - 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_nr++; - pack_order[i] = data[i].nr; - } - for (i = 0; i < ctx->nr; i++) { - struct pack_info *pack = &ctx->info[ctx->pack_perm[i]]; - if (pack->bitmap_pos == BITMAP_POS_UNKNOWN) - pack->bitmap_pos = 0; - } - free(data); - - trace2_region_leave("midx", "midx_pack_order", the_repository); - - return pack_order; -} - -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; - - trace2_region_enter("midx", "write_midx_reverse_index", the_repository); - - strbuf_addf(&buf, "%s-%s.rev", midx_name, hash_to_hex(midx_hash)); - - tmp_file = write_rev_file_order(NULL, ctx->pack_order, ctx->entries_nr, - midx_hash, WRITE_REV); - - if (finalize_object_file(tmp_file, buf.buf)) - die(_("cannot store reverse index file")); - - strbuf_release(&buf); - - trace2_region_leave("midx", "write_midx_reverse_index", the_repository); -} - -static void clear_midx_files_ext(const char *object_dir, const char *ext, - unsigned char *keep_hash); - -static int midx_checksum_valid(struct multi_pack_index *m) +int midx_checksum_valid(struct multi_pack_index *m) { return hashfile_checksum_valid(m->data, m->data_len); } -static void prepare_midx_packing_data(struct packing_data *pdata, - struct write_midx_context *ctx) -{ - uint32_t i; - - trace2_region_enter("midx", "prepare_midx_packing_data", the_repository); - - memset(pdata, 0, sizeof(struct packing_data)); - prepare_packing_data(the_repository, pdata); - - for (i = 0; i < ctx->entries_nr; i++) { - struct pack_midx_entry *from = &ctx->entries[ctx->pack_order[i]]; - 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); -} - -static int add_ref_to_pending(const char *refname, - const struct object_id *oid, - int flag, void *cb_data) -{ - struct rev_info *revs = (struct rev_info*)cb_data; - struct object_id peeled; - struct object *object; - - if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) { - warning("symbolic ref is dangling: %s", refname); - return 0; - } - - if (!peel_iterated_oid(oid, &peeled)) - oid = &peeled; - - object = parse_object_or_die(oid, refname); - if (object->type != OBJ_COMMIT) - return 0; - - add_pending_object(revs, object, ""); - if (bitmap_is_preferred_refname(revs->repo, refname)) - object->flags |= NEEDS_BITMAP; - return 0; -} - -struct bitmap_commit_cb { - struct commit **commits; - size_t commits_nr, commits_alloc; - - struct write_midx_context *ctx; -}; - -static const struct object_id *bitmap_oid_access(size_t index, - const void *_entries) -{ - const struct pack_midx_entry *entries = _entries; - return &entries[index].oid; -} - -static void bitmap_show_commit(struct commit *commit, void *_data) -{ - struct bitmap_commit_cb *data = _data; - int pos = oid_pos(&commit->object.oid, data->ctx->entries, - data->ctx->entries_nr, - bitmap_oid_access); - if (pos < 0) - return; - - ALLOC_GROW(data->commits, data->commits_nr + 1, data->commits_alloc); - data->commits[data->commits_nr++] = commit; -} - -static int read_refs_snapshot(const char *refs_snapshot, - struct rev_info *revs) -{ - struct strbuf buf = STRBUF_INIT; - struct object_id oid; - FILE *f = xfopen(refs_snapshot, "r"); - - while (strbuf_getline(&buf, f) != EOF) { - struct object *object; - int preferred = 0; - char *hex = buf.buf; - const char *end = NULL; - - if (buf.len && *buf.buf == '+') { - preferred = 1; - hex = &buf.buf[1]; - } - - if (parse_oid_hex(hex, &oid, &end) < 0) - die(_("could not parse line: %s"), buf.buf); - if (*end) - die(_("malformed line: %s"), buf.buf); - - object = parse_object_or_die(&oid, NULL); - if (preferred) - object->flags |= NEEDS_BITMAP; - - add_pending_object(revs, object, ""); - } - - fclose(f); - 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) -{ - struct rev_info revs; - struct bitmap_commit_cb cb = {0}; - - trace2_region_enter("midx", "find_commits_for_midx_bitmap", - the_repository); - - cb.ctx = ctx; - - repo_init_revisions(the_repository, &revs, NULL); - if (refs_snapshot) { - read_refs_snapshot(refs_snapshot, &revs); - } else { - setup_revisions(0, NULL, &revs, NULL); - for_each_ref(add_ref_to_pending, &revs); - } - - /* - * Skipping promisor objects here is intentional, since it only excludes - * them from the list of reachable commits that we want to select from - * when computing the selection of MIDX'd commits to receive bitmaps. - * - * Reachability bitmaps do require that their objects be closed under - * reachability, but fetching any objects missing from promisors at this - * point is too late. But, if one of those objects can be reached from - * an another object that is included in the bitmap, then we will - * complain later that we don't have reachability closure (and fail - * appropriately). - */ - fetch_if_missing = 0; - revs.exclude_promisor_objects = 1; - - if (prepare_revision_walk(&revs)) - die(_("revision walk setup failed")); - - traverse_commit_list(&revs, bitmap_show_commit, NULL, &cb); - if (indexed_commits_nr_p) - *indexed_commits_nr_p = cb.commits_nr; - - release_revisions(&revs); - - trace2_region_leave("midx", "find_commits_for_midx_bitmap", - the_repository); - - return cb.commits; -} - -static int write_midx_bitmap(const char *midx_name, - const unsigned char *midx_hash, - struct packing_data *pdata, - struct commit **commits, - uint32_t commits_nr, - uint32_t *pack_order, - unsigned flags) -{ - int ret, i; - uint16_t options = 0; - struct pack_idx_entry **index; - char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name, - hash_to_hex(midx_hash)); - - trace2_region_enter("midx", "write_midx_bitmap", the_repository); - - if (flags & MIDX_WRITE_BITMAP_HASH_CACHE) - options |= BITMAP_OPT_HASH_CACHE; - - if (flags & MIDX_WRITE_BITMAP_LOOKUP_TABLE) - options |= BITMAP_OPT_LOOKUP_TABLE; - - /* - * Build the MIDX-order index based on pdata.objects (which is already - * in MIDX order; c.f., 'midx_pack_order_cmp()' for the definition of - * this order). - */ - ALLOC_ARRAY(index, pdata->nr_objects); - for (i = 0; i < pdata->nr_objects; i++) - index[i] = &pdata->objects[i].idx; - - bitmap_writer_show_progress(flags & MIDX_PROGRESS); - bitmap_writer_build_type_index(pdata, index, pdata->nr_objects); - - /* - * bitmap_writer_finish expects objects in lex order, but pack_order - * gives us exactly that. use it directly instead of re-sorting the - * array. - * - * This changes the order of objects in 'index' between - * bitmap_writer_build_type_index and bitmap_writer_finish. - * - * The same re-ordering takes place in the single-pack bitmap code via - * write_idx_file(), which is called by finish_tmp_packfile(), which - * happens between bitmap_writer_build_type_index() and - * bitmap_writer_finish(). - */ - for (i = 0; i < pdata->nr_objects; i++) - index[pack_order[i]] = &pdata->objects[i].idx; - - bitmap_writer_select_commits(commits, commits_nr, -1); - ret = bitmap_writer_build(pdata); - if (ret < 0) - goto cleanup; - - bitmap_writer_set_checksum(midx_hash); - bitmap_writer_finish(index, pdata->nr_objects, bitmap_name, options); - -cleanup: - free(index); - free(bitmap_name); - - trace2_region_leave("midx", "write_midx_bitmap", the_repository); - - return ret; -} - -static struct multi_pack_index *lookup_multi_pack_index(struct repository *r, - const char *object_dir) -{ - struct multi_pack_index *result = NULL; - struct multi_pack_index *cur; - char *obj_dir_real = real_pathdup(object_dir, 1); - struct strbuf cur_path_real = STRBUF_INIT; - - /* Ensure the given object_dir is local, or a known alternate. */ - find_odb(r, obj_dir_real); - - for (cur = get_multi_pack_index(r); cur; cur = cur->next) { - strbuf_realpath(&cur_path_real, cur->object_dir, 1); - if (!strcmp(obj_dir_real, cur_path_real.buf)) { - result = cur; - goto cleanup; - } - } - -cleanup: - free(obj_dir_real); - strbuf_release(&cur_path_real); - return result; -} - -static int write_midx_internal(const char *object_dir, - struct string_list *packs_to_include, - struct string_list *packs_to_drop, - const char *preferred_pack_name, - const char *refs_snapshot, - unsigned flags) -{ - struct strbuf midx_name = STRBUF_INIT; - unsigned char midx_hash[GIT_MAX_RAWSZ]; - uint32_t i; - struct hashfile *f = NULL; - struct lock_file lk; - 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; - struct chunkfile *cf; - - trace2_region_enter("midx", "write_midx_internal", the_repository); - - get_midx_filename(&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 (ctx.m && !midx_checksum_valid(ctx.m)) { - warning(_("ignoring existing multi-pack-index; checksum mismatch")); - ctx.m = NULL; - } - - ctx.nr = 0; - ctx.alloc = ctx.m ? ctx.m->num_packs : 16; - ctx.info = NULL; - ALLOC_ARRAY(ctx.info, ctx.alloc); - - if (ctx.m) { - for (i = 0; i < ctx.m->num_packs; i++) { - ALLOC_GROW(ctx.info, ctx.nr + 1, ctx.alloc); - - if (flags & MIDX_WRITE_REV_INDEX) { - /* - * If generating a reverse index, need to have - * packed_git's loaded to compare their - * mtimes and object count. - */ - if (prepare_midx_pack(the_repository, ctx.m, i)) { - error(_("could not load pack")); - result = 1; - goto cleanup; - } - - 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++], ctx.m->packs[i], - ctx.m->pack_names[i], i); - } - } - - ctx.pack_paths_checked = 0; - if (flags & MIDX_PROGRESS) - ctx.progress = start_delayed_progress(_("Adding packfiles to multi-pack-index"), 0); - else - ctx.progress = NULL; - - ctx.to_include = packs_to_include; - - 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) && - !(packs_to_include || packs_to_drop)) { - struct bitmap_index *bitmap_git; - int bitmap_exists; - int want_bitmap = flags & MIDX_WRITE_BITMAP; - - bitmap_git = prepare_midx_bitmap_git(ctx.m); - bitmap_exists = bitmap_git && bitmap_is_midx(bitmap_git); - free_bitmap_index(bitmap_git); - - if (bitmap_exists || !want_bitmap) { - /* - * The correct MIDX already exists, and so does a - * corresponding bitmap (or one wasn't requested). - */ - if (!want_bitmap) - clear_midx_files_ext(object_dir, ".bitmap", - NULL); - goto cleanup; - } - } - - if (preferred_pack_name) { - ctx.preferred_pack_idx = -1; - - for (i = 0; i < ctx.nr; i++) { - if (!cmp_idx_or_pack_name(preferred_pack_name, - ctx.info[i].pack_name)) { - ctx.preferred_pack_idx = i; - break; - } - } - - if (ctx.preferred_pack_idx == -1) - warning(_("unknown preferred pack: '%s'"), - preferred_pack_name); - } else if (ctx.nr && - (flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP))) { - struct packed_git *oldest = ctx.info[ctx.preferred_pack_idx].p; - ctx.preferred_pack_idx = 0; - - if (packs_to_drop && packs_to_drop->nr) - BUG("cannot write a MIDX bitmap during expiration"); - - /* - * set a preferred pack when writing a bitmap to ensure that - * the pack from which the first object is selected in pseudo - * pack-order has all of its objects selected from that pack - * (and not another pack containing a duplicate) - */ - for (i = 1; i < ctx.nr; i++) { - struct packed_git *p = ctx.info[i].p; - - if (!oldest->num_objects || p->mtime < oldest->mtime) { - oldest = p; - ctx.preferred_pack_idx = i; - } - } - - if (!oldest->num_objects) { - /* - * If all packs are empty; unset the preferred index. - * This is acceptable since there will be no duplicate - * objects to resolve, so the preferred value doesn't - * matter. - */ - ctx.preferred_pack_idx = -1; - } - } else { - /* - * otherwise don't mark any pack as preferred to avoid - * interfering with expiration logic below - */ - ctx.preferred_pack_idx = -1; - } - - if (ctx.preferred_pack_idx > -1) { - struct packed_git *preferred = ctx.info[ctx.preferred_pack_idx].p; - if (!preferred->num_objects) { - error(_("cannot select preferred pack %s with no objects"), - preferred->pack_name); - result = 1; - goto cleanup; - } - } - - ctx.entries = get_sorted_entries(ctx.m, ctx.info, ctx.nr, &ctx.entries_nr, - ctx.preferred_pack_idx); - - ctx.large_offsets_needed = 0; - for (i = 0; i < ctx.entries_nr; i++) { - if (ctx.entries[i].offset > 0x7fffffff) - ctx.num_large_offsets++; - if (ctx.entries[i].offset > 0xffffffff) - ctx.large_offsets_needed = 1; - } - - QSORT(ctx.info, ctx.nr, pack_info_compare); - - if (packs_to_drop && packs_to_drop->nr) { - int drop_index = 0; - int missing_drops = 0; - - for (i = 0; i < ctx.nr && drop_index < packs_to_drop->nr; i++) { - int cmp = strcmp(ctx.info[i].pack_name, - packs_to_drop->items[drop_index].string); - - if (!cmp) { - drop_index++; - ctx.info[i].expired = 1; - } else if (cmp > 0) { - error(_("did not see pack-file %s to drop"), - packs_to_drop->items[drop_index].string); - drop_index++; - missing_drops++; - i--; - } else { - ctx.info[i].expired = 0; - } - } - - if (missing_drops) { - result = 1; - goto cleanup; - } - } - - /* - * pack_perm stores a permutation between pack-int-ids from the - * previous multi-pack-index to the new one we are writing: - * - * pack_perm[old_id] = new_id - */ - ALLOC_ARRAY(ctx.pack_perm, ctx.nr); - for (i = 0; i < ctx.nr; i++) { - if (ctx.info[i].expired) { - dropped_packs++; - ctx.pack_perm[ctx.info[i].orig_pack_int_id] = PACK_EXPIRED; - } else { - ctx.pack_perm[ctx.info[i].orig_pack_int_id] = i - dropped_packs; - } - } - - for (i = 0; i < ctx.nr; i++) { - if (ctx.info[i].expired) - continue; - pack_name_concat_len += strlen(ctx.info[i].pack_name) + 1; - bitmapped_packs_concat_len += 2 * sizeof(uint32_t); - } - - /* Check that the preferred pack wasn't expired (if given). */ - if (preferred_pack_name) { - struct pack_info *preferred = bsearch(preferred_pack_name, - ctx.info, ctx.nr, - sizeof(*ctx.info), - idx_or_pack_name_cmp); - if (preferred) { - uint32_t perm = ctx.pack_perm[preferred->orig_pack_int_id]; - if (perm == PACK_EXPIRED) - warning(_("preferred pack '%s' is expired"), - preferred_pack_name); - } - } - - if (pack_name_concat_len % MIDX_CHUNK_ALIGNMENT) - 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; - goto cleanup; - } - - if (!ctx.entries_nr) { - if (flags & MIDX_WRITE_BITMAP) - warning(_("refusing to write multi-pack .bitmap without any objects")); - flags &= ~(MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP); - } - - cf = init_chunkfile(f); - - add_chunk(cf, MIDX_CHUNKID_PACKNAMES, pack_name_concat_len, - write_midx_pack_names); - 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), - write_midx_oid_lookup); - add_chunk(cf, MIDX_CHUNKID_OBJECTOFFSETS, - st_mult(ctx.entries_nr, MIDX_CHUNK_OFFSET_WIDTH), - write_midx_object_offsets); - - if (ctx.large_offsets_needed) - add_chunk(cf, MIDX_CHUNKID_LARGEOFFSETS, - st_mult(ctx.num_large_offsets, - MIDX_CHUNK_LARGE_OFFSET_WIDTH), - write_midx_large_offsets); - - if (flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP)) { - ctx.pack_order = midx_pack_order(&ctx); - add_chunk(cf, MIDX_CHUNKID_REVINDEX, - st_mult(ctx.entries_nr, sizeof(uint32_t)), - write_midx_revindex); - add_chunk(cf, MIDX_CHUNKID_BITMAPPEDPACKS, - bitmapped_packs_concat_len, - write_midx_bitmapped_packs); - } - - write_midx_header(f, get_num_chunks(cf), ctx.nr - dropped_packs); - write_chunkfile(cf, &ctx); - - finalize_hashfile(f, midx_hash, FSYNC_COMPONENT_PACK_METADATA, - CSUM_FSYNC | CSUM_HASH_IN_STREAM); - free_chunkfile(cf); - - if (flags & MIDX_WRITE_REV_INDEX && - git_env_bool("GIT_TEST_MIDX_WRITE_REV", 0)) - write_midx_reverse_index(midx_name.buf, midx_hash, &ctx); - - if (flags & MIDX_WRITE_BITMAP) { - struct packing_data pdata; - struct commit **commits; - uint32_t commits_nr; - - if (!ctx.entries_nr) - BUG("cannot write a bitmap without any objects"); - - prepare_midx_packing_data(&pdata, &ctx); - - commits = find_commits_for_midx_bitmap(&commits_nr, refs_snapshot, &ctx); - - /* - * The previous steps translated the information from - * 'entries' into information suitable for constructing - * bitmaps. We no longer need that array, so clear it to - * reduce memory pressure. - */ - FREE_AND_NULL(ctx.entries); - ctx.entries_nr = 0; - - if (write_midx_bitmap(midx_name.buf, midx_hash, &pdata, - commits, commits_nr, ctx.pack_order, - flags) < 0) { - error(_("could not write multi-pack bitmap")); - result = 1; - clear_packing_data(&pdata); - free(commits); - goto cleanup; - } - - clear_packing_data(&pdata); - free(commits); - } - /* - * NOTE: Do not use ctx.entries beyond this point, since it might - * have been freed in the previous if block. - */ - - if (ctx.m) - close_object_store(the_repository->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); - -cleanup: - for (i = 0; i < ctx.nr; i++) { - if (ctx.info[i].p) { - close_pack(ctx.info[i].p); - free(ctx.info[i].p); - } - free(ctx.info[i].pack_name); - } - - free(ctx.info); - free(ctx.entries); - free(ctx.pack_perm); - free(ctx.pack_order); - strbuf_release(&midx_name); - - trace2_region_leave("midx", "write_midx_internal", the_repository); - - return result; -} - -int write_midx_file(const char *object_dir, - const char *preferred_pack_name, - const char *refs_snapshot, - unsigned flags) -{ - return write_midx_internal(object_dir, NULL, NULL, preferred_pack_name, - refs_snapshot, flags); -} - -int write_midx_file_only(const char *object_dir, - struct string_list *packs_to_include, - const char *preferred_pack_name, - const char *refs_snapshot, - unsigned flags) -{ - return write_midx_internal(object_dir, packs_to_include, NULL, - preferred_pack_name, refs_snapshot, flags); -} - struct clear_midx_data { char *keep; const char *ext; @@ -1784,8 +508,8 @@ static void clear_midx_file_ext(const char *full_path, size_t full_path_len UNUS die_errno(_("failed to remove %s"), full_path); } -static void clear_midx_files_ext(const char *object_dir, const char *ext, - unsigned char *keep_hash) +void clear_midx_files_ext(const char *object_dir, const char *ext, + unsigned char *keep_hash) { struct clear_midx_data data; memset(&data, 0, sizeof(struct clear_midx_data)); @@ -1988,256 +712,3 @@ cleanup: return verify_midx_error; } - -int expire_midx_packs(struct repository *r, const char *object_dir, unsigned flags) -{ - uint32_t i, *count, result = 0; - struct string_list packs_to_drop = STRING_LIST_INIT_DUP; - struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir); - struct progress *progress = NULL; - - if (!m) - return 0; - - CALLOC_ARRAY(count, m->num_packs); - - if (flags & MIDX_PROGRESS) - progress = start_delayed_progress(_("Counting referenced objects"), - m->num_objects); - for (i = 0; i < m->num_objects; i++) { - int pack_int_id = nth_midxed_pack_int_id(m, i); - count[pack_int_id]++; - display_progress(progress, i + 1); - } - stop_progress(&progress); - - if (flags & MIDX_PROGRESS) - progress = start_delayed_progress(_("Finding and deleting unreferenced packfiles"), - m->num_packs); - for (i = 0; i < m->num_packs; i++) { - char *pack_name; - display_progress(progress, i + 1); - - if (count[i]) - continue; - - if (prepare_midx_pack(r, m, i)) - continue; - - if (m->packs[i]->pack_keep || m->packs[i]->is_cruft) - continue; - - pack_name = xstrdup(m->packs[i]->pack_name); - close_pack(m->packs[i]); - - string_list_insert(&packs_to_drop, m->pack_names[i]); - unlink_pack_path(pack_name, 0); - free(pack_name); - } - stop_progress(&progress); - - free(count); - - if (packs_to_drop.nr) - result = write_midx_internal(object_dir, NULL, &packs_to_drop, NULL, NULL, flags); - - string_list_clear(&packs_to_drop, 0); - - return result; -} - -struct repack_info { - timestamp_t mtime; - uint32_t referenced_objects; - uint32_t pack_int_id; -}; - -static int compare_by_mtime(const void *a_, const void *b_) -{ - const struct repack_info *a, *b; - - a = (const struct repack_info *)a_; - b = (const struct repack_info *)b_; - - if (a->mtime < b->mtime) - return -1; - if (a->mtime > b->mtime) - return 1; - return 0; -} - -static int fill_included_packs_all(struct repository *r, - struct multi_pack_index *m, - unsigned char *include_pack) -{ - uint32_t i, count = 0; - int pack_kept_objects = 0; - - repo_config_get_bool(r, "repack.packkeptobjects", &pack_kept_objects); - - for (i = 0; i < m->num_packs; i++) { - if (prepare_midx_pack(r, m, i)) - continue; - if (!pack_kept_objects && m->packs[i]->pack_keep) - continue; - if (m->packs[i]->is_cruft) - continue; - - include_pack[i] = 1; - count++; - } - - return count < 2; -} - -static int fill_included_packs_batch(struct repository *r, - struct multi_pack_index *m, - unsigned char *include_pack, - size_t batch_size) -{ - uint32_t i, packs_to_repack; - size_t total_size; - struct repack_info *pack_info; - int pack_kept_objects = 0; - - CALLOC_ARRAY(pack_info, m->num_packs); - - repo_config_get_bool(r, "repack.packkeptobjects", &pack_kept_objects); - - for (i = 0; i < m->num_packs; i++) { - pack_info[i].pack_int_id = i; - - if (prepare_midx_pack(r, m, i)) - continue; - - pack_info[i].mtime = m->packs[i]->mtime; - } - - for (i = 0; i < m->num_objects; i++) { - uint32_t pack_int_id = nth_midxed_pack_int_id(m, i); - pack_info[pack_int_id].referenced_objects++; - } - - QSORT(pack_info, m->num_packs, compare_by_mtime); - - total_size = 0; - packs_to_repack = 0; - for (i = 0; total_size < batch_size && i < m->num_packs; i++) { - int pack_int_id = pack_info[i].pack_int_id; - struct packed_git *p = m->packs[pack_int_id]; - size_t expected_size; - - if (!p) - continue; - if (!pack_kept_objects && p->pack_keep) - continue; - if (p->is_cruft) - continue; - if (open_pack_index(p) || !p->num_objects) - continue; - - expected_size = st_mult(p->pack_size, - pack_info[i].referenced_objects); - expected_size /= p->num_objects; - - if (expected_size >= batch_size) - continue; - - packs_to_repack++; - total_size += expected_size; - include_pack[pack_int_id] = 1; - } - - free(pack_info); - - if (packs_to_repack < 2) - return 1; - - return 0; -} - -int midx_repack(struct repository *r, const char *object_dir, size_t batch_size, unsigned flags) -{ - int result = 0; - uint32_t i; - unsigned char *include_pack; - struct child_process cmd = CHILD_PROCESS_INIT; - FILE *cmd_in; - struct strbuf base_name = STRBUF_INIT; - struct multi_pack_index *m = lookup_multi_pack_index(r, object_dir); - - /* - * When updating the default for these configuration - * variables in builtin/repack.c, these must be adjusted - * to match. - */ - int delta_base_offset = 1; - int use_delta_islands = 0; - - if (!m) - return 0; - - CALLOC_ARRAY(include_pack, m->num_packs); - - if (batch_size) { - if (fill_included_packs_batch(r, m, include_pack, batch_size)) - goto cleanup; - } else if (fill_included_packs_all(r, m, include_pack)) - goto cleanup; - - repo_config_get_bool(r, "repack.usedeltabaseoffset", &delta_base_offset); - repo_config_get_bool(r, "repack.usedeltaislands", &use_delta_islands); - - strvec_push(&cmd.args, "pack-objects"); - - strbuf_addstr(&base_name, object_dir); - strbuf_addstr(&base_name, "/pack/pack"); - strvec_push(&cmd.args, base_name.buf); - - if (delta_base_offset) - strvec_push(&cmd.args, "--delta-base-offset"); - if (use_delta_islands) - strvec_push(&cmd.args, "--delta-islands"); - - if (flags & MIDX_PROGRESS) - strvec_push(&cmd.args, "--progress"); - else - strvec_push(&cmd.args, "-q"); - - strbuf_release(&base_name); - - cmd.git_cmd = 1; - cmd.in = cmd.out = -1; - - if (start_command(&cmd)) { - error(_("could not start pack-objects")); - result = 1; - goto cleanup; - } - - cmd_in = xfdopen(cmd.in, "w"); - - for (i = 0; i < m->num_objects; i++) { - struct object_id oid; - uint32_t pack_int_id = nth_midxed_pack_int_id(m, i); - - if (!include_pack[pack_int_id]) - continue; - - nth_midxed_object_oid(&oid, m, i); - fprintf(cmd_in, "%s\n", oid_to_hex(&oid)); - } - fclose(cmd_in); - - if (finish_command(&cmd)) { - error(_("could not finish pack-objects")); - result = 1; - goto cleanup; - } - - result = write_midx_internal(object_dir, NULL, NULL, NULL, NULL, flags); - -cleanup: - free(include_pack); - return result; -} @@ -8,6 +8,25 @@ struct pack_entry; struct repository; struct bitmapped_pack; +#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */ +#define MIDX_VERSION 1 +#define MIDX_BYTE_FILE_VERSION 4 +#define MIDX_BYTE_HASH_VERSION 5 +#define MIDX_BYTE_NUM_CHUNKS 6 +#define MIDX_BYTE_NUM_PACKS 8 +#define MIDX_HEADER_SIZE 12 + +#define MIDX_CHUNK_ALIGNMENT 4 +#define MIDX_CHUNKID_PACKNAMES 0x504e414d /* "PNAM" */ +#define MIDX_CHUNKID_BITMAPPEDPACKS 0x42544d50 /* "BTMP" */ +#define MIDX_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */ +#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */ +#define MIDX_CHUNKID_OBJECTOFFSETS 0x4f4f4646 /* "OOFF" */ +#define MIDX_CHUNKID_LARGEOFFSETS 0x4c4f4646 /* "LOFF" */ +#define MIDX_CHUNKID_REVINDEX 0x52494458 /* "RIDX" */ +#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" diff --git a/name-hash.c b/name-hash.c index 251f036eef..3a58ce03d9 100644 --- a/name-hash.c +++ b/name-hash.c @@ -685,13 +685,20 @@ static int same_name(const struct cache_entry *ce, const char *name, int namelen return slow_same_name(name, namelen, ce->name, len); } -int index_dir_exists(struct index_state *istate, const char *name, int namelen) +int index_dir_find(struct index_state *istate, const char *name, int namelen, + struct strbuf *canonical_path) { struct dir_entry *dir; lazy_init_name_hash(istate); expand_to_path(istate, name, namelen, 0); dir = find_dir_entry(istate, name, namelen); + + if (canonical_path && dir && dir->nr) { + strbuf_reset(canonical_path); + strbuf_add(canonical_path, dir->name, dir->namelen); + } + return dir && dir->nr; } diff --git a/name-hash.h b/name-hash.h index b1b4b0fb33..0cbfc42863 100644 --- a/name-hash.h +++ b/name-hash.h @@ -4,7 +4,12 @@ struct cache_entry; struct index_state; -int index_dir_exists(struct index_state *istate, const char *name, int namelen); + +int index_dir_find(struct index_state *istate, const char *name, int namelen, + struct strbuf *canonical_path); + +#define index_dir_exists(i, n, l) index_dir_find((i), (n), (l), NULL) + void adjust_dirname_case(struct index_state *istate, char *name); struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase); diff --git a/notes-merge.c b/notes-merge.c index 8799b522a5..51282934ae 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -607,7 +607,8 @@ int notes_merge(struct notes_merge_options *o, assert(local && remote); /* Find merge bases */ - bases = repo_get_merge_bases(the_repository, local, remote); + if (repo_get_merge_bases(the_repository, local, remote, &bases) < 0) + exit(128); if (!bases) { base_oid = null_oid(); base_tree_oid = the_hash_algo->empty_tree; diff --git a/object-file-convert.c b/object-file-convert.c new file mode 100644 index 0000000000..4f6189095b --- /dev/null +++ b/object-file-convert.c @@ -0,0 +1,277 @@ +#include "git-compat-util.h" +#include "gettext.h" +#include "strbuf.h" +#include "hex.h" +#include "repository.h" +#include "hash-ll.h" +#include "hash.h" +#include "object.h" +#include "loose.h" +#include "commit.h" +#include "gpg-interface.h" +#include "object-file-convert.h" + +int repo_oid_to_algop(struct repository *repo, const struct object_id *src, + const struct git_hash_algo *to, struct object_id *dest) +{ + /* + * If the source algorithm is not set, then we're using the + * default hash algorithm for that object. + */ + const struct git_hash_algo *from = + src->algo ? &hash_algos[src->algo] : repo->hash_algo; + + if (from == to) { + if (src != dest) + oidcpy(dest, src); + return 0; + } + if (repo_loose_object_map_oid(repo, src, to, dest)) { + /* + * We may have loaded the object map at repo initialization but + * another process (perhaps upstream of a pipe from us) may have + * written a new object into the map. If the object is missing, + * let's reload the map to see if the object has appeared. + */ + repo_read_loose_object_map(repo); + if (repo_loose_object_map_oid(repo, src, to, dest)) + return -1; + } + return 0; +} + +static int decode_tree_entry_raw(struct object_id *oid, const char **path, + size_t *len, const struct git_hash_algo *algo, + const char *buf, unsigned long size) +{ + uint16_t mode; + const unsigned hashsz = algo->rawsz; + + if (size < hashsz + 3 || buf[size - (hashsz + 1)]) { + return -1; + } + + *path = parse_mode(buf, &mode); + if (!*path || !**path) + return -1; + *len = strlen(*path) + 1; + + oidread_algop(oid, (const unsigned char *)*path + *len, algo); + return 0; +} + +static int convert_tree_object(struct strbuf *out, + const struct git_hash_algo *from, + const struct git_hash_algo *to, + const char *buffer, size_t size) +{ + const char *p = buffer, *end = buffer + size; + + while (p < end) { + struct object_id entry_oid, mapped_oid; + const char *path = NULL; + size_t pathlen; + + if (decode_tree_entry_raw(&entry_oid, &path, &pathlen, from, p, + end - p)) + return error(_("failed to decode tree entry")); + if (repo_oid_to_algop(the_repository, &entry_oid, to, &mapped_oid)) + return error(_("failed to map tree entry for %s"), oid_to_hex(&entry_oid)); + strbuf_add(out, p, path - p); + strbuf_add(out, path, pathlen); + strbuf_add(out, mapped_oid.hash, to->rawsz); + p = path + pathlen + from->rawsz; + } + return 0; +} + +static int convert_tag_object(struct strbuf *out, + const struct git_hash_algo *from, + const struct git_hash_algo *to, + const char *buffer, size_t size) +{ + struct strbuf payload = STRBUF_INIT, oursig = STRBUF_INIT, othersig = STRBUF_INIT; + const int entry_len = from->hexsz + 7; + size_t payload_size; + struct object_id oid, mapped_oid; + const char *p; + + /* Consume the object line */ + if ((entry_len >= size) || + memcmp(buffer, "object ", 7) || buffer[entry_len] != '\n') + return error("bogus tag object"); + if (parse_oid_hex_algop(buffer + 7, &oid, &p, from) < 0) + return error("bad tag object ID"); + if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid)) + return error("unable to map tree %s in tag object", + oid_to_hex(&oid)); + size -= ((p + 1) - buffer); + buffer = p + 1; + + /* Is there a signature for our algorithm? */ + payload_size = parse_signed_buffer(buffer, size); + if (payload_size != size) { + /* Yes, there is. */ + strbuf_add(&oursig, buffer + payload_size, size - payload_size); + } + + /* Now, is there a signature for the other algorithm? */ + parse_buffer_signed_by_header(buffer, payload_size, &payload, &othersig, to); + /* + * Our payload is now in payload and we may have up to two signatrures + * in oursig and othersig. + */ + + /* Add some slop for longer signature header in the new algorithm. */ + strbuf_grow(out, (7 + to->hexsz + 1) + size + 7); + strbuf_addf(out, "object %s\n", oid_to_hex(&mapped_oid)); + strbuf_addbuf(out, &payload); + if (oursig.len) + add_header_signature(out, &oursig, from); + strbuf_addbuf(out, &othersig); + + strbuf_release(&payload); + strbuf_release(&othersig); + strbuf_release(&oursig); + return 0; +} + +static int convert_commit_object(struct strbuf *out, + const struct git_hash_algo *from, + const struct git_hash_algo *to, + const char *buffer, size_t size) +{ + const char *tail = buffer; + const char *bufptr = buffer; + const int tree_entry_len = from->hexsz + 5; + const int parent_entry_len = from->hexsz + 7; + struct object_id oid, mapped_oid; + const char *p, *eol; + + tail += size; + + while ((bufptr < tail) && (*bufptr != '\n')) { + eol = memchr(bufptr, '\n', tail - bufptr); + if (!eol) + return error(_("bad %s in commit"), "line"); + + if (((bufptr + 5) < eol) && !memcmp(bufptr, "tree ", 5)) + { + if (((bufptr + tree_entry_len) != eol) || + parse_oid_hex_algop(bufptr + 5, &oid, &p, from) || + (p != eol)) + return error(_("bad %s in commit"), "tree"); + + if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid)) + return error(_("unable to map %s %s in commit object"), + "tree", oid_to_hex(&oid)); + strbuf_addf(out, "tree %s\n", oid_to_hex(&mapped_oid)); + } + else if (((bufptr + 7) < eol) && !memcmp(bufptr, "parent ", 7)) + { + if (((bufptr + parent_entry_len) != eol) || + parse_oid_hex_algop(bufptr + 7, &oid, &p, from) || + (p != eol)) + return error(_("bad %s in commit"), "parent"); + + if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid)) + return error(_("unable to map %s %s in commit object"), + "parent", oid_to_hex(&oid)); + + strbuf_addf(out, "parent %s\n", oid_to_hex(&mapped_oid)); + } + else if (((bufptr + 9) < eol) && !memcmp(bufptr, "mergetag ", 9)) + { + struct strbuf tag = STRBUF_INIT, new_tag = STRBUF_INIT; + + /* Recover the tag object from the mergetag */ + strbuf_add(&tag, bufptr + 9, (eol - (bufptr + 9)) + 1); + + bufptr = eol + 1; + while ((bufptr < tail) && (*bufptr == ' ')) { + eol = memchr(bufptr, '\n', tail - bufptr); + if (!eol) { + strbuf_release(&tag); + return error(_("bad %s in commit"), "mergetag continuation"); + } + strbuf_add(&tag, bufptr + 1, (eol - (bufptr + 1)) + 1); + bufptr = eol + 1; + } + + /* Compute the new tag object */ + if (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) { + strbuf_release(&tag); + strbuf_release(&new_tag); + return -1; + } + + /* Write the new mergetag */ + strbuf_addstr(out, "mergetag"); + strbuf_add_lines(out, " ", new_tag.buf, new_tag.len); + strbuf_release(&tag); + strbuf_release(&new_tag); + } + else if (((bufptr + 7) < tail) && !memcmp(bufptr, "author ", 7)) + strbuf_add(out, bufptr, (eol - bufptr) + 1); + else if (((bufptr + 10) < tail) && !memcmp(bufptr, "committer ", 10)) + strbuf_add(out, bufptr, (eol - bufptr) + 1); + else if (((bufptr + 9) < tail) && !memcmp(bufptr, "encoding ", 9)) + strbuf_add(out, bufptr, (eol - bufptr) + 1); + else if (((bufptr + 6) < tail) && !memcmp(bufptr, "gpgsig", 6)) + strbuf_add(out, bufptr, (eol - bufptr) + 1); + else { + /* Unknown line fail it might embed an oid */ + return -1; + } + /* Consume any trailing continuation lines */ + bufptr = eol + 1; + while ((bufptr < tail) && (*bufptr == ' ')) { + eol = memchr(bufptr, '\n', tail - bufptr); + if (!eol) + return error(_("bad %s in commit"), "continuation"); + strbuf_add(out, bufptr, (eol - bufptr) + 1); + bufptr = eol + 1; + } + } + if (bufptr < tail) + strbuf_add(out, bufptr, tail - bufptr); + return 0; +} + +int convert_object_file(struct strbuf *outbuf, + const struct git_hash_algo *from, + const struct git_hash_algo *to, + const void *buf, size_t len, + enum object_type type, + int gentle) +{ + int ret; + + /* Don't call this function when no conversion is necessary */ + if ((from == to) || (type == OBJ_BLOB)) + BUG("Refusing noop object file conversion"); + + switch (type) { + case OBJ_COMMIT: + ret = convert_commit_object(outbuf, from, to, buf, len); + break; + case OBJ_TREE: + ret = convert_tree_object(outbuf, from, to, buf, len); + break; + case OBJ_TAG: + ret = convert_tag_object(outbuf, from, to, buf, len); + break; + default: + /* Not implemented yet, so fail. */ + ret = -1; + break; + } + if (!ret) + return 0; + if (gentle) { + strbuf_release(outbuf); + return ret; + } + die(_("Failed to convert object from %s to %s"), + from->name, to->name); +} diff --git a/object-file-convert.h b/object-file-convert.h new file mode 100644 index 0000000000..a4f802aa8e --- /dev/null +++ b/object-file-convert.h @@ -0,0 +1,24 @@ +#ifndef OBJECT_CONVERT_H +#define OBJECT_CONVERT_H + +struct repository; +struct object_id; +struct git_hash_algo; +struct strbuf; +#include "object.h" + +int repo_oid_to_algop(struct repository *repo, const struct object_id *src, + const struct git_hash_algo *to, struct object_id *dest); + +/* + * Convert an object file from one hash algorithm to another algorithm. + * Return -1 on failure, 0 on success. + */ +int convert_object_file(struct strbuf *outbuf, + const struct git_hash_algo *from, + const struct git_hash_algo *to, + const void *buf, size_t len, + enum object_type type, + int gentle); + +#endif /* OBJECT_CONVERT_H */ diff --git a/object-file.c b/object-file.c index 619f039ebc..610b1f465c 100644 --- a/object-file.c +++ b/object-file.c @@ -35,6 +35,8 @@ #include "setup.h" #include "submodule.h" #include "fsck.h" +#include "loose.h" +#include "object-file-convert.h" /* The maximum size for an object header. */ #define MAX_HEADER_LEN 32 @@ -1084,9 +1086,11 @@ int check_object_signature(struct repository *r, const struct object_id *oid, void *buf, unsigned long size, enum object_type type) { + const struct git_hash_algo *algo = + oid->algo ? &hash_algos[oid->algo] : r->hash_algo; struct object_id real_oid; - hash_object_file(r->hash_algo, buf, size, type, &real_oid); + hash_object_file(algo, buf, size, type, &real_oid); return !oideq(oid, &real_oid) ? -1 : 0; } @@ -1652,10 +1656,101 @@ static int do_oid_object_info_extended(struct repository *r, return 0; } +static int oid_object_info_convert(struct repository *r, + const struct object_id *input_oid, + struct object_info *input_oi, unsigned flags) +{ + const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo]; + int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT; + struct strbuf type_name = STRBUF_INIT; + struct object_id oid, delta_base_oid; + struct object_info new_oi, *oi; + unsigned long size; + void *content; + int ret; + + if (repo_oid_to_algop(r, input_oid, the_hash_algo, &oid)) { + if (do_die) + die(_("missing mapping of %s to %s"), + oid_to_hex(input_oid), the_hash_algo->name); + return -1; + } + + /* Is new_oi needed? */ + oi = input_oi; + if (input_oi && (input_oi->delta_base_oid || input_oi->sizep || + input_oi->contentp)) { + new_oi = *input_oi; + /* Does delta_base_oid need to be converted? */ + if (input_oi->delta_base_oid) + new_oi.delta_base_oid = &delta_base_oid; + /* Will the attributes differ when converted? */ + if (input_oi->sizep || input_oi->contentp) { + new_oi.contentp = &content; + new_oi.sizep = &size; + new_oi.type_name = &type_name; + } + oi = &new_oi; + } + + ret = oid_object_info_extended(r, &oid, oi, flags); + if (ret) + return -1; + if (oi == input_oi) + return ret; + + if (new_oi.contentp) { + struct strbuf outbuf = STRBUF_INIT; + enum object_type type; + + type = type_from_string_gently(type_name.buf, type_name.len, + !do_die); + if (type == -1) + return -1; + if (type != OBJ_BLOB) { + ret = convert_object_file(&outbuf, + the_hash_algo, input_algo, + content, size, type, !do_die); + if (ret == -1) + return -1; + free(content); + size = outbuf.len; + content = strbuf_detach(&outbuf, NULL); + } + if (input_oi->sizep) + *input_oi->sizep = size; + if (input_oi->contentp) + *input_oi->contentp = content; + else + free(content); + if (input_oi->type_name) + *input_oi->type_name = type_name; + else + strbuf_release(&type_name); + } + if (new_oi.delta_base_oid == &delta_base_oid) { + if (repo_oid_to_algop(r, &delta_base_oid, input_algo, + input_oi->delta_base_oid)) { + if (do_die) + die(_("missing mapping of %s to %s"), + oid_to_hex(&delta_base_oid), + input_algo->name); + return -1; + } + } + input_oi->whence = new_oi.whence; + input_oi->u = new_oi.u; + return ret; +} + int oid_object_info_extended(struct repository *r, const struct object_id *oid, struct object_info *oi, unsigned flags) { int ret; + + if (oid->algo && (hash_algo_by_ptr(r->hash_algo) != oid->algo)) + return oid_object_info_convert(r, oid, oi, flags); + obj_read_lock(); ret = do_oid_object_info_extended(r, oid, oi, flags); obj_read_unlock(); @@ -1944,9 +2039,12 @@ static int start_loose_object_common(struct strbuf *tmp_file, const char *filename, unsigned flags, git_zstream *stream, unsigned char *buf, size_t buflen, - git_hash_ctx *c, + git_hash_ctx *c, git_hash_ctx *compat_c, char *hdr, int hdrlen) { + struct repository *repo = the_repository; + const struct git_hash_algo *algo = repo->hash_algo; + const struct git_hash_algo *compat = repo->compat_hash_algo; int fd; fd = create_tmpfile(tmp_file, filename); @@ -1966,14 +2064,18 @@ static int start_loose_object_common(struct strbuf *tmp_file, git_deflate_init(stream, zlib_compression_level); stream->next_out = buf; stream->avail_out = buflen; - the_hash_algo->init_fn(c); + algo->init_fn(c); + if (compat && compat_c) + compat->init_fn(compat_c); /* Start to feed header to zlib stream */ stream->next_in = (unsigned char *)hdr; stream->avail_in = hdrlen; while (git_deflate(stream, 0) == Z_OK) ; /* nothing */ - the_hash_algo->update_fn(c, hdr, hdrlen); + algo->update_fn(c, hdr, hdrlen); + if (compat && compat_c) + compat->update_fn(compat_c, hdr, hdrlen); return fd; } @@ -1982,16 +2084,21 @@ static int start_loose_object_common(struct strbuf *tmp_file, * Common steps for the inner git_deflate() loop for writing loose * objects. Returns what git_deflate() returns. */ -static int write_loose_object_common(git_hash_ctx *c, +static int write_loose_object_common(git_hash_ctx *c, git_hash_ctx *compat_c, git_zstream *stream, const int flush, unsigned char *in0, const int fd, unsigned char *compressed, const size_t compressed_len) { + struct repository *repo = the_repository; + const struct git_hash_algo *algo = repo->hash_algo; + const struct git_hash_algo *compat = repo->compat_hash_algo; int ret; ret = git_deflate(stream, flush ? Z_FINISH : 0); - the_hash_algo->update_fn(c, in0, stream->next_in - in0); + algo->update_fn(c, in0, stream->next_in - in0); + if (compat && compat_c) + compat->update_fn(compat_c, in0, stream->next_in - in0); if (write_in_full(fd, compressed, stream->next_out - compressed) < 0) die_errno(_("unable to write loose object file")); stream->next_out = compressed; @@ -2006,15 +2113,21 @@ static int write_loose_object_common(git_hash_ctx *c, * - End the compression of zlib stream. * - Get the calculated oid to "oid". */ -static int end_loose_object_common(git_hash_ctx *c, git_zstream *stream, - struct object_id *oid) +static int end_loose_object_common(git_hash_ctx *c, git_hash_ctx *compat_c, + git_zstream *stream, struct object_id *oid, + struct object_id *compat_oid) { + struct repository *repo = the_repository; + const struct git_hash_algo *algo = repo->hash_algo; + const struct git_hash_algo *compat = repo->compat_hash_algo; int ret; ret = git_deflate_end_gently(stream); if (ret != Z_OK) return ret; - the_hash_algo->final_oid_fn(oid, c); + algo->final_oid_fn(oid, c); + if (compat && compat_c) + compat->final_oid_fn(compat_oid, compat_c); return Z_OK; } @@ -2038,7 +2151,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr, fd = start_loose_object_common(&tmp_file, filename.buf, flags, &stream, compressed, sizeof(compressed), - &c, hdr, hdrlen); + &c, NULL, hdr, hdrlen); if (fd < 0) return -1; @@ -2048,14 +2161,14 @@ static int write_loose_object(const struct object_id *oid, char *hdr, do { unsigned char *in0 = stream.next_in; - ret = write_loose_object_common(&c, &stream, 1, in0, fd, + ret = write_loose_object_common(&c, NULL, &stream, 1, in0, fd, compressed, sizeof(compressed)); } while (ret == Z_OK); if (ret != Z_STREAM_END) die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid), ret); - ret = end_loose_object_common(&c, &stream, ¶no_oid); + ret = end_loose_object_common(&c, NULL, &stream, ¶no_oid, NULL); if (ret != Z_OK) die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid), ret); @@ -2100,10 +2213,12 @@ static int freshen_packed_object(const struct object_id *oid) int stream_loose_object(struct input_stream *in_stream, size_t len, struct object_id *oid) { + const struct git_hash_algo *compat = the_repository->compat_hash_algo; + struct object_id compat_oid; int fd, ret, err = 0, flush = 0; unsigned char compressed[4096]; git_zstream stream; - git_hash_ctx c; + git_hash_ctx c, compat_c; struct strbuf tmp_file = STRBUF_INIT; struct strbuf filename = STRBUF_INIT; int dirlen; @@ -2127,7 +2242,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, */ fd = start_loose_object_common(&tmp_file, filename.buf, 0, &stream, compressed, sizeof(compressed), - &c, hdr, hdrlen); + &c, &compat_c, hdr, hdrlen); if (fd < 0) { err = -1; goto cleanup; @@ -2145,7 +2260,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, if (in_stream->is_finished) flush = 1; } - ret = write_loose_object_common(&c, &stream, flush, in0, fd, + ret = write_loose_object_common(&c, &compat_c, &stream, flush, in0, fd, compressed, sizeof(compressed)); /* * Unlike write_loose_object(), we do not have the entire @@ -2168,7 +2283,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, */ if (ret != Z_STREAM_END) die(_("unable to stream deflate new object (%d)"), ret); - ret = end_loose_object_common(&c, &stream, oid); + ret = end_loose_object_common(&c, &compat_c, &stream, oid, &compat_oid); if (ret != Z_OK) die(_("deflateEnd on stream object failed (%d)"), ret); close_loose_object(fd, tmp_file.buf); @@ -2195,6 +2310,8 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, } err = finalize_object_file(tmp_file.buf, filename.buf); + if (!err && compat) + err = repo_add_loose_object_map(the_repository, oid, &compat_oid); cleanup: strbuf_release(&tmp_file); strbuf_release(&filename); @@ -2203,19 +2320,42 @@ cleanup: int write_object_file_flags(const void *buf, unsigned long len, enum object_type type, struct object_id *oid, - unsigned flags) + struct object_id *compat_oid_in, unsigned flags) { + struct repository *repo = the_repository; + const struct git_hash_algo *algo = repo->hash_algo; + const struct git_hash_algo *compat = repo->compat_hash_algo; + struct object_id compat_oid; char hdr[MAX_HEADER_LEN]; int hdrlen = sizeof(hdr); + /* Generate compat_oid */ + if (compat) { + if (compat_oid_in) + oidcpy(&compat_oid, compat_oid_in); + else if (type == OBJ_BLOB) + hash_object_file(compat, buf, len, type, &compat_oid); + else { + struct strbuf converted = STRBUF_INIT; + convert_object_file(&converted, algo, compat, + buf, len, type, 0); + hash_object_file(compat, converted.buf, converted.len, + type, &compat_oid); + strbuf_release(&converted); + } + } + /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. */ - write_object_file_prepare(the_hash_algo, buf, len, type, oid, hdr, - &hdrlen); + write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); if (freshen_packed_object(oid) || freshen_loose_object(oid)) return 0; - return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags); + if (write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags)) + return -1; + if (compat) + return repo_add_loose_object_map(repo, oid, &compat_oid); + return 0; } int write_object_file_literally(const void *buf, unsigned long len, @@ -2223,7 +2363,27 @@ int write_object_file_literally(const void *buf, unsigned long len, unsigned flags) { char *header; + struct repository *repo = the_repository; + const struct git_hash_algo *algo = repo->hash_algo; + const struct git_hash_algo *compat = repo->compat_hash_algo; + struct object_id compat_oid; int hdrlen, status = 0; + int compat_type = -1; + + if (compat) { + compat_type = type_from_string_gently(type, -1, 1); + if (compat_type == OBJ_BLOB) + hash_object_file(compat, buf, len, compat_type, + &compat_oid); + else if (compat_type != -1) { + struct strbuf converted = STRBUF_INIT; + convert_object_file(&converted, algo, compat, + buf, len, compat_type, 0); + hash_object_file(compat, converted.buf, converted.len, + compat_type, &compat_oid); + strbuf_release(&converted); + } + } /* type string, SP, %lu of the length plus NUL must fit this */ hdrlen = strlen(type) + MAX_HEADER_LEN; @@ -2236,6 +2396,8 @@ int write_object_file_literally(const void *buf, unsigned long len, if (freshen_packed_object(oid) || freshen_loose_object(oid)) goto cleanup; status = write_loose_object(oid, header, hdrlen, buf, len, 0, 0); + if (compat_type != -1) + return repo_add_loose_object_map(repo, oid, &compat_oid); cleanup: free(header); @@ -2244,9 +2406,12 @@ cleanup: int force_object_loose(const struct object_id *oid, time_t mtime) { + struct repository *repo = the_repository; + const struct git_hash_algo *compat = repo->compat_hash_algo; void *buf; unsigned long len; struct object_info oi = OBJECT_INFO_INIT; + struct object_id compat_oid; enum object_type type; char hdr[MAX_HEADER_LEN]; int hdrlen; @@ -2259,8 +2424,15 @@ int force_object_loose(const struct object_id *oid, time_t mtime) oi.contentp = &buf; if (oid_object_info_extended(the_repository, oid, &oi, 0)) return error(_("cannot read object for %s"), oid_to_hex(oid)); + if (compat) { + if (repo_oid_to_algop(repo, oid, compat, &compat_oid)) + return error(_("cannot map object %s to %s"), + oid_to_hex(oid), compat->name); + } hdrlen = format_object_header(hdr, sizeof(hdr), type, len); ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0); + if (!ret && compat) + ret = repo_add_loose_object_map(the_repository, oid, &compat_oid); free(buf); return ret; diff --git a/object-name.c b/object-name.c index 3a2ef5d680..523af6f64f 100644 --- a/object-name.c +++ b/object-name.c @@ -23,6 +23,7 @@ #include "midx.h" #include "commit-reach.h" #include "date.h" +#include "object-file-convert.h" static int get_oid_oneline(struct repository *r, const char *, struct object_id *, struct commit_list *); @@ -47,6 +48,7 @@ struct disambiguate_state { static void update_candidates(struct disambiguate_state *ds, const struct object_id *current) { + /* The hash algorithm of current has already been filtered */ if (ds->always_call_fn) { ds->ambiguous = ds->fn(ds->repo, current, ds->cb_data) ? 1 : 0; return; @@ -132,6 +134,8 @@ static void unique_in_midx(struct multi_pack_index *m, { 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; if (!num) @@ -147,7 +151,7 @@ static void unique_in_midx(struct multi_pack_index *m, for (i = first; i < num && !ds->ambiguous; i++) { struct object_id oid; current = nth_midxed_object_oid(&oid, m, i); - if (!match_hash(ds->len, ds->bin_pfx.hash, current->hash)) + if (!match_hash(len, ds->bin_pfx.hash, current->hash)) break; update_candidates(ds, current); } @@ -157,6 +161,8 @@ static void unique_in_pack(struct packed_git *p, struct disambiguate_state *ds) { uint32_t num, i, first = 0; + int len = ds->len > ds->repo->hash_algo->hexsz ? + ds->repo->hash_algo->hexsz : ds->len; if (p->multi_pack_index) return; @@ -175,7 +181,7 @@ static void unique_in_pack(struct packed_git *p, for (i = first; i < num && !ds->ambiguous; i++) { struct object_id oid; nth_packed_object_id(&oid, p, i); - if (!match_hash(ds->len, ds->bin_pfx.hash, oid.hash)) + if (!match_hash(len, ds->bin_pfx.hash, oid.hash)) break; update_candidates(ds, &oid); } @@ -186,6 +192,10 @@ static void find_short_packed_object(struct disambiguate_state *ds) struct multi_pack_index *m; struct packed_git *p; + /* Skip, unless oids from the storage hash algorithm are wanted */ + if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo)) + return; + for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous; m = m->next) unique_in_midx(m, ds); @@ -324,11 +334,12 @@ int set_disambiguate_hint_config(const char *var, const char *value) static int init_object_disambiguation(struct repository *r, const char *name, int len, + const struct git_hash_algo *algo, struct disambiguate_state *ds) { int i; - if (len < MINIMUM_ABBREV || len > the_hash_algo->hexsz) + if (len < MINIMUM_ABBREV || len > GIT_MAX_HEXSZ) return -1; memset(ds, 0, sizeof(*ds)); @@ -355,6 +366,7 @@ static int init_object_disambiguation(struct repository *r, ds->len = len; ds->hex_pfx[len] = '\0'; ds->repo = r; + ds->bin_pfx.algo = algo ? hash_algo_by_ptr(algo) : GIT_HASH_UNKNOWN; prepare_alt_odb(r); return 0; } @@ -489,9 +501,10 @@ static int repo_collect_ambiguous(struct repository *r UNUSED, return collect_ambiguous(oid, data); } -static int sort_ambiguous(const void *a, const void *b, void *ctx) +static int sort_ambiguous(const void *va, const void *vb, void *ctx) { struct repository *sort_ambiguous_repo = ctx; + const struct object_id *a = va, *b = vb; int a_type = oid_object_info(sort_ambiguous_repo, a, NULL); int b_type = oid_object_info(sort_ambiguous_repo, b, NULL); int a_type_sort; @@ -501,8 +514,12 @@ static int sort_ambiguous(const void *a, const void *b, void *ctx) * Sorts by hash within the same object type, just as * oid_array_for_each_unique() would do. */ - if (a_type == b_type) - return oidcmp(a, b); + if (a_type == b_type) { + if (a->algo == b->algo) + return oidcmp(a, b); + else + return a->algo > b->algo ? 1 : -1; + } /* * Between object types show tags, then commits, and finally @@ -531,8 +548,12 @@ static enum get_oid_result get_short_oid(struct repository *r, int status; struct disambiguate_state ds; int quietly = !!(flags & GET_OID_QUIETLY); + const struct git_hash_algo *algo = r->hash_algo; - if (init_object_disambiguation(r, name, len, &ds) < 0) + if (flags & GET_OID_HASH_ANY) + algo = NULL; + + if (init_object_disambiguation(r, name, len, algo, &ds) < 0) return -1; if (HAS_MULTI_BITS(flags & GET_OID_DISAMBIGUATORS)) @@ -586,7 +607,7 @@ static enum get_oid_result get_short_oid(struct repository *r, if (!ds.ambiguous) ds.fn = NULL; - repo_for_each_abbrev(r, ds.hex_pfx, collect_ambiguous, &collect); + repo_for_each_abbrev(r, ds.hex_pfx, algo, collect_ambiguous, &collect); sort_ambiguous_oid_array(r, &collect); if (oid_array_for_each(&collect, show_ambiguous_object, &out)) @@ -608,13 +629,14 @@ static enum get_oid_result get_short_oid(struct repository *r, } int repo_for_each_abbrev(struct repository *r, const char *prefix, + const struct git_hash_algo *algo, each_abbrev_fn fn, void *cb_data) { struct oid_array collect = OID_ARRAY_INIT; struct disambiguate_state ds; int ret; - if (init_object_disambiguation(r, prefix, strlen(prefix), &ds) < 0) + if (init_object_disambiguation(r, prefix, strlen(prefix), algo, &ds) < 0) return -1; ds.always_call_fn = 1; @@ -785,10 +807,12 @@ void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid, int repo_find_unique_abbrev_r(struct repository *r, char *hex, const struct object_id *oid, int len) { + const struct git_hash_algo *algo = + oid->algo ? &hash_algos[oid->algo] : r->hash_algo; struct disambiguate_state ds; struct min_abbrev_data mad; struct object_id oid_ret; - const unsigned hexsz = r->hash_algo->hexsz; + const unsigned hexsz = algo->hexsz; if (len < 0) { unsigned long count = repo_approximate_object_count(r); @@ -824,7 +848,7 @@ int repo_find_unique_abbrev_r(struct repository *r, char *hex, find_abbrev_len_packed(&mad); - if (init_object_disambiguation(r, hex, mad.cur_len, &ds) < 0) + if (init_object_disambiguation(r, hex, mad.cur_len, algo, &ds) < 0) return -1; ds.fn = repo_extend_abbrev_len; @@ -1034,6 +1058,15 @@ static int get_oid_basic(struct repository *r, const char *str, int len, len, str, show_date(co_time, co_tz, DATE_MODE(RFC2822))); } + } else if (nth == co_cnt && !is_null_oid(oid)) { + /* + * We were asked for the Nth reflog (counting + * from 0), but there were only N entries. + * read_ref_at() will have returned "1" to tell + * us it did not find an entry, but it did + * still fill in the oid with the "old" value, + * which we can use. + */ } else { if (flags & GET_OID_QUIETLY) { exit(128); @@ -1479,7 +1512,7 @@ int repo_get_oid_mb(struct repository *r, struct object_id *oid) { struct commit *one, *two; - struct commit_list *mbs; + struct commit_list *mbs = NULL; struct object_id oid_tmp; const char *dots; int st; @@ -1507,7 +1540,10 @@ int repo_get_oid_mb(struct repository *r, two = lookup_commit_reference_gently(r, &oid_tmp, 0); if (!two) return -1; - mbs = repo_get_merge_bases(r, one, two); + if (repo_get_merge_bases(r, one, two, &mbs) < 0) { + free_commit_list(mbs); + return -1; + } if (!mbs || mbs->next) st = -1; else { diff --git a/object-name.h b/object-name.h index 9ae5223071..064ddc97d1 100644 --- a/object-name.h +++ b/object-name.h @@ -67,7 +67,8 @@ enum get_oid_result get_oid_with_context(struct repository *repo, const char *st typedef int each_abbrev_fn(const struct object_id *oid, void *); -int repo_for_each_abbrev(struct repository *r, const char *prefix, each_abbrev_fn, void *); +int repo_for_each_abbrev(struct repository *r, const char *prefix, + const struct git_hash_algo *algo, each_abbrev_fn, void *); int set_disambiguate_hint_config(const char *var, const char *value); diff --git a/object-store-ll.h b/object-store-ll.h index 26a3895c82..c5f2bb2fc2 100644 --- a/object-store-ll.h +++ b/object-store-ll.h @@ -26,6 +26,9 @@ struct object_directory { uint32_t loose_objects_subdir_seen[8]; /* 256 bits */ struct oidtree *loose_objects_cache; + /* Map between object IDs for loose objects. */ + struct loose_object_map *loose_map; + /* * This is a temporary object store created by the tmp_objdir * facility. Disable ref updates since the objects in the store @@ -252,11 +255,11 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf, int write_object_file_flags(const void *buf, unsigned long len, enum object_type type, struct object_id *oid, - unsigned flags); + struct object_id *comapt_oid_in, unsigned flags); static inline int write_object_file(const void *buf, unsigned long len, enum object_type type, struct object_id *oid) { - return write_object_file_flags(buf, len, type, oid, 0); + return write_object_file_flags(buf, len, type, oid, NULL, 0); } int write_object_file_literally(const void *buf, unsigned long len, @@ -13,6 +13,7 @@ #include "alloc.h" #include "packfile.h" #include "commit-graph.h" +#include "loose.h" unsigned int get_max_object_index(void) { @@ -47,8 +48,7 @@ int type_from_string_gently(const char *str, ssize_t len, int gentle) len = strlen(str); for (i = 1; i < ARRAY_SIZE(object_type_strings); i++) - if (!strncmp(str, object_type_strings[i], len) && - object_type_strings[i][len] == '\0') + if (!xstrncmpz(object_type_strings[i], str, len)) return i; if (gentle) @@ -272,6 +272,7 @@ struct object *parse_object_with_flags(struct repository *r, enum parse_object_flags flags) { int skip_hash = !!(flags & PARSE_OBJECT_SKIP_HASH_CHECK); + int discard_tree = !!(flags & PARSE_OBJECT_DISCARD_TREE); unsigned long size; enum object_type type; int eaten; @@ -299,6 +300,17 @@ struct object *parse_object_with_flags(struct repository *r, return lookup_object(r, oid); } + /* + * If the caller does not care about the tree buffer and does not + * care about checking the hash, we can simply verify that we + * have the on-disk object with the correct type. + */ + if (skip_hash && discard_tree && + (!obj || obj->type == OBJ_TREE) && + oid_object_info(r, oid, NULL) == OBJ_TREE) { + return &lookup_tree(r, oid)->object; + } + buffer = repo_read_object_file(r, oid, &type, &size); if (buffer) { if (!skip_hash && @@ -312,6 +324,8 @@ struct object *parse_object_with_flags(struct repository *r, buffer, &eaten); if (!eaten) free(buffer); + if (discard_tree && type == OBJ_TREE) + free_tree_buffer((struct tree *)obj); return obj; } return NULL; @@ -540,6 +554,7 @@ void free_object_directory(struct object_directory *odb) { free(odb->path); odb_clear_loose_cache(odb); + loose_object_map_clear(&odb->loose_map); free(odb); } @@ -190,6 +190,24 @@ void *create_object(struct repository *r, const struct object_id *oid, void *obj void *object_as_type(struct object *obj, enum object_type type, int quiet); + +static inline const char *parse_mode(const char *str, uint16_t *modep) +{ + unsigned char c; + unsigned int mode = 0; + + if (*str == ' ') + return NULL; + + while ((c = *str++) != ' ') { + if (c < '0' || c > '7') + return NULL; + mode = (mode << 3) + (c - '0'); + } + *modep = mode; + return str; +} + /* * Returns the object, having parsed it to find out what it is. * @@ -197,6 +215,7 @@ void *object_as_type(struct object *obj, enum object_type type, int quiet); */ enum parse_object_flags { PARSE_OBJECT_SKIP_HASH_CHECK = 1 << 0, + PARSE_OBJECT_DISCARD_TREE = 1 << 1, }; struct object *parse_object(struct repository *r, const struct object_id *oid); struct object *parse_object_with_flags(struct repository *r, diff --git a/oid-array.c b/oid-array.c index 8e4717746c..1f36651754 100644 --- a/oid-array.c +++ b/oid-array.c @@ -6,12 +6,20 @@ void oid_array_append(struct oid_array *array, const struct object_id *oid) { ALLOC_GROW(array->oid, array->nr + 1, array->alloc); oidcpy(&array->oid[array->nr++], oid); + if (!oid->algo) + oid_set_algo(&array->oid[array->nr - 1], the_hash_algo); array->sorted = 0; } -static int void_hashcmp(const void *a, const void *b) +static int void_hashcmp(const void *va, const void *vb) { - return oidcmp(a, b); + const struct object_id *a = va, *b = vb; + int ret; + if (a->algo == b->algo) + ret = oidcmp(a, b); + else + ret = a->algo > b->algo ? 1 : -1; + return ret; } void oid_array_sort(struct oid_array *array) @@ -23,6 +23,16 @@ int oidset_insert(struct oidset *set, const struct object_id *oid) return !added; } +void oidset_insert_from_set(struct oidset *dest, struct oidset *src) +{ + struct oidset_iter iter; + struct object_id *src_oid; + + oidset_iter_init(src, &iter); + while ((src_oid = oidset_iter_next(&iter))) + oidset_insert(dest, src_oid); +} + int oidset_remove(struct oidset *set, const struct object_id *oid) { khiter_t pos = kh_get_oid_set(&set->set, *oid); @@ -48,6 +48,12 @@ int oidset_contains(const struct oidset *set, const struct object_id *oid); int oidset_insert(struct oidset *set, const struct object_id *oid); /** + * Insert all the oids that are in set 'src' into set 'dest'; a copy + * is made of each oid inserted into set 'dest'. + */ +void oidset_insert_from_set(struct oidset *dest, struct oidset *src); + +/** * Remove the oid from the set. * * Returns 1 if the oid was present in the set, 0 otherwise. diff --git a/oss-fuzz/.gitignore b/oss-fuzz/.gitignore index 5b95408825..a877c11f42 100644 --- a/oss-fuzz/.gitignore +++ b/oss-fuzz/.gitignore @@ -1,4 +1,5 @@ fuzz-commit-graph +fuzz-config fuzz-date fuzz-pack-headers fuzz-pack-idx diff --git a/oss-fuzz/fuzz-config.c b/oss-fuzz/fuzz-config.c new file mode 100644 index 0000000000..94027f5b97 --- /dev/null +++ b/oss-fuzz/fuzz-config.c @@ -0,0 +1,33 @@ +#include "git-compat-util.h" +#include "config.h" + +int LLVMFuzzerTestOneInput(const uint8_t *, size_t); +static int config_parser_callback(const char *, const char *, + const struct config_context *, void *); + +static int config_parser_callback(const char *key, const char *value, + const struct config_context *ctx UNUSED, + void *data UNUSED) +{ + /* + * Visit every byte of memory we are given to make sure the parser + * gave it to us appropriately. We need to unconditionally return 0, + * but we also want to prevent the strlen from being optimized away. + */ + size_t c = strlen(key); + + if (value) + c += strlen(value); + return c == SIZE_MAX; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, const size_t size) +{ + struct config_options config_opts = { 0 }; + + config_opts.error_action = CONFIG_ERROR_SILENT; + git_config_from_mem(config_parser_callback, CONFIG_ORIGIN_BLOB, + "fuzztest-config", (const char *)data, size, NULL, + CONFIG_SCOPE_UNKNOWN, &config_opts); + return 0; +} diff --git a/oss-fuzz/fuzz-date.c b/oss-fuzz/fuzz-date.c index 036378b946..9619dae40e 100644 --- a/oss-fuzz/fuzz-date.c +++ b/oss-fuzz/fuzz-date.c @@ -11,7 +11,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) int16_t tz; timestamp_t ts; enum date_mode_type dmtype; - struct date_mode *dm; + struct date_mode dm; if (size <= 4) /* @@ -40,10 +40,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) free(str); dm = date_mode_from_type(dmtype); - dm->local = local; + dm.local = local; show_date(ts, (int)tz, dm); - date_mode_release(dm); + date_mode_release(&dm); return 0; } diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 990a9498d7..c6c8f94cc5 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -370,7 +370,7 @@ static int fill_bitmap_tree(struct bitmap *bitmap, if (parse_tree(tree) < 0) die("unable to load tree object %s", oid_to_hex(&tree->object.oid)); - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { switch (object_type(entry.mode)) { diff --git a/pack-bitmap.c b/pack-bitmap.c index 2baeabacee..35c5ef9d3c 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -2049,7 +2049,10 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git, load_reverse_index(r, bitmap_git); - if (bitmap_is_midx(bitmap_git)) { + if (!bitmap_is_midx(bitmap_git) || !bitmap_git->midx->chunk_bitmapped_packs) + multi_pack_reuse = 0; + + if (multi_pack_reuse) { for (i = 0; i < bitmap_git->midx->num_packs; i++) { struct bitmapped_pack pack; if (nth_bitmapped_pack(r, bitmap_git->midx, &pack, i) < 0) { @@ -2062,34 +2065,32 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git, if (!pack.bitmap_nr) continue; - if (!multi_pack_reuse && pack.bitmap_pos) { - /* - * If we're only reusing a single pack, skip - * over any packs which are not positioned at - * the beginning of the MIDX bitmap. - * - * This is consistent with the existing - * single-pack reuse behavior, which only reuses - * parts of the MIDX's preferred pack. - */ - continue; - } - ALLOC_GROW(packs, packs_nr + 1, packs_alloc); memcpy(&packs[packs_nr++], &pack, sizeof(pack)); objects_nr += pack.p->num_objects; - - if (!multi_pack_reuse) - break; } QSORT(packs, packs_nr, bitmapped_pack_cmp); } else { - ALLOC_GROW(packs, packs_nr + 1, packs_alloc); + struct packed_git *pack; + + if (bitmap_is_midx(bitmap_git)) { + uint32_t preferred_pack_pos; + + if (midx_preferred_pack(bitmap_git->midx, &preferred_pack_pos) < 0) { + warning(_("unable to compute preferred pack, disabling pack-reuse")); + return; + } - packs[packs_nr].p = bitmap_git->pack; - packs[packs_nr].bitmap_nr = bitmap_git->pack->num_objects; + pack = bitmap_git->midx->packs[preferred_pack_pos]; + } else { + pack = bitmap_git->pack; + } + + ALLOC_GROW(packs, packs_nr + 1, packs_alloc); + packs[packs_nr].p = pack; + packs[packs_nr].bitmap_nr = pack->num_objects; packs[packs_nr].bitmap_pos = 0; objects_nr = packs[packs_nr++].bitmap_nr; diff --git a/packfile.c b/packfile.c index 84a005674d..d4df7fdeea 100644 --- a/packfile.c +++ b/packfile.c @@ -2249,7 +2249,8 @@ static int add_promisor_object(const struct object_id *oid, struct tree *tree = (struct tree *)obj; struct tree_desc desc; struct name_entry entry; - if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0)) + 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. diff --git a/parse-options.c b/parse-options.c index 63a99dea6e..30b9e68f8a 100644 --- a/parse-options.c +++ b/parse-options.c @@ -350,98 +350,107 @@ static int is_alias(struct parse_opt_ctx_t *ctx, return 0; } +struct parsed_option { + const struct option *option; + enum opt_parsed flags; +}; + +static void register_abbrev(struct parse_opt_ctx_t *p, + const struct option *option, enum opt_parsed flags, + struct parsed_option *abbrev, + struct parsed_option *ambiguous) +{ + if (p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT) + return; + if (abbrev->option && + !(abbrev->flags == flags && is_alias(p, abbrev->option, option))) { + /* + * If this is abbreviated, it is + * ambiguous. So when there is no + * exact match later, we need to + * error out. + */ + ambiguous->option = abbrev->option; + ambiguous->flags = abbrev->flags; + } + abbrev->option = option; + abbrev->flags = flags; +} + static enum parse_opt_result parse_long_opt( struct parse_opt_ctx_t *p, const char *arg, const struct option *options) { const char *arg_end = strchrnul(arg, '='); - const struct option *abbrev_option = NULL, *ambiguous_option = NULL; - enum opt_parsed abbrev_flags = OPT_LONG, ambiguous_flags = OPT_LONG; - int allow_abbrev = !(p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT); + const char *arg_start = arg; + enum opt_parsed flags = OPT_LONG; + int arg_starts_with_no_no = 0; + struct parsed_option abbrev = { .option = NULL, .flags = OPT_LONG }; + struct parsed_option ambiguous = { .option = NULL, .flags = OPT_LONG }; + + if (skip_prefix(arg_start, "no-", &arg_start)) { + if (skip_prefix(arg_start, "no-", &arg_start)) + arg_starts_with_no_no = 1; + else + flags |= OPT_UNSET; + } for (; options->type != OPTION_END; options++) { const char *rest, *long_name = options->long_name; - enum opt_parsed flags = OPT_LONG, opt_flags = OPT_LONG; + enum opt_parsed opt_flags = OPT_LONG; + int allow_unset = !(options->flags & PARSE_OPT_NONEG); if (options->type == OPTION_SUBCOMMAND) continue; if (!long_name) continue; - if (!starts_with(arg, "no-") && - !(options->flags & PARSE_OPT_NONEG) && - skip_prefix(long_name, "no-", &long_name)) + if (skip_prefix(long_name, "no-", &long_name)) opt_flags |= OPT_UNSET; + else if (arg_starts_with_no_no) + continue; - if (!skip_prefix(arg, long_name, &rest)) - rest = NULL; - if (!rest) { - /* abbreviated? */ - if (allow_abbrev && - !strncmp(long_name, arg, arg_end - arg)) { -is_abbreviated: - if (abbrev_option && - !is_alias(p, abbrev_option, options)) { - /* - * If this is abbreviated, it is - * ambiguous. So when there is no - * exact match later, we need to - * error out. - */ - ambiguous_option = abbrev_option; - ambiguous_flags = abbrev_flags; - } - if (!(flags & OPT_UNSET) && *arg_end) - p->opt = arg_end + 1; - abbrev_option = options; - abbrev_flags = flags ^ opt_flags; - continue; - } - /* negation allowed? */ - if (options->flags & PARSE_OPT_NONEG) - continue; - /* negated and abbreviated very much? */ - if (allow_abbrev && starts_with("no-", arg)) { - flags |= OPT_UNSET; - goto is_abbreviated; - } - /* negated? */ - if (!starts_with(arg, "no-")) - continue; - flags |= OPT_UNSET; - if (!skip_prefix(arg + 3, long_name, &rest)) { - /* abbreviated and negated? */ - if (allow_abbrev && - starts_with(long_name, arg + 3)) - goto is_abbreviated; - else - continue; - } - } - if (*rest) { - if (*rest != '=') + if (((flags ^ opt_flags) & OPT_UNSET) && !allow_unset) + continue; + + if (skip_prefix(arg_start, long_name, &rest)) { + if (*rest == '=') + p->opt = rest + 1; + else if (*rest) continue; - p->opt = rest + 1; + return get_value(p, options, flags ^ opt_flags); } - return get_value(p, options, flags ^ opt_flags); + + /* abbreviated? */ + if (!strncmp(long_name, arg_start, arg_end - arg_start)) + register_abbrev(p, options, flags ^ opt_flags, + &abbrev, &ambiguous); + + /* negated and abbreviated very much? */ + if (allow_unset && starts_with("no-", arg)) + register_abbrev(p, options, OPT_UNSET ^ opt_flags, + &abbrev, &ambiguous); } - if (disallow_abbreviated_options && (ambiguous_option || abbrev_option)) + if (disallow_abbreviated_options && (ambiguous.option || abbrev.option)) die("disallowed abbreviated or ambiguous option '%.*s'", (int)(arg_end - arg), arg); - if (ambiguous_option) { + if (ambiguous.option) { error(_("ambiguous option: %s " "(could be --%s%s or --%s%s)"), arg, - (ambiguous_flags & OPT_UNSET) ? "no-" : "", - ambiguous_option->long_name, - (abbrev_flags & OPT_UNSET) ? "no-" : "", - abbrev_option->long_name); + (ambiguous.flags & OPT_UNSET) ? "no-" : "", + ambiguous.option->long_name, + (abbrev.flags & OPT_UNSET) ? "no-" : "", + abbrev.option->long_name); return PARSE_OPT_HELP; } - if (abbrev_option) - return get_value(p, abbrev_option, abbrev_flags); + if (abbrev.option) { + if (*arg_end) + p->opt = arg_end + 1; + return get_value(p, abbrev.option, abbrev.flags); + } return PARSE_OPT_UNKNOWN; } @@ -28,8 +28,6 @@ static int get_st_mode_bits(const char *path, int *mode) return 0; } -static char bad_path[] = "/bad-path/"; - static struct strbuf *get_pathname(void) { static struct strbuf pathname_array[4] = { @@ -59,21 +57,6 @@ static void strbuf_cleanup_path(struct strbuf *sb) strbuf_remove(sb, 0, path - sb->buf); } -char *mksnpath(char *buf, size_t n, const char *fmt, ...) -{ - va_list args; - unsigned len; - - va_start(args, fmt); - len = vsnprintf(buf, n, fmt, args); - va_end(args); - if (len >= n) { - strlcpy(buf, bad_path, n); - return buf; - } - return (char *)cleanup_path(buf); -} - static int dir_prefix(const char *buf, const char *dir) { int len = strlen(dir); @@ -871,7 +854,7 @@ const char *enter_repo(const char *path, int strict) return NULL; } -static int calc_shared_perm(int mode) +int calc_shared_perm(int mode) { int tweak; @@ -24,12 +24,6 @@ char *mkpathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); /* - * Construct a path and place the result in the provided buffer `buf`. - */ -char *mksnpath(char *buf, size_t n, const char *fmt, ...) - __attribute__((format (printf, 3, 4))); - -/* * The `git_common_path` family of functions will construct a path into a * repository's common git directory, which is shared by all worktrees. */ @@ -181,6 +175,7 @@ const char *git_path_shallow(struct repository *r); int ends_with_path_components(const char *path, const char *components); int validate_headref(const char *ref); +int calc_shared_perm(int mode); int adjust_shared_perm(const char *path); char *interpolate_path(const char *path, int real_home); @@ -18,11 +18,11 @@ Members: Matthias Rüster <matthias.ruester@gmail.com> Language: el (Greek) Repository: https://github.com/vyruss/git-po-el -Leader: Jimmy Angelakos <vyruss@hellug.gr> +Members: Jimmy Angelakos <vyruss@hellug.gr> Language: es (Spanish) Repository: https://github.com/ChrisADR/git-po -Leader: Christopher DÃaz <christopher.diaz.riv@gmail.com> +Members: Christopher DÃaz <christopher.diaz.riv@gmail.com> Language: fr (French) Repository: https://github.com/jnavila/git @@ -34,25 +34,25 @@ Repository: https://github.com/bagasme/git-po Leader: Bagas Sanjaya <bagasdotme@gmail.com> Language: is (Icelandic) -Leader: Ævar Arnfjörð Bjarmason <avarab@gmail.com> +Members: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Language: it (Italian) Repository: https://github.com/AlessandroMenti/git-po -Leader: Alessandro Menti <alessandro.menti@alessandromenti.it> +Members: Alessandro Menti <alessandro.menti@alessandromenti.it> Language: ko (Korean) Repository: https://github.com/git-l10n-ko/git-l10n-ko/ -Leader: Gwan-gyeong Mun <elongbug@gmail.com> -Members: Changwoo Ryu <cwryu@debian.org> +Members: Gwan-gyeong Mun <elongbug@gmail.com> + Changwoo Ryu <cwryu@debian.org> Sihyeon Jang <uneedsihyeon@gmail.com> Language: pl (Polish) Repository: https://github.com/Arusekk/git-po -Leader: Arusekk <arek_koz@o2.pl> +Members: Arusekk <arek_koz@o2.pl> Language: pt_PT (Portuguese - Portugal) Repository: https://gitlab.com/alexandre1985/git-pt/ -Leader: Daniel Santos <dacs.git@brilhante.top> +Members: Daniel Santos <dacs.git@brilhante.top> Language: ru (Russian) Repository: https://github.com/DJm00n/git-po-ru/ @@ -73,9 +73,10 @@ Leader: Arkadii Yakovets <ark@cho.red> Members: Kateryna Golovanova <kate@kgthreads.com> Language: vi (Vietnamese) -Repository: https://github.com/vnwildman/git/ -Leader: Trần Ngá»c Quân <vnwildman AT gmail.com> -Members: Nguyá»…n Thái Ngá»c Duy <pclouds AT gmail.com> +Repository: https://github.com/Nekosha/git-po/ +Leader: VÅ© Tiến HÆ°ng <newcomerminecraft@gmail.com> +Members: Trần Ngá»c Quân <vnwildman AT gmail.com> + Nguyá»…n Thái Ngá»c Duy <pclouds AT gmail.com> Language: zh_CN (Simplified Chinese) Repository: https://github.com/dyrone/git/ @@ -191,7 +191,7 @@ # resolve-undo отмÑна на разрешените Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ # resolve conflict коригирам конфликт # resolve reference уÑтановÑване на обекта, Ñочен от указателÑ, проÑледÑване на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ -# cannot resolve reference не може да Ñее открие към какво Ñочи указателÑÑ‚ +# cannot resolve reference не може да Ñе открие към какво Ñочи указателÑÑ‚ # maintenance задачи по поддръжка # GLE поÑледна грешка в нишката - от GetLatError: https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror # lookup table таблица ÑÑŠÑ ÑъответÑÑ‚Ð²Ð¸Ñ @@ -216,7 +216,10 @@ # OID lookup chunk Ð¾Ñ‚ÐºÑŠÑ Ð·Ð° Ñ‚ÑŠÑ€Ñенето # autostash автоматично Ñкатано # symref файл Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» (regular file that stores a string that begins with ref: refs/) -# +# human-readable четим от хора +# pseudoref пÑевдоуказател, напр. MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD или REBASE_HEAD +# reftable таблица Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸ +# its referent '%s' ÑÐ¾Ñ‡ÐµÑ‰Ð¸Ñ Ð³Ð¾ „%s“ # # # ------------------------ @@ -244,10 +247,10 @@ # for i in `sort -u FILES`; do cnt=`grep $i FILES | wc -l`; echo $cnt $i ;done | sort -n msgid "" msgstr "" -"Project-Id-Version: git 2.44\n" +"Project-Id-Version: git 2.45\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-02-16 09:33+0100\n" -"PO-Revision-Date: 2024-02-16 09:38+0100\n" +"POT-Creation-Date: 2024-04-21 16:59+0200\n" +"PO-Revision-Date: 2024-04-21 17:00+0200\n" "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n" "Language-Team: Bulgarian <dict@fsa-bg.org>\n" "Language: bg\n" @@ -749,13 +752,13 @@ 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" "За да пропуÑнете редовете, започващи Ñ â€ž%c“: заменете знака Ñ â€ž “ (Ñтават " "контекÑÑ‚)\n" "За да пропуÑнете редовете, започващи Ñ â€ž%c“: изтрийте ги.\n" -"Редовете, които започват Ñ â€ž%c“ ще Ñе пропуÑнат.\n" +"Редовете, които започват Ñ â€ž%s“ ще Ñе пропуÑнат.\n" msgid "" "If it does not apply cleanly, you will be given an opportunity to\n" @@ -782,8 +785,8 @@ msgid "" "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? " msgstr "" "Редактираното парче не може да Ñе приложи. Да Ñе продължи ли Ñ " -"редактирането? (текущите редакции ще Ñе отменÑÑ‚ при отказ!): „y“ (да)/ " -"„n“ (не)? " +"редактирането? (текущите редакции ще Ñе отменÑÑ‚ при отказ!): „y“ (да)/ „n“ " +"(не)? " msgid "The selected hunks do not apply to the index!" msgstr "Избраните парчета не може да Ñе добавÑÑ‚ в индекÑа!" @@ -803,6 +806,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" "? - print help\n" msgstr "" "j — без решение за парчето, към Ñледващото парче без решение\n" @@ -813,7 +817,8 @@ msgstr "" "/ — Ñ‚ÑŠÑ€Ñене на парче, напаÑващо към даден регулÑрен израз\n" "s — разделÑне на текущото парче на по-малки\n" "e — ръчно редактиране на текущото парче\n" -"? — извеждане не помощта\n" +"p — извеждане на текущото парче\n" +"? — извеждане на помощта\n" msgid "No previous hunk" msgstr "ÐÑма друго парче преди това" @@ -877,8 +882,8 @@ msgstr "" " git config advice.%s false" #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sподÑказка: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sподÑказка:%s%.*s%s\n" msgid "Cherry-picking is not possible because you have unmerged files." msgstr "Отбирането на Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ðµ блокирано от неÑлети файлове." @@ -1981,6 +1986,12 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "„%s“ не е позволено име за клон" +msgid "See `man git check-ref-format`" +msgstr "" +"Вижте Ñтраницата в ръководÑтвото:\n" +"\n" +" git check-ref-format" + #, c-format msgid "a branch named '%s' already exists" msgstr "вече ÑъщеÑтвува клон Ñ Ð¸Ð¼Ðµ „%s“." @@ -2179,15 +2190,8 @@ msgstr "" msgid "adding embedded git repository: %s" msgstr "добавÑне на вградено хранилище: %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 "" -"Ползвайте опциÑта „-f“, ако наиÑтина иÑкате да ги добавите.\n" -"За да изключите това Ñъобщение, изпълнете:\n" -"\n" -" git config advice.addIgnoredFile false" +msgid "Use -f if you really want to add them." +msgstr "Използвайте „-f“, за да ги добавите" msgid "adding files failed" msgstr "неуÑпешно добавÑне на файлове" @@ -2204,15 +2208,8 @@ msgstr "опциÑта „%s“ и път Ñа неÑъвмеÑтими" msgid "Nothing specified, nothing added.\n" msgstr "Ðищо не е зададено и нищо не е добавено.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"„git add .“ ли иÑкахте да изпълните?\n" -"За да изключите това Ñъобщение, изпълнете:\n" -"\n" -" git config advice.addEmptyPathspec false" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "ВероÑтно иÑкахте да използвате „git add .“?" msgid "index file corrupt" msgstr "файлът Ñ Ð¸Ð½Ð´ÐµÐºÑа е повреден" @@ -2290,25 +2287,26 @@ msgid "Failed to split patches." msgstr "Кръпките не може да Ñе разделÑÑ‚." #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." +msgid "When you have resolved this problem, run \"%s --continue\".\n" msgstr "" "След коригирането на този проблем изпълнете:\n" "\n" -" %s --continue“" +" %s --continue“\n" #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" msgstr "" "Ðко предпочитате да преÑкочите тази кръпка, изпълнете:\n" "\n" -" %s --skip" +" %s --skip\n" #, 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 "" "За да включите празната кръпка като празно подаване, изпълнете:\n" "\n" -" %s --allow-empty" +" %s --allow-empty\n" #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." @@ -3204,11 +3202,11 @@ msgstr "клонът е копиран, но конфигурационниÑÑ‚ 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 "" "Въведете опиÑание на клона.\n" " %s\n" -"Редовете, които започват Ñ â€ž%c“, ще бъдат пропуÑнати.\n" +"Редовете, които започват Ñ â€ž%s“, ще бъдат пропуÑнати.\n" msgid "Generic options" msgstr "Общи наÑтройки" @@ -3413,10 +3411,12 @@ msgid "not run from a git repository - no hooks to show\n" msgstr "командата е Ñтартирана извън хранилище на Git, затова нÑма куки\n" 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) ПЪТ] [(-s|--suffix) ФОРМÐТ]\n" +"git bugreport [(-o|--output-directory) ПЪТ]\n" +" [(-s|--suffix) ФОРМÐТ|--no-suffix]\n" " [--diagnose[=РЕЖИМ]]" msgid "" @@ -3610,8 +3610,8 @@ msgstr "Извеждане на атрибутите на обектите (Ñ Ð msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)" msgstr "" -"показване на обекти от този ВИД: „blob“ (BLOB), „tree“ (дърво), " -"„commit“ (подаване), „tag“ (етикет и Ñ‚.н.…)" +"показване на обекти от този ВИД: „blob“ (BLOB), „tree“ (дърво), „commit“ " +"(подаване), „tag“ (етикет и Ñ‚.н.…)" msgid "show object size" msgstr "извеждане на размера на обект" @@ -3907,6 +3907,10 @@ msgstr "„%s“, „%s“ и „%s“ Ñа неÑъвмеÑтими Ñ Ð¸Ð·Ñ‚Ðµ msgid "path '%s' is unmerged" msgstr "пътÑÑ‚ „%s“ не е ÑлÑÑ‚" +#, c-format +msgid "unable to read tree (%s)" +msgstr "дървото не може да бъде прочетено (%s)" + msgid "you need to resolve your current index first" msgstr "първо Ñ‚Ñ€Ñбва да коригирате индекÑа Ñи" @@ -4142,6 +4146,10 @@ msgstr "" msgid "missing branch or commit argument" msgstr "липÑва аргумент — клон или подаване" +#, c-format +msgid "unknown conflict style '%s'" +msgstr "непознат вид конфликт „%s“" + msgid "perform a 3-way merge with the new branch" msgstr "извършване на тройно Ñливане Ñ Ð½Ð¾Ð²Ð¸Ñ ÐºÐ»Ð¾Ð½" @@ -4401,20 +4409,10 @@ msgstr "изтриване и на игнорираните файлове" msgid "remove only ignored files" msgstr "изтриване Ñамо на игнорирани файлове" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"ÐаÑтройката „clean.requireForce“ е зададена като иÑтина, което изиÑква нÑÐºÐ¾Ñ " -"от опциите „-i“, „-n“ или „-f“. ÐÑма да Ñе извърши изчиÑтване" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" +msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"ÐаÑтройката „clean.requireForce“ не е зададена, но Ñтандартно е иÑтина, " -"което изиÑква нÑÐºÐ¾Ñ Ð¾Ñ‚ опциите „-i“, „-n“ или „-f“. ÐÑма да Ñе извърши " -"изчиÑтване" +"ÐаÑтройката „clean.requireForce“ е зададена, което изиÑква опцииÑта „-f“. " +"ÐÑма да Ñе извърши изчиÑтване" msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [ОПЦИЯ…] [--] ХРÐÐИЛИЩЕ [ДИРЕКТОРИЯ]" @@ -4428,7 +4426,7 @@ msgstr "без Ñъздаване на работно дърво" msgid "create a bare repository" msgstr "Ñъздаване на голо хранилище" -msgid "create a mirror repository (implies bare)" +msgid "create a mirror repository (implies --bare)" msgstr "" "Ñъздаване на хранилище-огледало (включва опциÑта „--bare“ за голо хранилище)" @@ -4762,6 +4760,10 @@ msgstr "поле в знаци отдÑÑно" msgid "padding space between columns" msgstr "поле в знаци между колоните" +#, c-format +msgid "%s must be non-negative" +msgstr "%s Ñ‚Ñ€Ñбва да е неотрицателно" + msgid "--command must be the first argument" msgstr "опциÑта „--command“ Ñ‚Ñ€Ñбва да е първиÑÑ‚ аргумент" @@ -5088,35 +5090,35 @@ msgstr "шаблонът за подаване не може да бъде заР#, 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 "" "Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n" -"Ñ â€ž%c“, ще бъдат пропуÑнати.\n" +"Ñ â€ž%s“, ще бъдат пропуÑнати.\n" #, 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 "" "Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n" -"Ñ â€ž%c“, ще бъдат пропуÑнати, а празно Ñъобщение преуÑтановÑва подаването.\n" +"Ñ â€ž%s“, ще бъдат пропуÑнати, а празно Ñъобщение преуÑтановÑва подаването.\n" #, 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 "" "Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n" -"Ñ â€ž%c“, Ñъщо ще бъдат включени — може да ги изтриете вие.\n" +"Ñ â€ž%s“, Ñъщо ще бъдат включени — може да ги изтриете вие.\n" #, 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 "" "Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n" -"Ñ â€ž%c“, Ñъщо ще бъдат включени — може да ги изтриете вие. Празно \n" +"Ñ â€ž%s“, Ñъщо ще бъдат включени — може да ги изтриете вие. Празно \n" "Ñъобщение преуÑтановÑва подаването.\n" msgid "" @@ -5262,9 +5264,9 @@ msgid "" "show ignored files, optional modes: traditional, matching, no. (Default: " "traditional)" msgstr "" -"извеждане на игнорираните файлове. Възможните РЕЖИМи Ñа " -"„traditional“ (традиционен), „matching“ (напаÑващи), „no“ (без игнорираните " -"файлове). СтандартниÑÑ‚ РЕЖИМ е: „traditional“." +"извеждане на игнорираните файлове. Възможните РЕЖИМи Ñа „traditional“ " +"(традиционен), „matching“ (напаÑващи), „no“ (без игнорираните файлове). " +"СтандартниÑÑ‚ РЕЖИМ е: „traditional“." msgid "when" msgstr "КОГÐ" @@ -5274,8 +5276,8 @@ msgid "" "(Default: all)" msgstr "" "игнориране на промѐните в подмодулите. ÐžÐ¿Ñ†Ð¸Ñ Ñ Ð½ÐµÐ·Ð°Ð´ÑŠÐ»Ð¶Ð¸Ñ‚ÐµÐ»Ð½Ð° ÑтойноÑÑ‚ — " -"една от „all“ (вÑички), „dirty“ (тези Ñ Ð½ÐµÐ¿Ð¾Ð´Ð°Ð´ÐµÐ½Ð¸ промѐни), " -"„untracked“ (неÑледени)" +"една от „all“ (вÑички), „dirty“ (тези Ñ Ð½ÐµÐ¿Ð¾Ð´Ð°Ð´ÐµÐ½Ð¸ промѐни), „untracked“ " +"(неÑледени)" msgid "list untracked files in columns" msgstr "извеждане на неÑледените файлове в колони" @@ -5568,9 +5570,8 @@ msgstr "" msgid "show scope of config (worktree, local, global, system, command)" msgstr "" -"извеждане на обхвата на наÑтройката „worktree“ (работно дърво), " -"„local“ (хранилище), „global“ (потребител), „system“ (ÑиÑтема), " -"„command“ (команда)" +"извеждане на обхвата на наÑтройката „worktree“ (работно дърво), „local“ " +"(хранилище), „global“ (потребител), „system“ (ÑиÑтема), „command“ (команда)" msgid "value" msgstr "СТОЙÐОСТ" @@ -5578,6 +5579,9 @@ msgstr "СТОЙÐОСТ" msgid "with --get, use default value when missing entry" msgstr "Ñ â€ž--get“ Ñе използва Ñтандартна СТОЙÐОСТ при липÑваща" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "низ за подаване четим от хора (при нужда отпред Ñе Ð´Ð¾Ð±Ð°Ð²Ñ â€ž#“)" + #, c-format msgid "wrong number of arguments, should be %d" msgstr "неправилен брой аргументи, Ñ‚Ñ€Ñбва да е точно %d" @@ -5673,6 +5677,11 @@ msgstr "" 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 "--fixed-value only applies with 'value-pattern'" msgstr "опциÑта „--fixed-value“ е приложима Ñамо ÑÑŠÑ Ð¨ÐБЛОÐ_ЗÐ_СТОЙÐОСТ" @@ -5707,7 +5716,7 @@ msgid "no such section: %s" msgstr "такъв раззел нÑма: %s" msgid "print sizes in human readable format" -msgstr "извеждане на размерите на обектите във формат леÑно четим от хора" +msgstr "извеждане на размерите на обектите във формат четим от хора" #, c-format msgid "" @@ -6535,6 +6544,9 @@ msgstr "извеждане Ñамо на указателите, които не msgid "read reference patterns from stdin" msgstr "изчитане на шаблоните за указатели от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´" +msgid "also include HEAD ref and pseudorefs" +msgstr "включване и на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ както и пÑевдоуказателите" + msgid "unknown arguments supplied with --stdin" msgstr "непознат аргумент към опциÑта „--stdin“" @@ -7162,10 +7174,6 @@ msgid "no threads support, ignoring %s" msgstr "липÑва поддръжка за нишки. „%s“ ще Ñе пренебрегне" #, c-format -msgid "unable to read tree (%s)" -msgstr "дървото не може да бъде прочетено (%s)" - -#, c-format msgid "unable to read tree %s" msgstr "дървото не може да бъде прочетено: %s" @@ -7783,13 +7791,39 @@ msgstr "опциÑта „--separate-git-dir“ е неÑъвмеÑтима Ñ Ð 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 (КЛЮЧ|СИÐОÐИМ)[(=|:)СТОЙÐОСТ])…]\n" " [--parse] [ФÐЙЛ…]" +#, c-format +msgid "could not stat %s" +msgstr "Ðе може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" + +#, c-format +msgid "file %s is not a regular file" +msgstr "„%s“ не е обикновен файл" + +#, c-format +msgid "file %s is not writable by user" +msgstr "„%s“: нÑма права̀ за запиÑване на файла" + +msgid "could not open temporary file" +msgstr "временниÑÑ‚ файл не може да Ñе отвори" + +#, c-format +msgid "could not read input file '%s'" +msgstr "входниÑÑ‚ файл „%s“ не може да бъде прочетен" + +msgid "could not read from stdin" +msgstr "от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не може да Ñе чете" + +#, c-format +msgid "could not rename temporary file to %s" +msgstr "временниÑÑ‚ файл не може да Ñе преименува на „%s“" + msgid "edit files in place" msgstr "директно редактиране на файловете" @@ -8088,8 +8122,8 @@ msgstr "включване на кръпката в текÑта на пиÑма msgid "enable message threading, styles: shallow, deep" msgstr "" -"използване на нишки за ÑъобщениÑта. СТИЛът е „shallow“ (плитък) или " -"„deep“ (дълбок)" +"използване на нишки за ÑъобщениÑта. СТИЛът е „shallow“ (плитък) или „deep“ " +"(дълбок)" msgid "signature" msgstr "подпиÑ" @@ -8196,18 +8230,6 @@ msgstr "" msgid "could not get object info about '%s'" msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° обекта „%s“" -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "неправилен формат за „ls-tree“: елементът „%s“ не започва Ñ â€ž(“" - -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "неправилен формат за „ls-tree“: елементът „%s“ не завършва Ñ â€ž)“" - -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "неправилен формат за „ls-tree“: %%%.*s" - msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [ОПЦИЯ…] [ФÐЙЛ…]" @@ -8341,18 +8363,6 @@ msgstr "извеждане на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð·Ð°ÐµÐ´Ð½Ð¾ Ñ Ð¾Ð±ÐµÐºÑ‚Ð° msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [ОПЦИЯ…] УКÐЗÐТЕЛ_КЪМ_ДЪРВО [ПЪТ…]" -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "неправилен формат за „ls-tree“: елементът „%s“ не започва Ñ â€ž(“" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "неправилен формат за „ls-tree“: елементът „%s“ не завършва Ñ â€ž(“" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "неправилен формат за „ls-tree“: %%%.*s" - msgid "only show trees" msgstr "извеждане Ñамо на дървета" @@ -8547,6 +8557,10 @@ msgstr "указателÑÑ‚ „%s“ не може да бъде проÑлед msgid "Merging %s with %s\n" msgstr "Сливане на „%s“ Ñ â€ž%s“\n" +#, c-format +msgid "could not parse as tree '%s'" +msgstr "„%s“ не може да Ñе анализира като дърво" + msgid "not something we can merge" msgstr "не може да Ñе Ñлее" @@ -8754,10 +8768,10 @@ msgstr "Празно Ñъобщение предотвратÑва подаваР#, 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 "" -"Редовете, които започват Ñ â€ž%c“, ще бъдат пропуÑнати, а празно\n" +"Редовете, които започват Ñ â€ž%s“, ще бъдат пропуÑнати, а празно\n" "Ñъобщение преуÑтановÑва подаването.\n" msgid "Empty commit message." @@ -8923,9 +8937,6 @@ msgstr "обектът Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ не може да бъде прочетРmsgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "обектът „%s“ е Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ за %s, но е %s" -msgid "could not read from stdin" -msgstr "от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не може да Ñе чете" - msgid "tag on stdin did not pass our strict fsck check" msgstr "етикетът на ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не преминава Ñтрогата проверка Ñ â€žfsck“" @@ -9365,9 +9376,8 @@ msgid "" "cat_sort_uniq)" msgstr "" "коригиране на конфликтите при Ñливане на бележките чрез тази СТРÐТЕГИЯ — " -"„manual“ (ръчно), „ours“ (вашата верÑиÑ), „theirs“ (чуждата верÑиÑ), " -"„union“ (обединÑване), „cat_sort_uniq“ (обединÑване, подреждане, уникални " -"резултати)" +"„manual“ (ръчно), „ours“ (вашата верÑиÑ), „theirs“ (чуждата верÑиÑ), „union“ " +"(обединÑване), „cat_sort_uniq“ (обединÑване, подреждане, уникални резултати)" msgid "Committing unmerged notes" msgstr "Подаване на неÑлети бележки" @@ -9572,8 +9582,8 @@ msgstr "" msgid "" "object already configured in another uploadpack.blobpackfileuri (got '%s')" msgstr "" -"вече има наÑтройка за обекта в друг ред „uploadpack." -"blobpackfileuri“ (получена е „%s“)" +"вече има наÑтройка за обекта в друг ред „uploadpack.blobpackfileuri“ " +"(получена е „%s“)" #, c-format msgid "could not get type of object %s in pack %s" @@ -9855,10 +9865,11 @@ msgid "refusing to run without --i-still-use-this" msgstr "Ñ‚Ñ€Ñбва да добавите и опциÑта „--i-still-use-this“" 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 ШÐБЛОÐ] [--exclude ШÐБЛОÐ]" +"git pack-refs [--all] [--no-prune] [--auto] [--include ШÐБЛОÐ] [--exclude " +"ШÐБЛОÐ]" msgid "pack everything" msgstr "пакетиране на вÑичко" @@ -9866,6 +9877,9 @@ msgstr "пакетиране на вÑичко" msgid "prune loose refs (default)" msgstr "окаÑÑ‚Ñ€Ñне на недоÑтижимите указатели (Ñтандартно)" +msgid "auto-pack refs as needed" +msgstr "автоматично пакетиране на указателите при нужда" + msgid "references to include" msgstr "кои указатели да Ñе включат" @@ -10186,8 +10200,8 @@ msgstr "" msgid "" "You didn't specify any refspecs to push, and push.default is \"nothing\"." msgstr "" -"Ðе Ñте указали верÑÐ¸Ñ Ð·Ð° подаване, а наÑтройката „push.default“ е " -"„nothing“ (нищо без изрично указана верÑÐ¸Ñ Ð´Ð° не Ñе изтлаÑква)" +"Ðе Ñте указали верÑÐ¸Ñ Ð·Ð° подаване, а наÑтройката „push.default“ е „nothing“ " +"(нищо без изрично указана верÑÐ¸Ñ Ð´Ð° не Ñе изтлаÑква)" #, c-format msgid "" @@ -10542,19 +10556,6 @@ msgstr "неправилната ÑтойноÑÑ‚ на „allow_rerere_autoupdat msgid "could not remove '%s'" msgstr "„%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 "" -"След коригирането на конфликтите отбележете решаването им чрез:\n" -"„git add/rm ФÐЙЛ_С_КОÐФЛИКТ…“ и изпълнете „git rebase --continue“.\n" -"Ðко предпочитате да преÑкочите тази кръпка, изпълнете „git rebase --skip“.\n" -"За да откажете пребазирането и да Ñе върнете към първоначалното ÑÑŠÑтоÑние,\n" -"изпълнете „git rebase --abort“." - #, c-format msgid "" "\n" @@ -10583,13 +10584,17 @@ msgstr "не може да Ñе премине към „%s“" msgid "apply options and merge options cannot be used together" msgstr "опциите за прилагане и Ñливане Ñа неÑъвмеÑтими" +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "" +"комбинациÑта „--empty=ask“ е оÑтарÑла. ВмеÑто Ð½ÐµÑ Ð¿Ð¾Ð»Ð·Ð²Ð°Ð¹Ñ‚Ðµ „--empty=stop“." + #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." +"\"stop\"." msgstr "" -"неправилна ÑтойноÑÑ‚ „%s“: вариантите Ñа „drop“ (преÑкачане), " -"„keep“ (запазване) и „ask“ (питане)" +"неправилна празна ÑтойноÑÑ‚ „%s“: вариантите Ñа „drop“ (преÑкачане), „keep“ " +"(запазване) и „stop“ (Ñпиране)" msgid "" "--rebase-merges with an empty string argument is deprecated and will stop " @@ -10782,8 +10787,8 @@ msgstr "" "„preserve“.\n" "Тази ÑтойноÑÑ‚ вече не Ñе поддържа, заменете Ñ Ñ â€žmerges“." -msgid "No rebase in progress?" -msgstr "Изглежда в момента не тече пребазиране" +msgid "no rebase in progress" +msgstr "изглежда в момента не тече пребазиране" msgid "The --edit-todo action can only be used during interactive rebase." msgstr "" @@ -10984,6 +10989,9 @@ msgstr "Ñ‚Ñ€Ñбва да укажете директориÑ" msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [ОПЦИЯ…] [УКÐЗÐТЕЛ]" +msgid "git reflog list" +msgstr "git reflog list" + msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -11009,6 +11017,10 @@ msgstr "git reflog exists УКÐЗÐТЕЛ" msgid "invalid timestamp '%s' given to '--%s'" msgstr "неправилно времево клеймо „%s“ подадено към „--%s“" +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "„%s“ не приема аргументи: „%s“" + msgid "do not actually prune any entries" msgstr "без окаÑÑ‚Ñ€Ñне на запиÑи" @@ -11140,7 +11152,7 @@ msgstr "" "ползвайте „--mirror=fetch“ или „--mirror=push“" #, c-format -msgid "unknown mirror argument: %s" +msgid "unknown --mirror argument: %s" msgstr "неправилна ÑтойноÑÑ‚ за „--mirror“: %s" msgid "fetch the remote branches" @@ -11517,6 +11529,10 @@ msgstr "" "командата „pack-objects“ не може да Ñе Ñтартира за препакетирането на " "гарантиращите обекти" +msgid "failed to feed promisor objects to pack-objects" +msgstr "" +"гарантиращите обекти не може да Ñе подадат на командата „git pack-objects“" + msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" "repack: от „pack-objects“ Ñе изиÑкват редове Ñамо Ñ Ð¿ÑŠÐ»Ð½Ð¸ шеÑтнайÑетични " @@ -12127,6 +12143,13 @@ msgstr "опциÑта „--default“ изиÑква аргумент" msgid "--prefix requires an argument" msgstr "опциÑта „--prefix“ изиÑква аргумент" +msgid "no object format specified" +msgstr "не е указан формат на обект" + +#, c-format +msgid "unsupported object format: %s" +msgstr "неподдържан формат на обект: „%s“" + #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "непознат режим за „--abbrev-ref“: „%s“" @@ -12208,8 +12231,8 @@ msgstr "запазване на първоначално празните под msgid "allow commits with empty messages" msgstr "позволÑване на празни ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ подаване" -msgid "keep redundant, empty commits" -msgstr "запазване на излишните, празни подаваниÑ" +msgid "deprecated: use --empty=keep instead" +msgstr "ОСТÐРЯЛО: вмеÑто това ползвайте „--empty=keep“" msgid "use the 'reference' format to refer to commits" msgstr "указване на Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð²ÑŠÐ² формат за указател" @@ -13567,25 +13590,25 @@ 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" "Въведете Ñъобщение за етикета.\n" " %s\n" -"Редовете, които започват Ñ â€ž%c“, ще бъдат пропуÑнати.\n" +"Редовете, които започват Ñ â€ž%s“, ще бъдат пропуÑнати.\n" #, 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" "Въведете Ñъобщение за етикет.\n" " %s\n" -"Редовете, които започват Ñ â€ž%c“, Ñъщо ще бъдат включени — може да ги " +"Редовете, които започват Ñ â€ž%s“, Ñъщо ще бъдат включени — може да ги " "изтриете вие.\n" msgid "unable to sign the tag" @@ -13671,6 +13694,9 @@ msgstr "извеждане Ñамо на неÑлетите етикети" msgid "print only tags of the object" msgstr "извеждане Ñамо на етикетите на ОБЕКТÐ" +msgid "could not start 'git column'" +msgstr "неуÑпешно изпълнение на „git column“" + #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "опциÑта „%s“ изиÑква режим на ÑпиÑък" @@ -13936,11 +13962,14 @@ msgstr "" msgid "fsmonitor disabled" msgstr "Ñледенето чрез файловата ÑиÑтема е изключено" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [ОПЦИЯ…] -d ИМЕ_ÐÐ_УКÐЗÐТЕЛ [СТÐÐ Ð_СТОЙÐОСТ]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "" +"git update-ref [ОПЦИЯ…] -d ИМЕ_ÐÐ_УКÐЗÐТЕЛ [СТÐÐ _ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "git update-ref [ОПЦИЯ…] ИМЕ_ÐÐ_УКÐЗÐТЕЛ ÐОВÐ_СТОЙÐОСТ [СТÐÐ Ð_СТОЙÐОСТ]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "" +"git update-ref [ОПЦИЯ…] ИМЕ_ÐÐ_УКÐЗÐТЕЛ ÐОВ_ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ " +"[СТÐÐ _ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ]" msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [ОПЦИЯ…] --stdin [-z]" @@ -14623,9 +14652,7 @@ msgid "A really simple server for Git repositories" msgstr "Силно опроÑтен Ñървър за хранилища на Git" msgid "Give an object a human readable name based on an available ref" -msgstr "" -"Задаване на име удобно за потребителите на обект въз оÑнова на наличен " -"указател" +msgstr "Задаване на четимо от хора име на обект въз оÑнова на наличен указател" msgid "Generate a zip archive of diagnostic information" msgstr "Създаване на архив във формат zip Ñ Ð´Ð¸Ð°Ð³Ð½Ð¾Ñтична информациÑ" @@ -15341,6 +15368,10 @@ msgid "Verifying commits in commit graph" msgstr "Проверка на подаваниÑта в гра̀фа" #, c-format +msgid "could not parse commit %s" +msgstr "подаването „%s“ не може да бъде анализирано" + +#, c-format msgid "%s %s is not a commit!" msgstr "%s %s не е подаване!" @@ -15792,8 +15823,13 @@ msgstr "дължината на Ñъкращаване е извън диапаРmsgid "bad zlib compression level %d" msgstr "неправилно ниво на компреÑиране: %d" -msgid "core.commentChar should only be one ASCII character" -msgstr "наÑтройката „core.commentChar“ Ñ‚Ñ€Ñбва да е Ñамо един знак от ASCII" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s не може да Ñъдържа нови редове" + +#, c-format +msgid "%s must have at least one character" +msgstr "%s Ñ‚Ñ€Ñбва да Ñъдържа поне един знак" #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" @@ -15818,9 +15854,9 @@ msgstr "неправилна ÑтойноÑÑ‚ за „%s“: „%s“" msgid "must be one of nothing, matching, simple, upstream or current" msgstr "" "Ñ‚Ñ€Ñбва да е една от Ñледните ÑтойноÑти: „nothing“ (без изтлаÑкване при липÑа " -"на указател), „matching“ (вÑички клони ÑÑŠÑ Ñъвпадащи имена), " -"„simple“ (клонът ÑÑŠÑ Ñъщото име, от който Ñе издърпва), „upstream“ (клонът, " -"от който Ñе издърпва) или „current“ (клонът ÑÑŠÑ Ñъщото име)" +"на указател), „matching“ (вÑички клони ÑÑŠÑ Ñъвпадащи имена), „simple“ " +"(клонът ÑÑŠÑ Ñъщото име, от който Ñе издърпва), „upstream“ (клонът, от който " +"Ñе издърпва) или „current“ (клонът ÑÑŠÑ Ñъщото име)" #, c-format msgid "unable to load config blob object '%s'" @@ -15871,6 +15907,10 @@ msgid "failed to write new configuration file %s" msgstr "новиÑÑ‚ конфигурационен файл „%s“ не може да бъде запазен" #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "коментари на повече от един ред не Ñа позволени: „%s“" + +#, c-format msgid "could not lock config file %s" msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде заключен" @@ -16358,8 +16398,8 @@ msgid "" "'dimmed-zebra', 'plain'" msgstr "" "наÑтройката за цвÑÑ‚ за премеÑтване Ñ‚Ñ€Ñбва да е една от: „no“ (без), " -"„default“ (Ñтандартно), „blocks“ (парчета), „zebra“ (райе), „dimmed-" -"zebra“ (тъмно райе), „plain“ (обикновено)" +"„default“ (Ñтандартно), „blocks“ (парчета), „zebra“ (райе), „dimmed-zebra“ " +"(тъмно райе), „plain“ (обикновено)" #, c-format msgid "" @@ -17718,6 +17758,14 @@ msgid "Unable to create '%s.lock': %s" msgstr "Файлът-ключалка „%s.lock“ не може да бъде Ñъздаден: %s" #, 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" + +#, c-format msgid "unexpected line: '%s'" msgstr "неочакван ред: „%s“" @@ -17740,6 +17788,10 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (нÑма подаваниÑ)" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (хранилището е Ñ Ð³Ñ€ÐµÑˆÐºÐ¸)" + +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" "Подмодулът „%s“ не може да бъде ÑлÑÑ‚ (базата за Ñливане не предшеÑтва " @@ -18219,6 +18271,86 @@ msgstr "ÐеуÑпешен анализ на обекта „%s“" msgid "failed to read the cache" msgstr "кешът не може да бъде прочетен" +#, c-format +msgid "failed to add packfile '%s'" +msgstr "пакетниÑÑ‚ файл „%s“ не може да бъде добавен" + +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "индекÑÑŠÑ‚ за пакети „%s“ не може да бъде отворен" + +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "обект %d в Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» липÑва" + +msgid "cannot store reverse index file" +msgstr "файлът за индекÑа не може да бъде Ñъхранен" + +#, c-format +msgid "could not parse line: %s" +msgstr "редът не може да Ñе анализира: „%s“" + +#, c-format +msgid "malformed line: %s" +msgstr "неправилен ред: „%s“." + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"индекÑÑŠÑ‚ за множеÑтво пакети Ñе преÑкача, защото Ñумата за проверка не " +"Ñъвпада" + +msgid "could not load pack" +msgstr "пакетът не може да Ñе зареди" + +#, c-format +msgid "could not open index for %s" +msgstr "индекÑÑŠÑ‚ за „%s“ не може да Ñе отвори" + +msgid "Adding packfiles to multi-pack-index" +msgstr "ДобавÑне на пакетни файлове към Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети" + +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "непознат предпочитан пакет: %s" + +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "" +"не може да изберете „%s“, който не Ñъдържа обекти, за предпочитан пакет" + +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "пакетниÑÑ‚ файл за триене „%s“ не може да Ñе открие" + +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "предпочитаниÑÑ‚ пакет „%s“ е оÑтарÑл" + +msgid "no pack files to index." +msgstr "нÑма пакетни файлове за индекÑиране" + +msgid "refusing to write multi-pack .bitmap without any objects" +msgstr "" +"многопакетната битова маÑка без никакви обекти не може да бъде запазена" + +msgid "could not write multi-pack bitmap" +msgstr "многопакетната битова маÑка не може да бъде запазена" + +msgid "could not write multi-pack-index" +msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде запазен" + +msgid "Counting referenced objects" +msgstr "ПреброÑване на Ñвързаните обекти" + +msgid "Finding and deleting unreferenced packfiles" +msgstr "ТърÑене и изтриване на неÑвързаните пакетни файлове" + +msgid "could not start pack-objects" +msgstr "командата „pack-objects“ не може да бъде Ñтартирана" + +msgid "could not finish pack-objects" +msgstr "командата „pack-objects“ не може да бъде завършена" + msgid "multi-pack-index OID fanout is of the wrong size" msgstr "" "неправилен размер на откъÑа за разпределÑнето в индекÑа за множеÑтво пакети" @@ -18304,74 +18436,6 @@ msgstr "" "ÑтойноÑтта на отмеÑтването в индекÑа за множеÑтво пакети е извън диапазона" #, c-format -msgid "failed to add packfile '%s'" -msgstr "пакетниÑÑ‚ файл „%s“ не може да бъде добавен" - -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "индекÑÑŠÑ‚ за пакети „%s“ не може да бъде отворен" - -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "обект %d в Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» липÑва" - -msgid "cannot store reverse index file" -msgstr "файлът за индекÑа не може да бъде Ñъхранен" - -#, c-format -msgid "could not parse line: %s" -msgstr "редът не може да Ñе анализира: „%s“" - -#, c-format -msgid "malformed line: %s" -msgstr "неправилен ред: „%s“." - -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "" -"индекÑÑŠÑ‚ за множеÑтво пакети Ñе преÑкача, защото Ñумата за проверка не " -"Ñъвпада" - -msgid "could not load pack" -msgstr "пакетът не може да Ñе зареди" - -#, c-format -msgid "could not open index for %s" -msgstr "индекÑÑŠÑ‚ за „%s“ не може да Ñе отвори" - -msgid "Adding packfiles to multi-pack-index" -msgstr "ДобавÑне на пакетни файлове към Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети" - -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "непознат предпочитан пакет: %s" - -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "" -"не може да изберете „%s“, който не Ñъдържа обекти, за предпочитан пакет" - -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "пакетниÑÑ‚ файл за триене „%s“ не може да Ñе открие" - -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "предпочитаниÑÑ‚ пакет „%s“ е оÑтарÑл" - -msgid "no pack files to index." -msgstr "нÑма пакетни файлове за индекÑиране" - -msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "" -"многопакетната битова маÑка без никакви обекти не може да бъде запазена" - -msgid "could not write multi-pack bitmap" -msgstr "многопакетната битова маÑка не може да бъде запазена" - -msgid "could not write multi-pack-index" -msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде запазен" - -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде изчиÑтен при „%s“" @@ -18417,18 +18481,6 @@ msgstr "индекÑÑŠÑ‚ на пакета „%s“ не може да бъде msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "неправилно отмеÑтване на обект за oid[%d] = %s: %<PRIx64> != %<PRIx64>" -msgid "Counting referenced objects" -msgstr "ПреброÑване на Ñвързаните обекти" - -msgid "Finding and deleting unreferenced packfiles" -msgstr "ТърÑене и изтриване на неÑвързаните пакетни файлове" - -msgid "could not start pack-objects" -msgstr "командата „pack-objects“ не може да бъде Ñтартирана" - -msgid "could not finish pack-objects" -msgstr "командата „pack-objects“ не може да бъде завършена" - #, c-format msgid "unable to create lazy_dir thread: %s" msgstr "не може да Ñе Ñъздаде нишка за директории (lazy_dir): %s" @@ -18483,6 +18535,25 @@ msgstr "" msgid "Bad %s value: '%s'" msgstr "Зададена е лоша ÑтойноÑÑ‚ на променливата „%s“: „%s“" +msgid "failed to decode tree entry" +msgstr "запиÑÑŠÑ‚ в дърво не може да Ñе декодира" + +#, c-format +msgid "failed to map tree entry for %s" +msgstr "не може да Ñе открие ÑъответÑтвието на запиÑа в дърво за „%s“" + +#, c-format +msgid "bad %s in commit" +msgstr "неправилен Ð·Ð°Ð¿Ð¸Ñ â€ž%s“ в подаването" + +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "не може да Ñе открие ÑъответÑтвието на „%s %s“ в обекта-подаване" + +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "ÐеуÑпешно преобразуване на „%s“ към „%s“" + #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" msgstr "" @@ -18589,6 +18660,10 @@ msgid "packed object %s (stored in %s) is corrupt" msgstr "пакетираниÑÑ‚ обект „%s“ (в „%s“) е повреден" #, c-format +msgid "missing mapping of %s to %s" +msgstr "липÑва ÑъответÑтвие на „%s“ към „%s“" + +#, c-format msgid "unable to write file %s" msgstr "файлът „%s“ не може да бъде запиÑан" @@ -18643,6 +18718,10 @@ msgid "cannot read object for %s" msgstr "обектът за „%s“ не може да Ñе прочете" #, c-format +msgid "cannot map object %s to %s" +msgstr "липÑва ÑъответÑтвие на обекта „%s“ към „%s“" + +#, c-format msgid "object fails fsck: %s" msgstr "„fsck“ откри грешка в обект: „%s“" @@ -19110,8 +19189,8 @@ msgstr "неправилна дата на Ñрок: „%s“" #, c-format msgid "option `%s' expects \"always\", \"auto\", or \"never\"" msgstr "" -"опциÑта „%s“ изиÑква нÑÐºÐ¾Ñ Ð¾Ñ‚ ÑтойноÑтите: „always“ (винаги), " -"„auto“ (автоматично) или „never“ (никога)" +"опциÑта „%s“ изиÑква нÑÐºÐ¾Ñ Ð¾Ñ‚ ÑтойноÑтите: „always“ (винаги), „auto“ " +"(автоматично) или „never“ (никога)" #, c-format msgid "malformed object name '%s'" @@ -19165,6 +19244,18 @@ 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 "…" @@ -20056,6 +20147,78 @@ msgid "could not delete references: %s" msgstr "Указателите не може да бъдат изтрити: %s" #, c-format +msgid "refname is dangerous: %s" +msgstr "опаÑно име на указател: %s" + +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "опит за Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° указател „%s“ към обект, който не ÑъщеÑтвува: %s" + +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "опит за запиÑване на обект, който не е подаване — %s, в клона „%s“" + +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"не Ñа позволени повече от една промѐни (включително чрез ÑÐ¾Ñ‡ÐµÑ‰Ð¸Ñ Ð³Ð¾ „%s“) на " +"ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“" + +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "" +"указателÑÑ‚ „%s“ не може да Ñе заключи: не може да Ñе открие към какво Ñочи " +"указателÑÑ‚ „%s“" + +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "указателÑÑ‚ „%s“ не може да Ñе заключи: грешка при четене на указателÑ" + +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"не Ñа позволени повече от една промѐни на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€ž%s“ (включително през " +"ÑÐ¸Ð¼Ð²Ð¾Ð»Ð½Ð¸Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» „%s“)" + +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "указателÑÑ‚ „%s“ не може да Ñе заключи:cуказателÑÑ‚ вече ÑъщеÑтвува" + +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "" +"указателÑÑ‚ „%s“ не може да Ñе заключи: указателÑÑ‚ липÑва, а Ñе очаква „%s“" + +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "" +"указателÑÑ‚ „%s“ не може да Ñе заключи: той Ñочи към „%s“, а Ñе очаква да " +"Ñочи към „%s“" + +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "таблица Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸: подготовка на транзакциÑ: %s" + +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "таблица Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸: неуÑпешна транзакциÑ: %s" + +#, c-format +msgid "unable to compact stack: %s" +msgstr "Ñтекът не може да Ñе Ñвие: %s" + +#, c-format +msgid "refname %s not found" +msgstr "името на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€ž%s“ не може да бъде открито" + +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "името на указател „%s“ е Ñимволен указател, не може да Ñе копира" + +#, c-format msgid "invalid refspec '%s'" msgstr "неправилен указател: „%s“" @@ -20066,6 +20229,10 @@ msgstr "" "„%s“" #, c-format +msgid "unknown value for object-format: %s" +msgstr "непозната ÑтойноÑÑ‚ за „--object-format“: „%s“" + +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "„%sinfo/refs“ е неизползваемо, проверете дали е хранилище на git" @@ -20521,7 +20688,18 @@ msgstr "" "липÑва" #, c-format -msgid "could not get commit for ancestry-path argument %s" +msgid "%s exists but is a symbolic ref" +msgstr "„%s“ ÑъщеÑтвува и не е Ñимволна връзка" + +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"„--merge“ изиÑква нÑкой от пÑевдоуказателите „MERGE_HEAD“, " +"„CHERRY_PICK_HEAD“, „REVERT_HEAD“ или „REBASE_HEAD“" + +#, c-format +msgid "could not get commit for --ancestry-path argument %s" msgstr "подаването „%s“ към опциÑта „--ancestry-path“ не може да бъде получено" msgid "--unpacked=<packfile> no longer supported" @@ -20815,6 +20993,19 @@ msgid "unknown action: %d" msgstr "неизвеÑтно дейÑтвие: %d" 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 "" +"След коригирането на конфликтите отбележете решаването им чрез:\n" +"„git add/rm ФÐЙЛ_С_КОÐФЛИКТ…“ и изпълнете „git rebase --continue“.\n" +"Ðко предпочитате да преÑкочите тази кръпка, изпълнете „git rebase --skip“.\n" +"За да откажете пребазирането и да Ñе върнете към първоначалното ÑÑŠÑтоÑние,\n" +"изпълнете „git rebase --abort“." + +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -21065,10 +21256,6 @@ msgid "could not update %s" msgstr "„%s“ не може да Ñе обнови" #, c-format -msgid "could not parse commit %s" -msgstr "подаването „%s“ не може да бъде анализирано" - -#, c-format msgid "could not parse parent commit %s" msgstr "родителÑкото подаване „%s“ не може да бъде анализирано" @@ -21174,10 +21361,6 @@ msgid "invalid command '%.*s'" msgstr "неправилна команда „%.*s“" #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "„%s“ не приема аргументи: „%s“" - -#, c-format msgid "missing arguments for %s" msgstr "„%s“ изиÑква аргументи" @@ -21651,6 +21834,10 @@ msgstr "" "не може да Ñе зададе текуща работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð¿Ñ€Ð¸ неправилни наÑтройки" #, c-format +msgid "'%s' already specified as '%s'" +msgstr "„%s“ вече ÑъщеÑтвува като „%s“" + +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "Очаква Ñе верÑÐ¸Ñ Ð½Ð° хранилището на git <= %d, а не %d" @@ -21848,6 +22035,21 @@ msgstr "обектът в индекÑа е директориÑ, но не ча msgid "cannot use split index with a sparse index" msgstr "разделѐн Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе ползва чаÑтичен индекÑ" +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "неправилен формат за „%s“: елементът „%s“ не започва Ñ â€ž(“" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "неправилен формат за „%s“: елементът „%s“ не завършва Ñ â€ž)“" + +#. TRANSLATORS: %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "неправилен формат за „%s“: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #, c-format msgid "%u.%2.2u GiB" @@ -22175,29 +22377,6 @@ msgstr "непозната ÑтойноÑÑ‚ „%s“ за наÑтройката msgid "empty trailer token in trailer '%.*s'" msgstr "празна завършваща лекÑема в епилога „%.*s“" -#, c-format -msgid "could not read input file '%s'" -msgstr "входниÑÑ‚ файл „%s“ не може да бъде прочетен" - -#, c-format -msgid "could not stat %s" -msgstr "Ðе може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" - -#, c-format -msgid "file %s is not a regular file" -msgstr "„%s“ не е обикновен файл" - -#, c-format -msgid "file %s is not writable by user" -msgstr "„%s“: нÑма права̀ за запиÑване на файла" - -msgid "could not open temporary file" -msgstr "временниÑÑ‚ файл не може да Ñе отвори" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "временниÑÑ‚ файл не може да Ñе преименува на „%s“" - msgid "full write to remote helper failed" msgstr "неуÑпешен пълен Ð·Ð°Ð¿Ð¸Ñ ÐºÑŠÐ¼ наÑрещната помощна програма" @@ -22301,7 +22480,7 @@ msgstr "" "изброÑване на указателите" #, c-format -msgid "helper %s does not support 'force'" +msgid "helper %s does not support '--force'" msgstr "наÑрещната помощна програма „%s“ не поддържа опциÑта „--force“" msgid "couldn't run fast-export" @@ -22715,6 +22894,10 @@ msgstr "неправилен номер на порт" msgid "invalid '..' path segment" msgstr "неправилна чаÑÑ‚ от Ð¿ÑŠÑ‚Ñ â€ž..“" +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "ГРЕШКÐ: Ñъобщението не може да Ñе форматира: %s\n" + msgid "usage: " msgstr "употреба: " @@ -23539,8 +23722,8 @@ msgstr "ГРЕШКÐ: не може да Ñе извлече Ð°Ð´Ñ€ÐµÑ Ð¾Ñ‚ „ #. at this point. msgid "What to do with this address? ([q]uit|[d]rop|[e]dit): " msgstr "" -"Какво да Ñе направи Ñ Ñ‚Ð¾Ð·Ð¸ адреÑ? „q“ (Ñпиране), „d“ (изтриване), " -"„e“ (редактиране): " +"Какво да Ñе направи Ñ Ñ‚Ð¾Ð·Ð¸ адреÑ? „q“ (Ñпиране), „d“ (изтриване), „e“ " +"(редактиране): " #, perl-format msgid "CA path \"%s\" does not exist" @@ -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-02-17 18:07+0100\n" -"PO-Revision-Date: 2024-02-17 18:14+0100\n" +"POT-Creation-Date: 2024-04-26 16:16+0200\n" +"PO-Revision-Date: 2024-04-26 16:22+0200\n" "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n" "Language-Team: German\n" "Language: de\n" @@ -512,12 +512,12 @@ 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" "Um '%c' Zeilen zu entfernen, machen Sie aus diesen ' ' Zeilen (Kontext).\n" "Um '%c' Zeilen zu entfernen, löschen Sie diese.\n" -"Zeilen, die mit %c beginnen, werden entfernt.\n" +"Zeilen, die mit %s beginnen, werden entfernt.\n" msgid "" "If it does not apply cleanly, you will be given an opportunity to\n" @@ -566,6 +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" "? - print help\n" msgstr "" "j - diesen Patch-Block unbestimmt lassen, nächsten unbestimmten Patch-Block " @@ -575,9 +576,10 @@ msgstr "" "Block anzeigen\n" "K - diesen Patch-Block unbestimmt lassen, vorherigen Patch-Block anzeigen\n" "g - Patch-Block zum Hinspringen auswählen\n" -"/ - nach Patch-Block suchen, der gegebenem regulärem Ausdruck entspricht\n" +"/ - 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" "? - Hilfe anzeigen\n" msgid "No previous hunk" @@ -640,8 +642,8 @@ msgstr "" "Deaktivieren Sie diese Nachricht mit \"git config advice.%s false\"" #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sHinweis: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sHinweis:%s%.*s%s\n" msgid "Cherry-picking is not possible because you have unmerged files." msgstr "" @@ -1160,10 +1162,6 @@ msgstr[0] "Wende Patch %%s mit %d Zurückweisung an..." msgstr[1] "Wende Patch %%s mit %d Zurückweisungen an..." #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "Verkürze Name von .rej Datei zu %.*s.rej" - -#, c-format msgid "cannot open %s" msgstr "kann '%s' nicht öffnen" @@ -1600,6 +1598,10 @@ msgid "could not create file '%s'" msgstr "konnte Datei '%s' nicht erstellen" #, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "konnte 'show' für Objekt '%s' nicht starten" + +#, c-format msgid "could not read file '%s'" msgstr "Konnte Datei '%s' nicht lesen" @@ -1751,6 +1753,9 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "'%s' ist kein gültiger Branchname" +msgid "See `man git check-ref-format`" +msgstr "Siehe `man git check-ref-format`" + #, c-format msgid "a branch named '%s' already exists" msgstr "Branch '%s' existiert bereits" @@ -1957,14 +1962,8 @@ msgstr "" msgid "adding embedded git repository: %s" msgstr "Füge eingebettetes Repository hinzu: %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 "" -"Nutzen Sie die Option -f, wenn sie wirklich hinzugefügt werden sollen.\n" -"Um diese Meldung abzuschalten, führen Sie folgenden Befehl aus:\n" -"\"git config advice.addIgnoredFile false\"" +msgid "Use -f if you really want to add them." +msgstr "Verwenden Sie -f, wenn Sie diese wirklich hinzufügen möchten." msgid "adding files failed" msgstr "Hinzufügen von Dateien fehlgeschlagen" @@ -1982,14 +1981,8 @@ msgstr "" msgid "Nothing specified, nothing added.\n" msgstr "Nichts spezifiziert, nichts hinzugefügt.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"Eventuell meinten Sie 'git add .'?\n" -"Um diese Meldung abzuschalten, führen Sie folgenden Befehl aus:\n" -"\"git config advice.addEmptyPathspec false\"" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "Meinten Sie vielleicht 'git add .'?" msgid "index file corrupt" msgstr "Index-Datei beschädigt" @@ -2066,21 +2059,22 @@ msgid "Failed to split patches." msgstr "Fehler beim Aufteilen der Patches." #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." +msgid "When you have resolved this problem, run \"%s --continue\".\n" msgstr "" -"Wenn Sie das Problem aufgelöst haben, führen Sie \"%s --continue\" aus." +"Wenn Sie dieses Problem behoben haben, führen Sie \"%s --continue\" aus.\n" #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" msgstr "" "Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen \"%s --" -"skip\" aus." +"skip\" aus.\n" #, 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 "" -"Um den leeren Patch als einen leeren Commit zu speichern, führen Sie \"%s --" -"allow-empty\" aus." +"Um den leeren Patch als leeren Commit aufzuzeichnen, führen Sie \"%s --allow-" +"empty\" aus.\n" #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." @@ -2950,11 +2944,11 @@ msgstr "" 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 "" "Bitte ändern Sie die Beschreibung für den Branch\n" " %s\n" -"Zeilen, die mit '%c' beginnen, werden entfernt.\n" +"Zeilen, die mit '%s' beginnen, werden entfernt.\n" msgid "Generic options" msgstr "Allgemeine Optionen" @@ -3163,10 +3157,12 @@ msgid "not run from a git repository - no hooks to show\n" msgstr "nicht in einem Git-Repository ausgeführt - keine Hooks zum Anzeigen\n" 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) <Pfad>] [(-s | --suffix) <Format>]\n" +"git bugreport [(-o | --output-directory) <Pfad>]\n" +" [(-s | --suffix) <Format> | --no-suffix]\n" " [--diagnose[=<Modus>]]" msgid "" @@ -3660,6 +3656,10 @@ msgstr "" msgid "path '%s' is unmerged" msgstr "Pfad '%s' ist nicht zusammengeführt" +#, c-format +msgid "unable to read tree (%s)" +msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen" + msgid "you need to resolve your current index first" msgstr "Sie müssen zuerst die Konflikte in Ihrem aktuellen Index auflösen." @@ -3898,6 +3898,10 @@ msgstr "Kann Branch nicht zu Nicht-Commit '%s' wechseln" msgid "missing branch or commit argument" msgstr "Branch- oder Commit-Argument fehlt" +#, c-format +msgid "unknown conflict style '%s'" +msgstr "unbekannter Konfliktstil '%s'" + msgid "perform a 3-way merge with the new branch" msgstr "einen 3-Wege-Merge mit dem neuen Branch ausführen" @@ -4157,19 +4161,10 @@ msgstr "auch ignorierte Dateien löschen" msgid "remove only ignored files" msgstr "nur ignorierte Dateien löschen" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce auf \"true\" gesetzt und weder -i, -n noch -f gegeben; " -"\"clean\" verweigert" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" +msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"clean.requireForce standardmäßig auf \"true\" gesetzt und weder -i, -n noch -" -"f gegeben; \"clean\" verweigert" +"clean.requireForce ist 'true' und -f ist nicht angegeben: clean wird " +"verweigert" msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [<Optionen>] [--] <Repository> [<Verzeichnis>]" @@ -4183,8 +4178,8 @@ msgstr "kein Auschecken" msgid "create a bare repository" msgstr "ein Bare-Repository erstellen" -msgid "create a mirror repository (implies bare)" -msgstr "ein Spiegelarchiv erstellen (impliziert bare)" +msgid "create a mirror repository (implies --bare)" +msgstr "ein Spiegel-Repository erstellen (impliziert --bare)" msgid "to clone from a local repository" msgstr "von einem lokalen Repository klonen" @@ -4519,6 +4514,10 @@ msgstr "Abstand zum rechten Rand auffüllen" msgid "padding space between columns" msgstr "Abstand zwischen Spalten auffüllen" +#, c-format +msgid "%s must be non-negative" +msgstr "%s muss nicht-negativ sein" + msgid "--command must be the first argument" msgstr "--command muss an erster Stelle stehen" @@ -4837,38 +4836,38 @@ msgstr "Konnte Commit-Vorlage nicht schreiben" #, 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 "" "Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,\n" -"die mit '%c' beginnen, werden ignoriert.\n" +"die mit '%s' beginnen, werden ignoriert.\n" #, 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 "" "Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,\n" -"die mit '%c' beginnen, werden ignoriert, und eine leere Beschreibung\n" +"die mit '%s' beginnen, werden ignoriert, und eine leere Beschreibung\n" "bricht den Commit ab.\n" #, 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 "" "Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,\n" -"die mit '%c' beginnen, werden beibehalten; wenn Sie möchten, können Sie\n" +"die mit '%s' beginnen, werden beibehalten; wenn Sie möchten, können Sie\n" "diese entfernen.\n" #, 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 "" "Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen, " "die\n" -"mit '%c' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese " +"mit '%s' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese " "entfernen.\n" "Eine leere Beschreibung bricht den Commit ab.\n" @@ -5319,6 +5318,10 @@ msgstr "Wert" msgid "with --get, use default value when missing entry" msgstr "mit --get, benutze den Standardwert, wenn der Eintrag fehlt" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"menschenlesbare Kommentarzeichenfolge (# wird bei Bedarf vorangestellt)" + #, c-format msgid "wrong number of arguments, should be %d" msgstr "Falsche Anzahl von Argumenten - sollte %d sein." @@ -5413,6 +5416,10 @@ msgstr "" 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 "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value wird nur zusammen mit 'Wert-Muster' angewendet" @@ -6284,6 +6291,9 @@ msgstr "nur Referenzen ausgeben, die diesen Commit nicht enthalten" msgid "read reference patterns from stdin" msgstr "Referenzmuster von Standard-Eingabe lesen" +msgid "also include HEAD ref and pseudorefs" +msgstr "auch die Referenz HEAD und Pseudoreferenzen einschließen" + msgid "unknown arguments supplied with --stdin" msgstr "unbekannte Argumente mit --stdin geliefert" @@ -6909,10 +6919,6 @@ msgid "no threads support, ignoring %s" msgstr "keine Unterstützung von Threads, '%s' wird ignoriert" #, c-format -msgid "unable to read tree (%s)" -msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen" - -#, c-format msgid "unable to read tree %s" msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen" @@ -7527,7 +7533,7 @@ msgstr "--separate-git-dir nicht kompatibel mit Bare-Repository" 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" @@ -7535,6 +7541,32 @@ msgstr "" "[(=|:)<Wert>])...]\n" " [--parse] [<Datei>...]" +#, c-format +msgid "could not stat %s" +msgstr "Konnte '%s' nicht lesen" + +#, c-format +msgid "file %s is not a regular file" +msgstr "Datei '%s' ist keine reguläre Datei" + +#, c-format +msgid "file %s is not writable by user" +msgstr "Datei %s ist vom Benutzer nicht beschreibbar." + +msgid "could not open temporary file" +msgstr "konnte temporäre Datei '%s' nicht öffnen" + +#, c-format +msgid "could not read input file '%s'" +msgstr "Konnte Eingabe-Datei '%s' nicht lesen" + +msgid "could not read from stdin" +msgstr "konnte nicht von der Standard-Eingabe lesen" + +#, c-format +msgid "could not rename temporary file to %s" +msgstr "konnte temporäre Datei nicht zu %s umbenennen" + msgid "edit files in place" msgstr "vorhandene Dateien direkt bearbeiten" @@ -7929,18 +7961,6 @@ msgstr "" msgid "could not get object info about '%s'" msgstr "konnte Objekt-Informationen über '%s' nicht bestimmen" -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "ungültiges ls-files-Format: Element '%s' fängt nicht mit '(' an" - -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "ungültiges ls-files-Format: Element '%s' endet nicht auf ')'" - -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "ungültiges ls-files-Format: %%%.*s" - msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<Optionen>] [<Datei>...]" @@ -8078,18 +8098,6 @@ msgstr "zusätzlich zum Objekt die darauf verweisenden Referenzen anzeigen" msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<Optionen>] <Commit-Referenz> [<Pfad>...]" -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "ungültiges ls-tree-Format: Element '%s' fängt nicht mit '(' an" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "ungültiges ls-tree-Format: Element '%s' endet nicht mit ')'" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "ungültiges ls-tree-Format: %%%.*s" - msgid "only show trees" msgstr "nur Verzeichnisse anzeigen" @@ -8279,6 +8287,10 @@ msgstr "Konnte Referenz '%s' nicht auflösen" msgid "Merging %s with %s\n" msgstr "Führe %s mit %s zusammen\n" +#, c-format +msgid "could not parse as tree '%s'" +msgstr "'%s' konnte nicht als Tree geparst werden" + msgid "not something we can merge" msgstr "nichts was wir zusammenführen können" @@ -8487,10 +8499,10 @@ msgstr "Eine leere Commit-Beschreibung bricht den Commit ab.\n" #, 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 "" -"Zeilen, die mit '%c' beginnen, werden ignoriert,\n" +"Zeilen, die mit '%s' beginnen, werden ignoriert,\n" "und eine leere Beschreibung bricht den Commit ab.\n" msgid "Empty commit message." @@ -8655,9 +8667,6 @@ msgstr "konnte getaggtes Objekt '%s' nicht lesen" msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "Objekt '%s' als '%s' getaggt, aber ist ein '%s' Typ" -msgid "could not read from stdin" -msgstr "konnte nicht von der Standard-Eingabe lesen" - msgid "tag on stdin did not pass our strict fsck check" msgstr "" "Tag von der Standardeingabe für unsere strenge Ãœberprüfung bei fsck ungültig" @@ -8924,10 +8933,6 @@ msgstr "git notes prune [<Optionen>]" msgid "Write/edit the notes for the following object:" msgstr "Schreiben/Bearbeiten der Notizen für das folgende Objekt:" -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "konnte 'show' für Objekt '%s' nicht starten" - msgid "could not read 'show' output" msgstr "Konnte Ausgabe von 'show' nicht lesen." @@ -9579,10 +9584,11 @@ msgid "refusing to run without --i-still-use-this" msgstr "Ausführung ohne --i-still-use-this verweigert" 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 <Muster>] [--exclude <Muster>]" +"git pack-refs [--all] [--no-prune] [--auto] [--include <Muster>] [--exclude " +"<Muster>]" msgid "pack everything" msgstr "alles packen" @@ -9590,6 +9596,9 @@ msgstr "alles packen" msgid "prune loose refs (default)" msgstr "lose Referenzen entfernen (Standard)" +msgid "auto-pack refs as needed" +msgstr "auto-pack-Referenzen nach Bedarf" + msgid "references to include" msgstr "einzubeziehende Referenzen" @@ -9826,7 +9835,7 @@ msgid "git push [<options>] [<repository> [<refspec>...]]" msgstr "git push [<Optionen>] [<Repository> [<Refspec>...]]" msgid "tag shorthand without <tag>" -msgstr "Kurzschrift für Tag ohne <Tag>" +msgstr "Kurzschrift für das Tag ohne <Tag>" msgid "--delete only accepts plain target ref names" msgstr "--delete akzeptiert nur reine Referenznamen als Ziel" @@ -10281,21 +10290,6 @@ msgstr "Ignoriere ungültiges allow_rerere_autoupdate: '%s'" msgid "could not remove '%s'" msgstr "Konnte '%s' nicht löschen" -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 "" -"Lösen Sie alle Konflikte manuell auf, markieren Sie diese mit\n" -"\"git add/rm <konfliktbehaftete_Dateien>\" und führen Sie dann\n" -"\"git rebase --continue\" aus.\n" -"Sie können auch stattdessen diesen Commit auslassen, indem\n" -"Sie \"git rebase --skip\" ausführen.\n" -"Um abzubrechen und zurück zum Zustand vor \"git rebase\" zu gelangen,\n" -"führen Sie \"git rebase --abort\" aus." - #, c-format msgid "" "\n" @@ -10328,13 +10322,16 @@ msgstr "" "Optionen für \"am\" und Optionen für \"merge\" können nicht gemeinsam " "verwendet werden" +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask ist veraltet; verwenden Sie stattdessen '--empty=stop'." + #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." +"\"stop\"." msgstr "" "nicht erkannter leerer Typ '%s'; gültige Werte sind \"drop\", \"keep\", und " -"\"ask\"." +"\"stop\"." msgid "" "--rebase-merges with an empty string argument is deprecated and will stop " @@ -10522,8 +10519,8 @@ msgstr "" "'preserve' gesetzt, was nicht länger unterstützt wird; nutzen Sie\n" "stattdessen 'merges'" -msgid "No rebase in progress?" -msgstr "Kein Rebase im Gange?" +msgid "no rebase in progress" +msgstr "kein Rebase im Gange" msgid "The --edit-todo action can only be used during interactive rebase." msgstr "" @@ -10722,6 +10719,9 @@ msgstr "Sie müssen ein Verzeichnis angeben" msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<log-Optionen>] [<Referenz>]" +msgid "git reflog list" +msgstr "git reflog list" + msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -10748,6 +10748,10 @@ msgstr "git reflog exists <Referenz>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "ungültiger Zeitstempel '%s' für '--%s'" +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s akzeptiert keine Argumente: '%s'" + msgid "do not actually prune any entries" msgstr "Einträge nicht wirklich löschen" @@ -10877,8 +10881,8 @@ msgstr "" "\t benutzen Sie stattdessen --mirror=fetch oder --mirror=push" #, c-format -msgid "unknown mirror argument: %s" -msgstr "unbekanntes Argument für Option mirror: %s" +msgid "unknown --mirror argument: %s" +msgstr "unbekanntes --mirror Argument: %s" msgid "fetch the remote branches" msgstr "die Remote-Branches anfordern" @@ -11254,6 +11258,9 @@ msgstr "" "Konnte 'pack-objects' für das Neupacken von Objekten aus partiell geklonten\n" "Remote-Repositories nicht starten." +msgid "failed to feed promisor objects to pack-objects" +msgstr "promisor-Objekte konnten nicht an pack-objects übergeben werden" + msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" "repack: Erwarte Zeilen mit vollständiger Hex-Objekt-ID nur von pack-objects." @@ -11861,6 +11868,13 @@ msgstr "--default benötigt ein Argument" msgid "--prefix requires an argument" msgstr "--prefix benötigt ein Argument" +msgid "no object format specified" +msgstr "kein Objektformat angegeben" + +#, c-format +msgid "unsupported object format: %s" +msgstr "nicht unterstütztes Objekt-Format: %s" + #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "unbekannter Modus für --abbrev-ref: %s" @@ -11943,8 +11957,8 @@ msgstr "ursprüngliche, leere Commits erhalten" msgid "allow commits with empty messages" msgstr "Commits mit leerer Beschreibung erlauben" -msgid "keep redundant, empty commits" -msgstr "redundante, leere Commits behalten" +msgid "deprecated: use --empty=keep instead" +msgstr "veraltet: benutzen Sie stattdessen --empty=keep" msgid "use the 'reference' format to refer to commits" msgstr "das 'reference' Format nutzen, um auf Commits zu verweisen" @@ -13318,26 +13332,26 @@ 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" -"Geben Sie eine Beschreibung für Tag\n" +"Geben Sie eine Beschreibung für das Tag:\n" " %s\n" -"ein. Zeilen, die mit '%c' beginnen, werden ignoriert.\n" +"ein. Zeilen, die mit '%s' beginnen, werden ignoriert.\n" #, 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" -"Geben Sie eine Beschreibung für Tag\n" +"Geben Sie eine Beschreibung für das Tag\n" " %s\n" -"ein. Zeilen, die mit '%c' beginnen, werden behalten; Sie dürfen diese\n" -"selbst entfernen wenn Sie möchten.\n" +"ein. Zeilen, die mit '%s' beginnen, werden behalten; Sie dürfen diese\n" +"selbst entfernen, wenn Sie möchten.\n" msgid "unable to sign the tag" msgstr "konnte Tag nicht signieren" @@ -13422,6 +13436,9 @@ msgstr "nur Tags ausgeben, die nicht gemerged wurden" msgid "print only tags of the object" msgstr "nur Tags von dem Objekt ausgeben" +msgid "could not start 'git column'" +msgstr "konnte 'git column' nicht starten" + #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "die Option '%s' ist nur im Listenmodus erlaubt" @@ -13685,12 +13702,11 @@ msgstr "" msgid "fsmonitor disabled" msgstr "Dateisystem-Monitor deaktiviert" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<Optionen>] -d <Referenzname> [<alter-Wert>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<Optionen>] -d <Referenzname> [<alte-oid>]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "" -"git update-ref [<Optionen>] <Referenzname> <neuer-Wert> [<alter-Wert>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "git update-ref [<Optionen>] <Referenzname> <neue-oid> [<alte-oid>]" msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [<Optionen>] --stdin [-z]" @@ -15099,6 +15115,10 @@ msgid "Verifying commits in commit graph" msgstr "Commit in Commit-Graph überprüfen" #, c-format +msgid "could not parse commit %s" +msgstr "Konnte Commit %s nicht parsen." + +#, c-format msgid "%s %s is not a commit!" msgstr "%s %s ist kein Commit!" @@ -15537,8 +15557,13 @@ msgstr "Länge für Abkürzung von Commit-IDs außerhalb des Bereichs: %d" msgid "bad zlib compression level %d" msgstr "ungültiger zlib Komprimierungsgrad %d" -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar sollte nur ein ASCII-Zeichen sein" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s kann keinen Zeilenumbruch enthalten" + +#, c-format +msgid "%s must have at least one character" +msgstr "%s muss mindestens ein Zeichen enthalten" #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" @@ -15616,6 +15641,10 @@ msgid "failed to write new configuration file %s" msgstr "Konnte neue Konfigurationsdatei '%s' nicht schreiben." #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "kein mehrzeiliger Kommentar erlaubt: '%s'" + +#, c-format msgid "could not lock config file %s" msgstr "Konnte Konfigurationsdatei '%s' nicht sperren." @@ -17442,6 +17471,14 @@ msgid "Unable to create '%s.lock': %s" msgstr "Konnte '%s.lock' nicht erstellen: %s" #, 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" + +#, c-format msgid "unexpected line: '%s'" msgstr "unerwartete Zeile: '%s'" @@ -17452,6 +17489,10 @@ msgid "quoted CRLF detected" msgstr "angeführtes CRLF entdeckt" #, c-format +msgid "unable to format message: %s" +msgstr "Meldung kann nicht formatiert werden: %s" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Fehler beim Merge von Submodul %s (nicht ausgecheckt)." @@ -17464,6 +17505,11 @@ 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)" +msgstr "" +"Submodul %s konnte nicht zusammengeführt werden (Repository beschädigt)" + +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "Fehler beim Merge von Submodul %s (Commits folgen keiner Merge-Basis)" @@ -17950,6 +17996,83 @@ msgstr "Konnte Objekt '%s' nicht parsen." msgid "failed to read the cache" msgstr "Lesen des Zwischenspeichers fehlgeschlagen" +#, c-format +msgid "failed to add packfile '%s'" +msgstr "Fehler beim Hinzufügen von Packdatei '%s'" + +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "Fehler beim Öffnen von pack-index '%s'" + +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "Fehler beim Lokalisieren von Objekt %d in Packdatei" + +msgid "cannot store reverse index file" +msgstr "kann Reverse-Index-Datei nicht speichern" + +#, c-format +msgid "could not parse line: %s" +msgstr "Zeile konnte nicht geparst werden: %s" + +#, c-format +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" + +#, c-format +msgid "could not open index for %s" +msgstr "konnte Index für %s nicht öffnen" + +msgid "Adding packfiles to multi-pack-index" +msgstr "Packdateien zum Multi-Pack-Index hinzufügen" + +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "unbekanntes bevorzugtes Paket: '%s'" + +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "bevorzugtes Paket %s ohne Objekte kann nicht ausgewählt werden" + +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "Pack-Datei %s zum Weglassen nicht gefunden" + +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "bevorzugtes Paket '%s' ist abgelaufen" + +msgid "no pack files to index." +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 "could not write multi-pack bitmap" +msgstr "Multi-Pack-Bitmap konnte nicht geschrieben werden" + +msgid "could not write multi-pack-index" +msgstr "Multi-Pack-Index konnte nicht geschrieben werden" + +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 "could not start pack-objects" +msgstr "Konnte 'pack-objects' nicht ausführen" + +msgid "could not finish pack-objects" +msgstr "Konnte 'pack-objects' nicht beenden" + msgid "multi-pack-index OID fanout is of the wrong size" msgstr "Multi-Pack-Index OID fanout hat die falsche Größe" @@ -18025,71 +18148,6 @@ 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 add packfile '%s'" -msgstr "Fehler beim Hinzufügen von Packdatei '%s'" - -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "Fehler beim Öffnen von pack-index '%s'" - -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "Fehler beim Lokalisieren von Objekt %d in Packdatei" - -msgid "cannot store reverse index file" -msgstr "kann Reverse-Index-Datei nicht speichern" - -#, c-format -msgid "could not parse line: %s" -msgstr "Zeile konnte nicht geparst werden: %s" - -#, c-format -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" - -#, c-format -msgid "could not open index for %s" -msgstr "konnte Index für %s nicht öffnen" - -msgid "Adding packfiles to multi-pack-index" -msgstr "Packdateien zum Multi-Pack-Index hinzufügen" - -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "unbekanntes bevorzugtes Paket: '%s'" - -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "bevorzugtes Paket %s ohne Objekte kann nicht ausgewählt werden" - -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "Pack-Datei %s zum Weglassen nicht gefunden" - -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "bevorzugtes Paket '%s' ist abgelaufen" - -msgid "no pack files to index." -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 "could not write multi-pack bitmap" -msgstr "Multi-Pack-Bitmap konnte nicht geschrieben werden" - -msgid "could not write multi-pack-index" -msgstr "Multi-Pack-Index konnte nicht geschrieben werden" - -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "Fehler beim Löschen des Multi-Pack-Index bei %s" @@ -18130,18 +18188,6 @@ msgstr "Fehler beim Laden des Pack-Index für Packdatei %s" msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "Falscher Objekt-Offset für oid[%d] = %s: %<PRIx64> != %<PRIx64>" -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 "could not start pack-objects" -msgstr "Konnte 'pack-objects' nicht ausführen" - -msgid "could not finish pack-objects" -msgstr "Konnte 'pack-objects' nicht beenden" - #, c-format msgid "unable to create lazy_dir thread: %s" msgstr "Kann lazy_dir Thread nicht erzeugen: %s" @@ -18193,6 +18239,25 @@ msgstr "" msgid "Bad %s value: '%s'" msgstr "Ungültiger %s Wert: '%s'" +msgid "failed to decode tree entry" +msgstr "Tree-Eintrag konnte nicht dekodiert werden" + +#, c-format +msgid "failed to map tree entry for %s" +msgstr "der Tree-Eintrag für %s konnte nicht zugeordnet werden" + +#, c-format +msgid "bad %s in commit" +msgstr "ungültiges %s in Commit" + +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "kann %s %s in Commit-Objekt nicht zuordnen" + +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Objekt konnte nicht von %s nach %s konvertiert werden" + #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" msgstr "" @@ -18300,6 +18365,10 @@ msgid "packed object %s (stored in %s) is corrupt" msgstr "Gepacktes Objekt %s (gespeichert in %s) ist beschädigt." #, c-format +msgid "missing mapping of %s to %s" +msgstr "fehlende Abbildung von %s auf %s" + +#, c-format msgid "unable to write file %s" msgstr "Konnte Datei %s nicht schreiben." @@ -18355,6 +18424,10 @@ msgid "cannot read object for %s" msgstr "Kann Objekt für %s nicht lesen." #, c-format +msgid "cannot map object %s to %s" +msgstr "kann Objekt %s nicht auf %s abbilden" + +#, c-format msgid "object fails fsck: %s" msgstr "fsck schlägt bei Objekt fehl: %s" @@ -18668,6 +18741,11 @@ msgstr "" "Paket kann nicht geladen werden: '%s', Deaktivierung der Paket-" "Wiederverwendung" +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "" +"kann bevorzugtes Paket nicht berechnen, Wiederverwendung von Paketen wird " +"deaktiviert" + #, c-format msgid "object '%s' not found in type bitmaps" msgstr "Objekt '%s' nicht im Typ Bitmaps gefunden" @@ -19737,6 +19815,76 @@ msgid "could not delete references: %s" msgstr "konnte Referenzen nicht entfernen: %s" #, c-format +msgid "refname is dangerous: %s" +msgstr "Referenzname ist gefährlich: %s" + +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "Versuch, Referenz '%s' mit nicht existierendem Objekt %s zu schreiben" + +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "Versuch, Nicht-Commit-Objekt %s in Branch '%s' zu schreiben" + +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"mehrere Aktualisierungen für 'HEAD' (einschließlich einer über seinen " +"Referenten '%s') sind nicht erlaubt" + +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "" +"kann Referenz '%s' nicht sperren: Referenz '%s' kann nicht aufgelöst werden" + +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "kann Referenz '%s' nicht sperren: Fehler beim Lesen der Referenz" + +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"mehrere Aktualisierungen für '%s' (einschließlich einer über die symbolische " +"Referenz '%s') sind nicht erlaubt" + +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "kann Referenz '%s' nicht sperren: Referenz existiert bereits" + +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "kann Referenz '%s' nicht sperren: Referenz fehlt, aber bei %s erwartet" + +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "kann Referenz '%s' nicht sperren: ist bei %s, aber bei %s erwartet" + +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "reftable: Transaktion vorbereiten: %s" + +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "reftable: Transaktionsfehler: %s" + +#, c-format +msgid "unable to compact stack: %s" +msgstr "kann Stapel nicht verkleinern: %s" + +#, c-format +msgid "refname %s not found" +msgstr "Referenzname %s nicht gefunden" + +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "" +"Referenzname %s ist eine symbolische Referenz, Kopieren wird nicht " +"unterstützt" + +#, c-format msgid "invalid refspec '%s'" msgstr "ungültige Refspec '%s'" @@ -19745,6 +19893,10 @@ msgid "invalid quoting in push-option value: '%s'" msgstr "Ungültiges Quoting beim \"push-option\"-Wert: '%s'" #, c-format +msgid "unknown value for object-format: %s" +msgstr "unbekannter Wert für Objektformat: %s" + +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs nicht gültig: Ist das ein Git-Repository?" @@ -20198,8 +20350,19 @@ msgid "resolve-undo records `%s` which is missing" msgstr "resolve-undo zeichnet `%s` auf, das fehlt" #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "konnte kein Commit für das Argument ancestry-path %s erhalten" +msgid "%s exists but is a symbolic ref" +msgstr "%s existiert, ist aber eine symbolische Referenz" + +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge erfordert einen der Pseudoreferenzen MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD oder REBASE_HEAD" + +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "konnte keinen Commit für das Argument --ancestry-path erhalten %s" msgid "--unpacked=<packfile> no longer supported" msgstr "--unpacked=<Pack-Datei> wird nicht länger unterstützt" @@ -20487,6 +20650,21 @@ msgid "unknown action: %d" msgstr "Unbekannte Aktion: %d" 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 "" +"Lösen Sie alle Konflikte manuell auf, markieren Sie diese mit\n" +"\"git add/rm <konfliktbehaftete_Dateien>\" und führen Sie dann\n" +"\"git rebase --continue\" aus.\n" +"Sie können auch stattdessen diesen Commit auslassen, indem\n" +"Sie \"git rebase --skip\" ausführen.\n" +"Um abzubrechen und zurück zum Zustand vor \"git rebase\" zu gelangen,\n" +"führen Sie \"git rebase --abort\" aus." + +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -20714,10 +20892,6 @@ msgid "could not update %s" msgstr "Konnte %s nicht aktualisieren." #, c-format -msgid "could not parse commit %s" -msgstr "Konnte Commit %s nicht parsen." - -#, c-format msgid "could not parse parent commit %s" msgstr "Konnte Eltern-Commit %s nicht parsen." @@ -20823,10 +20997,6 @@ msgid "invalid command '%.*s'" msgstr "ungültiger Befehl '%.*s'" #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s akzeptiert keine Argumente: '%s'" - -#, c-format msgid "missing arguments for %s" msgstr "Fehlende Argumente für %s." @@ -21292,6 +21462,10 @@ msgstr "" "Konnte Arbeitsverzeichnis mit ungültiger Konfiguration nicht einrichten." #, c-format +msgid "'%s' already specified as '%s'" +msgstr "'%s' bereits als '%s' angegeben" + +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "Erwartete Git-Repository-Version <= %d, %d gefunden" @@ -21483,6 +21657,21 @@ msgstr "Index-Eintrag ist ein Verzeichnis, aber nicht partiell (%08x)" msgid "cannot use split index with a sparse index" msgstr "kann aufgeteilten Index nicht mit einem Sparse-Index benutzen" +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "ungültiges %s-Format: Element '%s' beginnt nicht mit '('" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "ungültiges %s-Format: Element '%s' endet nicht auf ')'" + +#. TRANSLATORS: %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "ungültiges %s-Format: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #, c-format msgid "%u.%2.2u GiB" @@ -21809,29 +21998,6 @@ msgstr "unbekannter Wert '%s' für Schlüssel %s" msgid "empty trailer token in trailer '%.*s'" msgstr "leerer Anhang-Token in Anhang '%.*s'" -#, c-format -msgid "could not read input file '%s'" -msgstr "Konnte Eingabe-Datei '%s' nicht lesen" - -#, c-format -msgid "could not stat %s" -msgstr "Konnte '%s' nicht lesen" - -#, c-format -msgid "file %s is not a regular file" -msgstr "Datei '%s' ist keine reguläre Datei" - -#, c-format -msgid "file %s is not writable by user" -msgstr "Datei %s ist vom Benutzer nicht beschreibbar." - -msgid "could not open temporary file" -msgstr "konnte temporäre Datei '%s' nicht öffnen" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "konnte temporäre Datei nicht zu %s umbenennen" - msgid "full write to remote helper failed" msgstr "Vollständiges Schreiben zu Remote-Helper fehlgeschlagen." @@ -21930,8 +22096,8 @@ msgid "remote-helper doesn't support push; refspec needed" msgstr "Remote-Helper unterstützt kein Push; Refspec benötigt" #, c-format -msgid "helper %s does not support 'force'" -msgstr "Remote-Helper %s unterstützt kein 'force'." +msgid "helper %s does not support '--force'" +msgstr "Helper %s unterstützt '--force' nicht" msgid "couldn't run fast-export" msgstr "Konnte \"fast-export\" nicht ausführen." @@ -22364,6 +22530,10 @@ msgstr "ungültige Portnummer" msgid "invalid '..' path segment" msgstr "ungültiges '..' Pfadsegment" +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "Fehler: Meldung kann nicht formatiert werden: %s\n" + msgid "usage: " msgstr "Verwendung: " @@ -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-02-16 19:18+0100\n" -"PO-Revision-Date: 2024-02-16 19:19+0100\n" +"POT-Creation-Date: 2024-04-16 22:57+0000\n" +"PO-Revision-Date: 2024-04-20 17:11+0800\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" @@ -576,12 +576,12 @@ 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" "Pour éliminer les lignes '%c', rendez-les ' ' (contexte).\n" "Pour éliminer les lignes '%c', effacez-les.\n" -"Les lignes commençant par %c seront éliminées.\n" +"Les lignes commençant par %s seront éliminées.\n" msgid "" "If it does not apply cleanly, you will be given an opportunity to\n" @@ -628,6 +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" "? - print help\n" msgstr "" "j - laisser cette section non décidée et aller à la suivante non-décidée\n" @@ -638,6 +639,7 @@ 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" "? - afficher l'aide\n" msgid "No previous hunk" @@ -700,8 +702,8 @@ msgstr "" "Désactivez ce message avec \"git config advice.%s false\"" #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sastuce: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sastuce :%s%.*s%s\n" msgid "Cherry-picking is not possible because you have unmerged files." msgstr "Impossible de picorer car vous avez des fichiers non fusionnés." @@ -1801,6 +1803,9 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "'%s' n'est pas un nom de branche valide" +msgid "See `man git check-ref-format`" +msgstr "Voir `man git check-ref-format`" + #, c-format msgid "a branch named '%s' already exists" msgstr "Une branche nommée '%s' existe déjà " @@ -2000,14 +2005,8 @@ msgstr "" msgid "adding embedded git repository: %s" msgstr "dépôt git embarqué ajouté : %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 "" -"Utilisez -f si vous voulez vraiment les ajouter.\n" -"Éliminez ce message en lançant\n" -"\"git config advice.addIgnoredFile false\"" +msgid "Use -f if you really want to add them." +msgstr "Utilisez -f si vous voulez vraiment les ajouter" msgid "adding files failed" msgstr "échec de l'ajout de fichiers" @@ -2026,14 +2025,8 @@ msgstr "" msgid "Nothing specified, nothing added.\n" msgstr "Rien de spécifié, rien n'a été ajouté.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"Peut-être avez-vous voulu dire 'git add .' ?\n" -"Éliminez ce message en lançant\n" -"\"git config advice.addEmptyPathspec false\"" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "Vous vouliez sûrement utiliser 'git add .' ?" msgid "index file corrupt" msgstr "fichier d'index corrompu" @@ -2110,18 +2103,19 @@ msgid "Failed to split patches." msgstr "Échec de découpage des patchs." #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "Quand vous avez résolu ce problème, lancez \"%s --continue\"." +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "Quand vous avez résolu ce problème, lancez \"%s --continue\".\n" #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "Si vous préférez plutôt sauter ce patch, lancez \"%s --skip\"." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "Si vous préférez plutôt sauter cette rustine, lancez \"%s --skip\".\n" #, 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 "" "Pour enregistrer la rustine vide comme un commit vide, lancez \"%s --allow-" -"empty\"." +"empty\".\n" #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." @@ -2995,11 +2989,11 @@ msgstr "" 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 "" "Veuillez éditer la description de la branche\n" " %s\n" -"Les lignes commençant par '%c' seront ignorées.\n" +"Les lignes commençant par '%s' seront ignorées.\n" msgid "Generic options" msgstr "Options génériques" @@ -3202,11 +3196,12 @@ msgid "not run from a git repository - no hooks to show\n" msgstr "lancé hors d'un dépôt git - aucun crochet à montrer\n" 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) <chemin>] [(-s | --suffix) " -"<format>]\n" +"git bugreport [(-o | --output-directory) <chemin>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" " [--diagnose[=<mode>]]" msgid "" @@ -3698,6 +3693,10 @@ msgstr "" msgid "path '%s' is unmerged" msgstr "le chemin '%s' n'est pas fusionné" +#, c-format +msgid "unable to read tree (%s)" +msgstr "impossible de lire l'arbre (%s)" + msgid "you need to resolve your current index first" msgstr "vous devez d'abord résoudre votre index courant" @@ -3931,6 +3930,10 @@ msgstr "Impossible de basculer de branche vers '%s' qui n'est pas un commit" msgid "missing branch or commit argument" msgstr "argument de branche ou de commit manquant" +#, c-format +msgid "unknown conflict style '%s'" +msgstr "style de conflit inconnu '%s'" + msgid "perform a 3-way merge with the new branch" msgstr "effectuer une fusion à 3 points avec la nouvelle branche" @@ -4190,19 +4193,9 @@ msgstr "supprimer les fichiers ignorés, aussi" msgid "remove only ignored files" msgstr "supprimer seulement les fichiers ignorés" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce positionné à true et ni -i, -n ou -f fourni ; refus de " -"nettoyer" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" +msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"clean.requireForce à true par défaut et ni -i, -n ou -f fourni ; refus de " -"nettoyer" +"clean.requireForce positionné est true et -f non fourni ; refus de nettoyer" msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [<options>] [--] <dépôt> [<répertoire>]" @@ -4216,8 +4209,8 @@ msgstr "ne pas créer d'extraction" msgid "create a bare repository" msgstr "créer un dépôt nu" -msgid "create a mirror repository (implies bare)" -msgstr "créer un dépôt miroir (implique dépôt nu)" +msgid "create a mirror repository (implies --bare)" +msgstr "créer un dépôt miroir (implique --bare)" msgid "to clone from a local repository" msgstr "pour cloner depuis un dépôt local" @@ -4541,6 +4534,10 @@ msgstr "remplissage d'espace sur le côté droit" msgid "padding space between columns" msgstr "remplissage d'espace entre les colonnes" +#, c-format +msgid "%s must be non-negative" +msgstr "%s doit être non négatif" + msgid "--command must be the first argument" msgstr "--command doit être le premier argument" @@ -4854,38 +4851,38 @@ msgstr "impossible d'écrire le modèle de commit" #, 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 "" "Veuillez saisir le message de validation pour vos modifications. Les lignes\n" -"commençant par '%c' seront ignorées.\n" +"commençant par '%s' seront ignorées.\n" #, 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 "" "Veuillez saisir le message de validation pour vos modifications. Les lignes\n" -"commençant par '%c' seront ignorées, et un message vide abandonne la " +"commençant par '%s' seront ignorées, et un message vide abandonne la " "validation.\n" #, 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 "" "Veuillez saisir le message de validation pour vos modifications. Les lignes " "commençant\n" -"par '%c' seront conservées ; vous pouvez les supprimer vous-même si vous le " +"par '%s' seront conservées ; vous pouvez les supprimer vous-même si vous le " "souhaitez.\n" #, 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 "" "Veuillez saisir le message de validation pour vos modifications. Les lignes\n" -"commençant par '%c' seront conservées ; vous pouvez les supprimer vous-même\n" +"commençant par '%s' seront conservées ; vous pouvez les supprimer vous-même\n" "si vous le souhaitez. Un message vide abandonne la validation.\n" msgid "" @@ -5337,6 +5334,11 @@ msgstr "valeur" 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 "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)" + #, c-format msgid "wrong number of arguments, should be %d" msgstr "mauvais nombre d'arguments, devrait être %d" @@ -5431,6 +5433,9 @@ msgstr "" 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 "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value ne s'applique qu'à 'motif-de-valeur'" @@ -6287,6 +6292,9 @@ msgstr "afficher seulement les références qui ne contiennent pas le commit" msgid "read reference patterns from stdin" msgstr "lire les motifs de références depuis l'entrée standard" +msgid "also include HEAD ref and pseudorefs" +msgstr "inclure aussi la référence HEAD et les pseudo-réfs" + msgid "unknown arguments supplied with --stdin" msgstr "arguments inconnus fournis avec l'option --stdin" @@ -6912,10 +6920,6 @@ msgid "no threads support, ignoring %s" msgstr "pas de support des fils, ignore %s" #, c-format -msgid "unable to read tree (%s)" -msgstr "impossible de lire l'arbre (%s)" - -#, c-format msgid "unable to read tree %s" msgstr "impossible de lire l'arbre %s" @@ -7528,7 +7532,7 @@ msgstr "--separate-git-dir est incompatible avec un dépôt nu" 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" @@ -7536,6 +7540,32 @@ msgstr "" "[(=|:)<valeur>])...]\n" " [--parse] [<fichier>...]" +#, c-format +msgid "could not stat %s" +msgstr "stat impossible de %s" + +#, c-format +msgid "file %s is not a regular file" +msgstr "%s n'est pas un fichier régulier" + +#, c-format +msgid "file %s is not writable by user" +msgstr "le fichier %s n'est pas inscriptible par l'utilisateur" + +msgid "could not open temporary file" +msgstr "impossible de créer un fichier temporaire" + +#, c-format +msgid "could not read input file '%s'" +msgstr "impossible de lire le fichier d'entrée '%s'" + +msgid "could not read from stdin" +msgstr "impossible de lire depuis l'entrée standard" + +#, c-format +msgid "could not rename temporary file to %s" +msgstr "impossible de renommer un fichier temporaire en %s" + msgid "edit files in place" msgstr "éditer les fichiers sur place" @@ -7941,18 +7971,6 @@ msgstr "" msgid "could not get object info about '%s'" msgstr "impossible d'obtenir l'information d'objet pour '%s'" -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "mauvais format ls-files : l'élément '%s' ne commence pas par '('" - -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "mauvais format ls-files : l'élément '%s' ne se termine pas par ')'" - -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "mauvais format ls-files : %%%.*s" - msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<options>] [<fichier>...]" @@ -8088,18 +8106,6 @@ msgstr "afficher la réf sous-jacente en plus de l'objet pointé par elle" msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<options>] <arbre ou apparenté> [<chemin>...]" -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "mauvais format ls-tree : l'élément '%s' ne commence pas par '('" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "mauvais format ls-tree : l'élément '%s' ne se termine pas ')'" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "mauvais format ls-tree : %%%.*s" - msgid "only show trees" msgstr "afficher seulement les arbres" @@ -8290,6 +8296,10 @@ msgstr "impossible de résoudre la référence '%s'" msgid "Merging %s with %s\n" msgstr "Fusion de %s avec %s\n" +#, c-format +msgid "could not parse as tree '%s'" +msgstr "impossible d'analyser '%s' comme un arbre" + msgid "not something we can merge" msgstr "pas possible de fusionner ceci" @@ -8497,10 +8507,10 @@ msgstr "Un message vide abandonne la validation.\n" #, 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 lignes commençant par '%c' seront ignorées, et un message vide\n" +"Les lignes commençant par '%s' seront ignorées, et un message vide\n" "abandonne la validation.\n" msgid "Empty commit message." @@ -8662,9 +8672,6 @@ msgstr "impossible de lire l'objet étiqueté '%s'" msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "l'objet '%s' étiqueté comme '%s', mais est de type '%s'" -msgid "could not read from stdin" -msgstr "impossible de lire depuis l'entrée standard" - msgid "tag on stdin did not pass our strict fsck check" msgstr "l'étiquette sur stdin n'a pas passé le test strict fsck" @@ -9574,10 +9581,11 @@ msgid "refusing to run without --i-still-use-this" msgstr "refus de lancer sans --i-still-use-this" 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 <motif>] [--exclude <motif>]" +"git pack-refs [--all] [--no-prune] [--auto] [--include <motif>] [--exclude " +"<motif>]" msgid "pack everything" msgstr "empaqueter tout" @@ -9585,6 +9593,9 @@ msgstr "empaqueter tout" msgid "prune loose refs (default)" msgstr "élaguer les références perdues (défaut)" +msgid "auto-pack refs as needed" +msgstr "auto-empaqueter les réfs au besoin" + msgid "references to include" msgstr "références à inclure" @@ -10264,19 +10275,6 @@ msgstr "allow_rerere_autoupdate invalide ignoré : '%s'" msgid "could not remove '%s'" msgstr "impossible de supprimer '%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 "" -"Résolvez tous les conflits manuellement, marquez-les comme résolus avec\n" -"\"git add/rm <fichier en conflit>\", puis lancez \"git rebase --continue\".\n" -"Si vous préférez sauter ce commit, lancez \"git rebase --skip\". Pour " -"arrêter\n" -"et revenir à l'état antérieur à la commande, lancez \"git rebase --abort\"." - #, c-format msgid "" "\n" @@ -10307,13 +10305,16 @@ msgid "apply options and merge options cannot be used together" msgstr "" "Les options d'apply et celles de merge ne peuvent pas être utilisées ensemble" +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask est obsolète ; utilisez '--empty=stop' à la place." + #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." +"\"stop\"." msgstr "" "type vide non connu '%s' ; les valeurs valides sont \"drop\" (abandonner), " -"\"keep\" (garder) et \"ask\" (demander)." +"\"keep\" (garder) et \"stop\" (arrêter)." msgid "" "--rebase-merges with an empty string argument is deprecated and will stop " @@ -10495,8 +10496,8 @@ msgstr "" "Note : votre configuration `pull.rebase` peut aussi être 'preserve',\n" "qui n'est plus géré ; utilisez 'merges' à la place" -msgid "No rebase in progress?" -msgstr "Pas de rebasage en cours ?" +msgid "no rebase in progress" +msgstr "Pas de rebasage en cours" msgid "The --edit-todo action can only be used during interactive rebase." msgstr "" @@ -10693,6 +10694,9 @@ msgstr "Vous devez spécifier un répertoire" msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<options-de-journal>] [<réf>]" +msgid "git reflog list" +msgstr "git reflog list" + msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -10718,6 +10722,10 @@ msgstr "git reflog exists <référence>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "horodatage invalide '%s' fourni à '--%s'" +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s n'accepte pas d'argument : '%s'" + msgid "do not actually prune any entries" msgstr "ne pas réellement élaguer des entrées" @@ -10848,8 +10856,8 @@ msgstr "" "\t d'utiliser --mirror=fetch ou --mirror=push à la place" #, c-format -msgid "unknown mirror argument: %s" -msgstr "argument miroir inconnu : %s" +msgid "unknown --mirror argument: %s" +msgstr "argument de --mirror inconnu : %s" msgid "fetch the remote branches" msgstr "rapatrier les branches distantes" @@ -11224,6 +11232,9 @@ msgid "could not start pack-objects to repack promisor objects" msgstr "" "ne pas démarrer pack-objects pour ré-empaqueter les objects de prometteur" +msgid "failed to feed promisor objects to pack-objects" +msgstr "Échéc de la fourniture les objets du prometteur à pack-objects" + msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" "repack : attente de lignes d'Id d'objets en hexa complet seulement depuis " @@ -11831,6 +11842,13 @@ msgstr "--default exige un argument" msgid "--prefix requires an argument" msgstr "--prefix exige un argument" +msgid "no object format specified" +msgstr "aucun format d'objet spécifié" + +#, c-format +msgid "unsupported object format: %s" +msgstr "format d'objet non géré : %s" + #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "mode inconnu pour --abbrev-ref : %s" @@ -11912,8 +11930,8 @@ msgstr "préserver les validations vides initialement" msgid "allow commits with empty messages" msgstr "autoriser les validations avec des messages vides" -msgid "keep redundant, empty commits" -msgstr "garder les validations redondantes, vides" +msgid "deprecated: use --empty=keep instead" +msgstr "obsolète : utilisez --empty=keep à la place" msgid "use the 'reference' format to refer to commits" msgstr "utiliser le format 'reference' pour se référer aux commits" @@ -13283,25 +13301,25 @@ 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" "Écrivez un message pour l'étiquette :\n" " %s\n" -"Les lignes commençant par '%c' seront ignorées.\n" +"Les lignes commençant par '%s' seront ignorées.\n" #, 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" "Écrivez un message pour l'étiquette :\n" " %s\n" -"Les lignes commençant par '%c' seront gardées ; vous pouvez les retirer vous-" +"Les lignes commençant par '%s' seront gardées ; vous pouvez les retirer vous-" "même si vous le souhaitez.\n" msgid "unable to sign the tag" @@ -13388,6 +13406,9 @@ msgstr "afficher seulement les étiquettes qui ne sont pas fusionnées" msgid "print only tags of the object" msgstr "afficher seulement les étiquettes de l'objet" +msgid "could not start 'git column'" +msgstr "impossible de démarrer 'git column'" + #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "l'option '%s' est autorisée seulement en mode de liste" @@ -13643,13 +13664,12 @@ msgstr "" msgid "fsmonitor disabled" msgstr "fsmonitor désactivé" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<options>] -d <nom-référence> [<ancienne-valeur>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<options>] -d <nom-référence> [<ancien-oid>]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" msgstr "" -"git update-ref [<options>] <nom-référence> <nouvelle-valeur> [<ancienne-" -"valeur>]" +"git update-ref [<options>] <nom-référence> <nouvel-oid> [<ancien-oid>]" msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [<options>] --stdin [-z]" @@ -15070,6 +15090,10 @@ msgid "Verifying commits in commit graph" msgstr "Verification des commits dans le graphe de commits" #, c-format +msgid "could not parse commit %s" +msgstr "impossible d'analyser le commit %s" + +#, c-format msgid "%s %s is not a commit!" msgstr "%s %s n'est pas un commit !" @@ -15508,8 +15532,13 @@ msgstr "longueur d'abbrev hors plage : %d" msgid "bad zlib compression level %d" msgstr "niveau de compression zlib incorrect %d" -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar ne devrait être qu'un unique caractère ASCII" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s ne peut pas contenir de retour à la ligne" + +#, c-format +msgid "%s must have at least one character" +msgstr "%s doit contenir au moins un caractère" #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" @@ -15584,6 +15613,10 @@ msgid "failed to write new configuration file %s" msgstr "impossible d'écrire le fichier de configuration %s" #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "aucun commentaire multi-ligne permis : '%s'" + +#, c-format msgid "could not lock config file %s" msgstr "impossible de verrouiller le fichier de configuration %s" @@ -17430,6 +17463,14 @@ msgid "Unable to create '%s.lock': %s" msgstr "Impossible de créer '%s.lock' : %s" #, 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" + +#, c-format msgid "unexpected line: '%s'" msgstr "ligne inattendue : '%s'" @@ -17452,6 +17493,10 @@ 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)" + +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" "Échec de la fusion du sous-module %s (les commits ne descendent pas de la " @@ -17925,6 +17970,83 @@ msgstr "Impossible d'analyser l'objet '%s'" msgid "failed to read the cache" msgstr "impossible de lire le cache" +#, c-format +msgid "failed to add packfile '%s'" +msgstr "échec de l'ajout du fichier paquet '%s'" + +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "échec à l'ouverture du fichier paquet '%s'" + +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "échec de localisation de l'objet %d dans le fichier paquet" + +msgid "cannot store reverse index file" +msgstr "impossible de stocker le fichier d'index inversé" + +#, c-format +msgid "could not parse line: %s" +msgstr "impossible d'analyser la ligne : %s" + +#, c-format +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" + +#, c-format +msgid "could not open index for %s" +msgstr "impossible d'ouvrir l'index pour %s" + +msgid "Adding packfiles to multi-pack-index" +msgstr "Ajout de fichiers paquet à un index multi-paquet" + +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "paquet préféré inconnu : %s" + +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "impossible de sélectionner le paquet préféré %s avec aucun objet" + +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "fichier paquet à éliminer %s non trouvé" + +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "le paquet préféré '%s' est expiré" + +msgid "no pack files to index." +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 "could not write multi-pack bitmap" +msgstr "impossible d'écrire le bitmap multi-paquet" + +msgid "could not write multi-pack-index" +msgstr "échec de l'écriture de l'index de multi-paquet" + +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 "could not start pack-objects" +msgstr "impossible de démarrer le groupement d'objets" + +msgid "could not finish pack-objects" +msgstr "impossible de finir le groupement d'objets" + msgid "multi-pack-index OID fanout is of the wrong size" msgstr "l'étalement de l'OID d'index multi-paquet n'a pas la bonne taille" @@ -18010,71 +18132,6 @@ 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 add packfile '%s'" -msgstr "échec de l'ajout du fichier paquet '%s'" - -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "échec à l'ouverture du fichier paquet '%s'" - -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "échec de localisation de l'objet %d dans le fichier paquet" - -msgid "cannot store reverse index file" -msgstr "impossible de stocker le fichier d'index inversé" - -#, c-format -msgid "could not parse line: %s" -msgstr "impossible d'analyser la ligne : %s" - -#, c-format -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" - -#, c-format -msgid "could not open index for %s" -msgstr "impossible d'ouvrir l'index pour %s" - -msgid "Adding packfiles to multi-pack-index" -msgstr "Ajout de fichiers paquet à un index multi-paquet" - -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "paquet préféré inconnu : %s" - -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "impossible de sélectionner le paquet préféré %s avec aucun objet" - -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "fichier paquet à éliminer %s non trouvé" - -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "le paquet préféré '%s' est expiré" - -msgid "no pack files to index." -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 "could not write multi-pack bitmap" -msgstr "impossible d'écrire le bitmap multi-paquet" - -msgid "could not write multi-pack-index" -msgstr "échec de l'écriture de l'index de multi-paquet" - -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "échec du nettoyage de l'index de multi-paquet à %s" @@ -18115,18 +18172,6 @@ msgstr "impossible de lire le fichier paquet %s" msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "décalage d'objet incorrect pour oid[%d] = %s : %<PRIx64> != %<PRIx64>" -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 "could not start pack-objects" -msgstr "impossible de démarrer le groupement d'objets" - -msgid "could not finish pack-objects" -msgstr "impossible de finir le groupement d'objets" - #, c-format msgid "unable to create lazy_dir thread: %s" msgstr "impossible de créer le fil lazy_dir : %s" @@ -18172,6 +18217,25 @@ msgstr "Refus de réécrire des notes dans %s (hors de refs/notes/)" msgid "Bad %s value: '%s'" msgstr "Mauvaise valeur de %s : '%s'" +msgid "failed to decode tree entry" +msgstr "échec de décodage de l'entrée d'abre" + +#, c-format +msgid "failed to map tree entry for %s" +msgstr "échec de mise en correspondance de l'entrée d'arbre avec %s" + +#, c-format +msgid "bad %s in commit" +msgstr "%s mauvais dans le commit" + +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "impossible de faire correspondre %s %s dans l'objet de commit" + +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Échec de conversion de l'objet de %s vers %s" + #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" msgstr "" @@ -18276,6 +18340,10 @@ msgid "packed object %s (stored in %s) is corrupt" msgstr "l'objet empaqueté %s (stocké dans %s) est corrompu" #, c-format +msgid "missing mapping of %s to %s" +msgstr "correspondance manquante entre %s et %s" + +#, c-format msgid "unable to write file %s" msgstr "impossible d'écrire le fichier %s" @@ -18330,6 +18398,10 @@ msgid "cannot read object for %s" msgstr "impossible de lire l'objet pour %s" #, c-format +msgid "cannot map object %s to %s" +msgstr "impossible de faire correspondre l'objet %s avec %s" + +#, c-format msgid "object fails fsck: %s" msgstr "l'objet est en échec de fsck : %s" @@ -19712,6 +19784,79 @@ msgid "could not delete references: %s" msgstr "impossible de supprimer les références : %s" #, c-format +msgid "refname is dangerous: %s" +msgstr "le nom de réference est dangereux : %s" + +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "essai d'écriture de la réf '%s' avec l'objet inexistant %s" + +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "essai d'écriture de l'objet non commit %s dans la branche '%s'" + +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"mises à jour multiples pour la réf 'HEAD' (l'une d'elle étant via son " +"référence '%s') non permises" + +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "" +"impossible de verrouiller la référence '%s' : impossible de résoudre la " +"référence '%s'" + +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "" +"impossible de verrouiller la référence '%s' : erreur de lecture de la " +"référence" + +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"mises à jour multiples pour '%s' (dont un via la symref '%s') non permises" + +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "impossible de verrouiller la référence '%s' : la référence existe déjà " + +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "" +"impossible de verrouiller la réf '%s' : la référence manque mais %s était " +"attendu" + +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "impossible de verrouiller '%s' : pointe sur %s mais %s était attendu" + +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "reftable : préparation de transaction : %s" + +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "reftable : échec de transaction : %s" + +#, c-format +msgid "unable to compact stack: %s" +msgstr "impossible de compacter la pile : %s" + +#, c-format +msgid "refname %s not found" +msgstr "nom de réf '%s' non trouvé" + +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "" +"le nom de réf %s est une réf symbolique, la copie n'est pas prise en charge" + +#, c-format msgid "invalid refspec '%s'" msgstr "spécificateur de réference invalide : '%s'" @@ -19720,6 +19865,10 @@ msgid "invalid quoting in push-option value: '%s'" msgstr "citation invalide dans la valeur push-option : '%s'" #, c-format +msgid "unknown value for object-format: %s" +msgstr "valeur inconnue pour object-format : %s" + +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs n'est pas valide : est-ce bien un dépôt git ?" @@ -20175,9 +20324,19 @@ msgid "resolve-undo records `%s` which is missing" msgstr "resolve-undo enregistre `%s` qui manque" #, c-format -msgid "could not get commit for ancestry-path argument %s" +msgid "%s exists but is a symbolic ref" +msgstr "%s existe mais c'est une référence symbolique" + +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" msgstr "" -"impossible de récupérer le commit pour l'argument de chemin d'ascendance %s" +"--merge nécessite une pseudo-réf MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD " +"ou REBASE_HEAD" + +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "impossible de récupérer le commit pour l'argument --ancestry-path %s" msgid "--unpacked=<packfile> no longer supported" msgstr "--unpacked=<fichier-paquet> n'est plus géré" @@ -20467,6 +20626,19 @@ msgid "unknown action: %d" msgstr "action inconnue : %d" 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 "" +"Résolvez tous les conflits manuellement, marquez-les comme résolus avec\n" +"\"git add/rm <fichier en conflit>\", puis lancez \"git rebase --continue\".\n" +"Si vous préférez sauter ce commit, lancez \"git rebase --skip\". Pour " +"arrêter\n" +"et revenir à l'état antérieur à la commande, lancez \"git rebase --abort\"." + +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -20690,10 +20862,6 @@ msgid "could not update %s" msgstr "impossible de mettre à jour %s" #, c-format -msgid "could not parse commit %s" -msgstr "impossible d'analyser le commit %s" - -#, c-format msgid "could not parse parent commit %s" msgstr "impossible d'analyser le commit parent %s" @@ -20799,10 +20967,6 @@ msgid "invalid command '%.*s'" msgstr "commande '%.*s' invalide" #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s n'accepte pas d'argument : '%s'" - -#, c-format msgid "missing arguments for %s" msgstr "argument manquant pour %s" @@ -21261,6 +21425,10 @@ msgstr "" "configuration invalide" #, c-format +msgid "'%s' already specified as '%s'" +msgstr "'%s' déjà spécifié comme '%s'" + +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "Version attendue du dépôt git <= %d, %d trouvée" @@ -21455,6 +21623,21 @@ msgstr "l'entrée d'index est un répertoire, mais pas clairsemé (%08x)" msgid "cannot use split index with a sparse index" msgstr "impossible d'utiliser l'index scindé avec un index clairsemé" +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "mauvais format %s : l'élément '%s' ne commence pas par '('" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "mauvais format '%s' : l'élément '%s' ne se termine pas ')'" + +#. TRANSLATORS: %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "mauvais format %s : %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #, c-format msgid "%u.%2.2u GiB" @@ -21785,29 +21968,6 @@ msgstr "valeur inconnue '%s' pour la clé '%s'" msgid "empty trailer token in trailer '%.*s'" msgstr "symbole vide dans la ligne de fin '%.*s'" -#, c-format -msgid "could not read input file '%s'" -msgstr "impossible de lire le fichier d'entrée '%s'" - -#, c-format -msgid "could not stat %s" -msgstr "stat impossible de %s" - -#, c-format -msgid "file %s is not a regular file" -msgstr "%s n'est pas un fichier régulier" - -#, c-format -msgid "file %s is not writable by user" -msgstr "le fichier %s n'est pas inscriptible par l'utilisateur" - -msgid "could not open temporary file" -msgstr "impossible de créer un fichier temporaire" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "impossible de renommer un fichier temporaire en %s" - msgid "full write to remote helper failed" msgstr "échec de l'écriture totale sur l'assistant distant" @@ -21908,8 +22068,8 @@ msgstr "" "nécessaire" #, c-format -msgid "helper %s does not support 'force'" -msgstr "l'assistant %s ne gère pas 'force'" +msgid "helper %s does not support '--force'" +msgstr "l'assistant %s ne gère pas '--force'" msgid "couldn't run fast-export" msgstr "impossible de lancer fast-export" @@ -22332,6 +22492,10 @@ msgstr "numéro de port invalide" msgid "invalid '..' path segment" msgstr "segment de chemin '..' invalide" +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "erreur : impossible de formater le message : %s\n" + msgid "usage: " msgstr "usage : " @@ -23302,6 +23466,49 @@ 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 "" +#~ "Use -f if you really want to add them.\n" +#~ "Turn this message off by running\n" +#~ "\"git config advice.addIgnoredFile false\"" +#~ msgstr "" +#~ "Utilisez -f si vous voulez vraiment les ajouter.\n" +#~ "Éliminez ce message en lançant\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 "" +#~ "Peut-être avez-vous voulu dire 'git add .' ?\n" +#~ "Éliminez ce message en lançant\n" +#~ "\"git config advice.addEmptyPathspec false\"" + +#~ msgid "" +#~ "clean.requireForce defaults to true and neither -i, -n, nor -f given; " +#~ "refusing to clean" +#~ msgstr "" +#~ "clean.requireForce à true par défaut et ni -i, -n ou -f fourni ; refus de " +#~ "nettoyer" + +#, c-format +#~ msgid "bad ls-files format: element '%s' does not start with '('" +#~ msgstr "mauvais format ls-files : l'élément '%s' ne commence pas par '('" + +#, c-format +#~ msgid "bad ls-files format: element '%s' does not end in ')'" +#~ msgstr "mauvais format ls-files : l'élément '%s' ne se termine pas par ')'" + +#, c-format +#~ msgid "bad ls-files format: %%%.*s" +#~ msgstr "mauvais format ls-files : %%%.*s" + +#~ msgid "keep redundant, empty commits" +#~ msgstr "garder les validations redondantes, vides" + +#~ 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" @@ -23350,10 +23557,6 @@ msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " #~ msgid "%s is incompatible with %s" #~ msgstr "%s est incompatible avec %s" -#, c-format -#~ msgid "could not remove reference %s" -#~ msgstr "impossible de supprimer la référence %s" - #~ msgid "unhandled options" #~ msgstr "options non gérées" @@ -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-02-16 09:36+0700\n" -"PO-Revision-Date: 2024-02-16 10:45+0700\n" +"POT-Creation-Date: 2024-04-25 18:57+0000\n" +"PO-Revision-Date: 2024-04-26 15:33+0700\n" "Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n" "Language-Team: Indonesian\n" "Language: id\n" @@ -591,12 +591,12 @@ 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" "Untuk menghapus baris '%c', buatlah menjadi baris ' ' (konteks).\n" "Untuk menghapus baris '%c', hapuslahnya.\n" -"Baris yang diawali dengan %c akan dihapus.\n" +"Baris yang diawali dengan %s akan dihapus.\n" #: add-patch.c msgid "" @@ -651,17 +651,19 @@ 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" "? - print help\n" msgstr "" -"j - biarkan bingkah ini ragu, lihat bingkah ragu berikutnya\n" -"J - biarkan bingkah ini ragu, lihat bingkah berikutnya\n" -"k - biarkan bingkah ini ragu, lihat bingkah ragu sebelumnya\n" -"K - biarkan bingkah ini ragu, lihat bingkah sebelumnya\n" +"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" "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" -"? - cetak bantuan\n" +"p - lihat bingkah saat ini\n" +"? - lihat bantuan\n" #: add-patch.c msgid "No previous hunk" @@ -740,8 +742,8 @@ msgstr "" #: advice.c #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%shint: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%spetunjuk:%s%.*s%s\n" #: advice.c msgid "Cherry-picking is not possible because you have unmerged files." @@ -1359,11 +1361,6 @@ msgstr[1] "Menerapkan tambalan %%s dengan %d penolakan..." #: apply.c #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "memotong nama berkas .rej ke %.*s.rej" - -#: apply.c -#, c-format msgid "cannot open %s" msgstr "tidak dapat membuka %s" @@ -1904,6 +1901,11 @@ msgstr "sebuah revisi %s diperlukan" msgid "could not create file '%s'" msgstr "tidak dapat membuat berkas '%s'" +#: bisect.c builtin/notes.c +#, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "tidak dapat memulai 'show' untuk objek '%s'" + #: bisect.c builtin/merge.c #, c-format msgid "could not read file '%s'" @@ -1954,8 +1956,8 @@ msgstr "" "--reverse dan --first-parent bersama-sama butuh komit terbaru yang disebutkan" #: blame.c builtin/commit.c builtin/log.c builtin/merge.c -#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c -#: sequencer.c submodule.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 "persiapan jalan revisi gagal" @@ -2080,6 +2082,10 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "'%s' bukan nama cabang valid" +#: branch.c builtin/branch.c +msgid "See `man git check-ref-format`" +msgstr "Lihat `man git check-ref-format`" + #: branch.c #, c-format msgid "a branch named '%s' already exists" @@ -2319,14 +2325,8 @@ msgid "adding embedded git repository: %s" msgstr "menambahkan repositori git tertanam: %s" #: builtin/add.c -msgid "" -"Use -f if you really want to add them.\n" -"Turn this message off by running\n" -"\"git config advice.addIgnoredFile false\"" -msgstr "" -"Gunakan -f jika Anda benar-benar ingin menambahkannya.\n" -"Matikan pesan ini dengan menjalankan\n" -"\"git config advice.addIgnoredFile false\"" +msgid "Use -f if you really want to add them." +msgstr "Gunakan -f jika Anda benar-benar ingin menambahkannya." #: builtin/add.c msgid "adding files failed" @@ -2349,14 +2349,8 @@ msgid "Nothing specified, nothing added.\n" msgstr "Tidak ada yang disebutkan, tidak ada yang ditambahkan.\n" #: builtin/add.c -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"Mungkin Anda ingin bilang 'git add .'?\n" -"Matikan pesan ini dengan menjalankan\n" -"\"git config advice.addEmptyPathspec false\"" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "Mungkin Anda ingin bilang '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 @@ -2376,8 +2370,8 @@ msgid "bad action '%s' for '%s'" msgstr "tindakan jelek '%s' untuk '%s'" #: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c -#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c -#: parallel-checkout.c sequencer.c setup.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 "nilai tidak valid untuk '%s': '%s'" @@ -2461,29 +2455,30 @@ msgstr "Gagal memecah tambalan." #: builtin/am.c #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "Saat Anda sudah menyelesaikan masalah ini, jalankan \"%s --continue\"." +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "" +"Saat Anda sudah menyelesaikan masalah ini, jalankan \"%s --continue\".\n" #: builtin/am.c #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" msgstr "" -"Jika Anda lebih suka melewati tambalan ini, jalankan \"%s --skip\" sebagai " -"gantinya." +"Jika Anda lebih suka melewati tambalan ini, jalankan \"%s --skip\" saja.\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 "" "Untuk merekam tambalan kosong sebagai komit kosong, jalankan \"%s --allow-" -"empty\"." +"empty\".\n" #: builtin/am.c #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." msgstr "" "Untuk mengembalikan cabang yang asli dan berhenti menambal, jalankan \"%s --" -"abort\"" +"abort\"." #: builtin/am.c msgid "Patch sent with format=flowed; space at the end of lines might be lost." @@ -3553,11 +3548,11 @@ msgstr "cabang disalin, tapi pembaruan berkas konfigurasi gagal" 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 "" "Mohon sunting deskripsi untuk cabang\n" " %s\n" -"Baris yang diawali dengan '%c' akan dicopot.\n" +"Baris yang diawali dengan '%s' akan dicopot.\n" #: builtin/branch.c msgid "Generic options" @@ -3820,11 +3815,12 @@ msgstr "" #: 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) <berkas>] [(-s |-- suffix) " -"<format>]\n" +"git bugreport [(-o | --output-directory) <jalur>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" " [--diagnose[=<mode>]]" #: builtin/bugreport.c @@ -4438,6 +4434,12 @@ msgstr "'%s', '%s', atau '%s' tidak dapat digunakan ketika men-checkout pohon" msgid "path '%s' is unmerged" msgstr "jalur '%s' tak tergabung" +#: 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 "tidak dapat membaca pohon (%s)" + #: builtin/checkout.c msgid "you need to resolve your current index first" msgstr "Anda perlu selesaikan dulu indeks Anda saat ini" @@ -4708,6 +4710,11 @@ msgid "missing branch or commit argument" msgstr "kehilangan argumen cabang atau komit" #: builtin/checkout.c +#, c-format +msgid "unknown conflict style '%s'" +msgstr "gaya konflik '%s' tidak dikenal" + +#: builtin/checkout.c msgid "perform a 3-way merge with the new branch" msgstr "lakukan penggabungan 3 arah dengan cabang baru" @@ -5030,20 +5037,8 @@ msgid "remove only ignored files" msgstr "hanya hapus berkas terabaikan" #: builtin/clean.c -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce disetel ke true dan baik -i, -n, atau -f tidak diberikan; " -"menolak membersihkan" - -#: builtin/clean.c -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" -msgstr "" -"clean.requireForce asal ke true dan baik -i, -n, atau -f tidak diberikan; " -"menolak membersihkan" +msgid "clean.requireForce is true and -f not given: refusing to clean" +msgstr "clean.requireForce 'true' dan -f tidak diberikan: menolak membersihkan" #: builtin/clone.c msgid "git clone [<options>] [--] <repo> [<dir>]" @@ -5062,8 +5057,8 @@ msgid "create a bare repository" msgstr "buat repositori bare" #: builtin/clone.c -msgid "create a mirror repository (implies bare)" -msgstr "buat repositori cermin (implikasikan bare)" +msgid "create a mirror repository (implies --bare)" +msgstr "buat repositori cermin (mengimplikasikan --bare)" #: builtin/clone.c msgid "to clone from a local repository" @@ -5470,6 +5465,11 @@ msgid "padding space between columns" msgstr "bantalan spasi di antara kolom" #: builtin/column.c +#, c-format +msgid "%s must be non-negative" +msgstr "%s harus non-negatif" + +#: builtin/column.c msgid "--command must be the first argument" msgstr "--command harus menjadi argumen pertama" @@ -5810,7 +5810,7 @@ msgstr "" "tidak dapat memilih karakter komentar yang tidak terpakai\n" "dalam pesan komit saat ini" -#: builtin/commit.c builtin/merge-tree.c +#: builtin/commit.c #, c-format msgid "could not lookup commit '%s'" msgstr "tidak dapat mencari komit '%s'" @@ -5855,38 +5855,38 @@ msgstr "tidak dapat menulis templat komit" #, 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 "" "Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n" -"dengan '%c' akan diabaikan.\n" +"dengan '%s' akan diabaikan.\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 "" "Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n" -"dengan '%c' akan diabaikan, dan pesan kosong batalkan komit.\n" +"dengan '%s' akan diabaikan, dan pesan kosong batalkan komit.\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 "" "Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n" -"dengan '%c' akan tetap; Anda dapat menghapusnya jika Anda mau.\n" +"dengan '%s' akan tetap; Anda dapat menghapusnya jika Anda mau.\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 "" "Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n" -"dengan '%c' akan tetap; Anda dapat menghapusnya jika Anda mau.\n" +"dengan '%s' akan tetap; Anda dapat menghapusnya jika Anda mau.\n" "Pesan kosong batalkan komit.\n" #: builtin/commit.c @@ -6118,7 +6118,7 @@ msgstr "tangal" msgid "override date for commit" msgstr "timpa tanggal komit" -#: builtin/commit.c builtin/merge-tree.c parse-options.h ref-filter.h +#: builtin/commit.c parse-options.h ref-filter.h msgid "commit" msgstr "komit" @@ -6449,6 +6449,11 @@ msgid "with --get, use default value when missing entry" msgstr "dengan --get, gunakan nilai asali ketika kehilangan entri" #: builtin/config.c +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"untai komentar yang dapat dibaca manusia (# akan ditambahkan bila diperlukan" + +#: builtin/config.c #, c-format msgid "wrong number of arguments, should be %d" msgstr "jumlah argumen salah, seharusnya %d" @@ -6564,6 +6569,12 @@ 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/config.c msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value hanya diterapkan dengan 'pola nilai'" @@ -7631,6 +7642,10 @@ msgid "read reference patterns from stdin" msgstr "baca pola referensi dari masukan standar" #: builtin/for-each-ref.c +msgid "also include HEAD ref and pseudorefs" +msgstr "juga termasuk referensi HEAD dan referensi semu" + +#: builtin/for-each-ref.c msgid "unknown arguments supplied with --stdin" msgstr "argumen tidak dikenal diberikan dengan --stdin" @@ -8413,11 +8428,6 @@ msgstr "tidak ada dukungan utas, abaikan %s" #: builtin/grep.c #, c-format -msgid "unable to read tree (%s)" -msgstr "tidak dapat membaca pohon (%s)" - -#: builtin/grep.c -#, c-format msgid "unable to read tree %s" msgstr "tidak dapat membaca pohon %s" @@ -9189,7 +9199,7 @@ msgstr "--separate-git-dir tidak kompatibel dengan repositori bare" #: 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" @@ -9197,6 +9207,39 @@ msgstr "" "[(=|:)<nilai>])...]\n" " [--parse] [<berkas>...]" +#: builtin/interpret-trailers.c wrapper.c +#, c-format +msgid "could not stat %s" +msgstr "tidak dapat membaca %s" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not a regular file" +msgstr "berkas %s bukan sebuah berkas reguler" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not writable by user" +msgstr "berkas %s tidak dapat ditulis oleh pengguna" + +#: builtin/interpret-trailers.c +msgid "could not open temporary file" +msgstr "tidak dapat membuka berkas sementara" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not read input file '%s'" +msgstr "tidak dapat membaca berkas masukan '%s'" + +#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c +msgid "could not read from stdin" +msgstr "tidak dapat membaca dari masukan standar" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not rename temporary file to %s" +msgstr "tidak dapat menamai ulang berkas sementara ke %s" + #: builtin/interpret-trailers.c msgid "edit files in place" msgstr "sunting berkas di tempat" @@ -9705,21 +9748,6 @@ msgid "could not get object info about '%s'" msgstr "tidak dapat mendapatkan info objek tentang '%s'" #: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "format ls-files jelek: elemen '%s' tidak dimulai dengan '('" - -#: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "format ls-files jelek: elemen '%s' tidak diakhiri dengan ')'" - -#: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "format ls-files jelek: %%%.*s" - -#: builtin/ls-files.c msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<opsi>] [<berkas>...]" @@ -9812,7 +9840,7 @@ msgid "if any <file> is not in the index, treat this as an error" msgstr "" "jika <berkas> apapun tidak berada di indeks, perlakukan sebagai kesalahan" -#: builtin/ls-files.c +#: builtin/ls-files.c builtin/merge-tree.c msgid "tree-ish" msgstr "mirip-pohon" @@ -9892,21 +9920,6 @@ msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<opsi>] <mirip-pohon> [<jalur>...]" #: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "format ls-tree jelek: elemen '%s' tidak dimulai dengan '('" - -#: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "format ls-tree jelek: elemen '%s' tidak diakhiri dengan ')'" - -#: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "format ls-tree jelek: %%%.*s" - -#: builtin/ls-tree.c msgid "only show trees" msgstr "hanya perlihatkan pohon" @@ -10150,6 +10163,11 @@ msgstr "tidak dapat menguraikan referensi '%s'" msgid "Merging %s with %s\n" msgstr "Menggabungkan %s dengan %s\n" +#: builtin/merge-tree.c +#, c-format +msgid "could not parse as tree '%s'" +msgstr "tidak dapat mengurai '%s' sebagai pohon" + #: builtin/merge-tree.c builtin/merge.c msgid "not something we can merge" msgstr "bukan sesuatu yang kami bisa gabungkan" @@ -10414,10 +10432,10 @@ msgstr "Pesan kosong membatalkan komit.\n" #: 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 "" -"Baris yang diawali dengan '%c' akan diabaikan, dan pesan kosong batalkan\n" +"Baris yang diawali dengan '%s' akan diabaikan, dan pesan kosong batalkan\n" "komit.\n" #: builtin/merge.c @@ -10615,10 +10633,6 @@ msgstr "tidak dapat membaca objek tertag '%s'" msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "objek '%s' ditag sebagai '%s', tetapi bertipe '%s'" -#: builtin/mktag.c imap-send.c trailer.c -msgid "could not read from stdin" -msgstr "tidak dapat membaca dari masukan standar" - #: builtin/mktag.c msgid "tag on stdin did not pass our strict fsck check" msgstr "tag pada masukan standar tidak lolos pemeriksaan fsck ketat kami" @@ -10956,11 +10970,6 @@ msgid "Write/edit the notes for the following object:" msgstr "Tulis/sunting catatan untuk objek berikut:" #: builtin/notes.c -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "tidak dapat memulai 'show' untuk objek '%s'" - -#: builtin/notes.c msgid "could not read 'show' output" msgstr "tidak dapat membaca keluaran 'show'" @@ -11754,10 +11763,11 @@ msgstr "menolak menjalankan tanpa --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 <pola>] [--exclude <pola>]" +"git pack-refs [--all] [--no-prune] [--auto] [--include <pola>][--exclude " +"<pola>]" #: builtin/pack-refs.c msgid "pack everything" @@ -11768,6 +11778,10 @@ msgid "prune loose refs (default)" msgstr "pangkas referensi longgar (asali)" #: builtin/pack-refs.c +msgid "auto-pack refs as needed" +msgstr "otomatis pak referensi jika dibutuhkan" + +#: builtin/pack-refs.c msgid "references to include" msgstr "referensi untuk ditambahkan" @@ -12565,21 +12579,6 @@ msgid "could not remove '%s'" msgstr "tidak dapat menghapus '%s'" #: builtin/rebase.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 "" -"Selesaikan semua konflik secara manual, tandai sebagai terselesaikan\n" -"dengan \"git add/rm <berkas terkonflik>\", lalu jalankan\n" -"\"git rebase --continue\".\n" -"Anda juga bisa melewatkan komit ini: jalankan \"git rebase --skip\".\n" -"Untuk membatalkan dan kembali ke kondisi sebelum \"git rebase\",jalankan " -"\"git rebase --abort\"." - -#: builtin/rebase.c #, c-format msgid "" "\n" @@ -12613,13 +12612,17 @@ msgid "apply options and merge options cannot be used together" msgstr "opsi apply dan opsi merge tidak dapat digunakan bersamaan" #: builtin/rebase.c +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask usang; gunakan '--empty=stop' sebagai gantinya." + +#: builtin/rebase.c #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." +"\"stop\"." msgstr "" "tipe kosong tak dikenali '%s'; nilai yang valid adalah \"drop\", \"keep\", " -"dan \"ask\"." +"dan \"stop\"." #: builtin/rebase.c msgid "" @@ -12761,7 +12764,7 @@ msgstr "biarkan pengguna menyunting daftar komit untuk didasarkan ulang" msgid "(REMOVED) was: try to recreate merges instead of ignoring them" msgstr "(USANG) yaitu: coba buat ulang penggabungan daripada abaikannya" -#: builtin/rebase.c +#: builtin/rebase.c builtin/revert.c msgid "how to handle commits that become empty" msgstr "bagaimana cara menangani komit yang menjadi kosong" @@ -12843,8 +12846,8 @@ msgstr "" "yang tidak lagi didukung; gunakan 'merges' sebagai gantinya" #: builtin/rebase.c -msgid "No rebase in progress?" -msgstr "Tidak ada pendasaran ulang yang sedang berjalan?" +msgid "no rebase in progress" +msgstr "tidak ada pendasaran ulang yang sedang berjalan" #: builtin/rebase.c msgid "The --edit-todo action can only be used during interactive rebase." @@ -13073,6 +13076,10 @@ msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git remote [show] [<opsi log>] [<referensi>]" #: 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" @@ -13101,6 +13108,11 @@ msgstr "git reflog exists <referensi>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "stempel waktu tidak valid '%s' diberikan ke '--%s'" +#: builtin/reflog.c sequencer.c +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s tidak menerima argumen: '%s'" + #: builtin/reflog.c msgid "do not actually prune any entries" msgstr "jangan benar-benar pangkas entri apapun" @@ -13263,8 +13275,8 @@ msgstr "" #: builtin/remote.c #, c-format -msgid "unknown mirror argument: %s" -msgstr "argumen mirror tidak dikenal: %s" +msgid "unknown --mirror argument: %s" +msgstr "argumen --mirror tidak dikenal: %s" #: builtin/remote.c msgid "fetch the remote branches" @@ -13721,6 +13733,10 @@ msgid "could not start pack-objects to repack promisor objects" msgstr "tidak dapat memulai pack-objects untuk mengepak ulang objek pejanji" #: builtin/repack.c +msgid "failed to feed promisor objects to pack-objects" +msgstr "gagal mengumpan objek penjanji ke pack-objects" + +#: builtin/repack.c msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "repack: Mengharapkan baris ID objek hex penuh hanya dari pack-objects." @@ -14481,6 +14497,15 @@ msgid "--prefix requires an argument" msgstr "--prefix butuh sebuah argumen" #: builtin/rev-parse.c +msgid "no object format specified" +msgstr "tidak ada format objek yang disebutkan" + +#: builtin/rev-parse.c +#, c-format +msgid "unsupported object format: %s" +msgstr "format objek tidak didukung: '%s'" + +#: builtin/rev-parse.c #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "mode untuk --abbrev-ref tidak dikenal: %s" @@ -14585,8 +14610,8 @@ msgid "allow commits with empty messages" msgstr "perbolehkan komit dengan pesan kosong" #: builtin/revert.c -msgid "keep redundant, empty commits" -msgstr "simpan komit kosong mubazir" +msgid "deprecated: use --empty=keep instead" +msgstr "usang: gunakan --empty=keep sebagai gantinya" #: builtin/revert.c msgid "use the 'reference' format to refer to commits" @@ -15047,7 +15072,7 @@ msgstr "inisialisasi checkout tipis dalam mode kerucut" msgid "toggle the use of a sparse index" msgstr "gunakan indeks tipis" -#: builtin/sparse-checkout.c commit-graph.c midx.c sequencer.c +#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c #, c-format msgid "unable to create leading directories of %s" msgstr "tidak dapat membuat direktori utama dari %s" @@ -16246,12 +16271,12 @@ 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" "Tulis pesan untuk tag:\n" " %s\n" -"Baris yang diawali dengan '%c' akan diabaikan.\n" +"Baris yang diawali dengan '%s' akan diabaikan.\n" #: builtin/tag.c #, c-format @@ -16259,13 +16284,13 @@ 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" "Tulis pesan untuk tag:\n" " %s\n" -"Baris yang diawali dengan '%c' akan disimpan; Anda dapat menghapusnya bila " +"Baris yang diawali dengan '%s' akan disimpan; Anda dapat menghapusnya bila " "Anda mau.\n" #: builtin/tag.c @@ -16376,6 +16401,10 @@ msgid "print only tags of the object" msgstr "hanya cetak tag dari objek" #: builtin/tag.c +msgid "could not start 'git column'" +msgstr "tidak dapat memulai 'git column'" + +#: builtin/tag.c #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "opsi '%s' hanya diperbolehkan dalam mode daftar" @@ -16687,13 +16716,12 @@ msgid "fsmonitor disabled" msgstr "fsmonitor dinonaktifkan" #: builtin/update-ref.c -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<opsi>] -d <nama referensi> [<nilai lama>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<opsi>] -d <nama referensi> [<oid lama>]" #: builtin/update-ref.c -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "" -"git update-ref [<opsi>] <nama referensi> <nilai baru> [<nilai lama>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "git update-ref [<options>] <nama referensi> <oid baru> [<oid lama>]" #: builtin/update-ref.c msgid "git update-ref [<options>] --stdin [-z]" @@ -18428,6 +18456,11 @@ msgstr "" msgid "Verifying commits in commit graph" msgstr "Memverifikasi komit di dalam grafik komit" +#: commit-reach.c sequencer.c +#, c-format +msgid "could not parse commit %s" +msgstr "tidak dapat menguraikan komit %s" + #: commit.c #, c-format msgid "%s %s is not a commit!" @@ -18961,8 +18994,14 @@ msgid "bad zlib compression level %d" msgstr "level kompresi zlib jelek %d" #: config.c -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar seharusnya hanya satu karakter ASCII" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s tidak dapat berisi baris baru" + +#: config.c +#, c-format +msgid "%s must have at least one character" +msgstr "%s harus ada sedikitnya satu karakter" #: config.c #, c-format @@ -19052,6 +19091,11 @@ msgstr "gagal menulis berkas konfigurasi baru %s" #: config.c #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "komentar multi baris tidak diperbolehkan: '%s'" + +#: config.c +#, c-format msgid "could not lock config file %s" msgstr "tidak dapat mengunci berkas konfigurasi %s" @@ -21280,6 +21324,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "Tidak dapat membuat '%s.lock': %s" +#: loose.c +#, c-format +msgid "could not write loose object index %s" +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" + #: ls-refs.c #, c-format msgid "unexpected line: '%s'" @@ -21293,6 +21347,11 @@ msgstr "bilasan diharapkan setelah argumen ls-refs" msgid "quoted CRLF detected" msgstr "CRLF terkutip terdeteksi" +#: mem-pool.c strbuf.c wrapper.c +#, c-format +msgid "unable to format message: %s" +msgstr "tidak dapat memformat pesan: %s" + #: merge-ort.c merge-recursive.c #, c-format msgid "Failed to merge submodule %s (not checked out)" @@ -21310,6 +21369,11 @@ msgstr "Gagal menggabungkan submodul %s (komit tidak ada)" #: merge-ort.c merge-recursive.c #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "Gagal menggabungkan submodul %s (repositori rusak)" + +#: merge-ort.c merge-recursive.c +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" "Gagal menggabungkan submodul %s (komit tidak mengikuti dasar penggabungan)" @@ -21868,6 +21932,104 @@ msgstr "Tidak dapat menguraikan objek '%s'" msgid "failed to read the cache" msgstr "gagal membaca tembolok" +#: midx-write.c +#, c-format +msgid "failed to add packfile '%s'" +msgstr "gagal menambah berkas pak '%s'" + +#: midx-write.c +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "gagal membuka indeks pak '%s'" + +#: midx-write.c +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "gagal melokasi objek %d di dalam berkas pak" + +#: midx-write.c +msgid "cannot store reverse index file" +msgstr "tidak dapat menyimpan berkas indeks balik" + +#: midx-write.c +#, c-format +msgid "could not parse line: %s" +msgstr "tidak dapat menguraikan baris: %s" + +#: midx-write.c +#, c-format +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" + +#: midx-write.c +#, c-format +msgid "could not open index for %s" +msgstr "tidak dapat membuka indeks untuk %s" + +#: midx-write.c +msgid "Adding packfiles to multi-pack-index" +msgstr "Menambahkan berkas pak ke indeks multipak" + +#: midx-write.c +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "pak yang disukai tidak dikenal: '%s'" + +#: midx-write.c +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "tidak dapat memilih pak yang disukai %s tanpa objek" + +#: midx-write.c +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "tidak melihat berkas pak %s untuk dijeblokkan" + +#: midx-write.c +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "pak yang disukai '%s' kadaluarsa" + +#: midx-write.c +msgid "no pack files to index." +msgstr "tidak ada berkas pak untuk diindeks." + +#: midx-write.c +msgid "refusing to write multi-pack .bitmap without any objects" +msgstr "menolak menulis .bitmap multipak tanpa objek apapun" + +#: midx-write.c +msgid "could not write multi-pack bitmap" +msgstr "tidak dapat menulis bitmap multipak" + +#: midx-write.c +msgid "could not write multi-pack-index" +msgstr "gagal menulis indeks multipak" + +#: midx-write.c +msgid "Counting referenced objects" +msgstr "Menghitung objek tereferensi" + +#: midx-write.c +msgid "Finding and deleting unreferenced packfiles" +msgstr "Mencari dan menghapus berkas pak tak tereferensi" + +#: midx-write.c +msgid "could not start pack-objects" +msgstr "tidak dapat memulai pack-objects" + +#: midx-write.c +msgid "could not finish pack-objects" +msgstr "tidak dapat menyelesaikan pack-objects" + #: midx.c msgid "multi-pack-index OID fanout is of the wrong size" msgstr "OID kipas-keluar indeks multipak salah ukuran" @@ -21960,88 +22122,6 @@ msgstr "offset indeks multipak besar di luar jangkauan" #: midx.c #, c-format -msgid "failed to add packfile '%s'" -msgstr "gagal menambah berkas pak '%s'" - -#: midx.c -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "gagal membuka indeks pak '%s'" - -#: midx.c -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "gagal melokasi objek %d di dalam berkas pak" - -#: midx.c -msgid "cannot store reverse index file" -msgstr "tidak dapat menyimpan berkas indeks balik" - -#: midx.c -#, c-format -msgid "could not parse line: %s" -msgstr "tidak dapat menguraikan baris: %s" - -#: midx.c -#, c-format -msgid "malformed line: %s" -msgstr "baris jelek '%s'." - -#: midx.c -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "abaikan indeks multipak yang sudah ada; checksum tidak cocok" - -#: midx.c -msgid "could not load pack" -msgstr "tidak dapat memuat pak" - -#: midx.c -#, c-format -msgid "could not open index for %s" -msgstr "tidak dapat membuka indeks untuk %s" - -#: midx.c -msgid "Adding packfiles to multi-pack-index" -msgstr "Menambahkan berkas pak ke indeks multipak" - -#: midx.c -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "pak yang disukai tidak dikenal: '%s'" - -#: midx.c -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "tidak dapat memilih pak yang disukai %s tanpa objek" - -#: midx.c -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "tidak melihat berkas pak %s untuk dijeblokkan" - -#: midx.c -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "pak yang disukai '%s' kadaluarsa" - -#: midx.c -msgid "no pack files to index." -msgstr "tidak ada berkas pak untuk diindeks." - -#: midx.c -msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "menolak menulis .bitmap multipak tanpa objek apapun" - -#: midx.c -msgid "could not write multi-pack bitmap" -msgstr "tidak dapat menulis bitmap multipak" - -#: midx.c -msgid "could not write multi-pack-index" -msgstr "gagal menulis indeks multipak" - -#: midx.c -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "gagal membersihkan indeks multipak pada %s" @@ -22093,22 +22173,6 @@ msgstr "gagal memuat indeks pak untuk berkas pak %s" msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "offset objek salah untuk oid[%d] = %s: %<PRIx64> != %<PRIx64>" -#: midx.c -msgid "Counting referenced objects" -msgstr "Menghitung objek tereferensi" - -#: midx.c -msgid "Finding and deleting unreferenced packfiles" -msgstr "Mencari dan menghapus berkas pak tak tereferensi" - -#: midx.c -msgid "could not start pack-objects" -msgstr "tidak dapat memulai pack-objects" - -#: midx.c -msgid "could not finish pack-objects" -msgstr "tidak dapat menyelesaikan pack-objects" - #: name-hash.c #, c-format msgid "unable to create lazy_dir thread: %s" @@ -22164,6 +22228,30 @@ msgstr "Menolak menulis ulang catatan di %s (di luar refs/notes/)" msgid "Bad %s value: '%s'" msgstr "Nilai %s jelek: '%s'" +#: object-file-convert.c +msgid "failed to decode tree entry" +msgstr "gagal mendekode entri pohon" + +#: object-file-convert.c +#, c-format +msgid "failed to map tree entry for %s" +msgstr "gagal memetakan entri pohon untuk %s" + +#: object-file-convert.c +#, c-format +msgid "bad %s in commit" +msgstr "%s di dalam komit" + +#: object-file-convert.c +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "tidak dapat memetakan %s %s pada objek komit" + +#: object-file-convert.c +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Gagal mengkonversi objek dari %s ke %s" + #: object-file.c #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" @@ -22293,6 +22381,11 @@ msgstr "objek terpak %s (disimpan di %s) rusak" #: object-file.c #, c-format +msgid "missing mapping of %s to %s" +msgstr "pemetaan %s ke %s hilang" + +#: object-file.c +#, c-format msgid "unable to write file %s" msgstr "tidak dapat menulis berkas %s" @@ -22362,6 +22455,11 @@ msgstr "tidak dapat membaca objek untuk %s" #: object-file.c #, c-format +msgid "cannot map object %s to %s" +msgstr "tidak dapat memetakan objek %s ke %s" + +#: object-file.c +#, c-format msgid "object fails fsck: %s" msgstr "fsck objek gagal: %s" @@ -22727,6 +22825,11 @@ msgid "unable to load pack: '%s', disabling pack-reuse" msgstr "tidak dapat memuat pak: '%s', mematikan penggunaan ulang pak" #: pack-bitmap.c +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "" +"tidak dapat menghitung pak yang disukai, mematikan penggunaan ulang pak" + +#: pack-bitmap.c #, c-format msgid "object '%s' not found in type bitmaps" msgstr "objek '%s' tidak ditemukan di bitmap tipe" @@ -24020,6 +24123,89 @@ msgstr "tidak dapat menghapus referensi %s: %s" msgid "could not delete references: %s" msgstr "tidak dapat menghapus referensi: %s" +#: refs/reftable-backend.c +#, c-format +msgid "refname is dangerous: %s" +msgstr "nama referensi berbahaya: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "mencoba menulis referensi '%s' dengan objek %s yang tak ada" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "mencoba menulis objek non-komit %s pada cabang '%s'" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"beberapa pembaruan 'HEAD' (termasuk yang lewat perujuknya '%s' tidak " +"diperbolehkan" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "tidak dapat mengunci '%s': tidak dapat menguraikan referensi '%s'" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "tidak dapat mengunci referensi '%s': kesalahan membaca referensi" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"beberapa pembaruan '%s' (termasuk yang lewat referensi simboliknya " +"'%s')tidak diperbolehkan" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "tidak dapat mengunci referensi '%s': referensi sudah ada" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "" +"tidak dapat mengunci referensi '%s' referensi %s hilang tapi diharapkan" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "tidak dapat mengunci referensi '%s': pada %s tetapi diharapkan %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "reftable: menyiapkan transaksi: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "reftable: transaksi gagal: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "unable to compact stack: %s" +msgstr "tidak dapat memampatkan tumpukan: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s not found" +msgstr "nama referensi %s tidak ditemukan" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "nama referensi %s simbolik, menyalinnya tidak didukung" + #: refspec.c #, c-format msgid "invalid refspec '%s'" @@ -24032,6 +24218,11 @@ msgstr "kuotasi tidak valid dalam nilai push-option: '%s'" #: remote-curl.c #, c-format +msgid "unknown value for object-format: %s" +msgstr "nilai object-format tidak dikenal: %s" + +#: remote-curl.c +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs tidak valid: apakah ini sebuah repositori git?" @@ -24579,8 +24770,21 @@ msgstr "resolve-undo merekam `%s` yang dimana hilang" #: revision.c #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "tidak dapat mendapatkan komit untuk argumen jalur leluhur '%s'" +msgid "%s exists but is a symbolic ref" +msgstr "%s ada dan tapi referensi simbolik" + +#: revision.c +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge butuh salah satu dari referensi semu MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD atau REBASE_HEAD" + +#: revision.c +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "tidak dapat mendapatkan komit untuk argumen --ancestry-path %s" #: revision.c msgid "--unpacked=<packfile> no longer supported" @@ -24944,6 +25148,21 @@ msgstr "aksi tidak dikenal: %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 "" +"Selesaikan semua konflik secara manual, tandai sebagai terselesaikan\n" +"dengan \"git add/rm <berkas terkonflik>\", lalu jalankan\n" +"\"git rebase --continue\".\n" +"Anda juga bisa melewatkan komit ini: jalankan \"git rebase --skip\".\n" +"Untuk membatalkan dan kembali ke kondisi sebelum \"git rebase\",jalankan " +"\"git rebase --abort\"." + +#: sequencer.c +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -25199,11 +25418,6 @@ msgstr "tidak dapat memperbarui %s" #: sequencer.c #, c-format -msgid "could not parse commit %s" -msgstr "tidak dapat menguraikan komit %s" - -#: sequencer.c -#, c-format msgid "could not parse parent commit %s" msgstr "tidak dapat menguraikan komit induk %s" @@ -25336,11 +25550,6 @@ msgstr "perintah tidak valid '%.*s'" #: sequencer.c #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s tidak menerima argumen: '%s'" - -#: sequencer.c -#, c-format msgid "missing arguments for %s" msgstr "argumen hilang untuk %s" @@ -25896,6 +26105,11 @@ msgstr "tidak dapat memasang pohon kerja menggunakan konfigurasi tidak valid" #: setup.c #, c-format +msgid "'%s' already specified as '%s'" +msgstr "'%s' sudah diberikan yaitu '%s'" + +#: setup.c +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "Versi repositori git diharapkan <= %d, dapat %d" @@ -26130,6 +26344,24 @@ msgstr "entri indeks adalah direktori, tapi bukan tipis (%08x)" msgid "cannot use split index with a sparse index" msgstr "tidak dapat menggunakan indeks terpisah dengan indeks tipis" +#. 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 jelek: elemen '%s' tidak dimulai dengan '('" + +#. 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 jelek: elemen '%s' tidak diakhiri dengan ')'" + +#. TRANSLATORS: %s is a command like "ls-tree". +#: strbuf.c +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "format %s jelek: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #: strbuf.c #, c-format @@ -26531,35 +26763,6 @@ msgstr "nilai tidak dikenal '%s' untuk kunci '%s'" msgid "empty trailer token in trailer '%.*s'" msgstr "token trailer kosong dalam trailer '%.*s'" -#: trailer.c -#, c-format -msgid "could not read input file '%s'" -msgstr "tidak dapat membaca berkas masukan '%s'" - -#: trailer.c wrapper.c -#, c-format -msgid "could not stat %s" -msgstr "tidak dapat membaca %s" - -#: trailer.c -#, c-format -msgid "file %s is not a regular file" -msgstr "berkas %s bukan sebuah berkas reguler" - -#: trailer.c -#, c-format -msgid "file %s is not writable by user" -msgstr "berkas %s tidak dapat ditulis oleh pengguna" - -#: trailer.c -msgid "could not open temporary file" -msgstr "tidak dapat membuka berkas sementara" - -#: trailer.c -#, c-format -msgid "could not rename temporary file to %s" -msgstr "tidak dapat menamai ulang berkas sementara ke %s" - #: transport-helper.c msgid "full write to remote helper failed" msgstr "gagal menulis penuh ke pembantu remote" @@ -26681,8 +26884,8 @@ msgstr "pembantu tidak mendukung pendorongan; spek referensi diperlukan" #: transport-helper.c #, c-format -msgid "helper %s does not support 'force'" -msgstr "pembantu %s tidak mendukung 'force'" +msgid "helper %s does not support '--force'" +msgstr "pembantu %s tidak mendukung '--force'" #: transport-helper.c msgid "couldn't run fast-export" @@ -27165,6 +27368,11 @@ msgid "invalid '..' path segment" msgstr "segmen jalur '..' tidak valid" #: usage.c +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "kesalahan: tidak dapat memformat pesan: %s\n" + +#: usage.c msgid "usage: " msgstr "penggunaan: " @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: git 2.44.0\n" +"Project-Id-Version: git 2.45.0\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-02-16 07:58+0100\n" -"PO-Revision-Date: 2024-02-16 07:59+0100\n" +"POT-Creation-Date: 2024-04-27 15:19+0100\n" +"PO-Revision-Date: 2024-04-27 15:20+0100\n" "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n" "Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -490,12 +490,12 @@ 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" "Ta bort â€%c†rader genom att göra dem †â€-rader (sammanhang).\n" "Ta bort â€%c†rader genom att radera dem.\n" -"Rader som börjar med %c kommer att tas bort.\n" +"Rader som börjar med %s kommer att tas bort.\n" msgid "" "If it does not apply cleanly, you will be given an opportunity to\n" @@ -542,6 +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" "? - print help\n" msgstr "" "j - lämna stycket obestämt, se nästa obestämda stycke\n" @@ -552,6 +553,7 @@ 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" "? - visa hjälp\n" msgid "No previous hunk" @@ -614,8 +616,8 @@ msgstr "" "SlÃ¥ av meddelandet med â€git config advice.%s falseâ€" #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%stips: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%stips:%s%.*s%s\n" msgid "Cherry-picking is not possible because you have unmerged files." msgstr "" @@ -889,11 +891,11 @@ msgstr "patch med bara skräp pÃ¥ rad %d" #, c-format msgid "unable to read symlink %s" -msgstr "kunde inte läsa symboliska länken %s" +msgstr "kan inte läsa symboliska länken %s" #, c-format msgid "unable to open or read %s" -msgstr "kunde inte öppna eller läsa %s" +msgstr "kan inte öppna eller läsa %s" #, c-format msgid "invalid start of line: '%c'" @@ -1116,10 +1118,6 @@ msgstr[0] "Tillämpade patchen %%s med %d refuserad..." msgstr[1] "Tillämpade patchen %%s med %d refuserade..." #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "trunkerar .rej-filnamnet till %.*s.rej" - -#, c-format msgid "cannot open %s" msgstr "kan inte öppna %s" @@ -1168,7 +1166,7 @@ msgstr[0] "%d rad applicerade efter att ha rättat fel i blanksteg." msgstr[1] "%d rader applicerade efter att ha rättat fel i blanksteg." msgid "Unable to write new index file" -msgstr "Kunde inte skriva ny indexfil" +msgstr "Kan inte skriva ny indexfil" msgid "don't apply changes matching the given path" msgstr "tillämpa inte ändringar som motsvarar given sökväg" @@ -1276,7 +1274,7 @@ msgstr "fel i deflate (%d)" #, c-format msgid "unable to start '%s' filter" -msgstr "kunde inte starta filtret â€%sâ€" +msgstr "kane inte starta filtret â€%sâ€" msgid "unable to redirect descriptor" msgstr "kan inte omdirigera handtag" @@ -1434,7 +1432,7 @@ msgid "%.*s is not a valid attribute name" msgstr "%-*s är inte ett giltigt namn pÃ¥ attribut" msgid "unable to add additional attribute" -msgstr "Kunde inte lägga till ytterligare attribut" +msgstr "kan inte lägga till ytterligare attribut" #, c-format msgid "ignoring overly long attributes line %d" @@ -1472,7 +1470,7 @@ msgstr "kan inte ta status pÃ¥ â€%sâ€" #, c-format msgid "unable to read %s" -msgstr "kunde inte läsa %s" +msgstr "kan inte läsa %s" #, c-format msgid "Badly quoted content in file '%s': %s" @@ -1544,6 +1542,10 @@ msgid "could not create file '%s'" msgstr "kunde inte skapa filen â€%sâ€" #, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "kan inte starta â€show†för objektet â€%sâ€" + +#, c-format msgid "could not read file '%s'" msgstr "kunde inte läsa filen â€%sâ€" @@ -1693,6 +1695,9 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "â€%s†är inte ett giltigt grennamn" +msgid "See `man git check-ref-format`" +msgstr "Se â€man git check-ref-formatâ€" + #, c-format msgid "a branch named '%s' already exists" msgstr "det finns redan en gren som heter â€%sâ€" @@ -1885,14 +1890,8 @@ msgstr "" msgid "adding embedded git repository: %s" msgstr "lägger till inbäddat git-arkiv: %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 "" -"Använd -f om du verkligen vill lägga till dem.\n" -"SlÃ¥ av detta meddelande med\n" -"â€git config advice.addIgnoredFile falseâ€" +msgid "Use -f if you really want to add them." +msgstr "Använd -f om du verkligen vill lägga till dem." msgid "adding files failed" msgstr "misslyckades lägga till filer" @@ -1909,20 +1908,14 @@ msgstr "â€%s†kan inte användas tillsammans med sökvägsangivelser" msgid "Nothing specified, nothing added.\n" msgstr "Inget angivet, inget tillagt.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"Tänkte du kanske säga â€git add .â€?\n" -"SlÃ¥ av detta meddelande genom att köra\n" -"â€git config advice.addEmptyPathspec falseâ€" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "Tänkte du kanske säga â€git add .â€?" msgid "index file corrupt" msgstr "indexfilen trasig" msgid "unable to write new index file" -msgstr "kunde inte skriva ny indexfil" +msgstr "kan inte skriva ny indexfil" #, c-format msgid "bad action '%s' for '%s'" @@ -1993,18 +1986,19 @@ msgid "Failed to split patches." msgstr "Misslyckades dela patchar." #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "När du har löst problemet, kör â€%s --continueâ€." +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "När du har löst problemet, kör â€%s --continueâ€.\n" #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "Om du hellre vill hoppa över patchen, kör â€%s --skip†i stället." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "Om du hellre vill hoppa över patchen, kör â€%s --skip†i stället.\n" #, 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 "" "För att registrera den tomma patchen som en tom incheckning, kör â€%s --allow-" -"emptyâ€." +"emptyâ€.\n" #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." @@ -2025,7 +2019,7 @@ msgstr "ogiltig ident-rad: %.*s" #, c-format msgid "unable to parse commit %s" -msgstr "kunde inte tolka incheckningen %s" +msgstr "kan inte tolka incheckningen %s" msgid "Repository lacks necessary blobs to fall back on 3-way merge." msgstr "" @@ -2056,7 +2050,7 @@ msgid "applying to an empty history" msgstr "tillämpar pÃ¥ en tom historik" msgid "failed to write commit object" -msgstr "kunde inte skriva incheckningsobjekt" +msgstr "misslyckades skriva incheckningsobjekt" #, c-format msgid "cannot resume: %s does not exist." @@ -2357,7 +2351,7 @@ msgstr "â€%s†är inte en giltig incheckning" msgid "" "could not check out original HEAD '%s'. Try 'git bisect reset <commit>'." msgstr "" -"Kunde inte checka ut original-HEAD â€%sâ€. Försök â€git bisect reset " +"kan inte checka ut original-HEAD â€%sâ€. Försök â€git bisect reset " "<incheckning>â€." #, c-format @@ -2849,11 +2843,11 @@ msgstr "grenen kopierades, men misslyckades uppdatera konfigurationsfilen" 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 "" "Redigera beskrivningen för grenen\n" " %s\n" -"Rader som inleds med â€%c†ignoreras.\n" +"Rader som inleds med â€%s†ignoreras.\n" msgid "Generic options" msgstr "Allmänna flaggor" @@ -3052,11 +3046,13 @@ msgid "not run from a git repository - no hooks to show\n" msgstr "körs inte frÃ¥n ett git-arkiv - inga krokar att visa\n" 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) <fil>] [(-s | --suffix) <format>]\n" -" [--diagnose[=<läge>]" +"git bugreport [(-o | --output-directory) <sökväg>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" +" [--diagnose[=<läge>]]" msgid "" "Thank you for filling out a Git bug report!\n" @@ -3117,7 +3113,7 @@ msgstr "kunde inte skapa inledande kataloger för â€%sâ€" #, c-format msgid "unable to create diagnostics archive %s" -msgstr "kunde inte skapa diagnostikarkiven %s" +msgstr "kan inte skapa diagnostikarkiven %s" msgid "System Info" msgstr "Systeminfo" @@ -3127,7 +3123,7 @@ msgstr "Aktiverade krokar" #, c-format msgid "unable to write to %s" -msgstr "kunde inte skriva till %s" +msgstr "kan inte skriva till %s" #, c-format msgid "Created new report at '%s'.\n" @@ -3407,7 +3403,7 @@ msgstr "läs även kontakter frÃ¥n standard in" #, c-format msgid "unable to parse contact: %s" -msgstr "kunde inte tolka kontakt: %s" +msgstr "kan inte tolka kontakt: %s" msgid "no contacts specified" msgstr "inga kontakter angavs" @@ -3488,7 +3484,7 @@ msgstr "sökväg â€%sâ€: kan inte slÃ¥ ihop" #, c-format msgid "Unable to add merge result for '%s'" -msgstr "Kunde inte lägga till sammanslagningsresultat för â€%sâ€" +msgstr "Kan inte lägga till sammanslagningsresultat för â€%sâ€" #, c-format msgid "Recreated %d merge conflict" @@ -3536,6 +3532,10 @@ msgstr "â€%sâ€, â€%s†eller â€%s†kan inte användas när en katalog che msgid "path '%s' is unmerged" msgstr "sökvägen â€%s†har inte slagits ihop" +#, c-format +msgid "unable to read tree (%s)" +msgstr "kan inte läsa träd (%s)" + msgid "you need to resolve your current index first" msgstr "du mÃ¥ste lösa ditt befintliga index först" @@ -3766,6 +3766,10 @@ msgstr "Kan inte växla gren till icke-incheckningen â€%sâ€" msgid "missing branch or commit argument" msgstr "saknar gren- eller incheckingsargument" +#, c-format +msgid "unknown conflict style '%s'" +msgstr "okänd konflikttyp â€%sâ€" + msgid "perform a 3-way merge with the new branch" msgstr "utför en 3-vägssammanslagning för den nya grenen" @@ -4021,19 +4025,8 @@ msgstr "ta även bort ignorerade filer" msgid "remove only ignored files" msgstr "ta endast bort ignorerade filer" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce satt till true, men varken -i, -n eller -f angavs; vägrar " -"städa" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" -msgstr "" -"clean.requireForce har standardvärdet true och varken -i, -n eller -f " -"angavs; vägrar städa" +msgid "clean.requireForce is true and -f not given: refusing to clean" +msgstr "clean.requireForce är true och -f angavs inte: vägrar städa" msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [<flaggor>] [--] <arkiv> [<kat>]" @@ -4047,8 +4040,8 @@ msgstr "skapa inte nÃ¥gon utcheckning" msgid "create a bare repository" msgstr "skapa ett naket (â€bareâ€) arkiv" -msgid "create a mirror repository (implies bare)" -msgstr "skapa ett spegelarkiv (implicerar â€bareâ€)" +msgid "create a mirror repository (implies --bare)" +msgstr "skapa ett spegelarkiv (implicerar --bare)" msgid "to clone from a local repository" msgstr "för att klona frÃ¥n ett lokalt arkiv" @@ -4223,10 +4216,10 @@ msgid "remote HEAD refers to nonexistent ref, unable to checkout" msgstr "HEAD hos fjärren pekar pÃ¥ en obefintlig referens, kan inte checka ut" msgid "unable to checkout working tree" -msgstr "kunde inte checka ut arbetskatalogen" +msgstr "kan inte checka ut arbetskatalogen" msgid "unable to write parameters to config file" -msgstr "kunde inte skriva parametrar till konfigurationsfilen" +msgstr "kan inte skriva parametrar till konfigurationsfilen" msgid "cannot repack to clean up" msgstr "kan inte packa om för att städa upp" @@ -4356,6 +4349,10 @@ msgstr "spaltfyllnad i högerkanten" msgid "padding space between columns" msgstr "spaltfyllnad mellan spalter" +#, c-format +msgid "%s must be non-negative" +msgstr "%s mÃ¥ste vara icke-negativt" + msgid "--command must be the first argument" msgstr "--command mÃ¥ste vara första argument" @@ -4584,7 +4581,7 @@ msgid "No paths with --include/--only does not make sense." msgstr "Du mÃ¥ste ange sökvägar tillsammans med --include/--only." msgid "unable to create temporary index" -msgstr "kunde inte skapa temporär indexfil" +msgstr "kan inte skapa temporär indexfil" msgid "interactive add failed" msgstr "interaktiv tilläggning misslyckades" @@ -4608,7 +4605,7 @@ msgid "cannot read the index" msgstr "kan inte läsa indexet" msgid "unable to write temporary index file" -msgstr "kunde inte skriva temporär indexfil" +msgstr "kan inte skriva temporär indexfil" #, c-format msgid "commit '%s' lacks author header" @@ -4629,7 +4626,7 @@ msgid "" "unable to select a comment character that is not used\n" "in the current commit message" msgstr "" -"kunde inte välja ett kommentarstecken som inte använts\n" +"kan inte välja ett kommentarstecken som inte använts\n" "i det befintliga incheckningsmeddelandet" #, c-format @@ -4667,35 +4664,35 @@ msgstr "kunde inte skriva incheckningsmall" #, 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 "" "Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n" -"med â€%c†kommer ignoreras.\n" +"med â€%s†kommer ignoreras.\n" #, 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 "" "Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n" -"med â€%c†kommer ignoreras, och ett tomt meddelande avbryter incheckningen.\n" +"med â€%s†kommer ignoreras, och ett tomt meddelande avbryter incheckningen.\n" #, 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 "" "Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n" -"med â€%c†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n" +"med â€%s†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n" #, 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 "" "Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n" -"med â€%c†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n" +"med â€%s†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n" "Ett tomt meddelande avbryter incheckningen.\n" msgid "" @@ -5134,6 +5131,9 @@ msgstr "värde" msgid "with --get, use default value when missing entry" msgstr "med --get, använd standardvärde vid saknad post" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "människoläsbar kommentarssträng (# läggs in först efter behov)" + #, c-format msgid "wrong number of arguments, should be %d" msgstr "fel antal argument, skulle vara %d" @@ -5226,6 +5226,9 @@ msgstr "" 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 "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value gäller endast med â€värde-mönsterâ€" @@ -5284,7 +5287,7 @@ msgstr "â€credential-cache†ej tillgänglig; stöd för unix-uttag saknas" #, c-format msgid "unable to get credential storage lock in %d ms" -msgstr "kunde inte erhÃ¥lla lÃ¥set för lagring av inlogginsuppgifter pÃ¥ %d ms" +msgstr "kan inte erhÃ¥lla lÃ¥set för lagring av inlogginsuppgifter pÃ¥ %d ms" msgid "" "git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]" @@ -5693,7 +5696,7 @@ msgid "[tag update]" msgstr "[uppdaterad tagg]" msgid "unable to update local ref" -msgstr "kunde inte uppdatera lokal ref" +msgstr "kan inte uppdatera lokal ref" msgid "would clobber existing tag" msgstr "skulle skriva över befintlig tagg" @@ -6061,6 +6064,9 @@ msgstr "visa endast referenser som inte innehÃ¥ller incheckningen" msgid "read reference patterns from stdin" msgstr "läs referensmönster frÃ¥n standard in" +msgid "also include HEAD ref and pseudorefs" +msgstr "ta ocksÃ¥ med HEAD- och pseudo-referenser" + msgid "unknown arguments supplied with --stdin" msgstr "okända argument angavs tillsammans med --stdin" @@ -6247,7 +6253,7 @@ msgstr "%s: ogiltig sha1-pekare i resolve-undo för %s" #, c-format msgid "unable to load rev-index for pack '%s'" -msgstr "kunde inte läsa rev-index för paketfil â€%sâ€" +msgstr "kan inte läsa rev-index för paketfil â€%sâ€" #, c-format msgid "invalid rev-index for pack '%s'" @@ -6456,11 +6462,11 @@ msgstr "packa om alla paket förutom det största paketet" #, c-format msgid "failed to parse gc.logExpiry value %s" -msgstr "kunde inte tolka värdet %s för gc.logExpiry" +msgstr "misslyckades tolka värdet %s för gc.logExpiry" #, c-format msgid "failed to parse prune expiry value %s" -msgstr "kunde inte tolka värdet %s för prune expiry" +msgstr "misslyckades tolka värdet %s för prune expiry" #, c-format msgid "Auto packing the repository in background for optimum performance.\n" @@ -6499,19 +6505,19 @@ msgid "unrecognized --schedule argument '%s'" msgstr "okänt argument för --schedule, %s" msgid "failed to write commit-graph" -msgstr "kunde inte skriva incheckningsgraf" +msgstr "misslyckades skriva incheckningsgraf" msgid "failed to prefetch remotes" -msgstr "kunde inte förhämta fjärrar" +msgstr "misslyckades förhämta fjärrar" msgid "failed to start 'git pack-objects' process" -msgstr "kunde inte starta â€git pack-objectsâ€-process" +msgstr "misslyckades starta â€git pack-objectsâ€-process" msgid "failed to finish 'git pack-objects' process" -msgstr "kunde inte avsluta â€git pack-objectsâ€-process" +msgstr "misslyckades att avsluta â€git pack-objectsâ€-process" msgid "failed to write multi-pack-index" -msgstr "kunde inte skriva multi-pack-index" +msgstr "misslyckades skriva multi-pack-index" msgid "'git multi-pack-index expire' failed" msgstr "â€git multi-pack-index expire†misslyckades" @@ -6680,16 +6686,12 @@ msgid "no threads support, ignoring %s" msgstr "trÃ¥dstöd saknas, ignorerar %s" #, c-format -msgid "unable to read tree (%s)" -msgstr "kunde inte läsa träd (%s)" - -#, c-format msgid "unable to read tree %s" -msgstr "kunde inte läsa trädet %s" +msgstr "kan inte läsa trädet %s" #, c-format msgid "unable to grep from object of type %s" -msgstr "kunde inte â€grep†frÃ¥n objekt av typen %s" +msgstr "kan inte â€grep†frÃ¥n objekt av typen %s" #, c-format msgid "switch `%c' expects a numerical value" @@ -6945,7 +6947,7 @@ msgid "Failed to start emacsclient." msgstr "Misslyckades starta emacsclient." msgid "Failed to parse emacsclient version." -msgstr "Kunde inte tolka emacsclient-version." +msgstr "Misslyckades tolka emacsclient-version." #, c-format msgid "emacsclient version '%d' too old (< 22)." @@ -6953,7 +6955,7 @@ msgstr "emacsclient version â€%d†för gammal (< 22)." #, c-format msgid "failed to exec '%s'" -msgstr "exec misslyckades för â€%sâ€" +msgstr "â€exec†misslyckades för â€%sâ€" #, c-format msgid "" @@ -7138,7 +7140,7 @@ msgstr "Analyserar delta" #, c-format msgid "unable to create thread: %s" -msgstr "kunde inte skapa trÃ¥d: %s" +msgstr "kan inte skapa trÃ¥d: %s" msgid "confusion beyond insanity" msgstr "förvirrad bortom vanvett" @@ -7161,7 +7163,7 @@ msgstr[1] "paketet har %d oanalyserade delta" #, c-format msgid "unable to deflate appended object (%d)" -msgstr "kunde inte utföra â€deflate†pÃ¥ tillagt objekt (%d)" +msgstr "kan inte utföra â€deflate†pÃ¥ tillagt objekt (%d)" #, c-format msgid "local object %s is corrupt" @@ -7181,7 +7183,7 @@ msgstr "kan inte stänga skriven %s-fil â€%sâ€" #, c-format msgid "unable to rename temporary '*.%s' file to '%s'" -msgstr "kunde inte byta namn pÃ¥ temporär â€*.%sâ€-fil till â€%sâ€" +msgstr "kan inte byta namn pÃ¥ temporär â€*.%sâ€-fil till â€%sâ€" msgid "error while closing pack file" msgstr "fel vid stängning av paketfil" @@ -7283,14 +7285,40 @@ msgstr "--separate-git-dir är inkompatibelt med naket arkiv" 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 (<nyckel>|<nyckelAlias>)" +" [(--trailer (<nyckel>|<nyckel-alias>)" "[(=|:)<värde>])...]\n" " [--parse] [<fil>...]" +#, c-format +msgid "could not stat %s" +msgstr "kunde inte ta status pÃ¥ %s" + +#, c-format +msgid "file %s is not a regular file" +msgstr "filen %s är inte en normal fil" + +#, c-format +msgid "file %s is not writable by user" +msgstr "filen %s är inte skrivbar av användaren" + +msgid "could not open temporary file" +msgstr "kunde inte öppna temporär fil" + +#, c-format +msgid "could not read input file '%s'" +msgstr "kunde inte läsa indatafilen â€%sâ€" + +msgid "could not read from stdin" +msgstr "kunde inte läsa frÃ¥n standard in" + +#, c-format +msgid "could not rename temporary file to %s" +msgstr "kunde inte byta namn pÃ¥ temporär fil till %s" + msgid "edit files in place" msgstr "redigera filer pÃ¥ plats" @@ -7380,7 +7408,7 @@ msgid "Final output: %d %s\n" msgstr "Slututdata: %d %s\n" msgid "unable to create temporary object directory" -msgstr "kunde inte skapa temporär objektkatalog" +msgstr "kan inte skapa temporär objektkatalog" #, c-format msgid "git show %s: bad file" @@ -7447,12 +7475,12 @@ msgid "" "please use git branch --set-upstream-to to track a remote branch.\n" "Or you could specify base commit by --base=<base-commit-id> manually" msgstr "" -"kunde inte hämta uppström, om du vill lagra basincheckningen automatiskt,\n" +"misslyckades hämta uppström, om du vill lagra basincheckningen automatiskt,\n" "använd git branch --set-upstream-to för att spÃ¥ra en fjärrgren.\n" "Eller sÃ¥ kan du ange basincheckning med --base=<bas-inchecknings-id> manuellt" msgid "failed to find exact merge base" -msgstr "kunde inte hitta exakt sammanslagningsbas" +msgstr "misslyckades hitta exakt sammanslagningsbas" msgid "base commit should be the ancestor of revision list" msgstr "basincheckningen bör vara förfader till revisionslistan" @@ -7653,7 +7681,7 @@ msgstr "Intervall-diff mot v%d:" #, c-format msgid "unable to read signature file '%s'" -msgstr "kunde inte läsa signaturfil â€%sâ€" +msgstr "kan inte läsa signaturfil â€%sâ€" msgid "Generating patches" msgstr "Skapar patchar" @@ -7673,18 +7701,6 @@ msgstr "Kunde inte hitta en spÃ¥rad fjärrgren, ange <uppström> manuellt.\n" msgid "could not get object info about '%s'" msgstr "kunde inte hämta objektinfo om â€%sâ€" -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "felaktigt ls-files-format: elementet â€%s†börjar inte med â€(â€" - -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "felaktigt ls-files-format: elementet â€%s†slutar inte med â€)â€" - -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "felaktigt ls-files-format: %%%.*s" - msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<flaggor>] [<fil>...]" @@ -7815,18 +7831,6 @@ msgstr "visa underliggande referens och objektet det pekar pÃ¥" msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<flaggor>] <träd-igt> [<sökväg>...]" -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "felaktigt ls-tree-format: elementet â€%s†börjar inte med â€(â€" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "felaktigt ls-tree-format: elementet â€%s†slutar inte med â€)â€" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "felaktigt ls-tree-format: %%%.*s" - msgid "only show trees" msgstr "visa endast träd" @@ -8012,6 +8016,10 @@ msgstr "kunde inte bestämma referensen â€%sâ€" msgid "Merging %s with %s\n" msgstr "SlÃ¥r ihop %s med %s\n" +#, c-format +msgid "could not parse as tree '%s'" +msgstr "kunde inte tolka som träd â€%sâ€" + msgid "not something we can merge" msgstr "inte nÃ¥got vi kan slÃ¥ ihop" @@ -8182,14 +8190,14 @@ msgid "Bad branch.%s.mergeoptions string: %s" msgstr "Felaktig branch.%s.mergeoptions-sträng: %s" msgid "Unable to write index." -msgstr "Kunde inte skriva indexet." +msgstr "Kan inte skriva indexet." msgid "Not handling anything other than two heads merge." msgstr "Hanterar inte nÃ¥got annat än en sammanslagning av tvÃ¥ huvuden." #, c-format msgid "unable to write %s" -msgstr "kunde inte skriva %s" +msgstr "kan inte skriva %s" #, c-format msgid "Could not read from '%s'" @@ -8215,10 +8223,10 @@ msgstr "Ett tomt meddelande avbryter incheckningen.\n" #, 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 "" -"Rader som inleds med â€%c†kommer ignoreras, och ett tomt meddelande\n" +"Rader som inleds med â€%s†kommer ignoreras, och ett tomt meddelande\n" "avbryter incheckningen.\n" msgid "Empty commit message." @@ -8376,9 +8384,6 @@ msgstr "kunde inte läsa det taggade objektet â€%sâ€" msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "objektet â€%s†taggat som â€%sâ€, men är av typen â€%sâ€" -msgid "could not read from stdin" -msgstr "kunde inte läsa frÃ¥n standard in" - msgid "tag on stdin did not pass our strict fsck check" msgstr "tagg pÃ¥ stdin godkänns inte av vÃ¥r strikta fsck-kontroll" @@ -8386,7 +8391,7 @@ msgid "tag on stdin did not refer to a valid object" msgstr "taggen pÃ¥ stdin pekar inte pÃ¥ ett giltigt objekt" msgid "unable to write tag file" -msgstr "kunde inte skriva tagg-filen" +msgstr "kan inte skriva tagg-filen" msgid "input is NUL terminated" msgstr "indata är NUL-terminerad" @@ -8640,22 +8645,18 @@ msgstr "git notes prune [<flaggor>]" msgid "Write/edit the notes for the following object:" msgstr "Skriv/redigera anteckningar för följande objekt:" -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "kunde inte starta â€show†för objektet â€%sâ€" - msgid "could not read 'show' output" -msgstr "kunde inte läsa utdata frÃ¥n â€showâ€" +msgstr "kan inte läsa utdata frÃ¥n â€showâ€" #, c-format msgid "failed to finish 'show' for object '%s'" -msgstr "kunde inte avsluta â€show†för objektet â€%sâ€" +msgstr "misslyckades att avsluta â€show†för objektet â€%sâ€" msgid "please supply the note contents using either -m or -F option" msgstr "ange innehÃ¥ll för anteckningen med antingen -m eller -F" msgid "unable to write note object" -msgstr "kunde inte skriva anteckningsobjekt" +msgstr "kan inte skriva anteckningsobjekt" #, c-format msgid "the note contents have been left in %s" @@ -8667,11 +8668,11 @@ msgstr "kunde inte öppna eller läsa â€%sâ€" #, c-format msgid "failed to resolve '%s' as a valid ref." -msgstr "kunde inte slÃ¥ upp â€%s†som en giltig referens." +msgstr "misslyckades slÃ¥ upp â€%s†som en giltig referens." #, c-format msgid "failed to read object '%s'." -msgstr "kunde inte läsa objektet â€%sâ€." +msgstr "misslyckades läsa objektet â€%sâ€." #, c-format msgid "cannot read note data from non-blob object '%s'." @@ -8849,7 +8850,7 @@ msgstr "" #, c-format msgid "Failed to resolve '%s' as a valid ref." -msgstr "Kunde inte slÃ¥ upp â€%s†som en giltig referens." +msgstr "Misslyckades slÃ¥ upp â€%s†som en giltig referens." #, c-format msgid "Object %s has no note\n" @@ -8955,7 +8956,7 @@ msgstr "kan inte hämta storlek pÃ¥ %s" #, c-format msgid "unable to parse object header of %s" -msgstr "kunde inte tolka objekthuvud för %s" +msgstr "kan inte tolka objekthuvud för %s" #, c-format msgid "object %s cannot be read" @@ -8978,7 +8979,7 @@ msgstr "kan inte packa objekt nÃ¥bara frÃ¥n taggen %s" #, c-format msgid "unable to get type of object %s" -msgstr "kunde inte hämta typ för objektet %s" +msgstr "kan inte hämta typ för objektet %s" msgid "Compressing objects" msgstr "Komprimerar objekt" @@ -9265,10 +9266,10 @@ msgid "refusing to run without --i-still-use-this" msgstr "vägrar köra utan --i-still-use-this" 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 <mönster>] [--exclude " +"git pack-refs [--all] [--no-prune] [--auto] [--include <mönster>] [--exclude " "<mönster>]" msgid "pack everything" @@ -9277,6 +9278,9 @@ msgstr "packa allt" msgid "prune loose refs (default)" msgstr "ta bort lösa referenser (standard)" +msgid "auto-pack refs as needed" +msgstr "packa referenser automatiskt om nödvändigt" + msgid "references to include" msgstr "referenser att ta med" @@ -9411,7 +9415,7 @@ msgstr "" #, c-format msgid "unable to access commit %s" -msgstr "kunde inte komma Ã¥t incheckningen %s" +msgstr "kan inte komma Ã¥t incheckningen %s" msgid "ignoring --verify-signatures for rebase" msgstr "ignorera --verify-signatures för ombasering" @@ -9902,7 +9906,7 @@ msgid "could not mark as interactive" msgstr "kunde inte markera som interaktiv" msgid "could not generate todo list" -msgstr "Kunde inte skapa attgöra-lista" +msgstr "kunde inte skapa attgöra-lista" msgid "a base commit must be provided with --upstream or --onto" msgstr "en basincheckning mÃ¥ste anges med --upstream eller --onto" @@ -9927,19 +9931,6 @@ msgstr "ignorera ogiltigt allow_rerere_autoupdate: â€%sâ€" msgid "could not remove '%s'" msgstr "kunde inte ta bort â€%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 "" -"Lös alla konflikter manuellt, märk dem som lösta med\n" -"â€git add/rm <filer_i_konflikt>â€, kör sedan â€git rebase --continueâ€.\n" -"Du kan hoppa över incheckningen istället: kör â€git rebase --skipâ€.\n" -"För att avbryta och Ã¥tergÃ¥ till där du var före ombaseringen, kör â€git " -"rebase --abortâ€." - #, c-format msgid "" "\n" @@ -9970,11 +9961,14 @@ msgid "apply options and merge options cannot be used together" msgstr "" "appliceringsflaggor och sammanslagningsflaggor kan inte användas tillsammans" +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask rekommenderas inte; använd â€--empty=stop†istället." + #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." -msgstr "okänd tom-typ â€%sâ€; giltiga värden är â€dropâ€, â€keep†och â€askâ€." +"\"stop\"." +msgstr "okänd tom-typ â€%sâ€; giltiga värden är â€dropâ€, â€keep†och â€stopâ€." msgid "" "--rebase-merges with an empty string argument is deprecated and will stop " @@ -10153,8 +10147,8 @@ msgstr "" "Observera: Din inställning för â€pull.rebase†kan ocksÃ¥ vara satt till\n" "â€preserveâ€, som inte längre stöds; använd â€merges†istället" -msgid "No rebase in progress?" -msgstr "Ingen ombasering pÃ¥gÃ¥r?" +msgid "no rebase in progress" +msgstr "ingen ombasering pÃ¥gÃ¥r" msgid "The --edit-todo action can only be used during interactive rebase." msgstr "Ã…tgärden --edit-todo kan endast användas under interaktiv ombasering." @@ -10348,6 +10342,9 @@ msgstr "du mÃ¥ste ange en katalog" msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<log-flaggor>] [<ref>]" +msgid "git reflog list" +msgstr "git reflog list" + msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -10373,6 +10370,10 @@ msgstr "git reflog exists <referens>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "ogiltig tidsstämpel â€%s†given i â€--%sâ€" +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s tar inte argument: â€%sâ€" + msgid "do not actually prune any entries" msgstr "rensa faktiskt inte nÃ¥gra poster" @@ -10498,8 +10499,8 @@ msgstr "" "\t --mirror=fetch eller --mirror=push istället" #, c-format -msgid "unknown mirror argument: %s" -msgstr "okänt argument till mirror: %s" +msgid "unknown --mirror argument: %s" +msgstr "okänt argument till --mirror: %s" msgid "fetch the remote branches" msgstr "hämta fjärrgrenarna" @@ -10862,6 +10863,9 @@ msgstr "" msgid "could not start pack-objects to repack promisor objects" msgstr "kunde inte starta pack-objects för att packa om kontraktsobjekt" +msgid "failed to feed promisor objects to pack-objects" +msgstr "misslyckades sända kontraktsobjekt till pack-objects" + msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" "repack: Förväntar kompletta hex-objekt-id-rader endast frÃ¥n pack-objects." @@ -11267,7 +11271,7 @@ msgstr "â€git rerere forget†utan sökvägar är förÃ¥ldrat" #, c-format msgid "unable to generate diff for '%s'" -msgstr "misslyckades skapa diff för â€%sâ€" +msgstr "kan inte skapa diff för â€%sâ€" msgid "" "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" @@ -11304,11 +11308,11 @@ msgid "You do not have a valid HEAD." msgstr "Du har inte en giltig HEAD." msgid "Failed to find tree of HEAD." -msgstr "Kunde inte hitta trädet för HEAD." +msgstr "Misslyckades hitta trädet för HEAD." #, c-format msgid "Failed to find tree of %s." -msgstr "Kunde inte hitta trädet för %s." +msgstr "Misslyckades hitta trädet för %s." #, c-format msgid "HEAD is now at %s" @@ -11341,11 +11345,11 @@ msgstr "registrera endast att borttagna sökvägar kommer läggas till senare" #, c-format msgid "Failed to resolve '%s' as a valid revision." -msgstr "Kunde inte slÃ¥ upp â€%s†som en giltig revision." +msgstr "Misslyckades slÃ¥ upp â€%s†som en giltig revision." #, c-format msgid "Failed to resolve '%s' as a valid tree." -msgstr "Kunde inte slÃ¥ upp â€%s†som ett giltigt träd." +msgstr "Misslyckades slÃ¥ upp â€%s†som ett giltigt träd." msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead." msgstr "" @@ -11456,6 +11460,13 @@ msgstr "--default kräver ett argument" msgid "--prefix requires an argument" msgstr "--prefix kräver ett argument" +msgid "no object format specified" +msgstr "inget objektformat angavs" + +#, c-format +msgid "unsupported object format: %s" +msgstr "objektformatet stöds ej: %s" + #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "okänt läge för --abbrev-ref: %s" @@ -11537,8 +11548,8 @@ msgstr "behÃ¥ll incheckningar som börjar som tomma" msgid "allow commits with empty messages" msgstr "tillÃ¥t incheckningar med tomt meddelande" -msgid "keep redundant, empty commits" -msgstr "behÃ¥ll redundanta, tomma incheckningar" +msgid "deprecated: use --empty=keep instead" +msgstr "avrÃ¥ds: använd --empty=keep istället" msgid "use the 'reference' format to refer to commits" msgstr "använd â€referensâ€-format för att referera till incheckningar" @@ -11905,7 +11916,7 @@ msgstr "slÃ¥ pÃ¥/av använding av glest index" #, c-format msgid "unable to create leading directories of %s" -msgstr "kunde inte skapa inledande kataloger för %s" +msgstr "kan inte skapa inledande kataloger för %s" #, c-format msgid "failed to open '%s'" @@ -11920,7 +11931,7 @@ msgid "unable to unquote C-style string '%s'" msgstr "kan inte ta bort citering av C-sträng â€%sâ€" msgid "unable to load existing sparse-checkout patterns" -msgstr "kunde inte läsa in existerande mönster för gles utcheckning" +msgstr "kan inte läsa in existerande mönster för gles utcheckning" msgid "existing sparse-checkout patterns do not use cone mode" msgstr "befintliga filter för gles utcheckning använder inte konläge" @@ -12860,29 +12871,29 @@ 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" "Skriv ett meddelande för taggen:\n" " %s\n" -"Rader som inleds med â€%c†ignoreras.\n" +"Rader som inleds med â€%s†ignoreras.\n" #, 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" "Skriv ett meddelande för taggen:\n" " %s\n" -"Rader som inleds med â€%c†kommer behÃ¥llas; du kan själv ta bort dem om\n" +"Rader som inleds med â€%s†kommer behÃ¥llas; du kan själv ta bort dem om\n" "du vill.\n" msgid "unable to sign the tag" -msgstr "kunde inte signera taggen" +msgstr "kan inte signera taggen" #, c-format msgid "" @@ -12963,6 +12974,9 @@ msgstr "visa endast taggar som ej slagits samman" msgid "print only tags of the object" msgstr "visa endast taggar för objektet" +msgid "could not start 'git column'" +msgstr "kunde inte starta â€git columnâ€" + #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "flaggan â€%s†är endast tillÃ¥ten i listläge" @@ -13204,11 +13218,11 @@ msgstr "" msgid "fsmonitor disabled" msgstr "fsmonitor inaktiverat" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<flaggor>] -d <refnamn> [<gammaltvärde>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<flaggor>] -d <refnamn> [<gammalt-oid>]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "git update-ref [<flaggor>] <refnamn> <gammaltvärde> [<nyttvärde>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "git update-ref [<flaggor>] <refnamn> <gammalt-oid> [<nytt-oid>]" msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [<flaggor>] --stdin [-z]" @@ -13627,7 +13641,7 @@ msgstr "överskred buntens URI-rekursionsgräns (%d)" #, c-format msgid "failed to download bundle from URI '%s'" -msgstr "kunde inte hämta bunt frÃ¥n URI:en â€%sâ€" +msgstr "misslyckades hämta bunt frÃ¥n URI:en â€%sâ€" #, c-format msgid "file at URI '%s' is not a bundle or bundle list" @@ -14454,7 +14468,7 @@ msgid "Finding extra edges in commit graph" msgstr "Söker ytterligare kanter i incheckingsgraf" msgid "failed to write correct number of base graph ids" -msgstr "kunde inte skriva korrekt antal bas-graf-id:n" +msgstr "misslyckades skriva korrekt antal bas-graf-id:n" msgid "unable to create temporary graph layer" msgstr "kan inte skapa temporärt graflager" @@ -14470,13 +14484,13 @@ msgstr[0] "Skriver ut incheckningsgraf i %d pass" msgstr[1] "Skriver ut incheckningsgraf i %d pass" msgid "unable to open commit-graph chain file" -msgstr "Kunde inte öppna incheckningsgrafkedjefilen" +msgstr "kan inte öppna incheckningsgrafkedjefilen" msgid "failed to rename base commit-graph file" -msgstr "kunde inte byta namn pÃ¥ bas-incheckingsgraffilen" +msgstr "misslyckades byta namn pÃ¥ bas-incheckingsgraffilen" msgid "failed to rename temporary commit-graph file" -msgstr "kunde inte byta namn pÃ¥ temporär incheckningsgraffil" +msgstr "misslyckades byta namn pÃ¥ temporär incheckningsgraffil" #, c-format msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits" @@ -14515,12 +14529,12 @@ msgstr "" #, c-format msgid "failed to parse commit %s from commit-graph" -msgstr "kunde inte tolka incheckning %s frÃ¥n incheckningsgraf" +msgstr "misslyckades tolka incheckningen %s frÃ¥n incheckningsgraf" #, c-format msgid "failed to parse commit %s from object database for commit-graph" msgstr "" -"misslyckades tolka incheckning %s frÃ¥n objektdatabasen för incheckningsgraf" +"misslyckades tolka incheckningen %s frÃ¥n objektdatabasen för incheckningsgraf" #, c-format msgid "root tree OID for commit %s in commit-graph is %s != %s" @@ -14563,6 +14577,10 @@ msgid "Verifying commits in commit graph" msgstr "Bekräftar incheckningar i incheckningsgrafen" #, c-format +msgid "could not parse commit %s" +msgstr "kunde inte tolka incheckningen %s" + +#, c-format msgid "%s %s is not a commit!" msgstr "%s %s är inte en incheckning!" @@ -14707,11 +14725,11 @@ msgstr "closedir('%s') misslyckades" #, c-format msgid "[GLE %ld] unable to open for read '%ls'" -msgstr "[GLE %ld] kunde inte öppna â€%ls†för läsning" +msgstr "[GLE %ld] kan inte öppna â€%ls†för läsning" #, c-format msgid "[GLE %ld] unable to get protocol information for '%ls'" -msgstr "[GLE %ld] kunde inte hämta protokollinformation för â€%lsâ€" +msgstr "[GLE %ld] kan inte hämta protokollinformation för â€%lsâ€" #, c-format msgid "failed to copy SID (%ld)" @@ -14990,8 +15008,13 @@ msgstr "förkortningslängd utanför intervallet: %d" msgid "bad zlib compression level %d" msgstr "felaktigt zlib-komprimeringsgrad %d" -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar kan bara vara ett ASCII-tecken" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s kan inte innehÃ¥lla nyradstecken" + +#, c-format +msgid "%s must have at least one character" +msgstr "%s mÃ¥ste innehÃ¥lla minst ett tecken" #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" @@ -15017,7 +15040,7 @@ msgstr "mÃ¥ste vara en av nothing, matching, simple, upstream eller current" #, c-format msgid "unable to load config blob object '%s'" -msgstr "kunde inte läsa konfigurerings-blobobjektet â€%sâ€" +msgstr "kan inte läsa konfigurerings-blobobjektet â€%sâ€" #, c-format msgid "reference '%s' does not point to a blob" @@ -15044,7 +15067,7 @@ msgstr "" #, c-format msgid "unable to parse '%s' from command-line config" -msgstr "kunde inte tolka värdet â€%s†frÃ¥n kommandoradskonfiguration" +msgstr "kan inte tolka värdet â€%s†frÃ¥n kommandoradskonfiguration" #, c-format msgid "bad config variable '%s' in file '%s' at line %d" @@ -15060,7 +15083,11 @@ msgstr "%s har flera värden" #, c-format msgid "failed to write new configuration file %s" -msgstr "kan inte skriva nya konfigurationsfilen â€%sâ€" +msgstr "misslyckades skriva nya konfigurationsfilen â€%sâ€" + +#, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "inga flerradiga kommentarer tillÃ¥tna: â€%sâ€" #, c-format msgid "could not lock config file %s" @@ -15080,7 +15107,7 @@ msgstr "fstat misslyckades pÃ¥ %s" #, c-format msgid "unable to mmap '%s'%s" -msgstr "kunde inte utföra mmap pÃ¥ â€%sâ€%s" +msgstr "kan inte utföra mmap pÃ¥ â€%sâ€%s" #, c-format msgid "chmod on %s failed" @@ -15178,7 +15205,7 @@ msgid "protocol '%s' is not supported" msgstr "protokollet â€%s†stöds inte" msgid "unable to set SO_KEEPALIVE on socket" -msgstr "kunde inte sätta SO_KEEPALIVE pÃ¥ uttaget" +msgstr "kan inte sätta SO_KEEPALIVE pÃ¥ uttaget" #, c-format msgid "Looking up %s ... " @@ -15202,7 +15229,7 @@ msgid "" "unable to connect to %s:\n" "%s" msgstr "" -"kunde inte ansluta till %s:\n" +"kan inte ansluta till %s:\n" "%s" #. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... " @@ -15211,7 +15238,7 @@ msgstr "klart." #, c-format msgid "unable to look up %s (%s)" -msgstr "kunde inte slÃ¥ upp %s (%s)" +msgstr "kan inte slÃ¥ upp %s (%s)" #, c-format msgid "unknown port %s" @@ -15249,16 +15276,16 @@ msgid "strange pathname '%s' blocked" msgstr "konstigt sökvägsnamn â€%s†blockerat" msgid "unable to fork" -msgstr "kunde inte grena (fork)" +msgstr "kan inte grena (fork)" msgid "Could not run 'git rev-list'" msgstr "Kunde inte köra â€git rev-listâ€" msgid "failed write to rev-list" -msgstr "kunde inte skriva till rev-list" +msgstr "misslyckades skriva till rev-list" msgid "failed to close rev-list's stdin" -msgstr "kunde inte stänga rev-list:s standard in" +msgstr "misslyckades stänga rev-list:s standard in" #, c-format msgid "illegal crlf_action %d" @@ -15320,7 +15347,7 @@ msgstr "omkodning av â€%s†frÃ¥n %s till %s och tillbaka ger inte samma resul #, c-format msgid "cannot fork to run external filter '%s'" -msgstr "kan inte grena (fork) för att köra externt filter â€%sâ€" +msgstr "kan inte grena (fork) av för att köra externt filter â€%sâ€" #, c-format msgid "cannot feed the input to external filter '%s'" @@ -15452,7 +15479,7 @@ msgstr "felaktigt trädobjektet %s" #, c-format msgid "failed to load island regex for '%s': %s" -msgstr "kunde inte hämta ö-regex för â€%sâ€: %s" +msgstr "misslyckades hämta ö-regex för â€%sâ€: %s" #, c-format msgid "island regex from config has too many capture groups (max=%d)" @@ -15615,7 +15642,7 @@ msgstr "okänt värde efter ws-error-highlight=%.*s" #, c-format msgid "unable to resolve '%s'" -msgstr "kunde inte slÃ¥ upp â€%sâ€" +msgstr "kan inte slÃ¥ upp â€%sâ€" #, c-format msgid "%s expects <n>/<m> form" @@ -15998,7 +16025,7 @@ msgstr "" #, c-format msgid "failed to read orderfile '%s'" -msgstr "kunde inte läsa orderfilen â€%sâ€" +msgstr "misslyckades läsa orderfilen â€%sâ€" msgid "Performing inexact rename detection" msgstr "Utför onöjaktig namnbytesdetektering" @@ -16098,7 +16125,7 @@ msgid "git fetch-pack: expected ACK/NAK, got '%s'" msgstr "git fetch-pack: förväntade ACK/NAK, fick â€%sâ€" msgid "unable to write to remote" -msgstr "kunde inte skriva till fjärren" +msgstr "kan inte skriva till fjärren" msgid "Server supports filter" msgstr "Servern stöder filter" @@ -16154,14 +16181,14 @@ msgid "already have %s (%s)" msgstr "har redan %s (%s)" msgid "fetch-pack: unable to fork off sideband demultiplexer" -msgstr "fetch-patch: kunde inte grena av sidbandsmultiplexare" +msgstr "fetch-patch: kan inte grena (fork) av sidbandsmultiplexare" msgid "protocol error: bad pack header" msgstr "protokollfel: felaktigt packhuvud" #, c-format msgid "fetch-pack: unable to fork off %s" -msgstr "fetch-patch: kunde inte grena av %s" +msgstr "fetch-patch: kan inte grena (fork) av %s" msgid "fetch-pack: invalid index-pack output" msgstr "fetch-patch: ogiltig utdata frÃ¥n index-pack" @@ -16214,7 +16241,7 @@ msgid "Server does not support shallow requests" msgstr "Servern stöder inte grunda förfrÃ¥gningar" msgid "unable to write request to remote" -msgstr "kunde inte skriva anrop till fjärren" +msgstr "kan inte skriva anrop till fjärren" #, c-format msgid "expected '%s', received '%s'" @@ -16516,7 +16543,7 @@ msgstr "" #, c-format msgid "'%s': unable to read %s" -msgstr "â€%s†kunde inte läsa %s" +msgstr "â€%sâ€: kan inte läsa %s" #, c-format msgid "'%s': short read" @@ -16747,14 +16774,14 @@ msgstr "ingen e-post angavs och autodetektering är inaktiverad" #, c-format msgid "unable to auto-detect email address (got '%s')" -msgstr "kunde inte autodetektera e-postadress (fick â€%sâ€)" +msgstr "kan inte autodetektera e-postadress (fick â€%sâ€)" msgid "no name was given and auto-detection is disabled" msgstr "inget namn angavs och autodetektering är inaktiverad" #, c-format msgid "unable to auto-detect name (got '%s')" -msgstr "kunde inte autodetektera namn (fick â€%sâ€)" +msgstr "kan inte autodetektera namn (fick â€%sâ€)" #, c-format msgid "empty ident name (for <%s>) not allowed" @@ -16789,7 +16816,7 @@ msgid "multiple filter-specs cannot be combined" msgstr "flera filterspecifikationer kan inte kombineras" msgid "unable to upgrade repository format to support partial clone" -msgstr "kunde inte uppgradera arkivformat till att stöda delvis klon" +msgstr "kan inte uppgradera arkivformat till att stöda delvis klon" msgid "args" msgstr "argument" @@ -16799,11 +16826,11 @@ msgstr "objektfiltrering" #, c-format msgid "unable to access sparse blob in '%s'" -msgstr "kunde inte nÃ¥ gles blob pÃ¥ â€%sâ€" +msgstr "kan inte nÃ¥ gles blob pÃ¥ â€%sâ€" #, c-format msgid "unable to parse sparse filter data in %s" -msgstr "kunde inte tolka gles filterdata i %s" +msgstr "kan inte tolka gles filterdata i %s" #, c-format msgid "entry '%s' in tree %s has tree mode, but is not a tree" @@ -16815,7 +16842,7 @@ msgstr "posten â€%s†i trädet %s har blob-läge, men är inte en blob" #, c-format msgid "unable to load root tree for commit %s" -msgstr "kunde inte läsa in rot-trädet för incheckningen %s" +msgstr "kan inte läsa in rot-trädet för incheckningen %s" #, c-format msgid "" @@ -16841,6 +16868,14 @@ msgid "Unable to create '%s.lock': %s" msgstr "Kunde inte skapa â€%s.lockâ€: %s" #, 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" + +#, c-format msgid "unexpected line: '%s'" msgstr "oväntad rad: â€%sâ€" @@ -16851,6 +16886,10 @@ msgid "quoted CRLF detected" msgstr "citerad CRLF upptäcktes" #, c-format +msgid "unable to format message: %s" +msgstr "kan inte formatera meddelandet: %s" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Misslyckades slÃ¥ ihop undermodulen %s (ej utcheckad)" @@ -16863,6 +16902,10 @@ 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)" + +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" "Misslyckades slÃ¥ ihop undermodulen %s (incheckningar följer inte " @@ -16895,7 +16938,7 @@ msgstr "misslyckades exekvera intern sammanslagning" #, c-format msgid "unable to add %s to database" -msgstr "kunde inte lägga till %s till databasen" +msgstr "kan inte lägga till %s till databasen" #, c-format msgid "Auto-merging %s" @@ -17329,6 +17372,82 @@ msgstr "Kunde inte tolka objektet â€%sâ€" msgid "failed to read the cache" msgstr "misslyckades läsa cachen" +#, c-format +msgid "failed to add packfile '%s'" +msgstr "misslyckades läsa paketfilen â€%sâ€" + +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "misslyckades öppna paketindexet â€%sâ€" + +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "misslyckades hitta objekt %d i paketfilen" + +msgid "cannot store reverse index file" +msgstr "kan inte spara reverse-index-fil" + +#, c-format +msgid "could not parse line: %s" +msgstr "kunde inte tolka rad: %s" + +#, c-format +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{" + +#, c-format +msgid "could not open index for %s" +msgstr "kunde inte öppna indexet för %s" + +msgid "Adding packfiles to multi-pack-index" +msgstr "Lägger till paketfiler till multi-pack-index" + +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "okänt föredraget paket: %s" + +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "kan inte välja föredraget paket %s som inte har nÃ¥gra objekt" + +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "sÃ¥g inte paketfilen %s som skulle kastas" + +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "föredraget paket â€%s†har löpt ut" + +msgid "no pack files to index." +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 "could not write multi-pack bitmap" +msgstr "kunde inte skriva fler-paketsbitkarta" + +msgid "could not write multi-pack-index" +msgstr "kunde inte skriva flerpakets-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 "could not start pack-objects" +msgstr "kunde inte starta pack-objects" + +msgid "could not finish pack-objects" +msgstr "kunde inte avsluta pack-objects" + msgid "multi-pack-index OID fanout is of the wrong size" msgstr "OID-utbredning för multi-pack-index har fel storlek" @@ -17402,70 +17521,6 @@ 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 add packfile '%s'" -msgstr "misslyckades läsa paketfilen â€%sâ€" - -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "misslyckades öppna paketindexet â€%sâ€" - -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "misslyckades hitta objekt %d i paketfilen" - -msgid "cannot store reverse index file" -msgstr "kan inte spara reverse-index-fil" - -#, c-format -msgid "could not parse line: %s" -msgstr "kunde inte tolka rad: %s" - -#, c-format -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{" - -#, c-format -msgid "could not open index for %s" -msgstr "kunde inte öppna indexet för %s" - -msgid "Adding packfiles to multi-pack-index" -msgstr "Lägger till paketfiler till multi-pack-index" - -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "okänt föredraget paket: %s" - -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "kan inte välja föredraget paket %s som inte har nÃ¥gra objekt" - -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "sÃ¥g inte paketfilen %s som skulle kastas" - -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "föredraget paket â€%s†har löpt ut" - -msgid "no pack files to index." -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 "could not write multi-pack bitmap" -msgstr "kunde inte skriva fler-paketsbitkarta" - -msgid "could not write multi-pack-index" -msgstr "kunde inte skriva flerpakets-index" - -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "misslyckades städa multi-pack-index pÃ¥ %s" @@ -17506,29 +17561,17 @@ msgstr "misslyckades läsa paketindex för paketfil %s" msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "felaktigt objekt-offset för oid[%d] = %s: %<PRIx64> != %<PRIx64>" -msgid "Counting referenced objects" -msgstr "Räknar refererade objekt" - -msgid "Finding and deleting unreferenced packfiles" -msgstr "Ser efter och tar bort orefererade packfiler" - -msgid "could not start pack-objects" -msgstr "kunde inte starta pack-objects" - -msgid "could not finish pack-objects" -msgstr "kunde inte avsluta pack-objects" - #, c-format msgid "unable to create lazy_dir thread: %s" -msgstr "misslyckades skapa lazy_dir-trÃ¥d: %s" +msgstr "kan inte skapa lazy_dir-trÃ¥d: %s" #, c-format msgid "unable to create lazy_name thread: %s" -msgstr "misslyckades skapa lazy_name-trÃ¥d: %s" +msgstr "kan inte skapa lazy_name-trÃ¥d: %s" #, c-format msgid "unable to join lazy_name thread: %s" -msgstr "misslyckades utföra join pÃ¥ lazy_name-trÃ¥d: %s" +msgstr "kan inte utföra join pÃ¥ lazy_name-trÃ¥d: %s" #, c-format msgid "" @@ -17564,13 +17607,32 @@ msgstr "Vägrar skriva över anteckningar i %s (utanför refs/notes/)" msgid "Bad %s value: '%s'" msgstr "Felaktigt värde pÃ¥ %s: â€%sâ€" +msgid "failed to decode tree entry" +msgstr "misslyckades avkoda trädposten" + +#, c-format +msgid "failed to map tree entry for %s" +msgstr "misslyckades koppla trädpost för %s" + +#, c-format +msgid "bad %s in commit" +msgstr "felaktig %s i incheckning" + +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "kan inte koppla %s %s i incheckningsobjekt" + +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Misslyckades konvertera objekt frÃ¥n %s till %s" + #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" msgstr "objektkatalogen %s finns inte; se .git/objects/info/alternates" #, c-format msgid "unable to normalize alternate object path: %s" -msgstr "kunde inte normalisera supplerande objektsökväg: %s" +msgstr "kan inte normalisera supplerande objektsökväg: %s" #, c-format msgid "%s: ignoring alternate object stores, nesting too deep" @@ -17665,8 +17727,12 @@ msgid "packed object %s (stored in %s) is corrupt" msgstr "packat objekt %s (lagrat i %s) är trasigt" #, c-format +msgid "missing mapping of %s to %s" +msgstr "saknar koppling av %s till %s" + +#, c-format msgid "unable to write file %s" -msgstr "kunde inte skriva filen %s" +msgstr "kan inte skriva filen %s" #, c-format msgid "unable to set permission to '%s'" @@ -17684,7 +17750,7 @@ msgid "unable to create temporary file" msgstr "kan inte skapa temporär fil" msgid "unable to write loose object file" -msgstr "kunde inte skriva fil för löst objekt" +msgstr "kan inte skriva fil för löst objekt" #, c-format msgid "unable to deflate new object %s (%d)" @@ -17712,13 +17778,17 @@ msgstr "â€deflatEend†pÃ¥ strömobjektet misslyckades (%d)" #, c-format msgid "unable to create directory %s" -msgstr "kunde inte skapa katalogen %s" +msgstr "kan inte skapa katalogen %s" #, c-format msgid "cannot read object for %s" msgstr "kan inte läsa objekt för %s" #, c-format +msgid "cannot map object %s to %s" +msgstr "kan inte koppla objektet %s till %s" + +#, c-format msgid "object fails fsck: %s" msgstr "objekt klarar inte fsck: %s" @@ -17935,7 +18005,7 @@ msgstr "objektet %s har okänd typ-id %d" #, c-format msgid "unable to parse object: %s" -msgstr "kunde inte tolka objektet: %s" +msgstr "kan inte tolka objektet: %s" #, c-format msgid "hash mismatch %s" @@ -18018,7 +18088,10 @@ msgstr "trasig ewah-bitkarta: avhugget huvud för bitkarta för incheckning â€% #, c-format msgid "unable to load pack: '%s', disabling pack-reuse" -msgstr "kunde inte läsa paketet: â€%sâ€, inaktiverar Ã¥teranvändning av paket" +msgstr "kan inte läsa paketet: â€%sâ€, inaktiverar Ã¥teranvändning av paket" + +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "kan inte beräkna föredraget paket, inaktiverar Ã¥teranvändning av paket" #, c-format msgid "object '%s' not found in type bitmaps" @@ -18123,7 +18196,7 @@ msgstr "kunde inte ta status: %s" #, c-format msgid "failed to make %s readable" -msgstr "kunde inte göra %s läsbar" +msgstr "misslyckades göra %s läsbar" #, c-format msgid "could not write '%s' promisor file" @@ -18285,7 +18358,7 @@ msgstr "felaktigt booleskt miljövariabelvärde â€%s†för â€%sâ€" #, c-format msgid "failed to parse %s" -msgstr "kunde inte tolka %s" +msgstr "misslyckades tolka %s" #, c-format msgid "Could not make %s writable by group" @@ -18364,7 +18437,7 @@ msgid "unable to write delim packet" msgstr "kan inte skriva delim-paket" msgid "unable to write response end packet" -msgstr "kunde inte skriva svarsavslutningspaket" +msgstr "kan inte skriva svarsavslutningspaket" msgid "flush packet write failed" msgstr "fel vid skrivning av â€flushâ€-paket" @@ -18405,16 +18478,16 @@ msgstr "Uppdaterar indexet" #, c-format msgid "unable to create threaded lstat: %s" -msgstr "kunde inte skapa trÃ¥dad lstat: %s" +msgstr "kan inte skapa trÃ¥dad lstat: %s" msgid "unable to parse --pretty format" -msgstr "kunde inte tolka format för --pretty" +msgstr "kan inte tolka format för --pretty" msgid "promisor-remote: unable to fork off fetch subprocess" -msgstr "promisor-remote: kunde inte starta (fork) underprocessen för fetch" +msgstr "promisor-remote: kan inte grena (fork) av underprocessen för fetch" msgid "promisor-remote: could not write to fetch subprocess" -msgstr "promisor-remote: kunde skriva till underprocessen för fetch" +msgstr "promisor-remote: kan skriva till underprocessen för fetch" msgid "promisor-remote: could not close stdin to fetch subprocess" msgstr "" @@ -18552,11 +18625,11 @@ msgstr "osorterade köposter för â€%sâ€" #, c-format msgid "unable to create load_cache_entries thread: %s" -msgstr "kunde inte skapa trÃ¥d för load_cache_entries: %s" +msgstr "kan inte skapa trÃ¥d för load_cache_entries: %s" #, c-format msgid "unable to join load_cache_entries thread: %s" -msgstr "kunde inte ansluta till trÃ¥den för load_cache_entries: %s" +msgstr "kan inte ansluta till trÃ¥den för load_cache_entries: %s" #, c-format msgid "%s: index file open failed" @@ -18576,11 +18649,11 @@ msgstr "%s: kan inte koppla indexfilen%s" #, c-format msgid "unable to create load_index_extensions thread: %s" -msgstr "kunde inte skapa load_index_extensions-trÃ¥den: %s" +msgstr "kan inte skapa load_index_extensions-trÃ¥den: %s" #, c-format msgid "unable to join load_index_extensions thread: %s" -msgstr "kunde inte utföra join pÃ¥ load_index_extensions-trÃ¥den: %s" +msgstr "kan inte utföra join pÃ¥ load_index_extensions-trÃ¥den: %s" #, c-format msgid "could not freshen shared index '%s'" @@ -18598,11 +18671,11 @@ msgstr "misslyckades omvandla till glest index" #, c-format msgid "unable to open git dir: %s" -msgstr "kunde inte öppna git-katalog: %s" +msgstr "kan inte öppna git-katalog: %s" #, c-format msgid "unable to unlink: %s" -msgstr "misslyckades ta bort länken: %s" +msgstr "kan inte ta bort länken: %s" #, c-format msgid "cannot fix permission bits on '%s'" @@ -19070,6 +19143,72 @@ msgid "could not delete references: %s" msgstr "kunde inte ta bort referenser: %s" #, c-format +msgid "refname is dangerous: %s" +msgstr "refnamnet är farligt: %s" + +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "försöker skriva referensen â€%s†med icke-existerande objektet %s" + +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "försöker skriva objektet %s som inte är incheckning till grenen â€%sâ€" + +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"flera uppdateringar för â€HEAD†(inklusive en via dess referent â€%sâ€) tillÃ¥ts " +"inte" + +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "kan inte lÃ¥sa referensen â€%sâ€: kan inte slÃ¥ upp referensen â€%sâ€" + +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "kan inte lÃ¥sa referensen â€%sâ€: fel vid läsning av referensen" + +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"flera uppdateringar för â€%s†(inklusive en via symrefen â€%sâ€) tillÃ¥ts inte" + +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "kan inte lÃ¥sa referensen â€%sâ€: referensen finns redan" + +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "kan inte lÃ¥sa referensen â€%sâ€: referensen saknas men förväntade %s" + +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "kan inte lÃ¥sa referensen â€%sâ€: är vid %s men förväntade %s" + +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "referenstabell: förbereder transaktion: %s" + +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "referenstabell: transaktionen misslyckades: %s" + +#, c-format +msgid "unable to compact stack: %s" +msgstr "kan inte kompaktera stack: %s" + +#, c-format +msgid "refname %s not found" +msgstr "referensnamnet %s hittades inte" + +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "referensnamnet %s är en symbolisk referens, kopiering stöds inte" + +#, c-format msgid "invalid refspec '%s'" msgstr "felaktig referensspecifikation: â€%sâ€" @@ -19078,6 +19217,10 @@ msgid "invalid quoting in push-option value: '%s'" msgstr "felaktig citering pÃ¥ värde för push-option: â€%sâ€" #, c-format +msgid "unknown value for object-format: %s" +msgstr "okänt värde för object-format: %s" + +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs inte giltig: är detta ett git-arkiv?" @@ -19115,7 +19258,7 @@ msgid "remote server sent unexpected response end packet" msgstr "fjärrservern sände oväntat svarsavslutningspaketet" msgid "unable to rewind rpc post data - try increasing http.postBuffer" -msgstr "kunde inte spola tillbaka rpc-postdata - försök öka http.postBuffer" +msgstr "kan inte spola tillbaka rpc-postdata - försök öka http.postBuffer" #, c-format msgid "remote-curl: bad line length character: %.4s" @@ -19350,7 +19493,7 @@ msgstr "â€enkel push†motsvarar flera olika mÃ¥l" #, c-format msgid "couldn't find remote ref %s" -msgstr "Kunde inte hitta fjärr-referensen %s" +msgstr "kunde inte hitta fjärr-referensen %s" #, c-format msgid "* Ignoring funny ref '%s' locally" @@ -19438,7 +19581,7 @@ msgid "corrupt MERGE_RR" msgstr "trasig MERGE_RR" msgid "unable to write rerere record" -msgstr "kunde inte skriva rerere-post" +msgstr "kan inte skriva rerere-post" #, c-format msgid "there were errors while writing '%s' (%s)" @@ -19503,7 +19646,7 @@ msgstr "kunde inte bestämma HEAD-revision" #, c-format msgid "failed to find tree of %s" -msgstr "kunde inte hitta trädet för %s." +msgstr "misslyckades hitta trädet för %s." #, c-format msgid "unsupported section for hidden refs: %s" @@ -19517,15 +19660,26 @@ msgid "resolve-undo records `%s` which is missing" msgstr "resolve-undo registrerar â€%s†som saknas" #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "kunde inte hämta incheckning för â€ancestry-pathâ€-argumentet %s" +msgid "%s exists but is a symbolic ref" +msgstr "%s finns men är en symbolisk referens" + +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge kräver en av pseudoreferenserna MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD eller REBASE_HEAD" + +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "kunde inte hämta incheckning för â€--ancestry-pathâ€-argumentet %s" msgid "--unpacked=<packfile> no longer supported" msgstr "--unpacked=<paketfil> stöds inte längre" #, c-format msgid "invalid option '%s' in --stdin mode" -msgstr "ogiltig flagga â€%s†i --stdin-läge" +msgstr "ogiltig flagga â€%s†i â€--stdinâ€-läge" msgid "your current branch appears to be broken" msgstr "din nuvarande gren verkar vara trasig" @@ -19747,7 +19901,7 @@ msgstr "oväntat flush-paket vid läsning av fjärruppackningsstatus" #, c-format msgid "unable to parse remote unpack status: %s" -msgstr "kunde inte tolka fjärruppackningsstatus: %s" +msgstr "kan inte tolka fjärruppackningsstatus: %s" #, c-format msgid "remote unpack failed: %s" @@ -19757,7 +19911,7 @@ msgid "failed to sign the push certificate" msgstr "misslyckades underteckna push-certifikatet" msgid "send-pack: unable to fork off fetch subprocess" -msgstr "send-pack: kunde inte starta (fork) underprocessen för fetch" +msgstr "send-pack: kan inte grena (fork) av underprocessen för fetch" msgid "push negotiation failed; proceeding anyway with push" msgstr "sänd-förhandling misslyckades; fortsätter ändÃ¥ med sändningen" @@ -19803,6 +19957,19 @@ msgid "unknown action: %d" msgstr "okänd funktion: %d" 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 "" +"Lös alla konflikter manuellt, märk dem som lösta med\n" +"â€git add/rm <filer_i_konflikt>â€, kör sedan â€git rebase --continueâ€.\n" +"Du kan hoppa över incheckningen istället: kör â€git rebase --skipâ€.\n" +"För att avbryta och Ã¥tergÃ¥ till där du var före ombaseringen, kör â€git " +"rebase --abortâ€." + +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -19989,7 +20156,7 @@ msgid "could not parse newly created commit" msgstr "kunde inte tolka en precis skapad incheckning" msgid "unable to resolve HEAD after creating commit" -msgstr "kunde inte bestämma HEAD efter att ha skapat incheckning" +msgstr "kan inte bestämma HEAD efter att ha skapat incheckning" msgid "detached HEAD" msgstr "frÃ¥nkopplad HEAD" @@ -20005,11 +20172,11 @@ msgid "HEAD %s is not a commit!" msgstr "HEAD %s är inte en incheckning!" msgid "unable to parse commit author" -msgstr "kunde inte tolka incheckningens författare" +msgstr "kan inte tolka incheckningens författare" #, c-format msgid "unable to read commit message from '%s'" -msgstr "kunde inte läsa incheckningsmeddelande frÃ¥n â€%sâ€" +msgstr "kan inte läsa incheckningsmeddelande frÃ¥n â€%sâ€" #, c-format msgid "invalid author identity '%s'" @@ -20023,10 +20190,6 @@ msgid "could not update %s" msgstr "kunde inte uppdatera %s" #, c-format -msgid "could not parse commit %s" -msgstr "kunde inte tolka incheckningen %s" - -#, c-format msgid "could not parse parent commit %s" msgstr "kunde inte tolka föräldraincheckningen %s" @@ -20130,10 +20293,6 @@ msgid "invalid command '%.*s'" msgstr "ogiltigt kommando â€%.*sâ€" #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s tar inte argument: â€%sâ€" - -#, c-format msgid "missing arguments for %s" msgstr "argument saknas för %s" @@ -20231,7 +20390,7 @@ msgid "no cherry-pick in progress" msgstr "ingen â€cherry-pick†pÃ¥gÃ¥r" msgid "failed to skip the commit" -msgstr "kunde inte hoppa över incheckningen" +msgstr "misslyckades hoppa över incheckningen" msgid "there is nothing to skip" msgstr "ingenting att hoppa över" @@ -20588,6 +20747,10 @@ msgid "unable to set up work tree using invalid config" msgstr "kan inte skapa arbetskatalog med felaktig konfiguration" #, c-format +msgid "'%s' already specified as '%s'" +msgstr "â€%s†har redan angivits som â€%sâ€" + +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "Förväntade git-arkivversion <= %d, hittade %d" @@ -20776,6 +20939,21 @@ msgstr "indexposten är en katalog, men inte gles (%08x)" msgid "cannot use split index with a sparse index" msgstr "kan inte dela indexet med ett glest index" +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "felaktigt %s-format: elementet â€%s†börjar inte med â€(â€" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "felaktigt %s-format: elementet â€%s†slutar inte med â€)â€" + +#. TRANSLATORS: %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "felaktigt %s-format: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #, c-format msgid "%u.%2.2u GiB" @@ -20833,11 +21011,11 @@ msgstr "ignorerar â€%s†som kan tolkas som en kommandoradsflagga: %s" #, c-format msgid "Could not update .gitmodules entry %s" -msgstr "Kunde inte uppdatera .gitmodules-posten %s" +msgstr "Kunde inte uppdatera â€.gitmodulesâ€-posten %s" msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" msgstr "" -"Kan inte ändra .gitmodules-fil som inte slagits ihop, lös " +"Kan inte ändra â€.gitmodulesâ€-fil som inte slagits ihop, lös " "sammanslagningskonflikter först" #, c-format @@ -20846,7 +21024,7 @@ msgstr "Hittade inte nÃ¥gon sektion i .gitmodules där sökväg=%s" #, c-format msgid "Could not remove .gitmodules entry for %s" -msgstr "Kunde inte ta bort .gitmodules-posten för %s" +msgstr "Kunde inte ta bort â€.gitmodulesâ€-posten för %s" msgid "staging updated .gitmodules failed" msgstr "misslyckades köa uppdaterad .gitmodules" @@ -20909,7 +21087,7 @@ msgstr "Kunde inte komma Ã¥t undermodulen â€%s†vid incheckningen %s\n" #, c-format msgid "Fetching submodule %s%s at commit %s\n" -msgstr "Hämtar undermodulen %s%s vvid incheckningen %s\n" +msgstr "Hämtar undermodulen %s%s vid incheckningen %s\n" #, c-format msgid "" @@ -21098,29 +21276,6 @@ msgstr "okänt värde â€%s†för nyckeln â€%sâ€" msgid "empty trailer token in trailer '%.*s'" msgstr "tom släpradssymbol i släpraden â€%.*sâ€" -#, c-format -msgid "could not read input file '%s'" -msgstr "kunde inte läsa indatafilen â€%sâ€" - -#, c-format -msgid "could not stat %s" -msgstr "kunde inte ta status pÃ¥ %s" - -#, c-format -msgid "file %s is not a regular file" -msgstr "filen %s är inte en normal fil" - -#, c-format -msgid "file %s is not writable by user" -msgstr "filen %s är inte skrivbar av användaren" - -msgid "could not open temporary file" -msgstr "kunde inte öppna temporär fil" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "kunde inte byta namn pÃ¥ temporär fil till %s" - msgid "full write to remote helper failed" msgstr "komplett skrivning till fjärrhjälpare misslyckades" @@ -21218,8 +21373,8 @@ msgid "remote-helper doesn't support push; refspec needed" msgstr "fjärrhjälparen stöder inte push; referensspecifikation krävs" #, c-format -msgid "helper %s does not support 'force'" -msgstr "hjälparen %s stöder inte â€forceâ€" +msgid "helper %s does not support '--force'" +msgstr "hjälparen %s stöder inte â€--forceâ€" msgid "couldn't run fast-export" msgstr "kunde inte köra fast-export" @@ -21346,7 +21501,7 @@ msgid "Aborting." msgstr "Avbryter." msgid "failed to push all needed submodules" -msgstr "kunde inte sända alla nödvändiga undermoduler" +msgstr "misslyckades sända alla nödvändiga undermoduler" msgid "bundle-uri operation not supported by protocol" msgstr "bundle-uri-funktionen stöds inte av protokollet" @@ -21636,6 +21791,10 @@ msgstr "felaktigt portnummer" msgid "invalid '..' path segment" msgstr "felaktigt â€..â€-sökvägssegment" +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "fel: kan inte formatera meddelande: %s\n" + msgid "usage: " msgstr "användning: " @@ -21683,13 +21842,13 @@ msgid "not a valid path" msgstr "inte en giltig sökväg" msgid "unable to locate repository; .git is not a file" -msgstr "hittar inte arkivet; .git är inte en fil" +msgstr "kan inte hitta arkivet; .git är inte en fil" msgid "unable to locate repository; .git file does not reference a repository" -msgstr "hittar inte arkivet; .git-filen hänvisar inte till ett arkiv" +msgstr "kan inte hitta arkivet; â€.gitâ€-filen hänvisar inte till ett arkiv" msgid "unable to locate repository; .git file broken" -msgstr "hittar inte arkivet; .git-filen är trasig" +msgstr "kan inte hitta arkivet; â€.gitâ€-filen är trasig" msgid "gitdir unreadable" msgstr "gitdir är oläsbar" @@ -21701,21 +21860,21 @@ msgid "not a valid directory" msgstr "inte i en giltig katalog" msgid "gitdir file does not exist" -msgstr "gitdir-filen existerar inte" +msgstr "â€gitdirâ€-filen existerar inte" #, c-format msgid "unable to read gitdir file (%s)" -msgstr "kunde inte läsa gitdir-filen (%s)" +msgstr "kan inte läsa â€gitdirâ€-filen (%s)" #, c-format msgid "short read (expected %<PRIuMAX> bytes, read %<PRIuMAX>)" msgstr "kort läsning (förväntade %<PRIuMAX> byte, läste %<PRIuMAX>)" msgid "invalid gitdir file" -msgstr "ogiltig gitdir-fil" +msgstr "ogiltig â€gitdirâ€-fil" msgid "gitdir file points to non-existent location" -msgstr "gitdir-filen pekar pÃ¥ en ickeexisterande plats" +msgstr "â€gitdirâ€-filen pekar pÃ¥ en ickeexisterande plats" #, c-format msgid "unable to set %s in '%s'" @@ -21734,7 +21893,7 @@ msgstr "kunde inte lagra miljövariabeln â€%sâ€" #, c-format msgid "unable to create '%s'" -msgstr "kunde inte skapa â€%sâ€" +msgstr "kan inte skapa â€%sâ€" #, c-format msgid "could not open '%s' for reading and writing" @@ -21748,7 +21907,7 @@ msgid "unable to get current working directory" msgstr "kan inte hämta aktuell arbetskatalog" msgid "unable to get random bytes" -msgstr "kunde inte hämta slumpdata" +msgstr "kan inte hämta slumpdata" msgid "Unmerged paths:" msgstr "Ej sammanslagna sökvägar:" @@ -22222,7 +22381,7 @@ msgstr "använd: $dashless $USAGE" #, sh-format msgid "Cannot chdir to $cdup, the toplevel of the working tree" -msgstr "Kunde inte byta katalog till $cdup, toppnivÃ¥n pÃ¥ arbetskatalogen" +msgstr "Kan inte byta katalog till $cdup, toppnivÃ¥n pÃ¥ arbetskatalogen" #, sh-format msgid "fatal: $program_name cannot be used without a working tree." @@ -22352,7 +22511,7 @@ msgstr "Ingen ärenderad i %s?" #, perl-format msgid "Failed to open for writing %s: %s" -msgstr "Kunde inte öppna för skrivning %s: %s" +msgstr "Misslyckades öppna för skrivning %s: %s" msgid "" "Lines beginning in \"GIT:\" will be removed.\n" @@ -22417,7 +22576,7 @@ msgstr "" #, perl-format msgid "error: unable to extract a valid address from: %s\n" -msgstr "fel: kunde inte fÃ¥ fram en giltig adress frÃ¥n: %s\n" +msgstr "fel: kan inte fÃ¥ fram en giltig adress frÃ¥n: %s\n" #. TRANSLATORS: Make sure to include [q] [d] [e] in your #. translation. The program will only accept English input @@ -22555,7 +22714,7 @@ msgstr "" #, perl-format msgid "unable to open %s: %s\n" -msgstr "kunde inte öppna %s: %s\n" +msgstr "kan inte öppna %s: %s\n" #, perl-format msgid "" @@ -20,7 +20,7 @@ # clone | klon(lamak) # # commit (ad) | iÅŸleme # # commit (eyl.) | iÅŸlemek # -# commitish | iÅŸlememsi # +# commit-ish | iÅŸlememsi # # conflict | çakışma # # cruft | süprüntü # # dangling object | sallanan nesne # @@ -49,8 +49,8 @@ # pathspec | yol belirteci # # pattern | dizgi # # porcelain | okunabilir # -# prune | buda(mak) # -# pseudoref | yalancıktan baÅŸvuru # +# prune | buda(mak) # +# pseudoref | yalancı baÅŸvuru # # pull | çek(mek) # # push | it(mek) # # rebase | yeniden temellendirme(k) # @@ -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-02-16 22:04+0300\n" -"PO-Revision-Date: 2024-02-16 22:00+0300\n" +"POT-Creation-Date: 2024-04-29 01:09+0300\n" +"PO-Revision-Date: 2024-04-29 01:10+0300\n" "Last-Translator: Emir SARI <emir_sari@icloud.com>\n" "Language-Team: Turkish (https://github.com/bitigchi/git-po/)\n" "Language: tr\n" @@ -580,12 +580,12 @@ 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" "'%c' satır kaldırmak için onları ' ' satır yapın (baÄŸlam).\n" "'%c' satır kaldırmak için onları silin.\n" -"%c kaldırılacak.\n" +"%s ile baÅŸlayan satırlar kaldırılacak.\n" msgid "" "If it does not apply cleanly, you will be given an opportunity to\n" @@ -632,6 +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" "? - print help\n" msgstr "" "j - bu parça için sonra karar ver, bir sonraki karar verilmemiÅŸ parçayı gör\n" @@ -642,6 +643,7 @@ msgstr "" "/ - 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" "? - yardımı yazdır\n" msgid "No previous hunk" @@ -704,8 +706,8 @@ msgstr "" "Bu iletiyi \"git config advice.%s false\" ile devre dışı bırakın" #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sipucu: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sipucu: %s%.*s%s\n" msgid "Cherry-picking is not possible because you have unmerged files." msgstr "Seç-al yapılamaz; birleÅŸtirmesi tamamlanmamış dosyalarınız var." @@ -1203,10 +1205,6 @@ msgstr[0] "%%s yaması %d geri çevirme ile uygulanıyor..." msgstr[1] "%%s yaması %d geri çevirme ile uygulanıyor..." #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr ".rej dosya adı %.*s.rej olarak kısaltılıyor" - -#, c-format msgid "cannot open %s" msgstr "%s açılamıyor" @@ -1627,6 +1625,10 @@ msgid "could not create file '%s'" msgstr "'%s' dosyası oluÅŸturulamadı" #, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "'%s' nesnesi için 'show' baÅŸlatılamıyor" + +#, c-format msgid "could not read file '%s'" msgstr "'%s' dosyası okunamadı" @@ -1778,6 +1780,9 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "'%s' geçerli bir dal adı deÄŸil" +msgid "See `man git check-ref-format`" +msgstr "'man git check-ref-format' kılavuz sayfasına bakın" + #, c-format msgid "a branch named '%s' already exists" msgstr "'%s' adında bir dal halihazırda var" @@ -1973,14 +1978,8 @@ msgstr "" msgid "adding embedded git repository: %s" msgstr "gömülü git deposu ekleniyor: %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 "" -"Gerçekten eklemek istiyorsanız -f kullanın.\n" -"Bu iletiyi 'git config advice.addIgnoredFile false'\n" -"yaparak kapatabilirsiniz" +msgid "Use -f if you really want to add them." +msgstr "Onları gerçekten eklemek istiyorsanız -f kullanın." msgid "adding files failed" msgstr "dosya ekleme baÅŸarısız" @@ -1997,14 +1996,8 @@ msgstr "'%s' ve yol belirteci argümanları birlikte kullanılamaz" msgid "Nothing specified, nothing added.\n" msgstr "Hiçbir ÅŸey belirtilmedi, hiçbir ÅŸey eklenmedi.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"'git add .' mı demek istediniz?\n" -"Bu iletiyi 'git config advice.addEmptyPathspec false'\n" -"yaparak kapatabilirsiniz" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "'git add .' mi demek istediniz?" msgid "index file corrupt" msgstr "indeks dosyası hasarlı" @@ -2081,24 +2074,25 @@ msgid "Failed to split patches." msgstr "Yamalar parçalanıp bölünemedi." #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "Bu sorunu çözdüğünüzde \"%s --continue\" çalıştırın." +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "Bu sorunu çözdüğünüzde \"%s --continue\" çalıştırın.\n" #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "EÄŸer bu yamayı atlamayı yeÄŸliyorsanız \"%s --skip\" çalıştırın." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "EÄŸer bu yamayı atlamayı yeÄŸliyorsanız \"%s --skip\" çalıştırın.\n" #, 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 "" "BoÅŸ yamayı boÅŸ iÅŸleme kaydı olarak yazmak için \"%s --allow-empty\" " -"çalıştırın." +"çalıştırın.\n" #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." msgstr "" "Ä°lk dalı eski durumuna getirip yamalamayı durdurmak için \"%s --abort\" " -"çalıştır." +"çalıştırın." msgid "Patch sent with format=flowed; space at the end of lines might be lost." msgstr "" @@ -2941,11 +2935,11 @@ msgstr "dal kopyalandı; ancak config-file güncellenemedi" 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 "" -"Lütfen dal açıklamasını düzenleyin:\n" +"Lütfen dal açıklamasını düzenleyin\n" "\t%s\n" -"'%c' ile baÅŸlayan satırlar çıkarılacaktır.\n" +"'%s' ile baÅŸlayan satırlar soyulacaktır.\n" msgid "Generic options" msgstr "Genel seçenekler" @@ -3146,10 +3140,12 @@ msgid "not run from a git repository - no hooks to show\n" msgstr "bir git deposundan çalıştırılmadı - gösterilecek kanca yok\n" 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) <yol>] [(-s | --suffix) <biçim>]\n" +"git bugreport [(-o | --output-directory) <yol>]\n" +" [(-s | --suffix) <biçim> | --no-suffix]\n" " [--diagnose[=<kip>]]" msgid "" @@ -3630,6 +3626,10 @@ msgstr "'%s', '%s' veya '%s' bir aÄŸaçtan çıkış yaparken kullanılamaz" msgid "path '%s' is unmerged" msgstr "'%s' yolu birleÅŸtirilmemiÅŸ" +#, c-format +msgid "unable to read tree (%s)" +msgstr "aÄŸaç okunamıyor (%s)" + msgid "you need to resolve your current index first" msgstr "önce geçerli indeksinizi çözmelisiniz" @@ -3859,6 +3859,10 @@ msgstr "Dal, iÅŸleme olmayan '%s' ögesine deÄŸiÅŸtirilemez" msgid "missing branch or commit argument" msgstr "dal veya iÅŸleme argümanı eksik" +#, c-format +msgid "unknown conflict style '%s'" +msgstr "bilinmeyen çakışma stili '%s'" + msgid "perform a 3-way merge with the new branch" msgstr "yeni dal ile bir 3 yönlü birleÅŸtirme gerçekleÅŸtir" @@ -4115,19 +4119,10 @@ msgstr "yok sayılan dosyalar da kaldırıldı" msgid "remove only ignored files" msgstr "yalnızca yok sayılan dosyaları kaldır" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" +msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"clean.requireForce 'true' olarak ayarlanmış ve ne -i ne -n ne de -f " -"verilmiÅŸ; temizleme reddediliyor" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" -msgstr "" -"clean.requireForce öntanımlı olarak 'true' ve ne -i ne -n ne de -f verilmiÅŸ; " -"temizleme reddediliyor" +"clean.requireForce 'true' olarak ayarlı ve -f verilmedi; temizlik " +"reddediliyor" msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [<seçenekler>] [--] <depo> [<dizin>]" @@ -4141,8 +4136,8 @@ msgstr "çıkış yapma!" msgid "create a bare repository" msgstr "çıplak bir depo oluÅŸtur" -msgid "create a mirror repository (implies bare)" -msgstr "bir yansı depo oluÅŸtur (çıplak ima eder)" +msgid "create a mirror repository (implies --bare)" +msgstr "bir yansı depo oluÅŸtur (--bare ima eder)" msgid "to clone from a local repository" msgstr "bir yerel depodan klonla" @@ -4262,7 +4257,7 @@ msgstr "%s var ve bir dizin deÄŸil" #, c-format msgid "'%s' is a symlink, refusing to clone with --local" -msgstr "'%s' bir sembolik baÄŸlantı; --local ile klonlama reddediliyor" +msgstr "'%s' bir sembolik baÄŸ; --local ile klonlama reddediliyor" #, c-format msgid "failed to start iterator over '%s'" @@ -4270,7 +4265,7 @@ msgstr "yineleyici '%s' üzerinden çalıştırılamadı" #, c-format msgid "symlink '%s' exists, refusing to clone with --local" -msgstr "'%s' sembolik baÄŸlantısı var, --local ile klonlama reddediliyor" +msgstr "'%s' sembolik bağı var, --local ile klonlama reddediliyor" #, c-format msgid "failed to unlink '%s'" @@ -4452,6 +4447,10 @@ msgstr "saÄŸ kenardaki dolgu boÅŸluÄŸu" msgid "padding space between columns" msgstr "sütunlar arasındaki dolgu boÅŸluÄŸu" +#, c-format +msgid "%s must be non-negative" +msgstr "%s negatif dışı bir deÄŸer olmalı" + msgid "--command must be the first argument" msgstr "--command ilk argüman olmalı" @@ -4765,34 +4764,34 @@ msgstr "iÅŸleme ÅŸablonu yazılamadı" #, 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 "" -"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%c' ile baÅŸlayan\n" +"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%s' ile baÅŸlayan\n" "satırlar yok sayılacaktır.\n" #, 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 "" -"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%c' ile baÅŸlayan\n" +"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%s' ile baÅŸlayan\n" "satırlar yok sayılacaktır. BoÅŸ bir ileti iÅŸlemeyi iptal eder.\n" #, 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 "" -"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%c' ile baÅŸlayan\n" +"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%s' ile baÅŸlayan\n" "satırlar tutulacaktır; isterseniz onları kaldırabilirsiniz.\n" #, 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 "" -"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%c' ile baÅŸlayan\n" +"Lütfen deÄŸiÅŸiklikleriniz için bir iÅŸleme iletisi girin. '%s' ile baÅŸlayan\n" "satırlar tutulacaktır; isterseniz onları kaldırabilirsiniz.\n" "BoÅŸ bir ileti iÅŸlemeyi iptal eder.\n" @@ -5241,6 +5240,9 @@ msgstr "deÄŸer" msgid "with --get, use default value when missing entry" msgstr "--get ile girdi verilmemiÅŸse öntanımlı deÄŸeri kullan" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "kiÅŸi tarafından okunabilir yorum satırı (gerekirse önüne # koyulur)" + #, c-format msgid "wrong number of arguments, should be %d" msgstr "yanlış argüman sayısı, %d olmalı" @@ -5332,7 +5334,10 @@ msgstr "" "ve --list" msgid "--default is only applicable to --get" -msgstr "--default yalnızca ÅŸuna uygulanabilir: --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 "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value yalnızca 'deÄŸer-dizgisi' ile uygulanır" @@ -6174,6 +6179,9 @@ msgstr "yalnızca iÅŸlemeyi içermeyen baÅŸvuruları yazdır" msgid "read reference patterns from stdin" msgstr "baÅŸvuru dizgilerini stdin'den oku" +msgid "also include HEAD ref and pseudorefs" +msgstr "ayrıca HEAD ve yalancı baÅŸvuruları içer" + msgid "unknown arguments supplied with --stdin" msgstr "--stdin ile bilinmeyen argümanlar verilmiÅŸ" @@ -6786,10 +6794,6 @@ msgid "no threads support, ignoring %s" msgstr "iÅŸ parçacığı desteÄŸi yok, %s yok sayılıyor" #, c-format -msgid "unable to read tree (%s)" -msgstr "aÄŸaç okunamıyor (%s)" - -#, c-format msgid "unable to read tree %s" msgstr "%s aÄŸacı okunamıyor" @@ -7395,14 +7399,39 @@ msgstr "--separate-git-dir, çıplak depo ile uyumsuz" 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 (<anahtar>|<anArması>)" -"[(=|:)<deÄŸer>])...]\n" +" [(--trailer (<anahtar>|<arma>)[(=|:)<deÄŸer>])...]\n" " [--parse] [<dosya>...]" +#, c-format +msgid "could not stat %s" +msgstr "%s dosya bilgileri alınamadı" + +#, c-format +msgid "file %s is not a regular file" +msgstr "%s dosyası sıradan bir dosya deÄŸil" + +#, c-format +msgid "file %s is not writable by user" +msgstr "%s dosyası kullanıcı tarafından yazılabilir deÄŸil" + +msgid "could not open temporary file" +msgstr "geçici dosya açılamadı" + +#, c-format +msgid "could not read input file '%s'" +msgstr "'%s' girdi dosyası okunamadı" + +msgid "could not read from stdin" +msgstr "stdin'den okunamadı" + +#, c-format +msgid "could not rename temporary file to %s" +msgstr "geçici dosya adı %s olarak deÄŸiÅŸtirilemedi" + msgid "edit files in place" msgstr "dosyaları yerinde düzenle" @@ -7788,18 +7817,6 @@ msgstr "Ä°zlenen bir uzak dal bulunamadı, lütfen el ile <üstkaynak> belirtin. msgid "could not get object info about '%s'" msgstr "'%s' hakkında nesne bilgisi alınamadı" -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "hatalı ls-files biçimi: '%s' ögesi, '(' ile baÅŸlamıyor" - -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "hatalı ls-files biçimi: '%s' ögesi, ')' ile sonlanmıyor" - -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "hatalı ls-files biçimi: %%%.*s" - msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<seçenekler>] [<dosya>...]" @@ -7930,18 +7947,6 @@ msgstr "iÅŸaret ettiÄŸi nesneye ek olarak altında yatan baÅŸvuruyu göster" msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<seçenekler>] <aÄŸacımsı> [<yol>...]" -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "hatalı ls-tree biçimi: '%s' ögesi '(' ile baÅŸlamıyor" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "hatalı ls-tree biçimi: '%s' ögesi ')' ile sonlanmıyor" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "hatalı ls-tree biçimi: %%%.*s" - msgid "only show trees" msgstr "yalnızca aÄŸaçları göster" @@ -8128,6 +8133,10 @@ msgstr "'%s' baÅŸvurusu çözülemedi" msgid "Merging %s with %s\n" msgstr "%s, %s ile birleÅŸtiriliyor\n" +#, c-format +msgid "could not parse as tree '%s'" +msgstr "'%s' aÄŸacı olarak ayrıştırılamadı" + msgid "not something we can merge" msgstr "birleÅŸtirebileceÄŸimiz bir ÅŸey deÄŸil" @@ -8330,10 +8339,10 @@ msgstr "BoÅŸ bir ileti iÅŸlemeyi iptal eder.\n" #, 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 "" -"'%c' ile baÅŸlayan satırlar yok sayılacaktır. BoÅŸ bir ileti iÅŸlemeyi\n" +"'%s' ile baÅŸlayan satırlar yok sayılacaktır. BoÅŸ bir ileti iÅŸlemeyi\n" "iptal eder.\n" msgid "Empty commit message." @@ -8490,9 +8499,6 @@ msgstr "etiketlenmiÅŸ nesne '%s' okunamadı" msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "'%s' nesnesi '%s' olarak etiketlenmiÅŸ; ancak bir '%s' türü" -msgid "could not read from stdin" -msgstr "stdin'den okunamadı" - msgid "tag on stdin did not pass our strict fsck check" msgstr "stdin üzerindeki etiket bizim sıkı fsck denetimimizi geçemedi" @@ -8753,10 +8759,6 @@ msgstr "git notes prune [<seçenekler>]" msgid "Write/edit the notes for the following object:" msgstr "AÅŸağıdaki nesneler için not yaz/düzenle:" -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "'%s' nesnesi için 'show' baÅŸlatılamıyor" - msgid "could not read 'show' output" msgstr "'show' çıktısı okunamadı" @@ -9383,11 +9385,11 @@ msgid "refusing to run without --i-still-use-this" msgstr "--i-still-use-this olmadan çalıştırma reddediliyor" 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]git pack-refs [--all] [--no-prune] [--" -"include <dizgi>] [--exclude <dizgi>]" +"git pack-refs [--all] [--no-prune] [--auto] [--include <dizgi>] [--exclude " +"<dizgi>]" msgid "pack everything" msgstr "her ÅŸeyi paketle" @@ -9395,6 +9397,9 @@ msgstr "her ÅŸeyi paketle" msgid "prune loose refs (default)" msgstr "gevÅŸek baÅŸvuruları buda (öntanımlı)" +msgid "auto-pack refs as needed" +msgstr "gerekirse baÅŸvuruları paketle" + msgid "references to include" msgstr "içerilecek baÅŸvurular" @@ -10047,19 +10052,6 @@ msgstr "geçersiz allow_rerere_autoupdate yok sayılıyor: '%s'" msgid "could not remove '%s'" msgstr "'%s' kaldırılamadı" -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 "" -"Tüm çakışmaları el ile çözün, onları \"git add/rm <çakışan-dosyalar>\"\n" -"ile tamam olarak imleyin, ardından \"git rebase --continue\"\n" -"çalıştırın. Bunun yerine bu iÅŸlemeyi atlayabilirsiniz: \"git rebase\n" -"--skip\" yapın. Ä°ptal edip \"git rebase\" öncesine geri dönmek için\n" -"\"git rebase --abort\" çalıştırın." - #, c-format msgid "" "\n" @@ -10089,12 +10081,15 @@ msgstr "ÅŸuraya geçilemedi: %s" msgid "apply options and merge options cannot be used together" msgstr "uygulama seçenekleri ve birleÅŸtirme seçenekleri birlikte kullanılamaz" +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask artık kullanılmıyor; yerine '--empty=stop' kullanın." + #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." +"\"stop\"." msgstr "" -"Tanımlanamayan boÅŸ tür '%s'; geçerli türler: \"drop\", \"keep\" ve \"ask\"." +"Tanımlanamayan boÅŸ tür '%s'; geçerli türler: \"drop\", \"keep\" ve \"stop\"." msgid "" "--rebase-merges with an empty string argument is deprecated and will stop " @@ -10278,8 +10273,8 @@ msgstr "" "Not: `pull.rebase` yapılandırmanız, artık desteklenmeyen'\n" "'preserve' olarak ayarlı olabilir; yerine 'merges' kullanın" -msgid "No rebase in progress?" -msgstr "Sürmekte olan bir yeniden temellendirme yok" +msgid "no rebase in progress" +msgstr "sürmekte olan yeniden temellendirme yok" msgid "The --edit-todo action can only be used during interactive rebase." msgstr "" @@ -10475,6 +10470,9 @@ msgstr "bir dizin belirtmelisiniz" msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<günlük-seçenekleri>] [<baÅŸvuru>]" +msgid "git reflog list" +msgstr "git reflog list" + msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -10500,6 +10498,10 @@ msgstr "git reflog exists <baÅŸvuru>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "geçersiz zaman damgası '%s', '--%s' argümanına verildi" +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s argüman kabul etmiyor: '%s'" + msgid "do not actually prune any entries" msgstr "özünde, hiçbir girdiyi budama" @@ -10627,8 +10629,8 @@ msgstr "" "\t yerine --mirror=fetch veya --mirror=push kullanın" #, c-format -msgid "unknown mirror argument: %s" -msgstr "bilinmeyen yansı argümanı: %s" +msgid "unknown --mirror argument: %s" +msgstr "bilinmeyen --mirror argümanı: %s" msgid "fetch the remote branches" msgstr "uzak konum dallarını getir" @@ -10997,6 +10999,9 @@ msgstr "" msgid "could not start pack-objects to repack promisor objects" msgstr "vaatçi nesneleri yeniden paketleme için pack-objects baÅŸlatılamadı" +msgid "failed to feed promisor objects to pack-objects" +msgstr "vaatçi nesneleri pack-objects'e beslenemedi" + msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" "repack: Onaltılı tam nesne no satırları yalnızca pack-objects'ten bekleniyor." @@ -11593,6 +11598,13 @@ msgstr "--default bir argüman gerektiriyor" msgid "--prefix requires an argument" msgstr "--prefix bir argüman gerektiriyor" +msgid "no object format specified" +msgstr "belirtilen nesne biçimi yok" + +#, c-format +msgid "unsupported object format: %s" +msgstr "desteklenmeyen nesne biçimi: %s" + #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "--abbrev-ref için bilinmeyen kip: %s" @@ -11674,8 +11686,8 @@ msgstr "baÅŸlangıçta boÅŸ olan iÅŸlemeleri koru" msgid "allow commits with empty messages" msgstr "boÅŸ iletili iÅŸlemelere izin ver" -msgid "keep redundant, empty commits" -msgstr "gereksiz, boÅŸ iÅŸlemeleri tut" +msgid "deprecated: use --empty=keep instead" +msgstr "kullanılmıyor: Yerine --empty=keep kullanın" msgid "use the 'reference' format to refer to commits" msgstr "iÅŸlemelere baÅŸvurmak için 'reference' biçimini kullan" @@ -12999,25 +13011,25 @@ 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" "Etiket için bir ileti yazın:\n" " %s\n" -"'%c' ile baÅŸlayan satırlar yok sayılacaktır.\n" +"'%s' ile baÅŸlayan satırlar yok sayılacaktır.\n" #, 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" "Etiket için bir ileti yazın:\n" " %s\n" -"'%c' ile baÅŸlayan satırlar tutulacaktır; isterseniz onları " +"'%s' ile baÅŸlayan satırlar tutulacaktır; isterseniz onları " "kaldırabilirsiniz.\n" msgid "unable to sign the tag" @@ -13102,6 +13114,9 @@ msgstr "yalnızca birleÅŸtirilmeyen etiketleri yazdır" msgid "print only tags of the object" msgstr "yalnızca nesnenin etiketlerini yazdır" +msgid "could not start 'git column'" +msgstr "'git column' baÅŸlatılamadı" + #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "'%s' seçeneÄŸine yalnızca liste kipinde izin verilir" @@ -13343,12 +13358,12 @@ msgstr "" msgid "fsmonitor disabled" msgstr "dosya sistemi monitörü devre dışı" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<seçenekler>] -d <bÅŸvr-adı> [<eski-deÄŸer>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<seçenekler>] -d <bÅŸvr-adı> [<eski-nesne-kimliÄŸi>]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" msgstr "" -"git update-ref [<seçenekler>] <bÅŸvr-adı> <yeni-deÄŸer> [<eski-deÄŸer>]" +"git update-ref [<seçenekler>] <bÅŸvr-adı> <yeni-n-kiml> [<eski-n-kiml>]" msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [<seçenekler>] --stdin [-z]" @@ -14692,6 +14707,10 @@ msgid "Verifying commits in commit graph" msgstr "Ä°ÅŸleme grafiÄŸindeki iÅŸlemeler doÄŸrulanıyor" #, c-format +msgid "could not parse commit %s" +msgstr "%s iÅŸlemesi ayrıştırılamadı" + +#, c-format msgid "%s %s is not a commit!" msgstr "%s %s bir iÅŸleme deÄŸil!" @@ -15122,8 +15141,13 @@ msgstr "kısaltma uzunluÄŸu erim dışında: %d" msgid "bad zlib compression level %d" msgstr "hatalı zlib sıkıştırma düzeyi %d" -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar yalnızca bir ASCII karakter olmalı" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s yenisatır içeremez" + +#, c-format +msgid "%s must have at least one character" +msgstr "%s, en az bir karaktere iye olmalı" #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" @@ -15194,6 +15218,10 @@ msgid "failed to write new configuration file %s" msgstr "yeni yapılandırma dosyası %s yazılamadı" #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "çok satırlı iÅŸlemeye izin verilmiyor: '%s'" + +#, c-format msgid "could not lock config file %s" msgstr "%s yapılandırma dosyası kilitlenemedi" @@ -16985,6 +17013,14 @@ msgid "Unable to create '%s.lock': %s" msgstr "'%s.lock' oluÅŸturulamıyor: %s" #, 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" + +#, c-format msgid "unexpected line: '%s'" msgstr "beklenmedik satır: '%s'" @@ -16995,6 +17031,10 @@ msgid "quoted CRLF detected" msgstr "alıntılanmış CRLF algılandı" #, c-format +msgid "unable to format message: %s" +msgstr "ileti biçimlendirilemiyor: %s" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "%s altmodülü birleÅŸtirilemedi (çıkış yapılmadı)" @@ -17007,6 +17047,10 @@ 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ı)" + +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "%s altmodülü birleÅŸtirilemedi (iÅŸlemeler merge-base'i takip etmiyor)" @@ -17480,6 +17524,82 @@ msgstr "'%s' nesnesi ayrıştırılamadı" msgid "failed to read the cache" msgstr "önbellek okunamadı" +#, c-format +msgid "failed to add packfile '%s'" +msgstr "paket dosyası '%s' eklenemedi" + +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "pack-index '%s' açılamadı" + +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "%d nesnesi paket dosyasında bulunamadı" + +msgid "cannot store reverse index file" +msgstr "ters indeks dosyası depolanamıyor" + +#, c-format +msgid "could not parse line: %s" +msgstr "satır ayrıştırılamadı: %s" + +#, c-format +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" + +#, c-format +msgid "could not open index for %s" +msgstr "%s için indeks açılamadı" + +msgid "Adding packfiles to multi-pack-index" +msgstr "Paket dosyaları multi-pack-index'e ekleniyor" + +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "bilinmeyen tercih edilen paket: '%s'" + +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "yeÄŸlenen paket %s nesnesiz seçilemiyor" + +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "bırakılacak pack-file %s görülmedi" + +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "tercih edilen '%s' paketinin süresi geçmiÅŸ" + +msgid "no pack files to index." +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 "could not write multi-pack bitmap" +msgstr "çoklu paket biteÅŸlem yazılamadı" + +msgid "could not write multi-pack-index" +msgstr "multi-pack-index yazılamadı" + +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 "could not start pack-objects" +msgstr "pack-objects baÅŸlatılamadı" + +msgid "could not finish pack-objects" +msgstr "pack-objects bitirilemedi" + msgid "multi-pack-index OID fanout is of the wrong size" msgstr "multi-pack-index OID çıkış sayısı boyutu yanlış" @@ -17549,70 +17669,6 @@ 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 add packfile '%s'" -msgstr "paket dosyası '%s' eklenemedi" - -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "pack-index '%s' açılamadı" - -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "%d nesnesi paket dosyasında bulunamadı" - -msgid "cannot store reverse index file" -msgstr "ters indeks dosyası depolanamıyor" - -#, c-format -msgid "could not parse line: %s" -msgstr "satır ayrıştırılamadı: %s" - -#, c-format -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" - -#, c-format -msgid "could not open index for %s" -msgstr "%s için indeks açılamadı" - -msgid "Adding packfiles to multi-pack-index" -msgstr "Paket dosyaları multi-pack-index'e ekleniyor" - -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "bilinmeyen tercih edilen paket: '%s'" - -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "yeÄŸlenen paket %s nesnesiz seçilemiyor" - -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "bırakılacak pack-file %s görülmedi" - -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "tercih edilen '%s' paketinin süresi geçmiÅŸ" - -msgid "no pack files to index." -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 "could not write multi-pack bitmap" -msgstr "çoklu paket biteÅŸlem yazılamadı" - -msgid "could not write multi-pack-index" -msgstr "multi-pack-index yazılamadı" - -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "multi-pack-index %s konumunda temizlenemedi" @@ -17653,18 +17709,6 @@ msgstr "paket dosyası %s için pack-index yüklenemedi" msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "ÅŸunun için yanlış nesne ofseti: oid[%d] = %s: %<PRIx64> != %<PRIx64>" -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 "could not start pack-objects" -msgstr "pack-objects baÅŸlatılamadı" - -msgid "could not finish pack-objects" -msgstr "pack-objects bitirilemedi" - #, c-format msgid "unable to create lazy_dir thread: %s" msgstr "lazy_dir iÅŸ parçacığı oluÅŸturulamıyor: %s" @@ -17711,6 +17755,25 @@ msgstr "%s içindeki notları yeniden yazma reddediliyor (refs/notes/ dışında msgid "Bad %s value: '%s'" msgstr "Hatalı %s deÄŸeri: '%s'" +msgid "failed to decode tree entry" +msgstr "aÄŸaç girdisinin kodu çözülemedi" + +#, c-format +msgid "failed to map tree entry for %s" +msgstr "%s için olan aÄŸaç girdisi eÅŸlemlenemedi" + +#, c-format +msgid "bad %s in commit" +msgstr "iÅŸlemede hatalı %s" + +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "iÅŸleme nesnesinde %s %s eÅŸlemlenemiyor" + +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Nesne, %s -> %s olarak dönüştürülemedi" + #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" msgstr "nesne dizini %s yok; ÅŸurayı denetleyin: .git/objects/info/alternates" @@ -17813,6 +17876,10 @@ msgid "packed object %s (stored in %s) is corrupt" msgstr "paketlenmiÅŸ nesne %s (%s içinde depolanıyor) hasarlı" #, c-format +msgid "missing mapping of %s to %s" +msgstr "%s ögesinin %s ögesine eksik eÅŸlemlemesi" + +#, c-format msgid "unable to write file %s" msgstr "%s dosyası yazılamıyor" @@ -17866,6 +17933,10 @@ msgid "cannot read object for %s" msgstr "%s için nesne okunamıyor" #, c-format +msgid "cannot map object %s to %s" +msgstr "%s nesnesi %s ögesine eÅŸlemlenemiyor" + +#, c-format msgid "object fails fsck: %s" msgstr "nesne fsck'yi baÅŸarısız ediyor: %s" @@ -18170,6 +18241,9 @@ msgstr "" msgid "unable to load pack: '%s', disabling pack-reuse" msgstr "paket yüklenemiyor: '%s', pack-reuse devre dışı bırakılıyor" +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "yeÄŸlenen paket hesaplanamıyor, pack-reuse devre dışı bırakılıyor" + #, c-format msgid "object '%s' not found in type bitmaps" msgstr "'%s' nesnesi, tür biteÅŸlemlerinde bulunamadı" @@ -19219,6 +19293,73 @@ msgid "could not delete references: %s" msgstr "baÅŸvurular silinemedi: %s" #, c-format +msgid "refname is dangerous: %s" +msgstr "baÅŸvuru adı tehlikeli: %s" + +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "'%s' baÅŸvurusu, var olmayan %s nesnesiyle yazılmaya çalışılıyor" + +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "iÅŸleme olmayan %s nesnesi '%s' dalına yazılmaya çalışılıyor" + +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"'HEAD' için birden çok güncellemeye (ona baÅŸvuran '%s' ile olan bir tanesini " +"de içeren) izin verilmiyor" + +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "'%s' baÅŸvurusu kilitlenemiyor: '%s' baÅŸvurusu çözülemiyor" + +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "'%s' baÅŸvurusu kilitlenemiyor: BaÅŸvuruyu okurken hata" + +#, c-format +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" + +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "'%s' baÅŸvurusu kilitlenemiyor: BaÅŸvuru halihazırda var" + +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "'%s' baÅŸvurusu kilitlenemiyor: BaÅŸvuru eksik; ancak %s bekleniyordu" + +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "'%s' baÅŸvurusu kilitlenemiyor: %s üzerinde; ancak %s bekleniyordu" + +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "reftable: Ä°ÅŸlem hazırlığı: %s" + +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "reftable: Ä°ÅŸlem baÅŸarısız: %s" + +#, c-format +msgid "unable to compact stack: %s" +msgstr "yığın kompaktlaÅŸtırılamıyor: %s" + +#, c-format +msgid "refname %s not found" +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" + +#, c-format msgid "invalid refspec '%s'" msgstr "geçersiz baÅŸvuru belirteci '%s'" @@ -19227,6 +19368,10 @@ msgid "invalid quoting in push-option value: '%s'" msgstr "push-option deÄŸerinde geçersiz tırnak içine alım: '%s'" #, c-format +msgid "unknown value for object-format: %s" +msgstr "object-format için bilinmeyen deÄŸer: %s" + +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs geçerli deÄŸil: bu bir git deposu mu?" @@ -19669,8 +19814,19 @@ msgid "resolve-undo records `%s` which is missing" msgstr "resolve-undo, kayıp olan '%s' ögesini kaydetmiÅŸ" #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "soy yolu argümanı %s için iÅŸleme alınamadı" +msgid "%s exists but is a symbolic ref" +msgstr "%s var; ancak bir sembolik baÄŸ" + +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge; MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD veya REBASE_HEAD yalancı " +"baÅŸvurularından birini gerektiriyor" + +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "--ancestry-path argümanı %s için olan iÅŸleme alınamadı" msgid "--unpacked=<packfile> no longer supported" msgstr "--unpacked=<paketdosyası> artık desteklenmiyor" @@ -19955,6 +20111,19 @@ msgid "unknown action: %d" msgstr "bilinmeyen eylem: %d" 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 "" +"Tüm çakışmaları el ile çözün, onları \"git add/rm <çakışan-dosyalar>\"\n" +"ile tamam olarak imleyin, ardından \"git rebase --continue\"\n" +"çalıştırın. Bunun yerine bu iÅŸlemeyi atlayabilirsiniz: \"git rebase\n" +"--skip\" yapın. Ä°ptal edip \"git rebase\" öncesine geri dönmek için\n" +"\"git rebase --abort\" çalıştırın." + +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -20174,10 +20343,6 @@ msgid "could not update %s" msgstr "%s güncellenemedi" #, c-format -msgid "could not parse commit %s" -msgstr "%s iÅŸlemesi ayrıştırılamadı" - -#, c-format msgid "could not parse parent commit %s" msgstr "üst iÅŸleme %s ayrıştırılamadı" @@ -20282,10 +20447,6 @@ msgid "invalid command '%.*s'" msgstr "geçersiz komut %.*s" #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s argüman kabul etmiyor: '%s'" - -#, c-format msgid "missing arguments for %s" msgstr "%s için eksik argüman" @@ -20737,6 +20898,10 @@ msgid "unable to set up work tree using invalid config" msgstr "geçersiz yapılandırma kullanılarak çalışma aÄŸacı kurulamıyor" #, c-format +msgid "'%s' already specified as '%s'" +msgstr "'%s', halihazırda '%s' olarak belirtilmiÅŸ" + +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "Beklenen git repo sürümü <= %d, %d bulundu" @@ -20926,6 +21091,21 @@ msgstr "indeks girdisi bir dizin; ancak aralıklı deÄŸil (%08x)" msgid "cannot use split index with a sparse index" msgstr "bir aralıklı indeksle bölünmüş indeks kullanılamıyor" +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "hatalı %s biçimi: '%s' ögesi '(' ile baÅŸlamıyor" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "hatalı %s biçimi: '%s' ögesi ')' ile sonlanmıyor" + +#. TRANSLATORS: %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "hatalı %s biçimi: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #, c-format msgid "%u.%2.2u GiB" @@ -21248,29 +21428,6 @@ msgstr "bilinmeyen deÄŸer '%s' ('%s' anahtarı için)" msgid "empty trailer token in trailer '%.*s'" msgstr "'%.*s' artbilgisi içinde boÅŸ artbilgi jetonu" -#, c-format -msgid "could not read input file '%s'" -msgstr "'%s' girdi dosyası okunamadı" - -#, c-format -msgid "could not stat %s" -msgstr "%s dosya bilgileri alınamadı" - -#, c-format -msgid "file %s is not a regular file" -msgstr "%s dosyası sıradan bir dosya deÄŸil" - -#, c-format -msgid "file %s is not writable by user" -msgstr "%s dosyası kullanıcı tarafından yazılabilir deÄŸil" - -msgid "could not open temporary file" -msgstr "geçici dosya açılamadı" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "geçici dosya adı %s olarak deÄŸiÅŸtirilemedi" - msgid "full write to remote helper failed" msgstr "uzak konum yardımcısına tam yazım baÅŸarısız" @@ -21366,8 +21523,8 @@ msgid "remote-helper doesn't support push; refspec needed" msgstr "remote-helper itme desteklemiyor; baÅŸvuru belirteci gerekli" #, c-format -msgid "helper %s does not support 'force'" -msgstr "%s yardımcısı 'force' desteklemiyor" +msgid "helper %s does not support '--force'" +msgstr "%s yardımcısı '--force' desteklemiyor" msgid "couldn't run fast-export" msgstr "fast-export çalıştırılamadı" @@ -21780,6 +21937,10 @@ msgstr "geçersiz kapı numarası" msgid "invalid '..' path segment" msgstr "geçersiz '..' yol kesimi" +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "hata: ileti biçimlendirilemiyor: %s\n" + msgid "usage: " msgstr "kullanım: " @@ -6,10 +6,10 @@ # msgid "" msgstr "" -"Project-Id-Version: Git v2.43\n" +"Project-Id-Version: Git v2.45\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2023-11-09 14:26-0800\n" -"PO-Revision-Date: 2024-02-11 09:26-0800\n" +"POT-Creation-Date: 2024-04-27 09:55-0700\n" +"PO-Revision-Date: 2024-04-15 15:55-0700\n" "Last-Translator: Arkadii Yakovets <ark@cho.red>\n" "Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n" "Language: uk\n" @@ -496,12 +496,12 @@ 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" "Щоб видалити Ñ€Ñдки \"%c\", зробіть Ñ—Ñ… Ñ€Ñдками \" \" (контекÑÑ‚).\n" "Щоб видалити Ñ€Ñдки \"%c\", вилучіть Ñ—Ñ….\n" -"Буде видалено Ñ€Ñдки, що починаютьÑÑ Ð· %c.\n" +"Ð Ñдки, що починаютьÑÑ Ð· %s, будуть видалені.\n" msgid "" "If it does not apply cleanly, you will be given an opportunity to\n" @@ -549,6 +549,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" "? - print help\n" msgstr "" "j - залишити цей шматок невизначеним, перейти до наÑтупного невизначеного " @@ -561,6 +562,7 @@ msgstr "" "/ - шукати шматок, що відповідає заданому регвиру\n" "s - розбити поточний шматок на менші шматки\n" "e - редагувати поточний шматок вручну\n" +"p - показати поточний шматок\n" "? - показати довідку\n" msgid "No previous hunk" @@ -624,8 +626,8 @@ msgstr "" "Вимкнути це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ð½Ð° за допомогою \"git config advice.%s false\"" #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sпідказка: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sпідказка:%s%.*s%s\n" msgid "Cherry-picking is not possible because you have unmerged files." msgstr "ВиÑÐ¼Ð¸ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ðµ, оÑкільки у Ð²Ð°Ñ Ñ” не злиті файли." @@ -1138,10 +1140,6 @@ msgstr[1] "ЗаÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ñ‚ÐºÐ¸ %%s з %d відкиданнÑмРmsgstr[2] "ЗаÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ñ‚ÐºÐ¸ %%s з %d відкиданнÑми..." #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð½Ð°Ð·Ð²Ð¸ файлу .rej до %.*s.rej" - -#, c-format msgid "cannot open %s" msgstr "неможливо відкрити %s" @@ -1570,6 +1568,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\"" @@ -1722,6 +1724,9 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "\"%s\" не Ñ” допуÑтимою назвою гілки" +msgid "See `man git check-ref-format`" +msgstr "ДивітьÑÑ \"man git check-ref-format\"" + #, c-format msgid "a branch named '%s' already exists" msgstr "гілка з ім’Ñм \"%s\" вже Ñ–Ñнує" @@ -1918,14 +1923,8 @@ msgstr "" msgid "adding embedded git repository: %s" msgstr "Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ð±ÑƒÐ´Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ git Ñховища: %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 "" -"ВикориÑтовуйте -f, Ñкщо ви дійÑно хочете Ñ—Ñ… додати.\n" -"Щоб вимкнути це повідомленнÑ, виконайте\n" -"\"git config advice.addIgnoredFile false\"" +msgid "Use -f if you really want to add them." +msgstr "СкориÑтайтеÑÑŒ -f, Ñкщо ви дійÑно хочете Ñ—Ñ… додати." msgid "adding files failed" msgstr "Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² завершилоÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾" @@ -1942,14 +1941,8 @@ msgstr "\"%s\" та аргументи визначника шлÑху не мо msgid "Nothing specified, nothing added.\n" msgstr "Ðічого не зазначено, нічого не додано.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"Можливо, ви хотіли вказати \"git add .\"?\n" -"Щоб вимкнути це повідомленнÑ, виконайте\n" -"\"git config advice.addEmptyPathspec false\"" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "Можливо, ви хотіли вказати \"git add .\"?" msgid "index file corrupt" msgstr "індекÑний файл пошкоджено" @@ -2026,18 +2019,20 @@ msgid "Failed to split patches." msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ñ‰ÐµÐ¿Ð¸Ñ‚Ð¸ латки." #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "Коли ви вирішите цю проблему, виконайте \"%s --continue\"." +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "Коли ви вирішите цю проблему, виконайте \"%s --continue\".\n" #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" msgstr "" -"Якщо ви бажаєте пропуÑтити цю латку, виконайте \"%s --skip\" заміÑÑ‚ÑŒ цього." +"Якщо ви бажаєте пропуÑтити цю латку, виконайте \"%s --skip\" заміÑÑ‚ÑŒ цього.\n" #, 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 "" -"Щоб запиÑати порожню латку Ñк порожній коміт, виконайте \"%s --allow-empty\"." +"Щоб запиÑати порожню латку Ñк порожній коміт, виконайте \"%s --allow-" +"empty\".\n" #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." @@ -2905,11 +2900,11 @@ msgstr "гілку Ñкопійовано, але не вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸ 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 "" "Будь лаÑка, відредагуйте Ð¾Ð¿Ð¸Ñ Ð³Ñ–Ð»ÐºÐ¸\n" " %s\n" -"Ð Ñдки, що починаютьÑÑ Ð· \"%c\", будуть вилучені.\n" +"Ð Ñдки, що починаютьÑÑ Ð· \"%s\", будуть вилучені.\n" msgid "Generic options" msgstr "Загальні опції" @@ -3112,10 +3107,12 @@ msgid "not run from a git repository - no hooks to show\n" msgstr "запущено не з git Ñховища - немає гачків Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ\n" 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) <шлÑÑ…>] [(-s | --suffix) <формат>]\n" +"git bugreport [(-o | --output-directory) <шлÑÑ…>]\n" +" [(-s | --suffix) <формат> | --no-suffix]\n" " [--diagnose[=<режим>]]" msgid "" @@ -3603,6 +3600,10 @@ msgstr "" msgid "path '%s' is unmerged" msgstr "шлÑÑ… '%s' не злитий" +#, c-format +msgid "unable to read tree (%s)" +msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ дерево (%s)" + msgid "you need to resolve your current index first" msgstr "Ñпочатку потрібно розібратиÑÑŒ з вашим поточним індекÑом" @@ -3845,6 +3846,10 @@ msgstr "Ðеможливо переключити гілку на не ÐºÐ¾Ð¼Ñ–Ñ msgid "missing branch or commit argument" msgstr "відÑÑƒÑ‚Ð½Ñ Ð³Ñ–Ð»ÐºÐ° або коміт" +#, c-format +msgid "unknown conflict style '%s'" +msgstr "невідомий Ñтиль конфлікту \"%s\"" + msgid "perform a 3-way merge with the new branch" msgstr "здійÑнити 3-Ñтороннє Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð· новою гілкою" @@ -4101,19 +4106,9 @@ msgstr "видалити також ігноровані файли" msgid "remove only ignored files" msgstr "видалити лише ігноровані файли" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" +msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"clean.requireForce вÑтановлено у true Ñ– не задано ні -i, ні -n, ні -f; " -"відмовлено в прибиранні" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" -msgstr "" -"clean.requireForce вÑтановлено у true за замовчуваннÑм Ñ– не задано ні -i, ні " -"-n, ні -f; відмовлено в прибиранні" +"clean.requireForce вÑтановлено у true Ñ– -f не задано: відмовлено в прибиранні" msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [<опції>] [--] <Ñховище> [<директоріÑ>]" @@ -4127,8 +4122,8 @@ msgstr "не переходити на гілку" msgid "create a bare repository" msgstr "Ñтворити порожнє Ñховище" -msgid "create a mirror repository (implies bare)" -msgstr "Ñтворити дзеркальне Ñховище (включає опцію bare)" +msgid "create a mirror repository (implies --bare)" +msgstr "Ñтворити дзеркальне Ñховище (включає опцію --bare)" msgid "to clone from a local repository" msgstr "клонувати з локального Ñховища" @@ -4448,6 +4443,10 @@ msgstr "відÑтуп по правому краю" msgid "padding space between columns" msgstr "відÑтуп між Ñтовпчиками" +#, c-format +msgid "%s must be non-negative" +msgstr "%s має бути невідʼємним значеннÑм" + msgid "--command must be the first argument" msgstr "--command має бути першим аргументом" @@ -4761,35 +4760,35 @@ msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати шаблон комітів" #, 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 "" "Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. Ð Ñдки, що починаютьÑÑ Ð·\n" -" \"%c\" будуть проігноровані.\n" +" \"%s\" будуть проігноровані.\n" #, 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 "" "Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. Ð Ñдки, що починаютьÑÑ Ð·\n" -" \"%c\" будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð²Ðµ коміт.\n" +" \"%s\" будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð²Ðµ коміт.\n" #, 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 "" "Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. Ð Ñдки, що починаютьÑÑ Ð·\n" -" \"%c\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n" +" \"%s\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n" #, 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 "" "Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. Ð Ñдки, що починаютьÑÑ Ð·\n" -" \"%c\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n" +" \"%s\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n" "Порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð¸Ð²Ð°Ñ” коміт.\n" msgid "" @@ -5235,6 +5234,10 @@ msgid "with --get, use default value when missing entry" msgstr "" "з --get викориÑтовувати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм, Ñкщо Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´Ñутній" +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"зрозумілий Ð´Ð»Ñ Ð»ÑŽÐ´Ð¸Ð½Ð¸ Ñ€Ñдок ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ (# буде додано перед за потребою)" + #, c-format msgid "wrong number of arguments, should be %d" msgstr "невірна кількіÑÑ‚ÑŒ аргументів, має бути %d" @@ -5329,6 +5332,9 @@ msgstr "" 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 "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ з \"шаблоном-значеннÑ\"" @@ -6179,6 +6185,9 @@ msgstr "виводити тільки Ñ‚Ñ– поÑиланнÑ, що не міÑÑ msgid "read reference patterns from stdin" msgstr "читати шаблони поÑилань з stdin" +msgid "also include HEAD ref and pseudorefs" +msgstr "також включити HEAD та пÑевдопоÑиланнÑ" + msgid "unknown arguments supplied with --stdin" msgstr "невідомі аргументи надані через --stdin" @@ -6799,10 +6808,6 @@ msgid "no threads support, ignoring %s" msgstr "немає підтримки потоків, Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ %s" #, c-format -msgid "unable to read tree (%s)" -msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ дерево (%s)" - -#, c-format msgid "unable to read tree %s" msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ дерево %s" @@ -7412,7 +7417,7 @@ msgstr "--separate-git-dir неÑуміÑна з порожнім Ñховище 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" @@ -7420,6 +7425,32 @@ msgstr "" "<аліаÑКлюча>[(=|:)<значеннÑ>])...]\n" " [--parse] [<файл>...]" +#, c-format +msgid "could not stat %s" +msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ stat Ð´Ð»Ñ %s" + +#, c-format +msgid "file %s is not a regular file" +msgstr "файл %s не Ñ” звичайним файлом" + +#, c-format +msgid "file %s is not writable by user" +msgstr "файл %s не доÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу кориÑтувачем" + +msgid "could not open temporary file" +msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ тимчаÑовий файл" + +#, c-format +msgid "could not read input file '%s'" +msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ вхідний файл \"%s\"" + +msgid "could not read from stdin" +msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ з stdin" + +#, c-format +msgid "could not rename temporary file to %s" +msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ñ‚Ð¸ тимчаÑовий файл на %s" + msgid "edit files in place" msgstr "редагувати файли на міÑцÑÑ…" @@ -7813,18 +7844,6 @@ msgstr "" msgid "could not get object info about '%s'" msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ інформацію про обʼєкт \"%s\"" -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "невірний ls-files формат: елемент \"%s\" не починаєтьÑÑ Ð· \"(\"" - -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "невірний ls-files формат: елемент \"%s\" не закінчуєтьÑÑ Ð½Ð° \")\"" - -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "невірний ls-files формат: %%%.*s" - msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<опції>] [<файл>...]" @@ -7956,18 +7975,6 @@ msgstr "показувати базове поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° додаток msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<опції>] <деревоподібне-джерело> [<шлÑÑ…>...]" -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "невірний формат ls-tree: елемент \"%s\" не починаєтьÑÑ Ð· \"(\"" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "невірний формат ls-tree: елемент \"%s\" не закінчуєтьÑÑ Ð½Ð° \")\"" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "невірний формат ls-tree: %%%.*s" - msgid "only show trees" msgstr "показувати тільки дерева" @@ -8157,6 +8164,11 @@ msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð²Ê¼Ñзати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" msgid "Merging %s with %s\n" msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ %s з %s\n" +# c-format +#, c-format +msgid "could not parse as tree '%s'" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ дерево з \"%s\"" + msgid "not something we can merge" msgstr "не те, що ми в змозі об’єднати" @@ -8359,10 +8371,10 @@ msgstr "Порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð²Ðµ Ð¿Ñ€Ð¾Ñ†ÐµÑ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ.\n" #, 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 "" -"Ð Ñдки, що починаютьÑÑ Ð· \"%c\", будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ " +"Ð Ñдки, що починаютьÑÑ Ð· \"%s\", будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ " "перерве\n" "Ð¿Ñ€Ð¾Ñ†ÐµÑ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ.\n" @@ -8523,9 +8535,6 @@ msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ тегований об’єкт msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "об’єкт \"%s\", позначений Ñк \"%s\", але має тип \"%s\"" -msgid "could not read from stdin" -msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ з stdin" - msgid "tag on stdin did not pass our strict fsck check" msgstr "тег з stdin не пройшов нашу Ñувору перевірку fsck" @@ -8789,10 +8798,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\"" @@ -9421,10 +9426,11 @@ msgid "refusing to run without --i-still-use-this" msgstr "відмовлено в запуÑку без --i-still-use-this" 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 <шаблон>] [--exclude <шаблон>]" +"git pack-refs [--all] [--no-prune] [--auto] [--include <шаблон>] [--exclude " +"<шаблон>]" msgid "pack everything" msgstr "запакувати вÑе" @@ -9432,6 +9438,9 @@ msgstr "запакувати вÑе" msgid "prune loose refs (default)" msgstr "видалити вивільнені поÑÐ¸Ð»Ð°Ð½Ð½Ñ (за замовчуваннÑм)" +msgid "auto-pack refs as needed" +msgstr "Ð°Ð²Ñ‚Ð¾Ð¿Ð°ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñилань за потреби" + msgid "references to include" msgstr "поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ" @@ -10103,21 +10112,6 @@ msgstr "Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ¿Ñ€Ð¸Ð¿ÑƒÑтимого allow_rerere_autoupd msgid "could not remove '%s'" msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ \"%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 "" -"Вирішіть уÑÑ– конфлікти вручну, позначте Ñ—Ñ… Ñк вирішені за допомогою\n" -"\"git add/rm <конфліктні_файли>\", а потім виконайте \"git rebase --" -"continue\".\n" -"ЗаміÑÑ‚ÑŒ цього ви можете пропуÑтити цей коміт: виконайте \"git rebase --" -"skip\".\n" -"Щоб перервати Ð¿Ñ€Ð¾Ñ†ÐµÑ Ñ– повернутиÑÑ Ð´Ð¾ Ñтану перед \"git rebase\", виконайте " -"\"git rebase --abort\"." - #, c-format msgid "" "\n" @@ -10147,13 +10141,16 @@ msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡Ð¸Ñ‚Ð¸ÑÑŒ на %s" msgid "apply options and merge options cannot be used together" msgstr "apply опції не можна викориÑтовувати разом з merge опціÑми" +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask заÑтаріло; викориÑтовуйте \"--empty=stop\" заміÑÑ‚ÑŒ цього." + #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." +"\"stop\"." msgstr "" "нерозпізнаний порожній тип \"%s\"; припуÑтимими значеннÑми Ñ” \"drop\", " -"\"keep\" та \"ask\"." +"\"keep\" та \"stop\"." msgid "" "--rebase-merges with an empty string argument is deprecated and will stop " @@ -10341,8 +10338,8 @@ msgstr "" "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ \"preserve\",\n" "Ñкий більше не підтримуєтьÑÑ; натоміÑÑ‚ÑŒ викориÑтовуйте \"merges\"" -msgid "No rebase in progress?" -msgstr "ÐŸÐµÑ€ÐµÐ±Ð°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ відбуваєтьÑÑ?" +msgid "no rebase in progress" +msgstr "Ð¿ÐµÑ€ÐµÐ±Ð°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ відбуваєтьÑÑ" msgid "The --edit-todo action can only be used during interactive rebase." msgstr "" @@ -10540,6 +10537,9 @@ msgstr "необхідно вказати директорію" msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<лог-опції>] [<поÑиланнÑ>]" +msgid "git reflog list" +msgstr "git reflog list" + msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -10565,6 +10565,10 @@ msgstr "git reflog exists <поÑиланнÑ>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "неприпуÑтима позначка чаÑу \"%s\" передана до \"--%s\"" +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s не приймає аргументів: \"%s\"" + msgid "do not actually prune any entries" msgstr "наÑправді не видалÑти жодного запиÑу" @@ -10693,8 +10697,8 @@ msgstr "" "\t ÑкориÑтайтеÑÑŒ --mirror=fetch або --mirror=push" #, c-format -msgid "unknown mirror argument: %s" -msgstr "невідомий аргумент дзеркала: %s" +msgid "unknown --mirror argument: %s" +msgstr "невідомий --mirror аргумент: %s" msgid "fetch the remote branches" msgstr "отримати віддалені гілки" @@ -11070,6 +11074,9 @@ msgstr "" msgid "could not start pack-objects to repack promisor objects" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ pack-objects Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¿Ð°ÐºÑƒÐ²Ð°Ð½Ð½Ñ promisor обʼєктів" +msgid "failed to feed promisor objects to pack-objects" +msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚Ð¸ promisor обʼєкти обʼєктам пакунків" + msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" "перепакуваннÑ: очікуютьÑÑ Ð¿Ð¾Ð²Ð½Ñ– Ñ€Ñдки hex ідентифікаторів обʼєктів тільки " @@ -11671,6 +11678,13 @@ msgstr "--default потребує аргументу" msgid "--prefix requires an argument" msgstr "--prefix потребує аргументу" +msgid "no object format specified" +msgstr "не зазначено формат обʼєкту" + +#, c-format +msgid "unsupported object format: %s" +msgstr "непідтримуваний формат обʼєкту: %s" + #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "невідомий режим Ð´Ð»Ñ --abbrev-ref: %s" @@ -11752,8 +11766,8 @@ msgstr "зберігати первинно порожні коміти" msgid "allow commits with empty messages" msgstr "дозволити коміти з порожніми допиÑами" -msgid "keep redundant, empty commits" -msgstr "зберігати зайві порожні коміти" +msgid "deprecated: use --empty=keep instead" +msgstr "заÑтаріле: викориÑтовуйте --empty=keep заміÑÑ‚ÑŒ цього" msgid "use the 'reference' format to refer to commits" msgstr "викориÑтовувати \"reference\" формат Ð´Ð»Ñ Ð¿Ð¾Ñилань на коміти" @@ -13108,25 +13122,25 @@ 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" "Ðапишіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ тегу:\n" " %s\n" -"Ð Ñдки, що починаютьÑÑ Ð· \"%c\", будуть проігноровані.\n" +"Ð Ñдки, що починаютьÑÑ Ð· \"%s\", будуть проігноровані.\n" #, 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" "Ðапишіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ тегу:\n" " %s\n" -"Ð Ñдки, що починаютьÑÑ Ð· \"%c\", будуть збережені; ви можете вилучити Ñ—Ñ… " +"Ð Ñдки, що починаютьÑÑ Ð· \"%s\", будуть збережені; ви можете вилучити Ñ—Ñ… " "ÑамоÑтійно, Ñкщо захочете.\n" msgid "unable to sign the tag" @@ -13212,6 +13226,9 @@ msgstr "вивеÑти тільки не злиті теги" msgid "print only tags of the object" msgstr "вивеÑти тільки теги обʼєкта" +msgid "could not start 'git column'" +msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ \"git column\"" + #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "Ð¾Ð¿Ñ†Ñ–Ñ \"%s\" дозволена лише в режимі виводу" @@ -13458,12 +13475,12 @@ msgstr "" msgid "fsmonitor disabled" msgstr "fsmonitor вимкнено" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<опції>] -d <назва поÑиланнÑ> [<Ñтаре значеннÑ>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<опції>] -d <назва-поÑиланнÑ> [<Ñтарий-oid>]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" msgstr "" -"git update-ref [<опції>] <назва-поÑиланнÑ> <нове-значеннÑ> [<Ñтаре-значеннÑ>]" +"git update-ref [<опції>] <назва-поÑиланнÑ> <новий-oid> [<Ñтарий-oid>]" msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [<опції>] --stdin [-z]" @@ -14821,6 +14838,10 @@ msgid "Verifying commits in commit graph" msgstr "Перевірка комітів у коміт-графі" #, c-format +msgid "could not parse commit %s" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ коміт %s" + +#, c-format msgid "%s %s is not a commit!" msgstr "%s %s не Ñ” комітом!" @@ -15251,8 +15272,13 @@ msgstr "довжина ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ð·Ð° діапазоном: %d" msgid "bad zlib compression level %d" msgstr "невірний рівень zlib компреÑÑ–Ñ— %d" -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar має бути лише одним Ñимволом ASCII" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s не може міÑтити Ñимволи нового Ñ€Ñдка" + +#, c-format +msgid "%s must have at least one character" +msgstr "%s повинен мати принаймні один Ñимвол" #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" @@ -15324,6 +15350,10 @@ msgid "failed to write new configuration file %s" msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати новий конфігураційний файл %s" #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "багаторÑдкові коментарі не дозволÑÑŽÑ‚ÑŒÑÑ: \"%s\"" + +#, c-format msgid "could not lock config file %s" msgstr "не вдалоÑÑ Ð·Ð°Ñ„Ñ–ÐºÑувати файл конфігурації %s" @@ -15508,7 +15538,7 @@ msgstr "ssh Ð¾Ð¿Ñ†Ñ–Ñ \"simple\" не підтримує вÑтановленн #, c-format msgid "strange pathname '%s' blocked" -msgstr "дивне Ñ–Ð¼Ê¼Ñ ÑˆÐ»Ñху \"%s\" заблоковано" +msgstr "дивна назва шлÑху \"%s\" заблокована" msgid "unable to fork" msgstr "неможливо розгалужити" @@ -17134,6 +17164,14 @@ msgid "Unable to create '%s.lock': %s" msgstr "Ðе вдалоÑÑ Ñтворити \"%s.lock\": %s" #, 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" + +#, c-format msgid "unexpected line: '%s'" msgstr "неочікуваний Ñ€Ñдок: \"%s\"" @@ -17144,6 +17182,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 (не активне)" @@ -17156,6 +17198,10 @@ msgid "Failed to merge submodule %s (commits not present)" msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (відÑутні коміти)" #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "Ðе вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (Ñховище пошкоджено)" + +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (коміти не відповідають базі)" @@ -17624,6 +17670,83 @@ msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ обʼєкт \"%s\"" msgid "failed to read the cache" msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ кеш" +#, c-format +msgid "failed to add packfile '%s'" +msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ packfile \"%s\"" + +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ pack-index \"%s\"" + +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ обʼєкт %d у packfile" + +msgid "cannot store reverse index file" +msgstr "неможливо зберегти файл зворотнього індекÑу" + +#, c-format +msgid "could not parse line: %s" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ Ñ€Ñдок: %s" + +#, c-format +msgid "malformed line: %s" +msgstr "невірно Ñформований Ñ€Ñдок: %s" + +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ñнуючого multi-pack-index; невідповідніÑÑ‚ÑŒ контрольних Ñум" + +msgid "could not load pack" +msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакунок" + +#, c-format +msgid "could not open index for %s" +msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ Ñ–Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ %s" + +msgid "Adding packfiles to multi-pack-index" +msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÑ–Ð² до multi-pack-index" + +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "невідомий бажаний пакунок: \"%s\"" + +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "неможливо вибрати бажаний пакунок %s за відÑутноÑÑ‚Ñ– об’єктів" + +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "не знайдено файл пакунка %s Ð´Ð»Ñ ÑкиданнÑ" + +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "у бажаного пакунка \"%s\" закінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії" + +msgid "no pack files to index." +msgstr "немає файлів пакунків Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑації." + +msgid "refusing to write multi-pack .bitmap without any objects" +msgstr "відмовлено в запиÑÑ– мультіпакункового .bitmap без обʼєктів" + +msgid "could not write multi-pack bitmap" +msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати мультіпакунковий bitmap" + +msgid "could not write multi-pack-index" +msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати multi-pack-index" + +msgid "Counting referenced objects" +msgstr "Підрахунок обʼєктів, на Ñкі Ñ” поÑиланнÑ" + +msgid "Finding and deleting unreferenced packfiles" +msgstr "Пошук Ñ– Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² пакунків без поÑилань" + +msgid "could not start pack-objects" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ pack-objects" + +msgid "could not finish pack-objects" +msgstr "не вдалоÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚Ð¸ pack-objects" + msgid "multi-pack-index OID fanout is of the wrong size" msgstr "multi-pack-index OID розÑÑ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð¼Ð°Ñ” невірний розмір" @@ -17699,71 +17822,6 @@ msgid "multi-pack-index large offset out of bounds" msgstr "large offset multi-pack-index виходить за межі" #, c-format -msgid "failed to add packfile '%s'" -msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ packfile \"%s\"" - -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ pack-index \"%s\"" - -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ обʼєкт %d у файлі пакунка" - -msgid "cannot store reverse index file" -msgstr "неможливо зберегти файл зворотнього індекÑу" - -#, c-format -msgid "could not parse line: %s" -msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ Ñ€Ñдок: %s" - -#, c-format -msgid "malformed line: %s" -msgstr "невірно Ñформований Ñ€Ñдок: %s" - -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "" -"Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ñнуючого multi-pack-index; невідповідніÑÑ‚ÑŒ контрольних Ñум" - -msgid "could not load pack" -msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакет" - -#, c-format -msgid "could not open index for %s" -msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ Ñ–Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ %s" - -msgid "Adding packfiles to multi-pack-index" -msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÑ–Ð² до multi-pack-index" - -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "невідомий бажаний пакунок: \"%s\"" - -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "неможливо вибрати бажаний пакунок %s за відÑутноÑÑ‚Ñ– об’єктів" - -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "не побачив файл пакунка %s, Ñкий потрібно Ñкинути" - -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "у бажаного пакета \"%s\" закінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії" - -msgid "no pack files to index." -msgstr "немає файлів пакунків Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑації." - -msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "відмовлено в запиÑÑ– мультіпакункового .bitmap без обʼєктів" - -msgid "could not write multi-pack bitmap" -msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати мультіпакунковий bitmap" - -msgid "could not write multi-pack-index" -msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати multi-pack-index" - -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "не вдалоÑÑ Ð¾Ñ‡Ð¸Ñтити multi-pack-index при %s" @@ -17804,18 +17862,6 @@ msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ Ñ–Ð½Ð´ÐµÐºÑ Ñ„Ð°Ð¹Ð»Ð° паРmsgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "невірне Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ð° Ð´Ð»Ñ oid[%d] = %s: %<PRIx64> != %<PRIx64>" -msgid "Counting referenced objects" -msgstr "Підрахунок обʼєктів, на Ñкі Ñ” поÑиланнÑ" - -msgid "Finding and deleting unreferenced packfiles" -msgstr "Пошук Ñ– Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² пакунків без поÑилань" - -msgid "could not start pack-objects" -msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ pack-objects" - -msgid "could not finish pack-objects" -msgstr "не вдалоÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚Ð¸ pack-objects" - #, c-format msgid "unable to create lazy_dir thread: %s" msgstr "не вдалоÑÑ Ñтворити lazy_dir потік: %s" @@ -17862,6 +17908,25 @@ msgstr "Відмовлено в перезапиÑÑ– нотаток у %s (за msgid "Bad %s value: '%s'" msgstr "Ðевірне %s значеннÑ: \"%s\"" +msgid "failed to decode tree entry" +msgstr "не вдалоÑÑ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ñ‚Ð¸ Ð·Ð°Ð¿Ð¸Ñ Ð´ÐµÑ€ÐµÐ²Ð°" + +#, c-format +msgid "failed to map tree entry for %s" +msgstr "не вдалоÑÑ Ð·Ñ–Ñтавити Ð·Ð°Ð¿Ð¸Ñ Ñƒ дереві Ð´Ð»Ñ %s" + +#, c-format +msgid "bad %s in commit" +msgstr "невірній %s у коміті" + +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "не вдалоÑÑ Ð·Ñ–Ñтавити %s %s в обʼєкті коміту" + +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ обʼєкт з \"%s\" на \"%s\"" + #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" msgstr "Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ñ–Ñ Ð¾Ð±â€™Ñ”ÐºÑ‚Ð° %s не Ñ–Ñнує; перевірте .git/objects/info/alternates" @@ -17965,6 +18030,10 @@ msgid "packed object %s (stored in %s) is corrupt" msgstr "упакований обʼєкт %s (що зберігаєтьÑÑ Ñƒ %s) пошкоджено" #, c-format +msgid "missing mapping of %s to %s" +msgstr "відÑутнє зіÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ñ %s до %s" + +#, c-format msgid "unable to write file %s" msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл %s" @@ -18018,6 +18087,10 @@ msgid "cannot read object for %s" msgstr "неможливо прочитати обʼєкт Ð´Ð»Ñ %s" #, c-format +msgid "cannot map object %s to %s" +msgstr "неможливо зіÑтавити обʼєкт %s з %s" + +#, c-format msgid "object fails fsck: %s" msgstr "об’єкт не пройшов перевірку fsck: %s" @@ -18329,6 +18402,11 @@ msgstr "" "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакунок: \"%s\", Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ викориÑÑ‚Ð°Ð½Ð½Ñ " "пакунків" +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "" +"не вдалоÑÑ Ð¾Ð±Ñ‡Ð¸Ñлити бажаний пакунок, Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ викориÑÑ‚Ð°Ð½Ð½Ñ " +"пакунків" + #, c-format msgid "object '%s' not found in type bitmaps" msgstr "обʼєкт \"%s\" не знайдено в типах bitmap" @@ -19391,6 +19469,79 @@ msgid "could not delete references: %s" msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ поÑиланнÑ: %s" #, c-format +msgid "refname is dangerous: %s" +msgstr "refname Ñ” небезпечним: %s" + +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "Ñпроба запиÑати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" з неіÑнуючим обʼєктом %s" + +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "Ñпроба запиÑати не коміт обʼєкт %s у гілку \"%s\"" + +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"багаторазові Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ \"HEAD\" (включаючи через поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· \"%s\") не " +"дозволені" + +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "" +"неможливо зафікÑуваті поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": не вдалоÑÑŒ розвʼÑзати поÑÐ¸Ð»Ð°Ð½Ð½Ñ " +"\"%s\"" + +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "" +"неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": помилка при зчитуванні поÑиланнÑ" + +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"багаторазові Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ \"%s\" (включаючи Ñимвольні поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· \"%s\") " +"не дозволені" + +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²Ð¶Ðµ Ñ–Ñнує" + +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "" +"неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñутнє, але очікуване %s" + +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "" +"неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": Ñтановить %s, але очікуєтьÑÑ %s" + +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Ð¿Ð¾Ñилань: підготовка транзакції: \"%s\"" + +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Ð¿Ð¾Ñилань: помилка транзакції: \"%s\"" + +#, c-format +msgid "unable to compact stack: %s" +msgstr "не вдалоÑÑ ÑтиÑнути Ñтек: %s" + +#, c-format +msgid "refname %s not found" +msgstr "назва поÑÐ¸Ð»Ð°Ð½Ð½Ñ %s не знайдена" + +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "" +"назва поÑÐ¸Ð»Ð°Ð½Ð½Ñ %s Ñ” Ñимвольним поÑиланнÑм, ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñкого не підтримуєтьÑÑ" + +#, c-format msgid "invalid refspec '%s'" msgstr "неприпуÑтимий визначник поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" @@ -19399,6 +19550,10 @@ msgid "invalid quoting in push-option value: '%s'" msgstr "неприпуÑтимі лапки у значенні push-опції: \"%s\"" #, c-format +msgid "unknown value for object-format: %s" +msgstr "невідоме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ object-format: %s" + +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs не дійÑні: це git Ñховище?" @@ -19860,8 +20015,19 @@ msgid "resolve-undo records `%s` which is missing" msgstr "resolve-undo запиÑує \"%s\", Ñкий відÑутній" #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ коміт Ð´Ð»Ñ ancestry-path аргументу %s" +msgid "%s exists but is a symbolic ref" +msgstr "%s Ñ–Ñнує але Ñ” Ñимвольним поÑиланнÑм" + +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge вимагає одне з пÑевдопоÑилань MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD або REBASE_HEAD" + +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ коміт Ð´Ð»Ñ --ancestry-path аргументу %s" msgid "--unpacked=<packfile> no longer supported" msgstr "--unpacked=<файл пакунка> більше не підтримуєтьÑÑ" @@ -20149,6 +20315,21 @@ msgid "unknown action: %d" msgstr "невідома діÑ: %d" 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 "" +"Вирішіть уÑÑ– конфлікти вручну, позначте Ñ—Ñ… Ñк вирішені за допомогою\n" +"\"git add/rm <конфліктні_файли>\", а потім виконайте \"git rebase --" +"continue\".\n" +"ЗаміÑÑ‚ÑŒ цього ви можете пропуÑтити цей коміт: виконайте \"git rebase --" +"skip\".\n" +"Щоб перервати Ð¿Ñ€Ð¾Ñ†ÐµÑ Ñ– повернутиÑÑ Ð´Ð¾ Ñтану перед \"git rebase\", виконайте " +"\"git rebase --abort\"." + +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -20376,10 +20557,6 @@ msgid "could not update %s" msgstr "не вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ %s" #, c-format -msgid "could not parse commit %s" -msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ коміт %s" - -#, c-format msgid "could not parse parent commit %s" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ джерельний коміт %s" @@ -20484,10 +20661,6 @@ msgid "invalid command '%.*s'" msgstr "неприпуÑтима команда \"%.*s\"" #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s не приймає аргументи: \"%s\"" - -#, c-format msgid "missing arguments for %s" msgstr "відÑутні аргументи Ð´Ð»Ñ %s" @@ -20945,6 +21118,10 @@ msgstr "" "конфігурацію" #, c-format +msgid "'%s' already specified as '%s'" +msgstr "\"%s\" вже зазначено Ñк \"%s\"" + +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "ОчікувалоÑÑŒ git Ñховищe верÑÑ–Ñ— <= %d, знайдено %d" @@ -21138,6 +21315,21 @@ msgstr "Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð½Ð´ÐµÐºÑу Ñ” директорією, але не Ñ€Ð¾Ð·Ñ msgid "cannot use split index with a sparse index" msgstr "неможливо викориÑтовувати розділений Ñ–Ð½Ð´ÐµÐºÑ Ð· розрідженим індекÑом" +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "невірний формат %s: елемент \"%s\" не починаєтьÑÑ Ð· \"(\"" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "невірний формат %s: елемент \"%s\" не закінчуєтьÑÑ Ð½Ð° \")\"" + +#. TRANSLATORS: %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "невірний формат %s: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #, c-format msgid "%u.%2.2u GiB" @@ -21470,29 +21662,6 @@ msgstr "невідоме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ \"%s\" Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡Ð° \"%s\"" msgid "empty trailer token in trailer '%.*s'" msgstr "порожній токен трейлера в трейлері \"%.*s\"" -#, c-format -msgid "could not read input file '%s'" -msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ вхідний файл \"%s\"" - -#, c-format -msgid "could not stat %s" -msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ %s" - -#, c-format -msgid "file %s is not a regular file" -msgstr "файл %s не Ñ” звичайним файлом" - -#, c-format -msgid "file %s is not writable by user" -msgstr "файл %s не доÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу кориÑтувачем" - -msgid "could not open temporary file" -msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ тимчаÑовий файл" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ñ‚Ð¸ тимчаÑовий файл на %s" - msgid "full write to remote helper failed" msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ повний Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ віддаленого помічника" @@ -21588,8 +21757,8 @@ msgid "remote-helper doesn't support push; refspec needed" msgstr "remote-helper не підтримує push; потрібен refspec" #, c-format -msgid "helper %s does not support 'force'" -msgstr "помічник %s не підтримує \"force\"" +msgid "helper %s does not support '--force'" +msgstr "помічник %s не підтримує \"--force\"" msgid "couldn't run fast-export" msgstr "не вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити fast-export" @@ -22012,6 +22181,10 @@ msgstr "неприпуÑтимий номер порту" msgid "invalid '..' path segment" msgstr "неприпуÑтимий \"..\" Ñегмент шлÑху" +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "помилка: не вдалоÑÑ Ð²Ñ–Ð´Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸ допиÑ: %s\n" + msgid "usage: " msgstr "викориÑтаннÑ: " @@ -2,32 +2,33 @@ # 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. # msgid "" msgstr "" -"Project-Id-Version: git v2.37.0\n" +"Project-Id-Version: git 2.45\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2022-06-21 20:20+0000\n" -"PO-Revision-Date: 2022-06-25 08:37+0700\n" -"Last-Translator: Trần Ngá»c Quân <vnwildman@gmail.com>\n" -"Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n" +"POT-Creation-Date: 2024-04-25 18:57+0000\n" +"PO-Revision-Date: 2024-04-28 14:01+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" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0\n" -"X-Language-Team-Website: <http://translationproject.org/team/vi.html>\n" -"X-Generator: Gtranslator 42.0\n" #, c-format msgid "Huh (%s)?" msgstr "Hả (%s)?" msgid "could not read index" -msgstr "không thể Ä‘á»c bảng mục lục" +msgstr "không thể Ä‘á»c chỉ mục" msgid "binary" msgstr "nhị phân" @@ -43,31 +44,31 @@ 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' lên bệ phóng" msgid "could not write index" -msgstr "không thể ghi bảng mục lục" +msgstr "không thể ghi chỉ mục" -#, c-format, perl-format +#, c-format msgid "updated %d path\n" msgid_plural "updated %d paths\n" msgstr[0] "đã cáºp nháºt %d Ä‘Æ°á»ng dẫn\n" -#, c-format, perl-format +#, c-format msgid "note: %s is untracked now.\n" -msgstr "chú ý: %s giỠđã bá» theo dõi.\n" +msgstr "chú ý: đã bá» theo dõi %s.\n" #, c-format msgid "make_cache_entry failed for path '%s'" -msgstr "make_cache_entry gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn “%sâ€" +msgstr "make_cache_entry gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn '%s'" msgid "Revert" msgstr "Hoà n nguyên" msgid "Could not parse HEAD^{tree}" -msgstr "Không thể phân tÃch cú pháp HEAD^{tree}" +msgstr "Không hiểu cú pháp HEAD^{tree}" -#, c-format, perl-format +#, c-format msgid "reverted %d path\n" msgid_plural "reverted %d paths\n" msgstr[0] "đã hoà n nguyên %d Ä‘Æ°á»ng dẫn\n" @@ -77,33 +78,33 @@ msgid "No untracked files.\n" msgstr "Không có táºp tin nà o chÆ°a được theo dõi.\n" msgid "Add untracked" -msgstr "Thêm các cái chÆ°a được theo dõi" +msgstr "Thêm các táºp tin chÆ°a được theo dõi" -#, c-format, perl-format +#, c-format msgid "added %d path\n" msgid_plural "added %d paths\n" msgstr[0] "đã thêm %d Ä‘Æ°á»ng dẫn\n" #, c-format msgid "ignoring unmerged: %s" -msgstr "bá» qua những thứ chÆ°a hòa trá»™n: %s" +msgstr "bá» qua những táºp tin chÆ°a hòa trá»™n: %s" #, c-format msgid "Only binary files changed.\n" -msgstr "Chỉ có các táºp tin nhị phân là thay đổi.\n" +msgstr "Chỉ có các táºp tin nhị phân thay đổi.\n" #, c-format msgid "No changes.\n" msgstr "Không có thay đổi nà o.\n" msgid "Patch update" -msgstr "Cáºp nháºt miếng vá" +msgstr "Cáºp nháºt bản vá" msgid "Review diff" -msgstr "Xem xét lại diff" +msgstr "Xem xét lại thay đổi" msgid "show paths with changes" -msgstr "hiển thị Ä‘Æ°á»ng dẫn vá»›i các thay đổi" +msgstr "hiển thị các Ä‘Æ°á»ng dẫn có thay đổi" msgid "add working tree state to the staged set of changes" msgstr "" @@ -116,10 +117,10 @@ msgstr "" "bản HEAD" msgid "pick hunks and update selectively" -msgstr "chá»n các “khúc†và cáºp nháºt có tuyển chá»n" +msgstr "chá»n các khúc và cáºp nháºt có lá»±a chá»n" msgid "view diff between HEAD and index" -msgstr "xem khác biệt giữa HEAD và mục lục" +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 "" @@ -139,7 +140,7 @@ msgid "select multiple ranges" msgstr "chá»n nhiá»u vùng" msgid "select item based on unique prefix" -msgstr "chá»n mục dá»±a trên tiá»n tố duy nhất" +msgstr "chá»n mục dá»±a trên tiá»n tố Ä‘á»™c nhất" msgid "unselect specified items" msgstr "bá» chá»n các mục đã cho" @@ -151,7 +152,7 @@ msgid "(empty) finish selecting" msgstr "(để trống) hoà n tất chá»n lá»±a" msgid "select a numbered item" -msgstr "tùy chá»n mục bằng số" +msgstr "lá»±a chá»n mục bằng số" msgid "(empty) select nothing" msgstr "(để trống) không chá»n gì" @@ -172,25 +173,25 @@ msgid "path" msgstr "Ä‘Æ°á»ng-dẫn" msgid "could not refresh index" -msgstr "không thể Ä‘á»c lại bảng mục lục" +msgstr "không thể Ä‘á»c lại chỉ mục" #, c-format msgid "Bye.\n" msgstr "Tạm biệt.\n" -#, c-format, perl-format +#, c-format msgid "Stage mode change [y,n,q,a,d%s,?]? " -msgstr "Thay đổi chế Ä‘á»™ bệ phóng [y,n,q,a,d%s,?]? " +msgstr "ÄÆ°a lên bệ phóng thay đổi chế Ä‘á»™ [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Stage deletion [y,n,q,a,d%s,?]? " -msgstr "Xóa khá»i bệ phóng [y,n,q,a,d%s,?]? " +msgstr "ÄÆ°a lên bệ phóng thao tác xoá [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Stage addition [y,n,q,a,d%s,?]? " -msgstr "Thêm và o bệ phóng [y,n,q,a,d%s,?]? " +msgstr "ÄÆ°a lên bệ phóng thao tác thêm [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, 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,?]? " @@ -198,7 +199,7 @@ msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "staging." msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức được đánh dấu " +"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." msgid "" @@ -210,24 +211,23 @@ msgid "" 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 cÅ©ng nhÆ° bất kỳ cái nà o còn lại\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 cÅ©ng nhÆ° bất kỳ cái nà o còn lại 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" -#, c-format, perl-format +#, c-format msgid "Stash mode change [y,n,q,a,d%s,?]? " -msgstr "Thay đổi chế Ä‘á»™ tạm cất Ä‘i [y,n,q,a,d%s,?]? " +msgstr "Tạm cất thay đổi chế Ä‘á»™ [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Stash deletion [y,n,q,a,d%s,?]? " -msgstr "Xóa tạm cất [y,n,q,a,d%s,?]? " +msgstr "Tạm cất thao tác xoá [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Stash addition [y,n,q,a,d%s,?]? " -msgstr "Thêm và o tạm cất [y,n,q,a,d%s,?]? " +msgstr "Tạm cất thao tác thêm [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Stash this hunk [y,n,q,a,d%s,?]? " msgstr "Tạm cất khúc nà y [y,n,q,a,d%s,?]? " @@ -235,7 +235,7 @@ msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "stashing." msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức được đánh dấu " +"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 " "để tạm cất." msgid "" @@ -247,23 +247,23 @@ msgid "" msgstr "" "y - tạm cất khúc nà y\n" "n - đừng tạm cất khúc nà y\n" -"q - thoát; đừng tạm cất khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" +"q - thoát; đừng tạm cất khúc nà y hay bất kỳ cái nà o còn lại\n" "a - tạm cất khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng tạm cất khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại trong táºp tin\n" +"d - đừng tạm cất khúc nà y hay bất kỳ cái nà o còn lại trong táºp tin\n" -#, c-format, perl-format +#, c-format msgid "Unstage mode change [y,n,q,a,d%s,?]? " -msgstr "Thay đổi chế Ä‘á»™ bá» ra khá»i bệ phóng [y,n,q,a,d%s,?]? " +msgstr "Bá» ra khá»i bệ phóng thay đổi chế Ä‘á»™ [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Unstage deletion [y,n,q,a,d%s,?]? " -msgstr "Xóa bá» việc bá» ra khá»i bệ phóng [y,n,q,a,d%s,?]? " +msgstr "Bá» ra khá»i bệ phóng thao tác xoá [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Unstage addition [y,n,q,a,d%s,?]? " -msgstr "Thêm và o việc bá» ra khá»i bệ phóng [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,?]? " -#, c-format, perl-format +#, 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,?]? " @@ -271,7 +271,7 @@ msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "unstaging." msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức được đánh dấu " +"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." msgid "" @@ -283,33 +283,32 @@ msgid "" 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 cÅ©ng nhÆ° bất kỳ cái nà o còn " -"lại\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 cÅ©ng nhÆ° bất kỳ cái nà o còn lại 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 " +"tin\n" -#, c-format, perl-format +#, c-format msgid "Apply mode change to index [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho mục lục [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thay đổi chế Ä‘á»™ và o chỉ mục [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Apply deletion to index [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng việc xóa và o mục lục [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thao tác xóa và o chỉ mục [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Apply addition to index [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng các thêm và o mục lục [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thao tác thêm và o chỉ mục [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Apply this hunk to index [y,n,q,a,d%s,?]? " -msgstr "Ão dụng khúc nà y và o mục lục [y,n,q,a,d%s,?]? " +msgstr "Ão dụng khúc nà y và o chỉ mục [y,n,q,a,d%s,?]? " msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "applying." msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức được đánh dấu " +"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 " "để áp dụng." msgid "" @@ -319,25 +318,25 @@ msgid "" "a - apply this hunk and all later hunks in the file\n" "d - do not apply this hunk or any of the later hunks in the file\n" msgstr "" -"y - áp dụng khúc nà y và o mục lục\n" -"n - đừng áp dụng khúc nà y và o mục lục\n" -"q - thoát; đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" +"y - áp dụng khúc nà y và o chỉ mục\n" +"n - đừng áp dụng khúc nà y và o chỉ mục\n" +"q - thoát; đừng áp dụng khúc nà y hay bất kỳ cái nà o còn lại\n" "a - áp dụng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin\n" +"d - đừng áp dụng khúc nà y hay bất kỳ cái nà o sau nà y trong táºp tin\n" -#, c-format, perl-format +#, c-format msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? " -msgstr "Loại bá» các thay đổi chế Ä‘á»™ từ cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Loại bá» thay đổi chế Ä‘á»™ khá»i cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? " -msgstr "Loại bá» việc xóa khá»i cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Loại bá» thao tác xóa khá»i cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Discard addition from worktree [y,n,q,a,d%s,?]? " -msgstr "Thêm các loại bá» khá»i cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Loại bá» thao tác thêm khá»i cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? " msgstr "Loại bá» khúc nà y khá»i cây là m việc [y,n,q,a,d%s,?]? " @@ -345,7 +344,7 @@ msgid "" "If the patch applies cleanly, the edited hunk will immediately be marked for " "discarding." msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức được đánh dấu " +"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 " "để loại bá»." msgid "" @@ -357,25 +356,25 @@ msgid "" msgstr "" "y - loại bá» khúc nà y khá»i cây là m việc\n" "n - đừng loại bá» khúc khá»i cây là m việc\n" -"q - thoát; đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" +"q - thoát; đừng loại bá» khúc nà y hay bất kỳ cái nà o còn lại\n" "a - loại bá» khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin\n" +"d - đừng loại bá» khúc nà y hay bất kỳ cái nà o sau nà y trong táºp tin\n" -#, c-format, perl-format +#, c-format msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? " -msgstr "Loại bá» thay đổi chế Ä‘á»™ từ mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Loại bá» thay đổi chế Ä‘á»™ khá»i chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? " -msgstr "Loại bá» việc xóa khá»i mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Loại bá» thao tác xóa khá»i chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? " -msgstr "Thêm các loại bá» từ mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Loại bá» thao tác thêm khá»i chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " -msgstr "Loại bá» khúc nà y khá»i mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Loại bá» khúc nà y khá»i chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " msgid "" "y - discard this hunk from index and worktree\n" @@ -384,27 +383,27 @@ msgid "" "a - discard this hunk and all later hunks in the file\n" "d - do not discard this hunk or any of the later hunks in the file\n" msgstr "" -"y - loại bá» khúc nà y khá»i mục lục và cây là m việc\n" -"n - đừng loại bá» khúc khá»i mục lục và cây là m việc\n" -"q - thoát; đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" +"y - loại bá» khúc nà y khá»i chỉ mục và cây là m việc\n" +"n - đừng loại bá» khúc khá»i chỉ mục và cây là m việc\n" +"q - thoát; đừng loại bá» khúc nà y hay bất kỳ cái nà o còn lại\n" "a - loại bá» khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin\n" +"d - đừng loại bá» khúc nà y hay bất kỳ cái nà o sau nà y trong táºp tin\n" -#, c-format, perl-format +#, c-format msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng việc xóa và o mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thao tác xóa và o chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng thêm và o mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thao tác thêm và o chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " -#, c-format, perl-format +#, c-format msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng khúc nà y và o mục lục và cây là m việc [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng khúc nà y và o chỉ mục và cây là m việc [y,n,q,a,d%s,?]? " msgid "" "y - apply this hunk to index and worktree\n" @@ -413,11 +412,27 @@ msgid "" "a - apply this hunk and all later hunks in the file\n" "d - do not apply this hunk or any of the later hunks in the file\n" msgstr "" -"y - áp dụng khúc nà y và o mục lục và cây là m việc\n" -"n - đừng áp dụng khúc và o mục lục và cây là m việc\n" -"q - thoát; đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" +"y - áp dụng khúc nà y và o chỉ mục và cây là m việc\n" +"n - đừng áp dụng khúc và o chỉ mục và cây là m việc\n" +"q - thoát; đừng áp dụng khúc nà y hay bất kỳ cái nà o còn lại\n" "a - áp dụng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin\n" +"d - đừng áp dụng khúc nà y hay bất kỳ cái nà o sau nà y trong táºp tin\n" + +#, c-format +msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho cây là m việc [y,n,q,a,d%s,?]? " + +#, c-format +msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thao tác xóa cho cây là m việc [y,n,q,a,d%s,?]? " + +#, c-format +msgid "Apply addition to worktree [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng thao tác thêm cho cây là m việc [y,n,q,a,d%s,?]? " + +#, c-format +msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? " +msgstr "Ãp dụng khúc nà y và o cây là m việc [y,n,q,a,d%s,?]? " msgid "" "y - apply this hunk to worktree\n" @@ -428,36 +443,32 @@ msgid "" msgstr "" "y - áp dụng khúc nà y và o cây là m việc\n" "n - đừng áp dụng khúc và o cây là m việc\n" -"q - thoát; đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" +"q - thoát; đừng áp dụng khúc nà y hay bất kỳ cái nà o còn lại\n" "a - áp dụng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin\n" +"d - đừng áp dụng khúc nà y hay bất kỳ cái nà o sau nà y trong táºp tin\n" #, c-format msgid "could not parse hunk header '%.*s'" -msgstr "không thể phân tÃch cú pháp phần đầu của khúc “%.*sâ€" - -#, c-format -msgid "could not parse colored hunk header '%.*s'" -msgstr "không thể phân tÃch cú pháp phần đầu khúc đã tô mà u “%.*sâ€" +msgstr "không thể Ä‘á»c phần đầu của khúc '%.*s'" msgid "could not parse diff" -msgstr "không thể phân tÃch cú pháp khác biệt" +msgstr "không thể Ä‘á»c diff" msgid "could not parse colored diff" -msgstr "không thể phân tÃch khác biệt được tô mà u" +msgstr "không thể Ä‘á»c diff có mà u" #, c-format msgid "failed to run '%s'" -msgstr "gặp lá»—i khi chạy “%sâ€" +msgstr "gặp lá»—i khi chạy '%s'" msgid "mismatched output from interactive.diffFilter" -msgstr "đầu ra không khá»›p từ interactive.diffFilter" +msgstr "đầu ra không khá»›p nhau từ interactive.diffFilter" msgid "" "Your filter must maintain a one-to-one correspondence\n" "between its input and output lines." msgstr "" -"Bá»™ lá»c của bạn phải duy trì má»™t quan hệ má»™t-đến-má»™t\n" +"Bá»™ lá»c của bạn phải duy trì quan hệ má»™t-má»™t\n" "giữa các dòng đầu và o và đầu ra của nó." #, c-format @@ -465,7 +476,7 @@ msgid "" "expected context line #%d in\n" "%.*s" msgstr "" -"cần dòng ngữ cảnh #%d trong\n" +"cần dòng ngữ cảnh số %d trong\n" "%.*s" #, c-format @@ -481,51 +492,42 @@ msgstr "" "%.*s" msgid "Manual hunk edit mode -- see bottom for a quick guide.\n" -msgstr "Chế Ä‘á»™ sá»a khúc bằng tay -- xem ở đáy để có hÆ°á»›ng dẫn sá» dụng nhanh.\n" +msgstr "" +"Chế Ä‘á»™ sá»a khúc bằng tay -- xem ở dÆ°á»›i để có hÆ°á»›ng dẫn sá» dụng nhanh.\n" #, 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" -"Äể gỡ bá» dòng “%câ€, sá»a chúng thà nh những dòng “ †(ngữ cảnh).\n" -"Äể gõ bá» dòng “%câ€, xóa chúng Ä‘i.\n" -"Những dòng bắt đầu bằng %c sẽ bị loại bá».\n" +"Äể gỡ bá» dòng '%c', sá»a chúng thà nh những dòng ' ' (ngữ cảnh).\n" +"Äể gõ bá» dòng '%c', xóa chúng Ä‘i.\n" +"Những dòng bắt đầu bằng %s sẽ bị loại bá».\n" -#. #-#-#-#-# git-add--interactive.perl.po #-#-#-#-# -#. TRANSLATORS: 'it' refers to the patch mentioned in the previous messages. 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" "aborted and the hunk is left unchanged.\n" msgstr "" -"Nếu miếng vá không được áp dụng sạch sẽ, bạn sẽ có má»™t cÆ¡ há»™i\n" -"để sá»a lần nữa. Nếu má»i dòng của khúc bị xóa bá», thế thì những\n" -"sá»a dổi sẽ bị loại bá», và khúc vẫn giữ nguyên.\n" +"Nếu bản vá không được áp dụng hoà n toà n, bạn sẽ có cÆ¡ há»™i\n" +"để sá»a lại. Nếu má»i dòng của khúc bị xóa bá», thì những\n" +"sá»a đổi sẽ bị loại bá», và khúc vẫn giữ nguyên.\n" msgid "could not parse hunk header" -msgstr "không thể phân tÃch cú pháp phần đầu khúc" +msgstr "không hiểu cú pháp phần đầu khúc" msgid "'git apply --cached' failed" -msgstr "“git apply --cached†gặp lá»—i" +msgstr "'git apply --cached' gặp lá»—i" -#. #-#-#-#-# add-patch.c.po #-#-#-#-# #. TRANSLATORS: do not translate [y/n] #. The program will only accept that input at this point. #. Consider translating (saying "no" discards!) as #. (saying "n" for "no" discards!) if the translation #. of the word "no" does not start with n. #. -#. #-#-#-#-# git-add--interactive.perl.po #-#-#-#-# -#. TRANSLATORS: do not translate [y/n] -#. The program will only accept that input -#. at this point. -#. Consider translating (saying "no" discards!) as -#. (saying "n" for "no" discards!) if the translation -#. of the word "no" does not start with n. msgid "" "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? " msgstr "" @@ -533,7 +535,7 @@ msgstr "" "bá»!) [y/n]? " msgid "The selected hunks do not apply to the index!" -msgstr "Các khúc đã chá»n không được áp dụng và o bảng mục lục!" +msgstr "Các khúc đã chá»n không được áp dụng và o chỉ mục!" msgid "Apply them to the worktree anyway? " msgstr "Vẫn áp dụng chúng cho cây là m việc? " @@ -550,6 +552,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" "? - 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" @@ -557,9 +560,10 @@ msgstr "" "k - để lại khúc nà y là chÆ°a quyết định, xem khúc chÆ°a quyết định kế trÆ°á»›c\n" "K - để lại khúc nà y là chÆ°a quyết định, xem khúc kế trÆ°á»›c\n" "g - chá»n má»™t khúc muốn tá»›i\n" -"/ - tìm má»™t khúc khá»›p vá»›i biểu thức chÃnh quy Ä‘Æ°a ra\n" +"/ - 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" "? - hiển thị trợ giúp\n" msgid "No previous hunk" @@ -569,48 +573,48 @@ msgid "No next hunk" msgstr "Không có khúc kế tiếp" msgid "No other hunks to goto" -msgstr "Không còn khúc nà o để mà nhảy đến" +msgstr "Không còn khúc nà o để nhảy đến" msgid "go to which hunk (<ret> to see more)? " -msgstr "nhảy đến khúc nà o (<ret> để xem thêm)? " +msgstr "nhảy đến khúc nà o (<Enter> để xem thêm)? " msgid "go to which hunk? " msgstr "nhảy đến khúc nà o? " #, c-format msgid "Invalid number: '%s'" -msgstr "Số không hợp lệ: “%sâ€" +msgstr "Số không hợp lệ: '%s'" #, c-format msgid "Sorry, only %d hunk available." msgid_plural "Sorry, only %d hunks available." -msgstr[0] "Rất tiếc, chỉ có sẵn %d khúc." +msgstr[0] "Chỉ có %d khúc." msgid "No other hunks to search" -msgstr "Không còn khúc nà o để mà tìm kiếm" +msgstr "Không còn khúc nà o để tìm kiếm" msgid "search for regex? " -msgstr "tìm kiếm cho biểu thức chÃnh quy? " +msgstr "tìm kiếm cho biểu thức chÃnh quy (regex)? " #, c-format msgid "Malformed search regexp %s: %s" -msgstr "Äịnh dạng tìm kiếm của biểu thức chÃnh quy không đúng %s: %s" +msgstr "Äịnh dạng tìm kiếm của biểu thức chÃnh quy (regex) bất thÆ°á»ng %s: %s" msgid "No hunk matches the given pattern" msgstr "Không thấy khúc nà o khá»›p mẫu đã cho" msgid "Sorry, cannot split this hunk" -msgstr "Rất tiếc, không thể chia nhá» khúc nà y" +msgstr "Không thể chia nhá» khúc nà y" #, c-format msgid "Split into %d hunks." -msgstr "Chi nhá» thà nh %d khúc." +msgstr "Chia nhá» thà nh %d khúc." msgid "Sorry, cannot edit this hunk" -msgstr "Rất tiếc, không thể sá»a khúc nà y" +msgstr "Không thể sá»a khúc nà y" msgid "'git apply' failed" -msgstr "“git apply†gặp lá»—i" +msgstr "'git apply' gặp lá»—i" #, c-format msgid "" @@ -621,47 +625,41 @@ msgstr "" "Tắt lá»i nhắn nà y bằng \"git config advice.%s false\"" #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sgợi ý: %.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sgợi ý:%s%.*s%s\n" msgid "Cherry-picking is not possible because you have unmerged files." msgstr "" -"Cherry-picking là không thể thá»±c hiện bởi vì bạn có những táºp tin chÆ°a được " -"hòa trá»™n." +"Không thể thá»±c hiện cherry-pick vì bạn có những táºp tin chÆ°a được hòa trá»™n." msgid "Committing is not possible because you have unmerged files." msgstr "" -"Không thể thá»±c hiện chuyển giao được bởi vì bạn có những táºp tin chÆ°a được " -"hòa trá»™n." +"Không thể thá»±c hiện chuyển giao vì bạn có những táºp tin chÆ°a được hòa trá»™n." msgid "Merging is not possible because you have unmerged files." msgstr "" -"Không thể thá»±c hiện hòa trá»™n bởi vì bạn có những táºp tin chÆ°a được hòa trá»™n." +"Không thể thá»±c hiện hòa trá»™n vì bạn có những táºp tin chÆ°a được hòa trá»™n." msgid "Pulling is not possible because you have unmerged files." -msgstr "" -"Không thể thá»±c hiện kéo vá» bởi vì bạn có những táºp tin chÆ°a được hòa trá»™n." +msgstr "Không thể thá»±c hiện kéo vá» vì bạn có những táºp tin chÆ°a được hòa trá»™n." msgid "Reverting is not possible because you have unmerged files." msgstr "" -"Không thể thá»±c hiện hoà n nguyên bởi vì bạn có những táºp tin chÆ°a được hòa " -"trá»™n." +"Không thể thá»±c hiện hoà n nguyên vì bạn có những táºp tin chÆ°a được hòa trá»™n." -#, c-format -msgid "It is not possible to %s because you have unmerged files." +msgid "Rebasing is not possible because you have unmerged files." msgstr "" -"Việc nà y không thể thá»±c hiện vá»›i %s bởi vì bạn có những táºp tin chÆ°a được " -"hòa trá»™n." +"Không thể thá»±c hiện hoà n nguyên vì bạn có những táºp tin chÆ°a được hòa trá»™n." 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 "" -"Sá»a chúng trong cây là m việc, và sau đó dùng lệnh “git add/rm <táºp-tin>â€\n" -"dà nh riêng cho việc đánh dấu cần giải quyết và tạo lần chuyển giao." +"Sá»a chúng trong cây là m việc, và sau đó dùng lệnh 'git add/rm <táºp-tin>'\n" +"để chá»n cách giải quyết và tiến hà nh chuyển giao." msgid "Exiting because of an unresolved conflict." -msgstr "Thoát ra bởi vì xung Ä‘á»™t không thể giải quyết." +msgstr "Thoát vì không thể giải quyết xung Ä‘á»™t." msgid "You have not concluded your merge (MERGE_HEAD exists)." msgstr "Bạn chÆ°a kết thúc việc hòa trá»™n (MERGE_HEAD vẫn tồn tại)." @@ -670,10 +668,27 @@ msgid "Please, commit your changes before merging." msgstr "Vui lòng chuyển giao các thay đổi trÆ°á»›c khi hòa trá»™n." msgid "Exiting because of unfinished merge." -msgstr "Thoát ra bởi vì việc hòa trá»™n không hoà n tất." +msgstr "Thoát vì việc hòa trá»™n còn dang dở." + +msgid "" +"Diverging branches can't be fast-forwarded, you need to either:\n" +"\n" +"\tgit merge --no-ff\n" +"\n" +"or:\n" +"\n" +"\tgit rebase\n" +msgstr "" +"Không thể chuyển-tiếp-nhanh các nhánh phân kỳ, bạn cần dùng:\n" +"\n" +"\tgit merge --no-ff\n" +"\n" +"hoặc:\n" +"\n" +"\tgit rebase\n" msgid "Not possible to fast-forward, aborting." -msgstr "Thá»±c hiện lệnh chuyển-tiếp-nhanh là không thể được, Ä‘ang bá» qua." +msgstr "Không thể chuyển-tiếp-nhanh, Ä‘ang huá»· lệnh." #, c-format msgid "" @@ -683,7 +698,7 @@ msgid "" msgstr "" "Các Ä‘Æ°á»ng dẫn và /hoặc đặc tả Ä‘Æ°á»ng dẫn sau đây khá»›p vá»›i các Ä‘Æ°á»ng dẫn tồn " "tại\n" -"bên ngoà i định nghÄ©a “sparse-checkout†của bạn, vì váºy sẽ không\n" +"bên ngoà i định nghÄ©a 'sparse-checkout' của bạn, vì váºy sẽ không\n" "cáºp nháºt trong chỉ mục:\n" msgid "" @@ -693,7 +708,7 @@ msgid "" msgstr "" "Nếu bạn có ý định cáºp nháºt các mục nhÆ° váºy, hãy thá» má»™t trong các mục sau:\n" "* Sá» dụng tùy chá»n --sparse.\n" -"* Vô hiệu hóa hoặc sá»a đổi các quy tắc thÆ°a thá»›t." +"* Vô hiệu hóa hoặc sá»a đổi sparse rules (luáºt thÆ°a)." #, c-format msgid "" @@ -716,14 +731,14 @@ msgid "" "false\n" "\n" msgstr "" -"Chú ý: Ä‘ang chuyển sang “%sâ€.\n" +"Chú ý: Ä‘ang chuyển sang '%s'.\n" "\n" -"Bạn Ä‘ang ở tình trạng “detached HEADâ€. Bạn có thể xem qua, tạo các thay\n" -"đổi thá» nghiệm và chuyển giao chúng, bạn có thể loại bá» bất kỳ lần chuyển\n" -"giao nà o trong tình trạng nà y mà không cần đụng chạm đến bất kỳ nhánh nà o\n" +"Bạn Ä‘ang ở tình trạng 'detached HEAD'. Bạn có thể xem qua, tạo và \n" +"chuyển giao các thay đổi thá» nghiệm, và bạn có thể loại bá» các lần chuyển\n" +"giao trong trạng thái nà y mà không ảnh hưởng đến bất kỳ nhánh nà o\n" "bằng cách chuyển trở lại má»™t nhánh.\n" "\n" -"Nếu bạn muốn tạo má»™t nhánh má»›i để giữ lại các lần chuyển giao bạn tạo,\n" +"Nếu bạn muốn tạo má»™t nhánh má»›i để giữ lại các lần chuyển giao đã tạo,\n" "bạn có thể là m thế (ngay bây giá» hay sau nà y) bằng cách dùng tùy chá»n\n" "dòng lệnh -c. Và dụ:\n" "\n" @@ -736,19 +751,41 @@ msgstr "" "Tắt hÆ°á»›ng dẫn nà y bằng cách đặt biến advice.detachedHead thà nh false\n" "\n" +#, c-format +msgid "" +"The following paths have been moved outside the\n" +"sparse-checkout definition but are not sparse due to local\n" +"modifications.\n" +msgstr "" +"Các Ä‘Æ°á»ng dẫn sau đã được di chuyển ra ngoà i định nghÄ©a\n" +"sparse-checkout nhÆ°ng không còn thuá»™c loại sparse (thÆ°a) vì có\n" +"thay đổi ná»™i bá»™.\n" + +msgid "" +"To correct the sparsity of these paths, do the following:\n" +"* Use \"git add --sparse <paths>\" to update the index\n" +"* Use \"git sparse-checkout reapply\" to apply the sparsity rules" +msgstr "" +"Äể sá»a lại đúng loại sprase (thÆ°a) của các táºp nà y, hãy thá»±c hiện:\n" +"* Chạy \"git add --sparse <Ä‘Æ°á»ng-dẫn>\" để cáºp nháºt chỉ mục\n" +"* Chạy \"git sparse-checkout reapply\" để áp dụng luáºt thÆ°a" + msgid "cmdline ends with \\" -msgstr "cmdline kết thúc vá»›i \\" +msgstr "cuối dòng lệnh có \\" msgid "unclosed quote" msgstr "chÆ°a có dấu nháy đóng" +msgid "too many arguments" +msgstr "có quá nhiá»u đối số" + #, c-format msgid "unrecognized whitespace option '%s'" -msgstr "không nháºn ra tùy chá»n vá» khoảng trắng “%sâ€" +msgstr "không nháºn ra tùy chá»n vá» khoảng trắng '%s'" #, c-format msgid "unrecognized whitespace ignore option '%s'" -msgstr "không nháºn ra tùy chá»n bá» qua khoảng trắng “%sâ€" +msgstr "không nháºn ra tùy chá»n bá» qua khoảng trắng '%s'" #, c-format msgid "options '%s' and '%s' cannot be used together" @@ -756,13 +793,17 @@ msgstr "tùy chá»n '%s' và '%s' không thể dùng cùng nhau" #, c-format msgid "'%s' outside a repository" -msgstr "'%s' ở ngoà i má»™t kho chứa" +msgstr "'%s' ở ngoà i kho chứa" + +msgid "failed to read patch" +msgstr "gặp lá»—i khi Ä‘á»c bản vá" + +msgid "patch too large" +msgstr "bản vá quá lá»›n" #, c-format msgid "Cannot prepare timestamp regexp %s" -msgstr "" -"Không thể chuẩn bị biểu thức chÃnh qui dấu vết thá»i gian (timestamp regexp) " -"%s" +msgstr "Không thể chuẩn bị biểu thức chÃnh quy dấu thá»i gian%s" #, c-format msgid "regexec returned %d for input: %s" @@ -770,12 +811,11 @@ msgstr "thi hà nh biểu thức chÃnh quy trả vá» %d cho đầu và o: %s" #, c-format msgid "unable to find filename in patch at line %d" -msgstr "không thể tìm thấy tên táºp tin trong miếng vá tại dòng %d" +msgstr "không thể tìm thấy tên táºp tin trong bản vá tại dòng %d" #, c-format msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d" -msgstr "" -"git apply: git-diff sai - cần /dev/null, nhÆ°ng lại nháºn được %s trên dòng %d" +msgstr "git apply: git-diff sai - cần /dev/null, nhÆ°ng lại có %s trên dòng %d" #, c-format msgid "git apply: bad git-diff - inconsistent new filename on line %d" @@ -787,7 +827,7 @@ msgstr "git apply: git-diff sai - tên táºp tin cÅ© không nhất quán trên d #, c-format msgid "git apply: bad git-diff - expected /dev/null on line %d" -msgstr "git apply: git-diff sai - cần “/dev/null†trên dòng %d" +msgstr "git apply: git-diff sai - cần '/dev/null' trên dòng %d" #, c-format msgid "invalid mode on line %d: %s" @@ -795,7 +835,7 @@ msgstr "chế Ä‘á»™ không hợp lệ trên dòng %d: %s" #, c-format msgid "inconsistent header lines %d and %d" -msgstr "phần đầu mâu thuẫn dòng %d và %d" +msgstr "phần đầu không nhất quán tại dòng %d và %d" #, c-format msgid "" @@ -805,8 +845,8 @@ msgid_plural "" "git diff header lacks filename information when removing %d leading pathname " "components (line %d)" msgstr[0] "" -"phần đầu diff cho git thiếu thông tin tên táºp tin khi gỡ bá» Ä‘i %d trong " -"thà nh phần dẫn đầu tên của Ä‘Æ°á»ng dẫn (dòng %d)" +"phần đầu diff cho git thiếu thông tin tên táºp tin khi xoá Ä‘i %d mục dẫn đầu " +"trong tên của Ä‘Æ°á»ng dẫn (dòng %d)" #, c-format msgid "git diff header lacks filename information (line %d)" @@ -814,11 +854,11 @@ msgstr "phần đầu diff cho git thiếu thông tin tên táºp tin (dòng %d)" #, c-format msgid "recount: unexpected line: %.*s" -msgstr "chi tiết: dòng không cần: %.*s" +msgstr "recount: dòng bất thÆ°á»ng %.*s" #, c-format msgid "patch fragment without header at line %d: %.*s" -msgstr "miếng vá phân mảnh mà không có phần đầu tại dòng %d: %.*s" +msgstr "bản vá không có phần đầu tại dòng %d: %.*s" msgid "new file depends on old contents" msgstr "táºp tin má»›i phụ thuá»™c và o ná»™i dung cÅ©" @@ -828,7 +868,7 @@ msgstr "táºp tin đã xóa vẫn còn ná»™i dung" #, c-format msgid "corrupt patch at line %d" -msgstr "miếng vá há»ng tại dòng %d" +msgstr "bản vá há»ng tại dòng %d" #, c-format msgid "new file %s depends on old contents" @@ -844,15 +884,15 @@ msgstr "** cảnh báo: táºp tin %s trở nên trống rá»—ng nhÆ°ng không bá» #, c-format msgid "corrupt binary patch at line %d: %.*s" -msgstr "miếng vá định dạng nhị phân sai há»ng tại dòng %d: %.*s" +msgstr "bản vá nhị phân há»ng tại dòng %d: %.*s" #, c-format msgid "unrecognized binary patch at line %d" -msgstr "miếng vá định dạng nhị phân không được nháºn ra tại dòng %d" +msgstr "bản vá nhị phân không thể nháºn diện tại dòng %d" #, c-format msgid "patch with only garbage at line %d" -msgstr "vá chỉ vá»›i “rác†tại dòng %d" +msgstr "bản vá chứa 'rác' tại dòng %d" #, c-format msgid "unable to read symlink %s" @@ -864,64 +904,59 @@ msgstr "không thể mở hay Ä‘á»c %s" #, c-format msgid "invalid start of line: '%c'" -msgstr "sai khởi đầu dòng: “%câ€" +msgstr "sai khởi đầu dòng: '%c'" #, c-format msgid "Hunk #%d succeeded at %d (offset %d line)." msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." -msgstr[0] "Khối dữ liệu #%d thà nh công tại %d (offset %d dòng)." +msgstr[0] "Khối thứ %d thà nh công tại %d (offset %d dòng)." #, c-format msgid "Context reduced to (%ld/%ld) to apply fragment at %d" -msgstr "Ngữ cảnh bị giảm xuống còn (%ld/%ld) để áp dụng mảnh dữ liệu tại %d" +msgstr "Ngữ cảnh bị giảm xuống còn (%ld/%ld) để áp dụng bản vá tại %d" #, c-format msgid "" "while searching for:\n" "%.*s" msgstr "" -"trong khi Ä‘ang tìm kiếm cho:\n" +"trong khi Ä‘ang tìm kiếm:\n" "%.*s" #, c-format msgid "missing binary patch data for '%s'" -msgstr "thiếu dữ liệu của miếng vá định dạng nhị phân cho “%sâ€" +msgstr "thiếu dữ liệu của bản vá nhị phân cho '%s'" #, c-format msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'" -msgstr "" -"không thể reverse-apply má»™t miếng vá nhị phân mà không đảo ngược khúc thà nh " -"“%sâ€" +msgstr "không thể đảo ngược bản vá nhị phân mà không có khúc ngược cho '%s'" #, c-format msgid "cannot apply binary patch to '%s' without full index line" msgstr "" -"không thể áp dụng miếng vá nhị phân thà nh “%s†mà không có dòng chỉ mục đầy " -"đủ" +"không thể áp dụng bản vá nhị phân cho '%s' mà không có dòng chỉ mục đầy đủ" #, c-format msgid "" "the patch applies to '%s' (%s), which does not match the current contents." -msgstr "" -"miếng vá áp dụng cho “%s†(%s), cái mà không khá»›p vá»›i các ná»™i dung hiện tại." +msgstr "bản vá áp dụng cho '%s' (%s), nhÆ°ng không khá»›p vá»›i ná»™i dung hiện tại." #, c-format msgid "the patch applies to an empty '%s' but it is not empty" -msgstr "miếng vá áp dụng cho má»™t “%s†trống rá»—ng nhÆ°ng nó lại không trống" +msgstr "bản vá áp dụng cho '%s' trống rá»—ng nhÆ°ng nó lại không trống" #, c-format msgid "the necessary postimage %s for '%s' cannot be read" -msgstr "không thể Ä‘á»c postimage %s cần thiết cho “%sâ€" +msgstr "không thể Ä‘á»c háºu ảnh %s cần thiết cho '%s'" #, c-format msgid "binary patch does not apply to '%s'" -msgstr "miếng vá định dạng nhị phân không được áp dụng cho “%sâ€" +msgstr "bản vá nhị phân không được áp dụng cho '%s'" #, c-format msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" msgstr "" -"vá nhị phân cho “%s†tạo ra kết quả không chÃnh xác (mong chá» %s, lại nháºn " -"%s)" +"bản vá nhị phân cho '%s' cho ra kết quả không chÃnh xác (cần %s, lại nháºn %s)" #, c-format msgid "patch failed: %s:%ld" @@ -929,7 +964,7 @@ msgstr "gặp lá»—i khi vá: %s:%ld" #, c-format msgid "cannot checkout %s" -msgstr "không thể lấy ra %s" +msgstr "không thể checkout %s" #, c-format msgid "failed to read %s" @@ -937,7 +972,7 @@ msgstr "gặp lá»—i khi Ä‘á»c %s" #, c-format msgid "reading from '%s' beyond a symbolic link" -msgstr "Ä‘á»c từ “%s†vượt ra ngoà i liên kết má»m" +msgstr "Ä‘á»c từ '%s' đứng sau liên kết má»m" #, c-format msgid "path %s has been renamed/deleted" @@ -945,41 +980,42 @@ msgstr "Ä‘Æ°á»ng dẫn %s đã bị xóa hoặc đổi tên" #, c-format msgid "%s: does not exist in index" -msgstr "%s: không tồn tại trong bảng mục lục" +msgstr "%s: không tồn tại trong chỉ mục" #, c-format msgid "%s: does not match index" -msgstr "%s: không khá»›p trong mục lục" +msgstr "%s: không khá»›p vá»›i chỉ mục" msgid "repository lacks the necessary blob to perform 3-way merge." -msgstr "kho thiếu đối tượng blob cần thiết để thá»±c hiện hòa trá»™n “3-wayâ€." +msgstr "" +"kho thiếu đối tượng blob cần thiết để thá»±c hiện hòa trá»™n kiểu three-way." #, c-format msgid "Performing three-way merge...\n" -msgstr "Äang thá»±c hiện hòa trá»™n “3-Ä‘Æ°á»ngâ€â€¦\n" +msgstr "Äang thá»±c hiện hòa trá»™n three-way...\n" #, c-format msgid "cannot read the current contents of '%s'" -msgstr "không thể Ä‘á»c ná»™i dung hiện hà nh của “%sâ€" +msgstr "không thể Ä‘á»c ná»™i dung hiện hà nh của '%s'" #, c-format msgid "Failed to perform three-way merge...\n" -msgstr "Gặp lá»—i khi thá»±c hiện hòa trá»™n kiểu “three-wayâ€â€¦\n" +msgstr "Gặp lá»—i khi thá»±c hiện hòa trá»™n kiểu three-way...\n" #, c-format msgid "Applied patch to '%s' with conflicts.\n" -msgstr "Äã áp dụng miếng vá %s vá»›i các xung Ä‘á»™t.\n" +msgstr "Ãp dụng bản vá '%s' còn các xung Ä‘á»™t.\n" #, c-format msgid "Applied patch to '%s' cleanly.\n" -msgstr "Äã áp dụng miếng vá %s má»™t cách sạch sẽ.\n" +msgstr "Ãp dụng bản vá %s má»™t cách hoà n toà n.\n" #, c-format msgid "Falling back to direct application...\n" -msgstr "Äang trở lại ứng dụng chi phối…\n" +msgstr "Äang trở vá» cách áp dụng trá»±c tiếp..\n" msgid "removal patch leaves file contents" -msgstr "loại bá» miếng vá để lại ná»™i dung táºp tin" +msgstr "bản vá để lại táºp tin còn ná»™i dung" #, c-format msgid "%s: wrong type" @@ -991,15 +1027,15 @@ msgstr "%s có kiểu %o, cần %o" #, c-format msgid "invalid path '%s'" -msgstr "Ä‘Æ°á»ng dẫn không hợp lệ “%sâ€" +msgstr "Ä‘Æ°á»ng dẫn không hợp lệ '%s'" #, c-format msgid "%s: already exists in index" -msgstr "%s: đã có từ trÆ°á»›c trong bảng mục lục" +msgstr "%s: đã sẵn có trong chỉ mục" #, c-format msgid "%s: already exists in working directory" -msgstr "%s: đã sẵn có trong thÆ° mục Ä‘ang là m việc" +msgstr "%s: đã sẵn có trong thÆ° mục là m việc" #, c-format msgid "new mode (%o) of %s does not match old mode (%o)" @@ -1011,15 +1047,15 @@ msgstr "chế Ä‘á»™ má»›i (%o) của %s không khá»›p vá»›i chế Ä‘á»™ cÅ© (%o) #, c-format msgid "affected file '%s' is beyond a symbolic link" -msgstr "táºp tin chịu tác Ä‘á»™ng “%s†vượt ra ngoà i liên kết má»m" +msgstr "táºp tin chịu tác Ä‘á»™ng '%s' đứng sau liên kết má»m" #, c-format msgid "%s: patch does not apply" -msgstr "%s: miếng vá không được áp dụng" +msgstr "%s: bản vá không được áp dụng" #, c-format msgid "Checking patch %s..." -msgstr "Äang kiểm tra miếng vá %s…" +msgstr "Äang kiểm tra bản vá %s..." #, c-format msgid "sha1 information is lacking or useless for submodule %s" @@ -1027,35 +1063,35 @@ msgstr "thông tin sha1 thiếu hoặc không dùng được cho mô-Ä‘un %s" #, c-format msgid "mode change for %s, which is not in current HEAD" -msgstr "thay đổi chế Ä‘á»™ cho %s, cái mà không phải là HEAD hiện tại" +msgstr "thay đổi chế Ä‘á»™ cho %s, nhÆ°ng nó không nằm trong HEAD hiện tại" #, c-format msgid "sha1 information is lacking or useless (%s)." -msgstr "thông tin sha1 còn thiếu hay không dùng được(%s)." +msgstr "thông tin sha1 còn thiếu hay không dùng được (%s)." #, c-format msgid "could not add %s to temporary index" -msgstr "không thể thêm %s và o chỉ mục tạm thá»i" +msgstr "không thể thêm %s và o chỉ mục tạm" #, c-format msgid "could not write temporary index to %s" -msgstr "không thể ghi mục lục tạm và o %s" +msgstr "không thể ghi chỉ mục tạm và o %s" #, c-format msgid "unable to remove %s from index" -msgstr "không thể gỡ bá» %s từ mục lục" +msgstr "không thể gỡ bá» %s từ chỉ mục" #, c-format msgid "corrupt patch for submodule %s" -msgstr "miếng vá sai há»ng cho mô-Ä‘un-con %s" +msgstr "bản vá há»ng cho mô-Ä‘un-con %s" #, c-format msgid "unable to stat newly created file '%s'" -msgstr "không thể lấy thống kê vá» táºp tin %s má»›i hÆ¡n đã được tạo" +msgstr "không thể stat táºp tin '%s' má»›i tạo" #, c-format msgid "unable to create backing store for newly created file %s" -msgstr "không thể tạo “kho lÆ°u đằng sau†cho táºp tin được tạo má»›i hÆ¡n %s" +msgstr "không thể tạo 'backing store' cho táºp tin má»›i tạo %s" #, c-format msgid "unable to add cache entry for %s" @@ -1063,19 +1099,19 @@ msgstr "không thể thêm mục nhá»› đệm cho %s" #, c-format msgid "failed to write to '%s'" -msgstr "gặp lá»—i khi ghi và o “%sâ€" +msgstr "gặp lá»—i khi ghi và o '%s'" #, c-format msgid "closing file '%s'" -msgstr "Ä‘ang đóng táºp tin “%sâ€" +msgstr "Ä‘ang đóng táºp tin '%s'" #, c-format msgid "unable to write file '%s' mode %o" -msgstr "không thể ghi và o táºp tin “%s†chế Ä‘á»™ %o" +msgstr "không thể ghi và o táºp tin '%s' chế Ä‘á»™ %o" #, c-format msgid "Applied patch %s cleanly." -msgstr "Äã áp dụng miếng vá %s má»™t cách sạch sẽ." +msgstr "Äã áp dụng bản vá %s má»™t cách hoà n toà n." msgid "internal error" msgstr "lá»—i ná»™i bá»™" @@ -1083,43 +1119,43 @@ msgstr "lá»—i ná»™i bá»™" #, c-format msgid "Applying patch %%s with %d reject..." msgid_plural "Applying patch %%s with %d rejects..." -msgstr[0] "Äang áp dụng miếng vá %%s vá»›i %d lần từ chối…" +msgstr[0] "Äang áp dụng bản vá %%s vá»›i %d lần từ chối..." #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "Ä‘ang cắt ngắn tên táºp tin .rej thà nh %.*s.rej" +msgid "cannot open %s" +msgstr "không thể mở '%s'" #, c-format -msgid "cannot open %s" -msgstr "không mở được “%sâ€" +msgid "cannot unlink '%s'" +msgstr "không thể unlink '%s'" #, c-format msgid "Hunk #%d applied cleanly." -msgstr "Khối nhá»› #%d được áp dụng gá»n gà ng." +msgstr "Khúc #%d được áp dụng hoà n toà n." #, c-format msgid "Rejected hunk #%d." -msgstr "Äoạn dữ liệu #%d bị từ chối." +msgstr "Khúc #%d bị từ chối." #, c-format msgid "Skipped patch '%s'." -msgstr "Bá» qua Ä‘Æ°á»ng dẫn “%sâ€." +msgstr "Bá» qua Ä‘Æ°á»ng dẫn '%s'." msgid "No valid patches in input (allow with \"--allow-empty\")" msgstr "" -"Không có miếng vá hợp lệ nà o trong đầu và o (cho phép vá»›i \"--allow-empty\")" +"Không có bản vá hợp lệ nà o trong đầu và o (cho phép vá»›i \"--allow-empty\")" msgid "unable to read index file" -msgstr "không thể Ä‘á»c táºp tin lÆ°u bảng mục lục" +msgstr "không thể Ä‘á»c táºp tin chỉ mục" #, c-format msgid "can't open patch '%s': %s" -msgstr "không thể mở miếng vá “%sâ€: %s" +msgstr "không thể mở bản vá '%s': %s" #, c-format msgid "squelched %d whitespace error" msgid_plural "squelched %d whitespace errors" -msgstr[0] "đã chấm dứt %d lá»—i khoảng trắng" +msgstr[0] "đã xá» lý %d lá»—i khoảng trắng" #, c-format msgid "%d line adds whitespace errors." @@ -1132,7 +1168,7 @@ msgid_plural "%d lines applied after fixing whitespace errors." msgstr[0] "%d dòng được áp dụng sau khi sá»a các lá»—i khoảng trắng." msgid "Unable to write new index file" -msgstr "Không thể ghi táºp tin lÆ°u bảng mục lục má»›i" +msgstr "Không thể ghi táºp tin chỉ mục má»›i" msgid "don't apply changes matching the given path" msgstr "không áp dụng các thay đổi khá»›p vá»›i Ä‘Æ°á»ng dẫn đã cho" @@ -1144,52 +1180,46 @@ msgid "num" msgstr "số" msgid "remove <num> leading slashes from traditional diff paths" -msgstr "gỡ bá» <số> dấu gạch chéo dẫn đầu từ Ä‘Æ°á»ng dẫn diff cổ Ä‘iển" +msgstr "gỡ bá» <số> dấu gạch chéo dẫn đầu từ Ä‘Æ°á»ng dẫn diff" msgid "ignore additions made by the patch" -msgstr "lá» Ä‘i phần bổ xung được tạo ra bởi miếng vá" +msgstr "bá» qua các bổ sung trong bản vá" msgid "instead of applying the patch, output diffstat for the input" -msgstr "" -"thay vì áp dụng má»™t miếng vá, kết xuất kết quả từ lệnh diffstat cho đầu ra" +msgstr "thay vì áp dụng bản vá, xuất kết quả diffstat cho đầu và o" msgid "show number of added and deleted lines in decimal notation" -msgstr "" -"hiển thị số lượng các dòng được thêm và o và xóa Ä‘i theo ký hiệu tháºp phân" +msgstr "hiển thị số lượng các dòng được thêm và o và xóa Ä‘i theo hệ tháºp phân" msgid "instead of applying the patch, output a summary for the input" -msgstr "thay vì áp dụng má»™t miếng vá, kết xuất kết quả cho đầu và o" +msgstr "thay vì áp dụng bản vá, xuất tóm tắt kết quả cho đầu và o" msgid "instead of applying the patch, see if the patch is applicable" -msgstr "thay vì áp dụng miếng vá, hãy xem xem miếng vá có thÃch hợp không" +msgstr "thay vì áp dụng bản vá, xem xem bản vá có thÃch hợp không" msgid "make sure the patch is applicable to the current index" -msgstr "hãy chắc chắn là miếng vá thÃch hợp vá»›i bảng mục lục hiện hà nh" +msgstr "kiểm tra chắc chắn là bản vá thÃch hợp vá»›i chỉ mục hiện hà nh" msgid "mark new files with `git add --intent-to-add`" -msgstr "đánh dấu các táºp tin má»›i vá»›i “git add --intent-to-addâ€" +msgstr "đánh dấu các táºp tin má»›i vá»›i 'git add --intent-to-add'" msgid "apply a patch without touching the working tree" -msgstr "áp dụng má»™t miếng vá mà không Ä‘á»™ng chạm đến cây là m việc" +msgstr "áp dụng bản vá mà không Ä‘á»™ng chạm đến cây là m việc" msgid "accept a patch that touches outside the working area" -msgstr "chấp nháºn má»™t miếng vá mà không Ä‘á»™ng chạm đến cây là m việc" +msgstr "chấp nháºn bản vá có Ä‘á»™ng chạm đến ngoà i cây là m việc" msgid "also apply the patch (use with --stat/--summary/--check)" -msgstr "" -"đồng thá»i áp dụng miếng vá (dùng vá»›i tùy chá»n --stat/--summary/--check)" +msgstr "đồng thá»i áp dụng bản vá (dùng vá»›i tùy chá»n --stat/--summary/--check)" 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 dán bình thÆ°á»ng nếu không thể thá»±c " -"hiện được" +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 "build a temporary index based on embedded index information" -msgstr "" -"xây dá»±ng bảng mục lục tạm thá»i trên cÆ¡ sở thông tin bảng mục lục được nhúng" +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" msgid "paths are separated with NUL character" -msgstr "các Ä‘Æ°á»ng dẫn bị ngăn cách bởi ký tá»± NULL" +msgstr "các Ä‘Æ°á»ng dẫn được ngăn cách bởi ký tá»± NULL" msgid "ensure at least <n> lines of context match" msgstr "đảm bảo rằng có Ãt nhất <n> dòng ngữ cảnh khá»›p" @@ -1198,22 +1228,22 @@ msgid "action" msgstr "hà nh Ä‘á»™ng" msgid "detect new or modified lines that have whitespace errors" -msgstr "tìm thấy má»™t dòng má»›i hoặc bị sá»a đổi mà nó có lá»—i do khoảng trắng" +msgstr "tìm thấy dòng má»›i hoặc dòng bị sá»a đổi có lá»—i khoảng trắng" msgid "ignore changes in whitespace when finding context" -msgstr "lá» Ä‘i sá»± thay đổi do khoảng trắng gây ra khi tìm ngữ cảnh" +msgstr "bá» qua sá»± thay đổi do khoảng trắng gây ra khi tìm ngữ cảnh" msgid "apply the patch in reverse" -msgstr "áp dụng miếng vá theo chiá»u ngược" +msgstr "áp dụng bản vá theo chiá»u ngược" msgid "don't expect at least one line of context" msgstr "đừng hy vá»ng có Ãt nhất má»™t dòng ngữ cảnh" msgid "leave the rejected hunks in corresponding *.rej files" -msgstr "để lại khối dữ liệu bị từ chối trong các táºp tin *.rej tÆ°Æ¡ng ứng" +msgstr "để lại khối bị từ chối trong các táºp tin *.rej tÆ°Æ¡ng ứng" msgid "allow overlapping hunks" -msgstr "cho phép chồng khối nhá»›" +msgstr "cho phép chồng khối" msgid "tolerate incorrectly detected missing new-line at the end of file" msgstr "" @@ -1226,65 +1256,69 @@ msgid "root" msgstr "gốc" msgid "prepend <root> to all filenames" -msgstr "treo thêm <root> và o tất cả các tên táºp tin" +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 miếng vá trống rá»—ng" +msgstr "đừng trả vá» lá»—i khi các bản vá trống rá»—ng" #, c-format msgid "cannot stream blob %s" -msgstr "không thể stream blob “%sâ€" +msgstr "không thể stream blob '%s'" #, c-format msgid "unsupported file mode: 0%o (SHA1: %s)" msgstr "chế Ä‘á»™ táºp tin không được há»— trợ: 0%o (SHA1: %s)" #, c-format +msgid "deflate error (%d)" +msgstr "lá»—i giải nén (%d)" + +#, c-format msgid "unable to start '%s' filter" -msgstr "không thể bắt đầu bá»™ lá»c “%sâ€" +msgstr "không thể khởi chạy bá»™ lá»c '%s'" msgid "unable to redirect descriptor" -msgstr "không thể chuyển hÆ°á»›ng mô tả" +msgstr "không thể chuyển hÆ°á»›ng và o/ra" #, c-format msgid "'%s' filter reported error" -msgstr "bá»™ lá»c “%s†đã báo cáo lá»—i" +msgstr "bá»™ lá»c '%s' đã báo lá»—i" #, c-format msgid "path is not valid UTF-8: %s" -msgstr "Ä‘Æ°á»ng dẫn không hợp lệ UTF-8: %s" +msgstr "Ä‘Æ°á»ng dẫn không hợp lệ theo UTF-8: %s" #, c-format msgid "path too long (%d chars, SHA1: %s): %s" msgstr "Ä‘Æ°á»ng dẫn quá dà i (%d ký tá»±, SHA1: %s): %s" #, c-format -msgid "deflate error (%d)" -msgstr "lá»—i giải nén (%d)" - -#, c-format msgid "timestamp too large for this system: %<PRIuMAX>" -msgstr "dấu vết thá»i gian là quá lá»›n cho hệ thống nà y: %<PRIuMAX>" +msgstr "dấu thá»i gian là quá lá»›n cho hệ thống nà y: %<PRIuMAX>" msgid "git archive [<options>] <tree-ish> [<path>...]" -msgstr "git archive [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>…]" +msgstr "git archive [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>...]" msgid "" "git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]" msgstr "" "git archive --remote <kho> [--exec <lệnh>] [<các tùy chá»n>] <tree-ish> [</" -"Ä‘Æ°á»ng/dẫn>…]" +"Ä‘Æ°á»ng/dẫn>...]" msgid "git archive --remote <repo> [--exec <cmd>] --list" msgstr "git archive --remote <kho> [--exec <lệnh>] --list" #, c-format msgid "cannot read '%s'" -msgstr "không thể Ä‘á»c “%sâ€" +msgstr "không thể Ä‘á»c '%s'" + +#, c-format +msgid "pathspec '%s' matches files outside the current directory" +msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' nằm ngoà i thÆ° mục hiện hà nh" #, c-format msgid "pathspec '%s' did not match any files" -msgstr "đặc tả Ä‘Æ°á»ng dẫn “%s†không khá»›p vá»›i bất kỳ táºp tin nà o" +msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' không khá»›p vá»›i bất kỳ táºp tin nà o" #, c-format msgid "no such ref: %.*s" @@ -1292,14 +1326,11 @@ msgstr "không có tham chiếu nà o nhÆ° thế: %.*s" #, c-format msgid "not a valid object name: %s" -msgstr "không phải là tên đối tượng hợp lệ: “%sâ€" +msgstr "không phải là tên đối tượng hợp lệ: %s" #, c-format msgid "not a tree object: %s" -msgstr "không phải là đối tượng cây: “%sâ€" - -msgid "current working directory is untracked" -msgstr "thÆ° mục là m việc hiện hà nh chÆ°a được theo dõi" +msgstr "không phải là đối tượng cây: %s" #, c-format msgid "File not found: %s" @@ -1307,7 +1338,7 @@ msgstr "Không tìm thấy táºp tin: %s" #, c-format msgid "Not a regular file: %s" -msgstr "Không phải má»™t táºp tin thÆ°á»ng: %s" +msgstr "Không phải táºp tin thÆ°á»ng: %s" #, c-format msgid "unclosed quote: '%s'" @@ -1315,26 +1346,26 @@ msgstr "chÆ°a có dấu nháy đóng: '%s'" #, c-format msgid "missing colon: '%s'" -msgstr "thiếu dấu hai chấm: “%sâ€" +msgstr "thiếu dấu hai chấm: '%s'" #, c-format msgid "empty file name: '%s'" -msgstr "tên táºp tin trống rá»—ng: “%sâ€" +msgstr "tên táºp tin trống: '%s'" msgid "fmt" -msgstr "định_dạng" +msgstr "định-dạng" msgid "archive format" msgstr "định dạng lÆ°u trữ" msgid "prefix" -msgstr "tiá»n_tố" +msgstr "tiá»n tố" msgid "prepend prefix to each pathname in the archive" msgstr "nối thêm tiá»n tố và o từng Ä‘Æ°á»ng dẫn táºp tin trong kho lÆ°u" msgid "file" -msgstr "táºp_tin" +msgstr "táºp tin" msgid "add untracked file to archive" msgstr "thêm các táºp tin không được theo dõi và o kho lÆ°u" @@ -1349,7 +1380,13 @@ msgid "read .gitattributes in working directory" msgstr "Ä‘á»c .gitattributes trong thÆ° mục là m việc" msgid "report archived files on stderr" -msgstr "liệt kê các táºp tin được lÆ°u trữ và o stderr (đầu ra lá»—i tiêu chuẩn)" +msgstr "liệt kê các táºp tin được lÆ°u trữ ra stderr" + +msgid "time" +msgstr "thá»i-gian" + +msgid "set modification time of archive entries" +msgstr "đặt thá»i Ä‘iểm sá»a đổi của các mục nén" msgid "set compression level" msgstr "đặt mức nén" @@ -1370,27 +1407,38 @@ msgid "path to the remote git-upload-archive command" msgstr "Ä‘Æ°á»ng dẫn đến lệnh git-upload-archive trên máy chủ" msgid "Unexpected option --remote" -msgstr "Gặp tùy chá»n không cần --remote" +msgstr "Gặp tùy chá»n bất thÆ°á»ng --remote" #, c-format msgid "the option '%s' requires '%s'" -msgstr "tùy chá»n “%s†yêu cầu “%sâ€" +msgstr "tùy chá»n '%s' yêu cầu '%s'" msgid "Unexpected option --output" -msgstr "Gặp tùy chá»n không cần --output" +msgstr "Gặp tùy chá»n bất thÆ°á»ng --output" + +#, c-format +msgid "extra command line parameter '%s'" +msgstr "thừa tham số dòng lệnh '%s'" #, c-format msgid "Unknown archive format '%s'" -msgstr "Không hiểu định dạng “%sâ€" +msgstr "Không hiểu định dạng lÆ°u trữ '%s'" #, c-format msgid "Argument not supported for format '%s': -%d" -msgstr "Tham số không được há»— trợ cho định dạng “%sâ€: -%d" +msgstr "Tham số không được há»— trợ cho định dạng '%s': -%d" #, c-format msgid "%.*s is not a valid attribute name" msgstr "%.*s không phải tên thuá»™c tÃnh hợp lệ" +msgid "unable to add additional attribute" +msgstr "Không thể thêm thuá»™c tÃnh" + +#, c-format +msgid "ignoring overly long attributes line %d" +msgstr "bá» qua dòng thuá»™c tÃnh thứ %d quá dà i" + #, c-format msgid "%s not allowed: %s:%d" msgstr "%s không được phép: %s:%d" @@ -1399,16 +1447,39 @@ msgid "" "Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." msgstr "" -"Các mẫu dạng phủ định bị cấm dùng cho các thuá»™c tÃnh của git\n" -"Dùng “\\!†cho các chuá»—i văn bản có dấu chấm than dẫn đầu." +"Các mẫu dạng phủ định bị cấm dùng cho git attribute\n" +"Dùng '\\!' cho tên có dấu chấm than dẫn đầu." + +#, c-format +msgid "cannot fstat gitattributes file '%s'" +msgstr "không thể fstat táºp tin gitattributes '%s'" + +#, c-format +msgid "ignoring overly large gitattributes file '%s'" +msgstr "bá» qua táºp tin gitattributes quá lá»›n '%s'" + +#, c-format +msgid "ignoring overly large gitattributes blob '%s'" +msgstr "bá» qua blob gitattributes quá lá»›n '%s'" + +msgid "bad --attr-source or GIT_ATTR_SOURCE" +msgstr "--attr-source hoặc GIT_ATTR_SOURCE sai" + +#, c-format +msgid "unable to stat '%s'" +msgstr "không thể stat '%s'" + +#, c-format +msgid "unable to read %s" +msgstr "không thể Ä‘á»c %s" #, c-format msgid "Badly quoted content in file '%s': %s" -msgstr "Ná»™i dung được trÃch dẫn sai trong táºp tin “%sâ€: %s" +msgstr "Ná»™i dung được trÃch dẫn sai trong táºp tin '%s': %s" #, c-format msgid "We cannot bisect more!\n" -msgstr "Chúng tôi không bisect thêm nữa!\n" +msgstr "Không bisect thêm nữa!\n" #, c-format msgid "Not a valid commit name %s" @@ -1419,16 +1490,16 @@ msgid "" "The merge base %s is bad.\n" "This means the bug has been fixed between %s and [%s].\n" msgstr "" -"Hòa trá»™n trên %s là sai.\n" -"Äiá»u đó có nghÄ©a là lá»—i đã được sá»a chữa giữa %s và [%s].\n" +"Gốc hòa trá»™n trên %s là sai.\n" +"Có nghÄ©a là lá»—i đã được sá»a chữa giữa %s và [%s].\n" #, c-format msgid "" "The merge base %s is new.\n" "The property has changed between %s and [%s].\n" msgstr "" -"Hòa trá»™n trên %s là má»›i.\n" -"Gần nhÆ° chắc chắn là có thay đổi giữa %s và [%s].\n" +"Gốc hòa trá»™n trên %s là má»›i.\n" +"Äã có thay đổi thuá»™c tÃnh giữa %s và [%s].\n" #, c-format msgid "" @@ -1436,7 +1507,7 @@ msgid "" "This means the first '%s' commit is between %s and [%s].\n" msgstr "" "Hòa trá»™n trên %s là %s.\n" -"Äiá»u đó có nghÄ©a là lần chuyển giao “%s†đầu tiên là giữa %s và [%s].\n" +"Có nghÄ©a là lần chuyển giao '%s' đầu tiên là giữa %s và [%s].\n" #, c-format msgid "" @@ -1445,7 +1516,7 @@ msgid "" "Maybe you mistook %s and %s revs?\n" msgstr "" "Má»™t số Ä‘iểm xét duyệt %s không phải tổ tiên của Ä‘iểm xét duyệt %s.\n" -"git bisect không thể là m việc đúng đắn trong trÆ°á»ng hợp nà y.\n" +"git bisect không thể là m việc đúng trong trÆ°á»ng hợp nà y.\n" "Liệu có phải bạn nhầm lẫn các Ä‘iểm %s và %s không?\n" #, c-format @@ -1454,14 +1525,13 @@ msgid "" "So we cannot be sure the first %s commit is between %s and %s.\n" "We continue anyway." msgstr "" -"hòa trá»™n trên cÆ¡ sở giữa %s và [%s] phải bị bá» qua.\n" -"Do váºy chúng tôi không thể chắc lần chuyển giao đầu tiên %s là giữa %s và " -"%s.\n" -"Chúng tôi vẫn cứ tiếp tục." +"gốc hòa trá»™n giữa %s và [%s] phải bị bá» qua.\n" +"Do váºy không thể chắc chắn lần chuyển giao %s đầu tiên là giữa %s và %s.\n" +"Vẫn tiếp tục." #, c-format msgid "Bisecting: a merge base must be tested\n" -msgstr "Bisecting: ná»n hòa trá»™n cần phải được kiểm tra\n" +msgstr "Äang bisect: gốc hòa trá»™n cần phải được kiểm tra\n" #, c-format msgid "a %s revision is needed" @@ -1469,11 +1539,15 @@ msgstr "cần má»™t Ä‘iểm xét duyệt %s" #, c-format msgid "could not create file '%s'" -msgstr "không thể tạo táºp tin “%sâ€" +msgstr "không thể tạo táºp tin '%s'" + +#, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "không thể khởi chạy 'show' cho đối tượng '%s'" #, c-format msgid "could not read file '%s'" -msgstr "không thể Ä‘á»c táºp tin “%sâ€" +msgstr "không thể Ä‘á»c táºp tin '%s'" msgid "reading bisect refs failed" msgstr "việc Ä‘á»c tham chiếu bisect gặp lá»—i" @@ -1487,13 +1561,13 @@ msgid "" "No testable commit found.\n" "Maybe you started with bad path arguments?\n" msgstr "" -"Không tìm thấy lần chuyển giao kiểm tra được nà o.\n" +"Không tìm thấy lần chuyển giao nà o kiểm tra được.\n" "Có lẽ bạn bắt đầu vá»›i các tham số Ä‘Æ°á»ng dẫn sai?\n" #, c-format msgid "(roughly %d step)" msgid_plural "(roughly %d steps)" -msgstr[0] "(Æ°á»›c chừng %d bÆ°á»›c)" +msgstr[0] "(cần khoảng chừng %d bÆ°á»›c)" #. TRANSLATORS: the last %s will be replaced with "(roughly %d #. steps)" translation. @@ -1501,13 +1575,10 @@ msgstr[0] "(Æ°á»›c chừng %d bÆ°á»›c)" #, c-format msgid "Bisecting: %d revision left to test after this %s\n" msgid_plural "Bisecting: %d revisions left to test after this %s\n" -msgstr[0] "Bisecting: còn %d Ä‘iểm xét duyệt để kiểm sau %s nà y\n" +msgstr[0] "Bisecting: còn %d Ä‘iểm xét duyệt để kiểm tra %s\n" msgid "--contents and --reverse do not blend well." -msgstr "tùy chá»n --contents và --reverse không được trá»™n và o nhau." - -msgid "cannot use --contents with final commit object name" -msgstr "không thể dùng --contents vá»›i tên đối tượng chuyển giao cuối cùng" +msgstr "tùy chá»n --contents và --reverse không nên Ä‘i vá»›i nhau." msgid "--reverse and --first-parent together require specified latest commit" msgstr "" @@ -1519,16 +1590,16 @@ msgstr "cà i đặt việc di chuyển qua các Ä‘iểm xét duyệt gặp lá»—i msgid "" "--reverse --first-parent together require range along first-parent chain" msgstr "" -"cùng sá» dụng --reverse --first-parent yêu cầu vùng cùng vá»›i chuá»—i cha-mẹ-đầu-" -"tiên" +"cùng sá» dụng --reverse và --first-parent yêu cầu vùng cùng vá»›i chuá»—i cha-mẹ-" +"đầu-tiên" #, c-format msgid "no such path %s in %s" -msgstr "không có Ä‘Æ°á»ng dẫn %s trong “%sâ€" +msgstr "không có Ä‘Æ°á»ng dẫn %s trong '%s'" #, c-format msgid "cannot read blob %s for path %s" -msgstr "không thể Ä‘á»c blob %s cho Ä‘Æ°á»ng dẫn “%sâ€" +msgstr "không thể Ä‘á»c blob %s cho Ä‘Æ°á»ng dẫn '%s'" msgid "" "cannot inherit upstream tracking configuration of multiple refs when " @@ -1539,19 +1610,19 @@ msgstr "" #, c-format msgid "not setting branch '%s' as its own upstream" -msgstr "không cà i đặt nhánh '%s' nhÆ° là thượng nguồn của nó" +msgstr "không đặt nhánh '%s' là thượng nguồn của chÃnh nó" #, c-format msgid "branch '%s' set up to track '%s' by rebasing." -msgstr "nhánh “%s†cà i đặt để theo dõi “%s†bằng cách rebase." +msgstr "nhánh '%s' cà i đặt để theo dõi '%s' bằng cách rebase." #, c-format msgid "branch '%s' set up to track '%s'." -msgstr "nhánh “%s†cà i đặt để theo dõi “%sâ€." +msgstr "nhánh '%s' cà i đặt để theo dõi '%s'." #, c-format msgid "branch '%s' set up to track:" -msgstr "nhánh “%s†cà i đặt để theo dõi:" +msgstr "nhánh '%s' cà i đặt để theo dõi:" msgid "unable to write upstream branch configuration" msgstr "không thể ghi cấu hình nhánh thượng nguồn" @@ -1562,19 +1633,17 @@ msgid "" "the remote tracking information by invoking:" msgstr "" "\n" -"Sau khi sá»a nguyên nhân gây lá»—i bạn có lẻ cần thá» sá»a\n" +"Sau khi sá»a nguyên nhân gây lá»—i bạn có thể thá» sá»a\n" "thông tin theo dõi máy chủ bằng cách gá»i lệnh:" #, c-format msgid "asked to inherit tracking from '%s', but no remote is set" -msgstr "" -"đã há»i để kế thừa theo dõi từ '%s', nhÆ°ng không có máy chủ nà o được đặt" +msgstr "đã yêu cầu kế thừa theo dõi từ '%s', nhÆ°ng chÆ°a cấu hình máy chủ nà o" #, c-format msgid "asked to inherit tracking from '%s', but no merge configuration is set" msgstr "" -"đã há»i để kế thừa theo dõi từ '%s', nhÆ°ng không có cấu hình hòa trá»™n nà o " -"được đặt" +"đã yêu cầu kế thừa theo dõi từ '%s', nhÆ°ng không có cấu hình hòa trá»™n nà o" #, c-format msgid "not tracking: ambiguous information for ref '%s'" @@ -1609,8 +1678,8 @@ msgid "" "different remotes' fetch refspecs map into different\n" "tracking namespaces." msgstr "" -"Có nhiá»u máy chủ những cái lấy ánh xạ refspecs tham chiếu theo\n" -"dõi máy chủ '%s':\n" +"Có nhiá»u máy chủ có fetch refspec ánh xạ tá»›i refspecs tham chiếu\n" +"theo dõi máy chủ '%s':\n" "%s\n" "Äây thÆ°á»ng là lá»—i cấu hình.\n" "\n" @@ -1620,25 +1689,29 @@ msgstr "" #, c-format msgid "'%s' is not a valid branch name" -msgstr "“%s†không phải là má»™t tên nhánh hợp lệ" +msgstr "'%s' không phải là má»™t tên nhánh hợp lệ" + +msgid "See `man git check-ref-format`" +msgstr "Äá»c `man git check-ref-format`" #, c-format msgid "a branch named '%s' already exists" -msgstr "đã có nhánh mang tên “%sâ€" +msgstr "đã có nhánh mang tên '%s'" #, c-format -msgid "cannot force update the branch '%s' checked out at '%s'" -msgstr "không thể ép buá»™c cáºp nháºt nhánh “%s†đã được lấy ra tại “%sâ€" +msgid "cannot force update the branch '%s' used by worktree at '%s'" +msgstr "" +"không thể ép buá»™c cáºp nháºt nhánh '%s' Ä‘ang được sá» dụng tại cây là m việc '%s'" #, c-format msgid "cannot set up tracking information; starting point '%s' is not a branch" msgstr "" -"không thể cà i đặt thông tin theo dõi; Ä‘iểm bắt đầu “%s†không phải là má»™t " +"không thể cà i đặt thông tin theo dõi; Ä‘iểm bắt đầu '%s' không phải là má»™t " "nhánh" #, c-format msgid "the requested upstream branch '%s' does not exist" -msgstr "nhánh thượng nguồn đã yêu cầu “%s†không tồn tại" +msgstr "nhánh thượng nguồn đã yêu cầu '%s' không tồn tại" msgid "" "\n" @@ -1651,95 +1724,83 @@ msgid "" "\"git push -u\" to set the upstream config as you push." msgstr "" "\n" -"Nếu bạn có ý định “cải tổ†công việc của bạn trên nhánh thượng nguồn\n" -"(upstream) cái mà đã sẵn có trên máy chủ, bạn cần chạy\n" +"Nếu bạn có ý định bắt đầu công việc của bạn trên nhánh thượng nguồn\n" +"(upstream) đã sẵn có trên máy chủ, bạn cần chạy\n" "lệnh \"git fetch\" để lấy nó vá».\n" "\n" -"Nếu bạn có ý định đẩy lên lên má»™t nhánh ná»™i bá»™ má»›i cái mà \n" -"sẽ theo dõi bản đối chiếu máy chủ của nó, bạn cần dùng lệnh\n" -"\"git push -u\" để đặt cấu hình thượng nguồn bạn muốn push." +"Nếu bạn có ý định đẩy má»™t nhánh ná»™i bá»™ má»›i mà \n" +"sẽ theo dõi nhánh trên máy chủ, bạn cần dùng lệnh\n" +"\"git push -u\" để đặt cấu hình thượng nguồn khi push." #, c-format msgid "not a valid object name: '%s'" -msgstr "không phải là tên đối tượng hợp lệ: “%sâ€" +msgstr "không phải là tên đối tượng hợp lệ: '%s'" #, c-format msgid "ambiguous object name: '%s'" -msgstr "tên đối tượng chÆ°a rõ rà ng: “%sâ€." +msgstr "tên đối tượng chÆ°a rõ rà ng: '%s'." #, c-format msgid "not a valid branch point: '%s'" -msgstr "không phải là má»™t Ä‘iểm nhánh hợp lệ: “%sâ€" +msgstr "không phải là má»™t Ä‘iểm nhánh hợp lệ: '%s'" #, c-format msgid "submodule '%s': unable to find submodule" -msgstr "mô-Ä‘un-con “%sâ€: không thể tìm thấy mô-Ä‘un-con" +msgstr "mô-Ä‘un-con '%s': không thể tìm thấy mô-Ä‘un-con" #, c-format msgid "" -"You may try updating the submodules using 'git checkout %s && git submodule " -"update --init'" +"You may try updating the submodules using 'git checkout --no-recurse-" +"submodules %s && git submodule update --init'" msgstr "" -"Bạn có thể thá» cáºp nháºt các mô-Ä‘un-con bằng cách sá» dụng 'git checkout %s && " -"git submodule update --init'" +"Bạn có thể thá» cáºp nháºt các mô-Ä‘un-con bằng cách sá» dụng 'git checkout --no-" +"recurse-submodules %s && git submodule update --init'" #, c-format msgid "submodule '%s': cannot create branch '%s'" -msgstr "mô-Ä‘un-con “%sâ€: không thể tạo nhánh “%sâ€" +msgstr "mô-Ä‘un-con '%s': không thể tạo nhánh '%s'" #, c-format -msgid "'%s' is already checked out at '%s'" -msgstr "“%s†đã được lấy ra tại “%s†rồi" - -#, c-format -msgid "HEAD of working tree %s is not updated" -msgstr "HEAD của cây là m việc %s chÆ°a được cáºp nháºt" +msgid "'%s' is already used by worktree at '%s'" +msgstr "'%s' Ä‘ang được sá» dụng tại cây là m việc '%s'" msgid "git add [<options>] [--] <pathspec>..." -msgstr "git add [<các tùy chá»n>] [--] <pathspec>…" +msgstr "git add [<các tùy chá»n>] [--] <pathspec>..." #, c-format msgid "cannot chmod %cx '%s'" -msgstr "không thể chmod %cx “%sâ€" - -#, c-format -msgid "unexpected diff status %c" -msgstr "trạng thái lệnh diff không nhÆ° mong đợi %c" - -msgid "updating files failed" -msgstr "cáºp nháºt táºp tin gặp lá»—i" - -#, c-format -msgid "remove '%s'\n" -msgstr "gỡ bỠ“%sâ€\n" +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 tÆ°Æ¡i má»›i lại bảng mục lục:" +msgstr "ÄÆ°a ra khá»i bệ phóng 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 bảng mục lụ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." -msgid "Could not write patch" -msgstr "Không thể ghi ra miếng vá" +msgid "could not read the index" +msgstr "Không thể Ä‘á»c chỉ mục" msgid "editing patch failed" -msgstr "gặp lá»—i khi sá»a miếng vá" +msgstr "gặp lá»—i khi sá»a bản vá" #, c-format -msgid "Could not stat '%s'" -msgstr "Không thể lấy thông tin thống kê vỠ“%sâ€" +msgid "could not stat '%s'" +msgstr "không thể stat '%s'" -msgid "Empty patch. Aborted." -msgstr "Miếng vá trống rá»—ng. Nên bá» qua." +msgid "empty patch. aborted" +msgstr "bản vá trống rá»—ng. huá»· bá»" #, c-format -msgid "Could not apply '%s'" -msgstr "Không thể áp dụng miếng vá “%sâ€" +msgid "could not apply '%s'" +msgstr "không thể áp dụng bản vá '%s'" msgid "The following paths are ignored by one of your .gitignore files:\n" msgstr "" -"Các Ä‘Æ°á»ng dẫn theo sau đây sẽ bị lá» Ä‘i bởi má»™t trong các táºp tin .gitignore " +"Các Ä‘Æ°á»ng dẫn theo sau đây sẽ bị bá» qua bởi má»™t trong các táºp tin .gitignore " "của bạn:\n" msgid "dry run" @@ -1752,7 +1813,7 @@ msgid "interactive picking" msgstr "sá»a bằng cách tÆ°Æ¡ng tác" msgid "select hunks interactively" -msgstr "chá»n “hunks†theo kiểu tÆ°Æ¡ng tác" +msgstr "chá»n 'hunks' theo kiểu tÆ°Æ¡ng tác" msgid "edit current diff and apply" msgstr "sá»a diff hiện nay và áp dụng nó" @@ -1764,22 +1825,19 @@ msgid "update tracked files" msgstr "cáºp nháºt các táºp tin được theo dõi" msgid "renormalize EOL of tracked files (implies -u)" -msgstr "thÆ°á»ng hóa lại EOL của các táºp tin được theo dõi (ý là -u)" +msgstr "thÆ°á»ng hóa lại EOL của các táºp tin được theo dõi (ngụ ý -u)" msgid "record only the fact that the path will be added later" msgstr "chỉ ghi lại sá»± việc mà đưá»ng dẫn sẽ được thêm và o sau" msgid "add changes from all tracked and untracked files" -msgstr "" -"thêm các thay đổi từ tất cả các táºp tin có cÅ©ng nhÆ° không được theo dõi dấu " -"vết" +msgstr "thêm các thay đổi từ tất cả các táºp tin dù được theo dõi hay không" msgid "ignore paths removed in the working tree (same as --no-all)" -msgstr "" -"lá» Ä‘i các Ä‘Æ°á»ng dẫn bị gỡ bá» trong cây thÆ° mục là m việc (giống vá»›i --no-all)" +msgstr "bá» qua các Ä‘Æ°á»ng dẫn bị xoá bá» trong cây là m việc (giống vá»›i --no-all)" msgid "don't add, only refresh the index" -msgstr "không thêm, chỉ là m tÆ°Æ¡i má»›i bảng mục lục" +msgstr "không thêm, chỉ là m má»›i chỉ mục" msgid "just skip files which cannot be added because of errors" msgstr "chie bá» qua những táºp tin mà nó không thể được thêm và o bởi vì gặp lá»—i" @@ -1789,10 +1847,11 @@ msgstr "" "kiểm tra xem - tháºm chà thiếu - táºp tin bị bá» qua trong quá trình chạy thá»" msgid "allow updating entries outside of the sparse-checkout cone" -msgstr "cho phép cáºp nháºt các mục ở ngoà i “sparse-checkout coneâ€" +msgstr "" +"cho phép cáºp nháºt các mục ở ngoà i 'sparse-checkout cone' (nón checkout thÆ°a)" msgid "override the executable bit of the listed files" -msgstr "ghi đè lên bÃt thi hà nh của các táºp tin được liệt kê" +msgstr "ghi đè lên executable bit (bÃt thá»±c thi) của các táºp tin được liệt kê" msgid "warn when adding an embedded repository" msgstr "cảnh báo khi thêm má»™t kho nhúng" @@ -1820,8 +1879,8 @@ msgstr "" "\n" "\tgit submodule add <url> %s\n" "\n" -"Nếu bạn đã thêm miếng vá nà y chỉ là sai sót, bạn có thể xóa bá»\n" -"nó khá»i mục lục bằng:\n" +"Nếu bạn đã thêm bản vá nà y chỉ là sai sót, bạn có thể xóa bá»\n" +"nó khá»i chỉ mục bằng:\n" "\n" "\tgit rm --cached %s\n" "\n" @@ -1831,21 +1890,15 @@ msgstr "" msgid "adding embedded git repository: %s" msgstr "thêm cần má»™t kho git nhúng: %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 "" -"Sá» dụng -f nếu bạn thá»±c sá»± muốn thêm chúng.\n" -"Tắt thông báo nà y bằng cách chạy lệnh\n" -"\"git config advice.addIgnoredFile false\"" +msgid "Use -f if you really want to add them." +msgstr "Dùng -f nếu bạn thá»±c sá»± muốn thêm chúng" msgid "adding files failed" msgstr "thêm táºp tin gặp lá»—i" #, c-format msgid "--chmod param '%s' must be either -x or +x" -msgstr "--chmod tham số “%s†phải hoặc là -x hay +x" +msgstr "--chmod tham số '%s' phải hoặc là -x hay +x" #, c-format msgid "'%s' and pathspec arguments cannot be used together" @@ -1855,21 +1908,18 @@ msgstr "'%s' và các tham số đặc tả Ä‘Æ°á»ng dẫn không thể dùng c msgid "Nothing specified, nothing added.\n" msgstr "Không có gì được chỉ ra, không có gì được thêm và o.\n" -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"Có lẽ bạn muốn chạy “git add .â€?\n" -"Tắt thông báo nà y bằng cách chạy lệnh\n" -"\"git config advice.addEmptyPathspec false\"" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "Có lẽ là bạn muốn dùng 'git add .'?" msgid "index file corrupt" -msgstr "táºp tin ghi bảng mục lục bị há»ng" +msgstr "táºp tin ghi chỉ mục bị há»ng" + +msgid "unable to write new index file" +msgstr "không thể ghi táºp tin chỉ mục má»›i" #, c-format msgid "bad action '%s' for '%s'" -msgstr "thao tác sai “%s†cho “%sâ€" +msgstr "thao tác sai '%s' cho '%s'" #, c-format msgid "invalid value for '%s': '%s'" @@ -1877,44 +1927,44 @@ msgstr "giá trị không hợp lệ cho '%s': '%s'" #, c-format msgid "could not read '%s'" -msgstr "không thể Ä‘á»c “%sâ€" +msgstr "không thể Ä‘á»c '%s'" msgid "could not parse author script" -msgstr "không thể phân tÃch cú pháp văn lệnh tác giả" +msgstr "không hiểu cú pháp author script" #, c-format msgid "could not parse %s" -msgstr "không thể phân tÃch cú pháp %s" +msgstr "không hiểu cú pháp %s" #, c-format msgid "'%s' was deleted by the applypatch-msg hook" -msgstr "“%s†bị xóa bởi móc applypatch-msg" +msgstr "'%s' bị xóa bởi móc applypatch-msg" #, c-format msgid "Malformed input line: '%s'." -msgstr "Dòng đầu và o dị hình: “%sâ€." +msgstr "Dòng đầu và o sai quy cách: '%s'." #, c-format msgid "Failed to copy notes from '%s' to '%s'" -msgstr "Gặp lá»—i khi sao chép ghi chú (note) từ “%s†tá»›i “%sâ€" +msgstr "Gặp lá»—i khi sao chép ghi chú (note) từ '%s' tá»›i '%s'" msgid "fseek failed" msgstr "fseek gặp lá»—i" #, c-format msgid "could not open '%s' for reading" -msgstr "không thể mở “%s†để Ä‘á»c" +msgstr "không thể mở '%s' để Ä‘á»c" #, c-format msgid "could not open '%s' for writing" -msgstr "không thể mở “%s†để ghi" +msgstr "không thể mở '%s' để ghi" #, c-format msgid "could not parse patch '%s'" -msgstr "không thể phân tÃch cú pháp “%sâ€" +msgstr "không hiểu cú pháp '%s'" msgid "Only one StGIT patch series can be applied at once" -msgstr "Chỉ có má»™t sê-ri miếng vá StGIT được áp dụng má»™t lúc" +msgstr "Chỉ có má»™t sê-ri bản vá StGIT được áp dụng má»™t lúc" msgid "invalid timestamp" msgstr "dấu thá»i gian không hợp lệ" @@ -1926,29 +1976,30 @@ msgid "invalid timezone offset" msgstr "Ä‘á»™ lệch múi giá» không hợp lệ" msgid "Patch format detection failed." -msgstr "Dò tìm định dạng miếng vá gặp lá»—i." +msgstr "Dò tìm định dạng bản vá gặp lá»—i." #, c-format msgid "failed to create directory '%s'" msgstr "tạo thÆ° mục \"%s\" gặp lá»—i" msgid "Failed to split patches." -msgstr "Gặp lá»—i khi chia nhá» các miếng vá." +msgstr "Gặp lá»—i khi chia nhá» các bản vá." #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "Khi bạn đã giải quyết xong trục trặc nà y, hãy chạy \"%s --continue\"." +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "" +"Sau khi bạn đã giải quyết xong vấn Ä‘á», hãy chạy lệnh\"%s --continue\".\n" #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "" -"Nếu bạn muốn bá» qua miếng vá nà y, hãy chạy lệnh \"%s --skip\" để thay thế." +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "Nếu bạn muốn bá» qua bản vá nà y, hãy chạy lệnh \"%s --skip\".\n" #, 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 "" -"Äể ghi má»™t miếng vá trống rá»—ng nhÆ° má»™t lần chuyển giao rông, \"%s --allow-" -"empty\"." +"Äể ghi lại lần chuyển giao rá»—ng ứng vá»›i má»™t bản vá rá»—ng, hãy chạy \"%s --" +"allow-empty\".\n" #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." @@ -1956,7 +2007,7 @@ msgstr "Äể phục hồi lại nhánh gốc và dừng vá, hãy chạy \"%s - msgid "Patch sent with format=flowed; space at the end of lines might be lost." msgstr "" -"Miếng vá được gá»i vá»›i format=flowed; khoảng trống ở cuối của các dòng có thể " +"bản vá được gá»i vá»›i format=flowed; khoảng trống ở cuối của các dòng có thể " "bị mất." #, c-format @@ -1969,24 +2020,24 @@ msgstr "dòng định danh không hợp lệ: %.*s" #, c-format msgid "unable to parse commit %s" -msgstr "không thể phân tÃch lần chuyển giao “%sâ€" +msgstr "không thể Ä‘á»c lần chuyển giao '%s'" msgid "Repository lacks necessary blobs to fall back on 3-way merge." -msgstr "Kho thiếu đối tượng blob cần thiết để thá»±c hiện “3-way mergeâ€." +msgstr "Kho thiếu đối tượng blob cần thiết để thá»±c hiện '3-way merge'." msgid "Using index info to reconstruct a base tree..." msgstr "" -"Sá» dụng thông tin trong bảng mục lục để cấu trúc lại má»™t cây (tree) cÆ¡ sở…" +"Sá» dụng thông tin trong chỉ mục để cấu trúc lại má»™t cây (tree) cÆ¡ sở..." msgid "" "Did you hand edit your patch?\n" "It does not apply to blobs recorded in its index." msgstr "" -"Bạn đã sá»a miếng vá của mình bằng cách thủ công à ?\n" -"Nó không thể áp dụng các blob đã được ghi lại trong bảng mục lục của nó." +"Bạn đã sá»a bản vá của mình bằng cách thủ công à ?\n" +"Nó không thể áp dụng các blob đã được ghi lại trong chỉ mục của nó." msgid "Falling back to patching base and 3-way merge..." -msgstr "Äang dùng phÆ°Æ¡ng án dá»± phòng: vá bản cÆ¡ sở và “hòa trá»™n 3-Ä‘Æ°á»ngâ€â€¦" +msgstr "Äang dùng phÆ°Æ¡ng án dá»± phòng: vá bản cÆ¡ sở và 'hòa trá»™n 3-Ä‘Æ°á»ng'..." msgid "Failed to merge in the changes." msgstr "Gặp lá»—i khi trá»™n và o các thay đổi." @@ -2018,11 +2069,12 @@ msgstr "" "cả [a]: " msgid "unable to write index file" -msgstr "không thể ghi táºp tin lÆ°u mục lục" +msgstr "không thể ghi táºp tin chỉ mục" #, c-format msgid "Dirty index: cannot apply patches (dirty: %s)" -msgstr "Bảng mục lục bẩn: không thể áp dụng các miếng vá (bẩn: %s)" +msgstr "" +"chỉ mục không sạch sẽ: không thể áp dụng các bản vá (còn không sạch: %s)" #, c-format msgid "Skipping: %.*s" @@ -2033,21 +2085,21 @@ msgid "Creating an empty commit: %.*s" msgstr "Äang tạo má»™t lần chuyển giao trống rá»—ng: %.*s" msgid "Patch is empty." -msgstr "Miếng vá trống rá»—ng." +msgstr "bản vá trống rá»—ng." #, c-format msgid "Applying: %.*s" msgstr "Ãp dụng: %.*s" msgid "No changes -- Patch already applied." -msgstr "Không thay đổi gì cả -- Miếng vá đã được áp dụng rồi." +msgstr "Không thay đổi gì cả -- bản vá đã được áp dụng rồi." #, c-format msgid "Patch failed at %s %.*s" msgstr "Gặp lá»—i khi vá tại %s %.*s" msgid "Use 'git am --show-current-patch=diff' to see the failed patch" -msgstr "Dùng “git am --show-current-patch=diff†để xem miếng vá bị lá»—i" +msgstr "Dùng 'git am --show-current-patch=diff' để xem bản vá bị lá»—i" msgid "No changes - recorded it as an empty commit." msgstr "Không có thay đổi nà o - được ghi thà nh má»™t lần chuyển giao rá»—ng." @@ -2057,7 +2109,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 "" -"Không có thay đổi nà o - bạn đã quên sá» dụng lệnh “git add†à ?\n" +"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." @@ -2069,38 +2121,31 @@ 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 " +"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 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ó." - -msgid "unable to write new index file" -msgstr "không thể ghi táºp tin lÆ°u bảng mục lục má»›i" +"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ó." #, c-format msgid "Could not parse object '%s'." -msgstr "Không thể phân tÃch đối tượng “%sâ€." +msgstr "Không thể Ä‘á»c đối tượng '%s'." msgid "failed to clean index" -msgstr "gặp lá»—i khi dá»n bảng mục lục" +msgstr "gặp lá»—i khi dá»n chỉ mục" msgid "" "You seem to have moved HEAD since the last 'am' failure.\n" "Not rewinding to ORIG_HEAD" msgstr "" -"Bạn có lẽ đã có HEAD đã bị di chuyển Ä‘i kể từ lần “am†thất bại cuối cùng.\n" +"Bạn có lẽ đã có HEAD đã bị di chuyển Ä‘i kể từ lần 'am' thất bại cuối cùng.\n" "Không thể chuyển tá»›i ORIG_HEAD" #, c-format msgid "failed to read '%s'" -msgstr "gặp lá»—i khi Ä‘á»c “%sâ€" - -#, c-format -msgid "options '%s=%s' and '%s=%s' cannot be used together" -msgstr "tùy chá»n '%s=%s' và '%s=%s' không thể dùng cùng nhau" +msgstr "gặp lá»—i khi Ä‘á»c '%s'" msgid "git am [<options>] [(<mbox> | <Maildir>)...]" -msgstr "git am [<các tùy chá»n>] [(<mbox>|<Maildir>)…]" +msgstr "git am [<các tùy chá»n>] [(<mbox>|<Maildir>)...]" msgid "git am [<options>] (--continue | --skip | --abort)" msgstr "git am [<các tùy chá»n>] (--continue | --skip | --abort)" @@ -2108,11 +2153,14 @@ msgstr "git am [<các tùy chá»n>] (--continue | --skip | --abort)" msgid "run interactively" msgstr "chạy kiểu tÆ°Æ¡ng tác" +msgid "bypass pre-applypatch and applypatch-msg hooks" +msgstr "bá» qua hook pre-applypatch và applypatch-msg" + msgid "historical option -- no-op" -msgstr "tùy chá»n lịch sá» -- không-toán-tá»" +msgstr "tùy chá»n cÅ© -- không là m gì cả" msgid "allow fall back on 3way merging if needed" -msgstr "cho phép quay trở lại để hòa trá»™n kiểu “3way†nếu cần" +msgstr "cho phép quay trở lại để hòa trá»™n kiểu 3way nếu cần" msgid "be quiet" msgstr "im lặng" @@ -2135,10 +2183,6 @@ msgstr "chuyển cá» -m cho git-mailinfo" msgid "pass --keep-cr flag to git-mailsplit for mbox format" msgstr "chuyển cá» --keep-cr cho git-mailsplit vá»›i định dạng mbox" -msgid "do not pass --keep-cr flag to git-mailsplit independent of am.keepcr" -msgstr "" -"đừng chuyển cá» --keep-cr cho git-mailsplit không phụ thuá»™c và o am.keepcr" - msgid "strip everything before a scissors line" msgstr "cắt má»i thứ trÆ°á»›c dòng scissors" @@ -2155,31 +2199,31 @@ msgid "format" msgstr "định dạng" msgid "format the patch(es) are in" -msgstr "định dạng (các) miếng vá theo" +msgstr "định dạng (các) bản vá theo" msgid "override error message when patch failure occurs" msgstr "đè lên các lá»i nhắn lá»—i khi xảy ra lá»—i vá nghiêm trá»ng" msgid "continue applying patches after resolving a conflict" -msgstr "tiếp tục áp dụng các miếng vá sau khi giải quyết xung Ä‘á»™t" +msgstr "tiếp tục áp dụng các bản vá sau khi giải quyết xung Ä‘á»™t" msgid "synonyms for --continue" msgstr "đồng nghÄ©a vá»›i --continue" msgid "skip the current patch" -msgstr "bá» qua miếng vá hiện hà nh" +msgstr "bá» qua bản vá hiện hà nh" msgid "restore the original branch and abort the patching operation" -msgstr "phục hồi lại nhánh gốc và loại bá» thao tác vá" +msgstr "phục hồi lại nhánh gốc và huá»· thao tác vá" msgid "abort the patching operation but keep HEAD where it is" -msgstr "bá» qua thao tác vá nhÆ°ng vẫn giữ HEAD nÆ¡i nó chỉ đến" +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ị miếng vá đã được áp dụng rồi" +msgstr "hiển thị bản vá đã được áp dụng rồi" msgid "record the empty patch as an empty commit" -msgstr "ghi lại miếng vá trống rá»—ng nhÆ° là má»™t lần chuyển giao trống" +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" @@ -2194,7 +2238,7 @@ msgid "GPG-sign commits" msgstr "Các lần chuyển giao ký-GPG" msgid "how to handle empty patches" -msgstr "xá» lý các miếng vá trống rá»—ng nhÆ° thế nà o" +msgstr "xá» lý các bản vá trống rá»—ng nhÆ° thế nà o" msgid "(internal use for git-rebase)" msgstr "(dùng ná»™i bá»™ cho git-rebase)" @@ -2204,10 +2248,10 @@ msgid "" "it will be removed. Please do not use it anymore." msgstr "" "Tùy chá»n -b/--binary đã không dùng từ lâu rồi, và \n" -"nó sẽ được bá» Ä‘i. Xin đừng sá» dụng nó thêm nữa." +"nó sẽ được bá» Ä‘i. Xin đừng sá» dụng nó nữa." msgid "failed to read the index" -msgstr "gặp lá»—i Ä‘á»c bảng mục lục" +msgstr "gặp lá»—i Ä‘á»c chỉ mục" #, c-format msgid "previous rebase directory %s still exists but mbox given." @@ -2222,16 +2266,16 @@ msgstr "" "Dùng \"git am --abort\" để loại bá» nó Ä‘i." msgid "Resolve operation not in progress, we are not resuming." -msgstr "Thao tác phân giải không được tiến hà nh, chúng ta không phục hồi lại." +msgstr "Thao tác phân giải không được tiến hà nh, sẽ không phục hồi lại." msgid "interactive mode requires patches on the command line" -msgstr "chế Ä‘á»™ tÆ°Æ¡ng tác yêu cầu có các miếng vá trên dòng lệnh" +msgstr "chế Ä‘á»™ tÆ°Æ¡ng tác yêu cầu có các bản vá trên dòng lệnh" msgid "git apply [<options>] [<patch>...]" -msgstr "git apply [<các tùy chá»n>] [<miếng-vá>…]" +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 kết xuất" +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" @@ -2247,58 +2291,53 @@ msgid "git archive: protocol error" msgstr "git archive: lá»—i giao thức" msgid "git archive: expected a flush" -msgstr "git archive: cần má»™t flush (đẩy dữ liệu lên Ä‘Ä©a)" - -msgid "git bisect--helper --bisect-reset [<commit>]" -msgstr "git bisect--helper --bisect-reset [<lần_chuyển_giao>]" +msgstr "git archive: cần flush dữ liệu" msgid "" -"git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}" -"=<term>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] " -"[<paths>...]" +"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" +"checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" msgstr "" -"git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}" -"=<term>] [--no-checkout] [--first-parent] [<bad> [<good>…]] [--] [</các/" -"Ä‘Æ°á»ng/dẫn>…]" +"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" +"checkout] [--first-parent] [<bad> [<good>...]] [--] [<Ä‘Æ°á»ng/dẫn>...]" -msgid "git bisect--helper --bisect-state (bad|new) [<rev>]" -msgstr "git bisect--helper --bisect-state (bad|new) [<lần_chuyển_giao>]" +msgid "git bisect (good|bad) [<rev>...]" +msgstr "git bisect (good|bad) [<rev>...]" -msgid "git bisect--helper --bisect-state (good|old) [<rev>...]" -msgstr "git bisect--helper --bisect-state (good|old) [<lần_chuyển_giao>…]" +msgid "git bisect skip [(<rev>|<range>)...]" +msgstr "git bisect skip [(<rev>|<vùng>)...]" -msgid "git bisect--helper --bisect-replay <filename>" -msgstr "git bisect--helper --bisect-replay <tên_táºp_tin>" +msgid "git bisect reset [<commit>]" +msgstr "git bisect reset [<lần_chuyển_giao>]" -msgid "git bisect--helper --bisect-skip [(<rev>|<range>)...]" -msgstr "git bisect--helper --bisect-skip [(<rev>|<vùng>)…]" +msgid "git bisect replay <logfile>" +msgstr "git bisect replay <tên_táºp tin>" -msgid "git bisect--helper --bisect-run <cmd>..." -msgstr "git bisect--helper --bisect-run <lệnh>…" +msgid "git bisect run <cmd> [<arg>...]" +msgstr "git bisect run <lệnh> [<đối_số>]..." #, c-format msgid "cannot open file '%s' in mode '%s'" -msgstr "không thể mở táºp tin “%s†ở chế Ä‘á»™ “%sâ€" +msgstr "không thể mở táºp tin '%s' ở chế Ä‘á»™ '%s'" #, c-format msgid "could not write to file '%s'" -msgstr "không thể ghi và o táºp tin “%sâ€" +msgstr "không thể ghi và o táºp tin '%s'" #, c-format msgid "cannot open file '%s' for reading" -msgstr "không thể mở táºp tin “%s†để Ä‘á»c" +msgstr "không thể mở táºp tin '%s' để Ä‘á»c" #, c-format msgid "'%s' is not a valid term" -msgstr "“%s†không phải má»™t thá»i hạn hợp lệ" +msgstr "'%s' không phải má»™t thá»i hạn hợp lệ" #, c-format msgid "can't use the builtin command '%s' as a term" -msgstr "không thể dùng lệnh tÃch hợp “%s†nhÆ° là má»™t thá»i kỳ" +msgstr "không thể dùng lệnh tÃch hợp '%s' nhÆ° là má»™t thá»i kỳ" #, c-format msgid "can't change the meaning of the term '%s'" -msgstr "không thể thay đổi nghÄ©a của thá»i kỳ “%sâ€" +msgstr "không thể thay đổi nghÄ©a của thá»i kỳ '%s'" msgid "please use two different terms" msgstr "vui lòng dùng hai thá»i kỳ khác nhau" @@ -2309,14 +2348,14 @@ msgstr "Chúng tôi Ä‘ang không bisect.\n" #, c-format msgid "'%s' is not a valid commit" -msgstr "“%s†không phải má»™t lần chuyển giao hợp lệ" +msgstr "'%s' không phải má»™t lần chuyển giao hợp lệ" #, c-format msgid "" "could not check out original HEAD '%s'. Try 'git bisect reset <commit>'." msgstr "" -"không thể lấy ra HEAD nguyên thủy của “%sâ€. Hãy thỠ“git bisect reset <lần-" -"chuyển-giao>â€." +"không thể checkout HEAD nguyên thủy của '%s'. Hãy thá» 'git bisect reset <lần-" +"chuyển-giao>'." #, c-format msgid "Bad bisect_write argument: %s" @@ -2324,11 +2363,11 @@ msgstr "Äối số bisect_write sai: %s" #, c-format msgid "couldn't get the oid of the rev '%s'" -msgstr "không thể lấy oid của Ä‘iểm xét duyệt “%sâ€" +msgstr "không thể lấy oid của Ä‘iểm xét duyệt '%s'" #, c-format msgid "couldn't open the file '%s'" -msgstr "không thể mở táºp tin “%sâ€" +msgstr "không thể mở táºp tin '%s'" #, c-format msgid "Invalid command: you're currently in a %s/%s bisect" @@ -2393,7 +2432,7 @@ msgid "" "invalid argument %s for 'git bisect terms'.\n" "Supported options are: --term-good|--term-old and --term-bad|--term-new." msgstr "" -"tham số không hợp lệ %s cho “git bisect termsâ€.\n" +"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" @@ -2401,35 +2440,32 @@ msgstr "gặp lá»—i cà i đặt việc di chuyển qua các Ä‘iểm xét duyệt #, c-format msgid "could not open '%s' for appending" -msgstr "không thể mở “%s†để nối thêm" +msgstr "không thể mở '%s' để nối thêm" msgid "'' is not a valid term" -msgstr "†không phải má»™t thá»i hạn hợp lệ" +msgstr "'' không phải term hợp lệ" #, c-format msgid "unrecognized option: '%s'" -msgstr "tùy chá»n không được thừa nháºn: “%sâ€" +msgstr "không nháºn ra tuỳ chá»n: '%s'" #, c-format msgid "'%s' does not appear to be a valid revision" -msgstr "“%s†không có vẻ nhÆ° là má»™t Ä‘iểm xét duyệt hợp lệ" +msgstr "'%s' không có vẻ nhÆ° là má»™t Ä‘iểm xét duyệt hợp lệ" msgid "bad HEAD - I need a HEAD" msgstr "sai HEAD - Tôi cần má»™t HEAD" #, c-format msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'." -msgstr "lấy ra “%s†ra gặp lá»—i. Hãy thá» \"git bisect reset <nhánh_hợp_lệ>\"." - -msgid "won't bisect on cg-seek'ed tree" -msgstr "sẽ không di chuyển ná»a bÆ°á»›c trên cây được cg-seek" +msgstr "checkout '%s' ra gặp lá»—i. Hãy thá» \"git bisect reset <nhánh_hợp_lệ>\"." msgid "bad HEAD - strange symbolic ref" msgstr "sai HEAD - tham chiếu má»m kỳ lạ" #, c-format msgid "invalid ref: '%s'" -msgstr "refspec không hợp lệ: “%sâ€" +msgstr "refspec không hợp lệ: '%s'" msgid "You need to start by \"git bisect start\"\n" msgstr "Bạn cần khởi đầu bằng \"git bisect start\"\n" @@ -2442,11 +2478,11 @@ msgid "Do you want me to do it for you [Y/n]? " msgstr "Bạn có muốn tôi thá»±c hiện Ä‘iá»u nà y cho bạn không [Y/n]? " msgid "Please call `--bisect-state` with at least one argument" -msgstr "Hãy gá»i “--bisect-state†vá»›i Ãt nhất má»™t đối số" +msgstr "Hãy gá»i '--bisect-state' vá»›i Ãt nhất má»™t đối số" #, c-format msgid "'git bisect %s' can take only one argument." -msgstr "“git bisect %s†có thể lấy chỉ má»™t đối số." +msgstr "'git bisect %s' có thể lấy chỉ má»™t đối số." #, c-format msgid "Bad rev input: %s" @@ -2461,11 +2497,11 @@ msgstr "Chúng tôi không bisect." #, c-format msgid "'%s'?? what are you talking about?" -msgstr "“%sâ€?? bạn Ä‘ang nói gì thế?" +msgstr "'%s'?? bạn Ä‘ang nói gì thế?" #, c-format msgid "cannot read file '%s' for replaying" -msgstr "không thể Ä‘á»c táºp tin “%s†để thao diá»…n lại" +msgstr "không thể Ä‘á»c táºp tin '%s' để thao diá»…n lại" #, c-format msgid "running %s\n" @@ -2475,97 +2511,68 @@ msgid "bisect run failed: no command provided." msgstr "bisect chạy gặp lá»—i: không Ä‘Æ°a ra lệnh." #, c-format -msgid "unable to verify '%s' on good revision" -msgstr "không thể xác nháºn “%s†trên Ä‘iểm xét duyệt tốt" +msgid "unable to verify %s on good revision" +msgstr "không thể xác nháºn '%s' trên Ä‘iểm xét duyệt tốt" #, c-format msgid "bogus exit code %d for good revision" -msgstr "mã thoát giả %d cho Ä‘iểm xét duyệt tốt" +msgstr "mã trả vá» %d bất thÆ°á»ng cho Ä‘iểm xét duyệt tốt" #, c-format -msgid "bisect run failed: exit code %d from '%s' is < 0 or >= 128" -msgstr "chạy bisect gặp lá»—i: mã trả vá» %d từ lệnh “%s†là < 0 hoặc >= 128" +msgid "bisect run failed: exit code %d from %s is < 0 or >= 128" +msgstr "bisect gặp lá»—i: mã trả vá» %d từ lệnh '%s' < 0 hoặc >= 128" #, c-format msgid "cannot open file '%s' for writing" -msgstr "không thể mở “%s†để ghi" +msgstr "không thể mở '%s' để ghi" msgid "bisect run cannot continue any more" -msgstr "bisect không thể tiếp tục thêm được nữa" +msgstr "không thể tiếp tục bisect thêm được nữa" -#, c-format msgid "bisect run success" -msgstr "bisect chạy thà nh công" +msgstr "bisect thà nh công" -#, c-format msgid "bisect found first bad commit" msgstr "bisect tìm thấy lần chuyển giao sai đầu tiên" #, c-format -msgid "" -"bisect run failed: 'git bisect--helper --bisect-state %s' exited with error " -"code %d" -msgstr "" -"chạy bisect gặp lá»—i: “git bisect--helper --bisect-state %s†đã thoát ra vá»›i " -"mã lá»—i %d" - -msgid "reset the bisection state" -msgstr "đặt lại trạng di chuyển ná»a bÆ°á»›c" - -msgid "check whether bad or good terms exist" -msgstr "kiểm tra xem các thá»i Ä‘iểm xấu/tốt có tồn tại không" - -msgid "print out the bisect terms" -msgstr "in ra các thá»i Ä‘iểm di chuyển ná»a bÆ°á»›c" - -msgid "start the bisect session" -msgstr "bắt đầu phiên di chuyển ná»a bÆ°á»›c" - -msgid "find the next bisection commit" -msgstr "tìm lần chuyển giao không di chuyển phân đôi" - -msgid "mark the state of ref (or refs)" -msgstr "đánh dấu trạng thái ref (hoặc refs)" - -msgid "list the bisection steps so far" -msgstr "liệt kê các bÆ°á»›c bisection Ä‘i quá xa" - -msgid "replay the bisection process from the given file" -msgstr "phát lại quá trình bisection từ tệp đã cho" - -msgid "skip some commits for checkout" -msgstr "bá» qua má»™t số lần chuyển giao để lấy ra" +msgid "bisect run failed: 'git bisect %s' exited with error code %d" +msgstr "bisect gặp lá»—i: 'git bisect %s' đã thoát vá»›i mã lá»—i %d" -msgid "visualize the bisection" -msgstr "trá»±c quan việc di chuyển ná»a bÆ°á»›c" - -msgid "use <cmd>... to automatically bisect" -msgstr "dùng <cmd>… để bisect má»™t cách tá»± Ä‘á»™ng" +#, c-format +msgid "'%s' requires either no argument or a commit" +msgstr "'%s' không nháºn đối số hay lần chuyển giao" -msgid "no log for BISECT_WRITE" -msgstr "không có nháºt ký cho BISECT_WRITE" +#, c-format +msgid "'%s' requires 0 or 1 argument" +msgstr "%s cần 0 hoặc 1 tham số" -msgid "--bisect-reset requires either no argument or a commit" -msgstr "" -"--bisect-reset requires không nháºn đối số cÅ©ng không nháºn lần chuyển giao" +#, c-format +msgid "'%s' requires 0 arguments" +msgstr "%s không cần tham số" -msgid "--bisect-terms requires 0 or 1 argument" -msgstr "--bisect-terms cần 0 hoặc 1 tham số" +msgid "no logfile given" +msgstr "chÆ°a chỉ ra táºp tin ghi nháºt ký" -msgid "--bisect-next requires 0 arguments" -msgstr "--bisect-next cần 0 tham số" +#, c-format +msgid "'%s' failed: no command provided." +msgstr "'%s' gặp lá»—i: không chỉ ra lệnh." -msgid "--bisect-log requires 0 arguments" -msgstr "--bisect-log cần 0 tham số" +msgid "need a command" +msgstr "cần chỉ ra lệnh" -msgid "no logfile given" -msgstr "chÆ°a chỉ ra táºp tin ghi nháºt ký" +#, c-format +msgid "unknown command: '%s'" +msgstr "không hiểu câu lệnh: '%s'" msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>" msgstr "git blame [<các tùy chá»n>] [<rev-opts>] [<rev>] [--] <táºp-tin>" +msgid "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>" +msgstr "git annotate [<các tùy chá»n>] [<rev-opts>] [<rev>] [--] <táºp-tin>" + msgid "<rev-opts> are documented in git-rev-list(1)" -msgstr "<rev-opts> được mô tả trong tà i liệu git-rev-list(1)" +msgstr "<rev-opts> được mô tả trong git-rev-list(1)" #, c-format msgid "expecting a color: %s" @@ -2576,10 +2583,10 @@ msgstr "phải kết thúc bằng má»™t mà u" #, c-format msgid "cannot find revision %s to ignore" -msgstr "không thể tìm thấy Ä‘iểm xét duyệt %s để mà bá» qua" +msgstr "không thể tìm thấy Ä‘iểm xét duyệt %s để bá» qua" msgid "show blame entries as we find them, incrementally" -msgstr "hiển thị các mục “blame†nhÆ° là chúng ta thấy chúng, tăng dần" +msgstr "hiển thị các mục 'blame' theo thá»i gian, tăng dần" msgid "do not show object names of boundary commits (Default: off)" msgstr "" @@ -2593,10 +2600,10 @@ msgid "show work cost statistics" msgstr "hiển thị thống kê công sức là m việc" msgid "force progress reporting" -msgstr "ép buá»™c báo cáo tiến triển công việc" +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ị kết xuất Ä‘iểm số 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)" @@ -2608,7 +2615,7 @@ msgid "show in a format designed for machine consumption" msgstr "hiển thị ở định dạng đã thiết kế cho dùng bằng máy" msgid "show porcelain format with per-line commit information" -msgstr "hiển thị định dạng “porcelain†vá»›i thông tin chuyển giao má»—i dòng" +msgstr "hiển thị định dạng 'porcelain' vá»›i thông tin chuyển giao má»—i dòng" msgid "use the same output mode as git-annotate (Default: off)" msgstr "dùng cùng chế Ä‘á»™ xuất ra vá»›i git-annotate (Mặc định: off)" @@ -2648,7 +2655,7 @@ msgstr "tiêu thụ thêm năng tà i nguyên máy móc để tìm kiếm tốt h 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" @@ -2681,7 +2688,7 @@ msgstr "" #. columns. #. msgid "4 years, 11 months ago" -msgstr "4 năm, 11 tháng trÆ°á»›c" +msgstr "11 tháng, 28 ngà y trÆ°á»›c" #, c-format msgid "file %s has only %lu line" @@ -2705,7 +2712,7 @@ msgid "git branch [<options>] [-l] [<pattern>...]" msgstr "git branch [<các tùy chá»n>] [-l] [<mẫu>...]" msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..." -msgstr "git branch [<các tùy chá»n>] [-r] (-d | -D) <tên-nhánh> …" +msgstr "git branch [<các tùy chá»n>] [-r] (-d | -D) <tên-nhánh> ..." msgid "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>" msgstr "git branch [<các tùy chá»n>] (-m | -M) [<nhánh-cÅ©>] <nhánh-má»›i>" @@ -2722,51 +2729,56 @@ msgstr "git branch [<các tùy chá»n>] [-r | -a] [--format]" #, c-format msgid "" "deleting branch '%s' that has been merged to\n" -" '%s', but not yet merged to HEAD." +" '%s', but not yet merged to HEAD" msgstr "" -"Ä‘ang xóa nhánh “%s†mà nó lại đã được hòa trá»™n và o\n" -" “%sâ€, nhÆ°ng vẫn chÆ°a được hòa trá»™n và o HEAD." +"Ä‘ang xóa nhánh '%s' đã được hòa trá»™n và o\n" +" '%s', nhÆ°ng vẫn chÆ°a được hòa trá»™n và o HEAD." #, c-format msgid "" "not deleting branch '%s' that is not yet merged to\n" -" '%s', even though it is merged to HEAD." +" '%s', even though it is merged to HEAD" msgstr "" -"không xóa nhánh “%s†cái mà chÆ°a được hòa trá»™n và o\n" -" “%sâ€, cho dù là nó đã được hòa trá»™n và o HEAD." +"không xóa nhánh '%s' chÆ°a được hòa trá»™n và o\n" +" '%s', dù đã được hòa trá»™n và o HEAD." #, c-format -msgid "Couldn't look up commit object for '%s'" -msgstr "Không thể tìm kiếm đối tượng chuyển giao cho “%sâ€" +msgid "couldn't look up commit object for '%s'" +msgstr "Không thể tìm kiếm đối tượng chuyển giao cho '%s'" #, c-format -msgid "" -"The branch '%s' is not fully merged.\n" -"If you are sure you want to delete it, run 'git branch -D %s'." -msgstr "" -"Nhánh “%s†không được trá»™n má»™t cách đầy đủ.\n" -"Nếu bạn thá»±c sá»± muốn xóa nó, thì chạy lệnh “git branch -D %sâ€." +msgid "the branch '%s' is not fully merged" +msgstr "nhánh '%s' chÆ°a được hoà trá»™n." + +#, c-format +msgid "If you are sure you want to delete it, run 'git branch -D %s'" +msgstr "Nếu bạn thá»±c sá»± muốn xóa nó, hãy chạy lệnh 'git branch -D %s'." -msgid "Update of config-file failed" -msgstr "Cáºp nháºt táºp tin cấu hình gặp lá»—i" +msgid "update of config-file failed" +msgstr "cáºp nháºt táºp tin cấu hình gặp lá»—i" msgid "cannot use -a with -d" msgstr "không thể dùng tùy chá»n -a vá»›i -d" -msgid "Couldn't look up commit object for HEAD" -msgstr "Không thể tìm kiếm đối tượng chuyển giao cho HEAD" +#, c-format +msgid "cannot delete branch '%s' used by worktree at '%s'" +msgstr "chông thể xóa nhánh '%s' Ä‘ang được sá» dụng tại cây là m việc '%s'" #, c-format -msgid "Cannot delete branch '%s' checked out at '%s'" -msgstr "Không thể xóa nhánh “%s†đã được lấy ra tại “%sâ€" +msgid "remote-tracking branch '%s' not found" +msgstr "không tìm thấy nhánh theo dõi máy chủ '%s'." #, c-format -msgid "remote-tracking branch '%s' not found." -msgstr "không tìm thấy nhánh theo dõi máy chủ “%sâ€." +msgid "" +"branch '%s' not found.\n" +"Did you forget --remote?" +msgstr "" +"không tìm thấy nhánh '%s'.\n" +"Bạn có quên dùng --remote không?" #, c-format -msgid "branch '%s' not found." -msgstr "không tìm thấy nhánh “%sâ€." +msgid "branch '%s' not found" +msgstr "không tìm thấy nhánh '%s'." #, c-format msgid "Deleted remote-tracking branch %s (was %s).\n" @@ -2774,10 +2786,10 @@ msgstr "Äã xóa nhánh theo dõi máy chủ \"%s\" (từng là %s).\n" #, c-format msgid "Deleted branch %s (was %s).\n" -msgstr "Nhánh “%s†đã bị xóa (từng là %s)\n" +msgstr "Nhánh '%s' đã bị xóa (từng là %s)\n" msgid "unable to parse format string" -msgstr "không thể phân tÃch chuá»—i định dạng" +msgstr "không thể Ä‘á»c chuá»—i định dạng" msgid "could not resolve HEAD" msgstr "không thể phân giải HEAD" @@ -2787,56 +2799,62 @@ msgid "HEAD (%s) points outside of refs/heads/" msgstr "HEAD (%s) chỉ bên ngoà i của refs/heads/" #, c-format -msgid "Branch %s is being rebased at %s" -msgstr "Nhánh %s Ä‘ang được cải tổ lại tại %s" +msgid "branch %s is being rebased at %s" +msgstr "Nhánh %s Ä‘ang được cải tổ tại %s" + +#, c-format +msgid "branch %s is being bisected at %s" +msgstr "Nhánh %s Ä‘ang được bisect tại %s" #, c-format -msgid "Branch %s is being bisected at %s" -msgstr "Nhánh %s Ä‘ang được di chuyển phân đôi (bisect) tại %s" +msgid "HEAD of working tree %s is not updated" +msgstr "HEAD của cây là m việc %s chÆ°a được cáºp nháºt" -msgid "cannot copy the current branch while not on any." -msgstr "không thể sao chép nhánh hiện hà nh trong khi nó chẳng ở đâu cả." +#, c-format +msgid "invalid branch name: '%s'" +msgstr "tên nhánh không hợp lệ: '%s'" -msgid "cannot rename the current branch while not on any." -msgstr "không thể đổi tên nhánh hiện hà nh trong khi nó chẳng ở đâu cả." +#, c-format +msgid "no commit on branch '%s' yet" +msgstr "vẫn chÆ°a chuyển giao trên nhánh '%s'." #, c-format -msgid "Invalid branch name: '%s'" -msgstr "Tên nhánh không hợp lệ: “%sâ€" +msgid "no branch named '%s'" +msgstr "không có nhánh nà o có tên '%s'." -msgid "Branch rename failed" -msgstr "Gặp lá»—i khi đổi tên nhánh" +msgid "branch rename failed" +msgstr "gặp lá»—i khi đổi tên nhánh" -msgid "Branch copy failed" -msgstr "Gặp lá»—i khi sao chép nhánh" +msgid "branch copy failed" +msgstr "gặp lá»—i khi sao chép nhánh" #, c-format -msgid "Created a copy of a misnamed branch '%s'" -msgstr "Äã tạo má»™t bản sao của nhánh khuyết danh “%sâ€" +msgid "created a copy of a misnamed branch '%s'" +msgstr "đã tạo má»™t bản sao của nhánh khuyết danh '%s'" #, c-format -msgid "Renamed a misnamed branch '%s' away" -msgstr "Äã đổi tên nhánh khuyết danh “%s†đi" +msgid "renamed a misnamed branch '%s' away" +msgstr "đã đổi tên nhánh khuyết danh '%s'" #, c-format -msgid "Branch renamed to %s, but HEAD is not updated!" -msgstr "Nhánh bị đổi tên thà nh %s, nhÆ°ng HEAD lại không được cáºp nháºt!" +msgid "branch renamed to %s, but HEAD is not updated" +msgstr "đã đổi tên nhánh thà nh %s, nhÆ°ng HEAD không được cáºp nháºt" -msgid "Branch is renamed, but update of config-file failed" -msgstr "Nhánh bị đổi tên, nhÆ°ng cáºp nháºt táºp tin cấu hình gặp lá»—i" +msgid "branch is renamed, but update of config-file failed" +msgstr "đã đổi tên nhánh, nhÆ°ng cáºp nháºt táºp tin cấu hình gặp lá»—i" -msgid "Branch is copied, but update of config-file failed" -msgstr "Nhánh đã được sao chép, nhÆ°ng cáºp nháºt táºp tin cấu hình gặp lá»—i" +msgid "branch is copied, but update of config-file failed" +msgstr "đã sao chép nhánh, nhÆ°ng cáºp nháºt táºp tin cấu hình gặp lá»—i" #, 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 "" -"Viết các ghi chú cho nhánh:\n" +"Viết các ghi chú cho nhánh\n" " %s\n" -"Những dòng được bắt đầu bằng “%c†sẽ được cắt bá».\n" +"Những dòng được bắt đầu bằng '%s' sẽ được cắt bá».\n" msgid "Generic options" msgstr "Tùy chá»n chung" @@ -2866,7 +2884,7 @@ msgid "use colored output" msgstr "tô mà u kết xuất" msgid "act on remote-tracking branches" -msgstr "thao tác trên nhánh “remote-trackingâ€" +msgstr "thao tác trên nhánh 'remote-tracking'" msgid "print only branches that contain the commit" msgstr "chỉ hiển thị những nhánh mà nó chứa lần chuyển giao" @@ -2878,7 +2896,7 @@ msgid "Specific git-branch actions:" msgstr "Hà nh Ä‘á»™ng git-branch:" msgid "list both remote-tracking and local branches" -msgstr "liệt kê cả nhánh “remote-tracking†và ná»™i bá»™" +msgstr "liệt kê cả nhánh 'remote-tracking' và ná»™i bá»™" msgid "delete fully merged branch" msgstr "xóa má»™t toà n bá»™ nhánh đã hòa trá»™n" @@ -2892,6 +2910,9 @@ msgstr "di chuyển hay đổi tên má»™t nhánh và reflog của nó" msgid "move/rename a branch, even if target exists" msgstr "di chuyển hoặc đổi tên má»™t nhánh ngay cả khi Ä‘Ãch đã có sẵn" +msgid "do not output a newline after empty formatted refs" +msgstr "không in ra ký tá»± xuống dòng sau tham chiếu rá»—ng" + msgid "copy a branch and its reflog" msgstr "sao chép má»™t nhánh và reflog của nó" @@ -2937,8 +2958,8 @@ msgstr "đệ quy xuyên qua mô-Ä‘un con" msgid "format to use for the output" msgstr "định dạng sẽ dùng cho đầu ra" -msgid "Failed to resolve HEAD as a valid ref." -msgstr "Gặp lá»—i khi phân giải HEAD nhÆ° là má»™t tham chiếu hợp lệ." +msgid "failed to resolve HEAD as a valid ref" +msgstr "gặp lá»—i khi phân giải HEAD thà nh má»™t tham chiếu hợp lệ." msgid "HEAD not found below refs/heads!" msgstr "Không tìm thấy HEAD ở dÆ°á»›i refs/heads!" @@ -2956,22 +2977,20 @@ msgstr "--recurse-submodules chỉ có thể được sá» dụng để tạo ra msgid "branch name required" msgstr "cần chỉ ra tên nhánh" -msgid "Cannot give description to detached HEAD" -msgstr "Không thể Ä‘Æ°a ra mô tả HEAD đã tách rá»i" +msgid "cannot give description to detached HEAD" +msgstr "không thể Ä‘Æ°a ra mô tả cho HEAD đã tách rá»i" msgid "cannot edit description of more than one branch" msgstr "không thể sá»a mô tả cho nhiá»u hÆ¡n má»™t nhánh" -#, c-format -msgid "No commit on branch '%s' yet." -msgstr "Vẫn chÆ°a chuyển giao trên nhánh “%sâ€." +msgid "cannot copy the current branch while not on any" +msgstr "không thể sao chép nhánh hiện hà nh khi Ä‘ang không ở trên nhánh nà o." -#, c-format -msgid "No branch named '%s'." -msgstr "Không có nhánh nà o có tên “%sâ€." +msgid "cannot rename the current branch while not on any" +msgstr "không thể đổi tên nhánh hiện hà nh khi Ä‘ang không ở trên nhánh nà o." msgid "too many branches for a copy operation" -msgstr "quá nhiá»u nhánh dà nh cho thao tác sao chép" +msgstr "quá nhiá»u nhánh cho thao tác sao chép" msgid "too many arguments for a rename operation" msgstr "quá nhiá»u tham số cho thao tác đổi tên" @@ -2981,50 +3000,48 @@ msgstr "quá nhiá»u tham số để đặt thượng nguồn má»›i" #, c-format msgid "" -"could not set upstream of HEAD to %s when it does not point to any branch." +"could not set upstream of HEAD to %s when it does not point to any branch" msgstr "" -"không thể đặt thượng nguồn của HEAD thà nh %s khi mà nó chẳng chỉ đến nhánh " -"nà o cả." +"không thể đặt thượng nguồn của HEAD thà nh %s khi nó không chỉ đến nhánh nà o." #, c-format msgid "no such branch '%s'" -msgstr "không có nhánh nà o nhÆ° thế “%sâ€" +msgstr "không có nhánh nà o tên '%s'" #, c-format msgid "branch '%s' does not exist" -msgstr "chÆ°a có nhánh “%sâ€" +msgstr "chÆ°a có nhánh '%s'" msgid "too many arguments to unset upstream" msgstr "quá nhiá»u tham số để bỠđặt thượng nguồn" -msgid "could not unset upstream of HEAD when it does not point to any branch." -msgstr "không thể bỠđặt thượng nguồn của HEAD không chỉ đến má»™t nhánh nà o cả." +msgid "could not unset upstream of HEAD when it does not point to any branch" +msgstr "không thể bỠđặt thượng nguồn của HEAD khi nó không chỉ đến nhánh nà o." #, c-format -msgid "Branch '%s' has no upstream information" -msgstr "Nhánh “%s†không có thông tin thượng nguồn" +msgid "branch '%s' has no upstream information" +msgstr "nhánh '%s' không có thông tin thượng nguồn" msgid "" -"The -a, and -r, options to 'git branch' do not take a branch name.\n" +"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 "" -"Hai tùy chá»n -a và -r áp dụng cho lệnh “git branch†không nháºn má»™t tên " -"nhánh.\n" -"Có phải ý bạn là dùng: -a|-r --list <mẫu>?" +"Hai tùy chá»n -a, và -r, cho lệnh 'git branch' không nháºn má»™t tên nhánh.\n" +"Có phải ý bạn là : -a|-r --list <mẫu>?" msgid "" "the '--set-upstream' option is no longer supported. Please use '--track' or " -"'--set-upstream-to' instead." +"'--set-upstream-to' instead" msgstr "" -"tùy chá»n --set-upstream đã không còn được há»— trợ nữa. Vui lòng dùng “--" -"track†hoặc “--set-upstream-to†để thay thế." +"tùy chá»n --set-upstream đã không còn được há»— trợ nữa. Vui lòng dùng '--" +"track' hoặc '--set-upstream-to'" msgid "git version:\n" msgstr "phiên bản git:\n" #, c-format msgid "uname() failed with error '%s' (%d)\n" -msgstr "uname() gặp lá»—i “%s†(%d)\n" +msgstr "uname() gặp lá»—i '%s' (%d)\n" msgid "compiler info: " msgstr "thông tin trình biên dịch: " @@ -3033,11 +3050,16 @@ msgid "libc info: " msgstr "thông tin libc: " msgid "not run from a git repository - no hooks to show\n" -msgstr "không chạy từ má»™t kho git - nên chẳng có móc nà o để mà hiển thị cả\n" +msgstr "không chạy từ má»™t kho git - nên chẳng có móc nà o để hiển thị cả\n" -msgid "git bugreport [-o|--output-directory <file>] [-s|--suffix <format>]" +msgid "" +"git bugreport [(-o | --output-directory) <path>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" +" [--diagnose[=<mode>]]" msgstr "" -"git bugreport [-o|--output-directory <táºp_tin>] [-s|--suffix <định_dạng>]" +"git bugreport [(-o | --output-directory) <Ä‘Æ°á»ng dẫn>]\n" +" [(-s | --suffix) <định dạng> | --no-suffix]\n" +" [--diagnose[=<chế Ä‘á»™>]]" msgid "" "Thank you for filling out a Git bug report!\n" @@ -3059,29 +3081,45 @@ msgstr "" "Cảm Æ¡n bạn đã tạo má»™t báo cáo lá»—i Git!\n" "Vui lòng trả lá»i các câu há»i sau để giúp chúng tôi hiểu vấn Ä‘á» của bạn.\n" "\n" -"Bạn đã là m gì trÆ°á»›c khi lá»—i xảy ra? (Các bÆ°á»›c để tái tạo sá»± cố của bạn)\n" +"Bạn đã là m gì trÆ°á»›c khi lá»—i xảy ra? (Các bÆ°á»›c để tái hiện sá»± cố của bạn)\n" "\n" "Äiá»u bạn mong muốn xảy ra? (Hà nh vi dá»± kiến)\n" "\n" -"Äiá»u gì đã xảy ra thay thế? (Hà nh vi thá»±c tế)\n" +"Äiá»u gì đã xảy ra? (Hà nh vi thá»±c tế)\n" "\n" "Có gì khác biệt giữa những gì bạn mong đợi và những gì thá»±c sá»± xảy ra?\n" "\n" -"Bất kỳ thứ gì khác bạn muốn thêm:\n" +"Những thứ khác bạn muốn thêm:\n" "\n" -"Vui lòng xen xét phần còn lại của báo cáo lá»—i bên dÆ°á»›i.\n" +"Vui lòng xem xét phần còn lại của báo cáo lá»—i bên dÆ°á»›i.\n" "Bạn có thể xóa bất kỳ dòng nà o bạn không muốn chia sẻ.\n" -msgid "specify a destination for the bugreport file" -msgstr "chỉ định thÆ° mục định để tạo táºp tin báo cáo lá»—i" +msgid "mode" +msgstr "chế Ä‘á»™" -msgid "specify a strftime format suffix for the filename" +msgid "" +"create an additional zip archive of detailed diagnostics (default 'stats')" +msgstr "" +"tạo thêm táºp tin nén zip của bản báo cáo chi tiết hÆ¡n (mặc định 'stats')" + +msgid "specify a destination for the bugreport file(s)" +msgstr "chỉ định thÆ° mục Ä‘Ãch để tạo táºp tin báo cáo lá»—i" + +msgid "specify a strftime format suffix for the filename(s)" msgstr "" "chỉ định chuá»—i định dạng thá»i gian strftime dùng là m háºu tố cho tên táºp tin" #, c-format +msgid "unknown argument `%s'" +msgstr "không hiểu đối số: '%s'" + +#, c-format msgid "could not create leading directories for '%s'" -msgstr "không thể tạo các thÆ° mục dẫn đầu cho “%sâ€" +msgstr "không thể tạo các thÆ° mục cha cho '%s'" + +#, c-format +msgid "unable to create diagnostics archive %s" +msgstr "không thể tạo bản báo cáo %s" msgid "System Info" msgstr "Thông tin hệ thống" @@ -3095,34 +3133,41 @@ msgstr "không thể ghi và o %s" #, c-format msgid "Created new report at '%s'.\n" -msgstr "Äã tạo báo cáo má»›i tại “%sâ€\n" +msgstr "Äã tạo báo cáo má»›i tại '%s'\n" -msgid "git bundle create [<options>] <file> <git-rev-list args>" -msgstr "git bundle create [<các tùy chá»n>] <táºp_tin> <git-rev-list args>" +msgid "" +"git bundle create [-q | --quiet | --progress]\n" +" [--version=<version>] <file> <git-rev-list-args>" +msgstr "" +"git bundle create [-q | --quiet | --progress]\n" +" [--version=<phiên_bản>] <táºp tin> <đối-số-git-rev-list>" -msgid "git bundle verify [<options>] <file>" -msgstr "git bundle verify [<các tùy chá»n>] <táºp-tin>" +msgid "git bundle verify [-q | --quiet] <file>" +msgstr "git bundle verify [-q | --quiet] <táºp-tin>" msgid "git bundle list-heads <file> [<refname>...]" -msgstr "git bundle list-heads <táºp tin> [<tên tham chiếu>…]" +msgstr "git bundle list-heads <táºp tin> [<tên tham chiếu>...]" + +msgid "git bundle unbundle [--progress] <file> [<refname>...]" +msgstr "git bundle unbundle [--progress] <táºp tin> [<tên tham chiếu>...]" -msgid "git bundle unbundle <file> [<refname>...]" -msgstr "git bundle unbundle <táºp tin> [<tên tham chiếu>…]" +msgid "need a <file> argument" +msgstr "cần tham số <táºp_tin>" msgid "do not show progress meter" -msgstr "không hiển thị bá»™ Ä‘o tiến trình" +msgstr "không hiển thị thanh Ä‘o tiến Ä‘á»™" msgid "show progress meter" -msgstr "hiển thị bá»™ Ä‘o tiến trình" +msgstr "hiển thị thanh Ä‘o tiến Ä‘á»™" -msgid "show progress meter during object writing phase" -msgstr "hiển thị bá»™ Ä‘o tiến triển trong suốt pha ghi đối tượng" +msgid "historical; same as --progress" +msgstr "tuỳ chá»n cÅ©; giống nhÆ° --progress" -msgid "similar to --all-progress when progress meter is shown" -msgstr "tÆ°Æ¡ng tá»± --all-progress khi bá»™ Ä‘o tiến trình được xuất hiện" +msgid "historical; does nothing" +msgstr "tuỳ chá»n cÅ©; không là m gì cả" msgid "specify bundle format version" -msgstr "chỉ Ä‘iịnh định dạng cho bundle" +msgstr "chỉ định phiên bản định dạng bundle" msgid "Need a repository to create a bundle." msgstr "Cần má»™t kho chứa để có thể tạo má»™t bundle." @@ -3132,7 +3177,7 @@ msgstr "không hiển thị chi tiết bundle (bó)" #, c-format msgid "%s is okay\n" -msgstr "“%s†tốt\n" +msgstr "%s tốt\n" msgid "Need a repository to unbundle." msgstr "Cần má»™t kho chứa để có thể giải nén má»™t bundle." @@ -3141,12 +3186,8 @@ msgid "Unbundling objects" msgstr "Tháo rá»i các đối tượng" #, c-format -msgid "Unknown subcommand: %s" -msgstr "Không hiểu câu lệnh con: %s" - -#, c-format msgid "cannot read object %s '%s'" -msgstr "không thể Ä‘á»c đối tượng %s “%sâ€" +msgstr "không thể Ä‘á»c đối tượng %s '%s'" msgid "flush is only for --buffer mode" msgstr "flush chỉ dà nh cho chế Ä‘á»™ --buffer" @@ -3166,10 +3207,6 @@ msgstr "%s cần các tham số" msgid "%s takes no arguments" msgstr "%s không nháºn tham số" -#, c-format -msgid "unknown command: '%s'" -msgstr "không hiểu câu lệnh: '%s'" - msgid "only one batch option may be specified" msgstr "chỉ má»™t tùy chá»n batch được chỉ ra" @@ -3183,22 +3220,22 @@ msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" msgstr "git cat-file (-t | -s) [--allow-unknown-type] <đối_tượng>" msgid "" +"git cat-file (--textconv | --filters)\n" +" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]" +msgstr "" +"git cat-file (--textconv | --filters)\n" +" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]" + +msgid "" "git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" "objects]\n" " [--buffer] [--follow-symlinks] [--unordered]\n" -" [--textconv | --filters]" +" [--textconv | --filters] [-Z]" msgstr "" "git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" "objects]\n" " [--buffer] [--follow-symlinks] [--unordered]\n" -" [--textconv | --filters]" - -msgid "" -"git cat-file (--textconv | --filters)\n" -" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]" -msgstr "" -"git cat-file (--textconv | --filters)\n" -" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]" +" [--textconv | --filters] [-Z]" msgid "Check object existence or emit object contents" msgstr "Kiểm tra đối tượng có sẵn hay không hoặc phát ná»™i dung của đối tượng" @@ -3223,10 +3260,11 @@ msgstr "hiển thị kÃch thÆ°á»›c đối tượng" msgid "allow -s and -t to work with broken/corrupt objects" msgstr "cho phép -s và -t để là m việc vá»›i các đối tượng sai/há»ng" +msgid "use mail map file" +msgstr "sá» dụng táºp tin ánh xạ thÆ°" + msgid "Batch objects requested on stdin (or --batch-all-objects)" -msgstr "" -"Äã yêu cầu các đối tượng batch trên đầu và o tiêu chuẩn stdin (hoặc --batch-" -"all-objects)" +msgstr "Äã yêu cầu các đối tượng batch trên stdin (hoặc --batch-all-objects)" msgid "show full <object> or <rev> contents" msgstr "hiển thị đầy đủ ná»™i dung <object> hay <rev>" @@ -3234,13 +3272,17 @@ msgstr "hiển thị đầy đủ ná»™i dung <object> hay <rev>" msgid "like --batch, but don't emit <contents>" msgstr "giống --batch, nhÆ°ng không phát ra <contents>" +msgid "stdin is NUL-terminated" +msgstr "stdin được kết thúc bởi NUL" + +msgid "stdin and stdout is NUL-terminated" +msgstr "stdin và stdout được kết thúc bởi NUL" + msgid "read commands from stdin" -msgstr "Ä‘á»c các lệnh từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c các lệnh từ stdin" msgid "with --batch[-check]: ignores stdin, batches all known objects" -msgstr "" -"vá»›i --batch[-check]: bá» qua đầu và o tiêu chuẩn stdin, batch má»i đối tượng đã " -"biết" +msgstr "vá»›i --batch[-check]: bá» qua stdin, batch má»i đối tượng đã biết" msgid "Change or optimize batch output" msgstr "Thay đổi hay tối Æ°u hóa đầu ra batch" @@ -3283,11 +3325,11 @@ msgstr "path|tree-ish" #, c-format msgid "'%s' requires a batch mode" -msgstr "“%s†cần má»™t chế Ä‘á»™ batch" +msgstr "'%s' cần má»™t chế Ä‘á»™ batch" #, c-format msgid "'-%c' is incompatible with batch mode" -msgstr "'-%c' là xung khắc vá»›i chế Ä‘á»™ batch" +msgstr "'-%c' không tÆ°Æ¡ng thÃch vá»›i chế Ä‘á»™ batch" msgid "batch modes take no arguments" msgstr "chế Ä‘á»™ batch không nháºn các đối số" @@ -3300,30 +3342,39 @@ msgstr "cần <rev> vá»›i '%s'" msgid "<object> required with '-%c'" msgstr "cần <object> vá»›i '-%c'" -msgid "too many arguments" -msgstr "có quá nhiá»u đối số" - #, c-format msgid "only two arguments allowed in <type> <object> mode, not %d" msgstr "chỉ hai đối số được phép trong chế Ä‘á»™ <type> <object>, không phải %d" -msgid "git check-attr [-a | --all | <attr>...] [--] <pathname>..." -msgstr "git check-attr [-a | --all | <attr>…] [--] tên-Ä‘Æ°á»ng-dẫn…" +msgid "" +"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] " +"<pathname>..." +msgstr "" +"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] <tên-" +"Ä‘Æ°á»ng-dẫn>..." -msgid "git check-attr --stdin [-z] [-a | --all | <attr>...]" -msgstr "git check-attr --stdin [-z] [-a | --all | <attr>…]" +msgid "" +"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" +msgstr "" +"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" msgid "report all attributes set on file" -msgstr "báo cáo tất cả các thuá»™c tÃnh đặt trên táºp tin" +msgstr "liệt kê tất cả các thuá»™c tÃnh đặt trên táºp tin" msgid "use .gitattributes only from the index" -msgstr "chỉ dùng .gitattributes từ bảng mục lục" +msgstr "chỉ dùng .gitattributes từ chỉ mục" msgid "read file names from stdin" -msgstr "Ä‘á»c tên táºp tin từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c tên táºp tin từ stdin" msgid "terminate input and output records by a NUL character" -msgstr "chấm dứt các bản ghi và o và ra bằng ký tá»± NULL" +msgstr "kết thúc các bản ghi và o và ra bằng ký tá»± NULL" + +msgid "<tree-ish>" +msgstr "<tree-ish>" + +msgid "which tree-ish to check attributes at" +msgstr "kiểm tra thuá»™c tÃnh từ tree-ish nà o" msgid "suppress progress reporting" msgstr "chặn các báo cáo tiến trình hoạt Ä‘á»™ng" @@ -3332,7 +3383,7 @@ msgid "show non-matching input paths" msgstr "hiển thị những Ä‘Æ°á»ng dẫn đầu và o không khá»›p vá»›i mẫu" msgid "ignore index when checking" -msgstr "bá» qua mục lục khi kiểm tra" +msgstr "bá» qua chỉ mục khi kiểm tra" msgid "cannot specify pathnames with --stdin" msgstr "không thể chỉ định các tên Ä‘Æ°á»ng dẫn vá»›i --stdin" @@ -3353,14 +3404,14 @@ msgid "--non-matching is only valid with --verbose" msgstr "tùy-chá»n --non-matching chỉ hợp lệ khi dùng vá»›i --verbose" msgid "git check-mailmap [<options>] <contact>..." -msgstr "git check-mailmap [<các tùy chá»n>] <danh-bạ>…" +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ừ đầu và o tiêu chuẩn" +msgstr "đồng thá»i Ä‘á»c các danh bạ từ stdin" #, c-format msgid "unable to parse contact: %s" -msgstr "không thể phân tÃch danh bạ: “%sâ€" +msgstr "không thể Ä‘á»c danh bạ: '%s'" msgid "no contacts specified" msgstr "chÆ°a chỉ ra danh bạ" @@ -3375,13 +3426,13 @@ msgid "when creating files, prepend <string>" msgstr "khi tạo các táºp tin, nối thêm <chuá»—i>" msgid "git checkout-index [<options>] [--] [<file>...]" -msgstr "git checkout-index [<các tùy chá»n>] [--] [<táºp-tin>…]" +msgstr "git checkout-index [<các tùy chá»n>] [--] [<táºp-tin>...]" msgid "stage should be between 1 and 3 or all" msgstr "stage nên giữa 1 và 3 hay all" msgid "check out all files in the index" -msgstr "lấy ra toà n bá»™ các táºp tin trong bảng mục lục" +msgstr "checkout toà n bá»™ các táºp tin trong chỉ mục" msgid "do not skip files with skip-worktree set" msgstr "đừng bá» qua các táºp tin vá»›i skip-worktree được đặt" @@ -3390,17 +3441,16 @@ msgid "force overwrite of existing files" msgstr "ép buá»™c ghi đè lên táºp tin đã sẵn có từ trÆ°á»›c" msgid "no warning for existing files and files not in index" -msgstr "" -"không cảnh báo cho những táºp tin tồn tại và không có trong bảng mục lục" +msgstr "không cảnh báo cho những táºp tin tồn tại và không có trong chỉ mục" msgid "don't checkout new files" msgstr "không checkout các táºp tin má»›i" msgid "update stat information in the index file" -msgstr "cáºp nháºt thông tin thống kê trong táºp tin lÆ°u bảng mục lục má»›i" +msgstr "cáºp nháºt thông tin thống kê trong táºp tin chỉ mục má»›i" msgid "read list of paths from the standard input" -msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn từ stdin" msgid "write the content to temporary files" msgstr "ghi ná»™i dung và o táºp tin tạm" @@ -3412,37 +3462,37 @@ msgid "git checkout [<options>] <branch>" msgstr "git checkout [<các tùy chá»n>] <nhánh>" msgid "git checkout [<options>] [<branch>] -- <file>..." -msgstr "git checkout [<các tùy chá»n>] [<nhánh>] -- <táºp-tin>…" +msgstr "git checkout [<các tùy chá»n>] [<nhánh>] -- <táºp-tin>..." msgid "git switch [<options>] [<branch>]" msgstr "git switch [<các tùy chá»n>] [<nhánh>]" msgid "git restore [<options>] [--source=<branch>] <file>..." -msgstr "git restore [<các tùy chá»n>] [--source=<nhánh>] <táºp tin>…" +msgstr "git restore [<các tùy chá»n>] [--source=<nhánh>] <táºp tin>..." #, c-format msgid "path '%s' does not have our version" -msgstr "Ä‘Æ°á»ng dẫn “%s†không có các phiên bản của chúng ta" +msgstr "Ä‘Æ°á»ng dẫn '%s' không có các phiên bản của ta" #, c-format msgid "path '%s' does not have their version" -msgstr "Ä‘Æ°á»ng dẫn “%s†không có các phiên bản của chúng" +msgstr "Ä‘Æ°á»ng dẫn '%s' không có các phiên bản của há»" #, c-format msgid "path '%s' does not have all necessary versions" -msgstr "Ä‘Æ°á»ng dẫn “%s†không có tất cả các phiên bản cần thiết" +msgstr "Ä‘Æ°á»ng dẫn '%s' không có tất cả các phiên bản cần thiết" #, c-format msgid "path '%s' does not have necessary versions" -msgstr "Ä‘Æ°á»ng dẫn “%s†không có các phiên bản cần thiết" +msgstr "Ä‘Æ°á»ng dẫn '%s' không có các phiên bản cần thiết" #, c-format msgid "path '%s': cannot merge" -msgstr "Ä‘Æ°á»ng dẫn “%sâ€: không thể hòa trá»™n" +msgstr "Ä‘Æ°á»ng dẫn '%s': không thể hòa trá»™n" #, c-format msgid "Unable to add merge result for '%s'" -msgstr "Không thể thêm kết quả hòa trá»™n cho “%sâ€" +msgstr "Không thể thêm kết quả hòa trá»™n cho '%s'" #, c-format msgid "Recreated %d merge conflict" @@ -3457,35 +3507,43 @@ msgstr[0] "Äã cáºp nháºt Ä‘Æ°á»ng dẫn %d từ %s" #, c-format msgid "Updated %d path from the index" msgid_plural "Updated %d paths from the index" -msgstr[0] "Äã cáºp nháºt Ä‘Æ°á»ng dẫn %d từ mục lục" +msgstr[0] "Äã cáºp nháºt Ä‘Æ°á»ng dẫn %d từ chỉ mục" #, c-format msgid "'%s' cannot be used with updating paths" -msgstr "không được dùng “%s†vá»›i các Ä‘Æ°á»ng dẫn cáºp nháºt" +msgstr "không được dùng '%s' vá»›i các Ä‘Æ°á»ng dẫn cáºp nháºt" #, c-format msgid "Cannot update paths and switch to branch '%s' at the same time." msgstr "" -"Không thể cáºp nháºt các Ä‘Æ°á»ng dẫn và chuyển đến nhánh “%s†cùng má»™t lúc." +"Không thể cáºp nháºt các Ä‘Æ°á»ng dẫn và chuyển đến nhánh '%s' cùng má»™t lúc." #, c-format msgid "neither '%s' or '%s' is specified" -msgstr "không chỉ định “%s†cÅ©ng không “%sâ€" +msgstr "không chỉ định '%s' cÅ©ng không '%s'" #, c-format msgid "'%s' must be used when '%s' is not specified" -msgstr "phải có “%s†khi không chỉ định “%sâ€" +msgstr "phải có '%s' khi không chỉ định '%s'" #, c-format msgid "'%s' or '%s' cannot be used with %s" -msgstr "“%s†hay “%s†không thể được sá» dụng vá»›i %s" +msgstr "'%s' hay '%s' không thể được sá» dụng vá»›i %s" + +#, c-format +msgid "'%s', '%s', or '%s' cannot be used when checking out of a tree" +msgstr "'%s', '%s', hay '%s' không thể được sá» dụng khi checkout cây là m việc" #, c-format msgid "path '%s' is unmerged" -msgstr "Ä‘Æ°á»ng dẫn “%s†không được hòa trá»™n" +msgstr "Ä‘Æ°á»ng dẫn '%s' không được hòa trá»™n" + +#, c-format +msgid "unable to read tree (%s)" +msgstr "không thể Ä‘á»c cây (%s)" msgid "you need to resolve your current index first" -msgstr "bạn cần phải giải quyết bảng mục lục hiện tại của bạn trÆ°á»›c đã" +msgstr "bạn cần phải giải quyết chỉ mục hiện tại của bạn trÆ°á»›c đã" #, c-format msgid "" @@ -3498,7 +3556,7 @@ msgstr "" #, c-format msgid "Can not do reflog for '%s': %s\n" -msgstr "Không thể thá»±c hiện reflog cho “%sâ€: %s\n" +msgstr "Không thể thá»±c hiện reflog cho '%s': %s\n" msgid "HEAD is now at" msgstr "HEAD hiện giá» tại" @@ -3508,27 +3566,27 @@ msgstr "không thể cáºp nháºt HEAD" #, c-format msgid "Reset branch '%s'\n" -msgstr "Äặt lại nhánh “%sâ€\n" +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 sà ng trên '%s'\n" #, c-format msgid "Switched to and reset branch '%s'\n" -msgstr "Äã chuyển tá»›i và đặt lại nhánh “%sâ€\n" +msgstr "Äã chuyển tá»›i và đặt lại nhánh '%s'\n" #, c-format msgid "Switched to a new branch '%s'\n" -msgstr "Äã chuyển đến nhánh má»›i “%sâ€\n" +msgstr "Äã chuyển đến nhánh má»›i '%s'\n" #, c-format msgid "Switched to branch '%s'\n" -msgstr "Äã chuyển đến nhánh “%sâ€\n" +msgstr "Äã chuyển đến nhánh '%s'\n" #, c-format msgid " ... and %d more.\n" -msgstr " … và nhiá»u hÆ¡n %d.\n" +msgstr " ... và nhiá»u hÆ¡n %d.\n" #, c-format msgid "" @@ -3582,7 +3640,7 @@ msgid "" "'%s' could be both a local file and a tracking branch.\n" "Please use -- (and optionally --no-guess) to disambiguate" msgstr "" -"“%s†không thể là cả táºp tin ná»™i bá»™ và má»™t nhánh theo dõi.\n" +"'%s' không thể là cả táºp tin ná»™i bá»™ và má»™t nhánh theo dõi.\n" "Vui long dùng -- (và tùy chá»n thêm --no-guess) để tránh lẫn lá»™n" msgid "" @@ -3595,18 +3653,18 @@ msgid "" "one remote, e.g. the 'origin' remote, consider setting\n" "checkout.defaultRemote=origin in your config." msgstr "" -"Nếu ý bạn là lấy ra nhánh máy chủ được theo dõi, và dụ “originâ€,\n" +"Nếu ý bạn là checkout nhánh máy chủ được theo dõi, và dụ 'origin',\n" "bạn có thể là m nhÆ° váºy bằng cách chỉ định đầy đủ tên vá»›i tùy chá»n --track:\n" "\n" " git checkout --track origin/<tên>\n" "\n" -"Nếu bạn muốn luôn lấy ra từ má»™t <tên> má»™t máy chủ Æ°a thÃch\n" -"chÆ°a rõ rà ng, và dụ máy chủ “originâ€, cân nhắc cà i đặt\n" +"Nếu bạn muốn luôn checkout từ má»™t <tên> má»™t máy chủ Æ°a thÃch\n" +"chÆ°a rõ rà ng, và dụ máy chủ 'origin', cân nhắc cà i đặt\n" "checkout.defaultRemote=origin trong cấu hình của bạn." #, c-format msgid "'%s' matched multiple (%d) remote tracking branches" -msgstr "“%s†khá»›p vá»›i nhiá»u (%d) nhánh máy chủ được theo dõi" +msgstr "'%s' khá»›p vá»›i nhiá»u (%d) nhánh máy chủ được theo dõi" msgid "only one reference expected" msgstr "chỉ cần má»™t tham chiếu" @@ -3625,19 +3683,19 @@ msgstr "tham chiếu không phải là má»™t cây:%s" #, c-format msgid "a branch is expected, got tag '%s'" -msgstr "cần má»™t nhánh, nhÆ°ng lại nháºn được thẻ “%sâ€" +msgstr "cần má»™t nhánh, nhÆ°ng lại có thẻ '%s'" #, c-format msgid "a branch is expected, got remote branch '%s'" -msgstr "cần má»™t nhánh, nhÆ°ng lại nháºn được nhánh máy phục vụ “%sâ€" +msgstr "cần má»™t nhánh, nhÆ°ng lại có nhánh máy chủ '%s'" #, c-format msgid "a branch is expected, got '%s'" -msgstr "cần má»™t nhánh, nhÆ°ng lại nháºn được “%sâ€" +msgstr "cần má»™t nhánh, nhÆ°ng lại có '%s'" #, c-format msgid "a branch is expected, got commit '%s'" -msgstr "cần má»™t nhánh, nhÆ°ng lại nháºn được “%sâ€" +msgstr "cần má»™t nhánh, nhÆ°ng lại có '%s'" msgid "" "If you want to detach HEAD at the commit, try again with the --detach option." @@ -3650,35 +3708,35 @@ msgid "" "Consider \"git merge --quit\" or \"git worktree add\"." msgstr "" "không thể chuyển nhánh trong khi Ä‘ang hòa trá»™n\n" -"Cân nhắc dung \"git merge --quit\" hoặc \"git worktree add\"." +"Thá» dung \"git merge --quit\" hoặc \"git worktree add\"." msgid "" "cannot switch branch in the middle of an am session\n" "Consider \"git am --quit\" or \"git worktree add\"." msgstr "" "không thể chuyển nhanh ở giữa má»™t phiên am\n" -"Cân nhắc dùng \"git am --quit\" hoặc \"git worktree add\"." +"Thá» dùng \"git am --quit\" hoặc \"git worktree add\"." msgid "" "cannot switch branch while rebasing\n" "Consider \"git rebase --quit\" or \"git worktree add\"." msgstr "" "không thể chuyển nhánh trong khi cải tổ\n" -"Cân nhắc dùng \"git rebase --quit\" hay \"git worktree add\"." +"Thá» dùng \"git rebase --quit\" hay \"git worktree add\"." msgid "" "cannot switch branch while cherry-picking\n" "Consider \"git cherry-pick --quit\" or \"git worktree add\"." msgstr "" -"không thể chuyển nhánh trong khi cherry-picking\n" -"Cân nhắc dùng \"git cherry-pick --quit\" hay \"git worktree add\"." +"không thể chuyển nhánh trong khi cherry-pick\n" +"Hãy dùng \"git cherry-pick --quit\" hay \"git worktree add\"." msgid "" "cannot switch branch while reverting\n" "Consider \"git revert --quit\" or \"git worktree add\"." msgstr "" "không thể chuyển nhánh trong khi hoà n nguyên\n" -"Cân nhắc dùng \"git revert --quit\" hoặc \"git worktree add\"." +"Thá» dùng \"git revert --quit\" hoặc \"git worktree add\"." msgid "you are switching branch while bisecting" msgstr "" @@ -3690,23 +3748,27 @@ 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 vá»›i các nhánh chuyển" #, c-format msgid "'%s' cannot be used with '%s'" -msgstr "“%s†không thể được dùng vá»›i “%sâ€" +msgstr "'%s' không thể được dùng vá»›i '%s'" #, c-format msgid "'%s' cannot take <start-point>" -msgstr "“%s†không thể nháºn <Ä‘iểm-đầu>" +msgstr "'%s' không thể nháºn <Ä‘iểm-đầu>" #, c-format msgid "Cannot switch branch to a non-commit '%s'" -msgstr "Không thể chuyển nhánh đến má»™t thứ không phải là lần chuyển giao “%sâ€" +msgstr "Không thể chuyển nhánh đến má»™t thứ không phải là lần chuyển giao '%s'" msgid "missing branch or commit argument" msgstr "thiếu tham số là nhánh hoặc lần chuyển giao" +#, c-format +msgid "unknown conflict style '%s'" +msgstr "không hiểu kiểu hiển thị xung Ä‘á»™t '%s'" + msgid "perform a 3-way merge with the new branch" msgstr "thá»±c hiện hòa trá»™n kiểu 3-way vá»›i nhánh má»›i" @@ -3720,13 +3782,13 @@ msgid "detach HEAD at named commit" msgstr "rá»i bá» HEAD tại lần chuyển giao theo tên" msgid "force checkout (throw away local modifications)" -msgstr "ép buá»™c lấy ra (bá» Ä‘i những thay đổi ná»™i bá»™)" +msgstr "ép buá»™c checkout (bá» Ä‘i những thay đổi ná»™i bá»™)" msgid "new-branch" msgstr "nhánh-má»›i" -msgid "new unparented branch" -msgstr "nhánh không cha má»›i" +msgid "new unborn branch" +msgstr "nhánh chÆ°a sinh má»›i" msgid "update ignored files (default)" msgstr "cáºp nháºt các táºp tin bị bá» qua (mặc định)" @@ -3735,15 +3797,13 @@ msgid "do not check if another worktree is holding the given ref" msgstr "không kiểm tra nếu cây là m việc khác Ä‘ang giữ tham chiếu đã cho" msgid "checkout our version for unmerged files" -msgstr "" -"lấy ra (checkout) phiên bản của chúng ta cho các táºp tin chÆ°a được hòa trá»™n" +msgstr "checkout phiên bản của ta cho các táºp tin chÆ°a được hòa trá»™n" msgid "checkout their version for unmerged files" -msgstr "" -"lấy ra (checkout) phiên bản của chúng há» cho các táºp tin chÆ°a được hòa trá»™n" +msgstr "checkout phiên bản của há» cho các táºp tin chÆ°a được hòa trá»™n" msgid "do not limit pathspecs to sparse entries only" -msgstr "không giá»›i hạn đặc tả Ä‘Æ°á»ng dẫn thà nh chỉ các mục rải rác" +msgstr "không giá»›i hạn đặc tả Ä‘Æ°á»ng dẫn chỉ trong các mục sparse (thÆ°a)" #, c-format msgid "options '-%c', '-%c', and '%s' cannot be used together" @@ -3758,7 +3818,7 @@ msgstr "thiếu tên nhánh; hãy thá» -%c" #, c-format msgid "could not resolve %s" -msgstr "không thể phân giải “%sâ€" +msgstr "không thể phân giải '%s'" msgid "invalid path specification" msgstr "Ä‘Æ°á»ng dẫn đã cho không hợp lệ" @@ -3766,19 +3826,19 @@ msgstr "Ä‘Æ°á»ng dẫn đã cho không hợp lệ" #, c-format msgid "'%s' is not a commit and a branch '%s' cannot be created from it" msgstr "" -"“%s†không phải là má»™t lần chuyển giao và má»™t nhánh'%s†không thể được tạo " +"'%s' không phải là má»™t lần chuyển giao và má»™t nhánh'%s' không thể được tạo " "từ đó" #, c-format msgid "git checkout: --detach does not take a path argument '%s'" -msgstr "git checkout: --detach không nháºn má»™t đối số Ä‘Æ°á»ng dẫn “%sâ€" +msgstr "git checkout: --detach không nháºn má»™t đối số Ä‘Æ°á»ng dẫn '%s'" msgid "" "git checkout: --ours/--theirs, --force and --merge are incompatible when\n" "checking out of the index." msgstr "" "git checkout: --ours/--theirs, --force và --merge là xung khắc vá»›i nhau khi\n" -"checkout bảng mục lục (index)." +"checkout chỉ mục (index)." msgid "you must specify path(s) to restore" msgstr "bạn phải chỉ định các thÆ° mục muốn hồi phục" @@ -3796,7 +3856,7 @@ msgid "create reflog for new branch" msgstr "tạo reflog cho nhánh má»›i" msgid "second guess 'git checkout <no-such-branch>' (default)" -msgstr "gợi ý thứ hai “git checkout <không-nhánh-nà o-nhÆ°-váºy>†(mặc định)" +msgstr "gợi ý thứ hai 'git checkout <không-nhánh-nà o-nhÆ°-váºy>' (mặc định)" msgid "use overlay mode (default)" msgstr "dùng chế Ä‘á»™ che phủ (mặc định)" @@ -3814,10 +3874,10 @@ msgid "throw away local modifications" msgstr "vứt bá» các sá»a đổi địa phÆ°Æ¡ng" msgid "which tree-ish to checkout from" -msgstr "lấy ra từ tree-ish nà o" +msgstr "checkout từ tree-ish nà o" msgid "restore the index" -msgstr "phục hồi bảng mục lục" +msgstr "phục hồi chỉ mục" msgid "restore the working tree (default)" msgstr "phục hồi cây là m việc (mặc định)" @@ -3829,18 +3889,18 @@ msgid "use overlay mode" msgstr "dùng chế Ä‘á»™ che phủ" msgid "" -"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..." +"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] " +"[<pathspec>...]" msgstr "" -"git clean [-d] [-f] [-i] [-n] [-q] [-e <mẫu>] [-x | -X] [--] </các/Ä‘Æ°á»ng/" -"dẫn>…" +"git clean [-d] [-f] [-i] [-n] [-q] [-e <mẫu>] [-x | -X] [--][<Ä‘Æ°á»ng/dẫn>...]" #, c-format msgid "Removing %s\n" -msgstr "Äang gỡ bá» %s\n" +msgstr "Äang xoá %s\n" #, c-format msgid "Would remove %s\n" -msgstr "Có thể gỡ bá» %s\n" +msgstr "Sẽ xoá %s\n" #, c-format msgid "Skipping repository %s\n" @@ -3852,17 +3912,17 @@ msgstr "Nên bá» qua kho chứa %s\n" #, c-format msgid "failed to remove %s" -msgstr "gặp lá»—i khi gỡ bá» %s" +msgstr "gặp lá»—i khi xoá %s" #, c-format msgid "could not lstat %s\n" -msgstr "không thể lấy thông tin thống kê đầy đủ của %s\n" +msgstr "không thể lstat %s\n" msgid "Refusing to remove current working directory\n" -msgstr "Từ chối gỡ bá» thÆ° mục là m việc hiện tại\n" +msgstr "Từ chối xoá thÆ° mục là m việc hiện tại\n" msgid "Would refuse to remove current working directory\n" -msgstr "Nên từ chối gỡ bá» thÆ° mục là m việc hiện tại\n" +msgstr "Sẽ từ chối xoá bá» thÆ° mục là m việc hiện tại\n" #, c-format msgid "" @@ -3892,17 +3952,17 @@ msgstr "" "3-5 - chá»n má»™t vùng\n" "2-3,6-9 - chá»n nhiá»u vùng\n" "foo - chá»n mục dá»±a trên tiá»n tố duy nhất\n" -"-… - không chá»n các mục đã chỉ ra\n" +"-... - không chá»n các mục đã chỉ ra\n" "* - chá»n tất\n" " - (để trống) kết thúc việc chá»n\n" -#, c-format, perl-format +#, c-format msgid "Huh (%s)?\n" msgstr "Hả (%s)?\n" #, c-format msgid "Input ignore patterns>> " -msgstr "Mẫu để lá»c các táºp tin đầu và o cần lá» Ä‘i>> " +msgstr "Mẫu để lá»c các táºp tin đầu và o cần bá» qua>> " #, c-format msgid "WARNING: Cannot find items matched by: %s" @@ -3914,7 +3974,7 @@ msgstr "Chá»n mục muốn xóa" #. TRANSLATORS: Make sure to keep [y/N] as is #, c-format msgid "Remove %s [y/N]? " -msgstr "Xóa bỠ“%s†[y/N]? " +msgstr "Xóa bá» '%s' [y/N]? " msgid "" "clean - start cleaning\n" @@ -3935,7 +3995,7 @@ msgstr "" msgid "Would remove the following item:" msgid_plural "Would remove the following items:" -msgstr[0] "Có muốn gỡ bá» (các) mục sau đây không:" +msgstr[0] "Có muốn xoá (các) mục sau đây không:" msgid "No more files to clean, exiting." msgstr "Không còn táºp-tin nà o để dá»n dẹp, Ä‘ang thoát ra." @@ -3950,13 +4010,13 @@ msgid "interactive cleaning" msgstr "dá»n bằng kiểu tÆ°Æ¡ng tác" msgid "remove whole directories" -msgstr "gỡ bá» toà n bá»™ thÆ° mục" +msgstr "xoá toà n bá»™ thÆ° mục" msgid "pattern" msgstr "mẫu" msgid "add <pattern> to ignore rules" -msgstr "thêm <mẫu> và o trong qui tắc bá» qua" +msgstr "thêm <mẫu> và o trong quy tắc bá» qua" msgid "remove ignored files, too" msgstr "đồng thá»i gỡ bá» cả các táºp tin bị bá» qua" @@ -3964,22 +4024,10 @@ msgstr "đồng thá»i gỡ bá» cả các táºp tin bị bá» qua" msgid "remove only ignored files" msgstr "chỉ gỡ bá» những táºp tin bị bá» qua" -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce được đặt thà nh true và không Ä‘Æ°a ra tùy chá»n -i, -n mà " -"cÅ©ng không -f; từ chối lệnh dá»n dẹp (clean)" - -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" +msgid "clean.requireForce is true and -f not given: refusing to clean" msgstr "" -"clean.requireForce mặc định được đặt là true và không Ä‘Æ°a ra tùy chá»n -i, -n " -"mà cÅ©ng không -f; từ chối lệnh dá»n dẹp (clean)" - -msgid "-x and -X cannot be used together" -msgstr "-x và -X không thể dùng cùng nhau" +"clean.requireForce được đặt thà nh true và không có tuỳ chá»n -f; từ chối dá»n " +"dẹp" msgid "git clone [<options>] [--] <repo> [<dir>]" msgstr "git clone [<các tùy chá»n>] [--] <kho> [<t.mục>]" @@ -3991,10 +4039,10 @@ msgid "don't create a checkout" msgstr "không tạo má»™t checkout" msgid "create a bare repository" -msgstr "tạo kho thuần" +msgstr "tạo kho bare" -msgid "create a mirror repository (implies bare)" -msgstr "tạo kho bản sao (ý là kho thuần)" +msgid "create a mirror repository (implies --bare)" +msgstr "tạo kho bản sao (ngụ ý --bare)" msgid "to clone from a local repository" msgstr "để nhân bản từ kho ná»™i bá»™" @@ -4030,10 +4078,10 @@ msgid "name" msgstr "tên" msgid "use <name> instead of 'origin' to track upstream" -msgstr "dùng <tên> thay cho “origin†để theo dõi thượng nguồn" +msgstr "dùng <tên> thay cho 'origin' để theo dõi thượng nguồn" msgid "checkout <branch> instead of the remote's HEAD" -msgstr "lấy ra <nhánh> thay cho HEAD của máy chủ" +msgstr "checkout <nhánh> thay cho HEAD của máy chủ" msgid "path to git-upload-pack on the remote" msgstr "Ä‘Æ°á»ng dẫn đến git-upload-pack trên máy chủ" @@ -4044,9 +4092,6 @@ msgstr "Ä‘á»™-sâu" msgid "create a shallow clone of that depth" msgstr "tạo bản sao không đầy đủ cho mức sâu đã cho" -msgid "time" -msgstr "thá»i-gian" - msgid "create a shallow clone since a specific time" msgstr "tạo bản sao không đầy đủ từ thá»i Ä‘iểm đã cho" @@ -4073,6 +4118,9 @@ msgstr "gitdir" msgid "separate git dir from working tree" msgstr "không dùng chung thÆ° mục dà nh riêng cho git và thÆ° mục là m việc" +msgid "specify the reference format to use" +msgstr "dùng định dạng tham chiếu nà o cho các lần chuyển giao" + msgid "key=value" msgstr "khóa=giá_trị" @@ -4085,40 +4133,48 @@ msgstr "đặc-tả-máy-phục-vụ" msgid "option to transmit" msgstr "tùy chá»n để chuyển giao" -msgid "use IPv4 addresses only" -msgstr "chỉ dùng địa chỉ IPv4" - -msgid "use IPv6 addresses only" -msgstr "chỉ dùng địa chỉ IPv6" - msgid "apply partial clone filters to submodules" msgstr "áp dụng các bá»™ lá»c nhân bản má»™t phần cho mô-Ä‘un-con" msgid "any cloned submodules will use their remote-tracking branch" -msgstr "má»i mô-Ä‘un-con nhân bản sẽ dung nhánh theo dõi máy chủ của chúng" +msgstr "má»i mô-Ä‘un-con được nhân bản sẽ dùng nhánh theo dõi máy chủ của chúng" msgid "initialize sparse-checkout file to include only files at root" msgstr "khởi tạo táºp tin sparse-checkout để bao gồm chỉ các táºp tin ở gốc" +msgid "uri" +msgstr "uri" + +msgid "a URI for downloading bundles before fetching from origin remote" +msgstr "URI để tải xuống bundle trÆ°á»›c khi lấy vá» từ máy chủ origin" + #, c-format msgid "info: Could not add alternate for '%s': %s\n" -msgstr "thông tin: không thể thêm thay thế cho “%sâ€: %s\n" +msgstr "thông tin: không thể thêm thay thế cho '%s': %s\n" #, c-format msgid "failed to stat '%s'" -msgstr "gặp lá»—i khi lấy thống kê vỠ“%sâ€" +msgstr "gặp lá»—i khi stat '%s'" #, c-format msgid "%s exists and is not a directory" msgstr "%s có tồn tại nhÆ°ng lại không phải là má»™t thÆ° mục" #, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "'%s' là liên kết má»m, từ chối sao chép vá»›i --local" + +#, c-format msgid "failed to start iterator over '%s'" -msgstr "gặp lá»—i khi bắt đầu lặp qua “%sâ€" +msgstr "gặp lá»—i khi bắt đầu lặp qua '%s'" + +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "liên kết má»m '%s' đã tồn tại, từ chối sao chép vá»›i --local" #, c-format msgid "failed to unlink '%s'" -msgstr "gặp lá»—i khi bá» liên kết (unlink) “%sâ€" +msgstr "gặp lá»—i khi unlink '%s'" #, c-format msgid "failed to create link '%s'" @@ -4126,11 +4182,11 @@ msgstr "gặp lá»—i khi tạo được 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 và '%s'" #, c-format msgid "failed to iterate over '%s'" -msgstr "gặp lá»—i khi lặp qua “%sâ€" +msgstr "gặp lá»—i khi lặp qua '%s'" #, c-format msgid "done.\n" @@ -4142,8 +4198,8 @@ msgid "" "and retry with 'git restore --source=HEAD :/'\n" msgstr "" "Việc nhân bản thà nh công, nhÆ°ng checkout gặp lá»—i.\n" -"Bạn kiểm tra kỹ xem cái gì được lấy ra bằng lệnh “git statusâ€\n" -"và thá» lấy ra vá»›i lệnh “git restore --source=HEAD :/â€\n" +"Kiểm tra xem cái gì đã được checkout bằng lệnh 'git status'\n" +"và thá» lại vá»›i lệnh 'git restore --source=HEAD :/'\n" #, c-format msgid "Could not find remote branch %s to clone." @@ -4159,11 +4215,11 @@ msgstr "không thể cáºp nháºt %s" msgid "failed to initialize sparse-checkout" msgstr "gặp lá»—i khi khởi tạo sparse-checkout" -msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n" -msgstr "refers HEAD máy chủ chỉ đến ref không tồn tại, không thể lấy ra.\n" +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "HEAD ở máy chủ chỉ đến ref không tồn tại, không thể checkout" msgid "unable to checkout working tree" -msgstr "không thể lấy ra (checkout) cây là m việc" +msgstr "không thể checkout cây là m việc" msgid "unable to write parameters to config file" msgstr "không thể ghi các tham số và o táºp tin cấu hình" @@ -4175,18 +4231,18 @@ msgid "cannot unlink temporary alternates file" msgstr "không thể bá» liên kết táºp tin thay thế tạm thá»i" msgid "Too many arguments." -msgstr "Có quá nhiá»u đối số." +msgstr "Quá nhiá»u đối số." msgid "You must specify a repository to clone." -msgstr "Bạn phải chỉ định má»™t kho để mà nhân bản (clone)." +msgstr "Bạn phải chỉ định má»™t kho để nhân bản." #, c-format -msgid "options '%s' and '%s %s' cannot be used together" -msgstr "tùy chá»n '%s', và '%s %s' không thể dùng cùng nhau" +msgid "unknown ref storage format '%s'" +msgstr "Không hiểu định dạng lÆ°u tham chiếu '%s'" #, c-format msgid "repository '%s' does not exist" -msgstr "kho chứa “%s†chÆ°a tồn tại" +msgstr "kho chứa '%s' chÆ°a tồn tại" #, c-format msgid "depth %s is not a positive number" @@ -4194,32 +4250,32 @@ msgstr "Ä‘á»™ sâu %s không phải là má»™t số nguyên dÆ°Æ¡ng" #, c-format msgid "destination path '%s' already exists and is not an empty directory." -msgstr "Ä‘Æ°á»ng dẫn Ä‘Ãch “%s†đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng." +msgstr "Ä‘Æ°á»ng dẫn Ä‘Ãch '%s' đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng." #, c-format msgid "repository path '%s' already exists and is not an empty directory." msgstr "" -"Ä‘Æ°á»ng dẫn kho chứa “%s†đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng." +"Ä‘Æ°á»ng dẫn kho chứa '%s' đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng." #, c-format msgid "working tree '%s' already exists." -msgstr "cây là m việc “%s†đã sẵn tồn tại rồi." +msgstr "cây là m việc '%s' đã sẵn tồn tại rồi." #, c-format msgid "could not create leading directories of '%s'" -msgstr "không thể tạo các thÆ° mục dẫn đầu của “%sâ€" +msgstr "không thể tạo các thÆ° mục dẫn đầu của '%s'" #, c-format msgid "could not create work tree dir '%s'" -msgstr "không thể tạo cây thÆ° mục là m việc dir “%sâ€" +msgstr "không thể tạo cây là m việc dir '%s'" #, c-format msgid "Cloning into bare repository '%s'...\n" -msgstr "Äang nhân bản thà nh kho chứa bare “%sâ€â€¦\n" +msgstr "Äang nhân bản thà nh kho chứa bare '%s'...\n" #, c-format msgid "Cloning into '%s'...\n" -msgstr "Äang nhân bản thà nh “%sâ€â€¦\n" +msgstr "Äang nhân bản thà nh '%s'...\n" msgid "" "clone --recursive is not compatible with both --reference and --reference-if-" @@ -4230,24 +4286,25 @@ msgstr "" #, c-format msgid "'%s' is not a valid remote name" -msgstr "“%s†không phải tên máy chủ hợp lệ" +msgstr "'%s' không phải tên máy chủ hợp lệ" msgid "--depth is ignored in local clones; use file:// instead." -msgstr "--depth bị lá» Ä‘i khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay thế." +msgstr "" +"--depth bị bá» qua khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay thế." msgid "--shallow-since is ignored in local clones; use file:// instead." msgstr "" -"--shallow-since bị lá» Ä‘i khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay " +"--shallow-since bị bá» qua khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay " "thế." msgid "--shallow-exclude is ignored in local clones; use file:// instead." msgstr "" -"--shallow-exclude bị lá» Ä‘i khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay " +"--shallow-exclude bị bá» qua khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay " "thế." msgid "--filter is ignored in local clones; use file:// instead." msgstr "" -"--filter bị lá» Ä‘i khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay thế." +"--filter bị bá» qua khi nhân bản ná»™i bá»™; hãy sá» dụng file:// để thay thế." msgid "source repository is shallow, reject to clone." msgstr "kho nguồn là nông, nên bá» từ chối nhân bản." @@ -4256,13 +4313,23 @@ msgid "source repository is shallow, ignoring --local" msgstr "kho nguồn là nông, nên bá» qua --local" msgid "--local is ignored" -msgstr "--local bị lá» Ä‘i" +msgstr "--local bị bá» qua" msgid "cannot clone from filtered bundle" msgstr "không thể nhân bản từ bundle được lá»c ra" +msgid "failed to initialize the repo, skipping bundle URI" +msgstr "khởi tạo kho chứa thất bại, Ä‘ang bá» qua URI bundle" + +#, c-format +msgid "failed to fetch objects from bundle URI '%s'" +msgstr "lấy vỠđối tượng từ URI bundle '%s' thất bại" + +msgid "failed to fetch advertised bundles" +msgstr "lấy vá» bundle thất bại" + msgid "remote transport reported error" -msgstr "váºn chuyển máy mạng đã báo cáo lá»—i" +msgstr "trình váºn chuyển đã báo lá»—i" #, c-format msgid "Remote branch %s not found in upstream %s" @@ -4292,38 +4359,50 @@ msgstr "chèn thêm khoảng trắng và o bên phải" msgid "padding space between columns" msgstr "chèn thêm khoảng trắng giữa các cá»™t" +#, c-format +msgid "%s must be non-negative" +msgstr "%s phải không âm" + msgid "--command must be the first argument" msgstr "--command phải là đối số đầu tiên" msgid "" -"git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]" +"git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]" msgstr "" "git commit-graph verify [--object-dir </thÆ°/mục/đối/tượng>] [--shallow] [--" "[no-]progress]" msgid "" -"git commit-graph write [--object-dir <objdir>] [--append] [--" -"split[=<strategy>]] [--reachable|--stdin-packs|--stdin-commits] [--changed-" -"paths] [--[no-]max-new-filters <n>] [--[no-]progress] <split options>" +"git commit-graph write [--object-dir <dir>] [--append]\n" +" [--split[=<strategy>]] [--reachable | --stdin-packs | " +"--stdin-commits]\n" +" [--changed-paths] [--[no-]max-new-filters <n>] [--" +"[no-]progress]\n" +" <split-options>" msgstr "" -"git commit-graph write [--object-dir </thÆ°/mục/đối/tượng>] [--append][--" -"split[=<chiến lược>]] [--reachable|--stdin-packs|--stdin-commits][--changed-" -"paths] [--[no-]max-new-filters <n>] [--[no-]progress] <các tùy chá»n chia " -"tách>" +"git commit-graph write [--object-dir </thÆ°/mục/đối/tượng>] [--append]\n" +" [--split[=<chiến lược>]] [--reachable | --stdin-packs " +"| --stdin-commits]\n" +" [--changed-paths] [--[no-]max-new-filters <n>] [--" +"[no-]progress]\n" +" <các tùy chá»n chia tách>" msgid "dir" -msgstr "tmục" +msgstr "thÆ° mục" msgid "the object directory to store the graph" msgstr "thÆ° mục đối tượng để lÆ°u đồ thị" msgid "if the commit-graph is split, only verify the tip file" -msgstr "" -"nếu đồ-thị-các-lần-chuyển-giao bị chia cắt, thì chỉ thẩm tra táºp tin đỉnh" +msgstr "nếu đồ-thị-chuyển-giao bị chia cắt, thì chỉ thẩm tra táºp tin đỉnh" #, c-format msgid "Could not open commit-graph '%s'" -msgstr "Không thể mở đồ thị chuyển giao “%sâ€" +msgstr "Không thể mở đồ thị chuyển giao '%s'" + +#, c-format +msgid "could not open commit-graph chain '%s'" +msgstr "Không thể mở dãy đồ thị chuyển giao '%s'" #, c-format msgid "unrecognized --split argument, %s" @@ -4331,7 +4410,7 @@ msgstr "đối số --split không được thừa nháºn, %s" #, c-format msgid "unexpected non-hex object ID: %s" -msgstr "nháºn được ID đối tượng không phải dạng hex không cần: %s" +msgstr "nháºn được ID đối tượng không phải dạng hex bất thÆ°á»ng %s" #, c-format msgid "invalid object: %s" @@ -4339,24 +4418,19 @@ msgstr "đối tượng không hợp lệ: %s" #, c-format msgid "option `%s' expects a numerical value" -msgstr "tùy chá»n “%s†cần má»™t giá trị bằng số" +msgstr "tùy chá»n '%s' cần má»™t giá trị bằng số" msgid "start walk at all refs" msgstr "bắt đầu di chuyển tại má»i tham chiếu" msgid "scan pack-indexes listed by stdin for commits" -msgstr "" -"quét dó các mục lục gói được liệt kê bởi đầu và o tiêu chuẩn cho các lần " -"chuyển giao" +msgstr "quét dó các chỉ mục gói được liệt kê bởi stdin cho các lần chuyển giao" msgid "start walk at commits listed by stdin" -msgstr "" -"bắt đầu di chuyển tại các lần chuyển giao được liệt kê bởi đầu và o tiêu chuẩn" +msgstr "bắt đầu di chuyển tại các lần chuyển giao được liệt kê bởi stdin" msgid "include all commits already in the commit-graph file" -msgstr "" -"bao gồm má»i lần chuyển giao đã sẵn có trongÆ°á»i táºp tin đồ-thị-các-lần-chuyển-" -"giao" +msgstr "bao gồm má»i lần chuyển giao đã sẵn có trong táºp tin đồ-thị-chuyển-giao" msgid "enable computation for changed paths" msgstr "cho phép tÃnh toán các Ä‘Æ°á»ng dẫn đã bị thay đổi" @@ -4366,11 +4440,11 @@ msgstr "cho phép ghi má»™t táºp tin đồ há»a các lần chuyển giao lá»›n msgid "maximum number of commits in a non-base split commit-graph" msgstr "" -"số lượng tối Ä‘a của các lần chuyển giao trong má»™t đồ-thị-các-lần-chuyển-giao " -"chia cắt không-cÆ¡-sở" +"số lượng tối Ä‘a của các lần chuyển giao trong má»™t đồ-thị-chuyển-giao chia " +"cắt không-cÆ¡-sở" msgid "maximum ratio between two levels of a split commit-graph" -msgstr "tá»· lệ tối Ä‘a giữa hai mức của má»™t đồ-thị-các-lần-chuyển-giao chia cắt" +msgstr "tỉ lệ tối Ä‘a giữa hai mức của má»™t đồ-thị-chuyển-giao chia cắt" msgid "only expire files older than a given date-time" msgstr "chỉ là m hết hạn các táºp tin khi nó cÅ© hÆ¡n khoảng <thá»i gian> Ä‘Æ°a ra" @@ -4385,16 +4459,15 @@ msgstr "" msgid "Collecting commits from input" msgstr "SÆ°u táºp các lần chuyển giao từ đầu và o" -#, c-format -msgid "unrecognized subcommand: %s" -msgstr "không hiểu câu lệnh con: %s" +msgid "git commit-tree <tree> [(-p <parent>)...]" +msgstr "git commit-tree <cây> [(-p <cha>)...]" msgid "" -"git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...] [(-F " -"<file>)...] <tree>" +"git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n" +" [(-F <file>)...] <tree>" msgstr "" -"git commit-tree [(-p <cha>)…] [-S[<keyid>]] [(-m <ghi chú>)…] [(-F <táºp tin>)" -"…] <cây>" +"git commit-tree [(-p <cha>)...] [-S[<keyid>]] [(-m <ghi chú>)...]\n" +" [(-F <táºp tin>)...] <cây>" #, c-format msgid "duplicate parent %s ignored" @@ -4402,15 +4475,15 @@ msgstr "cha mẹ bị trùng lặp %s đã bị bá» qua" #, c-format msgid "not a valid object name %s" -msgstr "không phải là tên đối tượng hợp lệ “%sâ€" +msgstr "không phải là tên đối tượng hợp lệ '%s'" #, c-format msgid "git commit-tree: failed to read '%s'" -msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c “%sâ€" +msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c '%s'" #, c-format msgid "git commit-tree: failed to close '%s'" -msgstr "git commit-tree: gặp lá»—i khi đóng “%sâ€" +msgstr "git commit-tree: gặp lá»—i khi đóng '%s'" msgid "parent" msgstr "cha-mẹ" @@ -4436,22 +4509,38 @@ msgstr "phải Ä‘Æ°a ra chÃnh xác má»™t cây" msgid "git commit-tree: failed to read" msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c" -msgid "git commit [<options>] [--] <pathspec>..." -msgstr "git commit [<các tùy chá»n>] [--] <pathspec>…" +msgid "" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" +" [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" +"reword):]<commit>)]\n" +" [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" +" [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n" +" [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" +" [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" +" [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" +" [--] [<pathspec>...]" +msgstr "" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u<chế-Ä‘á»™>] [--amend]\n" +" [--dry-run] [(-c | -C | --squash) <lần chuyển giao> | --fixup " +"[(amend|reword):]<lần chuyển giao>)]\n" +" [-F <táºp tin> | -m <ghi chú>] [--reset-author] [--allow-empty]\n" +" [--allow-empty-message] [--no-verify] [-e] [--author=<tác giả>]\n" +" [--date=<ngà y tháng>] [--cleanup=<chế-Ä‘á»™>] [--[no-]status]\n" +" [-i | -o] [--pathspec-from-file=<táºp-tin> [--pathspec-file-nul]]\n" +" [(--trailer <thẻ>[(=|:)<giá-trị>])...] [-S[<keyid>]]\n" +" [--] [<pathspec>...]" -msgid "git status [<options>] [--] <pathspec>..." -msgstr "git status [<các tùy chá»n>] [--] <pathspec>…" +msgid "git status [<options>] [--] [<pathspec>...]" +msgstr "git status [<các tùy chá»n>] [--] <pathspec>..." 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" "remove the commit entirely with \"git reset HEAD^\".\n" msgstr "" -"Bạn đã yêu cầu amend (“tu bổâ€) phần lá»›n các lần chuyển giao gần đây, nhÆ°ng " -"là m nhÆ° thế\n" -"có thể là m cho nó trở nên trống rá»—ng. Bạn có thể lặp lại lệnh của mình bằng " -"--allow-empty,\n" -"hoặc là bạn gỡ bá» các lần chuyển giao má»™t cách hoà n toà n bằng lệnh:\n" +"Bạn đã yêu cầu amend ('tu bổ') lần chuyển giao gần nhất, nhÆ°ng là m váºy\n" +"sẽ là m cho nó trở nên rá»—ng. Bạn có thể lặp lại lệnh vá»›i --allow-empty,\n" +"hoặc là bạn gỡ bá» lần chuyển giao má»™t cách hoà n toà n bằng lệnh:\n" "\"git reset HEAD^\".\n" msgid "" @@ -4461,18 +4550,17 @@ msgid "" " git commit --allow-empty\n" "\n" msgstr "" -"Lần cherry-pick trÆ°á»›c hiện nay trống rá»—ng, có lẽ là bởi vì sá»± phân giải xung " -"Ä‘á»™t.\n" +"Lần cherry-pick trÆ°á»›c hiện nay trống rá»—ng, có lẽ là do giải quyết xung Ä‘á»™t.\n" "Nếu bạn vẫn muốn chuyển giao nó cho dù thế nà o Ä‘i nữa, hãy dùng:\n" "\n" " git commit --allow-empty\n" "\n" msgid "Otherwise, please use 'git rebase --skip'\n" -msgstr "Nếu không được thì dùng lệnh \"git rebase --skip\"\n" +msgstr "Nếu không thì dùng lệnh \"git rebase --skip\"\n" msgid "Otherwise, please use 'git cherry-pick --skip'\n" -msgstr "Nếu không được thì dùng lệnh \"git cherry-pick --skip\"\n" +msgstr "Nếu không thì dùng lệnh \"git cherry-pick --skip\"\n" msgid "" "and then use:\n" @@ -4489,12 +4577,15 @@ msgstr "" "\n" " git cherry-pick --continue\n" "\n" -"để lại tiếp tục cherry-picking các lần chuyển giao còn lại.\n" +"để lại tiếp tục cherry-pick các lần chuyển giao còn lại.\n" "Nếu bạn muốn bá» qua lần chuyển giao nà y thì dùng:\n" "\n" " git cherry-pick --skip\n" "\n" +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" @@ -4502,20 +4593,17 @@ 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ý." msgid "unable to create temporary index" -msgstr "không thể tạo bảng mục lục tạm thá»i" +msgstr "không thể tạo chỉ mục tạm thá»i" msgid "interactive add failed" msgstr "gặp lá»—i khi thêm bằng cách tÆ°Æ¡ng" msgid "unable to update temporary index" -msgstr "không thể cáºp nháºt bảng mục lục tạm thá»i" +msgstr "không thể cáºp nháºt chỉ mục tạm thá»i" msgid "Failed to update main cache tree" msgstr "Gặp lá»—i khi cáºp nháºt cây bá»™ nhá»› đệm" -msgid "unable to write new_index file" -msgstr "không thể ghi táºp tin lÆ°u bảng mục lục má»›i (new_index)" - msgid "cannot do a partial commit during a merge." msgstr "" "không thể thá»±c hiện việc chuyển giao cục bá»™ trong khi Ä‘ang được hòa trá»™n." @@ -4529,21 +4617,21 @@ msgstr "" "không thể thá»±c hiện việc chuyển giao cục bá»™ trong khi Ä‘ang thá»±c hiện cải tổ." msgid "cannot read the index" -msgstr "không Ä‘á»c được bảng mục lục" +msgstr "không Ä‘á»c được chỉ mục" msgid "unable to write temporary index file" -msgstr "không thể ghi táºp tin lÆ°u bảng mục lục tạm thá»i" +msgstr "không thể ghi táºp tin chỉ mục tạm thá»i" #, c-format msgid "commit '%s' lacks author header" -msgstr "lần chuyển giao “%s†thiếu phần tác giả ở đầu" +msgstr "lần chuyển giao '%s' thiếu phần tác giả ở đầu" #, c-format msgid "commit '%s' has malformed author line" -msgstr "lần chuyển giao “%s†có phần tác giả ở đầu dị dạng" +msgstr "lần chuyển giao '%s' có phần tác giả ở đầu dị dạng" msgid "malformed --author parameter" -msgstr "đối số cho --author bị dị hình" +msgstr "đối số cho --author bị sai quy cách" #, c-format msgid "invalid date format: %s" @@ -4557,19 +4645,19 @@ msgstr "" "trong phần ghi chú hiện tại" #, c-format -msgid "could not lookup commit %s" -msgstr "không thể tìm kiếm commit (lần chuyển giao) %s" +msgid "could not lookup commit '%s'" +msgstr "không thể tìm kiếm lần chuyển giao '%s'" #, c-format msgid "(reading log message from standard input)\n" -msgstr "(Ä‘ang Ä‘á»c thông Ä‘iệp nháºt ký từ đầu và o tiêu chuẩn)\n" +msgstr "(Ä‘ang Ä‘á»c thông Ä‘iệp nháºt ký từ stdin)\n" msgid "could not read log from standard input" -msgstr "không thể Ä‘á»c nháºt ký từ đầu và o tiêu chuẩn" +msgstr "không thể Ä‘á»c nháºt ký từ stdin" #, c-format msgid "could not read log file '%s'" -msgstr "không Ä‘á»c được tệp nháºt ký “%sâ€" +msgstr "không Ä‘á»c được táºp nháºt ký '%s'" #, c-format msgid "options '%s' and '%s:%s' cannot be used together" @@ -4583,7 +4671,7 @@ msgstr "không thể Ä‘á»c MERGE_MSG" #, c-format msgid "could not open '%s'" -msgstr "không thể mở “%sâ€" +msgstr "không thể mở '%s'" msgid "could not write commit template" msgstr "không thể ghi mẫu chuyển giao" @@ -4591,39 +4679,39 @@ msgstr "không thể ghi mẫu chuyển giao" #, 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 "" "Hãy nháºp và o các thông tin để giải thÃch các thay đổi của bạn. Những\n" -"dòng được bắt đầu bằng “%c†sẽ được bá» qua.\n" +"dòng được bắt đầu bằng '%s' sẽ được bá» qua.\n" #, 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 "" "Hãy nháºp và o các thông tin để giải thÃch các thay đổi của bạn. Những dòng " "được\n" -"bắt đầu bằng “%c†sẽ được bá» qua, nếu phần chú thÃch rá»—ng sẽ hủy bá» lần " +"bắt đầu bằng '%s' sẽ được bá» qua, nếu phần chú thÃch rá»—ng sẽ hủy bá» lần " "chuyển giao.\n" #, 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 "" "Hãy nháºp và o các thông tin để giải thÃch các thay đổi của bạn. Những dòng " "được\n" -"bắt đầu bằng “%c†sẽ được bá» qua; bạn có thể xóa chúng Ä‘i nếu muốn thế.\n" +"bắt đầu bằng '%s' sẽ được bá» qua; bạn có thể xóa chúng Ä‘i nếu muốn thế.\n" #, 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 "" "Hãy nháºp và o các thông tin để giải thÃch các thay đổi của bạn. Những dòng " "được\n" -"bắt đầu bằng “%c†sẽ được bá» qua; bạn có thể xóa chúng Ä‘i nếu muốn thế.\n" +"bắt đầu bằng '%s' sẽ được bá» qua; bạn có thể xóa chúng Ä‘i nếu muốn thế.\n" "Phần chú thÃch nà y nếu trống rá»—ng sẽ hủy bá» lần chuyển giao.\n" msgid "" @@ -4665,10 +4753,10 @@ msgid "%sCommitter: %.*s <%.*s>" msgstr "%sNgÆ°á»i chuyển giao: %.*s <%.*s>" msgid "Cannot read index" -msgstr "Không Ä‘á»c được bảng mục lục" +msgstr "Không Ä‘á»c được chỉ mục" msgid "unable to pass trailers to --trailers" -msgstr "không thể chuyển phần Ä‘uôi cho “--trailersâ€" +msgstr "không thể chuyển phần Ä‘uôi cho '--trailers'" msgid "Error building trees" msgstr "Gặp lá»—i khi xây dá»±ng cây" @@ -4680,25 +4768,25 @@ msgstr "Xin hãy cung cấp lá»i chú giải hoặc là dùng tùy chá»n -m ho #, c-format msgid "--author '%s' is not 'Name <email>' and matches no existing author" msgstr "" -"--author “%s†không phải là “Há» và tên <thÆ° Ä‘iện tá»l>†và không khá»›p bất kỳ " -"tác giả nà o sẵn có" +"--author '%s' không phải là 'Há»-và -tên <email>' và không khá»›p bất kỳ tác giả " +"nà o sẵn có" #, c-format msgid "Invalid ignored mode '%s'" -msgstr "Chế Ä‘á»™ bá» qua không hợp lệ “%sâ€" +msgstr "Chế Ä‘á»™ bá» qua không hợp lệ '%s'" #, c-format msgid "Invalid untracked files mode '%s'" -msgstr "Chế Ä‘á»™ cho các táºp tin chÆ°a được theo dõi không hợp lệ “%sâ€" +msgstr "Chế Ä‘á»™ cho các táºp tin chÆ°a được theo dõi không hợp lệ '%s'" msgid "You are in the middle of a merge -- cannot reword." msgstr "" -"Bạn Ä‘ang ở giữa của quá trình hòa trá»™n -- không thể thá»±c hiện việc “rewordâ€." +"Bạn Ä‘ang ở giữa của quá trình hòa trá»™n -- không thể thá»±c hiện việc 'reword'." msgid "You are in the middle of a cherry-pick -- cannot reword." msgstr "" "Bạn Ä‘ang ở giữa của quá trình cherry-pick -- không thể thá»±c hiện việc " -"“rewordâ€." +"'reword'." #, c-format msgid "reword option of '%s' and path '%s' cannot be used together" @@ -4710,20 +4798,20 @@ msgid "reword option of '%s' and '%s' cannot be used together" msgstr "không thể tổ hợp tùy chá»n \"reword\" của '%s' vá»›i '%s' cùng nhau" msgid "You have nothing to amend." -msgstr "Không có gì để mà “tu bổ†cả." +msgstr "Không có gì để 'tu bổ' cả." msgid "You are in the middle of a merge -- cannot amend." msgstr "" -"Bạn Ä‘ang ở giữa của quá trình hòa trá»™n -- không thể thá»±c hiện việc “tu bổâ€." +"Bạn Ä‘ang ở giữa của quá trình hòa trá»™n -- không thể thá»±c hiện việc 'tu bổ'." msgid "You are in the middle of a cherry-pick -- cannot amend." msgstr "" -"Bạn Ä‘ang ở giữa của quá trình cherry-pick -- không thể thá»±c hiện việc “tu " -"bổâ€." +"Bạn Ä‘ang ở giữa của quá trình cherry-pick -- không thể thá»±c hiện việc 'tu " +"bổ'." msgid "You are in the middle of a rebase -- cannot amend." msgstr "" -"Bạn Ä‘ang ở giữa của quá trình cải tổ -- nên không thể thá»±c hiện việc “tu bổâ€." +"Bạn Ä‘ang ở giữa của quá trình cải tổ -- nên không thể thá»±c hiện việc 'tu bổ'." msgid "--reset-author can be used only with -C, -c or --amend." msgstr "" @@ -4735,7 +4823,7 @@ msgstr "không hiểu tùy chá»n: --fixup=%s:%s" #, c-format msgid "paths '%s ...' with -a does not make sense" -msgstr "các Ä‘Æ°á»ng dẫn “%s …†vá»›i tùy chá»n -a không hợp lý" +msgstr "các Ä‘Æ°á»ng dẫn '%s ...' vá»›i tùy chá»n -a không hợp lý" msgid "show status concisely" msgstr "hiển thị trạng thái ở dạng súc tÃch" @@ -4747,7 +4835,7 @@ msgid "show stash information" msgstr "hiển thị thông tin vá» tạm cất" msgid "compute full ahead/behind values" -msgstr "tÃnh đầy đủ giá trị trÆ°á»›c/sau" +msgstr "tÃnh đầy đủ giá trị dẫn trÆ°á»›c/sau" msgid "version" msgstr "phiên bản" @@ -4759,10 +4847,7 @@ msgid "show status in long format (default)" msgstr "hiển thị trạng thái ở định dạng dà i (mặc định)" msgid "terminate entries with NUL" -msgstr "chấm dứt các mục bằng NUL" - -msgid "mode" -msgstr "chế Ä‘á»™" +msgstr "kết thúc các mục bằng NUL" msgid "show untracked files, optional modes: all, normal, no. (Default: all)" msgstr "" @@ -4790,20 +4875,19 @@ msgid "list untracked files in columns" msgstr "hiển thị danh sách các táºp-tin chÆ°a được theo dõi trong các cá»™t" msgid "do not detect renames" -msgstr "không dò tìm các tên thay đổi" +msgstr "không dò tìm các lần đổi tên" msgid "detect renames, optionally set similarity index" -msgstr "dò các tên thay đổi, tùy ý đặt mục lục tÆ°Æ¡ng tá»±" +msgstr "tìm và phát hiện các lần đổi tên, có thể đánh chỉ số tÆ°Æ¡ng tá»±" msgid "Unsupported combination of ignored and untracked-files arguments" -msgstr "" -"Không há»— trỡ tổ hợp các tham số các táºp tin bị bá» qua và không được theo dõi" +msgstr "Không há»— trợ cùng lúc tham số táºp tin bị bá» qua và không được theo dõi" msgid "suppress summary after successful commit" msgstr "không hiển thị tổng kết sau khi chuyển giao thà nh công" msgid "show diff in commit message template" -msgstr "hiển thị sá»± khác biệt trong mẫu tin nhắn chuyển giao" +msgstr "hiển thị diff trong mẫu tin nhắn chuyển giao" msgid "Commit message options" msgstr "Các tùy chá»n ghi chú commit" @@ -4878,7 +4962,7 @@ msgid "commit all changed files" msgstr "chuyển giao tất cả các táºp tin có thay đổi" msgid "add specified files to index for commit" -msgstr "thêm các táºp tin đã chỉ ra và o bảng mục lục để chuyển giao" +msgstr "thêm các táºp tin đã chỉ ra và o chỉ mục để chuyển giao" msgid "interactively add files" msgstr "thêm các táºp-tin bằng tÆ°Æ¡ng tác" @@ -4896,7 +4980,7 @@ msgid "show what would be committed" msgstr "hiển thị xem cái gì có thể được chuyển giao" msgid "amend previous commit" -msgstr "“tu bổ†(amend) lần commit trÆ°á»›c" +msgstr "'tu bổ' (amend) lần commit trÆ°á»›c" msgid "bypass post-rewrite hook" msgstr "vòng qua móc (hook) post-rewrite" @@ -4908,7 +4992,7 @@ msgid "ok to record a change with an empty message" msgstr "ok để ghi các thay đổi vá»›i lá»i nhắn trống rá»—ng" msgid "could not parse HEAD commit" -msgstr "không thể phân tÃch commit (lần chuyển giao) HEAD" +msgstr "không thể Ä‘á»c commit (lần chuyển giao) HEAD" #, c-format msgid "Corrupt MERGE_HEAD file (%s)" @@ -4923,27 +5007,26 @@ msgstr "không thể Ä‘á»c phần chú thÃch (message) của lần chuyển gi #, c-format msgid "Aborting commit due to empty commit message.\n" -msgstr "Bãi bá» việc chuyển giao bởi vì phần chú thÃch của nó trống rá»—ng.\n" +msgstr "Huá»· bá» lệnh chuyển giao bởi vì phần chú thÃch của nó trống rá»—ng.\n" #, c-format msgid "Aborting commit; you did not edit the message.\n" msgstr "" -"Äang bá» qua việc chuyển giao; bạn đã không biên soạn phần chú thÃch " -"(message).\n" +"Huá»· bá» lệnh chuyển giao; bạn đã không biên soạn phần chú thÃch (message).\n" #, c-format msgid "Aborting commit due to empty commit message body.\n" msgstr "" -"Bãi bá» việc chuyển giao bởi vì phần thân chú thÃch của nó trống rá»—ng.\n" +"Huá»· bá» lệnh chuyển giao bởi vì phần thân chú thÃch của nó trống rá»—ng.\n" msgid "" "repository has been updated, but unable to write\n" -"new_index file. Check that disk is not full and quota is\n" +"new index file. Check that disk is not full and quota is\n" "not exceeded, and then \"git restore --staged :/\" to recover." msgstr "" "kho chứa đã được cáºp nháºt, nhÆ°ng không thể ghi và o\n" -"táºp tin new_index (bảng mục lục má»›i). Hãy kiểm tra xem Ä‘Ä©a\n" -"có bị đầy quá hay quota (hạn nghạch Ä‘Ä©a cứng) bị vượt quá,\n" +"táºp tin chỉ mục má»›i. Hãy kiểm tra xem Ä‘Ä©a\n" +"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>]" @@ -5017,7 +5100,7 @@ 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â€" +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" @@ -5059,7 +5142,7 @@ msgid "Other" msgstr "Khác" msgid "terminate values with NUL byte" -msgstr "chấm dứt giá trị vá»›i byte NUL" +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" @@ -5068,9 +5151,7 @@ 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ị nguyên gốc của cấu hình (táºp tin, đầu và o tiêu chuẩn, blob, dòng " -"lệnh)" +msgstr "hiển thị nguồn gốc của cấu hình (táºp tin, stdin, blob, dòng lệnh)" msgid "show scope of config (worktree, local, global, system, command)" msgstr "" @@ -5083,6 +5164,9 @@ msgstr "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" +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)" + #, c-format msgid "wrong number of arguments, should be %d" msgstr "sai số lượng tham số, phải là %d" @@ -5105,16 +5189,16 @@ msgstr "gặp lá»—i khi định dạng giá trị cấu hình mặc định: %s" #, c-format msgid "cannot parse color '%s'" -msgstr "không thể phân tÃch mà u “%sâ€" +msgstr "không thể Ä‘á»c mà u '%s'" msgid "unable to parse default color value" -msgstr "không thể phân tÃch giá trị mà u mặc định" +msgstr "không thể Ä‘á»c giá trị mà u mặc định" msgid "not in a git directory" msgstr "không trong thÆ° mục git" msgid "writing to stdin is not supported" -msgstr "việc ghi ra đầu ra tiêu chuẩn là không được há»— trợ" +msgstr "việc ghi ra stdin là không được há»— trợ" msgid "writing config blobs is not supported" msgstr "không há»— trợ ghi cấu hình các blob" @@ -5176,25 +5260,28 @@ msgstr "" 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 "--fixed-value only applies with 'value-pattern'" -msgstr "--fixed-value chỉ áp dụng vá»›i “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â€" +msgstr "không thể Ä‘á»c táºp tin cấu hình '%s'" msgid "error processing config file(s)" msgstr "gặp lá»—i khi xá» lý các táºp tin cấu hình" msgid "editing stdin is not supported" -msgstr "sá»a chữa đầu ra tiêu chuẩn là không được há»— trợ" +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â€" +msgstr "không thể tạo táºp tin cấu hình '%s'" #, c-format msgid "" @@ -5219,12 +5306,12 @@ msgid "" "\tchmod 0700 %s" msgstr "" "Quyá»n hạn trên thÆ° mục gói mạng của bạn không chÃnh xác; ngÆ°á»i dùng\n" -"khác có lẽ có thể Ä‘á»c được chứng thÆ° được lÆ°u đệm của bạn. Cân nhắc chạy:\n" +"khác có lẽ có thể Ä‘á»c được chứng thÆ° được lÆ°u đệm của bạn. Thá» chạy:\n" "\n" "\tchmod 0700 %s" msgid "print debugging messages to stderr" -msgstr "in thông tin gỡ lá»—i ra đầu ra lá»—i tiêu chuẩn" +msgstr "in thông tin gỡ lá»—i ra stderr" msgid "credential-cache--daemon unavailable; no unix socket support" msgstr "credential-cache--daemon không sẵn có; không há»— trợ unix socket" @@ -5236,17 +5323,24 @@ msgstr "credential-cache không sẵn có; không há»— trợ unix socket" msgid "unable to get credential storage lock in %d ms" msgstr "không thể lấy khóa lÆ°u trữ ủy nhiệm %d ms" -msgid "git describe [<options>] [<commit-ish>...]" -msgstr "git describe [<các tùy chá»n>] <commit-ish>*" +msgid "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]" +msgstr "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]" + +msgid "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]" +msgstr "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]" -msgid "git describe [<options>] --dirty" -msgstr "git describe [<các tùy chá»n>] --dirty" +msgid "git describe <blob>" +msgstr "git describe <blob>" msgid "head" -msgstr "phÃa trÆ°á»›c" +msgstr "head" msgid "lightweight" -msgstr "hạng nhẹ" +msgstr "nhẹ" msgid "annotated" msgstr "có diá»…n giải" @@ -5257,11 +5351,11 @@ msgstr "thẻ đã được ghi chú %s không sẵn để dùng" #, c-format msgid "tag '%s' is externally known as '%s'" -msgstr "ở bên ngoà i, thẻ “%s†đã được biết đến là “%sâ€" +msgstr "ở bên ngoà i, thẻ '%s' đã được biết đến là '%s'" #, c-format msgid "no tag exactly matches '%s'" -msgstr "không có thẻ nà o khá»›p chÃnh xác vá»›i “%sâ€" +msgstr "không có thẻ nà o khá»›p chÃnh xác vá»›i '%s'" #, c-format msgid "No exact match on refs or tags, searching to describe\n" @@ -5276,7 +5370,7 @@ msgid "" "No annotated tags can describe '%s'.\n" "However, there were unannotated tags: try --tags." msgstr "" -"Không có thẻ được chú giải nà o được mô tả là “%sâ€.\n" +"Không có thẻ được chú giải nà o được mô tả là '%s'.\n" "Tuy nhiên, ở đây có những thẻ không được chú giải: hãy thá» --tags." #, c-format @@ -5284,7 +5378,7 @@ msgid "" "No tags can describe '%s'.\n" "Try --always, or create some tags." msgstr "" -"Không có thẻ có thể mô tả “%sâ€.\n" +"Không có thẻ có thể mô tả '%s'.\n" "Hãy thá» --always, hoặc tạo má»™t số thẻ." #, c-format @@ -5315,13 +5409,13 @@ msgid "find the tag that comes after the commit" msgstr "tìm các thẻ mà nó đến trÆ°á»›c lần chuyển giao" msgid "debug search strategy on stderr" -msgstr "chiến lược tìm kiếm gỡ lá»—i trên đầu ra lá»—i chuẩn stderr" +msgstr "gỡ lá»—i chiến lược tìm kiếm ra stderr" msgid "use any ref" msgstr "dùng ref bất kỳ" msgid "use any tag, even unannotated" -msgstr "dùng thẻ bất kỳ, cả khi “unannotatedâ€" +msgstr "dùng thẻ bất kỳ, cả khi 'unannotated'" msgid "always use long format" msgstr "luôn dùng định dạng dà i" @@ -5333,39 +5427,60 @@ msgid "only output exact matches" msgstr "chỉ xuất những gì khá»›p chÃnh xác" msgid "consider <n> most recent tags (default: 10)" -msgstr "coi nhÆ° <n> thẻ gần đây nhất (mặc định: 10)" +msgstr "chá»n trong <n> thẻ gần đây nhất (mặc định: 10)" msgid "only consider tags matching <pattern>" -msgstr "chỉ cân nhắc đến những thẻ khá»›p vá»›i <mẫu>" +msgstr "chỉ chá»n những thẻ khá»›p vá»›i <mẫu>" msgid "do not consider tags matching <pattern>" -msgstr "không coi rằng các thẻ khá»›p vá»›i <mẫu>" +msgstr "không chá»n những thẻ khá»›p vá»›i <mẫu>" msgid "show abbreviated commit object as fallback" -msgstr "hiển thị đối tượng chuyển giao vắn tắt nhÆ° là fallback" +msgstr "hiển thị vắn tắt đối tượng chuyển giao để thay thế" msgid "mark" msgstr "dấu" msgid "append <mark> on dirty working tree (default: \"-dirty\")" -msgstr "thêm <dấu> trên cây thÆ° mục là m việc bẩn (mặc định \"-dirty\")" +msgstr "thêm <dấu> trên cây là m việc không sạch (mặc định \"-dirty\")" msgid "append <mark> on broken working tree (default: \"-broken\")" -msgstr "thêm <dấu> trên cây thÆ° mục là m việc bị há»ng (mặc định \"-broken\")" +msgstr "thêm <dấu> trên cây là m việc bị há»ng (mặc định \"-broken\")" msgid "No names found, cannot describe anything." -msgstr "Không tìm thấy các tên, không thể mô tả gì cả." +msgstr "Không tìm thấy tên, không thể mô tả gì cả." #, c-format msgid "option '%s' and commit-ishes cannot be used together" msgstr "tùy chá»n '%s' và commit-ishes không thể dùng cùng nhau" +msgid "" +"git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n" +" [--mode=<mode>]" +msgstr "" +"git diagnose [(-o | --output-directory) <táºp tin>] [(-s | --suffix) <định " +"dạng>]\n" +" [--mode=<chế Ä‘á»™>]" + +msgid "specify a destination for the diagnostics archive" +msgstr "chỉ định thÆ° mục Ä‘Ãch để tạo bản báo cáo" + +msgid "specify a strftime format suffix for the filename" +msgstr "" +"chỉ định chuá»—i định dạng thá»i gian strftime dùng là m háºu tố cho tên táºp tin" + +msgid "specify the content of the diagnostic archive" +msgstr "chỉ định ná»™i dung bản báo cáo" + msgid "--merge-base only works with two commits" msgstr "--merge-base chỉ hoạt Ä‘á»™ng vá»›i hai lần chuyển giao" #, c-format msgid "'%s': not a regular file or symlink" -msgstr "“%sâ€: không phải táºp tin bình thÆ°á»ng hay liên kết má»m" +msgstr "'%s': không phải táºp tin bình thÆ°á»ng hay liên kết má»m" + +msgid "no merge given, only parents." +msgstr "không có lần hoà trá»™n, chỉ có các lần chuyển giao cha" #, c-format msgid "invalid option: %s" @@ -5373,31 +5488,31 @@ msgstr "tùy chá»n không hợp lệ: %s" #, c-format msgid "%s...%s: no merge base" -msgstr "%s…%s: không có cÆ¡ sở hòa trá»™n" +msgstr "%s...%s: không có gốc hòa trá»™n" msgid "Not a git repository" msgstr "Không phải là kho git" #, c-format msgid "invalid object '%s' given." -msgstr "đối tượng đã cho “%s†không hợp lệ." +msgstr "đối tượng đã cho '%s' không hợp lệ." #, c-format msgid "more than two blobs given: '%s'" -msgstr "đã cho nhiá»u hÆ¡n hai đối tượng blob: “%sâ€" +msgstr "đã cho nhiá»u hÆ¡n hai đối tượng blob: '%s'" #, c-format msgid "unhandled object '%s' given." -msgstr "đã cho đối tượng không thể nắm giữ “%sâ€." +msgstr "đã cho đối tượng không thể xá» lý '%s'." #, c-format msgid "%s...%s: multiple merge bases, using %s" -msgstr "%s…%s: có nhiá»u cÆ¡ sở để hòa trá»™n, nên dùng %s" +msgstr "%s...%s: có nhiá»u gốc hòa trá»™n, sẽ dùng %s" msgid "git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]" msgstr "" "git difftool [<các tùy chá»n>] [<lần_chuyển_giao> [<lần_chuyển_giao>]] [--] </" -"Ä‘Æ°á»ng/dẫn>…]" +"Ä‘Æ°á»ng/dẫn>...]" #, c-format msgid "could not read symlink %s" @@ -5415,23 +5530,23 @@ msgid "" "combined diff formats ('-c' and '--cc') are not supported in\n" "directory diff mode ('-d' and '--dir-diff')." msgstr "" -"các định dạng diff tổ hợp(“-c†và “--ccâ€) chÆ°a được há»— trợ trong\n" -"chế Ä‘á»™ diff thÆ° mục(“-d†và “--dir-diffâ€)." +"các định dạng diff tổ hợp('-c' và '--cc') chÆ°a được há»— trợ trong\n" +"chế Ä‘á»™ diff thÆ° mục('-d' và '--dir-diff')." #, c-format msgid "both files modified: '%s' and '%s'." -msgstr "cả hai táºp tin đã bị sá»a: “%s†và “%sâ€." +msgstr "cả hai táºp tin đã bị sá»a: '%s' và '%s'." msgid "working tree file has been left." msgstr "cây là m việc ở bên trái." #, c-format msgid "could not copy '%s' to '%s'" -msgstr "không thể chép “%s†sang “%sâ€" +msgstr "không thể chép '%s' sang '%s'" #, c-format msgid "temporary files exist in '%s'." -msgstr "các táºp tin tạm đã sẵn có trong “%sâ€." +msgstr "các táºp tin tạm đã sẵn có trong '%s'." msgid "you may want to cleanup or recover these." msgstr "bạn có lẽ muốn dá»n dẹp hay phục hồi ở đây." @@ -5441,7 +5556,7 @@ msgid "failed: %d" msgstr "gặp lá»—i: %d" msgid "use `diff.guitool` instead of `diff.tool`" -msgstr "dùng “diff.guitool“ thay vì dùng “diff.tool“" +msgstr "dùng 'diff.guitool' thay vì dùng 'diff.tool'" msgid "perform a full-directory diff" msgstr "thá»±c hiện má»™t diff toà n thÆ° mục" @@ -5459,18 +5574,18 @@ msgid "use the specified diff tool" msgstr "dùng công cụ diff đã cho" msgid "print a list of diff tools that may be used with `--tool`" -msgstr "in ra danh sách các công cụ dif cái mà có thẻ dùng vá»›i “--tool“" +msgstr "in ra danh sách các công cụ dif cái mà có thẻ dùng vá»›i '--tool'" msgid "" "make 'git-difftool' exit when an invoked diff tool returns a non-zero exit " "code" -msgstr "là m cho “git-difftool†thoát khi gá»i công cụ diff trả vá» mã khác không" +msgstr "là m cho 'git-difftool' thoát khi gá»i công cụ diff trả vá» mã khác không" msgid "specify a custom command for viewing diffs" msgstr "chỉ định má»™t lệnh tùy ý để xem diff" msgid "passed to `diff`" -msgstr "chuyển cho “diffâ€" +msgstr "chuyển cho 'diff'" msgid "difftool requires worktree or --no-index" msgstr "difftool cần cây là m việc hoặc --no-index" @@ -5481,28 +5596,6 @@ msgstr "chÆ°a Ä‘Æ°a ra <công_cụ> cho --tool=<công_cụ>" msgid "no <cmd> given for --extcmd=<cmd>" msgstr "chÆ°a Ä‘Æ°a ra <lệnh> cho --extcmd=<lệnh>" -msgid "git env--helper --type=[bool|ulong] <options> <env-var>" -msgstr "git env--helper --type=[bool|ulong] <các tùy chá»n> <env-var>" - -msgid "default for git_env_*(...) to fall back on" -msgstr "mặc định cho git_env_*(…) để quay vá»" - -msgid "be quiet only use git_env_*() value as exit code" -msgstr "im lặng chỉ khi dung giá trị git_env_*() là m mã thoát" - -#, c-format -msgid "option `--default' expects a boolean value with `--type=bool`, not `%s`" -msgstr "" -"tùy chá»n “--default†cần má»™t giá trị logic vá»›i “--type=bool“, không phải “%s“" - -#, c-format -msgid "" -"option `--default' expects an unsigned long value with `--type=ulong`, not `" -"%s`" -msgstr "" -"tùy chá»n “--default†cần má»™t giá trị số nguyên dà i không dấu vá»›i “--" -"type=ulong“, không phải “%s“" - msgid "git fast-export [<rev-list-opts>]" msgstr "git fast-export [<rev-list-opts>]" @@ -5541,7 +5634,7 @@ msgid "output full tree for each commit" msgstr "xuất ra toà n bá»™ cây cho má»—i lần chuyển giao" msgid "use the done feature to terminate the stream" -msgstr "sá» dụng tÃnh năng done để chấm dứt luồng dữ liệu" +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" @@ -5574,40 +5667,40 @@ msgstr "gắn thẻ vá»›i các mã ID đánh dấu" #, c-format msgid "Missing from marks for submodule '%s'" -msgstr "Thiếu các đánh dấu cho mô-Ä‘un-con “%sâ€" +msgstr "Thiếu các đánh dấu cho mô-Ä‘un-con '%s'" #, c-format msgid "Missing to marks for submodule '%s'" -msgstr "Thiếu đánh dấu cho mô-Ä‘un-con “%sâ€" +msgstr "Thiếu đánh dấu cho mô-Ä‘un-con '%s'" #, c-format msgid "Expected 'mark' command, got %s" -msgstr "Cần lệnh “markâ€, nhÆ°ng lại nháºn được %s" +msgstr "Cần lệnh 'mark', nhÆ°ng lại có %s" #, c-format msgid "Expected 'to' command, got %s" -msgstr "Cần lệnh “toâ€, nhÆ°ng lại nháºn Ä‘ược %s" +msgstr "Cần lệnh 'to', nhÆ°ng lại có %s" msgid "Expected format name:filename for submodule rewrite option" -msgstr "Cần định dạng tên:tên_táºp_tin cho tùy chá»n ghi lại mô-Ä‘un-con" +msgstr "Cần định dạng tên:tên_táºp tin cho tùy chá»n ghi lại mô-Ä‘un-con" #, c-format msgid "feature '%s' forbidden in input without --allow-unsafe-features" msgstr "" -"tÃnh năng “%s†bị cấm chỉ trong đầu và o mà không có --allow-unsafe-features" +"tÃnh năng '%s' bị cấm chỉ trong đầu và o mà không có --allow-unsafe-features" #, c-format msgid "Lockfile created but not reported: %s" msgstr "Táºp tin khóa đã được tạo nhÆ°ng chÆ°a được báo cáo: %s" msgid "git fetch [<options>] [<repository> [<refspec>...]]" -msgstr "git fetch [<các tùy chá»n>] [<kho-chứa> [<refspec>…]]" +msgstr "git fetch [<các tùy chá»n>] [<kho-chứa> [<refspec>...]]" msgid "git fetch [<options>] <group>" msgstr "git fetch [<các tùy chá»n>] [<nhóm>" msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]" -msgstr "git fetch --multiple [<các tùy chá»n>] [(<kho> | <nhóm>)…]" +msgstr "git fetch --multiple [<các tùy chá»n>] [(<kho> | <nhóm>)...]" msgid "git fetch --all [<options>]" msgstr "git fetch --all [<các tùy chá»n>]" @@ -5615,118 +5708,14 @@ msgstr "git fetch --all [<các tùy chá»n>]" msgid "fetch.parallel cannot be negative" msgstr "fetch.parallel không thể âm" -msgid "fetch from all remotes" -msgstr "lấy vá» từ tất cả các máy chủ" - -msgid "set upstream for git pull/fetch" -msgstr "đặt thượng nguồn cho git pull/fetch" - -msgid "append to .git/FETCH_HEAD instead of overwriting" -msgstr "nối thêm và o .git/FETCH_HEAD thay vì ghi đè lên nó" - -msgid "use atomic transaction to update references" -msgstr "sá» dụng giao dịch hạt nhân bên phÃa máy chủ" - -msgid "path to upload pack on remote end" -msgstr "Ä‘Æ°á»ng dẫn đến gói tải lên trên máy chủ cuối" - -msgid "force overwrite of local reference" -msgstr "ép buá»™c ghi đè lên tham chiếu ná»™i bá»™" - -msgid "fetch from multiple remotes" -msgstr "lấy từ nhiá»u máy chủ cùng lúc" - -msgid "fetch all tags and associated objects" -msgstr "lấy tất cả các thẻ cùng vá»›i các đối tượng liên quan đến nó" - -msgid "do not fetch all tags (--no-tags)" -msgstr "không lấy tất cả các thẻ (--no-tags)" - -msgid "number of submodules fetched in parallel" -msgstr "số lượng mô-Ä‘un-con được lấy đồng thá»i" - -msgid "modify the refspec to place all refs within refs/prefetch/" -msgstr "" -"sá»a đặc tả Ä‘Æ°á»ng dẫn cho các tham chiếu má»i chá»— có trong refs/prefetch/" - -msgid "prune remote-tracking branches no longer on remote" -msgstr "" -"cắt cụt (prune) các nhánh “remote-tracking†không còn tồn tại trên máy chủ " -"nữa" - -msgid "prune local tags no longer on remote and clobber changed tags" -msgstr "cắt xém các thẻ ná»™i bá»™ không còn ở máy chủ và xóa các thẻ đã thay đổi" - -msgid "on-demand" -msgstr "khi-cần" - -msgid "control recursive fetching of submodules" -msgstr "Ä‘iá»u khiển việc lấy vỠđệ quy trong các mô-Ä‘un-con" - -msgid "write fetched references to the FETCH_HEAD file" -msgstr "ghi các tham chiếu lấy vá» và o táºp tin FETCH_HEAD" - -msgid "keep downloaded pack" -msgstr "giữ lại gói đã tải vá»" - -msgid "allow updating of HEAD ref" -msgstr "cho phép cáºp nháºt th.chiếu HEAD" - -msgid "deepen history of shallow clone" -msgstr "là m sâu hÆ¡n lịch sá» của bản sao" - -msgid "deepen history of shallow repository based on time" -msgstr "là m sâu hÆ¡n lịch sá» của kho bản sao shallow dá»±a trên thá»i gian" - -msgid "convert to a complete repository" -msgstr "chuyển đổi hoà n toà n sang kho git" - -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" - -msgid "" -"default for recursive fetching of submodules (lower priority than config " -"files)" -msgstr "" -"mặc định cho việc lấy đệ quy các mô-Ä‘un-con (có mức Æ°u tiên thấp hÆ¡n các táºp " -"tin cấu hình config)" - -msgid "accept refs that update .git/shallow" -msgstr "chấp nháºn tham chiếu cáºp nháºt .git/shallow" - -msgid "refmap" -msgstr "refmap" - -msgid "specify fetch refmap" -msgstr "chỉ ra refmap cần lấy vá»" - -msgid "report that we have only objects reachable from this object" -msgstr "" -"báo cáo rằng chúng ta chỉ có các đối tượng tiếp cáºn được từ đối tượng nà y" - -msgid "do not fetch a packfile; instead, print ancestors of negotiation tips" -msgstr "" -"không lấy vá» má»™t packfile; thay và o đó, hãy in tổ tiên của đỉnh Ä‘Ã m phán" - -msgid "run 'maintenance --auto' after fetching" -msgstr "chạy “maintenance --auto†sau khi lấy vá»" - -msgid "check for forced-updates on all updated branches" -msgstr "kiểm cho các-cáºp-nháºt-bắt-buá»™c trên má»i nhánh đã cáºp nháºt" - -msgid "write the commit-graph after fetching" -msgstr "ghi ra đồ thị các lần chuyển giao sau khi lấy vá»" - -msgid "accept refspecs from stdin" -msgstr "chấp nháºn tham chiếu từ đầu và o tiêu chuẩn" - msgid "couldn't find remote ref HEAD" msgstr "không thể tìm thấy HEAD tham chiếu máy chủ" #, c-format +msgid "From %.*s\n" +msgstr "Từ %.*s\n" + +#, c-format msgid "object %s not found" msgstr "không tìm thấy đối tượng %s" @@ -5736,11 +5725,8 @@ msgstr "[đã cáºp nháºt]" msgid "[rejected]" msgstr "[Bị từ chối]" -msgid "can't fetch in current branch" -msgstr "không thể fetch (lấy) vá» nhánh hiện hà nh" - -msgid "checked out in another worktree" -msgstr "lấy ra trong cây là m việc khác" +msgid "can't fetch into checked-out branch" +msgstr "không thể fetch vá» nhánh đã checkout" msgid "[tag update]" msgstr "[cáºp nháºt thẻ]" @@ -5768,7 +5754,7 @@ msgstr "không-phải-chuyển-tiếp-nhanh" #, c-format msgid "cannot open '%s'" -msgstr "không mở được “%sâ€" +msgstr "không mở được '%s'" msgid "" "fetch normally indicates which branches had a forced update,\n" @@ -5777,7 +5763,7 @@ msgid "" msgstr "" "việc lấy vá» thÆ°á»ng chỉ ra các nhánh buá»™c phải cáºp nháºt,\n" "nhÆ°ng lá»±a chá»n bị tắt; để kÃch hoạt lại, sá» dụng cá»\n" -"“--show-forced-updates†hoặc chạy “git config fetch.showForcedUpdates trueâ€." +"'--show-forced-updates' hoặc chạy 'git config fetch.showForcedUpdates true'." #, c-format msgid "" @@ -5787,8 +5773,8 @@ msgid "" "to avoid this check\n" msgstr "" "việc nà y cần %.2f giây để kiểm tra các cáºp nháºt ép buá»™c; bạn có thể dùng\n" -"“--no-show-forced-updates†hoặc chạy “git config fetch.showForcedUpdates " -"falseâ€\n" +"'--no-show-forced-updates' hoặc chạy 'git config fetch.showForcedUpdates " +"false'\n" "để tránh kiểm tra nà y\n" #, c-format @@ -5800,16 +5786,12 @@ msgid "rejected %s because shallow roots are not allowed to be updated" msgstr "từ chối %s bởi vì các gốc nông thì không được phép cáºp nháºt" #, c-format -msgid "From %.*s\n" -msgstr "Từ %.*s\n" - -#, c-format msgid "" "some local refs could not be updated; try running\n" " 'git remote prune %s' to remove any old, conflicting branches" msgstr "" "má»™t số tham chiếu ná»™i bá»™ không thể được cáºp nháºt; hãy thá» chạy\n" -" “git remote prune %s†để bá» Ä‘i những nhánh cÅ©, hay bị xung Ä‘á»™t" +" 'git remote prune %s' để bá» Ä‘i những nhánh cÅ©, hay bị xung Ä‘á»™t" #, c-format msgid " (%s will become dangling)" @@ -5827,7 +5809,7 @@ msgstr "(không)" #, c-format msgid "refusing to fetch into branch '%s' checked out at '%s'" -msgstr "từ chối lấy vá» và o nhánh “%s†đã được lấy ra tại “%sâ€" +msgstr "từ chối lấy vá» và o nhánh '%s' đã được checkout tại '%s'" #, c-format msgid "option \"%s\" value \"%s\" is not valid for %s" @@ -5843,7 +5825,7 @@ msgstr "%s không phải là má»™t đối tượng hợp lệ" #, c-format msgid "the object %s does not exist" -msgstr "đối tượng “%s†không tồn tại" +msgstr "đối tượng '%s' không tồn tại" msgid "multiple branches detected, incompatible with --set-upstream" msgstr "phát hiện nhiá»u nhánh, không tÆ°Æ¡ng thÃch vá»›i --set-upstream" @@ -5874,15 +5856,15 @@ msgstr "" #, c-format msgid "Fetching %s\n" -msgstr "Äang lấy “%s†vá»\n" +msgstr "Äang lấy '%s' vá»\n" #, c-format msgid "could not fetch %s" -msgstr "không thể lấy “%s†vá»" +msgstr "không thể lấy '%s' vá»" #, c-format msgid "could not fetch '%s' (exit code: %d)\n" -msgstr "không thể lấy “%s†(mã thoát: %d)\n" +msgstr "không thể lấy '%s' (mã thoát: %d)\n" msgid "" "no remote repository specified; please specify either a URL or a\n" @@ -5894,6 +5876,113 @@ msgstr "" msgid "you need to specify a tag name" msgstr "bạn cần chỉ định má»™t tên thẻ" +msgid "fetch from all remotes" +msgstr "lấy vá» từ tất cả các máy chủ" + +msgid "set upstream for git pull/fetch" +msgstr "đặt thượng nguồn cho git pull/fetch" + +msgid "append to .git/FETCH_HEAD instead of overwriting" +msgstr "nối thêm và o .git/FETCH_HEAD thay vì ghi đè lên nó" + +msgid "use atomic transaction to update references" +msgstr "sá» dụng giao dịch hạt nhân bên phÃa máy chủ" + +msgid "path to upload pack on remote end" +msgstr "Ä‘Æ°á»ng dẫn đến gói tải lên trên máy chủ cuối" + +msgid "force overwrite of local reference" +msgstr "ép buá»™c ghi đè lên tham chiếu ná»™i bá»™" + +msgid "fetch from multiple remotes" +msgstr "lấy từ nhiá»u máy chủ cùng lúc" + +msgid "fetch all tags and associated objects" +msgstr "lấy tất cả các thẻ cùng vá»›i các đối tượng liên quan đến nó" + +msgid "do not fetch all tags (--no-tags)" +msgstr "không lấy tất cả các thẻ (--no-tags)" + +msgid "number of submodules fetched in parallel" +msgstr "số lượng mô-Ä‘un-con được lấy đồng thá»i" + +msgid "modify the refspec to place all refs within refs/prefetch/" +msgstr "" +"sá»a đặc tả Ä‘Æ°á»ng dẫn cho các tham chiếu má»i chá»— có trong refs/prefetch/" + +msgid "prune remote-tracking branches no longer on remote" +msgstr "" +"cắt (prune) các nhánh 'remote-tracking' không còn tồn tại trên máy chủ nữa" + +msgid "prune local tags no longer on remote and clobber changed tags" +msgstr "" +"xoá (prune) các thẻ ná»™i bá»™ không còn ở máy chủ và xóa các thẻ đã thay đổi" + +msgid "on-demand" +msgstr "khi-cần" + +msgid "control recursive fetching of submodules" +msgstr "Ä‘iá»u khiển việc lấy vỠđệ quy trong các mô-Ä‘un-con" + +msgid "write fetched references to the FETCH_HEAD file" +msgstr "ghi các tham chiếu lấy vá» và o táºp tin FETCH_HEAD" + +msgid "keep downloaded pack" +msgstr "giữ lại gói đã tải vá»" + +msgid "allow updating of HEAD ref" +msgstr "cho phép cáºp nháºt th.chiếu HEAD" + +msgid "deepen history of shallow clone" +msgstr "là m sâu hÆ¡n lịch sá» của bản sao" + +msgid "deepen history of shallow repository based on time" +msgstr "là m sâu hÆ¡n lịch sá» của kho bản sao shallow dá»±a trên thá»i gian" + +msgid "convert to a complete repository" +msgstr "chuyển đổi hoà n toà n sang kho git" + +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" + +msgid "" +"default for recursive fetching of submodules (lower priority than config " +"files)" +msgstr "" +"mặc định cho việc lấy đệ quy các mô-Ä‘un-con (có mức Æ°u tiên thấp hÆ¡n các táºp " +"tin cấu hình config)" + +msgid "accept refs that update .git/shallow" +msgstr "chấp nháºn tham chiếu cáºp nháºt .git/shallow" + +msgid "refmap" +msgstr "refmap" + +msgid "specify fetch refmap" +msgstr "chỉ ra refmap cần lấy vá»" + +msgid "report that we have only objects reachable from this object" +msgstr "báo rằng ta chỉ có các đối tượng tiếp cáºn được từ đối tượng nà y" + +msgid "do not fetch a packfile; instead, print ancestors of negotiation tips" +msgstr "" +"không lấy vá» má»™t packfile; thay và o đó, hãy in tổ tiên của đỉnh Ä‘Ã m phán" + +msgid "run 'maintenance --auto' after fetching" +msgstr "chạy 'maintenance --auto' sau khi lấy vá»" + +msgid "check for forced-updates on all updated branches" +msgstr "kiểm cho các-cáºp-nháºt-bắt-buá»™c trên má»i nhánh đã cáºp nháºt" + +msgid "write the commit-graph after fetching" +msgstr "ghi ra đồ thị các lần chuyển giao sau khi lấy vá»" + +msgid "accept refspecs from stdin" +msgstr "chấp nháºn tham chiếu từ stdin" + msgid "--negotiate-only needs one or more --negotiation-tip=*" msgstr "--negotiate-only cần má»™t hay nhiá»u --negotiation-tip=* hÆ¡n" @@ -5903,6 +5992,10 @@ msgstr "mức sâu là số âm trong --deepen là không được há»— trợ" msgid "--unshallow on a complete repository does not make sense" msgstr "--unshallow trên kho hoà n chỉnh là không hợp lý" +#, c-format +msgid "failed to fetch bundles from '%s'" +msgstr "gặp lá»—i khi lấy vá» bundle từ '%s'" + msgid "fetch --all does not take a repository argument" msgstr "lệnh lấy vá» \"fetch --all\" không lấy đối số kho chứa" @@ -5942,16 +6035,16 @@ msgstr "" "tin>]" 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â€" +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 (không được dùng)" +msgstr "bà danh cho --log (đã lạc háºu)" msgid "text" msgstr "văn bản" msgid "use <text> as start of message" -msgstr "dùng <văn bản thÆ°á»ng> để bắt đầu ghi chú" +msgstr "dùng <văn bản> để bắt đầu ghi chú" msgid "use <name> instead of the real target branch" msgstr "dùng <tên> thay cho nhánh Ä‘Ãch tháºt" @@ -5976,16 +6069,16 @@ msgstr "" "chuyển-giao>]]" msgid "quote placeholders suitably for shells" -msgstr "trÃch dẫn để phù hợp cho hệ vá» (shell)" +msgstr "trÃch dẫn dạng phù hợp cho shell" msgid "quote placeholders suitably for perl" -msgstr "trÃch dẫn để phù hợp cho perl" +msgstr "trÃch dẫn dạng phù hợp cho perl" msgid "quote placeholders suitably for python" -msgstr "trÃch dẫn để phù hợp cho python" +msgstr "trÃch dẫn dạng phù hợp cho python" msgid "quote placeholders suitably for Tcl" -msgstr "trÃch dẫn để phù hợp cho Tcl" +msgstr "trÃch dẫn dạng phù hợp cho Tcl" msgid "show only <n> matched refs" msgstr "hiển thị chỉ <n> tham chiếu khá»›p" @@ -6008,8 +6101,17 @@ msgstr "chỉ hiển thị những tham chiếu mà nó chứa lần chuyển gi msgid "print only refs which don't contain the commit" msgstr "chỉ hiển thị những tham chiếu mà nó không chứa lần chuyển giao" -msgid "git for-each-repo --config=<config> <command-args>" -msgstr "git for-each-repo --config=<config> <command-args>" +msgid "read reference patterns from stdin" +msgstr "Ä‘á»c các mẫu tham chiếu từ stdin" + +msgid "also include HEAD ref and pseudorefs" +msgstr "bao gồm tham chiếu HEAD và giả tham chiếu" + +msgid "unknown arguments supplied with --stdin" +msgstr "đối số không rõ được chỉ định cùng vá»›i --stdin" + +msgid "git for-each-repo --config=<config> [--] <arguments>" +msgstr "git for-each-repo --config=<tùy chá»n> [--] <đối số>" msgid "config" msgstr "config" @@ -6020,6 +6122,10 @@ msgstr "khóa cấu hình lÆ°u trữ danh sách Ä‘Æ°á»ng dẫn kho lÆ°u trữ" msgid "missing --config=<config>" msgstr "thiếu --config=<config>" +#, c-format +msgid "got bad config --config=%s" +msgstr "cấu hình sai --config=%s" + msgid "unknown" msgstr "không hiểu" @@ -6068,11 +6174,11 @@ msgstr "không thể tạo lost-found" #, c-format msgid "could not write '%s'" -msgstr "không thể ghi “%sâ€" +msgstr "không thể ghi '%s'" #, c-format msgid "could not finish '%s'" -msgstr "không thể hoà n thà nh “%sâ€" +msgstr "không thể hoà n thà nh '%s'" #, c-format msgid "Checking %s" @@ -6087,7 +6193,7 @@ msgid "Checking %s %s" msgstr "Äang kiểm tra %s %s" msgid "broken links" -msgstr "các liên kết bị gẫy" +msgstr "liên kết há»ng" #, c-format msgid "root %s" @@ -6107,7 +6213,7 @@ msgstr "%s: mục reflog không hợp lệ %s" #, c-format msgid "Checking reflog %s->%s" -msgstr "Äang kiểm tra việc đổi tên của “%s†thà nh “%sâ€" +msgstr "Äang kiểm tra việc đổi tên của '%s' thà nh '%s'" #, c-format msgid "%s: invalid sha1 pointer %s" @@ -6130,11 +6236,11 @@ msgstr "%s: thiếu đối tượng hoặc há»ng: %s" #, c-format msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: đối tượng có kiểu chÆ°a biết “%sâ€: %s" +msgstr "%s: đối tượng có kiểu chÆ°a biết '%s': %s" #, c-format msgid "%s: object could not be parsed: %s" -msgstr "%s: không thể phân tÃch cú đối tượng: %s" +msgstr "%s: không thể Ä‘á»c cú đối tượng: %s" #, c-format msgid "bad sha1 file: %s" @@ -6166,36 +6272,57 @@ msgstr "%s: HEAD đã tách rá»i không chỉ và o đâu cả" msgid "notice: %s points to an unborn branch (%s)" msgstr "chú ý: %s chỉ đến má»™t nhánh chÆ°a sinh (%s)" -msgid "Checking cache tree" -msgstr "Äang kiểm tra cây nhá»› tạm" +#, c-format +msgid "Checking cache tree of %s" +msgstr "Äang kiểm tra cây nhá»› tạm của %s" #, c-format -msgid "%s: invalid sha1 pointer in cache-tree" -msgstr "%s: con trá» sha1 không hợp lệ trong cache-tree" +msgid "%s: invalid sha1 pointer in cache-tree of %s" +msgstr "%s: con trá» sha1 không hợp lệ trong cây nhá»› tạm của %s" msgid "non-tree in cache-tree" msgstr "non-tree trong cache-tree" -msgid "git fsck [<options>] [<object>...]" -msgstr "git fsck [<các tùy chá»n>] [<đối-tượng>…]" +#, c-format +msgid "%s: invalid sha1 pointer in resolve-undo of %s" +msgstr "%s: con trá» sha1 không hợp lệ trong resolve-undo của %s" + +#, c-format +msgid "unable to load rev-index for pack '%s'" +msgstr "không thể tải pack-index cho gói '%s'" + +#, c-format +msgid "invalid rev-index for pack '%s'" +msgstr "giá trị rev-index cho gói '%s' không hợp lệ" + +msgid "" +"git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" +" [--[no-]full] [--strict] [--verbose] [--lost-found]\n" +" [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" +" [--[no-]name-objects] [<object>...]" +msgstr "" +"git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" +" [--[no-]full] [--strict] [--verbose] [--lost-found]\n" +" [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" +" [--[no-]name-objects] [<đối tượng>...]" msgid "show unreachable objects" -msgstr "hiển thị các đối tượng không thể Ä‘á»c được" +msgstr "hiển thị các đối tượng không thể tá»›i được" msgid "show dangling objects" msgstr "hiển thị các đối tượng không được quản lý" msgid "report tags" -msgstr "báo cáo các thẻ" +msgstr "liệt kê các thẻ" msgid "report root nodes" -msgstr "báo cáo node gốc" +msgstr "liệt kê node gốc" msgid "make index objects head nodes" -msgstr "tạo “index objects head nodesâ€" +msgstr "tạo 'index objects head nodes'" msgid "make reflogs head nodes (default)" -msgstr "tạo “reflogs head nodes†(mặc định)" +msgstr "tạo 'reflogs head nodes' (mặc định)" msgid "also consider packs and alternate objects" msgstr "cÅ©ng cân nhắc đến các đối tượng gói và thay thế" @@ -6224,7 +6351,7 @@ msgstr "%s: thiếu đối tượng" #, c-format msgid "invalid parameter: expected sha1, got '%s'" -msgstr "tham số không hợp lệ: cần sha1, nhÆ°ng lại nháºn được “%sâ€" +msgstr "tham số không hợp lệ: cần sha1, nhÆ°ng lại có '%s'" msgid "git fsmonitor--daemon start [<options>]" msgstr "git fsmonitor--daemon start [<các tùy chá»n>]" @@ -6232,15 +6359,9 @@ msgstr "git fsmonitor--daemon start [<các tùy chá»n>]" msgid "git fsmonitor--daemon run [<options>]" msgstr "git fsmonitor--daemon run [<các tùy chá»n>]" -msgid "git fsmonitor--daemon stop" -msgstr "git fsmonitor--daemon stop" - -msgid "git fsmonitor--daemon status" -msgstr "git fsmonitor--daemon status" - #, c-format msgid "value of '%s' out of range: %d" -msgstr "siá trị '%s' ngoà i phạm vi cho phép: %d" +msgstr "giá trị '%s' ngoà i phạm vi cho phép: %d" #, c-format msgid "value of '%s' not bool or int: %d" @@ -6256,7 +6377,7 @@ msgstr "fsmonitor-daemon hiện không theo dõi '%s'\n" #, c-format msgid "could not create fsmonitor cookie '%s'" -msgstr "không thể tạo fsmonitor cookie “%sâ€" +msgstr "không thể tạo fsmonitor cookie '%s'" #, c-format msgid "fsmonitor: cookie_result '%d' != SEEN" @@ -6264,24 +6385,23 @@ msgstr "fsmonitor: cookie_result '%d' != SEEN" #, c-format msgid "could not start IPC thread pool on '%s'" -msgstr "không thể khởi chạy bể tiến trình IPC trêm “%sâ€" +msgstr "không thể khởi chạy pool tiến trình IPC trên '%s'" msgid "could not start fsmonitor listener thread" -msgstr "không thể lấy thông tin thống kê vá» tuyến trình lắng nghe fsmonitor" +msgstr "không thể khởi chạy fsmonitor listener thread" msgid "could not start fsmonitor health thread" -msgstr "" -"không thể lấy thông tin thống kê vá» tuyến trình theo dõi sức khá»e fsmonitor" +msgstr "không thể khởi chạy fsmonitor health thread" msgid "could not initialize listener thread" -msgstr "không thể khởi tạo tuyến trình lắng nghe" +msgstr "không thể khởi tạo listener thread" msgid "could not initialize health thread" -msgstr "không thể khởi tạo tuyến trình sức " +msgstr "không thể khởi tạo health thread" #, c-format msgid "could not cd home '%s'" -msgstr "không thể chuyển đến thÆ° mục cá nhân “%sâ€" +msgstr "không thể cd home '%s'" #, c-format msgid "fsmonitor--daemon is already running '%s'" @@ -6293,7 +6413,7 @@ msgstr "chạy fsmonitor-daemon trong '%s'\n" #, c-format msgid "starting fsmonitor-daemon in '%s'\n" -msgstr "Ä‘ang khởi chạy fsmonitor-daemon trong “%sâ€\n" +msgstr "Ä‘ang khởi chạy fsmonitor-daemon trong '%s'\n" msgid "daemon failed to start" msgstr "gặp lá»—i khi khởi chạy dịch vụ chạy ngầm" @@ -6329,15 +6449,15 @@ msgstr "git gc [<các tùy chá»n>]" #, c-format msgid "Failed to fstat %s: %s" -msgstr "Gặp lá»—i khi lấy thông tin thống kê vá» táºp tin %s: %s" +msgstr "Gặp lá»—i khi fstat %s: %s" #, c-format msgid "failed to parse '%s' value '%s'" -msgstr "gặp lá»—i khi phân tÃch “%s†giá trị “%sâ€" +msgstr "gặp lá»—i khi Ä‘á»c '%s' giá trị '%s'" #, c-format msgid "cannot stat '%s'" -msgstr "không thể lấy thông tin thống kê vỠ“%sâ€" +msgstr "không thể stat '%s'" #, c-format msgid "" @@ -6359,6 +6479,9 @@ msgstr "xóa bá» các đối tượng không được tham chiếu" msgid "pack unreferenced objects separately" msgstr "đóng gói riêng các đối tượng không được tham chiếu" +msgid "with --cruft, limit the size of new cruft packs" +msgstr "vá»›i tuỳ chá»n --cruft, giá»›i hạn kÃch thÆ°á»›c pack cruft má»›i" + msgid "be more thorough (increased runtime)" msgstr "cẩn tháºn hÆ¡n nữa (tăng thá»i gian chạy)" @@ -6373,11 +6496,11 @@ msgstr "đóng gói lại tất cả các gói khác ngoại trừ gói lá»›n nh #, c-format msgid "failed to parse gc.logExpiry value %s" -msgstr "gặp lá»—i khi phân tÃch giá trị gc.logExpiry %s" +msgstr "gặp lá»—i khi Ä‘á»c giá trị gc.logExpiry %s" #, c-format msgid "failed to parse prune expiry value %s" -msgstr "gặp lá»—i khi phân tÃch giá trị prune %s" +msgstr "gặp lá»—i khi Ä‘á»c giá trị prune %s" #, c-format msgid "Auto packing the repository in background for optimum performance.\n" @@ -6397,13 +6520,13 @@ msgstr "Xem \"git help gc\" để có hÆ°á»›ng dẫn cụ thể vá» cách dá»n msgid "" "gc is already running on machine '%s' pid %<PRIuMAX> (use --force if not)" msgstr "" -"gc Ä‘ang được thá»±c hiện trên máy “%s†pid %<PRIuMAX> (dùng --force nếu không " +"gc Ä‘ang được thá»±c hiện trên máy '%s' pid %<PRIuMAX> (dùng --force nếu không " "phải thế)" msgid "" "There are too many unreachable loose objects; run 'git prune' to remove them." msgstr "" -"Có quá nhiá»u đối tượng tá»± do không được dùng đến; hãy chạy lệnh “git prune†" +"Có quá nhiá»u đối tượng tá»± do không được dùng đến; hãy chạy lệnh 'git prune' " "để xóa bá» chúng Ä‘i." msgid "" @@ -6425,19 +6548,19 @@ msgid "failed to prefetch remotes" msgstr "gặp lá»—i khi tải trÆ°á»›c các máy chủ" msgid "failed to start 'git pack-objects' process" -msgstr "gặp lá»—i khi lấy thông tin thống kê vá» tiến trình “git pack-objectsâ€" +msgstr "gặp lá»—i khi khởi chạy tiến trình 'git pack-objects'" msgid "failed to finish 'git pack-objects' process" -msgstr "gặp lá»—i khi hoà n tất tiến trình “git pack-objectsâ€" +msgstr "gặp lá»—i khi hoà n tất tiến trình 'git pack-objects'" msgid "failed to write multi-pack-index" msgstr "gặp lá»—i khi ghi multi-pack-index" msgid "'git multi-pack-index expire' failed" -msgstr "gặp lá»—i khi chạy “git multi-pack-index expireâ€" +msgstr "gặp lá»—i khi chạy 'git multi-pack-index expire'" msgid "'git multi-pack-index repack' failed" -msgstr "gặp lá»—i khi chạy “git multi-pack-index repackâ€" +msgstr "gặp lá»—i khi chạy 'git multi-pack-index repack'" msgid "" "skipping incremental-repack task because core.multiPackIndex is disabled" @@ -6445,19 +6568,19 @@ msgstr "bá» qua tác vụ incremental-repack vì core.multiPackIndex bị vô h #, c-format msgid "lock file '%s' exists, skipping maintenance" -msgstr "đã có khóa của táºp tin “%sâ€, bá» qua bảo trì" +msgstr "đã có khóa của táºp tin '%s', bá» qua bảo trì" #, c-format msgid "task '%s' failed" -msgstr "gặp lá»—i khi thá»±c hiện nhiệm vụ “%sâ€" +msgstr "gặp lá»—i khi thá»±c hiện nhiệm vụ '%s'" #, c-format msgid "'%s' is not a valid task" -msgstr "“%s†không phải má»™t nhiệm vụ hợp lệ" +msgstr "'%s' không phải má»™t nhiệm vụ hợp lệ" #, c-format msgid "task '%s' cannot be selected multiple times" -msgstr "nhiệm vụ “%s†không được chá»n nhiá»u lần" +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" @@ -6469,7 +6592,7 @@ msgid "run tasks based on frequency" msgstr "chạy nhiệm vụ dá»±a trên tần suất" msgid "do not report progress or other information over stderr" -msgstr "đừng báo cáo diá»…n tiến hay các thông tin khác ra đầu lá»—i tiêu chuẩn" +msgstr "đừng báo cáo tiến Ä‘á»™ hay các thông tin khác ra stderr" msgid "task" msgstr "tác vụ" @@ -6480,12 +6603,24 @@ msgstr "chạy má»™t nhiệm vụ cụ thể" msgid "use at most one of --auto and --schedule=<frequency>" msgstr "dùng nhiá»u nhất là má»™t trong --auto và --schedule=<frequency>" -msgid "failed to run 'git config'" -msgstr "gặp lá»—i khi chạy “git configâ€" +#, c-format +msgid "unable to add '%s' value of '%s'" +msgstr "không thể thêm giá trị '%s' của '%s'" + +msgid "return success even if repository was not registered" +msgstr "trả vá» thà nh công kể cả khi kho chứa chÆ°a được ghi nháºn" + +#, c-format +msgid "unable to unset '%s' value of '%s'" +msgstr "không thể bỠđặt giá trị '%s' của '%s'" + +#, c-format +msgid "repository '%s' is not registered" +msgstr "kho chứa '%s' chÆ°a tồn tại" #, c-format msgid "failed to expand path '%s'" -msgstr "gặp lá»—i khi khai triển Ä‘Æ°á»ng dẫn “%sâ€" +msgstr "gặp lá»—i khi khai triển Ä‘Æ°á»ng dẫn '%s'" msgid "failed to start launchctl" msgstr "gặp lá»—i khi khởi chạy launchctl" @@ -6502,38 +6637,41 @@ msgid "failed to create temp xml file" msgstr "gặp lá»—i khi tạo táºp tin xml tạm thá»i" msgid "failed to start schtasks" -msgstr "gặp lá»—i khi lấy thông tin thống kê vá» schtasks" +msgstr "gặp lá»—i khi khởi chạy schtasks" msgid "failed to run 'crontab -l'; your system might not support 'cron'" msgstr "" -"gặp lá»—i khi chạy “crontab -lâ€; hệ thống của bạn có thể không há»— trợ “cronâ€" +"gặp lá»—i khi chạy 'crontab -l'; hệ thống của bạn có thể không há»— trợ 'cron'" -msgid "failed to run 'crontab'; your system might not support 'cron'" -msgstr "gặp lá»—i khi chạy “crontabâ€; hiển thị của bạn có lẽ không há»— trợ “cronâ€" +msgid "failed to create crontab temporary file" +msgstr "không thể tạo táºp tin tạm thá»i crontab" -msgid "failed to open stdin of 'crontab'" -msgstr "gặp lá»—i khi mở đầu và o tiêu chuẩn của “crontabâ€" +msgid "failed to open temporary file" +msgstr "không thể mở táºp tin tạm thá»i" -msgid "'crontab' died" -msgstr "“crontab†đã chết" - -msgid "failed to start systemctl" -msgstr "gặp lá»—i khi khởi chạy systemctl" +msgid "failed to run 'crontab'; your system might not support 'cron'" +msgstr "gặp lá»—i khi chạy 'crontab'; hệ thống của bạn có lẽ không há»— trợ 'cron'" -msgid "failed to run systemctl" -msgstr "gặp lá»—i khi chạy systemctl" +msgid "'crontab' died" +msgstr "'crontab' đã chết" #, c-format msgid "failed to delete '%s'" -msgstr "gặp lá»—i khi xóa “%sâ€" +msgstr "gặp lá»—i khi xóa '%s'" #, c-format msgid "failed to flush '%s'" -msgstr "gặp lá»—i khi đẩy dữ liệu “%s†lên Ä‘Ä©a" +msgstr "gặp lá»—i khi đẩy dữ liệu '%s' lên Ä‘Ä©a" + +msgid "failed to start systemctl" +msgstr "gặp lá»—i khi khởi chạy systemctl" + +msgid "failed to run systemctl" +msgstr "gặp lá»—i khi chạy systemctl" #, c-format msgid "unrecognized --scheduler argument '%s'" -msgstr "đối số --scheduler không được thừa nháºn “%sâ€" +msgstr "đối số --scheduler không được thừa nháºn '%s'" msgid "neither systemd timers nor crontab are available" msgstr "hoặc là bá»™ láºp lịch systemd hoặc là crontab không sẵn có" @@ -6554,18 +6692,17 @@ msgstr "bá»™ lên lịch" msgid "scheduler to trigger git maintenance run" msgstr "bá»™ lên lịch để kÃch hoạt chạy chÆ°Æ¡ng trình bảo trì git" +msgid "failed to set up maintenance schedule" +msgstr "gặp lá»—i khi lên lịch bảo trì" + msgid "failed to add repo to global config" msgstr "gặp lá»—i khi thêm cấu hình toà n cục" msgid "git maintenance <subcommand> [<options>]" msgstr "git maintenance run <lệnh_con> [<các tùy chá»n>]" -#, c-format -msgid "invalid subcommand: %s" -msgstr "lện con không hợp lệ: %s" - msgid "git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]" -msgstr "git grep [<các tùy chá»n>] [-e] <mẫu> [<rev>…] [[--] </Ä‘Æ°á»ng/dẫn>…]" +msgstr "git grep [<các tùy chá»n>] [-e] <mẫu> [<rev>...] [[--] </Ä‘Æ°á»ng/dẫn>...]" #, c-format msgid "grep: failed to create thread: %s" @@ -6585,8 +6722,8 @@ msgid "no threads support, ignoring %s" msgstr "không há»— trợ Ä‘a tuyến, bá» qua %s" #, c-format -msgid "unable to read tree (%s)" -msgstr "không thể Ä‘á»c cây (%s)" +msgid "unable to read tree %s" +msgstr "không thể Ä‘á»c cây %s" #, c-format msgid "unable to grep from object of type %s" @@ -6594,10 +6731,10 @@ msgstr "không thể thá»±c hiện lệnh grep (lá»c tìm) từ đối tượng #, c-format msgid "switch `%c' expects a numerical value" -msgstr "chuyển đến “%c†cần má»™t giá trị bằng số" +msgstr "chuyển đến '%c' cần má»™t giá trị bằng số" msgid "search in index instead of in the work tree" -msgstr "tìm trong bảng mục lục thay vì trong cây là m việc" +msgstr "tìm trong chỉ mục thay vì trong cây là m việc" msgid "find in contents not managed by git" msgstr "tìm trong ná»™i dung không được quản lý bởi git" @@ -6606,7 +6743,7 @@ msgid "search in both tracked and untracked files" msgstr "tìm kiếm các táºp tin được và chÆ°a được theo dõi dấu vết" msgid "ignore files specified via '.gitignore'" -msgstr "các táºp tin bị bá» qua được chỉ định thông qua “.gitignoreâ€" +msgstr "các táºp tin bị bá» qua được chỉ định thông qua '.gitignore'" msgid "recursively search in each submodule" msgstr "tìm kiếm đệ quy trong từng mô-Ä‘un-con" @@ -6627,16 +6764,16 @@ msgid "don't match patterns in binary files" msgstr "không khá»›p mẫu trong các táºp tin nhị phân" msgid "process binary files with textconv filters" -msgstr "xá» lý táºp tin nhị phân vá»›i các bá»™ lá»c “textconvâ€" +msgstr "xá» lý táºp tin nhị phân vá»›i các bá»™ lá»c 'textconv'" msgid "search in subdirectories (default)" msgstr "tìm kiếm trong thÆ° mục con (mặc định)" -msgid "descend at most <depth> levels" -msgstr "hạ xuống Ãt nhất là mức <sâu>" +msgid "descend at most <n> levels" +msgstr "hạ xuống tối Ä‘a <n> mức" msgid "use extended POSIX regular expressions" -msgstr "dùng biểu thức chÃnh qui POSIX có mở rá»™ng" +msgstr "dùng biểu thức chÃnh quy POSIX có mở rá»™ng" msgid "use basic POSIX regular expressions (default)" msgstr "sá» dụng biểu thức chÃnh quy kiểu POSIX (mặc định)" @@ -6684,7 +6821,7 @@ msgid "highlight matches" msgstr "tô sáng phần khá»›p mẫu" msgid "print empty line between matches from different files" -msgstr "hiển thị dòng trống giữa các lần khá»›p từ các táºp tin khác biệt" +msgstr "hiển thị dòng trống giữa các lần khá»›p từ các táºp tin khác nhau" msgid "show filename only once above matches from same file" msgstr "" @@ -6735,6 +6872,9 @@ msgstr "hiển thị các táºp tin khá»›p trong trang giấy" 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)" +msgid "maximum number of results per file" +msgstr "số lượng kết quả tối Ä‘a trên má»—i táºp tin" + msgid "no pattern given" msgstr "chÆ°a chỉ ra mẫu" @@ -6768,11 +6908,14 @@ msgid "both --cached and trees are given" msgstr "cả hai --cached và các cây phải được chỉ ra" msgid "" -"git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] " -"[--] <file>..." +"git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n" +" [--stdin [--literally]] [--] <file>..." msgstr "" -"git hash-object [-t <kiểu>] [-w] [--path=<táºp-tin> | --no-filters] [--stdin] " -"[--] <táºp-tin>…" +"git hash-object [-t <kiểu>] [-w] [--path=<táºp-tin> | --no-filters]\n" +" [--stdin [--literally]] [--] <táºp-tin>..." + +msgid "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]" +msgstr "git hash-object [-t <kiểu>] [-w] --stdin-paths [--no-filters] " msgid "object type" msgstr "kiểu đối tượng" @@ -6781,14 +6924,14 @@ msgid "write the object into the object database" msgstr "ghi đối tượng và o dữ liệu đối tượng" msgid "read the object from stdin" -msgstr "Ä‘á»c đối tượng từ đầu và o tiêu chuẩn stdin" +msgstr "Ä‘á»c đối tượng từ stdin" msgid "store file as is without filters" msgstr "lÆ°u các táºp tin mà nó không có các bá»™ lá»c" msgid "" "just hash any random garbage to create corrupt objects for debugging Git" -msgstr "chỉ cần băm rác ngẫu nhiên để tạo má»™t đối tượng há»ng để mà gỡ lá»—i Git" +msgstr "chỉ cần băm rác ngẫu nhiên để tạo má»™t đối tượng há»ng để gỡ lá»—i Git" msgid "process file as it were from this path" msgstr "xá» lý táºp tin nhÆ° là nó Ä‘ang ở thÆ° mục nà y" @@ -6820,49 +6963,55 @@ msgstr "hiển thị mô tả lệnh" msgid "print list of useful guides" msgstr "hiển thị danh sách các hÆ°á»›ng dẫn hữu dụng" +msgid "print list of user-facing repository, command and file interfaces" +msgstr "hiển thị các giao diện cho ngÆ°á»i dùng" + +msgid "print list of file formats, protocols and other developer interfaces" +msgstr "hiển thị các giao diện cho láºp trình viên" + msgid "print all configuration variable names" msgstr "in ra tất cả các tên biến cấu hình" -msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>]" -msgstr "git help [[-i|--info] [-m|--man] [-w|--web]] [<lệnh>]" +msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]" +msgstr "git help [[-i|--info] [-m|--man] [-w|--web]] [<lệnh>|<tà i liệu>]" #, c-format msgid "unrecognized help format '%s'" -msgstr "không nháºn ra định dạng trợ giúp “%sâ€" +msgstr "không nháºn ra định dạng trợ giúp '%s'" msgid "Failed to start emacsclient." msgstr "Gặp lá»—i khi khởi chạy emacsclient." msgid "Failed to parse emacsclient version." -msgstr "Gặp lá»—i khi phân tÃch phiên bản emacsclient." +msgstr "Gặp lá»—i khi Ä‘á»c phiên bản emacsclient." #, c-format msgid "emacsclient version '%d' too old (< 22)." -msgstr "phiên bản của emacsclient “%d†quá cÅ© (< 22)." +msgstr "phiên bản của emacsclient '%d' quá cÅ© (< 22)." #, c-format msgid "failed to exec '%s'" -msgstr "gặp lá»—i khi thá»±c thi “%sâ€" +msgstr "gặp lá»—i khi thá»±c thi '%s'" #, c-format msgid "" "'%s': path for unsupported man viewer.\n" "Please consider using 'man.<tool>.cmd' instead." msgstr "" -"“%sâ€: Ä‘Æ°á»ng dẫn không há»— trợ bá»™ trình chiếu man.\n" -"Hãy cân nhắc đến việc sá» dụng “man.<tool>.cmd†để thay thế." +"'%s': Ä‘Æ°á»ng dẫn không há»— trợ bá»™ trình chiếu man.\n" +"Hãy cân nhắc đến việc sá» dụng 'man.<tool>.cmd' để thay thế." #, c-format msgid "" "'%s': cmd for supported man viewer.\n" "Please consider using 'man.<tool>.path' instead." msgstr "" -"“%sâ€: cmd (lệnh) há»— trợ bá»™ trình chiếu man.\n" -"Hãy cân nhắc đến việc sá» dụng “man.<tool>.path†để thay thế." +"'%s': cmd (lệnh) há»— trợ bá»™ trình chiếu man.\n" +"Hãy cân nhắc đến việc sá» dụng 'man.<tool>.path' để thay thế." #, c-format msgid "'%s': unknown man viewer." -msgstr "“%sâ€: không rõ chÆ°Æ¡ng trình xem man." +msgstr "'%s': không rõ chÆ°Æ¡ng trình xem man." msgid "no man viewer handled the request" msgstr "không có trình xem trợ giúp dạng manpage tiếp hợp vá»›i yêu cầu" @@ -6872,7 +7021,7 @@ msgstr "không có trình xem trợ giúp dạng info tiếp hợp vá»›i yêu cá #, c-format msgid "'%s' is aliased to '%s'" -msgstr "“%s†được đặt bà danh thà nh “%sâ€" +msgstr "'%s' được đặt bà danh thà nh '%s'" #, c-format msgid "bad alias.%s string: %s" @@ -6893,13 +7042,20 @@ msgid "usage: %s%s" msgstr "cách dùng: %s%s" msgid "'git help config' for more information" -msgstr "Chạy lệnh “git help config†để có thêm thông tin" +msgstr "Chạy lệnh 'git help config' để có thêm thông tin" -msgid "git hook run [--ignore-missing] <hook-name> [-- <hook-args>]" -msgstr "git hook run [--ignore-missing] <tên-móc> [-- <các tham số cho móc>]" +msgid "" +"git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-" +"args>]" +msgstr "" +"git hook run [--ignore-missing] [--to-stdin=</Ä‘Æ°á»ng/dẫn/>] <tên-móc> [-- " +"<các tham số cho móc>]" msgid "silently ignore missing requested <hook-name>" -msgstr "bá» qua âm thầm các <hook-name> đã yêu cầu còn thiếu" +msgstr "âm thầm bá» qua các <hook-name> đã yêu cầu còn thiếu" + +msgid "file to read into hooks' stdin" +msgstr "táºp tin để Ä‘Æ°a và o stdin của hook" #, c-format msgid "object type mismatch at %s" @@ -6911,7 +7067,7 @@ msgstr "không thể lấy vỠđối tượng cần %s" #, c-format msgid "object %s: expected type %s, found %s" -msgstr "đối tượng %s: cần kiểu %s nhÆ°ng lại nháºn được %s" +msgstr "đối tượng %s: cần kiểu %s nhÆ°ng lại có %s" #, c-format msgid "cannot fill %d byte" @@ -6947,13 +7103,13 @@ msgstr "gói có đối tượng sai tại khoảng bù %<PRIuMAX>: %s" #, c-format msgid "inflate returned %d" -msgstr "xả nén trả vá» %d" +msgstr "giải nén trả vá» %d" msgid "offset value overflow for delta base object" msgstr "trà n giá trị khoảng bù cho đối tượng delta cÆ¡ sở" msgid "delta base offset is out of bound" -msgstr "khoảng bù cÆ¡ sở cho delta nằm ngoà i phạm vi" +msgstr "khoảng bù cÆ¡ sở cho delta nằm ngoà i biên" #, c-format msgid "unknown object type %d" @@ -6968,17 +7124,13 @@ msgid_plural "premature end of pack file, %<PRIuMAX> bytes missing" msgstr[0] "táºp tin gói bị kết thúc sá»›m, thiếu %<PRIuMAX> byte" msgid "serious inflate inconsistency" -msgstr "sá»± mâu thuẫn xả nén nghiêm trá»ng" +msgstr "sá»± mâu thuẫn giải nén nghiêm trá»ng" #, c-format msgid "SHA1 COLLISION FOUND WITH %s !" msgstr "Sá»° VA CHẠM SHA1 Äà XẢY RA VỚI %s!" #, c-format -msgid "unable to read %s" -msgstr "không thể Ä‘á»c %s" - -#, c-format msgid "cannot read existing object info %s" msgstr "không thể Ä‘á»c thông tin đối tượng sẵn có %s" @@ -7004,13 +7156,13 @@ msgid "Receiving objects" msgstr "Äang nháºn vá» các đối tượng" msgid "Indexing objects" -msgstr "Các đối tượng bảng mục lục" +msgstr "Các đối tượng chỉ mục" msgid "pack is corrupted (SHA1 mismatch)" msgstr "gói bị sai há»ng (SHA1 không khá»›p)" msgid "cannot fstat packfile" -msgstr "không thể lấy thông tin thống kê packfile" +msgstr "không thể fstat packfile" msgid "pack has junk at the end" msgstr "pack có phần thừa ở cuối" @@ -7035,7 +7187,7 @@ msgstr[0] "đầy đủ vá»›i %d đối tượng ná»™i bá»™" #, c-format msgid "Unexpected tail checksum for %s (disk corruption?)" -msgstr "Gặp tổng kiểm tra tail không cần cho %s (Ä‘Ä©a há»ng?)" +msgstr "Gặp tổng kiểm tra tail bất thÆ°á»ng cho %s (Ä‘Ä©a há»ng?)" #, c-format msgid "pack has %d unresolved delta" @@ -7044,7 +7196,7 @@ msgstr[0] "gói có %d delta chÆ°a được giải quyết" #, c-format msgid "unable to deflate appended object (%d)" -msgstr "không thể xả nén đối tượng nối thêm (%d)" +msgstr "không thể giải nén đối tượng nối thêm (%d)" #, c-format msgid "local object %s is corrupt" @@ -7052,19 +7204,19 @@ msgstr "đối tượng ná»™i bá»™ %s bị há»ng" #, c-format msgid "packfile name '%s' does not end with '.%s'" -msgstr "tên táºp tin táºp tin gói “%s†không được kết thúc “.%sâ€" +msgstr "tên táºp tin táºp tin gói '%s' không được kết thúc '.%s'" #, c-format msgid "cannot write %s file '%s'" -msgstr "không thể ghi %s táºp tin “%sâ€" +msgstr "không thể ghi %s táºp tin '%s'" #, c-format msgid "cannot close written %s file '%s'" -msgstr "không thể đóng táºp tin được ghi %s “%sâ€" +msgstr "không thể đóng táºp tin được ghi %s '%s'" #, c-format msgid "unable to rename temporary '*.%s' file to '%s'" -msgstr "không thể đổi tên táºp tin tạm thá»i “*.%s†thà nh “%sâ€" +msgstr "không thể đổi tên táºp tin tạm thá»i '*.%s' thà nh '%s'" msgid "error while closing pack file" msgstr "gặp lá»—i trong khi đóng táºp tin gói" @@ -7075,11 +7227,11 @@ msgstr "sai pack.indexVersion=%<PRIu32>" #, c-format msgid "Cannot open existing pack file '%s'" -msgstr "Không thể mở táºp tin gói đã sẵn có “%sâ€" +msgstr "Không thể mở táºp tin gói đã sẵn có '%s'" #, c-format msgid "Cannot open existing pack idx file for '%s'" -msgstr "Không thể mở táºp tin idx của gói cho “%sâ€" +msgstr "Không thể mở táºp tin idx của gói cho '%s'" #, c-format msgid "non delta: %d object" @@ -7089,10 +7241,10 @@ msgstr[0] "không delta: %d đối tượng" #, c-format msgid "chain length = %d: %lu object" msgid_plural "chain length = %d: %lu objects" -msgstr[0] "chiá»u dà i xÃch = %d: %lu đối tượng" +msgstr[0] "chiá»u dà i chuá»—i = %d: %lu đối tượng" msgid "Cannot come back to cwd" -msgstr "Không thể quay lại cwd" +msgstr "Không thể quay lại thÆ° mục hiện hà nh" #, c-format msgid "bad %s" @@ -7100,7 +7252,7 @@ msgstr "%s sai" #, c-format msgid "unknown hash algorithm '%s'" -msgstr "không hiểu thuáºt toán băm dữ liệu “%sâ€" +msgstr "không hiểu thuáºt toán băm dữ liệu '%s'" msgid "--stdin requires a git repository" msgstr "--stdin cần má»™t kho git" @@ -7111,83 +7263,18 @@ msgstr "dùng tùy chá»n --verify mà không Ä‘Æ°a ra tên packfile" msgid "fsck error in pack objects" msgstr "lá»—i fsck trong các đối tượng gói" -#, c-format -msgid "cannot stat template '%s'" -msgstr "không thể lấy thông tin thống kê vá» mẫu “%sâ€" - -#, c-format -msgid "cannot opendir '%s'" -msgstr "không thể opendir() “%sâ€" - -#, c-format -msgid "cannot readlink '%s'" -msgstr "không thể readlink “%sâ€" - -#, c-format -msgid "cannot symlink '%s' '%s'" -msgstr "không thể tạo liên kết má»m (symlink) “%s†“%sâ€" - -#, c-format -msgid "cannot copy '%s' to '%s'" -msgstr "không thể sao chép “%s†sang “%sâ€" - -#, c-format -msgid "ignoring template %s" -msgstr "Ä‘ang lá» Ä‘i mẫu “%sâ€" - -#, c-format -msgid "templates not found in %s" -msgstr "các mẫu không được tìm thấy trong %s" - -#, c-format -msgid "not copying templates from '%s': %s" -msgstr "không sao chép các mẫu từ “%sâ€: %s" - -#, c-format -msgid "invalid initial branch name: '%s'" -msgstr "tên nhánh khởi tạo không hợp lệ: “%sâ€" - -#, c-format -msgid "unable to handle file type %d" -msgstr "không thể xá» lý (handle) táºp tin kiểu %d" - -#, c-format -msgid "unable to move %s to %s" -msgstr "không di chuyển được %s và o %s" - -msgid "attempt to reinitialize repository with different hash" -msgstr "cố để khởi tạo lại má»™t kho vá»›i kiểu băm dữ liệu khác" - -#, c-format -msgid "%s already exists" -msgstr "%s đã có từ trÆ°á»›c rồi" - -#, c-format -msgid "re-init: ignored --initial-branch=%s" -msgstr "re-init: --initial-branch=%s bị bá» qua" - -#, c-format -msgid "Reinitialized existing shared Git repository in %s%s\n" -msgstr "Äã khởi tạo lại kho Git chia sẻ sẵn có trong %s%s\n" - -#, c-format -msgid "Reinitialized existing Git repository in %s%s\n" -msgstr "Äã khởi tạo lại kho Git sẵn có trong %s%s\n" - -#, c-format -msgid "Initialized empty shared Git repository in %s%s\n" -msgstr "Äã khởi tạo lại kho Git chia sẻ trống rá»—ng sẵn có trong %s%s\n" - -#, c-format -msgid "Initialized empty Git repository in %s%s\n" -msgstr "Äã khởi tạo lại kho Git trống rá»—ng sẵn có trong %s%s\n" - msgid "" -"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--" -"shared[=<permissions>]] [<directory>]" +"git init [-q | --quiet] [--bare] [--template=<template-directory>]\n" +" [--separate-git-dir <git-dir>] [--object-format=<format>]\n" +" [--ref-format=<format>]\n" +" [-b <branch-name> | --initial-branch=<branch-name>]\n" +" [--shared[=<permissions>]] [<directory>]" msgstr "" -"git init [-q | --quiet] [--bare] [--template=<thÆ°-mục-tạm>] [--shared[=<các-" -"quyá»n>]] [thÆ°-mục]" +"git init [-q | --quiet] [--bare] [--template=<thÆ° mục mẫu>]\n" +" [--separate-git-dir <thÆ° mục git>] [--object-format=<định dạng>]\n" +" [--ref-format=<định dạng>]\n" +" [-b <tên nhánh> | --initial-branch=<tên nhánh>]\n" +" [--shared[=<quyá»n hạn>]] [<thÆ° mục>]" msgid "permissions" msgstr "các quyá»n" @@ -7222,23 +7309,54 @@ msgstr "" #, c-format msgid "Cannot access work tree '%s'" -msgstr "Không thể truy cáºp cây (tree) là m việc “%sâ€" +msgstr "Không thể truy cáºp cây là m việc '%s'" msgid "--separate-git-dir incompatible with bare repository" -msgstr "--separate-git-dir xung khắc vá»›i kho thuần" +msgstr "--separate-git-dir không tÆ°Æ¡ng thÃch vá»›i kho bare" msgid "" -"git interpret-trailers [--in-place] [--trim-empty] [(--trailer " -"<token>[(=|:)<value>])...] [<file>...]" +"git interpret-trailers [--in-place] [--trim-empty]\n" +" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n" +" [--parse] [<file>...]" msgstr "" -"git interpret-trailers [--in-place] [--trim-empty] [(--trailer " -"<thẻ>[(=|:)<giá-trị>])…] [<táºp-tin>…]" +"git interpret-trailers [--in-place] [--trim-empty]\n" +" [(--trailer (<key>|<key-alias>)[(=|:)<giá-trị>])...]\n" +" [--parse] [<táºp-tin>...]" + +#, c-format +msgid "could not stat %s" +msgstr "không thể stat %s" + +#, c-format +msgid "file %s is not a regular file" +msgstr "\"%s\" không phải là táºp tin bình thÆ°á»ng" + +#, c-format +msgid "file %s is not writable by user" +msgstr "táºp tin %s ngÆ°á»i dùng không thể ghi được" + +msgid "could not open temporary file" +msgstr "không thể tạo táºp tin tạm thá»i" + +#, c-format +msgid "could not read input file '%s'" +msgstr "không Ä‘á»c được táºp tin đầu và o '%s'" + +msgid "could not read from stdin" +msgstr "không thể Ä‘á»c từ stdin" + +#, c-format +msgid "could not rename temporary file to %s" +msgstr "không thể đổi tên táºp tin tạm thá»i thà nh %s" msgid "edit files in place" msgstr "sá»a các táºp tin tại chá»—" msgid "trim empty trailers" -msgstr "bá»™ dò vết cắt bá» phần trống rá»—ng" +msgstr "cắt bá» phần trống thừa ở Ä‘uôi" + +msgid "placement" +msgstr "vị trÃ" msgid "where to place the new trailer" msgstr "đặt phần Ä‘uôi má»›i ở đâu" @@ -7252,20 +7370,20 @@ msgstr "thao tác khi thiếu phần Ä‘uôi" msgid "output only the trailers" msgstr "chỉ xuất phần Ä‘uôi" -msgid "do not apply config rules" -msgstr "đừng áp dụng các quy tắc cấu hình" +msgid "do not apply trailer.* configuration variables" +msgstr "không áp dụng các biến cấu hình trailer.*" -msgid "join whitespace-continued values" -msgstr "nối các giá trị khoảng-trắng-liên-tiếp" +msgid "reformat multiline trailer values as single-line values" +msgstr "định dạng lại giá trị Ä‘uôi thà nh giá trị trên má»™t dòng" -msgid "set parsing options" -msgstr "đặt các tùy chá»n phân tÃch cú pháp" +msgid "alias for --only-trailers --only-input --unfold" +msgstr "viết tắt cho --only-trailers --only-input --unfold" -msgid "do not treat --- specially" -msgstr "không coi --- là đặc biệt" +msgid "do not treat \"---\" as the end of input" +msgstr "không coi \"---\" là kết thúc đầu và o" msgid "trailer(s) to add" -msgstr "bá»™ dò vết cần thêm" +msgstr "phần Ä‘uôi cần thêm" msgid "--trailer with --only-input does not make sense" msgstr "--trailer cùng vá»›i --only-input không hợp lý" @@ -7274,10 +7392,10 @@ msgid "no input file given for in-place editing" msgstr "không Ä‘Æ°a ra táºp tin đầu và o để sá»a tại-chá»—" msgid "git log [<options>] [<revision-range>] [[--] <path>...]" -msgstr "git log [<các tùy chá»n>] [<vùng-xem-xét>] [[--] </Ä‘Æ°á»ng/dẫn>…]" +msgstr "git log [<các tùy chá»n>] [<vùng-xem-xét>] [[--] </Ä‘Æ°á»ng/dẫn>...]" msgid "git show [<options>] <object>..." -msgstr "git show [<các tùy chá»n>] <đối-tượng>…" +msgstr "git show [<các tùy chá»n>] <đối-tượng>..." #, c-format msgid "invalid --decorate option: %s" @@ -7289,8 +7407,8 @@ msgstr "chặn má»i kết xuất từ diff" msgid "show source" msgstr "hiển thị mã nguồn" -msgid "use mail map file" -msgstr "sá» dụng táºp tin ánh xạ thÆ°" +msgid "clear all previously-defined decoration filters" +msgstr "xoá các bá»™ lá»c decorate đã định nghÄ©a từ trÆ°á»›c" msgid "only decorate refs that match <pattern>" msgstr "chỉ tô sáng các tham chiếu khá»›p vá»›i <mẫu>" @@ -7299,21 +7417,21 @@ msgid "do not decorate refs that match <pattern>" msgstr "không tô sáng các tham chiếu khá»›p vá»›i <mẫu>" msgid "decorate options" -msgstr "các tùy chá»n trang trÃ" +msgstr "các tùy chá»n decorate" msgid "" "trace the evolution of line range <start>,<end> or function :<funcname> in " "<file>" msgstr "" -"theo dõi sá»± tiến hóa của phạm vi <start><end> dòng, hoặc chức năng:" -"<funcname> trong <file>" +"theo vết sá»± tiến hóa của phạm vi dòng <start>,<end>, hoặc hà m :<tên hà m> " +"trong <táºp tin>" #, c-format msgid "unrecognized argument: %s" msgstr "đối số không được thừa nháºn: %s" msgid "-L<range>:<file> cannot be used with pathspec" -msgstr "-L<vùng>:<táºp_tin> không thể được sá» dụng vá»›i đặc tả Ä‘Æ°á»ng dẫn" +msgstr "-L<vùng>:<táºp tin> không thể được sá» dụng vá»›i đặc tả Ä‘Æ°á»ng dẫn" #, c-format msgid "Final output: %d %s\n" @@ -7343,7 +7461,7 @@ msgstr "format.headers không có giá trị cụ thể" #, c-format msgid "cannot open patch file %s" -msgstr "không thể mở táºp tin miếng vá: %s" +msgstr "không thể mở táºp tin bản vá: %s" msgid "need exactly one range" msgstr "cần chÃnh xác má»™t vùng" @@ -7351,8 +7469,12 @@ msgstr "cần chÃnh xác má»™t vùng" msgid "not a range" msgstr "không phải là má»™t vùng" +#, c-format +msgid "unable to read branch description file '%s'" +msgstr "không thể Ä‘á»c táºp tin cấu hình nhánh '%s'" + msgid "cover letter needs email format" -msgstr "“cover letter†cần cho định dạng thÆ°" +msgstr "cover letter cần định dạng thÆ°" msgid "failed to create cover-letter file" msgstr "gặp lá»—i khi tạo các táºp tin cover-letter" @@ -7373,10 +7495,10 @@ msgstr "không hiểu lần chuyển giao %s" #, c-format msgid "failed to resolve '%s' as a valid ref" -msgstr "gặp lá»—i khi phân giải “%s†nhÆ° là má»™t tham chiếu hợp lệ" +msgstr "gặp lá»—i khi phân giải '%s' thà nh má»™t tham chiếu hợp lệ" msgid "could not find exact merge base" -msgstr "không tìm thấy ná»n hòa trá»™n chÃnh xác" +msgstr "không tìm thấy gốc hòa trá»™n chÃnh xác" msgid "" "failed to get upstream, if you want to record base commit automatically,\n" @@ -7389,7 +7511,7 @@ msgstr "" "\"--base=<base-commit-id>\" má»™t cách thủ công" msgid "failed to find exact merge base" -msgstr "gặp lá»—i khi tìm ná»n hòa trá»™n chÃnh xác" +msgstr "gặp lá»—i khi tìm gốc hòa trá»™n chÃnh xác" msgid "base commit should be the ancestor of revision list" msgstr "lần chuyển giao ná»n không là tổ tiên của danh sách Ä‘iểm xét duyệt" @@ -7398,7 +7520,7 @@ msgid "base commit shouldn't be in revision list" msgstr "lần chuyển giao ná»n không được trong danh sách Ä‘iểm xét duyệt" msgid "cannot get patch id" -msgstr "không thể lấy mã miếng vá" +msgstr "không thể lấy mã bản vá" msgid "failed to infer range-diff origin of current series" msgstr "" @@ -7406,70 +7528,73 @@ msgstr "" #, c-format msgid "using '%s' as range-diff origin of current series" -msgstr "dùng “%s†nhÆ° là gốc range-diff của sê-ri hiện tại" +msgstr "dùng '%s' là m gốc range-diff của sê-ri hiện tại" msgid "use [PATCH n/m] even with a single patch" -msgstr "dùng [PATCH n/m] ngay cả vá»›i miếng vá Ä‘Æ¡n" +msgstr "dùng [PATCH n/m] ngay cả vá»›i bản vá Ä‘Æ¡n" msgid "use [PATCH] even with multiple patches" -msgstr "dùng [VÃ] ngay cả vá»›i các miếng vá phức tạp" +msgstr "dùng [PATCH] ngay cả vá»›i các bản vá nhiá»u phần" msgid "print patches to standard out" -msgstr "hiển thị miếng vá ra đầu ra chuẩn" +msgstr "hiển thị bản vá ra stdout" msgid "generate a cover letter" msgstr "tạo bì thÆ°" msgid "use simple number sequence for output file names" -msgstr "sá» dụng chá»—i dãy số dạng Ä‘Æ¡n giản cho tên táºp-tin xuất ra" +msgstr "sá» dụng chuá»—i dãy số dạng Ä‘Æ¡n giản cho tên táºp-tin xuất ra" msgid "sfx" -msgstr "sfx" +msgstr "háºu-tố" msgid "use <sfx> instead of '.patch'" -msgstr "sá» dụng <sfx> thay cho “.patchâ€" +msgstr "sá» dụng <háºu-tố> thay cho '.patch'" msgid "start numbering patches at <n> instead of 1" -msgstr "bắt đầu đánh số miếng vá từ <n> thay vì 1" +msgstr "bắt đầu đánh số bản vá từ <n> thay vì 1" msgid "reroll-count" -msgstr "đếm reroll" +msgstr "số-lần-chạy-lại" msgid "mark the series as Nth re-roll" -msgstr "đánh dấu chuá»—i nối tiếp dạng thứ-N re-roll" +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 [Và RFC] thay cho [VÃ]" +msgstr "dùng [RFC PATCH] thay cho [PATCH]" msgid "cover-from-description-mode" msgstr "cover-from-description-mode" msgid "generate parts of a cover letter based on a branch's description" -msgstr "tạo ra các phần của má»™t lá thÆ° bao gồm dá»±a trên mô tả của nhánh" +msgstr "tạo ra phần bìa thÆ° dá»±a trên mô tả của nhánh" + +msgid "use branch description from file" +msgstr "dùng mô tả nhánh từ táºp tin" msgid "use [<prefix>] instead of [PATCH]" -msgstr "dùng [<tiá»n-tố>] thay cho [VÃ]" +msgstr "dùng [<tiá»n-tố>] thay cho [PATCH]" msgid "store resulting files in <dir>" -msgstr "lÆ°u các táºp tin kết quả trong <t.mục>" +msgstr "lÆ°u các táºp tin kết quả trong <thÆ° mục>" msgid "don't strip/add [PATCH]" -msgstr "không strip/add [VÃ]" +msgstr "không loại bá»/thêm [PATCH]" msgid "don't output binary diffs" -msgstr "không kết xuất diff (những khác biệt) nhị phân" +msgstr "không kết 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" msgid "don't include a patch matching a commit upstream" -msgstr "không bao gồm miếng vá khá»›p vá»›i má»™t lần chuyển giao thượng nguồn" +msgstr "không bao gồm bản vá khá»›p vá»›i má»™t lần chuyển giao thượng nguồn" msgid "show patch format instead of default (patch + stat)" -msgstr "hiển thị định dạng miếng vá thay vì mặc định (miếng vá + thống kê)" +msgstr "hiển thị định dạng bản vá thay vì mặc định (bản vá + thống kê)" msgid "Messaging" msgstr "Lá»i nhắn" @@ -7490,11 +7615,10 @@ msgid "add Cc: header" msgstr "thêm Cc: đầu Ä‘á» thÆ°" msgid "ident" -msgstr "thụt lá»" +msgstr "ident" msgid "set From address to <ident> (or committer ident if absent)" -msgstr "" -"đặt “Äịa chỉ gá»i†thà nh <thụ lá»> (hoặc thụt lá» ngÆ°á»i commit nếu bá» quên)" +msgstr "đặt 'Äịa chỉ gá»i' thà nh <ident> (hoặc ngÆ°á»i commit nếu bá» quên)" msgid "message-id" msgstr "message-id" @@ -7506,13 +7630,13 @@ msgid "boundary" msgstr "ranh giá»›i" msgid "attach the patch" -msgstr "Ä‘Ãnh kèm miếng vá" +msgstr "Ä‘Ãnh kèm bản vá" msgid "inline the patch" -msgstr "dùng miếng vá là m ná»™i dung" +msgstr "dùng bản vá là m ná»™i dung" msgid "enable message threading, styles: shallow, deep" -msgstr "cho phép luồng lá»i nhắn, kiểu: “shallowâ€, “deepâ€" +msgstr "cho phép luồng lá»i nhắn, kiểu: 'shallow', 'deep'" msgid "signature" msgstr "chữ ký" @@ -7524,28 +7648,31 @@ msgid "base-commit" msgstr "lần_chuyển_giao_ná»n" msgid "add prerequisite tree info to the patch series" -msgstr "add trÆ°á»›c hết đòi há»i thông tin cây tá»›i sê-ri miếng vá" +msgstr "add trÆ°á»›c hết đòi há»i thông tin cây tá»›i sê-ri bản vá" msgid "add a signature from a file" msgstr "thêm chữ ký từ má»™t táºp tin" msgid "don't print the patch filenames" -msgstr "không hiển thị các tên táºp tin của miếng vá" +msgstr "không hiển thị các tên táºp tin của bản vá" msgid "show progress while generating patches" -msgstr "hiển thị bá»™ Ä‘o tiến triển trong khi tạo các miếng vá" +msgstr "hiển thị bá»™ Ä‘o tiến triển trong khi tạo các bản vá" msgid "show changes against <rev> in cover letter or single patch" msgstr "" -"hiển thị các thay đổi dá»±a trên <rev> trong các chữ bao bá»c hoặc miếng vá Ä‘Æ¡n" +"hiển thị các thay đổi dá»±a trên <rev> trong các chữ bao bá»c hoặc bản vá Ä‘Æ¡n" msgid "show changes against <refspec> in cover letter or single patch" msgstr "" -"hiển thị các thay đổi dá»±a trên <refspec> trong các chữ bao bá»c hoặc miếng vá " +"hiển thị các thay đổi dá»±a trên <refspec> trong các chữ bao bá»c hoặc bản vá " "Ä‘Æ¡n" msgid "percentage by which creation is weighted" -msgstr "tá»· lệ phần trăm theo cái tạo là weighted" +msgstr "tỉ lệ phần trăm theo cái tạo là weighted" + +msgid "show in-body From: even if identical to the e-mail header" +msgstr "hiện mục From: trong phần thân kể cả khi giống vá»›i phần tiêu Ä‘á» e-mail" #, c-format msgid "invalid ident line: %s" @@ -7565,7 +7692,7 @@ msgstr "--remerge-diff không hợp lý" #, c-format msgid "could not create directory '%s'" -msgstr "không thể tạo thÆ° mục “%sâ€" +msgstr "không thể tạo thÆ° mục '%s'" msgid "--interdiff requires --cover-letter or single patch" msgstr "--interdiff cần --cover-letter hoặc vá Ä‘Æ¡n" @@ -7578,7 +7705,7 @@ msgid "Interdiff against v%d:" msgstr "Interdiff dá»±a trên v%d:" msgid "--range-diff requires --cover-letter or single patch" -msgstr "--range-diff yêu cầu --cover-letter hoặc miếng vá Ä‘Æ¡n" +msgstr "--range-diff yêu cầu --cover-letter hoặc bản vá Ä‘Æ¡n" msgid "Range-diff:" msgstr "Range-diff:" @@ -7589,10 +7716,10 @@ msgstr "Range-diff dá»±a trên v%d:" #, c-format msgid "unable to read signature file '%s'" -msgstr "không thể Ä‘á»c táºp tin chữ ký “%sâ€" +msgstr "không thể Ä‘á»c táºp tin chữ ký '%s'" msgid "Generating patches" -msgstr "Äang tạo các miếng vá" +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" @@ -7607,8 +7734,12 @@ msgstr "" "Không tìm thấy nhánh mạng được theo dõi, hãy chỉ định <thượng-nguồn> má»™t " "cách thủ công.\n" +#, c-format +msgid "could not get object info about '%s'" +msgstr "không thể lấy thông tin đối tượng vá» '%s'" + msgid "git ls-files [<options>] [<file>...]" -msgstr "git ls-files [<các tùy chá»n>] [<táºp-tin>…]" +msgstr "git ls-files [<các tùy chá»n>] [<táºp-tin>...]" msgid "separate paths with the NUL character" msgstr "các Ä‘Æ°á»ng dẫn được ngăn cách bởi ký tá»± NULL" @@ -7618,11 +7749,11 @@ msgstr "nháºn dạng các trạng thái táºp tin vá»›i thẻ" msgid "use lowercase letters for 'assume unchanged' files" msgstr "" -"dùng chữ cái viết thÆ°á»ng cho các táºp tin “assume unchanged†(giả định không " +"dùng chữ cái viết thÆ°á»ng cho các táºp tin 'assume unchanged' (giả định không " "thay đổi)" msgid "use lowercase letters for 'fsmonitor clean' files" -msgstr "dùng chữ cái viết thÆ°á»ng cho các táºp tin “fsmonitor cleanâ€" +msgstr "dùng chữ cái viết thÆ°á»ng cho các táºp tin 'fsmonitor clean'" 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)" @@ -7646,7 +7777,7 @@ 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á»" msgid "show 'other' directories' names only" -msgstr "chỉ hiển thị tên của các thÆ° mục “khácâ€" +msgstr "chỉ hiển thị tên của các thÆ° mục 'khác'" msgid "show line endings of files" msgstr "hiển thị kết thúc dòng của các táºp tin" @@ -7676,7 +7807,7 @@ 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" 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 bảng mục lục, xá» lý nó nhÆ° má»™t lá»—i" +msgstr "nếu <táºp tin> bất kỳ không ở trong chỉ mục, xá» lý nó nhÆ° má»™t lá»—i" msgid "tree-ish" msgstr "tree-ish" @@ -7692,16 +7823,23 @@ msgid "suppress duplicate entries" msgstr "chặn các mục tin trùng lặp" msgid "show sparse directories in the presence of a sparse index" -msgstr "hiển thị thÆ° mục \"sparse\" trong sá»± có mặt của mục lục \"sparse\"" +msgstr "hiển thị thÆ° mục thÆ°a trong sá»± có mặt của chỉ mục thÆ°a" + +msgid "" +"--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, " +"--eol" +msgstr "" +"--format không thể được dùng vá»›i -s, -o, -k, -t, --resolve-undo,--" +"deduplicate, --eol" msgid "" "git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n" -" [-q | --quiet] [--exit-code] [--get-url]\n" -" [--symref] [<repository> [<refs>...]]" +" [-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]\n" -" [--symref] [<kho> [<các tham chiếu>…]]" +" [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" +" [--symref] [<kho> [<mẫu>...]]" msgid "do not print remote URL" msgstr "không hiển thị URL máy chủ" @@ -7731,23 +7869,7 @@ msgid "show underlying ref in addition to the object pointed by it" msgstr "hiển thị tham chiếu nằm dÆ°á»›i để thêm và o đối tượng được chỉ bởi nó" msgid "git ls-tree [<options>] <tree-ish> [<path>...]" -msgstr "git ls-tree [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>…]" - -#, c-format -msgid "could not get object info about '%s'" -msgstr "không thể lấy thông tin đối tượng vỠ“%sâ€" - -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "định dạng ls-tree sai: phần tỠ“%s†không bắt đầu bằng “(â€" - -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "định dạng ls-tree sai: phần tỠ“%s†không bắt kết thúc bằng “)â€" - -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "định dạng ls-tree sai: %%%.*s" +msgstr "git ls-tree [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>...]" msgid "only show trees" msgstr "chỉ hiển thị các tree" @@ -7759,7 +7881,7 @@ msgid "show trees when recursing" msgstr "hiển thị cây khi đệ quy" msgid "terminate entries with NUL byte" -msgstr "chấm dứt mục tin vá»›i byte NUL" +msgstr "kết thúc mục tin vá»›i byte NUL" msgid "include object size" msgstr "gồm cả kÃch thÆ°á»›c đối tượng" @@ -7818,38 +7940,38 @@ msgid "use headers in message's body" msgstr "sá» dụng phần đầu trong ná»™i dung thÆ°" msgid "reading patches from stdin/tty..." -msgstr "Ä‘á»c các miếng vá từ đầu và o tiêu chuẩn stdin/tty..." +msgstr "Ä‘á»c các bản vá từ stdin/tty..." #, c-format msgid "empty mbox: '%s'" -msgstr "mbox trống rá»—ng: “%sâ€" +msgstr "mbox trống rá»—ng: '%s'" msgid "git merge-base [-a | --all] <commit> <commit>..." -msgstr "git merge-base [-a | --all] <lần_chuyển_giao> <lần_chuyển_giao>…" +msgstr "git merge-base [-a | --all] <lần_chuyển_giao> <lần_chuyển_giao>..." msgid "git merge-base [-a | --all] --octopus <commit>..." -msgstr "git merge-base [-a | --all] --octopus <lần_chuyển_giao>…" - -msgid "git merge-base --independent <commit>..." -msgstr "git merge-base --independent <lần_chuyển_giao>…" +msgstr "git merge-base [-a | --all] --octopus <lần_chuyển_giao>..." msgid "git merge-base --is-ancestor <commit> <commit>" msgstr "git merge-base --is-ancestor <commit> <lần_chuyển_giao>" +msgid "git merge-base --independent <commit>..." +msgstr "git merge-base --independent <lần_chuyển_giao>..." + msgid "git merge-base --fork-point <ref> [<commit>]" msgstr "git merge-base --fork-point <tham-chiếu> [<lần_chuyển_giao>]" msgid "output all common ancestors" -msgstr "xuất ra tất cả các ông bà , tổ tiên chung" +msgstr "xuất ra tất cả các ông bà tổ tiên chung" msgid "find ancestors for a single n-way merge" msgstr "tìm tổ tiên của hòa trá»™n n-way Ä‘Æ¡n" msgid "list revs not reachable from others" -msgstr "liệt kê các “rev†mà nó không thể Ä‘á»c được từ cái khác" +msgstr "liệt kê các 'rev' không thể tá»›i được từ cái còn lại" msgid "is the first one ancestor of the other?" -msgstr "là cha mẹ đầu tiên của cái khác?" +msgstr "có phải cái trÆ°á»›c là tổ tiên của cái sau?" msgid "find where <commit> forked from reflog of <ref>" msgstr "tìm xem <commit> được rẽ nhánh ở đâu từ reflog của <th.chiếu>" @@ -7861,8 +7983,18 @@ msgstr "" "git merge-file [<các tùy chá»n>] [-L <tên1> [-L <gốc> [-L <tên2>]]] <táºp-" "tin1> <táºp-tin-gốc> <táºp-tin2>" +msgid "" +"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and " +"\"histogram\"" +msgstr "" +"tùy chá»n diff-algorithm chấp nháºn \"myers\", \"minimal\", \"patience\" và " +"\"histogram\"" + msgid "send results to standard output" -msgstr "gá»i kết quả và o đầu ra tiêu chuẩn" +msgstr "gá»i kết quả ra stdout" + +msgid "use object IDs instead of filenames" +msgstr "dùng ID đối tượng thay vì tên táºp tin" msgid "use a diff3 based merge" msgstr "dùng kiểu hòa dá»±a trên diff3" @@ -7871,16 +8003,22 @@ 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 "để tránh xung Ä‘á»™t, sá» dụng phiên bản của chúng ta" +msgstr "nếu xung Ä‘á»™t, sá» dụng phiên bản của ta" msgid "for conflicts, use their version" -msgstr "để tránh xung Ä‘á»™t, sá» dụng phiên bản của há»" +msgstr "nếu xung Ä‘á»™t, sá» dụng phiên bản của há»" msgid "for conflicts, use a union version" -msgstr "để tránh xung Ä‘á»™t, sá» dụng phiên bản kết hợp" +msgstr "nếu xung Ä‘á»™t, sá» dụng phiên bản kết hợp" + +msgid "<algorithm>" +msgstr "<thuáºt toán>" + +msgid "choose a diff algorithm" +msgstr "chá»n thuáºt toán diff" msgid "for conflicts, use this marker size" -msgstr "để tránh xung Ä‘á»™t, hãy sá» dụng kÃch thÆ°á»›c bá»™ tạo nà y" +msgstr "nếu xung Ä‘á»™t, hãy sá» dụng kÃch thÆ°á»›c bá»™ tạo nà y" msgid "do not warn about conflicts" msgstr "không cảnh báo vá» các xung Ä‘á»™t xảy ra" @@ -7889,12 +8027,19 @@ msgid "set labels for file1/orig-file/file2" msgstr "đặt nhãn cho táºp-tin-1/táºp-tin-gốc/táºp-tin-2" #, c-format +msgid "object '%s' does not exist" +msgstr "đối tượng '%s' không tồn tại" + +msgid "Could not write object file" +msgstr "Không thể ghi và o táºp tin" + +#, c-format msgid "unknown option %s" msgstr "không hiểu tùy chá»n %s" #, c-format msgid "could not parse object '%s'" -msgstr "không thể phân tÃch đối tượng “%sâ€" +msgstr "không thể Ä‘á»c đối tượng '%s'" #, c-format msgid "cannot handle more than %d base. Ignoring %s." @@ -7912,33 +8057,94 @@ msgstr "không thể phân giải tham chiếu %s" msgid "Merging %s with %s\n" msgstr "Äang hòa trá»™n %s vá»›i %s\n" +#, c-format +msgid "could not parse as tree '%s'" +msgstr "không hiểu cú pháp cây '%s'" + +msgid "not something we can merge" +msgstr "không phải là thứ gì đó mà chúng tôi có thể hòa trá»™n" + +msgid "refusing to merge unrelated histories" +msgstr "từ chối hòa trá»™n lịch sá» không liên quan" + +msgid "failure to merge" +msgstr "gặp lá»—i khi hoà trá»™n" + +msgid "git merge-tree [--write-tree] [<options>] <branch1> <branch2>" +msgstr "git merge-tree [--write-tree] [<tuỳ chá»n>] <nhánh 1> <nhánh 2>" + +msgid "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>" +msgstr "git merge-tree [--trivial-merge] <cây gốc> <nhánh 1> <nhánh 2>" + +msgid "do a real merge instead of a trivial merge" +msgstr "hoà trá»™n đúng chuẩn thay vì Ä‘Æ¡n giản" + +msgid "do a trivial merge only" +msgstr "chỉ hoà trá»™n Ä‘Æ¡n giản" + +msgid "also show informational/conflict messages" +msgstr "hiển thị thông báo chú thÃch/xung Ä‘á»™t" + +msgid "list filenames without modes/oids/stages" +msgstr "liệt kê tên táºp tin không kèm chế Ä‘á»™/oid/stage" + +msgid "allow merging unrelated histories" +msgstr "cho phép hòa trá»™n lịch sá» không liên quan" + +msgid "perform multiple merges, one per line of input" +msgstr "thá»±c hiện hoà trá»™n nhiá»u lần, vá»›i từng dòng đầu và o" + +msgid "specify a merge-base for the merge" +msgstr "chỉ định gốc hoà trá»™n để hòa trá»™n" + +msgid "option=value" +msgstr "tùy_chá»n=giá_trị" + +msgid "option for selected merge strategy" +msgstr "tùy chá»n cho chiến lược hòa trá»™n đã chá»n" + +msgid "--trivial-merge is incompatible with all other options" +msgstr "--trivial-merge không tÆ°Æ¡ng thÃch vá»›i các tùy chá»n khác" + +#, c-format +msgid "unknown strategy option: -X%s" +msgstr "không hiểu chiến lược: -X%s" + +#, c-format +msgid "malformed input line: '%s'." +msgstr "dòng đầu và o sai quy cách: '%s'." + +#, c-format +msgid "merging cannot continue; got unclean result of %d" +msgstr "không thể tiếp tục hoà trá»™n; kết quả không hoà n toà n %d" + msgid "git merge [<options>] [<commit>...]" -msgstr "git merge [<các tùy chá»n>] [<commit>…]" +msgstr "git merge [<các tùy chá»n>] [<commit>...]" msgid "switch `m' requires a value" -msgstr "switch “m†yêu cầu má»™t giá trị" +msgstr "tuỳ chá»n 'm' yêu cầu má»™t giá trị" #, c-format msgid "option `%s' requires a value" -msgstr "tùy chá»n “%s†yêu cầu má»™t giá trị" +msgstr "tùy chá»n '%s' yêu cầu má»™t giá trị" #, c-format msgid "Could not find merge strategy '%s'.\n" -msgstr "Không tìm thấy chiến lược hòa trá»™n “%sâ€.\n" +msgstr "Không tìm thấy chiến lược hòa trá»™n '%s'.\n" #, c-format msgid "Available strategies are:" -msgstr "Các chiến lược sẵn sà ng là :" +msgstr "Các chiến lược khả dụng là :" #, c-format msgid "Available custom strategies are:" -msgstr "Các chiến lược tùy chỉnh sẵn sà ng là :" +msgstr "Các chiến lược tùy chỉnh khả dụng là :" msgid "do not show a diffstat at the end of the merge" -msgstr "không hiển thị thống kê khác biệt tại cuối của lần hòa trá»™n" +msgstr "không hiển thị diffstat (thống kê khác biệt) phÃa dÆ°á»›i hòa trá»™n" msgid "show a diffstat at the end of the merge" -msgstr "hiển thị thống kê khác biệt tại cuối của hòa trá»™n" +msgstr "hiển thị diffstat (thống kê khác biệt) phÃa dÆ°á»›i hòa trá»™n" msgid "(synonym to --stat)" msgstr "(đồng nghÄ©a vá»›i --stat)" @@ -7947,7 +8153,7 @@ msgid "add (at most <n>) entries from shortlog to merge commit message" msgstr "thêm (Ãt nhất <n>) mục từ shortlog cho ghi chú chuyển giao hòa trá»™n" msgid "create a single commit instead of doing a merge" -msgstr "tạo má»™t lần chuyển giao Ä‘Æ°on thay vì thá»±c hiện việc hòa trá»™n" +msgstr "tạo má»™t lần chuyển giao Ä‘Æ¡n thay vì thá»±c hiện việc hòa trá»™n" msgid "perform a commit if the merge succeeds (default)" msgstr "thá»±c hiện chuyển giao nếu hòa trá»™n thà nh công (mặc định)" @@ -7959,7 +8165,7 @@ msgid "allow fast-forward (default)" msgstr "cho phép chuyển-tiếp-nhanh (mặc định)" msgid "abort if fast-forward is not possible" -msgstr "bá» qua nếu chuyển-tiếp-nhanh không thể được" +msgstr "huá»· lệnh nếu không thể chuyển-tiếp-nhanh" msgid "verify that the named commit has a valid GPG signature" msgstr "thẩm tra xem lần chuyển giao có tên đó có chữ ký GPG hợp lệ hay không" @@ -7970,12 +8176,6 @@ msgstr "chiến lược" msgid "merge strategy to use" msgstr "chiến lược hòa trá»™n sẽ dùng" -msgid "option=value" -msgstr "tùy_chá»n=giá_trị" - -msgid "option for selected merge strategy" -msgstr "tùy chá»n cho chiến lược hòa trá»™n đã chá»n" - msgid "merge commit message (for a non-fast-forward merge)" msgstr "" "hòa trá»™n ghi chú của lần chuyển giao (dà nh cho hòa trá»™n không-chuyển-tiếp-" @@ -7985,17 +8185,14 @@ msgid "use <name> instead of the real target" msgstr "dùng <tên> thay cho Ä‘Ãch tháºt" msgid "abort the current in-progress merge" -msgstr "bãi bá» quá trình hòa trá»™n hiện tại Ä‘ang thá»±c hiện" +msgstr "huá»· bá» quá trình hòa trá»™n hiện Ä‘ang thá»±c hiện" msgid "--abort but leave index and working tree alone" -msgstr "--abort nhÆ°ng để lại bảng mục lục và cây là m việc" +msgstr "--abort nhÆ°ng để lại chỉ mục và cây là m việc" msgid "continue the current in-progress merge" msgstr "tiếp tục quá trình hòa trá»™n hiện tại Ä‘ang thá»±c hiện" -msgid "allow merging unrelated histories" -msgstr "cho phép hòa trá»™n lịch sá» không liên quan" - msgid "bypass pre-merge-commit and commit-msg hooks" msgstr "vòng qua móc (hook) pre-merge-commit và commit-msg" @@ -8028,34 +8225,30 @@ msgstr "Không có lá»i chú thÃch hòa trá»™n -- nên không cáºp nháºt HEA #, c-format msgid "'%s' does not point to a commit" -msgstr "“%s†không chỉ đến má»™t lần chuyển giao nà o cả" +msgstr "'%s' không chỉ đến má»™t lần chuyển giao nà o cả" #, c-format msgid "Bad branch.%s.mergeoptions string: %s" msgstr "Chuá»—i branch.%s.mergeoptions sai: %s" msgid "Unable to write index." -msgstr "Không thể ghi bảng mục lục." +msgstr "Không thể ghi chỉ mục." msgid "Not handling anything other than two heads merge." msgstr "Không cầm nắm gì ngoà i hai head hòa trá»™n." #, c-format -msgid "unknown strategy option: -X%s" -msgstr "không hiểu chiến lược: -X%s" - -#, c-format msgid "unable to write %s" msgstr "không thể ghi %s" #, c-format msgid "Could not read from '%s'" -msgstr "Không thể Ä‘á»c từ “%sâ€" +msgstr "Không thể Ä‘á»c từ '%s'" #, c-format msgid "Not committing merge; use 'git commit' to complete the merge.\n" msgstr "" -"Vẫn chÆ°a hòa trá»™n các lần chuyển giao; sá» dụng lệnh “git commit†để hoà n tất " +"Vẫn chÆ°a hòa trá»™n các lần chuyển giao; sá» dụng lệnh 'git commit' để hoà n tất " "việc hòa trá»™n.\n" msgid "" @@ -8074,10 +8267,10 @@ msgstr "Nếu phần chú thÃch rá»—ng sẽ hủy bá» lần chuyển giao.\n" #, 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 "" -"Những dòng được bắt đầu bằng “%c†sẽ được bá» qua, và nếu phần chú\n" +"Những dòng được bắt đầu bằng '%s' sẽ được bá» qua, và nếu phần chú\n" "thÃch rá»—ng sẽ hủy bá» lần chuyển giao.\n" msgid "Empty commit message." @@ -8108,19 +8301,16 @@ msgstr "Không nhánh mạng theo dõi cho %s từ %s" #, c-format msgid "Bad value '%s' in environment '%s'" -msgstr "Giá trị sai “%s†trong biến môi trÆ°á»ng “%sâ€" +msgstr "Giá trị sai '%s' trong biến môi trÆ°á»ng '%s'" #, c-format msgid "could not close '%s'" -msgstr "không thể đóng “%sâ€" +msgstr "không thể đóng '%s'" #, c-format msgid "not something we can merge in %s: %s" msgstr "không phải là má»™t thứ gì đó mà chúng tôi có thể hòa trá»™n trong %s: %s" -msgid "not something we can merge" -msgstr "không phải là thứ gì đó mà chúng tôi có thể hòa trá»™n" - msgid "--abort expects no arguments" msgstr "--abort không nháºn các đối số" @@ -8172,16 +8362,22 @@ msgid "Can merge only exactly one commit into empty head" msgstr "" "Không thể hòa trá»™n má»™t cách đúng đắn má»™t lần chuyển giao và o má»™t head rá»—ng" -msgid "refusing to merge unrelated histories" -msgstr "từ chối hòa trá»™n lịch sá» không liên quan" - #, c-format msgid "Updating %s..%s\n" msgstr "Äang cáºp nháºt %s..%s\n" #, c-format +msgid "" +"Your local changes to the following files would be overwritten by merge:\n" +" %s" +msgstr "" +"Các thay đổi ná»™i bá»™ của bạn vá»›i các táºp tin sau đây sẽ bị ghi đè bởi lệnh " +"hòa trá»™n:\n" +" %s" + +#, c-format msgid "Trying really trivial in-index merge...\n" -msgstr "Äang thá» hòa trá»™n kiểu “trivial in-indexâ€â€¦\n" +msgstr "Äang thá» hòa trá»™n kiểu 'trivial in-index'...\n" #, c-format msgid "Nope.\n" @@ -8189,15 +8385,15 @@ msgstr "Không.\n" #, c-format msgid "Rewinding the tree to pristine...\n" -msgstr "Äang tua lại cây thà nh thá»i xa xÆ°a…\n" +msgstr "Äang tua lại cây thà nh thá»i xa xÆ°a...\n" #, c-format msgid "Trying merge strategy %s...\n" -msgstr "Äang thá» chiến lược hòa trá»™n %s…\n" +msgstr "Äang thá» chiến lược hòa trá»™n %s...\n" #, c-format msgid "No merge strategy handled the merge.\n" -msgstr "Không có chiến lược hòa trá»™n nà o được nắm giữ (handle) sá»± hòa trá»™n.\n" +msgstr "Không có chiến lược hòa trá»™n nà o có thể xá» lý việc hòa trá»™n.\n" #, c-format msgid "Merge with strategy %s failed.\n" @@ -8209,9 +8405,12 @@ msgstr "Sá» dụng chiến lược %s để chuẩn bị giải quyết bằng #, c-format msgid "Automatic merge went well; stopped before committing as requested\n" +msgstr "Hòa trá»™n tá»± Ä‘á»™ng đã xong; dừng trÆ°á»›c khi chuyển giao nhÆ° đã yêu cầu\n" + +#, c-format +msgid "When finished, apply stashed changes with `git stash pop`\n" msgstr "" -"Hòa trá»™n tá»± Ä‘á»™ng đã trở nên tốt; bị dừng trÆ°á»›c khi việc chuyển giao được yêu " -"cầu\n" +"Sau khi hoà n thà nh, áp dụng các thay đổi trong stash vá»›i `git stash pop` \n" #, c-format msgid "warning: tag input does not pass fsck: %s" @@ -8219,11 +8418,11 @@ msgstr "cảnh báo: đầu và o thẻ không qua kiểm tra fsck: %s" #, c-format msgid "error: tag input does not pass fsck: %s" -msgstr "lá»—i: đầu và o thẻ không vượt qua fsck: %s" +msgstr "lá»—i: đầu và o thẻ không qua kiểm tra fsck: %s" #, c-format msgid "%d (FSCK_IGNORE?) should never trigger this callback" -msgstr "%d (FSCK_IGNORE?) không bao giá» nên kÃch hoạt cuá»™c gá»i ngược nà y" +msgstr "%d (FSCK_IGNORE?) không bao giá» nên kÃch hoạt callback nà y" #, c-format msgid "could not read tagged object '%s'" @@ -8231,24 +8430,20 @@ msgstr "không thể Ä‘á»c đối tượng được đánh thẻ %s" #, c-format msgid "object '%s' tagged as '%s', but is a '%s' type" -msgstr "đối tượng %s được đánh thẻ là %s, không phải là kiểu %s" - -msgid "could not read from stdin" -msgstr "không thể Ä‘á»c từ đầu và o tiêu chuẩn" +msgstr "đối tượng '%s' được đánh thẻ là '%s', nhÆ°ng là kiểu '%s'" msgid "tag on stdin did not pass our strict fsck check" msgstr "" "thẻ trên stdin đã không vượt qua kiểm tra fsck nghiêm ngặt của chúng tôi" msgid "tag on stdin did not refer to a valid object" -msgstr "" -"thẻ trên đầu và o tiêu chuẩn không chỉ đến má»™t lần chuyển giao hợp lệ nà o cả" +msgstr "thẻ trên stdin không chỉ đến má»™t đối tượng hợp lệ" msgid "unable to write tag file" -msgstr "không thể ghi và o táºp tin lÆ°u thẻ" +msgstr "không thể ghi và o táºp tin thẻ" msgid "input is NUL terminated" -msgstr "đầu và o được chấm dứt bởi NUL" +msgstr "đầu và o được kết thúc bởi NUL" msgid "allow missing objects" msgstr "cho phép thiếu đối tượng" @@ -8288,7 +8483,7 @@ msgid "write multi-pack bitmap" msgstr "ghi multi-pack bitmap" msgid "write multi-pack index containing only given indexes" -msgstr "ghi mục lục multi-pack chỉ chứa các mục lục đã cho" +msgstr "ghi chỉ mục multi-pack chỉ chứa các chỉ mục đã cho" msgid "refs snapshot for selecting bitmap commits" msgstr "ảnh chụp nhanh refs để chá»n các lần chuyển giao ánh xạ" @@ -8301,11 +8496,11 @@ msgstr "" "và o má»™t bó cái mà lá»›n hÆ¡n kÃch thÆ°á»›c nà y" msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<các tùy chá»n>] <nguồn>… <Ä‘Ãch>" +msgstr "git mv [<các tùy chá»n>] <nguồn>... <Ä‘Ãch>" #, c-format msgid "Directory %s is in index and no submodule?" -msgstr "ThÆ° mục “%s†có ở trong chỉ mục mà không có mô-Ä‘un con?" +msgstr "ThÆ° mục '%s' có ở trong chỉ mục mà không có mô-Ä‘un con?" msgid "Please stage your changes to .gitmodules or stash them to proceed" msgstr "" @@ -8313,7 +8508,7 @@ msgstr "" #, c-format msgid "%.*s is in index" -msgstr "%.*s trong bảng mục lục" +msgstr "%.*s trong chỉ mục" msgid "force move/rename even if target exists" msgstr "ép buá»™c di chuyển hay đổi tên tháºm chà cả khi Ä‘Ãch đã tồn tại" @@ -8323,20 +8518,23 @@ msgstr "bá» qua các lá»—i liên quan đến di chuyển, đổi tên" #, c-format msgid "destination '%s' is not a directory" -msgstr "có Ä‘Ãch “%s†nhÆ°ng đây không phải là má»™t thÆ° mục" +msgstr "có Ä‘Ãch '%s' nhÆ°ng đây không phải là má»™t thÆ° mục" #, c-format msgid "Checking rename of '%s' to '%s'\n" -msgstr "Äang kiểm tra việc đổi tên của “%s†thà nh “%sâ€\n" +msgstr "Äang kiểm tra việc đổi tên của '%s' thà nh '%s'\n" msgid "bad source" msgstr "nguồn sai" +msgid "destination exists" +msgstr "Ä‘Ãch đã tồn tại sẵn rồi" + msgid "can not move directory into itself" msgstr "không thể di chuyển má»™t thÆ° mục và o trong chÃnh nó được" -msgid "cannot move directory over file" -msgstr "không di chuyển được thÆ° mục thông qua táºp tin" +msgid "destination already exists" +msgstr "Ä‘Ãch đã tồn tại sẵn rồi" msgid "source directory is empty" msgstr "thÆ° mục nguồn là trống rá»—ng" @@ -8347,12 +8545,9 @@ msgstr "không nằm dÆ°á»›i sá»± quản lý mã nguồn" msgid "conflicted" msgstr "bị xung Ä‘á»™t" -msgid "destination exists" -msgstr "Ä‘Ãch đã tồn tại sẵn rồi" - #, c-format msgid "overwriting '%s'" -msgstr "Ä‘ang ghi đè lên “%sâ€" +msgstr "Ä‘ang ghi đè lên '%s'" msgid "Cannot overwrite" msgstr "Không thể ghi đè" @@ -8363,6 +8558,9 @@ msgstr "nhiá»u nguồn cho cùng má»™t Ä‘Ãch" msgid "destination directory does not exist" msgstr "thÆ° mục Ä‘Ãch không tồn tại" +msgid "destination exists in the index" +msgstr "Ä‘Ãch đã tồn tại sẵn trong chỉ mục" + #, c-format msgid "%s, source=%s, destination=%s" msgstr "%s, nguồn=%s, Ä‘Ãch=%s" @@ -8373,10 +8571,10 @@ msgstr "Äổi tên %s thà nh %s\n" #, c-format msgid "renaming '%s' failed" -msgstr "gặp lá»—i khi đổi tên “%sâ€" +msgstr "gặp lá»—i khi đổi tên '%s'" msgid "git name-rev [<options>] <commit>..." -msgstr "git name-rev [<các tùy chá»n>] <commit>…" +msgstr "git name-rev [<các tùy chá»n>] <commit>..." msgid "git name-rev [<options>] --all" msgstr "git name-rev [<các tùy chá»n>] --all" @@ -8404,33 +8602,37 @@ msgid "deprecated: use --annotate-stdin instead" msgstr "đã lạc háºu: hãy dùng --annotate-stdin để thay thế" msgid "annotate text from stdin" -msgstr "chú giải chữ từ đầu và o tiêu chuẩn stdin" +msgstr "chú giải chữ từ stdin" msgid "allow to print `undefined` names (default)" -msgstr "cho phép in các tên “chÆ°a định nghÄ©a†(mặc định)" +msgstr "cho phép in các tên `chÆ°a định nghÄ©a` (mặc định)" msgid "dereference tags in the input (internal use)" -msgstr "bãi bá» tham chiếu các thẻ trong đầu và o (dùng ná»™i bá»™)" +msgstr "giải tham chiếu các thẻ trong đầu và o (dùng ná»™i bá»™)" msgid "git notes [--ref <notes-ref>] [list [<object>]]" msgstr "git notes [--ref <notes-ref>] [list [<đối-tượng>]]" msgid "" -"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> " -"| (-c | -C) <object>] [<object>]" +"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] [-m <lá»i-nhắn> | -F " -"<táºp-tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]" +"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <lá»i-nhắn> | -F <táºp-" +"tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]" msgid "git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>" msgstr "git notes [--ref <notes-ref>] copy [-f] <từ-đối-tượng> <đến-đối-tượng>" msgid "" -"git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | " -"(-c | -C) <object>] [<object>]" +"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] [-m <lá»i-nhắn> | -F " -"<táºp-tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]" +"git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <lá»i-nhắn> | -F <táºp-" +"tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]" msgid "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]" msgstr "git notes [--ref <notes-ref>] edit [--allow-empty] [<đối-tượng>]" @@ -8444,7 +8646,7 @@ msgstr "" "git notes [--ref <notes-ref>] merge [-v | -q] [-s <chiến-lược> ] <notes-ref>" msgid "git notes [--ref <notes-ref>] remove [<object>...]" -msgstr "git notes [--ref <notes-ref>] remove [<đối-tượng>…]" +msgstr "git notes [--ref <notes-ref>] remove [<đối-tượng>...]" msgid "git notes [--ref <notes-ref>] prune [-n] [-v]" msgstr "git notes [--ref <notes-ref>] prune [-n] [-v]" @@ -8462,7 +8664,7 @@ msgid "git notes copy [<options>] <from-object> <to-object>" msgstr "git notes copy [<các tùy chá»n>] <từ-đối-tượng> <đến-đối-tượng>" msgid "git notes copy --stdin [<from-object> <to-object>]..." -msgstr "git notes copy --stdin [<từ-đối-tượng> <đến-đối-tượng>]…" +msgstr "git notes copy --stdin [<từ-đối-tượng> <đến-đối-tượng>]..." msgid "git notes append [<options>] [<object>]" msgstr "git notes append [<các tùy chá»n>] [<đối-tượng>]" @@ -8491,16 +8693,12 @@ msgstr "git notes prune [<các tùy chá»n>]" msgid "Write/edit the notes for the following object:" msgstr "Ghi hay sá»a ghi chú cho đối tượng sau đây:" -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "không thể khởi chạy “show†cho đối tượng “%sâ€" - msgid "could not read 'show' output" -msgstr "không thể Ä‘á»c kết xuất “showâ€" +msgstr "không thể Ä‘á»c kết xuất 'show'" #, c-format msgid "failed to finish 'show' for object '%s'" -msgstr "gặp lá»—i khi hoà n thà nh “show†cho đối tượng “%sâ€" +msgstr "gặp lá»—i khi hoà n thà nh 'show' cho đối tượng '%s'" msgid "please supply the note contents using either -m or -F option" msgstr "" @@ -8515,27 +8713,23 @@ msgstr "ná»™i dung ghi chú còn lại %s" #, c-format msgid "could not open or read '%s'" -msgstr "không thể mở hay Ä‘á»c “%sâ€" +msgstr "không thể mở hay Ä‘á»c '%s'" #, c-format msgid "failed to resolve '%s' as a valid ref." -msgstr "gặp lá»—i khi phân giải “%s†nhÆ° là má»™t tham chiếu hợp lệ." +msgstr "gặp lá»—i khi phân giải '%s' thà nh má»™t tham chiếu hợp lệ." #, c-format msgid "failed to read object '%s'." -msgstr "gặp lá»—i khi Ä‘á»c đối tượng “%sâ€." +msgstr "gặp lá»—i khi Ä‘á»c đối tượng '%s'." #, c-format msgid "cannot read note data from non-blob object '%s'." -msgstr "không thể Ä‘á»c dữ liệu ghi chú từ đối tượng không-blob “%sâ€." - -#, c-format -msgid "malformed input line: '%s'." -msgstr "dòng đầu và o dị hình: “%sâ€." +msgstr "không thể Ä‘á»c dữ liệu ghi chú từ đối tượng không-blob '%s'." #, c-format msgid "failed to copy notes from '%s' to '%s'" -msgstr "gặp lá»—i khi sao chép ghi chú (note) từ “%s†sang “%sâ€" +msgstr "gặp lá»—i khi sao chép ghi chú (note) từ '%s' sang '%s'" #. TRANSLATORS: the first %s will be replaced by a git #. notes command: 'add', 'merge', 'remove', etc. @@ -8566,13 +8760,22 @@ msgstr "cho lÆ°u trữ ghi chú trống rá»—ng" msgid "replace existing notes" msgstr "thay thế ghi chú trÆ°á»›c" +msgid "<paragraph-break>" +msgstr "<dấu ngắt Ä‘oạn>" + +msgid "insert <paragraph-break> between paragraphs" +msgstr "chèn <dấu ngắt Ä‘oạn> giữa các Ä‘oạn văn" + +msgid "remove unnecessary whitespace" +msgstr "Xóa bá» các khoảng trắng không cần thiết" + #, c-format msgid "" "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite " "existing notes" msgstr "" "Không thể thêm các ghi chú. Äã tìm thấy các ghi chú đã có sẵn cho đối tượng " -"%s. Sá» dụng tùy chá»n “-f†để ghi đè lên các ghi chú cÅ©" +"%s. Sá» dụng tùy chá»n '-f' để ghi đè lên các ghi chú cÅ©" #, c-format msgid "Overwriting existing notes for object %s\n" @@ -8583,10 +8786,10 @@ msgid "Removing note for object %s\n" msgstr "Äang gỡ bá» ghi chú (note) cho đối tượng %s\n" msgid "read objects from stdin" -msgstr "Ä‘á»c các đối tượng từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c các đối tượng từ stdin" msgid "load rewriting config for <command> (implies --stdin)" -msgstr "tải cấu hình chép lại cho <lệnh> (ngầm định là --stdin)" +msgstr "tải cấu hình chép lại cho <lệnh> (ngụ ý --stdin)" msgid "too few arguments" msgstr "quá Ãt đối số" @@ -8597,7 +8800,7 @@ msgid "" "existing notes" msgstr "" "Không thể sao chép các ghi chú. Äã tìm thấy các ghi chú đã có sẵn cho đối " -"tượng %s. Sá» dụng tùy chá»n “-f†để ghi đè lên các ghi chú cÅ©" +"tượng %s. Sá» dụng tùy chá»n '-f' để ghi đè lên các ghi chú cÅ©" #, c-format msgid "missing notes on source object %s. Cannot copy." @@ -8608,8 +8811,8 @@ msgid "" "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" msgstr "" -"Các tùy chá»n -m/-F/-c/-C đã cổ không còn dùng nữa cho lệnh con “editâ€.\n" -"Xin hãy sá» dụng lệnh sau để thay thế: “git notes add -f -m/-F/-c/-Câ€.\n" +"Các tùy chá»n -m/-F/-c/-C đã không còn dùng cho lệnh con 'edit'.\n" +"Xin hãy sá» dụng lệnh sau để thay thế: 'git notes add -f -m/-F/-c/-C'.\n" msgid "failed to delete ref NOTES_MERGE_PARTIAL" msgstr "gặp lá»—i khi xóa tham chiếu NOTES_MERGE_PARTIAL" @@ -8618,7 +8821,7 @@ msgid "failed to delete ref NOTES_MERGE_REF" msgstr "gặp lá»—i khi xóa tham chiếu NOTES_MERGE_REF" msgid "failed to remove 'git notes merge' worktree" -msgstr "gặp lá»—i khi gỡ bá» cây là m việc “git notes mergeâ€" +msgstr "gặp lá»—i khi gỡ bá» cây là m việc 'git notes merge'" msgid "failed to read ref NOTES_MERGE_PARTIAL" msgstr "gặp lá»—i khi Ä‘á»c tham chiếu NOTES_MERGE_PARTIAL" @@ -8627,7 +8830,7 @@ msgid "could not find commit from NOTES_MERGE_PARTIAL." msgstr "không thể tìm thấy lần chuyển giao từ NOTES_MERGE_PARTIAL." msgid "could not parse commit from NOTES_MERGE_PARTIAL." -msgstr "không thể phân tÃch cú pháp lần chuyển giao từ NOTES_MERGE_PARTIAL." +msgstr "không hiểu cú pháp lần chuyển giao từ NOTES_MERGE_PARTIAL." msgid "failed to resolve NOTES_MERGE_REF" msgstr "gặp lá»—i khi phân giải NOTES_MERGE_REF" @@ -8649,7 +8852,7 @@ msgid "" "resolve notes conflicts using the given strategy (manual/ours/theirs/union/" "cat_sort_uniq)" msgstr "" -"phân giải các xung Ä‘á»™t “notes†sá» dụng chiến lược đã Ä‘Æ°a ra (manual/ours/" +"phân giải các xung Ä‘á»™t 'notes' sá» dụng chiến lược đã Ä‘Æ°a ra (manual/ours/" "theirs/union/cat_sort_uniq)" msgid "Committing unmerged notes" @@ -8691,49 +8894,48 @@ msgid "" "abort'.\n" msgstr "" "Gặp lá»—i khi hòa trá»™n các ghi chú tá»± Ä‘á»™ng. Sá»a các xung Ä‘á»™t nà y trong %s và " -"chuyển giao kết quả bằng “git notes merge --commitâ€, hoặc bãi bá» việc hòa " -"trá»™n bằng “git notes merge --abortâ€.\n" +"chuyển giao kết quả bằng 'git notes merge --commit', hoặc huá»· bá» việc hòa " +"trá»™n bằng 'git notes merge --abort'.\n" #, c-format msgid "Failed to resolve '%s' as a valid ref." -msgstr "Gặp lá»—i khi phân giải “%s†nhÆ° là má»™t tham chiếu hợp lệ." +msgstr "Gặp lá»—i khi phân giải '%s' thà nh má»™t tham chiếu hợp lệ." #, c-format msgid "Object %s has no note\n" msgstr "Äối tượng %s không có ghi chú (note)\n" msgid "attempt to remove non-existent note is not an error" -msgstr "cố gắng gỡ bá» má»™t note chÆ°a từng tồn tại không phải là má»™t lá»—i" +msgstr "việc gỡ bá» má»™t note không tồn tại không phải là lá»—i" msgid "read object names from the standard input" -msgstr "Ä‘á»c tên đối tượng từ thiết bị nháºp chuẩn" +msgstr "Ä‘á»c tên đối tượng từ stdin" msgid "do not remove, show only" msgstr "không gỡ bá», chỉ hiển thị" msgid "report pruned notes" -msgstr "báo cáo các đối tượng đã prune" +msgstr "liệt kê các đối tượng đã prune" msgid "notes-ref" msgstr "notes-ref" msgid "use notes from <notes-ref>" -msgstr "dùng “notes†từ <notes-ref>" +msgstr "dùng 'notes' từ <notes-ref>" #, c-format -msgid "unknown subcommand: %s" -msgstr "không hiểu câu lệnh con: %s" +msgid "unknown subcommand: `%s'" +msgstr "không hiểu câu lệnh con: `%s'" -msgid "" -"git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]" +msgid "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]" msgstr "" -"git pack-objects --stdout [các tùy chá»n…] [< <danh-sách-tham-chiếu> | < " +"git pack-objects --stdout [<các tùy chá»n>] [< <danh-sách-tham-chiếu> | < " "<danh-sách-đối-tượng>]" msgid "" -"git pack-objects [<options>...] <base-name> [< <ref-list> | < <object-list>]" +"git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]" msgstr "" -"git pack-objects [các tùy chá»n…] <base-name> [< <danh-sách-ref> | < <danh-" +"git pack-objects [<các tùy chá»n>] <base-name> [< <danh-sách-ref> | < <danh-" "sách-đối-tượng>]" #, c-format @@ -8772,14 +8974,14 @@ msgstr "Äang ghi lại các đối tượng" #, c-format msgid "failed to stat %s" -msgstr "gặp lá»—i khi lấy thông tin thống kê vá» %s" +msgstr "gặp lá»—i khi stat %s" #, c-format msgid "failed utime() on %s" -msgstr "gặp lá»—i utime() trên “%sâ€" +msgstr "gặp lá»—i utime() trên '%s'" msgid "failed to write bitmap index" -msgstr "gặp lá»—i khi ghi mục lục ánh xạ" +msgstr "gặp lá»—i khi ghi chỉ mục ánh xạ" #, c-format msgid "wrote %<PRIu32> objects while expecting %<PRIu32>" @@ -8805,7 +9007,7 @@ msgstr "không thể lấy kÃch cỡ của %s" #, c-format msgid "unable to parse object header of %s" -msgstr "không thể phân tÃch phần đầu đối tượng của “%sâ€" +msgstr "không thể Ä‘á»c phần đầu đối tượng của '%s'" #, c-format msgid "object %s cannot be read" @@ -8826,11 +9028,11 @@ msgstr "Nén delta dùng tá»›i %d tuyến trình" #, c-format msgid "unable to pack objects reachable from tag %s" -msgstr "không thể đóng gói các đối tượng tiếp cáºn được từ thẻ “%sâ€" +msgstr "không thể đóng gói các đối tượng tiếp cáºn được từ thẻ '%s'" #, c-format msgid "unable to get type of object %s" -msgstr "không thể lấy kiểu của đối tượng “%sâ€" +msgstr "không thể lấy kiểu của đối tượng '%s'" msgid "Compressing objects" msgstr "Äang nén các đối tượng" @@ -8839,27 +9041,31 @@ msgid "inconsistency with delta count" msgstr "mâu thuẫn vá»›i số lượng delta" #, c-format +msgid "invalid pack.allowPackReuse value: '%s'" +msgstr "giá trị pack.allowPackReuse không hợp lệ: '%s'" + +#, c-format msgid "" "value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-" "hash> <uri>' (got '%s')" msgstr "" -"giá trị của uploadpack.blobpackfileuri phải có dạng “<object-hash> <pack-" -"hash> <uri>†(nháºn “%sâ€)" +"giá trị của uploadpack.blobpackfileuri phải có dạng '<object-hash> <pack-" +"hash> <uri>' (nháºn '%s')" #, c-format msgid "" "object already configured in another uploadpack.blobpackfileuri (got '%s')" msgstr "" "đối tượng đã được cấu hình trong má»™t uploadpack.blobpackfileuri khác (đã " -"nháºn “%sâ€)" +"nháºn '%s')" #, c-format msgid "could not get type of object %s in pack %s" -msgstr "không thể lấy kiểu của đối tượng “%s†trong gói “%sâ€" +msgstr "không thể lấy kiểu của đối tượng '%s' trong gói '%s'" #, c-format msgid "could not find pack '%s'" -msgstr "không thể tìm thấy gói “%sâ€" +msgstr "không thể tìm thấy gói '%s'" #, c-format msgid "packfile %s cannot be accessed" @@ -8879,7 +9085,7 @@ msgid "" "expected edge object ID, got garbage:\n" " %s" msgstr "" -"cần ID đối tượng cạnh, nháºn được rác:\n" +"cần ID đối tượng cạnh, có rác:\n" " %s" #, c-format @@ -8887,14 +9093,14 @@ msgid "" "expected object ID, got garbage:\n" " %s" msgstr "" -"cần ID đối tượng, nháºn được rác:\n" +"cần ID đối tượng, có rác:\n" " %s" msgid "could not load cruft pack .mtimes" msgstr "không thể tải cruft pack .mtimes" msgid "cannot open pack index" -msgstr "không thể mở mục lục của gói" +msgstr "không thể mở chỉ mục của gói" #, c-format msgid "loose object at %s could not be examined" @@ -8905,31 +9111,37 @@ msgstr "không thể buá»™c mất đối tượng" #, c-format msgid "not a rev '%s'" -msgstr "không phải má»™t rev “%sâ€" +msgstr "không phải má»™t rev '%s'" #, c-format msgid "bad revision '%s'" -msgstr "Ä‘iểm xem xét sai “%sâ€" +msgstr "Ä‘iểm xem xét sai '%s'" msgid "unable to add recent objects" msgstr "không thể thêm các đối tượng má»›i dùng" #, c-format msgid "unsupported index version %s" -msgstr "phiên bản mục lục không được há»— trợ %s" +msgstr "phiên bản chỉ mục không được há»— trợ %s" #, c-format msgid "bad index version '%s'" -msgstr "phiên bản mục lục sai “%sâ€" +msgstr "phiên bản chỉ mục sai '%s'" + +msgid "show progress meter during object writing phase" +msgstr "hiển thị bá»™ Ä‘o tiến triển trong suốt pha ghi đối tượng" + +msgid "similar to --all-progress when progress meter is shown" +msgstr "tÆ°Æ¡ng tá»± --all-progress khi bá»™ Ä‘o tiến trình được xuất hiện" msgid "<version>[,<offset>]" msgstr "<phiên bản>[,offset]" msgid "write the pack index file in the specified idx format version" -msgstr "ghi táºp tin bảng mục lục gói (pack) ở phiên bản định dạng idx đã cho" +msgstr "ghi táºp tin chỉ mục gói (pack) ở phiên bản định dạng idx đã cho" msgid "maximum size of each output pack file" -msgstr "kcÃh thÆ°á»›c tối Ä‘a cho táºp tin gói được tạo" +msgstr "kÃch thÆ°á»›c tối Ä‘a cho táºp tin gói được tạo" msgid "ignore borrowed objects from alternate object store" msgstr "bá» qua các đối tượng vay mượn từ kho đối tượng thay thế" @@ -8944,7 +9156,7 @@ msgid "limit pack window by memory in addition to object limit" msgstr "giá»›i hạn cá»a sổ đóng gói theo bá»™ nhá»› cá»™ng thêm vá»›i giá»›i hạn đối tượng" msgid "maximum length of delta chain allowed in the resulting pack" -msgstr "Ä‘á»™ dà i tối Ä‘a của chuá»—i móc xÃch “delta†được phép trong gói kết quả" +msgstr "Ä‘á»™ dà i tối Ä‘a của chuá»—i móc xÃch 'delta' được phép trong gói kết quả" msgid "reuse existing deltas" msgstr "dùng lại các delta sẵn có" @@ -8962,7 +9174,7 @@ msgid "do not create an empty pack output" msgstr "không thể tạo kết xuất gói trống rá»—ng" msgid "read revision arguments from standard input" -msgstr "Ä‘á»c tham số “revision†từ thiết bị nháºp chuẩn" +msgstr "Ä‘á»c tham số 'revision' từ stdin" msgid "limit the objects to those that are not yet packed" msgstr "giá»›i hạn các đối tượng thà nh những cái mà chúng vẫn chÆ°a được đóng gói" @@ -8974,13 +9186,13 @@ msgid "include objects referred by reflog entries" msgstr "bao gồm các đối tượng được tham chiếu bởi các mục reflog" msgid "include objects referred to by the index" -msgstr "bao gồm các đối tượng được tham chiếu bởi mục lục" +msgstr "bao gồm các đối tượng được tham chiếu bởi chỉ mục" msgid "read packs from stdin" -msgstr "Ä‘á»c các gói từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c các gói từ stdin" msgid "output pack to stdout" -msgstr "xuất gói ra đầu ra tiêu chuẩn" +msgstr "xuất gói ra stdout" msgid "include tag objects that refer to objects to be packed" msgstr "bao gồm các đối tượng tham chiếu đến các đối tượng được đóng gói" @@ -8993,16 +9205,16 @@ msgstr "pack mất các đối tượng không thể Ä‘á»c được" msgid "unpack unreachable objects newer than <time>" msgstr "" -"xả nén (gỡ khá»i gói) các đối tượng không thể Ä‘á»c được má»›i hÆ¡n <thá»i-gian>" +"giải nén (gỡ khá»i gói) các đối tượng không thể Ä‘á»c được má»›i hÆ¡n <thá»i-gian>" msgid "create a cruft pack" msgstr "tạo gói cruft" msgid "expire cruft objects older than <time>" -msgstr "các đối tượng cruft hết hạn cÅ© hÆ¡n khoảng <thá»i gian>" +msgstr "các đối tượng cruft hết hạn cÅ© hÆ¡n <mốc thá»i gian>" msgid "use the sparse reachability algorithm" -msgstr "sá» dụng thuáºt toán “sparse reachabilityâ€" +msgstr "sá» dụng thuáºt toán 'sparse reachability'" msgid "create thin packs" msgstr "tạo gói nhẹ" @@ -9020,25 +9232,25 @@ msgid "pack compression level" msgstr "mức nén gói" msgid "do not hide commits by grafts" -msgstr "không ẩn các lần chuyển giao bởi “graftsâ€" +msgstr "không ẩn các lần chuyển giao bởi 'grafts'" msgid "use a bitmap index if available to speed up counting objects" -msgstr "dùng mục lục ánh xạ nếu có thể được để nâng cao tốc Ä‘á»™ đếm đối tượng" +msgstr "dùng chỉ mục ánh xạ nếu có thể được để nâng cao tốc Ä‘á»™ đếm đối tượng" msgid "write a bitmap index together with the pack index" -msgstr "ghi má»™t mục lục ánh xạ cùng vá»›i mục lục gói" +msgstr "ghi má»™t chỉ mục ánh xạ cùng vá»›i chỉ mục gói" msgid "write a bitmap index if possible" -msgstr "ghi mục lục ánh xạ nếu được" +msgstr "ghi chỉ mục ánh xạ nếu được" msgid "handling for missing objects" msgstr "xá» lý cho thiếu đối tượng" msgid "do not pack objects in promisor packfiles" -msgstr "không thể đóng gói các đối tượng trong các táºp tin gói hứa hẹn" +msgstr "không thể đóng gói các đối tượng trong các táºp tin gói promisor" msgid "respect islands during delta compression" -msgstr "tôn trá»ng island trong suốt quá trình nén “deltaâ€" +msgstr "tôn trá»ng island trong suốt quá trình nén 'delta'" msgid "protocol" msgstr "giao thức" @@ -9048,7 +9260,7 @@ msgstr "loại trừ bất kỳ cấu hình uploadpack.blobpackfileuri vá»›i gia #, c-format msgid "delta chain depth %d is too deep, forcing %d" -msgstr "mức sau xÃch delta %d là quá sâu, buá»™c dùng %d" +msgstr "mức delta chain %d là quá sâu, buá»™c dùng %d" #, c-format msgid "pack.deltaCacheLimit is too high, forcing %d" @@ -9066,36 +9278,30 @@ msgid "minimum pack size limit is 1 MiB" msgstr "giá»›i hạn kÃch thÆ°á»›c tối thiểu của gói là 1 MiB" msgid "--thin cannot be used to build an indexable pack" -msgstr "--thin không thể được dùng để xây dá»±ng gói đánh mục lục được" - -msgid "cannot use --filter without --stdout" -msgstr "không thể dùng tùy chá»n --filter mà không có --stdout" +msgstr "không thể dùng --thin để xây dá»±ng gói đánh chỉ mục được" msgid "cannot use --filter with --stdin-packs" msgstr "không thể dùng tùy chá»n --filter vá»›i --stdin-packs" msgid "cannot use internal rev list with --stdin-packs" -msgstr "không thể dùng danh sách rev bên trong vá»›i --stdin-packs" +msgstr "không thể dùng danh sách rev ná»™i bá»™ vá»›i --stdin-packs" msgid "cannot use internal rev list with --cruft" -msgstr "không thể dùng danh sách rev bên trong vá»›i --cruft" +msgstr "không thể dùng danh sách rev ná»™i bá»™ vá»›i --cruft" msgid "cannot use --stdin-packs with --cruft" -msgstr "không thể dùng tùy chá»n --stdin-packs vá»›i --cruft" - -msgid "cannot use --max-pack-size with --cruft" -msgstr "không thể dùng tùy chá»n --max-pack-size vá»›i --cruft" +msgstr "không thể dùng tùy chá»n --stdin-packs vá»›i --cruft" msgid "Enumerating objects" -msgstr "Äánh số các đối tượng" +msgstr "Duyệt các đối tượng" #, c-format msgid "" "Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-" -"reused %<PRIu32>" +"reused %<PRIu32> (from %<PRIuMAX>)" msgstr "" -"Tổng %<PRIu32> (delta %<PRIu32>), dùng lại %<PRIu32> (delta %<PRIu32>), pack-" -"reused %<PRIu32>" +"Tổng %<PRIu32> (delta %<PRIu32>), dùng lại %<PRIu32> (delta %<PRIu32>),dùng " +"lại pack %<PRIu32> (trong số %<PRIuMAX>)" msgid "" "'git pack-redundant' is nominated for removal.\n" @@ -9104,14 +9310,21 @@ msgid "" "and let us know you still use it by sending an e-mail\n" "to <git@vger.kernel.org>. Thanks.\n" msgstr "" -"“git pack-redundant†được Ä‘á» cỠđể loại bá».\n" -"Nếu bạn vẫn sá» dụng lệnh nà y, vui lòng bổ sung\n" -"thêm má»™t tùy chá»n, “--i-still-use-thisâ€, trên dòng lệnh\n" +"'git pack-redundant' đã được Ä‘á» cỠđể loại bá».\n" +"Nếu bạn vẫn còn sá» dụng lệnh nà y, vui lòng bổ sung\n" +"thêm má»™t tùy chá»n, '--i-still-use-this', trên dòng lệnh\n" "và cho chúng tôi biết bạn vẫn sá» dụng nó bằng cách gá»i e-mail\n" -"đến <git@vger.kernel.org>. Cảm Æ¡n.\n" +"đến <git@vger.kernel.org>. Xin cảm Æ¡n.\n" + +msgid "refusing to run without --i-still-use-this" +msgstr "từ chối chạy lệnh nà y mà không có --i-still-use-this" -msgid "git pack-refs [<options>]" -msgstr "git pack-refs [<các tùy chá»n>]" +msgid "" +"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude " +"<pattern>]" +msgstr "" +"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude " +"<pattern>]" msgid "pack everything" msgstr "đóng gói má»i thứ" @@ -9119,23 +9332,45 @@ msgstr "đóng gói má»i thứ" msgid "prune loose refs (default)" msgstr "prune (cắt cụt) những tham chiếu bị mất (mặc định)" +msgid "auto-pack refs as needed" +msgstr "tá»± Ä‘á»™ng pack tham chiếu nếu cần" + +msgid "references to include" +msgstr "bao gồm các tham chiếu" + +msgid "references to exclude" +msgstr "loại trừ các tham chiếu" + +msgid "git patch-id [--stable | --unstable | --verbatim]" +msgstr "git patch-id [--stable | --unstable | --verbatim]" + +msgid "use the unstable patch-id algorithm" +msgstr "sá» dụng thuáºt toán patch-id unstable" + +msgid "use the stable patch-id algorithm" +msgstr "sá» dụng thuáºt toán patch-id stable" + +msgid "don't strip whitespace from the patch" +msgstr "không lược bá» khoảng trắng thừa từ bản vá" + msgid "git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]" -msgstr "git prune [-n] [-v] [--progress] [--expire <thá»i-gian>] [--] [<head>…]" +msgstr "" +"git prune [-n] [-v] [--progress] [--expire <thá»i-gian>] [--] [<head>...]" msgid "report pruned objects" -msgstr "báo cáo các đối tượng đã prune" +msgstr "liệt kê các đối tượng đã prune" msgid "expire objects older than <time>" msgstr "các đối tượng hết hạn cÅ© hÆ¡n khoảng <thá»i gian>" msgid "limit traversal to objects outside promisor packfiles" -msgstr "giá»›i hạn giao đến các đối tượng nằm ngoà i các táºp tin gói hứa hẹn" +msgstr "giá»›i hạn giao đến các đối tượng nằm ngoà i các táºp tin gói promisor" msgid "cannot prune in a precious-objects repo" msgstr "không thể tỉa bá»›t trong má»™t kho đối_tượng_vÄ©_đại" msgid "git pull [<options>] [<repository> [<refspec>...]]" -msgstr "git pull [<các tùy chá»n>] [<kho-chứa> [<refspec>…]]" +msgstr "git pull [<các tùy chá»n>] [<kho-chứa> [<refspec>...]]" msgid "control for recursive fetching of submodules" msgstr "Ä‘iá»u khiển việc lấy vỠđệ quy của các mô-Ä‘un-con" @@ -9164,6 +9399,12 @@ msgstr "ép buá»™c ghi đè lên nhánh ná»™i bá»™" msgid "number of submodules pulled in parallel" msgstr "số lượng mô-Ä‘un-con được đẩy lên đồng thá»i" +msgid "use IPv4 addresses only" +msgstr "chỉ dùng địa chỉ IPv4" + +msgid "use IPv6 addresses only" +msgstr "chỉ dùng địa chỉ IPv6" + msgid "" "There is no candidate for rebasing against among the refs that you just " "fetched." @@ -9181,9 +9422,9 @@ msgid "" "Generally this means that you provided a wildcard refspec which had no\n" "matches on the remote end." msgstr "" -"Äại thể Ä‘iá»u nà y có nghÄ©a là bạn đã cung cấp đặc tả Ä‘Æ°á»ng dẫn dạng dùng ký " +"Äại khái Ä‘iá»u nà y có nghÄ©a là bạn đã cung cấp đặc tả Ä‘Æ°á»ng dẫn dạng dùng ký " "tá»±\n" -"đại diện mà nó lại không khá»›p trên Ä‘iểm cuối máy phục vụ." +"đại diện mà nó lại không khá»›p trên Ä‘iểm cuối máy chủ." #, c-format msgid "" @@ -9191,16 +9432,16 @@ msgid "" "a branch. Because this is not the default configured remote\n" "for your current branch, you must specify a branch on the command line." msgstr "" -"Bạn yêu cầu pull từ máy dịch vụ “%sâ€, nhÆ°ng lại chÆ°a chỉ định\n" -"nhánh nà o. Bởi vì đây không phải là máy dịch vụ được cấu hình\n" -"theo mặc định cho nhánh hiện tại của bạn, bạn phải chỉ định\n" +"Bạn yêu cầu pull từ máy dịch vụ '%s', nhÆ°ng lại chÆ°a chỉ định\n" +"nhánh nà o. Bởi vì đây không phải là máy chủ được cấu hình\n" +"mặc định cho nhánh hiện tại của bạn, bạn phải chỉ định\n" "má»™t nhánh trên dòng lệnh." msgid "You are not currently on a branch." -msgstr "Hiện tại bạn chẳng ở nhánh nà o cả." +msgstr "Hiện tại bạn Ä‘ang không ở trên nhánh nà o." msgid "Please specify which branch you want to rebase against." -msgstr "Vui lòng chỉ định nhánh nà o bạn muốn cải tổ lại." +msgstr "Vui lòng chỉ định nhánh bạn muốn cải tổ lại." msgid "Please specify which branch you want to merge with." msgstr "Vui lòng chỉ định nhánh nà o bạn muốn hòa trá»™n và o." @@ -9220,22 +9461,23 @@ msgstr "Ở đây không có thông tin theo dõi cho nhánh hiện hà nh." msgid "" "If you wish to set tracking information for this branch you can do so with:" msgstr "" -"Nếu bạn muốn theo dõi thông tin cho nhánh nà y bạn có thể thá»±c hiện bằng lệnh:" +"Nếu bạn muốn thiết láºp thông tin theo dõi cho nhánh nà y bạn có thể thá»±c hiện " +"bằng lệnh:" #, c-format msgid "" "Your configuration specifies to merge with the ref '%s'\n" "from the remote, but no such ref was fetched." msgstr "" -"Các đặc tả cấu hình của bạn để hòa trá»™n vá»›i tham chiếu “%sâ€\n" -"từ máy dịch vụ, nhÆ°ng không có nhánh nà o nhÆ° thế được lấy vá»." +"Cấu hình của bạn nói cần hòa trá»™n vá»›i tham chiếu '%s'\n" +"từ máy dịch vụ, nhÆ°ng không có tham chiếu nà o nhÆ° thế được lấy vá»." #, c-format msgid "unable to access commit %s" -msgstr "không thể truy cáºp lần chuyển giao “%sâ€" +msgstr "không thể truy cáºp lần chuyển giao '%s'" msgid "ignoring --verify-signatures for rebase" -msgstr "bá» qua --verify-signatures khi rebase" +msgstr "bá» qua --verify-signatures khi cải tổ" msgid "" "You have divergent branches and need to specify how to reconcile them.\n" @@ -9252,31 +9494,30 @@ msgid "" "or --ff-only on the command line to override the configured default per\n" "invocation.\n" msgstr "" -"Bạn có các nhánh phân kỳ và cần chỉ định cách hòa hợp chúng.\n" -"Bạn có thể là m nhÆ° váºy bằng cách chạy má»™t trong những lệnh sau đây\n" -"thỉnh thoảng trÆ°á»›c khi thá»±c hiện lệnh pull tiếp theo của bạn:\n" +"Bạn có các nhánh phân kỳ và cần chỉ định cách hợp nhất chúng.\n" +"Bạn có thể là m váºy bằng cách chạy má»™t trong những lệnh sau đây\n" +"trÆ°á»›c khi thá»±c hiện lệnh pull tiếp theo của bạn:\n" "\n" -" git config pull.rebase false # merge\n" -" git config pull.rebase true # rebase\n" -" git config pull.ff only # chỉ fast-forward\n" +" git config pull.rebase false # hợp nhất\n" +" git config pull.rebase true # cải tổ\n" +" git config pull.ff only # chỉ chuyển tiếp nhanh\n" "\n" "Bạn có thể thay thế \"git config\" vá»›i \"git config --global\" để thiết láºp " "mặc định\n" -"Æ°u tiên cho tất cả các kho. Bạn cÅ©ng có thể chuyển qua --rebase, --no-" -"rebase,\n" -"hoặc --ff-only trên dòng lệnh để ghi đè các mặc định đã cấu hình cho má»—i\n" +"Æ°u tiên cho tất cả các kho. Bạn cÅ©ng có thể chỉ định --rebase, --no-rebase,\n" +"hoặc --ff-only trên dòng lệnh để ghi đè cấu hình mặc định cho từng\n" "lần gá»i.\n" msgid "Updating an unborn branch with changes added to the index." msgstr "" -"Äang cáºp nháºt má»™t nhánh chÆ°a được sinh ra vá»›i các thay đổi được thêm và o " -"bảng mục lục." +"Äang cáºp nháºt má»™t nhánh chÆ°a được sinh ra từ các thay đổi được thêm và o mục " +"lục." msgid "pull with rebase" msgstr "pull vá»›i rebase" -msgid "please commit or stash them." -msgstr "xin hãy chuyển giao hoặc tạm cất (stash) chúng." +msgid "Please commit or stash them." +msgstr "Xin hãy chuyển giao hoặc tạm cất chúng." #, c-format msgid "" @@ -9286,7 +9527,7 @@ msgid "" msgstr "" "fetch đã cáºp nháºt head nhánh hiện tại.\n" "Ä‘ang chuyển-tiếp-nhanh cây là m việc của bạn từ\n" -"lần chuyển giaot %s." +"lần chuyển giao %s." #, c-format msgid "" @@ -9299,30 +9540,29 @@ msgid "" msgstr "" "Không thể chuyển tiếp nhanh cây là m việc của bạn.\n" "Sau khi chắc chắn rằng mình đã ghi lại má»i thứ\n" -"quý báu từ kết xuất của lệnh\n" +"quan trá»ng từ đầu ra của lệnh\n" "$ git diff %s\n" "chạy\n" "$ git reset --hard\n" -"để khôi phục lại." +"để khôi phục." msgid "Cannot merge multiple branches into empty head." -msgstr "Không thể hòa trá»™n nhiá»u nhánh và o trong má»™t head trống rá»—ng." +msgstr "Không thể hòa trá»™n nhiá»u nhánh và o má»™t head trống rá»—ng." msgid "Cannot rebase onto multiple branches." -msgstr "Không thể thá»±c hiện lệnh rebase (cải tổ) trên nhiá»u nhánh." +msgstr "Không thể thá»±c hiện lệnh cải tổ trên nhiá»u nhánh." msgid "Cannot fast-forward to multiple branches." msgstr "Không thể thá»±c hiện chuyển tiếp nhanh trên nhiá»u nhánh." msgid "Need to specify how to reconcile divergent branches." -msgstr "Caanfchir định là m thế nà o để giải quyết các nhánh phân kỳ." +msgstr "Cần chỉ định là m thế nà o để giải quyết các nhánh phân kỳ." msgid "cannot rebase with locally recorded submodule modifications" -msgstr "" -"không thể cải tổ vá»›i các thay đổi mô-Ä‘un-con được ghi lại má»™t cách cục bá»™" +msgstr "không thể cải tổ vá»›i các thay đổi submodule cục bá»™" msgid "git push [<options>] [<repository> [<refspec>...]]" -msgstr "git push [<các tùy chá»n>] [<kho-chứa> [<refspec>…]]" +msgstr "git push [<các tùy chá»n>] [<kho-chứa> [<refspec>...]]" msgid "tag shorthand without <tag>" msgstr "dùng tốc ký thẻ không có <thẻ>" @@ -9335,14 +9575,13 @@ msgid "" "To choose either option permanently, see push.default in 'git help config'.\n" msgstr "" "\n" -"Äể chá»n má»—i tùy chá»n má»™t cách cố định, xem push.default trong “git help " -"configâ€.\n" +"Äể chá»n má»—i tùy chá»n má»™t cách cố định, xem push.default trong 'git help " +"config'.\n" msgid "" "\n" -"To avoid automatically configuring upstream branches when their name\n" -"doesn't match the local branch, see option 'simple' of branch." -"autoSetupMerge\n" +"To avoid automatically configuring an upstream branch when its name\n" +"won't match the local branch, see option 'simple' of branch.autoSetupMerge\n" "in 'git help config'.\n" msgstr "" "\n" @@ -9407,8 +9646,7 @@ msgid "" "%s" msgstr "" "Nhánh hiện tại %s không có nhánh thượng nguồn nà o.\n" -"Äể push (đẩy lên) nhánh hiện tại và đặt máy chủ nà y là m thượng nguồn " -"(upstream), sá» dụng\n" +"Äể đẩy lên nhánh hiện tại và đặt máy chủ nà y là m thượng nguồn, sá» dụng\n" "\n" " git push --set-upstream %s %s\n" "%s" @@ -9420,8 +9658,8 @@ msgstr "Nhánh hiện tại %s có nhiá»u nhánh thượng nguồn, từ chối msgid "" "You didn't specify any refspecs to push, and push.default is \"nothing\"." msgstr "" -"Bạn đã không chỉ ra má»™t refspecs nà o để đẩy lên, và push.default là \"không " -"là gì cả\"." +"Bạn đã không chỉ ra má»™t refspecs nà o để đẩy lên, và push.default " +"là \"nothing\"." #, c-format msgid "" @@ -9429,48 +9667,46 @@ msgid "" "your current branch '%s', without telling me what to push\n" "to update which remote branch." msgstr "" -"Bạn Ä‘ang push (đẩy lên) máy chủ “%sâ€, mà nó không phải là thượng nguồn " -"(upstream) của\n" -"nhánh hiện tại “%s†của bạn, mà không báo cho tôi biết là cái gì được push\n" -"để cáºp nháºt nhánh máy chủ nà o." +"Bạn Ä‘ang đẩy lên máy chủ '%s', không phải là thượng nguồn của\n" +"nhánh hiện tại '%s' của bạn, mà không báo cho tôi biết là cần đẩy lên\n" +"nhánh nà o để cáºp nháºt nhánh nà o." msgid "" "Updates were rejected because the tip of your current branch is behind\n" -"its remote counterpart. Integrate the remote changes (e.g.\n" -"'git pull ...') before pushing again.\n" +"its remote counterpart. If you want to integrate the remote changes,\n" +"use 'git pull' before pushing again.\n" "See the 'Note about fast-forwards' in 'git push --help' for details." msgstr "" -"Việc cáºp nháºt bị từ chối bởi vì đầu mút của nhánh hiện tại của bạn nằm đằng\n" -"sau bá»™ pháºn tÆ°Æ¡ng ứng của máy chủ. Hòa trá»™n vá»›i các thay đổi từ máy chủ\n" -"(v.d. \"git pull …\") trÆ°á»›c khi đẩy lên lần nữa.\n" -"Xem “Note about fast-forwards†trong “git push --help†để có thông tin chi " +"Việc cáºp nháºt bị từ chối bởi vì đỉnh của nhánh hiện tại của bạn đứng sau\n" +"nhánh tÆ°Æ¡ng ứng của máy chủ. Nếu bạn cần hòa trá»™n vá»›i các thay đổi từ\n" +"máy chủ, hãy chạy 'git pull' trÆ°á»›c khi đẩy lên.\n" +"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi " "tiết." msgid "" "Updates were rejected because a pushed branch tip is behind its remote\n" -"counterpart. Check out this branch and integrate the remote changes\n" -"(e.g. 'git pull ...') before pushing again.\n" +"counterpart. If you want to integrate the remote changes, use 'git pull'\n" +"before pushing again.\n" "See the 'Note about fast-forwards' in 'git push --help' for details." msgstr "" -"Việc cáºp nháºt bị từ chối bởi vì đầu mút của nhánh đã đẩy lên nằm đằng sau " -"bá»™\n" -"pháºn tÆ°Æ¡ng ứng của máy chủ. Checkou nhánh nà y và hòa trá»™n vá»›i các thay đổi\n" -"từ máy chủ (v.d. “git pull …â€) trÆ°á»›c khi lại push lần nữa.\n" -"Xem “Note about fast-forwards†trong “git push --help†để có thông tin chi " +"Việc cáºp nháºt bị từ chối bởi vì đỉnh của nhánh đã đẩy lên đứng sau\n" +"nhánh tÆ°Æ¡ng ứng của máy chủ. Nếu bạn cần hòa trá»™n vá»›i các thay đổi từ\n" +"máy chủ, hãy chạy 'git pull' trÆ°á»›c khi đẩy lên.\n" +"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi " "tiết." msgid "" -"Updates were rejected because the remote contains work that you do\n" -"not have locally. This is usually caused by another repository pushing\n" -"to the same ref. You may want to first integrate the remote changes\n" -"(e.g., 'git pull ...') before pushing again.\n" +"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" +"the same ref. If you want to integrate the remote changes, use\n" +"'git pull' before pushing again.\n" "See the 'Note about fast-forwards' in 'git push --help' for details." msgstr "" -"Việc cáºp nháºt bị từ chối bởi vì máy chủ có chứa công việc mà bạn không\n" -"có ở máy ná»™i bá»™ của mình. Lá»—i nà y thÆ°á»ng có nguyên nhân bởi kho khác đẩy\n" -"dữ liệu lên cùng má»™t tham chiếu. Bạn có lẽ muốn hòa trá»™n vá»›i các thay đổi\n" -"từ máy chủ (v.d. “git pull…â€) trÆ°á»›c khi lại push lần nữa.\n" -"Xem “Note about fast-forwards†trong “git push --help†để có thông tin chi " +"Việc cáºp nháºt bị từ chối bởi vì máy chủ có chứa thay đổi mà bạn không\n" +"có ở nhánh của mình. Lá»—i nà y thÆ°á»ng xảy ra khi kho khác đẩy dữ liệu\n" +"lên cùng má»™t tham chiếu. Nếu bạn cần hòa trá»™n vá»›i các thay đổi từ\n" +"máy chủ, hãy chạy 'git pull' trÆ°á»›c khi đẩy lên.\n" +"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi " "tiết." msgid "Updates were rejected because the tag already exists in the remote." @@ -9481,22 +9717,22 @@ msgid "" "or update a remote ref to make it point at a non-commit object,\n" "without using the '--force' option.\n" msgstr "" -"Không thể cáºp nháºt má»™t tham chiếu trên máy chủ mà nó chỉ đến đối tượng " -"không\n" -"phải là lần chuyển giao, hoặc cáºp nháºt má»™t tham chiếu máy chủ để nó chỉ đến " -"đối tượng\n" -"không phải chuyển giao, mà không sá» dụng tùy chá»n “--forceâ€.\n" +"Không thể cáºp nháºt tham chiếu trên máy chủ Ä‘ang chỉ đến đối tượng không\n" +"phải là lần chuyển giao, hoặc cáºp nháºt tham chiếu trên máy chủ để nó\n" +"chỉ đến đối tượng không phải lần chuyển giao, mà không sá» dụng\n" +"tùy chá»n '--force'.\n" msgid "" -"Updates were rejected because the tip of the remote-tracking\n" -"branch has been updated since the last checkout. You may want\n" -"to integrate those changes locally (e.g., 'git pull ...')\n" -"before forcing an update.\n" +"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" +"remote changes, use 'git pull' before pushing again.\n" +"See the 'Note about fast-forwards' in 'git push --help' for details." msgstr "" -"Việc cáºp nháºt bị từ chối bởi vì đầu mút của nhánh theo dõi máy chủ\n" -"đã được cáºp nháºt kể từ sau lần lấy ra cuối cùng. Bạn có lẽ muốn\n" -"tÃch hợp các thay đổi nà y má»™t cách cục bá»™ (v.d. \"git pull …\")\n" -"trÆ°á»›c khi ép buá»™c má»™t cáºp nháºt.\n" +"Việc cáºp nháºt bị từ chối bởi vì đỉnh của nhánh theo dõi máy chủ đã được\n" +"cáºp nháºt sau lần checkout trÆ°á»›c. Nếu bạn cần hòa trá»™n vá»›i các thay đổi từ\n" +"máy chủ, hãy chạy 'git pull' trÆ°á»›c khi đẩy lên.\n" +"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi " +"tiết." #, c-format msgid "Pushing to %s\n" @@ -9504,7 +9740,13 @@ msgstr "Äang đẩy lên %s\n" #, c-format msgid "failed to push some refs to '%s'" -msgstr "gặp lá»—i khi đẩy tá»›i má»™t số tham chiếu đến “%sâ€" +msgstr "gặp lá»—i khi đẩy tá»›i má»™t số tham chiếu đến '%s'" + +msgid "" +"recursing into submodule with push.recurseSubmodules=only; using on-demand " +"instead" +msgstr "" +"đệ quy và o mô-Ä‘un con vá»›i push.recurseSubmodules=only; thay bằng on-demand" #, c-format msgid "invalid value for '%s'" @@ -9513,17 +9755,17 @@ msgstr "giá trị cho '%s' không hợp lệ" msgid "repository" msgstr "kho" -msgid "push all refs" -msgstr "đẩy tất cả các tham chiếu" +msgid "push all branches" +msgstr "đẩy tất cả các nhánh" msgid "mirror all refs" -msgstr "mirror tất cả các tham chiếu" +msgstr "sao tất cả các tham chiếu" msgid "delete refs" msgstr "xóa các tham chiếu" -msgid "push tags (can't be used with --all or --mirror)" -msgstr "đẩy các thẻ (không dùng cùng vá»›i --all hay --mirror)" +msgid "push tags (can't be used with --all or --branches or --mirror)" +msgstr "đẩy các thẻ (không dùng cùng vá»›i --all hay --branches hay --mirror)" msgid "force updates" msgstr "ép buá»™c cáºp nháºt" @@ -9538,7 +9780,7 @@ msgid "require remote updates to be integrated locally" msgstr "yêu cầu máy chủ cáºp nháºt để thÃch hợp vá»›i máy cục bá»™" msgid "control recursive pushing of submodules" -msgstr "Ä‘iá»u khiển việc đẩy lên (push) đệ qui của mô-Ä‘un-con" +msgstr "Ä‘iá»u khiển việc đẩy lên (push) đệ quy của mô-Ä‘un-con" msgid "use thin pack" msgstr "tạo gói nhẹ" @@ -9569,7 +9811,7 @@ msgstr "--delete không hợp lý nếu không có bất kỳ tham chiếu nà o" #, c-format msgid "bad repository '%s'" -msgstr "repository (kho) sai “%sâ€" +msgstr "repository (kho) sai '%s'" msgid "" "No configured push destination.\n" @@ -9605,7 +9847,7 @@ msgstr "" "git range-diff [<các tùy chá»n>] <old-base>..<old-tip> <new-base>..<new-tip>" msgid "git range-diff [<options>] <old-tip>...<new-tip>" -msgstr "git range-diff [<các tùy chá»n>] <old-tip>…<new-tip>" +msgstr "git range-diff [<các tùy chá»n>] <old-tip>...<new-tip>" msgid "git range-diff [<options>] <base> <old-tip> <new-tip>" msgstr "git range-diff [<các tùy chá»n>] <base> <old-tip> <new-tip>" @@ -9617,7 +9859,7 @@ msgid "notes" msgstr "ghi chú" msgid "passed to 'git log'" -msgstr "chuyển cho “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" @@ -9626,29 +9868,36 @@ 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" #, c-format +msgid "not a revision: '%s'" +msgstr "không phải má»™t revision '%s'" + +#, c-format msgid "not a commit range: '%s'" -msgstr "không phải là vùng chuyển giao: “%sâ€" +msgstr "không phải là vùng chuyển giao: '%s'" -msgid "single arg format must be symmetric range" -msgstr "định dạng đối số Ä‘Æ¡n phải là má»™t vùng đối xứng" +#, c-format +msgid "not a symmetric range: '%s'" +msgstr "không phải là vùng tÆ°Æ¡ng xứng: '%s'" msgid "need two commit ranges" -msgstr "cần hai vùng lần chuyển giao" +msgstr "cần hai vùng chuyển giao" msgid "" -"git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>) " -"[-u | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-" -"ish1> [<tree-ish2> [<tree-ish3>]])" -msgstr "" "git read-tree [(-m [--trivial] [--aggressive] | --reset | --" -"prefix=<tiá»n_tố>) [-u | -i]] [--no-sparse-checkout] [--index-" -"output=<táºp_tin>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])" +"prefix=<prefix>)\n" +" [-u | -i]] [--index-output=<file>] [--no-sparse-checkout]\n" +" (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])" +msgstr "" +"git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<tiá»n " +"tố>)\n" +" [-u | -i]] [--index-output=<táºp tin>] [--no-sparse-checkout]\n" +" (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])" msgid "write resulting index to <file>" -msgstr "ghi mục lục kết quả và o <táºp-tin>" +msgstr "ghi chỉ mục kết quả và o <táºp-tin>" msgid "only empty the index" -msgstr "chỉ vá»›i bảng mục lục trống rá»—ng" +msgstr "chỉ vá»›i chỉ mục trống rá»—ng" msgid "Merging" msgstr "Hòa trá»™n" @@ -9658,10 +9907,10 @@ msgstr "thá»±c hiện má»™t hòa trá»™n thêm và o việc Ä‘á»c" msgid "3-way merge if no file level merging required" msgstr "" -"hòa trá»™n kiểu “3-way†nếu không có táºp tin mức hòa trá»™n nà o được yêu cầu" +"hòa trá»™n kiểu '3-way' nếu không có táºp tin mức hòa trá»™n nà o được yêu cầu" msgid "3-way merge in presence of adds and removes" -msgstr "hòa trá»™n 3-way trong sá»± hiện diện của “adds†và “removesâ€" +msgstr "hòa trá»™n 3-way trong sá»± hiện diện của 'adds' và 'removes'" msgid "same as -m, but discard unmerged entries" msgstr "giống vá»›i -m, nhÆ°ng bá» qua các mục chÆ°a được hòa trá»™n" @@ -9670,7 +9919,7 @@ msgid "<subdirectory>/" msgstr "<thÆ°-mục-con>/" msgid "read the tree into the index under <subdirectory>/" -msgstr "Ä‘á»c cây và o trong bảng mục lục dÆ°á»›i <thÆ°_mục_con>/" +msgstr "Ä‘á»c cây và o trong chỉ mục dÆ°á»›i <thÆ°_mục_con>/" msgid "update working tree with merge result" msgstr "cáºp nháºt cây là m việc vá»›i kết quả hòa trá»™n" @@ -9679,25 +9928,25 @@ msgid "gitignore" msgstr "gitignore" msgid "allow explicitly ignored files to be overwritten" -msgstr "cho phép các táºp tin rõ rà ng bị lá» Ä‘i được ghi đè" +msgstr "cho phép các táºp tin rõ rà ng bị bá» qua được ghi đè" msgid "don't check the working tree after merging" msgstr "không kiểm tra cây là m việc sau hòa trá»™n" msgid "don't update the index or the work tree" -msgstr "không cáºp nháºt bảng mục lục hay cây là m việc" +msgstr "không cáºp nháºt chỉ mục hay cây là m việc" msgid "skip applying sparse checkout filter" -msgstr "bá» qua áp dụng bá»™ lá»c lấy ra (checkout) thÆ°a thá»›t" +msgstr "bá» qua áp dụng bá»™ lá»c sparse checkout (checkout thÆ°a)" msgid "debug unpack-trees" -msgstr "gỡ lá»—i “unpack-treesâ€" +msgstr "gỡ lá»—i 'unpack-trees'" msgid "suppress feedback messages" msgstr "không xuất các thông tin phản hồi" msgid "You need to resolve your current index first" -msgstr "Bạn cần phải giải quyết bảng mục lục hiện tại của bạn trÆ°á»›c đã" +msgstr "Bạn cần phải giải quyết chỉ mục hiện tại của bạn trÆ°á»›c đã" msgid "" "git rebase [-i] [options] [--exec <cmd>] [--onto <newbase> | --keep-base] " @@ -9714,7 +9963,7 @@ msgstr "" #, c-format msgid "could not read '%s'." -msgstr "không thể Ä‘á»c “%sâ€." +msgstr "không thể Ä‘á»c '%s'." #, c-format msgid "could not create temporary %s" @@ -9734,34 +9983,20 @@ msgid "%s requires the merge backend" msgstr "%s cần má»™t ứng dụng hòa trá»™n chạy phÃa sau" #, c-format -msgid "could not get 'onto': '%s'" -msgstr "không thể đặt lấy “ontoâ€: “%sâ€" +msgid "invalid onto: '%s'" +msgstr "onto không hợp lệ: '%s'" #, c-format msgid "invalid orig-head: '%s'" -msgstr "orig-head không hợp lệ: “%sâ€" +msgstr "orig-head không hợp lệ: '%s'" #, c-format msgid "ignoring invalid allow_rerere_autoupdate: '%s'" -msgstr "Ä‘ang bá» qua allow_rerere_autoupdate không hợp lệ: “%sâ€" +msgstr "Ä‘ang bá» qua allow_rerere_autoupdate không hợp lệ: '%s'" #, c-format msgid "could not remove '%s'" -msgstr "không thể gỡ bỠ“%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 "" -"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" -"Bạn có thể bá» qua miếng vá, chạy \"git rebase --skip\".\n" -"Äể bãi bá» và quay trở lại trạng thái trÆ°á»›c \"git rebase\", chạy \"git rebase " -"--abort\"." +msgstr "không thể gỡ bá» '%s'" #, c-format msgid "" @@ -9774,24 +10009,44 @@ msgid "" "As a result, git cannot rebase them." msgstr "" "\n" -"git chạm trán má»™t lá»—i trong khi Ä‘ang chuẩn bị các miếng vá để diá»…n lại\n" +"git gặp phải má»™t lá»—i trong khi Ä‘ang chuẩn bị các bản vá để diá»…n lại\n" "những Ä‘iểm xét duyệt nà y:\n" "\n" " %s\n" "\n" -"Kết quả là git không thể cải tổ lại chúng." +"Kết quả là , git không thể cải tổ lại chúng." + +#, c-format +msgid "Unknown rebase-merges mode: %s" +msgstr "Không hiểu chế Ä‘á»™ cải tổ: %s" #, c-format msgid "could not switch to %s" msgstr "không thể chuyển đến %s" +msgid "apply options and merge options cannot be used together" +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'." + #, c-format msgid "" -"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask" -"\"." +"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " +"\"stop\"." msgstr "" -"kiểu rá»—ng không được nháºn dạng “%sâ€; giá trị hợp lệ là \"drop\", \"keep\", " -"và \"ask\"." +"kiểu rá»—ng không được nháºn dạng '%s'; giá trị hợp lệ là \"drop\", \"keep\", " +"và \"stop\"." + +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 " +"instead, which does the same thing." +msgstr "" +"--rebase-merges vá»›i tham số xâu rá»—ng được coi là lá»—i thá»i và sẽ không còn " +"hoạt Ä‘á»™ng trong Git tÆ°Æ¡ng lai. Thay và o đó dùng --rebase-merges không có " +"tham số, cho kết quả nhÆ° nhau." #, c-format msgid "" @@ -9803,10 +10058,10 @@ msgid "" "\n" msgstr "" "%s\n" -"Vui lòng chỉ định nhánh nà o bạn muốn cải tổ dá»±a và o.\n" +"Vui lòng chỉ định nhánh nà o bạn muốn cải tổ lên.\n" "Xem git-rebase(1) để biết thêm chi tiết.\n" "\n" -" git rebase “<nhánh>â€\n" +" git rebase '<nhánh>'\n" "\n" #, c-format @@ -9816,7 +10071,7 @@ msgid "" " git branch --set-upstream-to=%s/<branch> %s\n" "\n" msgstr "" -"Nếu bạn muốn theo dõi thông tin cho nhánh nà y bạn có thể thá»±c hiện bằng " +"Nếu bạn muốn đặt thông tin theo dõi cho nhánh nà y bạn có thể thá»±c hiện bằng " "lệnh:\n" "\n" " git branch --set-upstream-to=%s/<nhánh> %s\n" @@ -9832,17 +10087,16 @@ msgid "rebase onto given branch instead of upstream" msgstr "cải tổ và o nhánh đã cho thay cho thượng nguồn" msgid "use the merge-base of upstream and branch as the current base" -msgstr "" -"sá» dụng các cÆ¡ sở hòa trá»™n của thượng nguồn và nhánh nhÆ° là cÆ¡ sở hiện tại" +msgstr "sá» dụng gốc hòa trá»™n của thượng nguồn và nhánh là m gốc hiện tại" msgid "allow pre-rebase hook to run" msgstr "cho phép móc (hook) pre-rebase được chạy" msgid "be quiet. implies --no-stat" -msgstr "hãy im lặng. ý là --no-stat" +msgstr "im lặng. ngụ ý --no-stat" msgid "display a diffstat of what changed upstream" -msgstr "hiển thị má»™t diffstat của những thay đổi thượng nguồn" +msgstr "hiển thị diffstat của những thay đổi thượng nguồn" msgid "do not show diffstat of what changed upstream" msgstr "đừng hiển thị diffstat của những thay đổi thượng nguồn" @@ -9860,10 +10114,10 @@ msgid "synonym of --reset-author-date" msgstr "đồng nghÄ©a vá»›i --reset-author-date" msgid "passed to 'git apply'" -msgstr "chuyển cho “git applyâ€" +msgstr "chuyển cho 'git apply'" msgid "ignore changes in whitespace" -msgstr "lá» Ä‘i sá»± thay đổi do khoảng trắng gây ra" +msgstr "bá» qua sá»± thay đổi do khoảng trắng gây ra" msgid "cherry-pick all commits, even if unchanged" msgstr "" @@ -9873,19 +10127,19 @@ msgid "continue" msgstr "tiếp tục" msgid "skip current patch and continue" -msgstr "bá» qua miếng vá hiện hà nh và tiếp tục" +msgstr "bá» qua bản vá hiện hà nh và tiếp tục" msgid "abort and check out the original branch" -msgstr "bãi bá» và lấy ra nhánh nguyên thủy" +msgstr "huá»· bá» và checkout nhánh gốc" msgid "abort but keep HEAD where it is" -msgstr "bãi bá» nhÆ°ng vẫn vẫn giữ HEAD chỉ đến nó" +msgstr "huá»· bá» nhÆ°ng vẫn vẫn giữ nguyên HEAD" msgid "edit the todo list during an interactive rebase" -msgstr "sá»a danh sách cần là m trong quá trình “rebase†(cải tổ) tÆ°Æ¡ng tác" +msgstr "sá»a danh sách cần là m trong quá trình 'rebase' (cải tổ) tÆ°Æ¡ng tác" msgid "show the patch file being applied or merged" -msgstr "hiển thị miếng vá đã được áp dụng hay hòa trá»™n" +msgstr "hiển thị bản vá đã được áp dụng hay hòa trá»™n" msgid "use apply strategies to rebase" msgstr "dùng chiến lược áp dụng để cải tổ" @@ -9908,6 +10162,9 @@ msgstr "bá» qua các lần chuyển giao mà nó bắt đầu trống rá»—ng" msgid "move commits that begin with squash!/fixup! under -i" msgstr "di chuyển các lần chuyển giao mà bắt đầu bằng squash!/fixup! dÆ°á»›i -i" +msgid "update branches that point to commits that are being rebased" +msgstr "cáºp nháºt các nhánh trỠđến commit Ä‘ang được cải tổ" + msgid "add exec lines after each commit of the editable list" msgstr "thêm các dòng thá»±c thi sau từng lần chuyển giao của danh sách sá»a được" @@ -9918,7 +10175,7 @@ msgid "try to rebase merges instead of skipping them" msgstr "cố thá» cải tổ các hòa trá»™n thay vì bá» qua chúng" msgid "use 'merge-base --fork-point' to refine upstream" -msgstr "dùng “merge-base --fork-point†để định nghÄ©a lại thượng nguồn" +msgstr "dùng 'merge-base --fork-point' để định nghÄ©a lại thượng nguồn" msgid "use the given merge strategy" msgstr "dùng chiến lược hòa trá»™n đã cho" @@ -9933,7 +10190,7 @@ msgid "rebase all reachable commits up to the root(s)" msgstr "cải tổ tất các các lần chuyển giao cho đến root" msgid "automatically re-schedule any `exec` that fails" -msgstr "láºp lịch lại má»™t cách tá»± Ä‘á»™ng bất kỳ “exec“ bị lá»—i" +msgstr "láºp lịch lại má»™t cách tá»± Ä‘á»™ng bất kỳ 'exec' bị lá»—i" msgid "apply all changes, even those already present upstream" msgstr "" @@ -9941,7 +10198,7 @@ msgstr "" msgid "It looks like 'git am' is in progress. Cannot rebase." msgstr "" -"Hình nhÆ° Ä‘ang trong quá trình thá»±c hiện lệnh “git amâ€. Không thể rebase." +"Hình nhÆ° Ä‘ang trong quá trình thá»±c hiện lệnh 'git am'. Không thể rebase." msgid "" "`rebase --preserve-merges` (-p) is no longer supported.\n" @@ -9949,7 +10206,7 @@ msgid "" "Or downgrade to v2.33, or earlier, to complete the rebase." msgstr "" "`rebase --preserve-merges` (-p) không còn được há»— trợ nữa.\n" -"Dùng `git rebase --abort` để chấm dứt việc cải tổ hiện tại.\n" +"Dùng `git rebase --abort` để kết thúc việc cải tổ hiện tại.\n" "Hoặc là hạ phiên bản phần má»m xuống v2.33,\n" "hoặc trÆ°á»›c nữa, để hoà n thà nh việc cải tổ." @@ -9963,12 +10220,12 @@ msgstr "" "'preserve',\n" "cái mà giá» không còn được há»— trợ nữa; dùng 'merges' để thay thế" -msgid "No rebase in progress?" -msgstr "Không có tiến trình rebase nà o phải không?" +msgid "no rebase in progress" +msgstr "không có cải tổ Ä‘ang được thá»±c hiện" msgid "The --edit-todo action can only be used during interactive rebase." msgstr "" -"Hà nh Ä‘á»™ng “--edit-todo†chỉ có thể dùng trong quá trình “rebase†(sá»a lịch " +"Hà nh Ä‘á»™ng '--edit-todo' chỉ có thể dùng trong quá trình 'rebase' (sá»a lịch " "sá») tÆ°Æ¡ng tác." msgid "Cannot read HEAD" @@ -10000,67 +10257,67 @@ msgid "" "valuable there.\n" msgstr "" "Hình nhÆ° là ở đây sẵn có má»™t thÆ° mục %s, và \n" -"Tôi tá»± há»i có phải bạn Ä‘ang ở giữa má»™t lệnh rebase khác. Nếu đúng là \n" +"có lẽ bạn Ä‘ang ở giữa má»™t lệnh rebase khác. Nếu đúng là \n" "nhÆ° váºy, xin hãy thá»\n" "\t%s\n" "Nếu không phải thế, hãy thá»\n" "\t%s\n" -"và chạy TÔI lần nữa. TÔI dừng lại trong trÆ°á»ng hợp bạn vẫn\n" -"có má»™t số thứ quý giá ở đây.\n" +"và chạy TÔI lần nữa. TÔI sẽ dừng lại vì có khả năng bạn vẫn\n" +"còn má»™t số thứ quan trá»ng ở đây.\n" msgid "switch `C' expects a numerical value" -msgstr "tùy chá»n “%c†cần má»™t giá trị bằng số" - -#, c-format -msgid "Unknown mode: %s" -msgstr "Không hiểu chế Ä‘á»™: %s" +msgstr "tùy chá»n '%c' cần má»™t giá trị bằng số" -msgid "--strategy requires --merge or --interactive" -msgstr "--strategy cần --merge hay --interactive" +msgid "" +"apply options are incompatible with rebase.rebaseMerges. Consider adding --" +"no-rebase-merges" +msgstr "" +"tuỳ chá»n apply không tÆ°Æ¡ng thÃch vá»›i rebase.rebaseMerges. Cân nhắc dùng --no-" +"rebase-merges" -msgid "apply options and merge options cannot be used together" +msgid "" +"apply options are incompatible with rebase.updateRefs. Consider adding --no-" +"update-refs" 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" +"tuỳ chá»n apply không tÆ°Æ¡ng thÃch vá»›i rebase.updateRefs. Cân nhắc dùng --no-" +"update-refs" #, c-format msgid "Unknown rebase backend: %s" -msgstr "Không hiểu ứng dụng chạy phÃa sau lệnh cải tổ: %s" +msgstr "Không hiểu backend cải tổ: %s" msgid "--reschedule-failed-exec requires --exec or --interactive" msgstr "--reschedule-failed-exec cần --exec hay --interactive" #, c-format msgid "invalid upstream '%s'" -msgstr "thượng nguồn không hợp lệ “%sâ€" +msgstr "thượng nguồn không hợp lệ '%s'" msgid "Could not create new root commit" msgstr "Không thể tạo lần chuyển giao gốc má»›i" #, c-format msgid "no such branch/commit '%s'" -msgstr "không có nhánh/lần chuyển giao “%s†nhÆ° thế" +msgstr "không có nhánh/lần chuyển giao '%s' nhÆ° thế" #, c-format msgid "No such ref: %s" msgstr "Không có tham chiếu nà o nhÆ° thế: %s" -msgid "Could not resolve HEAD to a revision" -msgstr "Không thể phân giải lần chuyển giao HEAD đến má»™t Ä‘iểm xét duyệt" +msgid "Could not resolve HEAD to a commit" +msgstr "không thể phân giải HEAD thà nh tên lần chuyển giao" #, c-format msgid "'%s': need exactly one merge base with branch" -msgstr "“%sâ€: cần chÃnh xác má»™t cÆ¡ sở hòa trá»™n vá»›i nhánh" +msgstr "'%s': cần chÃnh xác má»™t gốc hòa trá»™n vá»›i nhánh" #, c-format msgid "'%s': need exactly one merge base" -msgstr "“%sâ€: cần chÃnh xác má»™t cÆ¡ sở hòa trá»™n" +msgstr "'%s': cần chÃnh xác má»™t gốc hòa trá»™n" #, c-format msgid "Does not point to a valid commit '%s'" -msgstr "Không chỉ đến má»™t lần chuyển giao không hợp lệ “%sâ€" - -msgid "Please commit or stash them." -msgstr "Xin hãy chuyển giao hoặc tạm cất (stash) chúng." +msgstr "Không chỉ đến má»™t lần chuyển giao không hợp lệ '%s'" msgid "HEAD is up to date." msgstr "HEAD đã cáºp nháºt." @@ -10090,7 +10347,7 @@ msgstr "Thay đổi từ %s thà nh %s:\n" #, c-format msgid "First, rewinding head to replay your work on top of it...\n" msgstr "" -"TrÆ°á»›c tiên, di chuyển head để xem lại các công việc trên đỉnh của nó…\n" +"TrÆ°á»›c tiên, di chuyển head để xem lại các công việc trên đỉnh của nó...\n" msgid "Could not detach HEAD" msgstr "Không thể tách rá»i HEAD" @@ -10117,19 +10374,19 @@ msgid "" "To squelch this message and still keep the default behaviour, set\n" "'receive.denyCurrentBranch' configuration variable to 'refuse'." msgstr "" -"Theo mặc định, việc cáºp nháºt nhánh hiện tại trong má»™t kho không-thuần\n" +"Theo mặc định, việc cáºp nháºt nhánh hiện tại trong má»™t kho không bare\n" "bị từ chối, bởi vì nó sẽ là m cho chỉ mục và cây là m việc mâu thuẫn vá»›i\n" -"cái mà bạn đẩy lên, và sẽ yêu cầu lệnh “git reset --hard†để mà là m\n" +"cái mà bạn đẩy lên, và sẽ yêu cầu lệnh 'git reset --hard' để là m\n" "cho cây là m việc khá»›p vá»›i HEAD.\n" "\n" -"Bạn có thể đặt biến cấu hình “receive.denyCurrentBranch†thà nh\n" -"“ignore†hay “warn†trong kho máy chủ để cho phép đẩy lên nhánh\n" +"Bạn có thể đặt biến cấu hình 'receive.denyCurrentBranch' thà nh\n" +"'ignore' hay 'warn' trong kho máy chủ để cho phép đẩy lên nhánh\n" "hiện tại của nó; tuy nhiên, không nên là m nhÆ° thế trừ phi bạn\n" "sắp đặt để cáºp nháºt cây là m việc của nó tÆ°Æ¡ng ứng vá»›i cái mà bạn đẩy\n" "lên theo cách nà o đó.\n" "\n" -"Äể chấm dứt lá»i nhắn nà y và vẫn giữ cách ứng xá» mặc định, hãy đặt\n" -"biến cấu hình “receive.denyCurrentBranch†thà nh “refuseâ€." +"Äể tắt lá»i nhắn nà y và vẫn giữ hà nh vi mặc định, hãy đặt\n" +"biến cấu hình 'receive.denyCurrentBranch' thà nh 'refuse'." msgid "" "By default, deleting the current branch is denied, because the next\n" @@ -10142,14 +10399,14 @@ msgid "" "To squelch this message, you can set it to 'refuse'." msgstr "" "Theo mặc định, việc cáºp xóa nhánh hiện tại bị từ chối, bởi vì\n" -"lệnh “git clone†tiếp theo sẽ không có tác dụng trong việc lấy\n" +"lệnh 'git clone' tiếp theo sẽ không có tác dụng trong việc lấy\n" "ra bất kỳ táºp tin nà o, dẫn đến há»—n loạn\n" "\n" -"Bạn có thể đặt biến cấu hình “receive.denyDeleteCurrent†thà nh\n" -"“warn†hay “ignore†trong kho máy chủ để cho phép đẩy xóa nhánh\n" +"Bạn có thể đặt biến cấu hình 'receive.denyDeleteCurrent' thà nh\n" +"'warn' hay 'ignore' trong kho máy chủ để cho phép đẩy xóa nhánh\n" "hiện tại của nó có hoặc không cảnh báo.\n" "\n" -"Äể chấm dứt lá»i nhắn nà y, bạn hãy đặt nó thà nh “refuseâ€." +"Äể tắt lá»i nhắn nà y, bạn hãy đặt nó thà nh 'refuse'." msgid "quiet" msgstr "im lặng" @@ -10160,6 +10417,9 @@ msgstr "bạn phải chỉ định thÆ° mục" msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<các tùy chá»n>] [<tham chiếu>]" +msgid "git reflog list" +msgstr "git reflog list" + msgid "" "git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" " [--rewrite] [--updateref] [--stale-fix]\n" @@ -10185,6 +10445,10 @@ msgstr "git reflog exists <tham_chiếu>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "dấu vết thá»i gian không hợp lệ '%s' Ä‘Æ°a cho '--%s'" +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s không nháºn các đối số: '%s'" + msgid "do not actually prune any entries" msgstr "thá»±c tế không cắt ngắn bất kỳ mục tin nà o" @@ -10222,7 +10486,7 @@ msgstr "giá»›i hạn xá» lý vá»›i reflogs chỉ từ thÆ° mục là m việc hi #, c-format msgid "Marking reachable objects..." -msgstr "Äánh dấu các đối tượng tiếp cáºn được…" +msgstr "Äánh dấu các đối tượng tiếp cáºn được..." #, c-format msgid "%s points nowhere!" @@ -10260,10 +10524,10 @@ msgstr "git remote prune [-n | --dry-run] <tên>" msgid "" "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]" msgstr "" -"git remote [-v | --verbose] update [-p | --prune] [(<nhóm> | <máy-chủ>)…]" +"git remote [-v | --verbose] update [-p | --prune] [(<nhóm> | <máy-chủ>)...]" msgid "git remote set-branches [--add] <name> <branch>..." -msgstr "git remote set-branches [--add] <tên> <nhánh>…" +msgstr "git remote set-branches [--add] <tên> <nhánh>..." msgid "git remote get-url [--push] [--all] <name>" msgstr "git remote set-url [--push] [--all] <tên>" @@ -10281,10 +10545,10 @@ msgid "git remote add [<options>] <name> <url>" msgstr "git remote add [<các tùy chá»n>] <tên> <url>" msgid "git remote set-branches <name> <branch>..." -msgstr "git remote set-branches <tên> <nhánh>…" +msgstr "git remote set-branches <tên> <nhánh>..." msgid "git remote set-branches --add <name> <branch>..." -msgstr "git remote set-branches --add <tên> <nhánh>…" +msgstr "git remote set-branches --add <tên> <nhánh>..." msgid "git remote show [<options>] <name>" msgstr "git remote show [<các tùy chá»n>] <tên>" @@ -10293,7 +10557,7 @@ msgid "git remote prune [<options>] <name>" msgstr "git remote prune [<các tùy chá»n>] <tên>" msgid "git remote update [<options>] [<group> | <remote>]..." -msgstr "git remote update [<các tùy chá»n>] [<nhóm> | <máy-chủ>]…" +msgstr "git remote update [<các tùy chá»n>] [<nhóm> | <máy-chủ>]..." #, c-format msgid "Updating %s" @@ -10301,27 +10565,28 @@ msgstr "Äang cáºp nháºt %s" #, c-format msgid "Could not fetch %s" -msgstr "Không thể lấy“%s†vá»" +msgstr "Không thể lấy'%s' vá»" msgid "" "--mirror is dangerous and deprecated; please\n" "\t use --mirror=fetch or --mirror=push instead" msgstr "" -"--mirror nguy hiểm và không dùng nữa; xin hãy\n" +"--mirror nguy hiểm và không được dùng nữa; xin hãy\n" "\t sá» dụng tùy chá»n --mirror=fetch hoặc --mirror=push để thay thế" #, c-format -msgid "unknown mirror argument: %s" -msgstr "không hiểu tham số máy bản sao (mirror): %s" +msgid "unknown --mirror argument: %s" +msgstr "không hiểu tham số --mirror: %s" msgid "fetch the remote branches" msgstr "lấy vá» các nhánh từ máy chủ" -msgid "import all tags and associated objects when fetching" -msgstr "nháºp và o tất cả các đối tượng thẻ và thà nh phần liên quan khi lấy vá»" - -msgid "or do not fetch any tag at all (--no-tags)" -msgstr "hoặc không lấy vá» bất kỳ thẻ nà o (--no-tags)" +msgid "" +"import all tags and associated objects when fetching\n" +"or do not fetch any tag at all (--no-tags)" +msgstr "" +"nháºp và o tất cả các thẻ và đối tượng liên quan khi lấy vá»\n" +"hoặc không nháºn vá» má»™t thẻ nà o cả (--no-tags)" msgid "branch(es) to track" msgstr "các nhánh để theo dõi" @@ -10336,7 +10601,7 @@ msgid "specifying a master branch makes no sense with --mirror" msgstr "Ä‘ang chỉ định má»™t nhánh master không hợp lý vá»›i tùy chá»n --mirror" msgid "specifying branches to track makes sense only with fetch mirrors" -msgstr "chỉ định những nhánh để theo dõi chỉ hợp lý vá»›i các “fetch mirrorâ€" +msgstr "chỉ định những nhánh để theo dõi chỉ hợp lý vá»›i các 'fetch mirror'" #, c-format msgid "remote %s already exists." @@ -10344,7 +10609,7 @@ msgstr "máy chủ %s đã tồn tại rồi." #, c-format msgid "Could not setup master '%s'" -msgstr "Không thể cà i đặt nhánh master “%sâ€" +msgstr "Không thể cà i đặt nhánh master '%s'" #, c-format msgid "more than one %s" @@ -10352,7 +10617,7 @@ msgstr "nhiá»u hÆ¡n má»™t %s" #, c-format msgid "unhandled branch.%s.rebase=%s; assuming 'true'" -msgstr "nhánh chÆ°a được quản lý.%s.rebase=%s; giả định là “trueâ€" +msgstr "nhánh chÆ°a được quản lý.%s.rebase=%s; giả định là 'true'" #, c-format msgid "Could not get fetch map for refspec %s" @@ -10366,11 +10631,11 @@ msgstr "(xóa)" #, c-format msgid "could not set '%s'" -msgstr "không thể đặt “%sâ€" +msgstr "không thể đặt '%s'" #, c-format msgid "could not unset '%s'" -msgstr "không thể thôi đặt “%sâ€" +msgstr "không thể thôi đặt '%s'" #, c-format msgid "" @@ -10380,15 +10645,15 @@ msgid "" msgstr "" "Cấu hình %s remote.pushDefault trong:\n" "\t%s:%d\n" -"bây giá» tên trên máy chủ không tồn tại “%sâ€" +"bây giá» tên trên máy chủ không tồn tại '%s'" #, c-format msgid "No such remote: '%s'" -msgstr "Không có máy chủ nà o nhÆ° váºy: “%sâ€" +msgstr "Không có máy chủ nà o nhÆ° váºy: '%s'" #, c-format msgid "Could not rename config section '%s' to '%s'" -msgstr "Không thể đổi tên phần của cấu hình từ “%s†thà nh “%sâ€" +msgstr "Không thể đổi tên phần của cấu hình từ '%s' thà nh '%s'" #, c-format msgid "" @@ -10396,20 +10661,20 @@ msgid "" "\t%s\n" "\tPlease update the configuration manually if necessary." msgstr "" -"Không cáºp nháºt “non-default fetch respecâ€\n" +"Không cáºp nháºt tham chiếu fetch không mặc định\n" "\t%s\n" -"\tXin hãy cáºp nháºt phần cấu hình má»™t cách thủ công nếu thấy cần thiết." +"\tXin hãy cáºp nháºt phần cấu hình má»™t cách thủ công nếu cần." msgid "Renaming remote references" msgstr "Äổi tên các tham chiếu máy chủ" #, c-format msgid "deleting '%s' failed" -msgstr "gặp lá»—i khi xóa “%sâ€" +msgstr "gặp lá»—i khi xóa '%s'" #, c-format msgid "creating '%s' failed" -msgstr "gặp lá»—i khi tạo “%sâ€" +msgstr "gặp lá»—i khi tạo '%s'" msgid "" "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n" @@ -10424,7 +10689,7 @@ msgstr[0] "" #, c-format msgid "Could not remove config section '%s'" -msgstr "Không thể gỡ bá» phần cấu hình “%sâ€" +msgstr "Không thể gỡ bá» phần cấu hình '%s'" #, c-format msgid " new (next fetch will store in remotes/%s)" @@ -10433,8 +10698,11 @@ msgstr " má»›i (lần lấy vá» tiếp theo sẽ lÆ°u trong remotes/%s)" msgid " tracked" msgstr " được theo dõi" +msgid " skipped" +msgstr " được bá» qua" + msgid " stale (use 'git remote prune' to remove)" -msgstr " cÅ© rÃch (dùng “git remote prune†để gỡ bá»)" +msgstr " đã cÅ© (dùng 'git remote prune' để xoá bá»)" msgid " ???" msgstr " ???" @@ -10546,15 +10814,15 @@ msgstr " (trạng thái không được yêu cầu)" msgid " Local branch configured for 'git pull':" msgid_plural " Local branches configured for 'git pull':" -msgstr[0] " Những nhánh ná»™i bá»™ đã được cấu hình cho lệnh “git pullâ€:" +msgstr[0] " Những nhánh ná»™i bá»™ đã được cấu hình cho lệnh 'git pull':" msgid " Local refs will be mirrored by 'git push'" -msgstr " refs ná»™i bá»™ sẽ được phản chiếu bởi lệnh “git pushâ€" +msgstr " refs ná»™i bá»™ sẽ được phản chiếu bởi lệnh 'git push'" #, c-format msgid " Local ref configured for 'git push'%s:" msgid_plural " Local refs configured for 'git push'%s:" -msgstr[0] " Những tham chiếu ná»™i bá»™ được cấu hình cho lệnh “git pushâ€%s:" +msgstr[0] " Những tham chiếu ná»™i bá»™ được cấu hình cho lệnh 'git push'%s:" msgid "set refs/remotes/<name>/HEAD according to remote" msgstr "đặt refs/remotes/<tên>/HEAD cho phù hợp vá»›i máy chủ" @@ -10609,7 +10877,7 @@ msgstr "cắt máy chủ sau khi lấy vá»" #, c-format msgid "No such remote '%s'" -msgstr "Không có máy chủ nà o có tên “%sâ€" +msgstr "Không có máy chủ nà o có tên '%s'" msgid "add branch" msgstr "thêm nhánh" @@ -10625,10 +10893,10 @@ 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â€" +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" +msgstr "đẩy các 'URL' bằng tay" msgid "add URL" msgstr "thêm URL" @@ -10665,35 +10933,45 @@ msgstr "" msgid "could not start pack-objects to repack promisor objects" msgstr "" -"không thể lấy thông tin thống kê pack-objects để mà đóng gói lại các đối " -"tượng hứa hẹn" +"không thể lấy thông tin thống kê pack-objects để đóng gói lại các đối tượng " +"promisor" + +msgid "failed to feed promisor objects to pack-objects" +msgstr "gặp lá»—i khi Ä‘Æ°a promisor object cho pack-objects" msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "" -"repack: Äang chỉ cần các dòng ID đối tượng dạng tháºp lục phân đầy dủ từ pack-" -"objects." +"repack: Äang chỉ cần các dòng ID đối tượng dạng hexa đầy đủ từ pack-objects." msgid "could not finish pack-objects to repack promisor objects" -msgstr "không thể hoà n tất pack-objects để đóng gói các đối tượng hứa hẹn" +msgstr "không thể hoà n tất pack-objects để đóng gói các đối tượng promisor" #, c-format msgid "cannot open index for %s" -msgstr "không thể mở mục lục cho “%sâ€" +msgstr "không thể mở chỉ mục cho %s" #, c-format msgid "pack %s too large to consider in geometric progression" -msgstr "gói %s là quá lá»›n để được xem là trong tiến trình hình há»c" +msgstr "gói %s quá lá»›n để xem xét cấp số nhân" #, c-format msgid "pack %s too large to roll up" -msgstr "gói %s là quá lá»›n để được cuá»™n lại" +msgstr "gói %s quá lá»›n để cuá»™n lại" #, c-format msgid "could not open tempfile %s for writing" msgstr "không thể mở táºp tin tạm %s để ghi" msgid "could not close refs snapshot tempfile" -msgstr "không thể đóng táºp tin tạm thá»i chụp nhanh các tham chiếu" +msgstr "không thể đóng táºp tin snapshot các tham chiếu" + +#, c-format +msgid "could not remove stale bitmap: %s" +msgstr "không thể xoá bá» bitmap đã cÅ©: %s" + +#, c-format +msgid "pack prefix %s does not begin with objdir %s" +msgstr "tiá»n tố gói '%s' không được bắt đầu vá»›i objdir '.%s'" msgid "pack everything in a single pack" msgstr "đóng gói má»i thứ trong má»™t gói Ä‘Æ¡n" @@ -10708,8 +10986,8 @@ msgstr "" msgid "approxidate" msgstr "ngà y Æ°á»›c tÃnh" -msgid "with -C, expire objects older than this" -msgstr "vá»›i -C, các đối tượng hết hạn cÅ© hÆ¡n khoảng nà y" +msgid "with --cruft, expire objects older than this" +msgstr "vá»›i --cruft, đánh dấu hết hạn các đối tượng cÅ© hÆ¡n khoảng nà y" msgid "remove redundant packs, and run git-prune-packed" msgstr "xóa bá» các gói dÆ° thừa, và chạy git-prune-packed" @@ -10727,7 +11005,7 @@ msgid "pass --local to git-pack-objects" msgstr "chuyển --local cho git-pack-objects" msgid "write bitmap index" -msgstr "ghi mục lục ánh xạ" +msgstr "ghi chỉ mục ánh xạ" msgid "pass --delta-islands to git-pack-objects" msgstr "chuyển --delta-islands cho git-pack-objects" @@ -10739,7 +11017,7 @@ msgid "with -a, repack unreachable objects" msgstr "vá»›i -a, đóng gói lại các đối tượng không thể Ä‘á»c được" msgid "size of the window used for delta compression" -msgstr "kÃch thÆ°á»›c cá»a sổ được dùng cho nén “deltaâ€" +msgstr "kÃch thÆ°á»›c cá»a sổ được dùng cho nén 'delta'" msgid "bytes" msgstr "byte" @@ -10748,7 +11026,7 @@ msgid "same as the above, but limit memory size instead of entries count" msgstr "giống nhÆ° trên, nhÆ°ng giá»›i hạn kÃch thÆ°á»›c bá»™ nhá»› hay vì số lượng" msgid "limits the maximum delta depth" -msgstr "giá»›i hạn Ä‘á»™ sâu tối Ä‘a của “deltaâ€" +msgstr "giá»›i hạn Ä‘á»™ sâu tối Ä‘a của 'delta'" msgid "limits the maximum number of threads" msgstr "giá»›i hạn số lượng tối Ä‘a tuyến trình" @@ -10766,25 +11044,35 @@ msgid "find a geometric progression with factor <N>" msgstr "tìm má»™t tiến trình hình há»c vá»›i hệ số <N>" msgid "write a multi-pack index of the resulting packs" -msgstr "ghi mục lục “multi-pack†của các gói kết quả" +msgstr "ghi chỉ mục 'multi-pack' của các gói kết quả" + +msgid "pack prefix to store a pack containing pruned objects" +msgstr "tiá»n tố của gói để lÆ°u gói gồm những đối tượng đã loại bá»" + +msgid "pack prefix to store a pack containing filtered out objects" +msgstr "tiá»n tố của gói để lÆ°u gói gồm những đối tượng đã lá»c bá»" msgid "cannot delete packs in a precious-objects repo" -msgstr "không thể xóa các gói trong má»™t kho đối_tượng_vÄ©_đại" +msgstr "không thể xóa các gói trong má»™t kho đối tượng cần thiết" + +#, c-format +msgid "option '%s' can only be used along with '%s'" +msgstr "tuỳ chá»n '%s' chỉ có thể được dùng vá»›i '%s'" msgid "Nothing new to pack." -msgstr "Không có gì má»›i để mà đóng gói." +msgstr "Không có gì má»›i để đóng gói." #, c-format -msgid "pack prefix %s does not begin with objdir %s" -msgstr "tiá»n tố gói “%s†không được bắt đầu vá»›i objdir “.%sâ€" +msgid "renaming pack to '%s' failed" +msgstr "gặp lá»—i khi đổi tên gói thà nh '%s'" #, c-format -msgid "missing required file: %s" -msgstr "thiếu táºp tin cần thiết: %s" +msgid "pack-objects did not write a '%s' file for pack %s-%s" +msgstr "pack-objects không ghi táºp tin '%s' cho gói %s-%s" #, c-format msgid "could not unlink: %s" -msgstr "không thể bá» liên kết: %s" +msgstr "không thể unlink: %s" msgid "git replace [-f] <object> <replacement>" msgstr "git replace [-f] <đối-tượng> <thay-thế>" @@ -10793,37 +11081,37 @@ msgid "git replace [-f] --edit <object>" msgstr "git replace [-f] --edit <đối tượng>" msgid "git replace [-f] --graft <commit> [<parent>...]" -msgstr "git replace [-f] --graft <lần_chuyển_giao> [<cha_mẹ>…]" +msgstr "git replace [-f] --graft <lần_chuyển_giao> [<cha_mẹ>...]" msgid "git replace -d <object>..." -msgstr "git replace -d <đối tượng>…" +msgstr "git replace -d <đối tượng>..." msgid "git replace [--format=<format>] [-l [<pattern>]]" -msgstr "git replace [--format=<định_dạng>] [-l [<mẫu>]]" +msgstr "git replace [--format=<định dạng>] [-l [<mẫu>]]" #, c-format msgid "" "invalid replace format '%s'\n" "valid formats are 'short', 'medium' and 'long'" msgstr "" -"định dạng thay thế không hợp lệ “%sâ€\n" -"định dạng hợp lệ là “shortâ€, “medium†và “longâ€" +"định dạng thay thế không hợp lệ '%s'\n" +"định dạng hợp lệ là 'short', 'medium' và 'long'" #, c-format msgid "replace ref '%s' not found" -msgstr "không tìm thấy tham chiếu thay thế “%sâ€" +msgstr "không tìm thấy tham chiếu thay thế '%s'" #, c-format msgid "Deleted replace ref '%s'" -msgstr "Äã xóa tham chiếu thay thế “%sâ€" +msgstr "Äã xóa tham chiếu thay thế '%s'" #, c-format msgid "'%s' is not a valid ref name" -msgstr "“%s†không phải tên tham chiếu hợp lệ" +msgstr "'%s' không phải tên tham chiếu hợp lệ" #, c-format msgid "replace ref '%s' already exists" -msgstr "tham chiếu thay thế “%s†đã tồn tại rồi" +msgstr "tham chiếu thay thế '%s' đã tồn tại rồi" #, c-format msgid "" @@ -10832,19 +11120,19 @@ msgid "" "while '%s' points to a replacement object of type '%s'." msgstr "" "Các đối tượng phải cùng kiểu.\n" -"“%s†chỉ đến đối tượng thay thế của kiểu “%sâ€\n" -"trong khi “%s†chỉ đến đối tượng tham chiếu của kiểu “%sâ€." +"'%s' chỉ đến đối tượng thay thế của kiểu '%s'\n" +"trong khi '%s' chỉ đến đối tượng tham chiếu của kiểu '%s'." #, c-format msgid "unable to open %s for writing" -msgstr "không thể mở “%s†để ghi" +msgstr "không thể mở '%s' để ghi" msgid "cat-file reported failure" -msgstr "cat-file đã báo cáo gặp lá»—i nghiêm trá»ng" +msgstr "cat-file đã báo nghiêm trá»ng" #, c-format msgid "unable to open %s for reading" -msgstr "không thể mở “%s†để Ä‘á»c" +msgstr "không thể mở '%s' để Ä‘á»c" msgid "unable to spawn mktree" msgstr "không thể sinh tiến trình con mktree" @@ -10853,7 +11141,7 @@ msgid "unable to read from mktree" msgstr "không thể Ä‘á»c từ mktree" msgid "mktree reported failure" -msgstr "mktree đã báo cáo gặp lá»—i nghiêm trá»ng" +msgstr "mktree đã báo lá»—i nghiêm trá»ng" msgid "mktree did not return an object name" msgstr "mktree đã không trả vá» má»™t tên đối tượng" @@ -10874,46 +11162,46 @@ msgstr "việc sá»a táºp tin đối tượng gặp lá»—i" #, c-format msgid "new object is the same as the old one: '%s'" -msgstr "đối tượng má»›i là giống vá»›i cái cÅ©: “%sâ€" +msgstr "đối tượng má»›i là giống vá»›i cái cÅ©: '%s'" #, c-format msgid "could not parse %s as a commit" -msgstr "không thể phân tÃch %s nhÆ° là má»™t lần chuyển giao" +msgstr "không thể Ä‘á»c %s nhÆ° là má»™t lần chuyển giao" #, c-format msgid "bad mergetag in commit '%s'" -msgstr "thẻ hòa trá»™n sai trong lần chuyển giao “%sâ€" +msgstr "thẻ hòa trá»™n sai trong lần chuyển giao '%s'" #, c-format msgid "malformed mergetag in commit '%s'" -msgstr "thẻ hòa trá»™n không đúng dạng ở lần chuyển giao “%sâ€" +msgstr "thẻ hòa trá»™n bất thÆ°á»ng dạng ở lần chuyển giao '%s'" #, c-format msgid "" "original commit '%s' contains mergetag '%s' that is discarded; use --edit " "instead of --graft" msgstr "" -"lần chuyển giao gốc “%s†có chứa thẻ hòa trá»™n “%s†cái mà bị loại bá»; dùng " -"tùy chá»n --edit thay cho --graft" +"lần chuyển giao gốc '%s' có chứa thẻ hòa trá»™n '%s' đã bị loại bá»; dùng tùy " +"chá»n --edit thay cho --graft" #, c-format msgid "the original commit '%s' has a gpg signature" -msgstr "lần chuyển giao gốc “%s†có chữ ký GPG" +msgstr "lần chuyển giao gốc '%s' có chữ ký GPG" msgid "the signature will be removed in the replacement commit!" msgstr "chữ ký sẽ được bá» Ä‘i trong lần chuyển giao thay thế!" #, c-format msgid "could not write replacement commit for: '%s'" -msgstr "không thể ghi lần chuyển giao thay thế cho: “%sâ€" +msgstr "không thể ghi lần chuyển giao thay thế cho: '%s'" #, c-format msgid "graft for '%s' unnecessary" -msgstr "graft cho “%s†không cần thiết" +msgstr "graft cho '%s' không cần thiết" #, c-format msgid "new commit is the same as the old one: '%s'" -msgstr "lần chuyển giao má»›i là giống vá»›i cái cÅ©: “%sâ€" +msgstr "lần chuyển giao má»›i là giống vá»›i cái cÅ©: '%s'" #, c-format msgid "" @@ -10974,19 +11262,85 @@ 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" -msgid "git rerere [clear | forget <path>... | status | remaining | diff | gc]" +msgid "need some commits to replay" +msgstr "cần các chuyển giao để phát lại" + +msgid "--onto and --advance are incompatible" +msgstr "--onto và --advance xung khắc" + +msgid "all positive revisions given must be references" +msgstr "má»i Ä‘iểm xét duyệt cá»™ng thêm phải là tên tham chiếu" + +msgid "argument to --advance must be a reference" +msgstr "tham số cho --advance phải là tham chiếu" + +msgid "" +"cannot advance target with multiple sources because ordering would be ill-" +"defined" +msgstr "không thể đẩy nhánh vá»›i nhiá»u nguồn vì thứ tá»± không xác định" + +msgid "" +"cannot implicitly determine whether this is an --advance or --onto operation" +msgstr "không thể tá»± xác định là thá»±c hiện --advance hay --onto" + +msgid "" +"cannot advance target with multiple source branches because ordering would " +"be ill-defined" +msgstr "không thể đẩy nhánh vá»›i nhiá»u nhánh nguồn vì thứ tá»± không xác định" + +msgid "cannot implicitly determine correct base for --onto" +msgstr "không thể tá»± xác định gốc thá»±c hiện --onto" + +msgid "" +"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance " +"<branch>) <revision-range>..." +msgstr "" +"(TRONG QUà TRÃŒNH THỬ NGHIỆM!) git replay ([--contained] --onto <gốc má»›i> | " +"--advance <nhánh>) <khoảng-xét-duyệt>..." + +msgid "make replay advance given branch" +msgstr "đẩy nhánh nà y trong khi phát lại" + +msgid "replay onto given commit" +msgstr "phát lại và o commit nà y" + +msgid "advance all branches contained in revision-range" +msgstr "đẩy tất cả các nhánh có trong khoảng-xét-duyệt " + +msgid "option --onto or --advance is mandatory" +msgstr "tuỳ chá»n --onto hoặc --advance là bắt buá»™c" + +#, c-format +msgid "" +"some rev walking options will be overridden as '%s' bit in 'struct rev_info' " +"will be forced" +msgstr "" +"má»™t số tuỳ chá»n duyệt qua Ä‘iểm xét duyệt sẽ bị bá» qua do bit '%s' trong " +"'struct rev_info' bị ép báºt/tắt" + +msgid "error preparing revisions" +msgstr "gặp lá»—i khi chuẩn bị các Ä‘iểm xét duyệt" + +msgid "replaying down to root commit is not supported yet!" +msgstr "chÆ°a há»— trợ phát lại đến lần chuyển giao gốc!" + +msgid "replaying merge commits is not supported yet!" +msgstr "chÆ°a há»— trợ phát lại các lần hoà trá»™n!" + +msgid "" +"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]" msgstr "" -"git rerere [clear | forget <Ä‘Æ°á»ng dẫn>… | status | remaining | diff | gc]" +"git rerere [clear | forget <Ä‘Æ°á»ng dẫn>... | diff | status | remaining | gc]" msgid "register clean resolutions in index" -msgstr "sổ ghi dá»n sạch các phân giải trong bản mục lục" +msgstr "ghi lại các lần giải quyết ổn thoả xung Ä‘á»™t trong chỉ mục" msgid "'git rerere forget' without paths is deprecated" -msgstr "“git rerere forget†mà không có các Ä‘Æ°á»ng dẫn là đã lạc háºu" +msgstr "không còn dùng 'git rerere forget' mà không có các Ä‘Æ°á»ng dẫn" #, c-format msgid "unable to generate diff for '%s'" -msgstr "không thể tạo khác biệt cho “%sâ€" +msgstr "không thể tạo diff cho '%s'" msgid "" "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" @@ -10994,7 +11348,7 @@ msgstr "" "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" msgid "git reset [-q] [<tree-ish>] [--] <pathspec>..." -msgstr "git reset [-q] [<tree-ish>] [--] <đặc/tả/Ä‘Æ°á»ng/dẫn>…" +msgstr "git reset [-q] [<tree-ish>] [--] <đặc/tả/Ä‘Æ°á»ng/dẫn>..." msgid "" "git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]" @@ -11002,7 +11356,7 @@ msgstr "" "git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]" msgid "git reset --patch [<tree-ish>] [--] [<pathspec>...]" -msgstr "git reset --patch [<tree-ish>] [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>…]" +msgstr "git reset --patch [<tree-ish>] [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>...]" msgid "mixed" msgstr "pha trá»™n" @@ -11041,16 +11395,16 @@ msgid "be quiet, only report errors" msgstr "là m việc ở chế Ä‘á»™ im lặng, chỉ hiển thị khi có lá»—i" msgid "skip refreshing the index after reset" -msgstr "bá» qua là m tÆ°Æ¡i mục lục sau khi đặt lại" +msgstr "bá» qua là m má»›i chỉ mục sau khi reset" msgid "reset HEAD and index" -msgstr "đặt lại (reset) HEAD và bảng mục lục" +msgstr "đặt lại HEAD và chỉ mục" msgid "reset only HEAD" -msgstr "chỉ đặt lại (reset) HEAD" +msgstr "chỉ đặt lại HEAD" msgid "reset HEAD, index and working tree" -msgstr "đặt lại HEAD, bảng mục lục và cây là m việc" +msgstr "đặt lại HEAD, chỉ mục và cây là m việc" msgid "reset HEAD but keep local changes" msgstr "đặt lại HEAD nhÆ°ng giữ lại các thay đổi ná»™i bá»™" @@ -11060,16 +11414,16 @@ msgstr "chỉ ghi lại những Ä‘Æ°á»ng dẫn thá»±c sá»± sẽ được thêm #, c-format msgid "Failed to resolve '%s' as a valid revision." -msgstr "Gặp lá»—i khi phân giải “%s†nhÆ° là điểm xét duyệt hợp lệ." +msgstr "Gặp lá»—i khi phân giải '%s' thà nh Ä‘iểm xét duyệt hợp lệ." #, c-format msgid "Failed to resolve '%s' as a valid tree." -msgstr "Gặp lá»—i khi phân giải “%s†nhÆ° là má»™t cây (tree) hợp lệ." +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 "" -"--mixed vá»›i các Ä‘Æ°á»ng dẫn không còn dùng nữa; hãy thay thế bằng lệnh “git " -"reset -- </các/Ä‘Æ°á»ng/dẫn>â€." +"không cho 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 msgid "Cannot do %s reset with paths." @@ -11077,7 +11431,7 @@ msgstr "Không thể thá»±c hiện lệnh %s reset vá»›i các Ä‘Æ°á»ng dẫn." #, c-format msgid "%s reset is not allowed in a bare repository" -msgstr "%s reset không được phép trên kho thuần" +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:" @@ -11087,21 +11441,25 @@ msgid "" "It took %.2f seconds to refresh the index after reset. You can use\n" "'--no-refresh' to avoid this." msgstr "" -"Việc nà y cần %.2f giây để là m tÆ°Æ¡i má»›i mục lục sau khi đặt lại. Bạn có thể " +"Việc nà y cần %.2f giây để là m tÆ°Æ¡i má»›i chỉ mục sau khi đặt lại. Bạn có thể " "sá» dụng\n" -"“--no-refresh†tránh Ä‘iá»u nà y." +"'--no-refresh' tránh Ä‘iá»u nà y." #, c-format msgid "Could not reset index file to revision '%s'." -msgstr "Không thể đặt lại (reset) bảng mục lục thà nh Ä‘iểm xét duyệt “%sâ€." +msgstr "Không thể đặt lại (reset) chỉ mục thà nh Ä‘iểm xét duyệt '%s'." msgid "Could not write new index file." -msgstr "Không thể ghi táºp tin lÆ°u bảng mục lục má»›i." +msgstr "Không thể ghi táºp tin chỉ mục má»›i." #, c-format msgid "unable to get disk usage of %s" msgstr "không thể dung lượng Ä‘Ä©a đã dùng của %s" +#, c-format +msgid "invalid value for '%s': '%s', the only allowed format is '%s'" +msgstr "giá trị không hợp lệ cho '%s': '%s', chỉ cho phép định dạng là '%s'" + msgid "rev-list does not support display of notes" msgstr "rev-list không há»— trợ hiển thị các ghi chú" @@ -11110,22 +11468,25 @@ msgid "marked counting and '%s' cannot be used together" msgstr "đánh dấu để đếm và '%s' không thể dùng cùng nhau" msgid "git rev-parse --parseopt [<options>] -- [<args>...]" -msgstr "git rev-parse --parseopt [<các tùy chá»n>] -- [<các tham số>…]" +msgstr "git rev-parse --parseopt [<các tùy chá»n>] -- [<các tham số>...]" msgid "keep the `--` passed as an arg" -msgstr "giữ lại “--†chuyển sang là m tham số" +msgstr "giữ lại '--' chuyển sang là m tham số" msgid "stop parsing after the first non-option argument" -msgstr "dừng phân tÃch sau đối số đầu tiên không có tùy chá»n" +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" msgid "premature end of input" -msgstr "đầu và o chấm dứt bất thÆ°á»ng" +msgstr "đầu và o kết thúc bất thÆ°á»ng" msgid "no usage string given before the `--' separator" -msgstr "không có chuá»—i cách dùng nà o được Ä‘Æ°a ra trÆ°á»›c dấu phân cách “--â€" +msgstr "không có chuá»—i cách dùng nà o được Ä‘Æ°a ra trÆ°á»›c dấu phân cách '--'" + +msgid "missing opt-spec before option flags" +msgstr "thiếu opt-spec trÆ°á»›c các tuỳ chá»n" msgid "Needed a single revision" msgstr "Cần má»™t Ä‘iểm xét duyệt Ä‘Æ¡n" @@ -11137,9 +11498,9 @@ msgid "" "\n" "Run \"git rev-parse --parseopt -h\" for more information on the first usage." msgstr "" -"git rev-parse --parseopt [<các tùy chá»n>] -- [<các đối số>…]\n" -" hoặc: git rev-parse --sq-quote [<Ä‘.số>…]\n" -" hoặc: git rev-parse [<các tùy chá»n>] [<Ä‘.số>…]\n" +"git rev-parse --parseopt [<các tùy chá»n>] -- [<các đối số>...]\n" +" hoặc: git rev-parse --sq-quote [<Ä‘.số>...]\n" +" hoặc: git rev-parse [<các tùy chá»n>] [<Ä‘.số>...]\n" "\n" "Chạy lệnh \"git rev-parse --parseopt -h\" để có thêm thông tin vá» cách dùng." @@ -11148,7 +11509,7 @@ msgstr "--resolve-git-dir cần má»™t tham số" #, c-format msgid "not a gitdir '%s'" -msgstr "không phải má»™t thÆ° mục git “%sâ€" +msgstr "không phải má»™t thÆ° mục git '%s'" msgid "--git-path requires an argument" msgstr "--git-path cần má»™t tham số" @@ -11169,6 +11530,13 @@ msgstr "--default cần má»™t tham số" msgid "--prefix requires an argument" msgstr "--prefix cần má»™t tham số" +msgid "no object format specified" +msgstr "không chỉ ra định dạng đối tượng" + +#, c-format +msgid "unsupported object format: %s" +msgstr "không há»— trợ định dạng đối tượng: %s" + #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "không hiểu chế Ä‘á»™ cho --abbrev-ref: %s" @@ -11176,25 +11544,36 @@ msgstr "không hiểu chế Ä‘á»™ cho --abbrev-ref: %s" msgid "this operation must be run in a work tree" msgstr "thao tác nà y phải được thá»±c hiện trong thÆ° mục là m việc" +msgid "Could not read the index" +msgstr "Không thể Ä‘á»c chỉ mục" + #, c-format msgid "unknown mode for --show-object-format: %s" msgstr "không hiểu chế Ä‘á»™ cho --show-object-format: %s" -msgid "git revert [<options>] <commit-ish>..." -msgstr "git revert [<các tùy chá»n>] <commit-ish>…" +msgid "" +"git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] " +"<commit>..." +msgstr "" +"git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] " +"<commit>..." -msgid "git revert <subcommand>" -msgstr "git revert <lệnh-con>" +msgid "git revert (--continue | --skip | --abort | --quit)" +msgstr "git revert (--continue | --skip | --abort | --quit)" -msgid "git cherry-pick [<options>] <commit-ish>..." -msgstr "git cherry-pick [<các tùy chá»n>] <commit-ish>…" +msgid "" +"git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n" +" [-S[<keyid>]] <commit>..." +msgstr "" +"git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n" +" [-S[<keyid>]] <commit>..." -msgid "git cherry-pick <subcommand>" -msgstr "git cherry-pick <lệnh-con>" +msgid "git cherry-pick (--continue | --skip | --abort | --quit)" +msgstr "git cherry-pick (--continue | --skip | --abort | --quit)" #, c-format msgid "option `%s' expects a number greater than zero" -msgstr "tùy chá»n “%s†cần má»™t giá trị bằng số lá»›n hÆ¡n không" +msgstr "tùy chá»n '%s' cần má»™t giá trị bằng số lá»›n hÆ¡n không" #, c-format msgid "%s: %s cannot be used with %s" @@ -11239,8 +11618,8 @@ msgstr "cấm khởi tạo lần chuyển giao trống rá»—ng" msgid "allow commits with empty messages" msgstr "chấp nháºn chuyển giao mà không ghi chú gì" -msgid "keep redundant, empty commits" -msgstr "giữ lại các lần chuyển giao dÆ° thừa, rá»—ng" +msgid "deprecated: use --empty=keep instead" +msgstr "đã lạc háºu: hãy dùng --empty=keep" msgid "use the 'reference' format to refer to commits" msgstr "dùng định dạng 'tham chiếu' để quy cho các lần chuyển giao" @@ -11251,8 +11630,14 @@ msgstr "hoà n nguyên gặp lá»—i" msgid "cherry-pick failed" msgstr "cherry-pick gặp lá»—i" -msgid "git rm [<options>] [--] <file>..." -msgstr "git rm [<các tùy chá»n>] [--] <táºp-tin>…" +msgid "" +"git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]\n" +" [--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" +" [--] [<pathspec>...]" +msgstr "" +"git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]\n" +" [--quiet] [--pathspec-from-file=<táºp tin> [--pathspec-file-nul]]\n" +" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>...]]" msgid "" "the following file has staged content different from both the\n" @@ -11273,7 +11658,7 @@ msgstr "" msgid "the following file has changes staged in the index:" msgid_plural "the following files have changes staged in the index:" -msgstr[0] "các táºp tin sau đây có thay đổi trạng thái trong bảng mục lục:" +msgstr[0] "các táºp tin sau đây có thay đổi trạng thái trong chỉ mục:" msgid "" "\n" @@ -11290,13 +11675,13 @@ msgid "do not list removed files" msgstr "không liệt kê các táºp tin đã gỡ bá»" msgid "only remove from the index" -msgstr "chỉ gỡ bá» từ mục lục" +msgstr "chỉ gỡ bá» từ chỉ mục" msgid "override the up-to-date check" msgstr "ghi đè lên kiểm tra cáºp nháºt" msgid "allow recursive removal" -msgstr "cho phép gỡ bỠđệ qui" +msgstr "cho phép gỡ bỠđệ quy" msgid "exit with a zero status even if nothing matched" msgstr "thoát ra vá»›i trạng thái khác không tháºm chà nếu không có gì khá»›p" @@ -11310,7 +11695,7 @@ msgstr "" #, c-format msgid "not removing '%s' recursively without -r" -msgstr "không thể gỡ bỠ“%s†má»™t cách đệ qui mà không có tùy chá»n -r" +msgstr "không thể gỡ bá» '%s' má»™t cách đệ quy mà không có tùy chá»n -r" #, c-format msgid "git rm: unable to remove %s" @@ -11320,37 +11705,43 @@ msgid "" "git send-pack [--mirror] [--dry-run] [--force]\n" " [--receive-pack=<git-receive-pack>]\n" " [--verbose] [--thin] [--atomic]\n" +" [--[no-]signed | --signed=(true|false|if-asked)]\n" " [<host>:]<directory> (--all | <ref>...)" msgstr "" "git send-pack [--mirror] [--dry-run] [--force]\n" " [--receive-pack=<git-receive-pack>]\n" " [--verbose] [--thin] [--atomic]\n" -" [<host>:]<thÆ° mục> (--all | <tham chiếu>…)" +" [--[no-]signed | --signed=(true|false|if-asked)]\n" +" [<host>:]<thÆ° mục> (--all | <tham chiếu>...)" msgid "remote name" msgstr "tên máy dịch vụ" +msgid "push all refs" +msgstr "đẩy tất cả các tham chiếu" + msgid "use stateless RPC protocol" msgstr "dùng giao thức RPC không ổn định" msgid "read refs from stdin" -msgstr "Ä‘á»c tham chiếu từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c tham chiếu từ stdin" msgid "print status from remote helper" msgstr "in các trạng thái từ phần hÆ°á»›ng dẫn trên máy dịch vụ" msgid "git shortlog [<options>] [<revision-range>] [[--] <path>...]" -msgstr "git shortlog [<các tùy chá»n>] [<vùng-xét-duyệt>] [[--] [<Ä‘Æ°á»ng/dẫn>…]]" +msgstr "" +"git shortlog [<các tùy chá»n>] [<vùng-xét-duyệt>] [[--] [<Ä‘Æ°á»ng/dẫn>...]]" msgid "git log --pretty=short | git shortlog [<options>]" msgstr "git log --pretty=short | git shortlog [<các tùy chá»n>]" msgid "using multiple --group options with stdin is not supported" -msgstr "" -"việc dùng nhiá»u tùy chá»n --group vá»›i đầu ra tiêu chuẩn là không được há»— trợ" +msgstr "việc dùng nhiá»u tùy chá»n --group vá»›i stdin là không được há»— trợ" -msgid "using --group=trailer with stdin is not supported" -msgstr "việc dùng --group=trailer vá»›i đầu ra tiêu chuẩn là không được há»— trợ" +#, c-format +msgid "using %s with stdin is not supported" +msgstr "không há»— trợ dùng %s cùng stdin" #, c-format msgid "unknown group type: %s" @@ -11387,15 +11778,17 @@ msgid "" "git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n" " [--current] [--color[=<when>] | --no-color] [--sparse]\n" " [--more=<n> | --list | --independent | --merge-base]\n" -" [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]" +" [--no-name | --sha1-name] [--topics]\n" +" [(<rev> | <glob>)...]" msgstr "" "git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n" " [--current] [--color[=<when>] | --no-color] [--sparse]\n" " [--more=<n> | --list | --independent | --merge-base]\n" -" [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)…]" +" [--no-name | --sha1-name] [--topics]\n" +" [(<rev> | <glob>)...]" msgid "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]" -msgstr "git show-branch (-g | --reflog)[=<n>[,<ná»n>]] [--list] [<ref>]" +msgstr "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]" #, c-format msgid "ignoring %s; cannot handle more than %d ref" @@ -11413,7 +11806,7 @@ msgid "show remote-tracking branches" msgstr "hiển thị các nhánh remote-tracking" msgid "color '*!+-' corresponding to the branch" -msgstr "mà u “*!+-†tÆ°Æ¡ng ứng vá»›i nhánh" +msgstr "mà u '*!+-' tÆ°Æ¡ng ứng vá»›i nhánh" msgid "show <n> more commits after the common ancestor" msgstr "hiển thị thêm <n> lần chuyển giao sau cha mẹ chung" @@ -11431,7 +11824,7 @@ msgid "name commits with their object names" msgstr "đặt tên các lần chuyển giao bằng các tên của đối tượng của chúng" msgid "show possible merge bases" -msgstr "hiển thị má»i cÆ¡ sở có thể dùng để hòa trá»™n" +msgstr "hiển thị má»i gốc hòa trá»™n khả dụng" msgid "show refs unreachable from any other ref" msgstr "hiển thị các tham chiếu không thể được Ä‘á»c bởi bất kỳ tham chiếu khác" @@ -11443,7 +11836,7 @@ msgid "show only commits not on the first branch" msgstr "chỉ hiển thị các lần chuyển giao không nằm trên nhánh đầu tiên" msgid "show merges reachable from only one tip" -msgstr "hiển thị các lần hòa trá»™n có thể Ä‘á»c được chỉ từ má»™t đầu mút" +msgstr "hiển thị các lần hòa trá»™n có thể Ä‘á»c được chỉ từ má»™t đỉnh" msgid "topologically sort, maintaining date order where possible" msgstr "sắp xếp hình thái há»c, bảo trì thứ tá»± ngà y nếu có thể" @@ -11452,7 +11845,7 @@ msgid "<n>[,<base>]" msgstr "<n>[,<cÆ¡_sở>]" msgid "show <n> most recent ref-log entries starting at base" -msgstr "hiển thị <n> các mục “ref-log†gần nhất kể từ ná»n (base)" +msgstr "hiển thị <n> các mục 'ref-log' gần nhất kể từ ná»n (base)" msgid "no branches given, and HEAD is not valid" msgstr "chÆ°a Ä‘Æ°a ra nhánh, và HEAD không hợp lệ" @@ -11476,7 +11869,7 @@ msgstr[0] "không thể xá» lý nhiá»u hÆ¡n %d Ä‘iểm xét duyệt." #, c-format msgid "'%s' is not a valid ref." -msgstr "“%s†không phải tham chiếu hợp lệ." +msgstr "'%s' không phải tham chiếu hợp lệ." #, c-format msgid "cannot find commit %s (%s)" @@ -11489,61 +11882,83 @@ msgid "Unknown hash algorithm" msgstr "Không hiểu thuáºt toán băm dữ liệu" msgid "" -"git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --" -"hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<pattern>...]" +"git show-ref [--head] [-d | --dereference]\n" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" +" [--heads] [--] [<pattern>...]" msgstr "" -"git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --" -"hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<mẫu>…]" +"git show-ref [--head] [-d | --dereference]\n" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n" +" [--heads] [--] [<mẫu>...]" + +msgid "" +"git show-ref --verify [-q | --quiet] [-d | --dereference]\n" +" [-s | --hash[=<n>]] [--abbrev[=<n>]]\n" +" [--] [<ref>...]" +msgstr "" +"git show-ref --verify [-q | --quiet] [-d | --dereference]\n" +" [-s | --hash[=<n>]] [--abbrev[=<n>]]\n" +" [--] [<mẫu>...]" msgid "git show-ref --exclude-existing[=<pattern>]" msgstr "git show-ref --exclude-existing[=<mẫu>]" +msgid "git show-ref --exists <ref>" +msgstr "git show-ref --exists <tham_chiếu>" + +msgid "reference does not exist" +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 heads (can be combined with tags)" msgstr "chỉ hiển thị đầu (có thể tổ hợp cùng vá»›i thẻ)" +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" + msgid "stricter reference checking, requires exact ref path" -msgstr "" -"việc kiểm tra tham chiếu chÃnh xác, đòi há»i chÃnh xác Ä‘Æ°á»ng dẫn tham chiếu" +msgstr "kiểm tra tham chiếu chÃnh xác, đòi há»i chÃnh xác Ä‘Æ°á»ng dẫn tham chiếu" msgid "show the HEAD reference, even if it would be filtered out" msgstr "hiển thị tham chiếu HEAD, ngay cả khi nó đã được lá»c ra" msgid "dereference tags into object IDs" -msgstr "bãi bá» tham chiếu các thẻ thà nh ra các ID đối tượng" +msgstr "giải tham chiếu các thẻ thà nh các ID đối tượng" msgid "only show SHA1 hash using <n> digits" msgstr "chỉ hiển thị mã băm SHA1 sá» dụng <n> chữ số" msgid "do not print results to stdout (useful with --verify)" -msgstr "" -"không hiển thị kết quả ra đầu ra chuẩn (stdout) (chỉ hữu dụng vá»›i --verify)" +msgstr "không hiển thị kết quả ra stdout (hữu dụng khi dùng cùng --verify)" msgid "show refs from stdin that aren't in local repository" -msgstr "" -"hiển thị các tham chiếu từ đầu và o tiêu chuẩn (stdin) cái mà không ở kho ná»™i " -"bá»™" +msgstr "hiển thị các tham chiếu từ stdin mà không ở kho ná»™i bá»™" -msgid "git sparse-checkout (init|list|set|add|reapply|disable) <options>" -msgstr "git sparse-checkout (init|list|set|add|reapply|disable) <các-tùy-chá»n>" +msgid "" +"git sparse-checkout (init | list | set | add | reapply | disable | check-" +"rules) [<options>]" +msgstr "" +"git sparse-checkout (init | list | set | add | reapply | disable | check-" +"rules) [<các-tùy-chá»n>]" msgid "this worktree is not sparse" -msgstr "cây là m việc nà y không phải là sparse" +msgstr "cây là m việc nà y không thÆ°a" msgid "this worktree is not sparse (sparse-checkout file may not exist)" msgstr "" -"không thể phân tÃch cú pháp cây là m việc nà y (táºp tin sparse-checkout có lẽ " -"không tồn tại)" +"cây là m việc nà y không thÆ°a (táºp tin sparse-checkout có lẽ không tồn tại)" #, c-format msgid "" "directory '%s' contains untracked files, but is not in the sparse-checkout " "cone" msgstr "" -"thÆ° mục “%s†có chứa các táºp tin chÆ°a được theo dõi, nhÆ°ng lại không trong " -"“sparse-checkout coneâ€" +"thÆ° mục '%s' có chứa các táºp tin chÆ°a được theo dõi, nhÆ°ng không nằm trong " +"'sparse-checkout cone' (vùng checkout thÆ°a)" #, c-format msgid "failed to remove directory '%s'" @@ -11556,35 +11971,35 @@ 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" msgid "failed to modify sparse-index config" -msgstr "gặp lá»—i khi sá»a cấu hình \"sparse-index\"" +msgstr "gặp lá»—i khi sá»a cấu hình sparse-index" msgid "initialize the sparse-checkout in cone mode" msgstr "khởi tạo sparse-checkout trong chế Ä‘á»™ nón" msgid "toggle the use of a sparse index" -msgstr "báºt tắt việc sá» dụng má»™t \"sparse index\"" +msgstr "báºt tắt việc sá» dụng sparse index" #, c-format msgid "unable to create leading directories of %s" -msgstr "không thể tạo các thÆ° mục dẫn đầu của “%sâ€" +msgstr "không thể tạo các thÆ° mục dẫn đầu của '%s'" #, c-format msgid "failed to open '%s'" -msgstr "gặp lá»—i khi mở “%sâ€" +msgstr "gặp lá»—i khi mở '%s'" #, c-format msgid "could not normalize path %s" -msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn “%sâ€" +msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn '%s'" #, c-format msgid "unable to unquote C-style string '%s'" -msgstr "không thể bá» trÃch dẫn chuá»—i kiểu C “%sâ€" +msgstr "không thể bá» trÃch dẫn chuá»—i kiểu C '%s'" msgid "unable to load existing sparse-checkout patterns" msgstr "không thể tải các mẫu sparse-checkout" msgid "existing sparse-checkout patterns do not use cone mode" -msgstr "đặt các mẫu sparse-checkout sẵn có không sá» dụng chế Ä‘á»™ cone" +msgstr "các mẫu sparse-checkout sẵn có không sá» dụng chế Ä‘á»™ cone" msgid "please run from the toplevel directory in non-cone mode" msgstr "vui lòng chạy từ thÆ° mục mức cao nhất trong chế Ä‘á»™ non-cone" @@ -11619,8 +12034,8 @@ msgid "" "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)." msgstr "" -"chuyển má»™t dấu xổ chéo dẫn đầu Ä‘Æ°á»ng dẫn nhÆ° là '%s' nếu bạn muốn má»™t táºp " -"tin Ä‘Æ¡n (xem NON-CONE PROBLEMS trong hÆ°á»›ng dẫn sá» dụng git-sparse-checkout)." +"dùng dấu gạch chéo dẫn đầu trÆ°á»›c Ä‘Æ°á»ng dẫn nhÆ° '%s' nếu bạn muốn má»™t táºp tin " +"Ä‘Æ¡n lẻ (xem NON-CONE PROBLEMS trong hÆ°á»›ng dẫn sá» dụng git-sparse-checkout)." msgid "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)" msgstr "git sparse-checkout add [--skip-checks] (--stdin | <các mẫu>)" @@ -11628,11 +12043,11 @@ msgstr "git sparse-checkout add [--skip-checks] (--stdin | <các mẫu>)" msgid "" "skip some sanity checks on the given paths that might give false positives" msgstr "" -"bá» qua má»™t số kiểm tra đúng mục trên Ä‘Æ°á»ng dẫn đã cho cái mà có thể Ä‘Æ°a ra " -"xác thá»±c sai" +"bá» qua má»™t số tiá»n kiểm tra có thể không cho kết quả đúng trên các Ä‘Æ°á»ng dẫn " +"đã cho" msgid "read patterns from standard in" -msgstr "Ä‘á»c các mẫu từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c các mẫu từ stdin" msgid "no sparse-checkout to add to" msgstr "không có sparse-checkout để thêm và o" @@ -11645,76 +12060,82 @@ msgstr "" "(--stdin | <các mẫu>)" msgid "must be in a sparse-checkout to reapply sparsity patterns" -msgstr "phải trong má»™t sparse-checkout để áp dụng lại các mẫu sparse" +msgstr "phải trong sparse-checkout để áp dụng lại các mẫu sparse" msgid "error while refreshing working directory" msgstr "gặp lá»—i khi Ä‘á»c lại thÆ° mục là m việc" -msgid "git stash list [<options>]" -msgstr "git stash list [<các tùy chá»n>]" +msgid "" +"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-" +"file <file>]" +msgstr "" +"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-" +"file <táºp tin>]" -msgid "git stash show [<options>] [<stash>]" -msgstr "git stash show [<các tùy chá»n>] <stash>" +msgid "terminate input and output files by a NUL character" +msgstr "kết thúc các bản ghi và o và ra bằng ký tá»± NULL" -msgid "git stash drop [-q|--quiet] [<stash>]" -msgstr "git stash drop [-q|--quiet] [<stash>]" +msgid "when used with --rules-file interpret patterns as cone mode patterns" +msgstr "khi dùng vá»›i --rules-file, dùng mẫu ở chế Ä‘á»™ cone" -msgid "git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]" -msgstr "git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]" +msgid "use patterns in <file> instead of the current ones." +msgstr "dùng mẫu từ <táºp tin> thay vì các mẫu hiện tại" -msgid "git stash branch <branchname> [<stash>]" -msgstr "git stash branch <tên-nhánh> [<stash>]" +msgid "git stash list [<log-options>]" +msgstr "git stash list [<các tùy chá»n>]" msgid "" -"git stash [push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--" -"quiet]\n" -" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n" -" [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" -" [--] [<pathspec>...]]" +"git stash show [-u | --include-untracked | --only-untracked] [<diff-" +"options>] [<stash>]" msgstr "" -"git stash [push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--" -"quiet]\n" -" [-u|--include-untracked] [-a|--all] [-m|--message <ghi chú>]\n" -" [--pathspec-from-file=<táºp_tin> [--pathspec-file-nul]]\n" -" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>…]]" +"git stash show [-u | --include-untracked | --only-untracked] [<diff-" +"options>] [<stash>]" -msgid "" -"git stash save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--" -"quiet]\n" -" [-u|--include-untracked] [-a|--all] [<message>]" -msgstr "" -"git stash save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--" -"quiet]\n" -" [-u|--include-untracked] [-a|--all] [<ghi chú>]" +msgid "git stash drop [-q | --quiet] [<stash>]" +msgstr "git stash drop [-q | --quiet] [<stash>]" + +msgid "git stash pop [--index] [-q | --quiet] [<stash>]" +msgstr "git stash pop [--index] [-q | --quiet] [<stash>]" -msgid "git stash pop [--index] [-q|--quiet] [<stash>]" -msgstr "git stash pop [--index] [-q|--quiet] [<stash>]" +msgid "git stash apply [--index] [-q | --quiet] [<stash>]" +msgstr "git stash apply [--index] [-q | --quiet] [<stash>]" -msgid "git stash apply [--index] [-q|--quiet] [<stash>]" -msgstr "git stash apply [--index] [-q|--quiet] [<stash>]" +msgid "git stash branch <branchname> [<stash>]" +msgstr "git stash branch <tên-nhánh> [<stash>]" -msgid "git stash store [-m|--message <message>] [-q|--quiet] <commit>" -msgstr "git stash store [-m|--message <ghi chú>] [-q|--quiet] <commit>" +msgid "git stash store [(-m | --message) <message>] [-q | --quiet] <commit>" +msgstr "git stash store [(-m | --message) <ghi chú>] [-q | --quiet] <commit>" msgid "" -"git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" -" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n" +"git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q " +"| --quiet]\n" +" [-u | --include-untracked] [-a | --all] [(-m | --message) " +"<message>]\n" +" [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" " [--] [<pathspec>...]]" msgstr "" -"git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" -" [-u|--include-untracked] [-a|--all] [-m|--message <lá»i nhắn>]\n" -" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>…]]" +"git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q " +"| --quiet]\n" +" [-u | --include-untracked] [-a | --all] [(-m | --message) <ghi " +"chú>]\n" +" [--pathspec-from-file=<táºp tin> [--pathspec-file-nul]]\n" +" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>...]]" msgid "" -"git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" -" [-u|--include-untracked] [-a|--all] [<message>]" +"git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | " +"--quiet]\n" +" [-u | --include-untracked] [-a | --all] [<message>]" msgstr "" -"git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n" -" [-u|--include-untracked] [-a|--all] [<ghi chú>]" +"git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | " +"--quiet]\n" +" [-u | --include-untracked] [-a | --all] [<ghi chú>]" + +msgid "git stash create [<message>]" +msgstr "git stash create [<ghi chú>]" #, c-format msgid "'%s' is not a stash-like commit" -msgstr "“%s†không phải là lần chuyển giao kiểu-stash (cất Ä‘i)" +msgstr "'%s' không phải là lần chuyển giao kiểu-stash" #, c-format msgid "Too many revisions specified:%s" @@ -11725,10 +12146,10 @@ msgstr "Không tìm thấy các mục tạm cất (stash) nà o." #, c-format msgid "%s is not a valid reference" -msgstr "“%s†không phải má»™t tham chiếu hợp lệ" +msgstr "'%s' không phải má»™t tham chiếu hợp lệ" msgid "git stash clear with arguments is unimplemented" -msgstr "git stash clear vá»›i các tham số là chÆ°a được thá»±c hiện" +msgstr "git stash clear vá»›i các tham số là chÆ°a được há»— trợ" #, c-format msgid "" @@ -11736,7 +12157,8 @@ msgid "" " %s -> %s\n" " to make room.\n" msgstr "" -"CẢNH BÃO: Tệp chÆ°a được theo dõi theo cách của tệp được theo dõi! Äổi tên\n" +"CẢNH BÃO: táºp tin chÆ°a được theo dõi chắn Ä‘Æ°á»ng táºp tin được theo dõi! Äổi " +"tên\n" " %s -> %s\n" " để nhÆ°á»ng chá»—.\n" @@ -11748,7 +12170,7 @@ msgid "could not generate diff %s^!." msgstr "không thể tạo diff %s^!." msgid "conflicts in index. Try without --index." -msgstr "xung Ä‘á»™t trong bảng mục lục. Hãy thá» mà không dùng tùy chá»n --index." +msgstr "xung Ä‘á»™t trong chỉ mục. Hãy thá» mà không dùng tùy chá»n --index." msgid "could not save index tree" msgstr "không thể ghi lại cây chỉ mục" @@ -11758,13 +12180,13 @@ msgid "Merging %s with %s" msgstr "Äang hòa trá»™n %s vá»›i %s" msgid "Index was not unstashed." -msgstr "Bảng mục lục đã không được bá» stash." +msgstr "chỉ mục đã không được bá» stash." msgid "could not restore untracked files from stash" msgstr "không thể phục hồi các táºp tin chÆ°a theo dõi từ mục cất Ä‘i (stash)" msgid "attempt to recreate the index" -msgstr "gặp lá»—i Ä‘á»c bảng mục lục" +msgstr "gặp lá»—i Ä‘á»c chỉ mục" #, c-format msgid "Dropped %s (%s)" @@ -11776,7 +12198,7 @@ msgstr "%s: Không thể xóa bá» mục stash" #, c-format msgid "'%s' is not a stash reference" -msgstr "â€%s†không phải tham chiếu đến stash" +msgstr "'%s' không phải tham chiếu đến stash" msgid "The stash entry is kept in case you need it again." msgstr "Các mục tạm cất (stash) được giữ trong trÆ°á»ng hợp bạn lại cần nó." @@ -11785,7 +12207,7 @@ msgid "No branch name specified" msgstr "ChÆ°a chỉ ra tên của nhánh" msgid "failed to parse tree" -msgstr "gặp lá»—i khi phân tÃch cây" +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" @@ -11816,7 +12238,7 @@ msgid "You do not have the initial commit yet" msgstr "Bạn chÆ°a còn có lần chuyển giao khởi tạo" msgid "Cannot save the current index state" -msgstr "Không thể ghi lại trạng thái bảng mục lục hiện hà nh" +msgstr "Không thể ghi lại trạng thái chỉ mục hiện hà nh" msgid "Cannot save the untracked files" msgstr "Không thể ghi lại các táºp tin chÆ°a theo dõi" @@ -11837,7 +12259,7 @@ msgid "Can't use --staged and --include-untracked or --all at the same time" msgstr "Không thể dùng --staged và --include-untracked hay --all cùng má»™t lúc" msgid "Did you forget to 'git add'?" -msgstr "Có lẽ bạn đã quên “git add †phải không?" +msgstr "Có lẽ bạn đã quên 'git add'?" msgid "No local changes to save" msgstr "Không có thay đổi ná»™i bá»™ nà o được ghi lại" @@ -11850,19 +12272,19 @@ msgstr "Không thể ghi lại trạng thái hiện hà nh" #, c-format msgid "Saved working directory and index state %s" -msgstr "Äã ghi lại thÆ° mục là m việc và trạng thái mục lục %s" +msgstr "Äã ghi lại thÆ° mục là m việc và trạng thái chỉ mục %s" msgid "Cannot remove worktree changes" msgstr "Không thể gỡ bá» các thay đổi cây-là m-việc" msgid "keep index" -msgstr "giữ nguyên bảng mục lục" +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" msgid "stash in patch mode" -msgstr "cất Ä‘i ở chế Ä‘á»™ miếng vá" +msgstr "cất Ä‘i ở chế Ä‘á»™ vá" msgid "quiet mode" msgstr "chế Ä‘á»™ im lặng" @@ -11881,29 +12303,27 @@ msgstr "treo trÆ°á»›c ký tá»± ghi chú và ký tá»± khoảng trắng cho từng #, c-format msgid "Expecting a full ref name, got %s" -msgstr "Cần tên tham chiếu dạng đầy đủ, nhÆ°ng lại nháºn được %s" +msgstr "Cần tên tham chiếu dạng đầy đủ, nhÆ°ng lại có %s" + +#, c-format +msgid "could not get a repository handle for submodule '%s'" +msgstr "không thể lấy thẻ quản kho cho mô-Ä‘un-con '%s'" #, c-format msgid "" "could not look up configuration '%s'. Assuming this repository is its own " "authoritative upstream." msgstr "" -"không thể tìm thấy cấu hình “%sâ€. Coi rằng đây là kho thượng nguồn có quyá»n " +"không thể tìm thấy cấu hình '%s'. Coi rằng đây là kho thượng nguồn có quyá»n " "sở hữu chÃnh nó." -msgid "alternative anchor for relative paths" -msgstr "Ä‘iểm neo thay thế cho các Ä‘Æ°á»ng dẫn tÆ°Æ¡ng đối" - -msgid "git submodule--helper list [--prefix=<path>] [<path>...]" -msgstr "git submodule--helper list [--prefix=</Ä‘Æ°á»ng/dẫn>] [</Ä‘Æ°á»ng/dẫn>…]" - #, c-format msgid "No url found for submodule path '%s' in .gitmodules" -msgstr "Không tìm thấy url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%s†trong .gitmodules" +msgstr "Không tìm thấy url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s' trong .gitmodules" #, c-format msgid "Entering '%s'\n" -msgstr "Äang và o “%sâ€\n" +msgstr "Äang và o '%s'\n" #, c-format msgid "" @@ -11929,44 +12349,44 @@ msgstr "chặn kết xuất 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" -msgid "git submodule--helper foreach [--quiet] [--recursive] [--] <command>" -msgstr "git submodule--helper foreach [--quiet] [--recursive] [--] <lệnh>" +msgid "git submodule foreach [--quiet] [--recursive] [--] <command>" +msgstr "git submodule foreach [--quiet] [--recursive] [--] <lệnh>" #, c-format msgid "Failed to register url for submodule path '%s'" -msgstr "Gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +msgstr "Gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Submodule '%s' (%s) registered for path '%s'\n" -msgstr "Mô-Ä‘un-con “%s†(%s) được đăng ký cho Ä‘Æ°á»ng dẫn “%sâ€\n" +msgstr "Mô-Ä‘un-con '%s' (%s) được đăng ký cho Ä‘Æ°á»ng dẫn '%s'\n" #, c-format msgid "warning: command update mode suggested for submodule '%s'\n" -msgstr "cảnh báo: chế Ä‘á»™ lệnh cáºp nháºt được gợi ý cho mô-Ä‘un-con “%sâ€\n" +msgstr "cảnh báo: chế Ä‘á»™ lệnh cáºp nháºt được gợi ý cho mô-Ä‘un-con '%s'\n" #, c-format 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â€" +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" -msgid "git submodule--helper init [<options>] [<path>]" -msgstr "git submodule--helper init [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>]" +msgid "git submodule init [<options>] [<path>]" +msgstr "git submodule init [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>]" #, c-format msgid "no submodule mapping found in .gitmodules for path '%s'" msgstr "" "không tìm thấy ánh xạ (mapping) mô-Ä‘un-con trong .gitmodules cho Ä‘Æ°á»ng dẫn " -"“%sâ€" +"'%s'" #, c-format msgid "could not resolve HEAD ref inside the submodule '%s'" -msgstr "không thể phân giải tham chiếu HEAD bên trong mô-Ä‘un-con “%sâ€" +msgstr "không thể phân giải tham chiếu HEAD bên trong mô-Ä‘un-con '%s'" #, c-format msgid "failed to recurse into submodule '%s'" -msgstr "gặp lá»—i khi đệ quy và o trong mô-Ä‘un-con “%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" @@ -11975,15 +12395,12 @@ msgid "" "use commit stored in the index instead of the one stored in the submodule " "HEAD" msgstr "" -"dùng lần chuyển giao lÆ°u trong mục lục thay cho cái được lÆ°u trong HEAD mô-" +"dùng lần chuyển giao lÆ°u trong chỉ mục thay cho cái được lÆ°u trong HEAD mô-" "Ä‘un-con" msgid "git submodule status [--quiet] [--cached] [--recursive] [<path>...]" msgstr "" -"git submodule status [--quiet] [--cached] [--recursive] [</Ä‘Æ°á»ng/dẫn>…]" - -msgid "git submodule--helper name <path>" -msgstr "git submodule--helper name </Ä‘Æ°á»ng/dẫn>" +"git submodule status [--quiet] [--cached] [--recursive] [</Ä‘Æ°á»ng/dẫn>...]" #, c-format msgid "* %s %s(blob)->%s(submodule)" @@ -12001,61 +12418,57 @@ msgstr "%s" #, c-format msgid "couldn't hash object from '%s'" -msgstr "không thể băm đối tượng từ “%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 "use the commit stored in the index instead of the submodule HEAD" -msgstr "hùng lần chuyển giao đã lÆ°u trong mục lục thay cho HEAD mô-Ä‘un-con" +msgstr "hùng lần chuyển giao đã lÆ°u trong chỉ mục thay cho HEAD mô-Ä‘un-con" msgid "compare the commit in the index with that in the submodule HEAD" -msgstr "để so sánh lần trong mục lục vá»›i cái trong HEAD mô-Ä‘un-con" +msgstr "để so sánh lần trong chỉ mục vá»›i cái trong HEAD mô-Ä‘un-con" msgid "skip submodules with 'ignore_config' value set to 'all'" msgstr "" -"bá» qua các mô-Ä‘un-con vá»›i giá trị của “ignore_config†được đặt thà nh “allâ€" +"bá» qua các mô-Ä‘un-con vá»›i giá trị của 'ignore_config' được đặt thà nh 'all'" msgid "limit the summary size" msgstr "giá»›i hạn kÃch cỡ tổng hợp" -msgid "git submodule--helper summary [<options>] [<commit>] [--] [<path>]" +msgid "git submodule summary [<options>] [<commit>] [--] [<path>]" msgstr "" -"git submodule--helper summary [<các tùy chá»n>] [<lần_chuyển_giao>] [--] [</" -"Ä‘Æ°á»ng/dẫn>]" +"git submodule summary [<các tùy chá»n>] [<lần_chuyển_giao>] [--] [</Ä‘Æ°á»ng/" +"dẫn>]" msgid "could not fetch a revision for HEAD" msgstr "không thể lấy vá» má»™t Ä‘iểm xem xét cho HEAD" #, c-format msgid "Synchronizing submodule url for '%s'\n" -msgstr "Url mô-Ä‘un-con đồng bá»™ hóa cho “%sâ€\n" +msgstr "Url mô-Ä‘un-con đồng bá»™ hóa cho '%s'\n" #, c-format msgid "failed to register url for submodule path '%s'" -msgstr "gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" - -#, c-format -msgid "failed to get the default remote for submodule '%s'" -msgstr "gặp lá»—i khi lấy máy chủ mặc định cho mô-Ä‘un-con “%sâ€" +msgstr "gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "failed to update remote for submodule '%s'" -msgstr "gặp lá»—i khi cáºp nháºt cho mô-Ä‘un-con “%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á»™" -msgid "git submodule--helper sync [--quiet] [--recursive] [<path>]" -msgstr "git submodule--helper sync [--quiet] [--recursive] [</Ä‘Æ°á»ng/dẫn>]" +msgid "git submodule sync [--quiet] [--recursive] [<path>]" +msgstr "git submodule sync [--quiet] [--recursive] [</Ä‘Æ°á»ng/dẫn>]" #, c-format msgid "" "Submodule work tree '%s' contains a .git directory. This will be replaced " "with a .git file by using absorbgitdirs." msgstr "" -"Cây là m việc mô-Ä‘un-con “%s†có chứa thÆ° mục .git. Việc nà y sẽ được thay thế " +"Cây là m việc mô-Ä‘un-con '%s' có chứa thÆ° mục .git. Việc nà y sẽ được thay thế " "vá»›i má»™t táºp tin .git bằng các sá» dụng absorbgitdirs." #, c-format @@ -12063,24 +12476,24 @@ msgid "" "Submodule work tree '%s' contains local modifications; use '-f' to discard " "them" msgstr "" -"Cây là m việc mô-Ä‘un-con “%s†chứa các thay đổi ná»™i bá»™; hãy dùng “-f†để loại " +"Cây là m việc mô-Ä‘un-con '%s' chứa các thay đổi ná»™i bá»™; hãy dùng '-f' để loại " "bá» chúng Ä‘i" #, c-format msgid "Cleared directory '%s'\n" -msgstr "Äã xóa thÆ° mục “%sâ€\n" +msgstr "Äã xóa thÆ° mục '%s'\n" #, c-format msgid "Could not remove submodule work tree '%s'\n" -msgstr "Không thể gỡ bá» cây là m việc mô-Ä‘un-con “%sâ€\n" +msgstr "Không thể gỡ bá» cây là m việc mô-Ä‘un-con '%s'\n" #, c-format msgid "could not create empty submodule directory %s" -msgstr "không thể tạo thÆ° mục mô-Ä‘un-con rá»—ng “%sâ€" +msgstr "không thể tạo thÆ° mục mô-Ä‘un-con rá»—ng '%s'" #, c-format msgid "Submodule '%s' (%s) unregistered for path '%s'\n" -msgstr "Mô-Ä‘un-con “%s†(%s) được đăng ký cho Ä‘Æ°á»ng dẫn “%sâ€\n" +msgstr "Mô-Ä‘un-con '%s' (%s) được đăng ký cho Ä‘Æ°á»ng dẫn '%s'\n" msgid "remove submodule working trees even if they contain local changes" msgstr "gỡ bá» cây là m việc của mô-Ä‘un-con ngay cả khi nó có thay đổi ná»™i bá»™" @@ -12091,10 +12504,11 @@ msgstr "bỠđăng ký tất cả các trong mô-Ä‘un-con" msgid "" "git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]" msgstr "" -"git submodule deinit [--quiet] [-f | --force] [--all | [--] [</Ä‘Æ°á»ng/dẫn>…]]" +"git submodule deinit [--quiet] [-f | --force] [--all | [--] [</Ä‘Æ°á»ng/" +"dẫn>...]]" msgid "Use '--all' if you really want to deinitialize all submodules" -msgstr "Dùng “--all†nếu bạn thá»±c sá»± muốn hủy khởi tạo má»i mô-Ä‘un-con" +msgstr "Dùng '--all' nếu bạn thá»±c sá»± muốn hủy khởi tạo má»i mô-Ä‘un-con" msgid "" "An alternate computed from a superproject's alternate is invalid.\n" @@ -12102,41 +12516,48 @@ msgid "" "submodule.alternateErrorStrategy to 'info' or, equivalently, clone with\n" "'--reference-if-able' instead of '--reference'." msgstr "" -"Má»™t cái thay thế được tÃnh toán từ má»™t thay thế của siêu dá»± án là không hợp " +"Má»™t cái thay thế được tÃnh toán từ má»™t thay thế của project cha là không hợp " "lệ.\n" "Äể cho Git thá»±c hiện nhân bản mà không có cái thay thế nhÆ° trong trÆ°á»ng hợp " "nà y, đặt\n" -"submodule.alternateErrorStrategy thà nh “info†hoặc, tÆ°Æ¡ng Ä‘Æ°Æ¡ng, nhân bản " +"submodule.alternateErrorStrategy thà nh 'info' hoặc, tÆ°Æ¡ng Ä‘Æ°Æ¡ng, nhân bản " "bằng\n" -"“--reference-if-able†thay vì dùng “--referenceâ€." +"'--reference-if-able' thay vì dùng '--reference'." + +#, c-format +msgid "could not get a repository handle for gitdir '%s'" +msgstr "không thể lấy thẻ quản kho cho gitdir '%s'" #, c-format msgid "submodule '%s' cannot add alternate: %s" -msgstr "mô-Ä‘un-con “%s†không thể thêm thay thế: %s" +msgstr "mô-Ä‘un-con '%s' không thể thêm thay thế: %s" #, c-format msgid "Value '%s' for submodule.alternateErrorStrategy is not recognized" -msgstr "Giá trị “%s†cho submodule.alternateErrorStrategy không được thừa nháºn" +msgstr "Giá trị '%s' cho submodule.alternateErrorStrategy không được thừa nháºn" #, c-format msgid "Value '%s' for submodule.alternateLocation is not recognized" -msgstr "Giá trị “%s†cho submodule.alternateLocation không được thừa nháºn" +msgstr "Giá trị '%s' cho submodule.alternateLocation không được thừa nháºn" #, c-format 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" +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" +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â€" +msgstr "thÆ° mục không trống: '%s'" #, c-format msgid "could not get submodule directory for '%s'" -msgstr "không thể lấy thÆ° mục mô-Ä‘un-con cho “%sâ€" +msgstr "không thể lấy thÆ° mục mô-Ä‘un-con cho '%s'" + +msgid "alternative anchor for relative paths" +msgstr "Ä‘iểm neo thay thế cho các Ä‘Æ°á»ng dẫn tÆ°Æ¡ng đối" msgid "where the new submodule will be cloned to" msgstr "nhân bản mô-Ä‘un-con má»›i và o chá»— nà o" @@ -12166,20 +12587,16 @@ msgstr "" "spec>] --url <url> --path </Ä‘Æ°á»ng/dẫn>" #, c-format -msgid "Invalid update mode '%s' for submodule path '%s'" -msgstr "Chế Ä‘á»™ cáºp nháºt “%s†không hợp lệ cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" - -#, c-format msgid "Invalid update mode '%s' configured for submodule path '%s'" msgstr "" -"Chế Ä‘á»™ cáºp nháºt “%s†không hợp lệ được cấu hình cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +"Chế Ä‘á»™ cáºp nháºt '%s' không hợp lệ được cấu hình cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Submodule path '%s' not initialized" -msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%s†chÆ°a được khởi tạo" +msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s' chÆ°a được khởi tạo" msgid "Maybe you want to use 'update --init'?" -msgstr "Có lẽ bạn là bạn muốn dùng \"update --init\" phải không?" +msgstr "Có lẽ bạn muốn dùng 'update --init'?" #, c-format msgid "Skipping unmerged submodule %s" @@ -12187,93 +12604,97 @@ msgstr "Bá» qua các mô-Ä‘un-con chÆ°a được hòa trá»™n %s" #, c-format msgid "Skipping submodule '%s'" -msgstr "Bá» qua mô-Ä‘un-con “%sâ€" +msgstr "Bá» qua mô-Ä‘un-con '%s'" + +#, c-format +msgid "cannot clone submodule '%s' without a URL" +msgstr "không thể nhân bản mô-Ä‘un-con '%s' nếu không có URL" #, c-format msgid "Failed to clone '%s'. Retry scheduled" -msgstr "Gặp lá»—i khi nhân bản “%sâ€. Thá» lại lịch trình" +msgstr "Gặp lá»—i khi nhân bản '%s'. Äã lên lịch thá» lại" #, c-format msgid "Failed to clone '%s' a second time, aborting" -msgstr "Gặp lá»—i khi nhân bản “%s†lần thứ hai nên bãi bá»" +msgstr "Gặp lá»—i khi nhân bản '%s' lần thứ hai, huá»· bá»" #, c-format msgid "Unable to checkout '%s' in submodule path '%s'" -msgstr "Không thể lấy ra “%s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +msgstr "Không thể checkout '%s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Unable to rebase '%s' in submodule path '%s'" -msgstr "Không thể cải tổ “%s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +msgstr "Không thể cải tổ '%s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Unable to merge '%s' in submodule path '%s'" -msgstr "Không thể hòa trá»™n (merge) “%s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +msgstr "Không thể hòa trá»™n (merge) '%s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Execution of '%s %s' failed in submodule path '%s'" msgstr "" -"Thá»±c hiện không thà nh công lệnh “%s %s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +"Thá»±c hiện không thà nh công lệnh '%s %s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Submodule path '%s': checked out '%s'\n" -msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: đã checkout “%sâ€\n" +msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': đã checkout '%s'\n" #, c-format msgid "Submodule path '%s': rebased into '%s'\n" -msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: được rebase và o trong “%sâ€\n" +msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': được rebase và o trong '%s'\n" #, c-format msgid "Submodule path '%s': merged in '%s'\n" -msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: được hòa trá»™n và o “%sâ€\n" +msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': được hòa trá»™n và o '%s'\n" #, c-format msgid "Submodule path '%s': '%s %s'\n" -msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: “%s %sâ€\n" +msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': '%s %s'\n" #, c-format msgid "Unable to fetch in submodule path '%s'; trying to directly fetch %s:" msgstr "" -"Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€; thá» lấy vá» trá»±c tiếp %s:" +"Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'; thá» lấy vá» trá»±c tiếp %s:" #, c-format msgid "" "Fetched in submodule path '%s', but it did not contain %s. Direct fetching " "of that commit failed." msgstr "" -"Äã lấy vá» từ Ä‘Æ°á»ng dẫn mô-Ä‘un con “%sâ€, nhÆ°ng nó không chứa %s. Lấy vá» trá»±c " +"Äã lấy vá» từ Ä‘Æ°á»ng dẫn mô-Ä‘un con '%s', nhÆ°ng nó không chứa %s. Lấy vá» trá»±c " "tiếp lần chuyển giao gặp lá»—i đó." #, c-format +msgid "could not initialize submodule at path '%s'" +msgstr "Không thể khởi tạo mô-Ä‘un-con tại Ä‘Æ°á»ng dẫn '%s'" + +#, c-format msgid "" "Submodule (%s) branch configured to inherit branch from superproject, but " "the superproject is not on any branch" msgstr "" -"Nhánh mô-Ä‘un-con (%s) được cấu hình kế thừa nhánh từ siêu dá»± án, nhÆ°ng siêu " -"dá»± án lại không trên bất kỳ nhánh nà o" - -#, c-format -msgid "could not get a repository handle for submodule '%s'" -msgstr "không thể lấy thẻ quản kho cho mô-Ä‘un-con “%sâ€" +"Nhánh mô-Ä‘un-con (%s) được cấu hình kế thừa nhánh từ project cha, nhÆ°ng " +"project cha lại không trên bất kỳ nhánh nà o" #, c-format msgid "Unable to find current revision in submodule path '%s'" msgstr "" -"Không tìm thấy Ä‘iểm xét duyệt hiện hà nh trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +"Không tìm thấy Ä‘iểm xét duyệt hiện hà nh trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Unable to fetch in submodule path '%s'" -msgstr "Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +msgstr "Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Unable to find %s revision in submodule path '%s'" -msgstr "Không tìm thấy Ä‘iểm xét duyệt %s trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +msgstr "Không tìm thấy Ä‘iểm xét duyệt %s trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" #, c-format msgid "Failed to recurse into submodule path '%s'" -msgstr "Gặp lá»—i khi đệ quy và o trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€" +msgstr "Gặp lá»—i khi đệ quy và o trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'" msgid "force checkout updates" -msgstr "ép buá»™c lấy ra các cáºp nháºt" +msgstr "ép buá»™c checkout các cáºp nháºt" msgid "initialize uninitialized submodules before update" msgstr "khởi tạo mô-Ä‘un-con chÆ°a khởi tạo trÆ°á»›c khi cáºp nháºt" @@ -12287,14 +12708,14 @@ msgstr "Ä‘i theo mô-Ä‘un con má»™t cách đệ quy" msgid "don't fetch new objects from the remote site" msgstr "đừng lấy các đối tượng má»›i từ địa chỉ trên mạng" -msgid "path into the working tree" -msgstr "Ä‘Æ°á»ng dẫn đến cây là m việc" +msgid "use the 'checkout' update strategy (default)" +msgstr "dùng chiến lược hòa trá»™n 'checkout' (mặc định)" -msgid "path into the working tree, across nested submodule boundaries" -msgstr "Ä‘Æ°á»ng dẫn đến cây là m việc, chéo biên giá»›i mô-Ä‘un-con lồng nhau" +msgid "use the 'merge' update strategy" +msgstr "dùng chiến lược hòa trá»™n 'merge'" -msgid "rebase, merge, checkout or none" -msgstr "rebase, merge, checkout hoặc không là m gì cả" +msgid "use the 'rebase' update strategy" +msgstr "dùng chiến lược hòa trá»™n 'rebase'" msgid "create a shallow clone truncated to the specified number of revisions" msgstr "" @@ -12309,6 +12730,9 @@ msgstr "nhân bản lần đầu có nên theo khuyến nghị là nông hay khà msgid "don't print cloning progress" msgstr "đừng in tiến trình nhân bản" +msgid "disallow cloning into non-empty directory, implies --init" +msgstr "không cho phép nhân bản và o thÆ° mục trống, ngụ ý --init" + msgid "" "git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] " "[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-" @@ -12320,35 +12744,17 @@ msgstr "" "shallow] [--reference <kho>] [--recursive] [--[no-]single-branch] [--] [</" "Ä‘Æ°á»ng/dẫn/>...]" -msgid "bad value for update parameter" -msgstr "giá trị cho tham số cáºp nháºt bị sai" - -msgid "recurse into submodules" -msgstr "đệ quy và o trong mô-Ä‘un-con" - -msgid "git submodule--helper absorb-git-dirs [<options>] [<path>...]" -msgstr "git submodule--helper absorb-git-dirs [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>…]" - -msgid "check if it is safe to write to the .gitmodules file" -msgstr "chá»n nếu nó là an toà n để ghi và o táºp tin .gitmodules" - -msgid "unset the config in the .gitmodules file" -msgstr "bỠđặt cấu hình trong táºp tin .gitmodules" - -msgid "git submodule--helper config <name> [<value>]" -msgstr "git submodule--helper config <tên> [<giá trị>]" - -msgid "git submodule--helper config --unset <name>" -msgstr "git submodule--helper config --unset <tên>" +msgid "Failed to resolve HEAD as a valid ref." +msgstr "Gặp lá»—i khi phân giải HEAD nhÆ° là má»™t tham chiếu hợp lệ." -msgid "please make sure that the .gitmodules file is in the working tree" -msgstr "hãy đảm bảo rằng táºp tin .gitmodules có trong cây là m việc" +msgid "git submodule absorbgitdirs [<options>] [<path>...]" +msgstr "git submodule absorbgitdirs [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>...]" msgid "suppress output for setting url of a submodule" -msgstr "chặn kết xuất cho cà i đặt url của má»™t mô-Ä‘un-con" +msgstr "chặn đầu ra cho việc đặt url của má»™t mô-Ä‘un-con" -msgid "git submodule--helper set-url [--quiet] <path> <newurl>" -msgstr "git submodule--helper set-url [--quiet] </Ä‘Æ°á»ng/dẫn> <url_má»›i>" +msgid "git submodule set-url [--quiet] <path> <newurl>" +msgstr "git submodule set-url [--quiet] </Ä‘Æ°á»ng/dẫn> <url_má»›i>" msgid "set the default tracking branch to master" msgstr "đặt nhánh theo dõi mặc định thà nh master" @@ -12356,15 +12762,12 @@ msgstr "đặt nhánh theo dõi mặc định thà nh master" msgid "set the default tracking branch" msgstr "đặt nhánh theo dõi mặc định" -msgid "git submodule--helper set-branch [-q|--quiet] (-d|--default) <path>" -msgstr "" -"git submodule--helper set-branch [-q|--quiet](-d|--default)</Ä‘Æ°á»ng/dẫn>" +msgid "git submodule set-branch [-q|--quiet] (-d|--default) <path>" +msgstr "git submodule set-branch [-q|--quiet](-d|--default)</Ä‘Æ°á»ng/dẫn>" -msgid "" -"git submodule--helper set-branch [-q|--quiet] (-b|--branch) <branch> <path>" +msgid "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>" msgstr "" -"git submodule--helper set-branch [-q|--quiet] (-b|--branch) <nhánh> </Ä‘Æ°á»ng/" -"dẫn>" +"git submodule set-branch [-q|--quiet] (-b|--branch) <nhánh> </Ä‘Æ°á»ng/dẫn>" msgid "--branch or --default required" msgstr "cần --branch hoặc --default" @@ -12387,19 +12790,19 @@ msgstr "" #, c-format msgid "creating branch '%s'" -msgstr "Ä‘ang tạo nhánh “%sâ€" +msgstr "Ä‘ang tạo nhánh '%s'" #, c-format msgid "Adding existing repo at '%s' to the index\n" -msgstr "Äang thêm repo có sẵn tại “%s†và o bảng mục lục\n" +msgstr "Äang thêm repo có sẵn tại '%s' và o chỉ mục\n" #, c-format msgid "'%s' already exists and is not a valid git repo" -msgstr "“%s†đã tồn tại từ trÆ°á»›c và không phải là má»™t kho git hợp lệ" +msgstr "'%s' đã tồn tại từ trÆ°á»›c và không phải là má»™t kho git hợp lệ" #, c-format msgid "A git directory for '%s' is found locally with remote(s):\n" -msgstr "ThÆ° mục git cho “%s†được tìm thấy má»™t cách cục bá»™ vá»›i các máy chủ:\n" +msgstr "ThÆ° mục git cho '%s' được tìm thấy má»™t cách cục bá»™ vá»›i các máy chủ:\n" #, c-format msgid "" @@ -12413,39 +12816,41 @@ msgstr "" "Nếu bạn muốn sá» dụng lại thÆ° mục git ná»™i bá»™ nà y thay vì nhân bản lại lần nữa " "từ\n" " %s\n" -"dùng tùy chá»n “--forceâ€. Nếu thÆ° mục git ná»™i bá»™ không phải là má»™t kho đúng " +"dùng tùy chá»n '--force'. Nếu thÆ° mục git ná»™i bá»™ không phải là má»™t kho đúng " "hoặc\n" -"là bạn không chắc chắn Ä‘iá»u đó nghÄ©a là gì thì chá»n tên khác vá»›i tùy chá»n “--" -"nameâ€." +"là bạn không chắc chắn Ä‘iá»u đó nghÄ©a là gì thì chá»n tên khác vá»›i tùy chá»n '--" +"name'." #, c-format msgid "Reactivating local git directory for submodule '%s'\n" -msgstr "Phục hồi sá»± hoạt Ä‘á»™ng của thÆ° mục git ná»™i bá»™ cho mô-Ä‘un-con “%sâ€.\n" +msgstr "Phục hồi sá»± hoạt Ä‘á»™ng của thÆ° mục git ná»™i bá»™ cho mô-Ä‘un-con '%s'.\n" #, c-format msgid "unable to checkout submodule '%s'" -msgstr "không thể lấy ra mô-Ä‘un-con “%sâ€" +msgstr "không thể checkout mô-Ä‘un-con '%s'" + +msgid "please make sure that the .gitmodules file is in the working tree" +msgstr "hãy đảm bảo rằng táºp tin .gitmodules có trong cây là m việc" #, c-format msgid "Failed to add submodule '%s'" -msgstr "Gặp lá»—i khi thêm mô-Ä‘un-con “%sâ€" +msgstr "Gặp lá»—i khi thêm mô-Ä‘un-con '%s'" #, c-format msgid "Failed to register submodule '%s'" -msgstr "Gặp lá»—i khi đăng ký mô-Ä‘un-con “%sâ€" +msgstr "Gặp lá»—i khi đăng ký mô-Ä‘un-con '%s'" #, c-format msgid "'%s' already exists in the index" -msgstr "â€%s†thá»±c sá»± đã tồn tại ở bảng mục lục rồi" +msgstr "'%s' thá»±c sá»± đã tồn tại ở chỉ mục rồi" #, c-format msgid "'%s' already exists in the index and is not a submodule" -msgstr "" -"â€%s†thá»±c sá»± đã tồn tại ở bảng mục lục rồi và không phải là má»™t mô-Ä‘un-con" +msgstr "'%s' thá»±c sá»± đã tồn tại ở chỉ mục rồi và không phải là má»™t mô-Ä‘un-con" #, c-format msgid "'%s' does not have a commit checked out" -msgstr "“%s†không có má»™t lần chuyển giao nà o được lấy ra" +msgstr "'%s' không có má»™t lần chuyển giao nà o được checkout" msgid "branch of repository to add as submodule" msgstr "nhánh của kho để thêm nhÆ° là mô-Ä‘un-con" @@ -12462,8 +12867,8 @@ msgid "" msgstr "" "đặt tên của mô-Ä‘un-con bằng chuá»—i đã cho thay vì mặc định là đưá»ng dẫn của nó" -msgid "git submodule--helper add [<options>] [--] <repository> [<path>]" -msgstr "git submodule--helper add [<các tùy chá»n>] [--] <kho> [</Ä‘Æ°á»ng/dẫn>]" +msgid "git submodule add [<options>] [--] <repository> [<path>]" +msgstr "git submodule add [<các tùy chá»n>] [--] <kho> [</Ä‘Æ°á»ng/dẫn>]" msgid "Relative path can only be used from the toplevel of the working tree" msgstr "" @@ -12472,28 +12877,26 @@ msgstr "" #, c-format msgid "repo URL: '%s' must be absolute or begin with ./|../" -msgstr "repo URL: “%s†phải là đưá»ng dẫn tuyệt đối hoặc là bắt đầu bằng ./|../" +msgstr "repo URL: '%s' phải là đưá»ng dẫn tuyệt đối hoặc là bắt đầu bằng ./|../" #, c-format msgid "'%s' is not a valid submodule name" -msgstr "“%s†không phải là má»™t tên mô-Ä‘un-con hợp lệ" +msgstr "'%s' không phải là má»™t tên mô-Ä‘un-con hợp lệ" -#, c-format -msgid "%s doesn't support --super-prefix" -msgstr "%s không há»— trợ --super-prefix" +msgid "git submodule--helper <command>" +msgstr "git submodule--helper <lệnh>" -#, c-format -msgid "'%s' is not a valid submodule--helper subcommand" -msgstr "“%s†không phải là lệnh con submodule--helper hợp lệ" +msgid "git symbolic-ref [-m <reason>] <name> <ref>" +msgstr "git symbolic-ref [-m <lý do>] <tên> <tham chiếu>" -msgid "git symbolic-ref [<options>] <name> [<ref>]" -msgstr "git symbolic-ref [<các tùy chá»n>] <tên> [<t.chiếu>]" +msgid "git symbolic-ref [-q] [--short] [--no-recurse] <name>" +msgstr "git symbolic-ref [-q] [--short] [--no-recurse] <tên>" -msgid "git symbolic-ref -d [-q] <name>" -msgstr "git symbolic-ref -d [-q] <tên>" +msgid "git symbolic-ref --delete [-q] <name>" +msgstr "git symbolic-ref --delete [-q] <tên>" msgid "suppress error message for non-symbolic (detached) refs" -msgstr "chặn các thông tin lá»—i cho các tham chiếu “không-má»m†(bị tách ra)" +msgstr "chặn các thông tin lá»—i cho các tham chiếu 'không-má»m' (bị tách ra)" msgid "delete symbolic ref" msgstr "xóa tham chiếu má»m" @@ -12501,6 +12904,9 @@ 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)" +msgid "recursively dereference (default)" +msgstr "chế Ä‘á»™ giải tham chiếu đệ quy (mặc định)" + msgid "reason" msgstr "lý do" @@ -12508,61 +12914,63 @@ msgid "reason of the update" msgstr "lý do cáºp nháºt" msgid "" -"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]\n" -" <tagname> [<head>]" +"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" <tagname> [<commit> | <object>]" msgstr "" -"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <táºp-tin>]\n" -" <tên-thẻ> [<head>]" +"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <táºp-tin>] [-e]\n" +" <tên-thẻ> [<lần chuyển giao> | <đối tượng> ]" msgid "git tag -d <tagname>..." -msgstr "git tag -d <tên-thẻ>…" +msgstr "git tag -d <tên-thẻ>..." msgid "" -"git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--" -"points-at <object>]\n" -" [--format=<format>] [--merged <commit>] [--no-merged <commit>] " -"[<pattern>...]" +"git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n" +" [--points-at <object>] [--column[=<options>] | --no-column]\n" +" [--create-reflog] [--sort=<key>] [--format=<format>]\n" +" [--merged <commit>] [--no-merged <commit>] [<pattern>...]" msgstr "" -"git tag -l [-n[<số>]] [--contains <lần_chuyển_giao>] [--no-contains " -"<lần_chuyển_giao>] [--points-at <đối-tượng>]\n" -" [--format=<định_dạng>] [--merged <lần_chuyển_giao>] [--no-merged " -"[<lần_chuyển_giao>]] [<mẫu>…]" +"git tag [-n[<số>]] -l [--contains <lần_chuyển_giao>] [--no-contains " +"<lần_chuyển_giao>]\n" +" [--points-at <đối-tượng>] [--column[=<options>] | --no-column]\n" +" [--create-reflog] [--sort=<key>] [--format=<định dạng>]\n" +" [--merged <lần_chuyển_giao>] [--no-merged <lần_chuyển_giao>] " +"[<mẫu>...]" msgid "git tag -v [--format=<format>] <tagname>..." -msgstr "git tag -v [--format=<định_dạng>] <tên-thẻ>…" +msgstr "git tag -v [--format=<định dạng>] <tên-thẻ>..." #, c-format msgid "tag '%s' not found." -msgstr "không tìm thấy tìm thấy thẻ “%sâ€." +msgstr "không tìm thấy thẻ '%s'." #, c-format msgid "Deleted tag '%s' (was %s)\n" -msgstr "Thẻ đã bị xóa “%s†(từng là %s)\n" +msgstr "Thẻ đã bị xóa '%s' (từng là %s)\n" #, 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" "Viết các ghi chú cho thẻ:\n" " %s\n" -"Những dòng được bắt đầu bằng “%c†sẽ được bá» qua.\n" +"Những dòng được bắt đầu bằng '%s' sẽ được bá» qua.\n" #, 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" "Viết các ghi chú cho thẻ:\n" " %s\n" -"Những dòng được bắt đầu bằng “%c†sẽ được giữ lại; bạn có thể xóa chúng Ä‘i " +"Những dòng được bắt đầu bằng '%s' sẽ được giữ lại; bạn có thể xóa chúng Ä‘i " "nếu muốn.\n" msgid "unable to sign the tag" @@ -12647,17 +13055,20 @@ msgstr "chỉ hiển thị những thẻ mà nó không được hòa trá»™n" msgid "print only tags of the object" msgstr "chỉ hiển thị các thẻ của đối tượng" +msgid "could not start 'git column'" +msgstr "không thể chạy 'git column'" + #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "tùy chá»n '%s' chỉ cho phép dùng trong chế Ä‘á»™ liệt kê" #, c-format msgid "'%s' is not a valid tag name." -msgstr "“%s†không phải thẻ hợp lệ." +msgstr "'%s' không phải thẻ hợp lệ." #, c-format msgid "tag '%s' already exists" -msgstr "thẻ “%s†đã tồn tại rồi" +msgstr "thẻ '%s' đã tồn tại rồi" #, c-format msgid "Invalid cleanup mode %s" @@ -12665,11 +13076,21 @@ msgstr "Chế Ä‘á»™ dá»n dẹp không hợp lệ %s" #, c-format msgid "Updated tag '%s' (was %s)\n" -msgstr "Äã cáºp nháºt thẻ “%s†(trÆ°á»›c là %s)\n" +msgstr "Äã cáºp nháºt thẻ '%s' (trÆ°á»›c là %s)\n" msgid "pack exceeds maximum allowed size" msgstr "gói đã vượt quá cỡ tối Ä‘a được phép" +msgid "failed to write object in stream" +msgstr "gặp lá»—i khi Ä‘á»c đối tượng trong stream" + +#, c-format +msgid "inflate returned (%d)" +msgstr "inflate trả vá» (%d)" + +msgid "invalid blob object from stream" +msgstr "đối tượng blob không hợp lệ trong stream" + msgid "Unpacking objects" msgstr "Äang giải nén các đối tượng" @@ -12687,7 +13108,7 @@ msgstr "gặp lá»—i khi xóa thÆ° mục %s" #, c-format msgid "Testing mtime in '%s' " -msgstr "Äang kiểm thá» mtime trong “%s†" +msgstr "Äang kiểm thá» mtime trong '%s' " msgid "directory stat info does not change after adding a new file" msgstr "thông tin thống kê thÆ° mục không thay đổi sau khi thêm táºp tin má»›i" @@ -12713,38 +13134,37 @@ msgid " OK" msgstr " Äồng ý" msgid "git update-index [<options>] [--] [<file>...]" -msgstr "git update-index [<các tùy chá»n>] [--] [<táºp-tin>…]" +msgstr "git update-index [<các tùy chá»n>] [--] [<táºp-tin>...]" msgid "continue refresh even when index needs update" -msgstr "tiếp tục là m má»›i ngay cả khi bảng mục lục cần được cáºp nháºt" +msgstr "tiếp tục là m má»›i ngay cả khi chỉ mục cần được cáºp nháºt" msgid "refresh: ignore submodules" -msgstr "refresh: lá» Ä‘i mô-Ä‘un-con" +msgstr "refresh: bá» qua mô-Ä‘un-con" msgid "do not ignore new files" msgstr "không bá» qua các táºp tin má»›i tạo" msgid "let files replace directories and vice-versa" -msgstr "để các táºp tin thay thế các thÆ° mục và “vice-versaâ€" +msgstr "để các táºp tin thay thế các thÆ° mục và 'vice-versa'" msgid "notice files missing from worktree" msgstr "thông báo các táºp-tin thiếu trong thÆ°-mục là m việc" msgid "refresh even if index contains unmerged entries" -msgstr "" -"là m tÆ°Æ¡i má»›i tháºm chà khi bảng mục lục chứa các mục tin chÆ°a được hòa trá»™n" +msgstr "là m tÆ°Æ¡i má»›i tháºm chà khi chỉ mục chứa các mục tin chÆ°a được hòa trá»™n" msgid "refresh stat information" msgstr "lấy lại thông tin thống kê" msgid "like --refresh, but ignore assume-unchanged setting" -msgstr "giống --refresh, nhÆ°ng bá» qua các cà i đặt “assume-unchangedâ€" +msgstr "giống --refresh, nhÆ°ng bá» qua các cà i đặt 'assume-unchanged'" msgid "<mode>,<object>,<path>" msgstr "<chế_Ä‘á»™>,<đối_tượng>,<Ä‘Æ°á»ng_dẫn>" msgid "add the specified entry to the index" -msgstr "thêm các táºp tin đã chỉ ra và o bảng mục lục" +msgstr "thêm các táºp tin đã chỉ ra và o chỉ mục" msgid "mark files as \"not changing\"" msgstr "đánh dấu các táºp tin là \"không thay đổi\"" @@ -12753,7 +13173,7 @@ msgid "clear assumed-unchanged bit" msgstr "xóa bÃt assumed-unchanged (giả định là không thay đổi)" msgid "mark files as \"index-only\"" -msgstr "đánh dấu các táºp tin là “chỉ-Ä‘á»câ€" +msgstr "đánh dấu các táºp tin là 'chỉ-Ä‘á»c'" msgid "clear skip-worktree bit" msgstr "xóa bÃt skip-worktree" @@ -12762,8 +13182,7 @@ msgid "do not touch index-only entries" msgstr "đừng Ä‘á»™ng và o các mục index-only" msgid "add to index only; do not add content to object database" -msgstr "" -"chỉ thêm và o bảng mục lục; không thêm ná»™i dung và o cÆ¡ sở dữ liệu đối tượng" +msgstr "chỉ thêm và o chỉ mục; không thêm ná»™i dung và o cÆ¡ sở dữ liệu đối tượng" msgid "remove named paths even if present in worktree" msgstr "" @@ -12771,13 +13190,13 @@ msgstr "" "là m việc" msgid "with --stdin: input lines are terminated by null bytes" -msgstr "vá»›i tùy chá»n --stdin: các dòng đầu và o được chấm dứt bởi ký tá»± null" +msgstr "vá»›i tùy chá»n --stdin: các dòng đầu và o được kết thúc bởi ký tá»± null" msgid "read list of paths to be updated from standard input" -msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn cần cáºp nháºt từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn cần cáºp nháºt từ stdin" msgid "add entries from standard input to the index" -msgstr "không thể Ä‘á»c các mục từ đầu và o tiêu chuẩn và o bảng mục lục" +msgstr "không thể Ä‘á»c các mục từ stdin và o chỉ mục" msgid "repopulate stages #2 and #3 for the listed paths" msgstr "phục hồi các trạng thái #2 và #3 cho các Ä‘Æ°á»ng dẫn được liệt kê" @@ -12789,16 +13208,19 @@ msgid "ignore files missing from worktree" msgstr "bá» qua các táºp-tin thiếu trong thÆ°-mục là m việc" msgid "report actions to standard output" -msgstr "báo cáo các thao tác ra thiết bị xuất chuẩn" +msgstr "ghi các thao tác ra stdout" msgid "(for porcelains) forget saved unresolved conflicts" -msgstr "(cho “porcelainsâ€) quên các xung Ä‘á»™t chÆ°a được giải quyết đã ghi" +msgstr "(cho 'porcelains') quên các xung Ä‘á»™t chÆ°a được giải quyết đã ghi" msgid "write index in this format" -msgstr "ghi mục lục ở định dạng nà y" +msgstr "ghi chỉ mục ở định dạng nà y" + +msgid "report on-disk index format version" +msgstr "cho biết phiên bản định dạng chỉ mục trên Ä‘Ä©a" msgid "enable or disable split index" -msgstr "báºt/tắt chia cắt bảng mục lục" +msgstr "báºt/tắt chia cắt chỉ mục" msgid "enable/disable untracked cache" msgstr "báºt/tắt bá»™ đệm không theo vết" @@ -12810,7 +13232,7 @@ msgid "enable untracked cache without testing the filesystem" msgstr "báºt bá»™ đệm không theo vết mà không kiểm tra hệ thống táºp tin" msgid "write out the index even if is not flagged as changed" -msgstr "ghi ra mục lục ngay cả khi không được đánh cá» là có thay đổi" +msgstr "ghi ra chỉ mục ngay cả khi không được đánh cá» là có thay đổi" msgid "enable or disable file system monitor" msgstr "báºt/tắt theo dõi hệ thống táºp tin" @@ -12821,19 +13243,27 @@ msgstr "đánh dấu các táºp tin là hợp lệ fsmonitor" msgid "clear fsmonitor valid bit" msgstr "xóa bÃt hợp lệ fsmonitor" +#, c-format +msgid "%d\n" +msgstr "%d\n" + +#, c-format +msgid "index-version: was %d, set to %d" +msgstr "index-version: Ä‘ang là %d, đặt vá» %d" + msgid "" "core.splitIndex is set to false; remove or change it, if you really want to " "enable split index" msgstr "" "core.splitIndex được đặt là sai; xóa bá» hay thay đổi nó, nếu bạn thá»±c sá»± " -"muốn báºt chia tách mục lục" +"muốn báºt chia tách chỉ mục" msgid "" "core.splitIndex is set to true; remove or change it, if you really want to " "disable split index" msgstr "" "core.splitIndex được đặt là đúng; xóa bá» hay thay đổi nó, nếu bạn thá»±c sá»± " -"muốn tắt chia tách mục lục" +"muốn tắt chia tách chỉ mục" msgid "" "core.untrackedCache is set to true; remove or change it, if you really want " @@ -12854,7 +13284,7 @@ msgstr "" #, c-format msgid "Untracked cache enabled for '%s'" -msgstr "Nhá»› đệm không theo vết được báºt cho “%sâ€" +msgstr "Nhá»› đệm không theo vết được báºt cho '%s'" msgid "core.fsmonitor is unset; set it if you really want to enable fsmonitor" msgstr "" @@ -12873,11 +13303,11 @@ msgstr "" msgid "fsmonitor disabled" msgstr "fsmonitor bị tắt" -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<các tùy chá»n>] -d <refname> [<biến-cÅ©>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<các tùy chá»n>] -d <refname> [<oid-cÅ©>]" -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "git update-ref [<các tùy chá»n>] <refname> <biến-má»›i> [<biến-cÅ©>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "git update-ref [<các tùy chá»n>] <refname> <oid-má»›i> [<oid-cÅ©>]" msgid "git update-ref [<options>] --stdin [-z]" msgstr "git update-ref [<các tùy chá»n>] --stdin [-z]" @@ -12889,19 +13319,23 @@ msgid "update <refname> not the one it points to" msgstr "cáºp nháºt <tên-tham-chiếu> không phải cái nó chỉ tá»›i" msgid "stdin has NUL-terminated arguments" -msgstr "đầu và o tiêu chuẩn có các đối số được chấm dứt bởi NUL" +msgstr "stdin có các đối số được kết thúc bởi NUL" msgid "read updates from stdin" -msgstr "Ä‘á»c cáºp nháºt từ đầu và o tiêu chuẩn" +msgstr "Ä‘á»c cáºp nháºt từ stdin" msgid "update the info files from scratch" msgstr "cáºp nháºt các táºp tin thông tin từ Ä‘iểm xuất phát" -msgid "git upload-pack [<options>] <dir>" -msgstr "git upload-pack [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn>" +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] <thÆ° mục>" msgid "quit after a single request/response exchange" -msgstr "thoát sau khi má»™t trao đổi yêu cầu hay trả lá»i Ä‘Æ¡n" +msgstr "thoát sau má»™t trao đổi yêu cầu/trả lá»i" msgid "serve up the info/refs for git-http-backend" msgstr "phục vụ info/refs (thông tin/tham chiếu) cho git-http-backend" @@ -12912,8 +13346,8 @@ msgstr "đừng thá» <thÆ°_mục>/.git/ nếu <thÆ°_mục> không phải là th msgid "interrupt transfer after <n> seconds of inactivity" msgstr "ngắt truyá»n thông sau <n> giây không hoạt Ä‘á»™ng" -msgid "git verify-commit [-v | --verbose] <commit>..." -msgstr "git verify-commit [-v | --verbose] <lần_chuyển_giao>…" +msgid "git verify-commit [-v | --verbose] [--raw] <commit>..." +msgstr "git verify-commit [-v | --verbose] [--raw] <lần_chuyển_giao>..." msgid "print commit contents" msgstr "hiển thị ná»™i dung của lần chuyển giao" @@ -12921,8 +13355,8 @@ 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ô" -msgid "git verify-pack [-v | --verbose] [-s | --stat-only] <pack>..." -msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] <gói>…" +msgid "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..." +msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <gói>.idx..." msgid "verbose" msgstr "chi tiết" @@ -12930,69 +13364,106 @@ msgstr "chi tiết" msgid "show statistics only" msgstr "chỉ hiển thị thống kê" -msgid "git verify-tag [-v | --verbose] [--format=<format>] <tag>..." -msgstr "git verify-tag [-v | --verbose] [--format=<định_dạng>] <thẻ>…" +msgid "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..." +msgstr "" +"git verify-tag [-v | --verbose] [--format=<định dạng>] [--raw] <thẻ>..." msgid "print tag contents" msgstr "hiển thị ná»™i dung của thẻ" -msgid "git worktree add [<options>] <path> [<commit-ish>]" -msgstr "git worktree add [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn> [<commit-ish>]" +msgid "" +"git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n" +" [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]" +msgstr "" +"git worktree add [-f] [--detach] [--checkout] [--lock [--reason <lý do>]]\n" +" [--orphan] [(-b | -B) <nhánh-má»›i>] <Ä‘Æ°á»ng/dẫn> [<commit-" +"ish>]" -msgid "git worktree list [<options>]" -msgstr "git worktree list [<các tùy chá»n>]" +msgid "git worktree list [-v | --porcelain [-z]]" +msgstr "git worktree list [-v | --porcelain [-z]]" -msgid "git worktree lock [<options>] <path>" -msgstr "git worktree lock [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn>" +msgid "git worktree lock [--reason <string>] <worktree>" +msgstr "git worktree lock [--reason <lý do>] <cây là m việc>" msgid "git worktree move <worktree> <new-path>" -msgstr "git worktree move <worktree> </Ä‘Æ°á»ng/dẫn/má»›i>" +msgstr "git worktree move <cây là m việc> </Ä‘Æ°á»ng/dẫn/má»›i>" -msgid "git worktree prune [<options>]" -msgstr "git worktree prune [<các tùy chá»n>]" +msgid "git worktree prune [-n] [-v] [--expire <expire>]" +msgstr "git worktree prune [-n] [-v] [--expire <khi nà o hết hạn>]" -msgid "git worktree remove [<options>] <worktree>" -msgstr "git worktree remove [<các tùy chá»n>] <worktree>" +msgid "git worktree remove [-f] <worktree>" +msgstr "git worktree remove [-f] <cây là m việc>" msgid "git worktree repair [<path>...]" msgstr "git worktree repair [</Ä‘Æ°á»ng/dẫn/>...]" -msgid "git worktree unlock <path>" -msgstr "git worktree unlock </Ä‘Æ°á»ng/dẫn>" +msgid "git worktree unlock <worktree>" +msgstr "git worktree unlock <cây là m việc>" + +msgid "No possible source branch, inferring '--orphan'" +msgstr "Không có nhánh gốc, Ä‘oán là --orphan" + +#, c-format +msgid "" +"If you meant to create a worktree containing a new unborn branch\n" +"(branch with no commits) for this repository, you can do so\n" +"using the --orphan flag:\n" +"\n" +" git worktree add --orphan -b %s %s\n" +msgstr "" +"Nếu bạn muốn tạo cây là m việc vá»›i nhánh chÆ°a sinh\n" +"(nhánh chÆ°a có lần chuyển giao) cho kho chứa nà y, bạn có thể dùng\n" +"tuỳ chá»n --orphan:\n" +"\n" +" git worktree add --orphan -b %s %s\n" + +#, c-format +msgid "" +"If you meant to create a worktree containing a new unborn branch\n" +"(branch with no commits) for this repository, you can do so\n" +"using the --orphan flag:\n" +"\n" +" git worktree add --orphan %s\n" +msgstr "" +"Nếu bạn muốn tạo cây là m việc vá»›i nhánh chÆ°a sinh\n" +"(nhánh chÆ°a có lần chuyển giao) cho kho chứa nà y, bạn có thể dùng\n" +"tuỳ chá»n --orphan:\n" +"\n" +" git worktree add --orphan %s\n" #, c-format msgid "Removing %s/%s: %s" msgstr "Äang xóa %s/%s: %s" msgid "report pruned working trees" -msgstr "báo cáo các cây là m việc đã prune" +msgstr "liệt kê các cây là m việc đã prune" msgid "expire working trees older than <time>" msgstr "các cây là m việc hết hạn cÅ© hÆ¡n khoảng <thá»i gian>" #, c-format msgid "'%s' already exists" -msgstr "“%s†đã có từ trÆ°á»›c rồi" +msgstr "'%s' đã có từ trÆ°á»›c rồi" #, c-format msgid "unusable worktree destination '%s'" -msgstr "Ä‘Ãch cây là m việc không sá» dụng được “%sâ€" +msgstr "Ä‘Ãch cây là m việc không sá» dụng được '%s'" #, c-format msgid "" "'%s' is a missing but locked worktree;\n" "use '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear" msgstr "" -"“%s†bị mất nhÆ°ng cây là m việc bị khóa;\n" -"dùng “%s -f -f†để ghi đè, hoặc “unlock†và “prune†hay “remove†để xóa" +"'%s' bị mất nhÆ°ng cây là m việc bị khóa;\n" +"dùng '%s -f -f' để ghi đè, hoặc 'unlock' và 'prune' hay 'remove' để xóa" #, c-format msgid "" "'%s' is a missing but already registered worktree;\n" "use '%s -f' to override, or 'prune' or 'remove' to clear" msgstr "" -"“%s†bị mất nhÆ°ng cây là m việc đã được đăng ký;\n" -"dùng “%s -f†để ghi đè, hoặc “prune†hay “remove†để xóa" +"'%s' bị mất nhÆ°ng cây là m việc đã được đăng ký;\n" +"dùng '%s -f' để ghi đè, hoặc 'prune' hay 'remove' để xóa" #, c-format msgid "failed to copy '%s' to '%s'; sparse-checkout may not work correctly" @@ -13000,37 +13471,62 @@ msgstr "gặp lá»—i khi sao chép '%s' sang '%s'; không thể là m việc đún #, c-format msgid "failed to copy worktree config from '%s' to '%s'" -msgstr "gặp lá»—i khi sao chép cấu hình cây là m việc từ “%s†sang “%sâ€" +msgstr "gặp lá»—i khi sao chép cấu hình cây là m việc từ '%s' sang '%s'" #, c-format msgid "failed to unset '%s' in '%s'" -msgstr "gặp lá»—i bỠđặt “%s†trong “%sâ€" +msgstr "gặp lá»—i bỠđặt '%s' trong '%s'" #, c-format msgid "could not create directory of '%s'" -msgstr "không thể tạo thÆ° mục của “%sâ€" +msgstr "không thể tạo thÆ° mục của '%s'" msgid "initializing" msgstr "khởi tạo" #, c-format +msgid "could not find created worktree '%s'" +msgstr "không tìm thấy cây là m việc '%s'" + +#, c-format msgid "Preparing worktree (new branch '%s')" -msgstr "Äang chuẩn bị cây là m việc (nhánh má»›i “%sâ€)" +msgstr "Äang chuẩn bị cây là m việc (nhánh má»›i '%s')" #, c-format msgid "Preparing worktree (resetting branch '%s'; was at %s)" -msgstr "Äang chuẩn bị cây là m việc (Ä‘ang cà i đặt nhánh “%sâ€, trÆ°á»›c đây tại %s)" +msgstr "Äang chuẩn bị cây là m việc (Ä‘ang tái đặt nhánh '%s'; trÆ°á»›c đây tại %s)" #, c-format msgid "Preparing worktree (checking out '%s')" -msgstr "Äang chuẩn bị cây là m việc (Ä‘ang lấy ra “%sâ€)" +msgstr "Äang chuẩn bị cây là m việc (Ä‘ang checkout '%s')" + +#, c-format +msgid "unreachable: invalid reference: %s" +msgstr "không tham chiếu được: tham chiếu không hợp lệ: %s" #, c-format msgid "Preparing worktree (detached HEAD %s)" -msgstr "Äang chuẩn bị cây là m việc (HEAD đã tách rá»i “%sâ€)" +msgstr "Äang chuẩn bị cây là m việc (HEAD đã tách rá»i '%s')" + +#, c-format +msgid "" +"HEAD points to an invalid (or orphaned) reference.\n" +"HEAD path: '%s'\n" +"HEAD contents: '%s'" +msgstr "" +"HEAD trỠđến tham chiếu sai (hoặc mồ côi).\n" +"ÄÆ°á»ng dẫn HEAD: '%s'\n" +"Ná»™i dung HEAD: '%s'" + +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" +msgstr "" +"Không tồn tại tham chiếu cục bá»™ hay trên máy chủ mặc dù có cấu hình\n" +"máy chủ, dừng lại; hãy dùng 'add -f' để ép buá»™c hoặc thá»±c hiện kéo vá» trÆ°á»›c" msgid "checkout <branch> even if already checked out in other worktree" -msgstr "lấy ra <nhánh> ngay cả khi nó đã được lấy ra ở cây là m việc khác" +msgstr "checkout <nhánh> ngay cả khi nó đã được checkout ở cây là m việc khác" msgid "create a new branch" msgstr "tạo nhánh má»›i" @@ -13038,11 +13534,14 @@ msgstr "tạo nhánh má»›i" msgid "create or reset a branch" msgstr "tạo hay đặt lại má»™t nhánh" +msgid "create unborn branch" +msgstr "tạo nhánh chÆ°a sinh" + msgid "populate the new working tree" msgstr "di chuyển cây là m việc má»›i" msgid "keep the new working tree locked" -msgstr "giữ cây là m việc má»›i bị khóa" +msgstr "tiếp tục khoá cây là m việc má»›i" msgid "reason for locking" msgstr "lý do khóa" @@ -13057,6 +13556,10 @@ msgstr "có khá»›p tên tên nhánh má»›i vá»›i má»™t nhánh theo dõi máy chá» msgid "options '%s', '%s', and '%s' cannot be used together" msgstr "tùy chá»n '%s', '%s' và '%s' không thể dùng cùng nhau" +#, c-format +msgid "option '%s' and commit-ish cannot be used together" +msgstr "tùy chá»n '%s' và commit-ish không thể dùng cùng nhau" + msgid "added with --lock" msgstr "được thêm vá»›i --lock" @@ -13068,30 +13571,30 @@ msgstr "hiển thị chú thÃch và lý do mở rá»™ng, nếu có" msgid "add 'prunable' annotation to worktrees older than <time>" msgstr "" -"thêm chú thÃch kiểu “prunable†cho các cây là m việc hết hạn cÅ© hÆ¡n khoảng " +"thêm chú thÃch kiểu 'prunable' cho các cây là m việc hết hạn cÅ© hÆ¡n khoảng " "<thá»i gian>" msgid "terminate records with a NUL character" -msgstr "chấm dứt các bản ghi bằng ký tá»± NULL" +msgstr "kết thúc các bản ghi bằng ký tá»± NULL" #, c-format msgid "'%s' is not a working tree" msgstr "%s không phải là cây là m việc" msgid "The main working tree cannot be locked or unlocked" -msgstr "Cây thÆ° mục là m việc chÃnh không thể khóa hay bá» khóa được" +msgstr "Cây là m việc chÃnh không thể khóa hay bá» khóa được" #, c-format msgid "'%s' is already locked, reason: %s" -msgstr "“%s†đã được khóa rồi, lý do: %s" +msgstr "'%s' đã được khóa rồi, lý do: %s" #, c-format msgid "'%s' is already locked" -msgstr "“%s†đã được khóa rồi" +msgstr "'%s' đã được khóa rồi" #, c-format msgid "'%s' is not locked" -msgstr "“%s†chÆ°a bị khóa" +msgstr "'%s' chÆ°a bị khóa" msgid "working trees containing submodules cannot be moved or removed" msgstr "cây là m việc có chứa mô-Ä‘un-con không thể di chuyển hay xóa bá»" @@ -13101,11 +13604,11 @@ msgstr "ép buá»™c ngay cả khi cây là m việc Ä‘ang bẩn hay bị khóa" #, c-format msgid "'%s' is a main working tree" -msgstr "“%s†là cây là m việc chÃnh" +msgstr "'%s' là cây là m việc chÃnh" #, c-format msgid "could not figure out destination name from '%s'" -msgstr "không thể phác há»a ra tên Ä‘Ãch đến “%sâ€" +msgstr "không thể phác há»a ra tên Ä‘Ãch đến '%s'" #, c-format msgid "" @@ -13113,14 +13616,14 @@ msgid "" "use 'move -f -f' to override or unlock first" msgstr "" "không thể di chuyển má»™t cây-là m-việc bị khóa, khóa vì: %s\n" -"dùng “move -f -f†để ghi đè hoặc mở khóa trÆ°á»›c đã" +"dùng 'move -f -f' để ghi đè hoặc mở khóa trÆ°á»›c đã" msgid "" "cannot move a locked working tree;\n" "use 'move -f -f' to override or unlock first" msgstr "" "không thể di chuyển má»™t cây-là m-việc bị khóa;\n" -"dùng “move -f -f†để ghi đè hoặc mở khóa trÆ°á»›c đã" +"dùng 'move -f -f' để ghi đè hoặc mở khóa trÆ°á»›c đã" #, c-format msgid "validation failed, cannot move working tree: %s" @@ -13128,21 +13631,21 @@ msgstr "thẩm tra gặp lá»—i, không thể di chuyển má»™t cây-là m-việc: #, c-format msgid "failed to move '%s' to '%s'" -msgstr "gặp lá»—i khi chuyển “%s†sang “%sâ€" +msgstr "gặp lá»—i khi chuyển '%s' sang '%s'" #, c-format msgid "failed to run 'git status' on '%s'" -msgstr "gặp lá»—i khi chạy “git status†và o “%sâ€" +msgstr "gặp lá»—i khi chạy 'git status' và o '%s'" #, c-format msgid "'%s' contains modified or untracked files, use --force to delete it" msgstr "" -"“%s†có chứa các táºp tin đã bị sá»a chữa hoặc chÆ°a được theo dõi, hãy dùng --" +"'%s' có chứa các táºp tin đã bị sá»a chữa hoặc chÆ°a được theo dõi, hãy dùng --" "force để xóa nó" #, c-format msgid "failed to run 'git status' on '%s', code %d" -msgstr "gặp lá»—i khi chạy “git status†trong “%sâ€, mã %d" +msgstr "gặp lá»—i khi chạy 'git status' trong '%s', mã %d" msgid "force removal even if worktree is dirty or locked" msgstr "ép buá»™c di chuyển tháºm chà cả khi cây là m việc Ä‘ang bẩn hay bị khóa" @@ -13153,14 +13656,14 @@ msgid "" "use 'remove -f -f' to override or unlock first" msgstr "" "không thể xóa bá» má»™t cây-là m-việc bị khóa, khóa vì: %s\n" -"dùng “remove -f -f†để ghi đè hoặc mở khóa trÆ°á»›c đã" +"dùng 'remove -f -f' để ghi đè hoặc mở khóa trÆ°á»›c đã" msgid "" "cannot remove a locked working tree;\n" "use 'remove -f -f' to override or unlock first" msgstr "" "không thể xóa bá» má»™t cây-là m-việc bị khóa;\n" -"dùng “remove -f -f†để ghi đè hoặc mở khóa trÆ°á»›c đã" +"dùng 'remove -f -f' để ghi đè hoặc mở khóa trÆ°á»›c đã" #, c-format msgid "validation failed, cannot remove working tree: %s" @@ -13186,17 +13689,73 @@ msgstr "ghi đối tượng cây (tree) cho <tiá»n tố> thÆ° mục con" msgid "only useful for debugging" msgstr "chỉ hữu Ãch khi cần gỡ lá»—i" +msgid "core.fsyncMethod = batch is unsupported on this platform" +msgstr "core.fsyncMethod = batch không được há»— trợ trên ná»n tảng nà y" + +#, c-format +msgid "could not parse bundle list key %s with value '%s'" +msgstr "không thể Ä‘á»c danh sách bundle khoá %s giá trị '%s'" + +#, c-format +msgid "bundle list at '%s' has no mode" +msgstr "bundle list at '%s' has no mode" + +msgid "failed to create temporary file" +msgstr "không thể tạo táºp tin tạm thá»i" + +msgid "insufficient capabilities" +msgstr "không đủ quyá»n hạn" + +#, c-format +msgid "file downloaded from '%s' is not a bundle" +msgstr "táºp tin lấy vá» từ '%s' không phải là bundle" + +msgid "failed to store maximum creation token" +msgstr "gặp lá»—i khi lÆ°u token tạo tối Ä‘a" + +#, c-format +msgid "unrecognized bundle mode from URI '%s'" +msgstr "không nháºn ra định dạng bundle từ URI '%s'" + +#, c-format +msgid "exceeded bundle URI recursion limit (%d)" +msgstr "vượt quá giá»›i hạn đệ quy URI (%d)" + +#, c-format +msgid "failed to download bundle from URI '%s'" +msgstr "gặp lá»—i khi tải bundle từ URI '%s'" + +#, c-format +msgid "file at URI '%s' is not a bundle or bundle list" +msgstr "táºp tin ở URI '%s' không phải bundle hay danh sách bundle" + +#, c-format +msgid "bundle-uri: unexpected argument: '%s'" +msgstr "bundle-uri: không nháºn ra đối số: '%s'" + +msgid "bundle-uri: expected flush after arguments" +msgstr "bundle-uri: cần flush dữ liệu sau các tham số" + +msgid "bundle-uri: got an empty line" +msgstr "bundle-uri: nháºn được dòng trống" + +msgid "bundle-uri: line is not of the form 'key=value'" +msgstr "bundle-uri: dòng không có dạng 'key=value'" + +msgid "bundle-uri: line has empty key or value" +msgstr "bundle-uri: dòng có key trống hoặc value trống" + #, c-format msgid "unrecognized bundle hash algorithm: %s" -msgstr "không hiểu thuáºt toán băm dữ liệu bundle: %s" +msgstr "không hiểu thuáºt toán băm bundle: %s" #, c-format msgid "unknown capability '%s'" -msgstr "không hiểu dung lượng “%sâ€" +msgstr "không hiểu dung lượng '%s'" #, c-format msgid "'%s' does not look like a v2 or v3 bundle file" -msgstr "“%s†không giống nhÆ° táºp tin v2 hay v3 bundle (định dạng dump của git)" +msgstr "'%s' không giống nhÆ° táºp tin bundle v2 hay v3 (định dạng dump của git)" #, c-format msgid "unrecognized header: %s%s (%d)" @@ -13208,6 +13767,13 @@ 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" +msgstr "" +"má»™t số lần chuyển giao tiên quyết tồn tại trong object store, nhÆ°ng không " +"nằm trong lịch sá» của kho chứa" + #, c-format msgid "The bundle contains this ref:" msgid_plural "The bundle contains these %<PRIuMAX> refs:" @@ -13221,18 +13787,26 @@ msgid "The bundle requires this ref:" msgid_plural "The bundle requires these %<PRIuMAX> refs:" msgstr[0] "Lệnh bundle yêu cầu %<PRIuMAX> tham chiếu nà y:" +#, c-format +msgid "The bundle uses this hash algorithm: %s" +msgstr "Lệnh bundle dùng thuáºt toán băm sau: %s" + +#, c-format +msgid "The bundle uses this filter: %s" +msgstr "Lệnh bundle dùng bá»™ lá»c sau: %s" + msgid "unable to dup bundle descriptor" -msgstr "không thể nhân đôi bá»™ mô tả bundle" +msgstr "không thể dup bundle descriptor" msgid "Could not spawn pack-objects" -msgstr "Không thể sản sinh đối tượng gói" +msgstr "Không thể spawn pack-objects" msgid "pack-objects died" -msgstr "đối tượng gói đã chết" +msgstr "pack-objects đã chết" #, c-format msgid "ref '%s' is excluded by the rev-list options" -msgstr "th.chiếu “%s†bị loại trừ bởi các tùy chá»n rev-list" +msgstr "th.chiếu '%s' bị loại trừ bởi các tùy chá»n rev-list" #, c-format msgid "unsupported bundle version %d" @@ -13247,25 +13821,29 @@ msgstr "Từ chối tạo má»™t bó dữ liệu trống rá»—ng." #, c-format msgid "cannot create '%s'" -msgstr "không thể tạo “%sâ€" +msgstr "không thể tạo '%s'" msgid "index-pack died" -msgstr "mục lục gói đã chết" +msgstr "index-pack đã chết" msgid "terminating chunk id appears earlier than expected" -msgstr "mã mảnh kết thúc sá»›m hÆ¡n bình thÆ°á»ng" +msgstr "id chunk kết thúc sá»›m hÆ¡n bình thÆ°á»ng" + +#, c-format +msgid "chunk id %<PRIx32> not %d-byte aligned" +msgstr "id chunk %<PRIx32> không thẳng %d-byte" #, c-format msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>" -msgstr "bù mảnh không đúng cách %<PRIx64> và %<PRIx64>" +msgstr "chunk offset bất thÆ°á»ng %<PRIx64> và %<PRIx64>" #, c-format msgid "duplicate chunk ID %<PRIx32> found" -msgstr "tìm thấy ID của mảnh bị trùng lặp %<PRIx32>" +msgstr "tìm thấy ID của chunk bị trùng lặp %<PRIx32>" #, c-format msgid "final chunk has non-zero id %<PRIx32>" -msgstr "mảnh cuối cùng có id không bằng không %<PRIx32>" +msgstr "chunk cuối cùng có id không bằng không %<PRIx32>" msgid "invalid hash version" msgstr "phiên bản băm không hợp lệ" @@ -13275,7 +13853,7 @@ msgid "invalid color value: %.*s" msgstr "giá trị mà u không hợp lệ: %.*s" msgid "Add file contents to the index" -msgstr "Thêm ná»™i dung táºp tin và o bảng mục lục" +msgstr "Thêm ná»™i dung táºp tin và o chỉ mục" msgid "Apply a series of patches from a mailbox" msgstr "Ãp dụng má»™t chuá»—i các miếng và từ má»™t mailbox" @@ -13284,8 +13862,7 @@ msgid "Annotate file lines with commit information" msgstr "Các dòng diá»…n giải táºp tin vá»›i thông tin chuyển giao" msgid "Apply a patch to files and/or to the index" -msgstr "" -"Ãp dụng má»™t miếng vá cho các táºp tin đã chỉ ra và /hoặc và o bảng mục lục" +msgstr "Ãp dụng má»™t bản vá cho các táºp tin đã chỉ ra và /hoặc và o chỉ mục" msgid "Import a GNU Arch repository into Git" msgstr "Nháºp má»™t kho GNU Arch và o má»™t kho Git" @@ -13310,8 +13887,8 @@ msgstr "SÆ°u táºp thông tin ngÆ°á»i dùng để báo cáo lá»—i" msgid "Move objects and refs by archive" msgstr "Di chuyển các đối tượng và tham chiếu theo kho lÆ°u" -msgid "Provide content or type and size information for repository objects" -msgstr "Cung cấp ná»™i dung hoặc thông tin vá» kiểu và cỡ cho các đối tượng kho" +msgid "Provide contents or details of repository objects" +msgstr "Cung cấp ná»™i dung hoặc thông tin vá» các đối tượng kho" msgid "Display gitattributes information" msgstr "Hiển thị thông tin gitattributes" @@ -13326,13 +13903,13 @@ msgid "Ensures that a reference name is well formed" msgstr "Äảm bảo rằng má»™t tên tham chiếu ở dạng thức tốt" msgid "Switch branches or restore working tree files" -msgstr "Chuyển các nhánh hoặc phục hồi lại các táºp tin cây là m việc" +msgstr "Chuyển các nhánh hoặc phục hồi lại các táºp tin trong cây là m việc" msgid "Copy files from the index to the working tree" -msgstr "Sao chép các táºp tin từ mục lục ra cây là m việc" +msgstr "Sao chép các táºp tin từ chỉ mục ra cây là m việc" msgid "Find commits yet to be applied to upstream" -msgstr "Tìm những lần chuyển giao còn chÆ°a được áp dụng lên thượng nguồn" +msgstr "Tìm những lần chuyển giao chÆ°a được đẩy lên thượng nguồn" msgid "Apply the changes introduced by some existing commits" msgstr "Ãp dụng các thay đổi được Ä‘Æ°a ra bởi má»™t số lần chuyển giao sẵn có" @@ -13369,13 +13946,13 @@ msgid "Retrieve and store user credentials" msgstr "Nháºn và lÆ°u chứng nháºn của ngÆ°á»i dùng" msgid "Helper to temporarily store passwords in memory" -msgstr "Bá»™ há»— trợ để lÆ°u máºt khẩu tạm thá»i trong bá»™ nhá»›" +msgstr "helper để lÆ°u máºt khẩu tạm thá»i trong bá»™ nhá»›" msgid "Helper to store credentials on disk" -msgstr "Bá»™ há»— trợ để lÆ°u chứng nháºn và o Ä‘Ä©a" +msgstr "helper để lÆ°u chứng nháºn và o Ä‘Ä©a" msgid "Export a single commit to a CVS checkout" -msgstr "Xuất má»™t lần chuyển giao thà nh má»™t lần lấy ra CVS" +msgstr "Xuất má»™t lần chuyển giao thà nh má»™t lần checkout CVS" msgid "Salvage your data out of another SCM people love to hate" msgstr "Xem xét giá trị dữ liệu của bạn khá»i ngÆ°á»i khác yêu SCM để ghét" @@ -13384,23 +13961,26 @@ msgid "A CVS server emulator for Git" msgstr "Má»™t bá»™ mô phá»ng máy dịch vụ CVS cho Git" msgid "A really simple server for Git repositories" -msgstr "Má»™t máy phục vụ thá»±c sá»± Ä‘Æ¡n giản dà nh cho kho Git" +msgstr "Má»™t máy chủ thá»±c sá»± Ä‘Æ¡n giản dà nh cho kho Git" msgid "Give an object a human readable name based on an available ref" msgstr "" "ÄÆ°a ra má»™t đối tượng dá»±a trên má»™t tên ở dạng con ngÆ°á»i Ä‘á»c được trên má»™t " "tham chiếu sẵn có" +msgid "Generate a zip archive of diagnostic information" +msgstr "tạo táºp tin nén zip của bản báo cáo" + msgid "Show changes between commits, commit and working tree, etc" msgstr "" "Hiển thị các thay đổi giữa những lần chuyển giao, giữa má»™t lần chuyển giao " "và cây là m việc, v.v.." msgid "Compares files in the working tree and the index" -msgstr "So sánh các táºp tin trong cây là m việc và bảng mục lục" +msgstr "So sánh các táºp tin trong cây là m việc và chỉ mục" msgid "Compare a tree to the working tree or index" -msgstr "So sánh các cây trong cây là m việc hoặc bảng mục lục" +msgstr "So sánh các cây trong cây là m việc hoặc chỉ mục" msgid "Compares the content and mode of blobs found via two tree objects" msgstr "" @@ -13434,7 +14014,7 @@ msgid "Run a Git command on a list of repositories" msgstr "Chạy lệnh Git trên danh sách các kho chứa" msgid "Prepare patches for e-mail submission" -msgstr "Chuẩn bị các miếng vá để gá»i qua thÆ° Ä‘iện tá»" +msgstr "Chuẩn bị các bản vá để gá»i qua thÆ° Ä‘iện tá»" msgid "Verifies the connectivity and validity of the objects in the database" msgstr "" @@ -13454,8 +14034,8 @@ msgstr "In ra những dòng khá»›p vá»›i má»™t mẫu" msgid "A portable graphical interface to Git" msgstr "Má»™t giao diện đồ há»a khả chuyển cho Git" -msgid "Compute object ID and optionally creates a blob from a file" -msgstr "TÃnh toán ID đối tượng và tùy chá»n là tạo má»™t blob từ má»™t táºp tin" +msgid "Compute object ID and optionally create an object from a file" +msgstr "TÃnh toán ID đối tượng và tùy tạo má»™t object từ má»™t táºp tin" msgid "Display help information about Git" msgstr "Hiển thị thông tin trợ giúp vá» Git" @@ -13464,7 +14044,7 @@ msgid "Run git hooks" msgstr "Chạy các móc git" msgid "Server side implementation of Git over HTTP" -msgstr "Thi hà nh phÃa máy chủ của Git qua HTTP" +msgstr "Há»— trợ phÃa máy chủ của Git qua HTTP" msgid "Download from a remote Git repository via HTTP" msgstr "Tải vá» từ má»™t kho chứa Git trên mạng thông qua HTTP" @@ -13473,11 +14053,10 @@ msgid "Push objects over HTTP/DAV to another repository" msgstr "Äẩy các đối tượng lên thông qua HTTP/DAV đến kho chứa khác" msgid "Send a collection of patches from stdin to an IMAP folder" -msgstr "" -"Gá»i má»™t bá»™ sÆ°u táºp các miếng vá từ đầu và o tiêu chuẩn đến má»™t thÆ° mục IMAP" +msgstr "Gá»i má»™t bá»™ sÆ°u táºp các bản vá từ stdin đến má»™t thÆ° mục IMAP" msgid "Build pack index file for an existing packed archive" -msgstr "Xây dá»±ng táºp tin mục lục gói cho má»™t kho nén đã đóng gói sẵn có" +msgstr "Xây dá»±ng táºp tin chỉ mục gói cho má»™t kho nén đã đóng gói sẵn có" msgid "Create an empty Git repository or reinitialize an existing one" msgstr "Tạo má»™t kho git má»›i hay khởi tạo lại má»™t kho đã tồn tại từ trÆ°á»›c" @@ -13486,13 +14065,13 @@ msgid "Instantly browse your working repository in gitweb" msgstr "Duyệt ngay kho là m việc của bạn trong gitweb" msgid "Add or parse structured information in commit messages" -msgstr "Thêm hay phân tÃch thông tin cấu trúc trong ghi chú lần chuyển giao" +msgstr "Thêm hay Ä‘á»c thông tin cấu trúc trong ghi chú lần chuyển giao" msgid "Show commit logs" msgstr "Hiển thị nháºt ký các lần chuyển giao" msgid "Show information about files in the index and the working tree" -msgstr "Hiển thị thông tin vá» các táºp tin trong bảng mục lục và cây là m việc" +msgstr "Hiển thị thông tin vá» các táºp tin trong chỉ mục và cây là m việc" msgid "List references in a remote repository" msgstr "Liệt kê các tham chiếu trong má»™t kho chứa trên mạng" @@ -13516,7 +14095,7 @@ msgid "Find as good common ancestors as possible for a merge" msgstr "Tìm các tổ tiên chung tốt có thể được cho hòa trá»™n" msgid "Run a three-way file merge" -msgstr "Chạy má»™t hòa trá»™n táºp tin “3-Ä‘Æ°á»ngâ€" +msgstr "Chạy má»™t hòa trá»™n táºp tin '3-Ä‘Æ°á»ng'" msgid "Run a merge for files needing merging" msgstr "Chạy má»™t hòa trá»™n cho các táºp tin cần hòa trá»™n" @@ -13524,13 +14103,12 @@ msgstr "Chạy má»™t hòa trá»™n cho các táºp tin cần hòa trá»™n" msgid "The standard helper program to use with git-merge-index" msgstr "Má»™t chÆ°Æ¡ng trình há»— trợ tiêu chuẩn dùng vá»›i git-merge-index" -msgid "Show three-way merge without touching index" -msgstr "Hiển thị hòa trá»™n ba-Ä‘Æ°á»ng mà không đụng chạm đến mục lục" +msgid "Perform merge without touching index or working tree" +msgstr "Ãp dụng má»™t bản vá mà không Ä‘á»™ng chạm đến cây là m việc" msgid "Run merge conflict resolution tools to resolve merge conflicts" msgstr "" -"Chạy công cụ phân giải xung Ä‘á»™t hòa trá»™n để mà giải quyết các xung Ä‘á»™t hòa " -"trá»™n" +"Chạy công cụ phân giải xung Ä‘á»™t hòa trá»™n để giải quyết các xung Ä‘á»™t hòa trá»™n" msgid "Creates a tag object with extra validation" msgstr "Tạo má»™t đối tượng thẻ vá»›i kiểm tra mở rá»™ng" @@ -13563,7 +14141,7 @@ msgid "Pack heads and tags for efficient repository access" msgstr "Äóng gói các phần đầu và thẻ để truy cáºp kho hiệu quả hÆ¡n" msgid "Compute unique ID for a patch" -msgstr "TÃnh toán ID duy nhất cho má»™t miếng vá" +msgstr "TÃnh toán ID duy nhất cho má»™t bản vá" msgid "Prune all unreachable objects from the object database" msgstr "" @@ -13579,16 +14157,16 @@ msgid "Update remote refs along with associated objects" msgstr "Cáºp nháºt th.chiếu máy chủ cùng vá»›i các đối tượng liên quan đến nó" msgid "Applies a quilt patchset onto the current branch" -msgstr "Ấp dụng má»™t bá»™ miếng vá quilt và o trong nhánh hiện hà nh" +msgstr "Ấp dụng má»™t bá»™ bản vá quilt và o trong nhánh hiện hà nh" msgid "Compare two commit ranges (e.g. two versions of a branch)" msgstr "So sánh hai vùng chuyển giao (vd: hai phiên bản của má»™t nhánh)" msgid "Reads tree information into the index" -msgstr "Äá»c thông tin cây và o trong mục lục" +msgstr "Äá»c thông tin cây và o trong chỉ mục" msgid "Reapply commits on top of another base tip" -msgstr "Thu hoạch các lần chuyển giao trên đỉnh của đầu mút cÆ¡ sở khác" +msgstr "Thu hoạch các lần chuyển giao trên đỉnh của đỉnh cÆ¡ sở khác" msgid "Receive what is pushed into the repository" msgstr "Nháºn cái mà được đẩy và o trong kho" @@ -13605,6 +14183,11 @@ msgstr "Äóng gói các đối tượng chÆ°a đóng gói ở má»™t kho chứa" msgid "Create, list, delete refs to replace objects" msgstr "Tạo, liệt kê, xóa các tham chiếu để thay thế các đối tượng" +msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too" +msgstr "" +"ÄANG TRONG QUà TRÃŒNH THỬ NGHIỆM: Phát lại lần chuyển giao và o gốc má»›i, dùng " +"được trong kho chứa bare" + msgid "Generates a summary of pending changes" msgstr "Tạo ra má»™t tóm tắt các thay đổi còn treo" @@ -13627,10 +14210,10 @@ msgid "Revert some existing commits" msgstr "Hoà n lại má»™t số lần chuyển giao sẵn có" msgid "Remove files from the working tree and from the index" -msgstr "Gỡ bá» các táºp tin từ cây là m việc và từ bảng mục lục" +msgstr "Gỡ bá» các táºp tin từ cây là m việc và từ chỉ mục" msgid "Send a collection of patches as emails" -msgstr "Gá»i má»™t táºp hợp của các miếng vá ở dạng thÆ° Ä‘iện tá»" +msgstr "Gá»i má»™t táºp hợp của các bản vá ở dạng thÆ° Ä‘iện tá»" 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" @@ -13645,7 +14228,7 @@ 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" msgid "Summarize 'git log' output" -msgstr "Kết xuất “git log†dạng tóm tắt" +msgstr "Kết xuất 'git log' dạng tóm tắt" msgid "Show various types of objects" msgstr "Hiển thị các kiểu khác nhau của các đối tượng" @@ -13698,7 +14281,7 @@ msgid "Unpack objects from a packed archive" msgstr "Gỡ các đối tượng khá»i má»™t kho lÆ°u đã đóng gói" msgid "Register file contents in the working tree to the index" -msgstr "Äăng ký ná»™i dung táºp tin từ cây là m việc đến bảng mục lục" +msgstr "Äăng ký ná»™i dung táºp tin từ cây là m việc đến chỉ mục" msgid "Update the object name stored in a ref safely" msgstr "Cáºp nháºt tên đối tượng được lÆ°u trong má»™t tham chiếu má»™t cách an toà n" @@ -13724,20 +14307,23 @@ msgstr "Kiểm tra lại các táºp tin kho (lÆ°u trữ, nén) Git đã được msgid "Check the GPG signature of tags" msgstr "Kiểm tra chữ ký GPG của các thẻ" -msgid "Show logs with difference each commit introduces" -msgstr "Hiển thị các nháºt ký vá»›i từng lần chuyển giao khác nhau Ä‘Æ°a ra" +msgid "Display version information about Git" +msgstr "Hiển thị thông tin vá» phiên bản Git" + +msgid "Show logs with differences each commit introduces" +msgstr "Hiển thị nháºt ký vá»›i thay đổi của từng lần chuyển giao" msgid "Manage multiple working trees" msgstr "Quản lý nhiá»u cây là m việc" msgid "Create a tree object from the current index" -msgstr "Tạo má»™t đối tượng cây từ đầu và o tiêu chuẩn stdin hiện tại" +msgstr "Tạo má»™t đối tượng cây từ chỉ mục hiện tại" msgid "Defining attributes per path" msgstr "Äịnh nghÄ©a các thuá»™c tÃnh cho má»—i Ä‘Æ°á»ng dẫn" msgid "Git command-line interface and conventions" -msgstr "Giao diện dòng lệnh Git và quy Æ°á»›c" +msgstr "Giao diện dòng lệnh Git và các quy Æ°á»›c" msgid "A Git core tutorial for developers" msgstr "HÆ°á»›ng dẫn Git cÆ¡ bản cho nhà phát triển" @@ -13752,22 +14338,40 @@ msgid "Tweaking diff output" msgstr "Chỉnh kết xuất diff" msgid "A useful minimum set of commands for Everyday Git" -msgstr "Má»™t táºp hợp lệnh hữu dụng tối thiểu để dùng Git hà ng ngà y" +msgstr "Táºp hợp lệnh hữu dụng tối thiểu để dùng Git hà ng ngà y" msgid "Frequently asked questions about using Git" msgstr "Các câu há»i thÆ°á»ng gặp vá» cách sá» dụng Git" +msgid "The bundle file format" +msgstr "Äịnh dạng táºp tin bundle" + +msgid "Chunk-based file formats" +msgstr "Äịnh dạng táºp tin dạng khúc" + +msgid "Git commit-graph format" +msgstr "Äịnh dạng đồ-thị-chuyển-giao" + +msgid "Git index format" +msgstr "Äịnh dạng chỉ mục" + +msgid "Git pack format" +msgstr "Äịnh dạng pack" + +msgid "Git cryptographic signature formats" +msgstr "Äịnh dạng chữ ký bảo máºt Git" + msgid "A Git Glossary" msgstr "Thuáºt ngữ chuyên môn Git" msgid "Hooks used by Git" -msgstr "Các móc được sá» dụng bởi Git" +msgstr "Các hook được sá» dụng bởi Git" msgid "Specifies intentionally untracked files to ignore" msgstr "Chỉ định các táºp tin không cần theo dõi" msgid "The Git repository browser" -msgstr "Bá»™ duyện kho Git" +msgstr "Bá»™ duyệt kho Git" msgid "Map author/committer names and/or E-Mail addresses" msgstr "Ãnh xạ tên tác giả/ngÆ°á»i chuyển giao và /hoặc địa chỉ E-Mail" @@ -13778,8 +14382,23 @@ msgstr "Äịnh nghÄ©a thuá»™c tÃnh mô-Ä‘un-con" msgid "Git namespaces" msgstr "Không gian tên Git" +msgid "Protocol v0 and v1 capabilities" +msgstr "Capabilities của giao thức v0 và v1" + +msgid "Things common to various protocols" +msgstr "Những thứ chung cho các giao thức" + +msgid "Git HTTP-based protocols" +msgstr "Những giao thức Git dá»±a trên HTTP" + +msgid "How packs are transferred over-the-wire" +msgstr "Gói được truyá»n thá»±c tế (over-the-wire) nhÆ° thế nà o" + +msgid "Git Wire Protocol, Version 2" +msgstr "Git Wire Protocol, Version 2" + msgid "Helper programs to interact with remote repositories" -msgstr "Các chÆ°Æ¡ng trình há»— trợ để tÆ°Æ¡ng tác vá»›i các kho chứa trên máy chủ" +msgstr "Các chÆ°Æ¡ng trình helper để tÆ°Æ¡ng tác vá»›i các kho chứa trên máy chủ" msgid "Git Repository Layout" msgstr "Bố cục kho Git" @@ -13802,44 +14421,90 @@ msgstr "Giao diện Git trên ná»n web (ứng dụng web chạy trên kho Git)" msgid "An overview of recommended workflows with Git" msgstr "Tổng quan vá» luồng công việc khuyến nghị nên dùng vá»›i Git" +msgid "A tool for managing large Git repositories" +msgstr "Công cụ quản lý các kho Git lá»›n" + msgid "commit-graph file is too small" -msgstr "táºp tin đồ-thị-các-lần-chuyển-giao quá nhá»" +msgstr "táºp tin đồ-thị-chuyển-giao quá nhá»" + +msgid "commit-graph oid fanout chunk is wrong size" +msgstr "đồ-thị-chuyển-giao có kÃch cỡ oid fanout chunk không đúng" + +msgid "commit-graph fanout values out of order" +msgstr "đồ-thị-chuyển-giao có giá trị fanout không đúng" + +msgid "commit-graph OID lookup chunk is the wrong size" +msgstr "đồ-thị-chuyển-giao có kÃch cỡ OID lookup chunk không đúng" + +msgid "commit-graph commit data chunk is wrong size" +msgstr "đồ-thị-chuyển-giao có kÃch cỡ commit data chunk không đúng" + +msgid "commit-graph generations chunk is wrong size" +msgstr "đồ-thị-chuyển-giao có kÃch cỡ generations chunk không đúng" + +msgid "commit-graph changed-path index chunk is too small" +msgstr "đồ-thị-chuyển-giao có changed-path index chunk quá nhá»" + +#, c-format +msgid "" +"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-" +"graph file" +msgstr "" +"bá» qua chunk thay-đổi-Ä‘Æ°á»ng-dẫn quá nhá» (%<PRIuMAX> < %<PRIuMAX>) trong táºp " +"tin đồ-thị-chuyển-giao" #, c-format msgid "commit-graph signature %X does not match signature %X" -msgstr "chữ ký đồ-thị-các-lần-chuyển-giao %X không khá»›p chữ ký %X" +msgstr "chữ ký đồ-thị-chuyển-giao %X không khá»›p chữ ký %X" #, c-format msgid "commit-graph version %X does not match version %X" -msgstr "phiên bản đồ-thị-các-lần-chuyển-giao %X không khá»›p phiên bản %X" +msgstr "phiên bản đồ-thị-chuyển-giao %X không khá»›p phiên bản %X" #, c-format msgid "commit-graph hash version %X does not match version %X" -msgstr "phiên bản đồ-thị-các-lần-chuyển-giao %X không khá»›p phiên bản %X" +msgstr "phiên bản đồ-thị-chuyển-giao %X không khá»›p phiên bản %X" #, c-format msgid "commit-graph file is too small to hold %u chunks" -msgstr "táºp tin đồ-thị-các-lần-chuyển-giao quá nhỠđể giữ %u mảnh dữ liệu" +msgstr "táºp tin đồ-thị-chuyển-giao quá nhỠđể giữ %u chunk" + +msgid "commit-graph required OID fanout chunk missing or corrupted" +msgstr "đồ-thị-chuyển-giao thiếu chunk OID fanout cần thiết hoặc bị há»ng" + +msgid "commit-graph required OID lookup chunk missing or corrupted" +msgstr "đồ-thị-chuyển-giao thiếu chunk OID lookup cần thiết hoặc bị há»ng" + +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" msgid "commit-graph has no base graphs chunk" -msgstr "đồ-thị-các-lần-chuyển-giao có không có mảnh các đồ há»a cÆ¡ sở" +msgstr "đồ thị chuyển giao không có chunk đồ thị cÆ¡ sở" + +msgid "commit-graph base graphs chunk is too small" +msgstr "đồ thị chuyển giao có chunk đồ thị cÆ¡ sở quá nhá»" msgid "commit-graph chain does not match" -msgstr "móc xÃch đồ-thị-các-lần-chuyển-giao không khá»›p" +msgstr "chuá»—i đồ-thị-chuyển-giao không khá»›p" + +#, c-format +msgid "commit count in base graph too high: %<PRIuMAX>" +msgstr "số lần chuyển giao trong đồ thị cÆ¡ sở quá lá»›n: %<PRIuMAX>" + +msgid "commit-graph chain file too small" +msgstr "táºp tin chuá»—i đồ-thị-chuyển-giao quá nhá»" #, c-format msgid "invalid commit-graph chain: line '%s' not a hash" msgstr "" -"móc xÃch đồ-thị-các-lần-chuyển-giao không hợp lệ: dòng “%s†không phải là " -"má»™t mã băm" +"chuá»—i đồ-thị-chuyển-giao không hợp lệ: dòng '%s' không phải là má»™t mã băm" msgid "unable to find all commit-graph files" -msgstr "không thể tìm thấy tất cả các táºp tin đồ-thị-các-lần-chuyển-giao" +msgstr "không thể tìm thấy tất cả các táºp tin đồ-thị-chuyển-giao" msgid "invalid commit position. commit-graph is likely corrupt" msgstr "" -"vị trà lần chuyển giao không hợp lệ. đồ-thị-các-lần-chuyển-giao có vẻ nhÆ° đã " -"bị há»ng" +"vị trà lần chuyển giao không hợp lệ. đồ-thị-chuyển-giao có vẻ nhÆ° đã bị há»ng" #, c-format msgid "could not find commit %s" @@ -13848,6 +14513,12 @@ msgstr "không thể tìm thấy lần chuyển giao %s" msgid "commit-graph requires overflow generation data but has none" msgstr "commit-graph yêu cầu dữ liệu tạo trà n nhÆ°ng không có" +msgid "commit-graph overflow generation data is too small" +msgstr "commit-graph yêu cầu dữ liệu tạo trà n nhÆ°ng quá nhá»" + +msgid "commit-graph extra-edges pointer out of bounds" +msgstr "con trá» extra-edge của đồ thị chuyển giao nằm ngoà i biên" + msgid "Loading known commits in commit graph" msgstr "Äang tải các lần chuyển giao chÆ°a biết trong đồ thị lần chuyển giao" @@ -13883,7 +14554,7 @@ msgstr "gặp lá»—i thêm gói %s" #, c-format msgid "error opening index for %s" -msgstr "gặp lá»—i khi mở mục lục cho “%sâ€" +msgstr "gặp lá»—i khi mở chỉ mục cho '%s'" msgid "Finding commits for commit graph among packed objects" msgstr "" @@ -13901,7 +14572,7 @@ msgstr "không thể tạo lá»›p sÆ¡ đồ tạm thá»i" #, c-format msgid "unable to adjust shared permissions for '%s'" -msgstr "không thể chỉnh sá»a quyá»n chia sẻ thà nh “%sâ€" +msgstr "không thể chỉnh sá»a quyá»n chia sẻ thà nh '%s'" #, c-format msgid "Writing out commit graph in %d pass" @@ -13912,20 +14583,28 @@ msgid "unable to open commit-graph chain file" msgstr "không thể mở táºp tin mắt xÃch đồ 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ị-các-lần-chuyển-giao" +msgstr "gặp lá»—i khi đổi tên táºp tin đồ-thị-chuyển-giao" msgid "failed to rename temporary commit-graph file" -msgstr "gặp lá»—i khi đổi tên táºp tin đồ-thị-các-lần-chuyển-giao tạm thá»i" +msgstr "gặp lá»—i khi đổi tên táºp tin đồ-thị-chuyển-giao tạm thá»i" + +#, c-format +msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits" +msgstr "không thể kết hợp đồ thị vá»›i %<PRIuMAX>, %<PRIuMAX> lần chuyển giao" + +#, c-format +msgid "cannot merge graph %s, too many commits: %<PRIuMAX>" +msgstr "không thể kết hợp đồ thị %s, quá nhiá»u lần chuyển giao: %<PRIuMAX>" msgid "Scanning merged commits" msgstr "Äang quét các lần chuyển giao đã hòa trá»™n" msgid "Merging commit-graph" -msgstr "Äang hòa trá»™n đồ-thị-các-lần-chuyển-giao" +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ị " +"cố gắng để ghi má»™t đồ thị các lần chuyển giao, nhÆ°ng 'core.commitGraph' bị " "vô hiệu hóa" msgid "too many commits to write graph" @@ -13933,78 +14612,70 @@ msgstr "có quá nhiá»u lần chuyển giao để ghi đồ thị" msgid "the commit-graph file has incorrect checksum and is likely corrupt" msgstr "" -"táºp tin đồ-thị-các-lần-chuyển-giao có tổng kiểm không đúng và có vẻ nhÆ° là " -"đã há»ng" +"táºp tin đồ-thị-chuyển-giao có tổng kiểm không đúng và có vẻ nhÆ° là đã há»ng" #, c-format msgid "commit-graph has incorrect OID order: %s then %s" -msgstr "đồ-thị-các-lần-chuyển-giao có thứ tá»± OID không đúng: %s sau %s" +msgstr "đồ-thị-chuyển-giao có thứ tá»± OID không đúng: %s sau %s" #, c-format msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u" -msgstr "" -"đồ-thị-các-lần-chuyển-giao có giá trị fanout không đúng: fanout[%d] = %u != " -"%u" +msgstr "đồ-thị-chuyển-giao có giá trị fanout không đúng: fanout[%d] = %u != %u" #, c-format msgid "failed to parse commit %s from commit-graph" -msgstr "gặp lá»—i khi phân tÃch lần chuyển giao từ %s đồ-thị-các-lần-chuyển-giao" - -msgid "Verifying commits in commit graph" -msgstr "Äang thẩm tra các lần chuyển giao trong đồ thị lần chuyển giao" +msgstr "gặp lá»—i khi Ä‘á»c lần chuyển giao từ %s đồ-thị-chuyển-giao" #, c-format msgid "failed to parse commit %s from object database for commit-graph" msgstr "" -"gặp lá»—i khi phân tÃch lần chuyển giao %s từ cÆ¡ sở dữ liệu đối tượng cho đồ " -"thị lần chuyển giao" +"gặp lá»—i khi Ä‘á»c lần chuyển giao %s từ cÆ¡ sở dữ liệu đối tượng cho đồ thị lần " +"chuyển giao" #, c-format msgid "root tree OID for commit %s in commit-graph is %s != %s" msgstr "" -"OID cây gốc cho lần chuyển giao %s trong đồ-thị-các-lần-chuyển-giao là %s != " -"%s" +"OID cây gốc cho lần chuyển giao %s trong đồ-thị-chuyển-giao là %s != %s" #, c-format msgid "commit-graph parent list for commit %s is too long" -msgstr "" -"danh sách cha mẹ đồ-thị-các-lần-chuyển-giao cho lần chuyển giao %s là quá dà i" +msgstr "danh sách cha mẹ đồ-thị-chuyển-giao cho lần chuyển giao %s là quá dà i" #, c-format msgid "commit-graph parent for %s is %s != %s" -msgstr "cha mẹ đồ-thị-các-lần-chuyển-giao cho %s là %s != %s" +msgstr "cha mẹ đồ-thị-chuyển-giao cho %s là %s != %s" #, c-format msgid "commit-graph parent list for commit %s terminates early" msgstr "" -"danh sách cha mẹ đồ-thị-các-lần-chuyển-giao cho lần chuyển giao %s bị chấm " -"dứt quá sá»›m" +"danh sách cha mẹ đồ-thị-chuyển-giao cho lần chuyển giao %s bị chấm dứt quá " +"sá»›m" #, c-format -msgid "" -"commit-graph has generation number zero for commit %s, but non-zero elsewhere" +msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>" msgstr "" -"đồ-thị-các-lần-chuyển-giao có con số không lần tạo cho lần chuyển giao %s, " -"nhÆ°ng không phải số không ở chá»— khác" +"tạo đồ-thị-chuyển-giao cho lần chuyển giao %s là %<PRIuMAX> < %<PRIuMAX>" #, c-format -msgid "" -"commit-graph has non-zero generation number for commit %s, but zero elsewhere" +msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>" msgstr "" -"đồ-thị-các-lần-chuyển-giao có con số không phải không lần tạo cho lần chuyển " -"giao %s, nhÆ°ng số không ở chá»— khác" +"ngà y chuyển giao cho lần chuyển giao %s trong đồ-thị-chuyển-giao là " +"%<PRIuMAX> != %<PRIuMAX>" #, c-format -msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>" +msgid "" +"commit-graph has both zero and non-zero generations (e.g., commits '%s' and " +"'%s')" msgstr "" -"tạo đồ-thị-các-lần-chuyển-giao cho lần chuyển giao %s là %<PRIuMAX> < " -"%<PRIuMAX>" +"đồ-thị-chuyển-giao có số thế hệ không và khác không (v.d. lần chuyển giao " +"'%s' và '%s')" + +msgid "Verifying commits in commit graph" +msgstr "Äang thẩm tra các lần chuyển giao trong đồ thị lần chuyển giao" #, c-format -msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>" -msgstr "" -"ngà y chuyển giao cho lần chuyển giao %s trong đồ-thị-các-lần-chuyển-giao là " -"%<PRIuMAX> != %<PRIuMAX>" +msgid "could not parse commit %s" +msgstr "không thể Ä‘á»c lần chuyển giao %s" #, c-format msgid "%s %s is not a commit!" @@ -14020,7 +14691,7 @@ msgid "" "Turn this message off by running\n" "\"git config advice.graftFileDeprecated false\"" msgstr "" -"Việc há»— trợ cho <GIT_DIR>/info/grafts đã lạc háºu\n" +"Há»— trợ cho <GIT_DIR>/info/grafts đã không còn\n" "và sẽ bị xóa bỠở phiên bản Git tÆ°Æ¡ng lai.\n" "\n" "Vui lòng dùng \"git replace --convert-graft-file\"\n" @@ -14030,6 +14701,12 @@ msgstr "" "\"git config advice.graftFileDeprecated false\"" #, c-format +msgid "commit %s exists in commit-graph but not in the object database" +msgstr "" +"commit %s tồn tại trong đồ-thị-chuyển-giao nhÆ°ng không có trong cÆ¡ sở dữ " +"liệu đối tượng" + +#, c-format msgid "Commit %s has an untrusted GPG signature, allegedly by %s." msgstr "" "Lần chuyển giao %s có má»™t chữ ký GPG không đáng tin, được cho là bởi %s." @@ -14062,6 +14739,14 @@ msgid "no libc information available\n" msgstr "không có thông tin vá» libc\n" #, c-format +msgid "could not determine free disk size for '%s'" +msgstr "không thể dò tìm chá»— trống trên Ä‘Ä©a cho '%s'" + +#, c-format +msgid "could not get info for '%s'" +msgstr "không thể lấy thông tin cho '%s'" + +#, c-format msgid "[GLE %ld] health thread could not open '%ls'" msgstr "[GLE %ld] không thể mở tuyến trình sức khá»e '%ls'" @@ -14085,6 +14770,10 @@ msgstr "có trÆ°á»ng hợp không được xá» lý trong 'has_worktree_moved' msgid "health thread wait failed [GLE %ld]" msgstr "gặp lá»—i khi chá» tiến trình sức khá»e [GLE %ld]" +#, c-format +msgid "Invalid path: %s" +msgstr "Ä‘Æ°á»ng dẫn không hợp lệ: %s" + msgid "Unable to create FSEventStream." msgstr "Không thể tạo FSEventStream." @@ -14116,6 +14805,30 @@ msgid "could not read directory changes [GLE %ld]" msgstr "không thể Ä‘á»c các thay đổi thÆ° mục [GLE %ld]" #, c-format +msgid "opendir('%s') failed" +msgstr "opendir('%s') gặp lá»—i" + +#, c-format +msgid "lstat('%s') failed" +msgstr "lstat('%s') gặp lá»—i" + +#, c-format +msgid "strbuf_readlink('%s') failed" +msgstr "strbuf_readlink('%s') gặp lá»—i" + +#, c-format +msgid "closedir('%s') failed" +msgstr "closedir('%s') gặp lá»—i" + +#, c-format +msgid "[GLE %ld] unable to open for read '%ls'" +msgstr "[GLE %ld] không thể mở hay Ä‘á»c '%ls'" + +#, c-format +msgid "[GLE %ld] unable to get protocol information for '%ls'" +msgstr "[GLE %ld] không thể lấy thông tin giao thức cho '%ls'" + +#, c-format msgid "failed to copy SID (%ld)" msgstr "gặp lá»—i khi sao chép SID (%ld)" @@ -14154,7 +14867,7 @@ msgid "Unmatched ( or \\(" msgstr "ChÆ°a khá»›p ( hay \\(" msgid "Unmatched \\{" -msgstr "ChÆ°a khá»›p cặp “\\{â€" +msgstr "ChÆ°a khá»›p cặp '\\{'" msgid "Invalid content of \\{\\}" msgstr "Ná»™i dung của \\{\\} không hợp lệ" @@ -14188,11 +14901,11 @@ msgstr "không thể Ä‘á»c đáp ứng IPC" #, c-format msgid "could not start accept_thread '%s'" -msgstr "không thể khởi chạy accept_thread “%sâ€" +msgstr "không thể khởi chạy accept_thread '%s'" #, c-format msgid "could not start worker[0] for '%s'" -msgstr "không thể khởi chạy bá»™ là m việc worker[0] cho “%sâ€" +msgstr "không thể khởi chạy bá»™ là m việc worker[0] cho '%s'" #, c-format msgid "ConnectNamedPipe failed for '%s' (%lu)" @@ -14204,11 +14917,11 @@ msgstr "không thể tạo mô tả táºp tin từ Ä‘Æ°á»ng ống cho '%s'" #, c-format msgid "could not start thread[0] for '%s'" -msgstr "không thể khởi chạy tiến trình[0] cho “%sâ€" +msgstr "không thể khởi chạy tiến trình[0] cho '%s'" #, c-format msgid "wait for hEvent failed for '%s'" -msgstr "chá» cho hEvent gặp lá»—i vá»›i “%sâ€" +msgstr "chá» cho hEvent gặp lá»—i vá»›i '%s'" msgid "cannot resume in the background, please use 'fg' to resume" msgstr "" @@ -14234,7 +14947,7 @@ msgstr "" #, c-format msgid "could not expand include path '%s'" -msgstr "không thể khai triển Ä‘Æ°á»ng dẫn “%sâ€" +msgstr "không thể khai triển Ä‘Æ°á»ng dẫn '%s'" msgid "relative config includes must come from files" msgstr "các bao gồm cấu hình liên quan phải đến từ các táºp tin" @@ -14246,7 +14959,7 @@ msgid "" "remote URLs cannot be configured in file directly or indirectly included by " "includeIf.hasconfig:remote.*.url" msgstr "" -"các URL máy chủ không thể được cấu hình trong tệp trá»±c tiếp hoặc gián tiếp " +"các URL máy chủ không thể được cấu hình trong táºp trá»±c tiếp hoặc gián tiếp " "được bao gồm bởi includeIf.hasconfig:remote.*.url" #, c-format @@ -14255,11 +14968,11 @@ msgstr "định dạng cấu hình không hợp lệ: %s" #, c-format msgid "missing environment variable name for configuration '%.*s'" -msgstr "thiếu tên biến môi trÆ°á»ng cho cấu hình “%.*sâ€" +msgstr "thiếu tên biến môi trÆ°á»ng cho cấu hình '%.*s'" #, c-format msgid "missing environment variable '%s' for configuration '%.*s'" -msgstr "thiếu biến môi trÆ°á»ng “%s†cho cấu hình “%.*sâ€" +msgstr "thiếu biến môi trÆ°á»ng '%s' cho cấu hình '%.*s'" #, c-format msgid "key does not contain a section: %s" @@ -14271,7 +14984,7 @@ msgstr "khóa không chứa bất kỳ má»™t tên biến nà o: %s" #, c-format msgid "invalid key: %s" -msgstr "khóa không đúng: %s" +msgstr "khóa không hợp lệ: %s" #, c-format msgid "invalid key (newline): %s" @@ -14298,11 +15011,11 @@ msgstr "quá nhiá»u mục tin trong %s" #, c-format msgid "missing config key %s" -msgstr "thiếu khóa cấu hình “%sâ€" +msgstr "thiếu khóa cấu hình '%s'" #, c-format msgid "missing config value %s" -msgstr "thiếu giá trị cấu hình “%sâ€" +msgstr "thiếu giá trị cấu hình '%s'" #, c-format msgid "bad config line %d in blob %s" @@ -14314,7 +15027,7 @@ msgstr "cấu hình sai tại dòng %d trong táºp tin %s" #, c-format msgid "bad config line %d in standard input" -msgstr "cấu hình sai tại dòng %d trong đầu và o tiêu chuẩn" +msgstr "cấu hình sai tại dòng %d từ stdin" #, c-format msgid "bad config line %d in submodule-blob %s" @@ -14336,33 +15049,32 @@ msgstr "Ä‘Æ¡n vị không hợp lệ" #, c-format msgid "bad numeric config value '%s' for '%s': %s" -msgstr "sai giá trị bằng số của cấu hình “%s†cho “%sâ€: %s" +msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s': %s" #, c-format msgid "bad numeric config value '%s' for '%s' in blob %s: %s" -msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong blob %s: %s" +msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong blob %s: %s" #, c-format msgid "bad numeric config value '%s' for '%s' in file %s: %s" -msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong táºp tin %s: %s" +msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong táºp tin %s: %s" #, c-format msgid "bad numeric config value '%s' for '%s' in standard input: %s" -msgstr "" -"sai giá trị bằng số của cấu hình “%s†cho “%s†trong đầu và o tiêu chuẩn: %s" +msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong stdin: %s" #, c-format msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s" msgstr "" -"sai giá trị bằng số của cấu hình “%s†cho “%s†trong submodule-blob %s: %s" +"sai giá trị bằng số của cấu hình '%s' cho '%s' trong submodule-blob %s: %s" #, c-format msgid "bad numeric config value '%s' for '%s' in command line %s: %s" -msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong dòng lệnh %s: %s" +msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong dòng lệnh %s: %s" #, c-format msgid "bad numeric config value '%s' for '%s' in %s: %s" -msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong %s: %s" +msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong %s: %s" #, c-format msgid "invalid value for variable %s" @@ -14374,15 +15086,15 @@ msgstr "bá» qua thà nh phần core.fsync chÆ°a biết '%s'" #, c-format msgid "bad boolean config value '%s' for '%s'" -msgstr "sai giá trị kiểu lô-gÃc của cấu hình “%s†cho “%sâ€" +msgstr "sai giá trị kiểu boolean của cấu hình '%s' cho '%s'" #, c-format msgid "failed to expand user dir in: '%s'" -msgstr "gặp lá»—i mở rá»™ng thÆ° mục ngÆ°á»i dùng trong: “%sâ€" +msgstr "gặp lá»—i mở rá»™ng thÆ° mục ngÆ°á»i dùng trong: '%s'" #, c-format msgid "'%s' for '%s' is not a valid timestamp" -msgstr "“%s†dà nh cho “%s†không phải là dấu vết thá»i gian hợp lệ" +msgstr "'%s' dà nh cho '%s' không phải là dấu vết thá»i gian hợp lệ" #, c-format msgid "abbrev length out of range: %d" @@ -14392,8 +15104,13 @@ msgstr "chiá»u dà i abbrev nằm ngoà i phạm vi: %d" msgid "bad zlib compression level %d" msgstr "mức nén zlib %d là sai" -msgid "core.commentChar should only be one character" -msgstr "core.commentChar chỉ được có má»™t ký tá»±" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s không thể chứa ký tá»± xuống dòng" + +#, c-format +msgid "%s must have at least one character" +msgstr "%s phải có Ãt nhất má»™t ký tá»±" #, c-format msgid "ignoring unknown core.fsyncMethod value '%s'" @@ -14419,45 +15136,41 @@ msgstr "phải là má»™t trong số nothing, matching, simple, upstream hay curr #, c-format msgid "unable to load config blob object '%s'" -msgstr "không thể tải đối tượng blob cấu hình “%sâ€" +msgstr "không thể tải đối tượng blob cấu hình '%s'" #, c-format msgid "reference '%s' does not point to a blob" -msgstr "tham chiếu “%s†không chỉ đến má»™t blob nà o cả" +msgstr "tham chiếu '%s' không chỉ đến má»™t blob nà o cả" #, c-format msgid "unable to resolve config blob '%s'" -msgstr "không thể phân giải Ä‘iểm xét duyệt “%sâ€" - -#, c-format -msgid "failed to parse %s" -msgstr "gặp lá»—i khi phân tÃch cú pháp %s" +msgstr "không thể phân giải Ä‘iểm xét duyệt '%s'" msgid "unable to parse command-line config" -msgstr "không thể phân tÃch cấu hình dòng lệnh" +msgstr "không thể Ä‘á»c cấu hình dòng lệnh" msgid "unknown error occurred while reading the configuration files" msgstr "đã có lá»—i chÆ°a biết xảy ra trong khi Ä‘á»c các táºp tin cấu hình" #, c-format msgid "Invalid %s: '%s'" -msgstr "%s không hợp lệ: “%sâ€" +msgstr "%s không hợp lệ: '%s'" #, c-format msgid "splitIndex.maxPercentChange value '%d' should be between 0 and 100" -msgstr "giá trị splitIndex.maxPercentChange “%d†phải nằm giữa 0 và 100" +msgstr "giá trị splitIndex.maxPercentChange '%d' phải nằm giữa 0 và 100" #, c-format msgid "unable to parse '%s' from command-line config" -msgstr "không thể phân tÃch “%s†từ cấu hình dòng lệnh" +msgstr "không thể Ä‘á»c '%s' từ cấu hình dòng lệnh" #, c-format msgid "bad config variable '%s' in file '%s' at line %d" -msgstr "sai biến cấu hình “%s†trong táºp tin “%s†tại dòng %d" +msgstr "sai biến cấu hình '%s' trong táºp tin '%s' tại dòng %d" #, c-format msgid "invalid section name '%s'" -msgstr "tên của phần không hợp lệ “%sâ€" +msgstr "tên của phần không hợp lệ '%s'" #, c-format msgid "%s has multiple values" @@ -14465,7 +15178,11 @@ msgstr "%s có Ä‘a giá trị" #, c-format msgid "failed to write new configuration file %s" -msgstr "gặp lá»—i khi ghi táºp tin cấu hình “%sâ€" +msgstr "gặp lá»—i khi ghi táºp tin cấu hình '%s'" + +#, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "không cho phép ghi chú nhiá»u dòng: '%s'" #, c-format msgid "could not lock config file %s" @@ -14473,11 +15190,11 @@ msgstr "không thể khóa táºp tin cấu hình %s" #, c-format msgid "opening %s" -msgstr "Ä‘ang mở “%sâ€" +msgstr "Ä‘ang mở '%s'" #, c-format msgid "invalid config file %s" -msgstr "táºp tin cấu hình “%s†không hợp lệ" +msgstr "táºp tin cấu hình '%s' không hợp lệ" #, c-format msgid "fstat on %s failed" @@ -14485,7 +15202,7 @@ msgstr "fstat trên %s gặp lá»—i" #, c-format msgid "unable to mmap '%s'%s" -msgstr "không thể mmap “%sâ€%s" +msgstr "không thể mmap '%s'%s" #, c-format msgid "chmod on %s failed" @@ -14493,19 +15210,23 @@ msgstr "chmod trên %s gặp lá»—i" #, c-format msgid "could not write config file %s" -msgstr "không thể ghi táºp tin cấu hình “%sâ€" +msgstr "không thể ghi táºp tin cấu hình '%s'" #, c-format msgid "could not set '%s' to '%s'" -msgstr "không thể đặt “%s†thà nh “%sâ€" +msgstr "không thể đặt '%s' thà nh '%s'" #, c-format msgid "invalid section name: %s" msgstr "tên của phần không hợp lệ: %s" #, c-format +msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>" +msgstr "từ chối là m việc vá»›i dòng quá dà i '%s' trên dòng %<PRIuMAX>" + +#, c-format msgid "missing value for '%s'" -msgstr "thiếu giá trị cho cho “%sâ€" +msgstr "thiếu giá trị cho cho '%s'" msgid "the remote end hung up upon initial contact" msgstr "máy chủ bị treo trên lần tiếp xúc đầu tiên" @@ -14523,25 +15244,25 @@ msgstr "" #, c-format msgid "server doesn't support '%s'" -msgstr "máy chủ không há»— trợ “%sâ€" +msgstr "máy chủ không há»— trợ '%s'" #, c-format msgid "server doesn't support feature '%s'" -msgstr "máy chủ không há»— trợ tÃnh năng “%sâ€" +msgstr "máy chủ không há»— trợ tÃnh năng '%s'" msgid "expected flush after capabilities" msgstr "cần đẩy dữ liệu lên Ä‘Ä©a sau các capabilities" #, c-format msgid "ignoring capabilities after first line '%s'" -msgstr "bá» qua capabilities sau dòng đầu tiên “%sâ€" +msgstr "bá» qua capabilities sau dòng đầu tiên '%s'" msgid "protocol error: unexpected capabilities^{}" -msgstr "lá»—i giao thức: không cần capabilities^{}" +msgstr "lá»—i giao thức: capabilities^{} bất thÆ°á»ng" #, c-format msgid "protocol error: expected shallow sha-1, got '%s'" -msgstr "lá»—i giao thức: cần sha-1 shallow, nhÆ°ng lại nháºn được “%sâ€" +msgstr "lá»—i giao thức: cần sha-1 shallow, nhÆ°ng lại có '%s'" msgid "repository on the other end cannot be shallow" msgstr "kho đã ở Ä‘iểm cuối khoác nên không thể được shallow" @@ -14551,11 +15272,21 @@ msgstr "gói không hợp lệ" #, c-format msgid "protocol error: unexpected '%s'" -msgstr "lá»—i giao thức: không cần “%sâ€" +msgstr "lá»—i giao thức: '%s' bất thÆ°á»ng" #, c-format msgid "unknown object format '%s' specified by server" -msgstr "không hiểu định dạng đối tượng “%s†được chỉ định bởi máy phục vụ" +msgstr "không hiểu định dạng đối tượng '%s' được chỉ định bởi máy chủ" + +#, c-format +msgid "error on bundle-uri response line %d: %s" +msgstr "lá»—i trên dòng phản hồi bundle-uri thứ %d: %s" + +msgid "expected flush after bundle-uri listing" +msgstr "cần đẩy dữ liệu lên Ä‘Ä©a sau khi liệt kê bundle-uri" + +msgid "expected response end packet after ref listing" +msgstr "cần nháºn được trả lá»i là kết thúc gói sau khi liệt kê tham chiếu" #, c-format msgid "invalid ls-refs response: %s" @@ -14564,19 +15295,16 @@ msgstr "trả vá» của ls-refs không hợp lệ: %s" msgid "expected flush after ref listing" msgstr "cần đẩy dữ liệu lên Ä‘Ä©a sau khi liệt kê tham chiếu" -msgid "expected response end packet after ref listing" -msgstr "cần nháºn được trả lá»i là kết thúc gói sau khi liệt kê tham chiếu" - #, c-format msgid "protocol '%s' is not supported" -msgstr "giao thức “%s†chÆ°a được há»— trợ" +msgstr "giao thức '%s' chÆ°a được há»— trợ" msgid "unable to set SO_KEEPALIVE on socket" msgstr "không thể đặt SO_KEEPALIVE trên ổ cắm" #, c-format msgid "Looking up %s ... " -msgstr "Äang tìm kiếm %s … " +msgstr "Äang tìm kiếm %s ... " #, c-format msgid "unable to look up %s (port %s) (%s)" @@ -14589,7 +15317,7 @@ msgid "" "Connecting to %s (port %s) ... " msgstr "" "xong.\n" -"Äang kết nối đến %s (cổng %s) … " +"Äang kết nối đến %s (cổng %s) ... " #, c-format msgid "" @@ -14613,221 +15341,46 @@ msgstr "không hiểu cổng %s" #, c-format msgid "strange hostname '%s' blocked" -msgstr "đã khóa tên máy lạ “%sâ€" +msgstr "đã khóa tên máy lạ '%s'" #, c-format msgid "strange port '%s' blocked" -msgstr "đã khóa cổng lạ “%sâ€" +msgstr "đã khóa cổng lạ '%s'" #, c-format msgid "cannot start proxy %s" -msgstr "không thể khởi chạy ủy nhiệm “%sâ€" +msgstr "không thể khởi chạy ủy nhiệm '%s'" msgid "no path specified; see 'git help pull' for valid url syntax" -msgstr "chÆ°a chỉ định Ä‘Æ°á»ng dẫn; xem'git help pull†để biết cú pháp url hợp lệ" +msgstr "chÆ°a chỉ định Ä‘Æ°á»ng dẫn; xem'git help pull' để biết cú pháp url hợp lệ" msgid "newline is forbidden in git:// hosts and repo paths" -msgstr "newline bị cấm trong các git:// máy chủ và đưá»ng dẫn repo" +msgstr "ký tá»± xuống dòng bị cấm trong các git:// máy chủ và đưá»ng dẫn repo" msgid "ssh variant 'simple' does not support -4" -msgstr "ssh biến thể “simple†không há»— trợ -4" +msgstr "ssh biến thể 'simple' không há»— trợ -4" msgid "ssh variant 'simple' does not support -6" -msgstr "ssh biến thể “simple†không há»— trợ -6" +msgstr "ssh biến thể 'simple' không há»— trợ -6" msgid "ssh variant 'simple' does not support setting port" -msgstr "ssh biến thể “simple†không há»— trợ đặt cổng" +msgstr "ssh biến thể 'simple' không há»— trợ đặt cổng" #, c-format msgid "strange pathname '%s' blocked" -msgstr "đã khóa tên Ä‘Æ°á»ng dẫn lạ “%sâ€" +msgstr "đã khóa tên Ä‘Æ°á»ng dẫn lạ '%s'" msgid "unable to fork" msgstr "không thể rẽ nhánh tiến trình con" msgid "Could not run 'git rev-list'" -msgstr "Không thể chạy “git rev-listâ€" +msgstr "Không thể chạy 'git rev-list'" msgid "failed write to rev-list" msgstr "gặp lá»—i khi ghi và o rev-list" msgid "failed to close rev-list's stdin" -msgstr "gặp lá»—i khi đóng đầu và o chuẩn stdin của rev-list" - -#, c-format -msgid "'%s' does not exist" -msgstr "\"%s\" không tồn tại" - -msgid "need a working directory" -msgstr "cần má»™t thÆ° mục là m việc" - -msgid "could not find enlistment root" -msgstr "không tìm thấy gốc enlistment" - -#, c-format -msgid "could not switch to '%s'" -msgstr "không thể chuyển đến '%s'" - -#, c-format -msgid "could not configure %s=%s" -msgstr "không thể đóng cấu hình %s=%s" - -msgid "could not configure log.excludeDecoration" -msgstr "không thể cấu hình log.excludeDecoration" - -msgid "Scalar enlistments require a worktree" -msgstr "'Scalar enlistments' cần má»™t cây là m việc" - -#, c-format -msgid "could not open directory '%s'" -msgstr "không thể mở thÆ° mục “%sâ€" - -#, c-format -msgid "skipping '%s', which is neither file nor directory" -msgstr "" -"Ä‘ang bá» qua “%sâ€, cái không phải là má»™t táºp tin, cÅ©ng không phải thÆ° mục" - -#, c-format -msgid "could not determine free disk size for '%s'" -msgstr "không thể dò tìm chá»— trống trên Ä‘Ä©a cho “%sâ€" - -#, c-format -msgid "could not get info for '%s'" -msgstr "không thể lấy thông tin cho “%sâ€" - -#, c-format -msgid "remote HEAD is not a branch: '%.*s'" -msgstr "HEAD của máy chủ không phải má»™t nhánh: '%.*s'" - -msgid "failed to get default branch name from remote; using local default" -msgstr "gặp lá»—i khi lấy tên nhánh mặc định từ máy chủ; sá» dụng mặc định ná»™i bá»™" - -msgid "failed to get default branch name" -msgstr "gặp lá»—i khi lấy tên nhánh mặc định" - -msgid "failed to unregister repository" -msgstr "gặp lá»—i khi hủy đăng ký kho chứa" - -msgid "failed to delete enlistment directory" -msgstr "gặp lá»—i khi xóa thÆ° mục dà nh được" - -msgid "branch to checkout after clone" -msgstr "nhánh để lấy ra sau khi nhân bản" - -msgid "when cloning, create full working directory" -msgstr "khi nhân bản, tạo đầy đủ thÆ° mục là m việc" - -msgid "only download metadata for the branch that will be checked out" -msgstr "chỉ siêu dữ liệu tải vá» cho nhánh mà sẽ được lấy ra" - -msgid "scalar clone [<options>] [--] <repo> [<dir>]" -msgstr "scalar clone [<các tùy chá»n>] [--] <kho> [<t.mục>]" - -#, c-format -msgid "cannot deduce worktree name from '%s'" -msgstr "không thể suy diá»…n tên cây là m việc từ '%s'" - -#, c-format -msgid "directory '%s' exists already" -msgstr "thÆ° mục '%s' đã sẵn có" - -#, c-format -msgid "failed to get default branch for '%s'" -msgstr "gặp lá»—i khi lấy nhánh mặc định cho '%s'" - -#, c-format -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 configure '%s'" -msgstr "không thể cấu hình '%s'" - -msgid "partial clone failed; attempting full clone" -msgstr "nhân bản từng phần gặp lá»—i; Ä‘ang cố thá» nhân bản đầy đủ" - -msgid "could not configure for full clone" -msgstr "không thể cấu hình cho nhân bản đầy đủ" - -msgid "scalar diagnose [<enlistment>]" -msgstr "scalar diagnose [<enlistment>]" - -#, c-format -msgid "could not create directory for '%s'" -msgstr "không thể tạo thÆ° mục cho “%sâ€" - -msgid "could not duplicate stdout" -msgstr "không thể nhân đôi đầu và o tiêu chuẩn" - -msgid "failed to write archive" -msgstr "gặp lá»—i khi khi kho nén" - -msgid "`scalar list` does not take arguments" -msgstr "`scalar list` không nháºn các tham số" - -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<enlistment>]" - -msgid "reconfigure all registered enlistments" -msgstr "cấu hình má»i enlistments đã đăng ký" - -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all | <enlistment>]" - -msgid "--all or <enlistment>, but not both" -msgstr "--all hoặc <enlistment>, không thể là cả hai" - -#, c-format -msgid "git repository gone in '%s'" -msgstr "kho git ra Ä‘i trong '%s'" - -msgid "" -"scalar run <task> [<enlistment>]\n" -"Tasks:\n" -msgstr "" -"scalar run <task> [<enlistment>]\n" -"Nhiệm vụ:\n" - -#, c-format -msgid "no such task: '%s'" -msgstr "không có nhiệm vụ nà o nhÆ° thế: “%sâ€" - -msgid "scalar unregister [<enlistment>]" -msgstr "scalar unregister [<enlistment>]" - -msgid "scalar delete <enlistment>" -msgstr "scalar delete <enlistment>" - -msgid "refusing to delete current working directory" -msgstr "từ chối gỡ bá» thÆ° mục là m việc hiện tại" - -msgid "include Git version" -msgstr "bao gồm phiên bản Git" - -msgid "include Git's build options" -msgstr "bao gồm các tùy chá»n biên dịch của Git" - -msgid "scalar verbose [-v | --verbose] [--build-options]" -msgstr "scalar verbose [-v | --verbose] [--build-options]" - -msgid "-C requires a <directory>" -msgstr "-C cần má»™t <thÆ°_mục>" - -#, c-format -msgid "could not change to '%s'" -msgstr "không thể chuyển sang “%sâ€" - -msgid "-c requires a <key>=<value> argument" -msgstr "-c cần má»™t tham số <key>=<value>" - -msgid "" -"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n" -"\n" -"Commands:\n" -msgstr "" -"scalar [-C </thÆ°/mục/>] [-c <khóa>=<giá trị>] <lệnh> [<các tùy chá»n>]\n" -"\n" -"Các lệnh:\n" +msgstr "gặp lá»—i khi đóng stdin của rev-list" #, c-format msgid "illegal crlf_action %d" @@ -14859,55 +15412,55 @@ msgstr "" #, c-format msgid "BOM is prohibited in '%s' if encoded as %s" -msgstr "BOM bị cấm trong “%s†nếu được mã hóa là %s" +msgstr "BOM bị cấm trong '%s' nếu được mã hóa là %s" #, c-format msgid "" "The file '%s' contains a byte order mark (BOM). Please use UTF-%.*s as " "working-tree-encoding." msgstr "" -"Táºp tin “%s†có chứa ký hiệu thứ tá»± byte (BOM). Vui lòng dùng UTF-%.*s nhÆ° " +"Táºp tin '%s' có chứa ký hiệu thứ tá»± byte (BOM). Vui lòng dùng UTF-%.*s nhÆ° " "là bảng mã cây là m việc." #, c-format msgid "BOM is required in '%s' if encoded as %s" -msgstr "BOM là bắt buá»™c trong “%s†nếu được mã hóa là %s" +msgstr "BOM là bắt buá»™c trong '%s' nếu được mã hóa là %s" #, 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 "" -"Táºp tin “%s†còn thiếu ký hiệu thứ tá»± byte (BOM). Vui lòng dùng UTF-%sBE hay " +"Táºp tin '%s' còn thiếu ký hiệu thứ tá»± byte (BOM). Vui lòng dùng UTF-%sBE hay " "UTF-%sLE (còn phục thuá»™c và o thứ tá»± byte) nhÆ° là bảng mã cây là m việc." #, c-format msgid "failed to encode '%s' from %s to %s" -msgstr "gặp lá»—i khi mã hóa “%s†từ “%s†sang “%sâ€" +msgstr "gặp lá»—i khi mã hóa '%s' từ '%s' sang '%s'" #, c-format msgid "encoding '%s' from %s to %s and back is not the same" -msgstr "mã hóa “%s†từ %s thà nh %s và ngược trở lại không phải là cùng" +msgstr "mã hóa '%s' từ %s thà nh %s và ngược trở lại không phải là cùng" #, c-format msgid "cannot fork to run external filter '%s'" -msgstr "không thể rẽ nhánh tiến trình để chạy bá»™ lá»c bên ngoà i “%sâ€" +msgstr "không thể rẽ nhánh tiến trình để chạy bá»™ lá»c bên ngoà i '%s'" #, c-format msgid "cannot feed the input to external filter '%s'" -msgstr "không thể cấp đầu và o cho bá»™ lá»c bên ngoà i “%sâ€" +msgstr "không thể cấp đầu và o cho bá»™ lá»c bên ngoà i '%s'" #, c-format msgid "external filter '%s' failed %d" -msgstr "chạy bá»™ lá»c bên ngoà i “%s†gặp lá»—i %d" +msgstr "chạy bá»™ lá»c bên ngoà i '%s' gặp lá»—i %d" #, c-format msgid "read from external filter '%s' failed" -msgstr "Ä‘á»c từ bá»™ lá»c bên ngoà i “%s†gặp lá»—i" +msgstr "Ä‘á»c từ bá»™ lá»c bên ngoà i '%s' gặp lá»—i" #, c-format msgid "external filter '%s' failed" -msgstr "gặp lá»—i khi chạy bá»™ lá»c bên ngoà i “%sâ€" +msgstr "gặp lá»—i khi chạy bá»™ lá»c bên ngoà i '%s'" msgid "unexpected filter type" msgstr "gặp kiểu bá»™ lá»c thừa" @@ -14920,23 +15473,23 @@ msgid "" "external filter '%s' is not available anymore although not all paths have " "been filtered" msgstr "" -"bá»™ lá»c bên ngoà i “%s†không sẵn sà ng nữa mặc dù không phải tất cả các Ä‘Æ°á»ng " -"dẫn đã được lá»c" +"bá»™ lá»c ngoà i '%s' không còn nữa mặc dù không phải tất cả các Ä‘Æ°á»ng dẫn đã " +"được lá»c" msgid "true/false are no valid working-tree-encodings" -msgstr "true/false là không phải bảng-mã-cây-là m-việc hợp lệ" +msgstr "true/false không phải là bảng mã cây là m việc hợp lệ" #, c-format msgid "%s: clean filter '%s' failed" -msgstr "%s: gặp lá»—i khi xóa bá»™ lá»c “%sâ€" +msgstr "%s: bá»™ lá»c clean '%s' gặp lá»—i" #, c-format msgid "%s: smudge filter %s failed" -msgstr "%s: smudge bá»™ lá»c %s gặp lá»—i" +msgstr "%s: bá»™ lá»c smudge %s gặp lá»—i" #, c-format msgid "skipping credential lookup for key: credential.%s" -msgstr "bá» qua tìm kiếm giấy chứng chá»±c cho khóa: credential.%s" +msgstr "bá» qua tìm kiếm giấy chứng thá»±c cho khóa: credential.%s" msgid "refusing to work with credential missing host field" msgstr "từ chối là m việc vá»›i giấy chứng thá»±c thiếu trÆ°á»ng máy chủ" @@ -14954,10 +15507,10 @@ msgstr "url không có lược đồ: %s" #, c-format msgid "credential url cannot be parsed: %s" -msgstr "không thể phân tÃch cú pháp giấy chứng thá»±c url: %s" +msgstr "không hiểu cú pháp giấy chứng thá»±c url: %s" msgid "in the future" -msgstr "ở thá»i tÆ°Æ¡ng lai" +msgstr "ở tÆ°Æ¡ng lai" #, c-format msgid "%<PRIuMAX> second ago" @@ -15010,35 +15563,64 @@ msgstr "Äang lan truyá»n các đánh dấu island" #, c-format msgid "bad tree object %s" -msgstr "đối tượng cây sai “%sâ€" +msgstr "đối tượng cây sai '%s'" #, c-format msgid "failed to load island regex for '%s': %s" -msgstr "gặp lá»—i khi tải biểu thức chÃnh quy island cho “%sâ€: %s" +msgstr "gặp lá»—i khi tải biểu thức chÃnh quy island cho '%s': %s" #, c-format msgid "island regex from config has too many capture groups (max=%d)" msgstr "" -"biểu thức chÃnh quy island từ cấu hình có quá nhiá»u nhóm chụp (tối Ä‘a=%d)" +"biểu thức chÃnh quy island từ cấu hình có quá nhiá»u nhóm chá»n (tối Ä‘a=%d)" #, c-format msgid "Marked %d islands, done.\n" msgstr "Äã đánh dấu %d island, xong.\n" -msgid "--merge-base does not work with ranges" -msgstr "--merge-base không hoạt Ä‘á»™ng vá»›i phạm vi" +#, c-format +msgid "invalid --%s value '%s'" +msgstr "giá trị --%s không hợp lệ: '%s'" -msgid "--merge-base only works with commits" -msgstr "--merge-base chỉ hoạt Ä‘á»™ng vá»›i các lần chuyển giao" +#, c-format +msgid "could not archive missing directory '%s'" +msgstr "không thể nén thÆ° mục '%s' không còn tồn tại" + +#, c-format +msgid "could not open directory '%s'" +msgstr "không thể mở thÆ° mục '%s'" + +#, c-format +msgid "skipping '%s', which is neither file nor directory" +msgstr "Ä‘ang bá» qua '%s', không phải là má»™t táºp tin hay thÆ° mục" + +msgid "could not duplicate stdout" +msgstr "không thể nhân bản stdout" + +#, c-format +msgid "could not add directory '%s' to archiver" +msgstr "không thể thêm thÆ° mục '%s' và o kho nén" + +msgid "failed to write archive" +msgstr "gặp lá»—i khi ghi kho nén" + +msgid "--merge-base does not work with ranges" +msgstr "--merge-base không thể dùng vá»›i chỉ vùng" msgid "unable to get HEAD" msgstr "không thể lấy HEAD" msgid "no merge base found" -msgstr "không tìm thấy cÆ¡ sở để hòa trá»™n" +msgstr "không tìm thấy gốc hòa trá»™n" msgid "multiple merge bases found" -msgstr "có nhiá»u cÆ¡ sở để hòa trá»™n" +msgstr "có nhiá»u hÆ¡n má»™t gốc hòa trá»™n" + +msgid "cannot compare stdin to a directory" +msgstr "không thể so sánh stdin và thÆ° mục" + +msgid "cannot compare a named pipe to a directory" +msgstr "không thể so sánh pipe có tên và thÆ° mục" msgid "git diff --no-index [<options>] <path> <path>" msgstr "git diff --no-index [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn> </Ä‘Æ°á»ng/dẫn>" @@ -15048,54 +15630,65 @@ msgid "" "tree" msgstr "" "Không phải là má»™t thÆ° mục git. Dùng --no-index để so sánh hai Ä‘Æ°á»ng dẫn bên " -"ngoà i má»™t cây là m việc" +"ngoà i cây là m việc" #, c-format msgid " Failed to parse dirstat cut-off percentage '%s'\n" -msgstr " Gặp lá»—i khi phân tÃch dirstat cắt bá» phần trăm “%sâ€\n" +msgstr " Gặp lá»—i khi Ä‘á»c phần trăm cắt bá» dirstat '%s'\n" #, c-format msgid " Unknown dirstat parameter '%s'\n" -msgstr " Không hiểu đối số dirstat “%sâ€\n" +msgstr " Không hiểu đối số dirstat '%s'\n" msgid "" "color moved setting must be one of 'no', 'default', 'blocks', 'zebra', " "'dimmed-zebra', 'plain'" msgstr "" -"cà i đặt mà u đã di chuyển phải là má»™t trong “noâ€, “defaultâ€, “blocksâ€, " -"“zebraâ€, “dimmed-zebraâ€, “plainâ€" +"cà i đặt color moved phải là má»™t trong 'no', 'default', 'blocks', 'zebra', " +"'dimmed-zebra', 'plain'" #, c-format msgid "" "unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', " "'ignore-space-at-eol', 'ignore-all-space', 'allow-indentation-change'" msgstr "" -"không hiểu chế Ä‘á»™ color-moved-ws “%sâ€, các giá trị có thể là “ignore-space-" -"changeâ€, “ignore-space-at-eolâ€, “ignore-all-spaceâ€, “allow-indentation-" -"changeâ€" +"không hiểu chế Ä‘á»™ color-moved-ws '%s', các giá trị có thể là 'ignore-space-" +"change', 'ignore-space-at-eol', 'ignore-all-space', 'allow-indentation-" +"change'" msgid "" "color-moved-ws: allow-indentation-change cannot be combined with other " "whitespace modes" msgstr "" -"color-moved-ws: allow-indentation-change không thể tổ hợp cùng vá»›i các chế " +"color-moved-ws: allow-indentation-change không thể kết hợp cùng vá»›i các chế " "Ä‘á»™ khoảng trắng khác" #, c-format msgid "Unknown value for 'diff.submodule' config variable: '%s'" -msgstr "Không hiểu giá trị cho biến cấu hình “diff.submoduleâ€: “%sâ€" +msgstr "Không hiểu giá trị cho biến cấu hình 'diff.submodule': '%s'" + +#, c-format +msgid "unknown value for config '%s': %s" +msgstr "không hiểu giá trị cho cho cấu hình '%s': %s" #, c-format msgid "" "Found errors in 'diff.dirstat' config variable:\n" "%s" msgstr "" -"Tìm thấy các lá»—i trong biến cấu hình “diff.dirstatâ€:\n" +"Tìm thấy các lá»—i trong biến cấu hình 'diff.dirstat':\n" "%s" #, c-format msgid "external diff died, stopping at %s" -msgstr "phần má»m diff ở bên ngoà i đã chết, dừng tại %s" +msgstr "phần má»m diff ở bên ngoà i đã thoát, dừng tại %s" + +msgid "--follow requires exactly one pathspec" +msgstr "--follow cần đúng má»™t đặc tả Ä‘Æ°á»ng dẫn" + +#, c-format +msgid "pathspec magic not supported by --follow: %s" +msgstr "đặc tả Ä‘Æ°á»ng dẫn đặc biệt chÆ°a được há»— trợ bởi --follow: %s" #, c-format msgid "options '%s', '%s', '%s', and '%s' cannot be used together" @@ -15111,28 +15704,25 @@ msgid "" msgstr "" "tùy chá»n '%s' và '%s' không thể dùng cùng nhau, dùng '%s' vá»›i '%s' và '%s'" -msgid "--follow requires exactly one pathspec" -msgstr "--follow cần chÃnh xác má»™t đặc tả Ä‘Æ°á»ng dẫn" - #, c-format msgid "invalid --stat value: %s" -msgstr "giá trị --stat không hợp lệ: “%sâ€" +msgstr "giá trị --stat không hợp lệ: '%s'" #, c-format msgid "%s expects a numerical value" -msgstr "tùy chá»n “%s†cần má»™t giá trị bằng số" +msgstr "tùy chá»n '%s' cần má»™t giá trị số" #, c-format msgid "" "Failed to parse --dirstat/-X option parameter:\n" "%s" msgstr "" -"Gặp lá»—i khi phân tÃch đối số tùy chá»n --dirstat/-X:\n" +"Gặp lá»—i khi Ä‘á»c đối số tùy chá»n --dirstat/-X:\n" "%s" #, c-format msgid "unknown change class '%c' in --diff-filter=%s" -msgstr "không hiểu lá»›p thay đổi “%c†trong --diff-filter=%s" +msgstr "không hiểu change class '%c' trong --diff-filter=%s" #, c-format msgid "unknown value after ws-error-highlight=%.*s" @@ -15140,7 +15730,7 @@ msgstr "không hiểu giá trị sau ws-error-highlight=%.*s" #, c-format msgid "unable to resolve '%s'" -msgstr "không thể phân giải “%sâ€" +msgstr "không thể phân giải '%s'" #, c-format msgid "%s expects <n>/<m> form" @@ -15148,7 +15738,7 @@ msgstr "%s cần dạng <n>/<m>" #, c-format msgid "%s expects a character, got '%s'" -msgstr "%s cần má»™t ký tá»±, nhÆ°ng lại nháºn được “%sâ€" +msgstr "%s cần má»™t ký tá»±, nhÆ°ng lại có '%s'" #, c-format msgid "bad --color-moved argument: %s" @@ -15156,14 +15746,7 @@ msgstr "đối số --color-moved sai: %s" #, c-format msgid "invalid mode '%s' in --color-moved-ws" -msgstr "chế Ä‘á»™ “%s†không hợp lệ trong --color-moved-ws" - -msgid "" -"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and " -"\"histogram\"" -msgstr "" -"tùy chá»n diff-algorithm chấp nháºn \"myers\", \"minimal\", \"patience\" và " -"\"histogram\"" +msgstr "chế Ä‘á»™ '%s' không hợp lệ trong --color-moved-ws" #, c-format msgid "invalid argument to %s" @@ -15171,11 +15754,11 @@ msgstr "tham số cho %s không hợp lệ" #, c-format msgid "invalid regex given to -I: '%s'" -msgstr "Ä‘Æ°a cho -I biểu thức chÃnh quy không hợp lệ: “%sâ€" +msgstr "Ä‘Æ°a cho -I biểu thức chÃnh quy không hợp lệ: '%s'" #, c-format msgid "failed to parse --submodule option parameter: '%s'" -msgstr "gặp lá»—i khi phân tÃch đối số tùy chá»n --submodule: “%sâ€" +msgstr "gặp lá»—i khi Ä‘á»c đối số tùy chá»n --submodule: '%s'" #, c-format msgid "bad --word-diff argument: %s" @@ -15185,7 +15768,7 @@ msgid "Diff output format options" msgstr "Các tùy chá»n định dạng khi xuất các khác biệt" msgid "generate patch" -msgstr "tạo miếng vá" +msgstr "tạo bản vá" msgid "<n>" msgstr "<n>" @@ -15197,10 +15780,10 @@ msgid "generate the diff in raw format" msgstr "tạo khác biệt ở định dạng thô" msgid "synonym for '-p --raw'" -msgstr "đồng nghÄ©a vá»›i “-p --rawâ€" +msgstr "đồng nghÄ©a vá»›i '-p --raw'" msgid "synonym for '-p --stat'" -msgstr "đồng nghÄ©a vá»›i “-p --statâ€" +msgstr "đồng nghÄ©a vá»›i '-p --stat'" msgid "machine friendly --stat" msgstr "--stat thuáºn tiện cho máy Ä‘á»c" @@ -15208,8 +15791,8 @@ 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" -msgid "<param1,param2>..." -msgstr "<tham_số_1,tham_số_2>…" +msgid "<param1>,<param2>..." +msgstr "<tham_số_1>,<tham_số_2>..." msgid "" "output the distribution of relative amount of changes for each sub-directory" @@ -15218,8 +15801,8 @@ msgstr "đầu ra phân phối của số lượng thay đổi tÆ°Æ¡ng đối ch msgid "synonym for --dirstat=cumulative" msgstr "đồng nghÄ©a vá»›i --dirstat=cumulative" -msgid "synonym for --dirstat=files,param1,param2..." -msgstr "đồng nghÄ©a vá»›i --dirstat=files,param1,param2…" +msgid "synonym for --dirstat=files,<param1>,<param2>..." +msgstr "đồng nghÄ©a vá»›i --dirstat=files,<tham_số_1>,<tham_số_2>..." msgid "warn if changes introduce conflict markers or whitespace errors" msgstr "" @@ -15266,8 +15849,8 @@ msgstr "xuất ra má»™t khác biệt dạng nhị phân cái mà có thể Ä‘Æ°á msgid "show full pre- and post-image object names on the \"index\" lines" msgstr "" -"hiển thị đầy đủ các tên đối tượng pre- và post-image trên các dòng \"mục lục" -"\"" +"hiển thị đầy đủ các tên đối tượng pre- và post-image trên các dòng \"mục " +"lục\"" msgid "show colored diff" msgstr "hiển thị thay đổi được tô mà u" @@ -15279,7 +15862,7 @@ msgid "" "highlight whitespace errors in the 'context', 'old' or 'new' lines in the " "diff" msgstr "" -"tô sáng các lá»—i vá» khoảng trắng trong các dòng “contextâ€, “old†và “new†" +"tô sáng các lá»—i vá» khoảng trắng trong các dòng 'context', 'old' và 'new' " "trong khác biệt" msgid "" @@ -15290,7 +15873,7 @@ msgstr "" "trong --raw hay --numstat" msgid "<prefix>" -msgstr "<tiá»n_tố>" +msgstr "<tiá»n tố>" msgid "show the given source prefix instead of \"a/\"" msgstr "hiển thị tiá»n tố nguồn đã cho thay cho \"a/\"" @@ -15304,6 +15887,9 @@ msgstr "treo và o trÆ°á»›c má»™t tiá»n tố bổ sung cho má»—i dòng kết xuá msgid "do not show any source or destination prefix" msgstr "đừng hiển thị bất kỳ tiá»n tố nguồn hay Ä‘Ãch" +msgid "use default prefixes a/ and b/" +msgstr "dùng tiá»n tố mặc định a/ và b/" + msgid "show context between diff hunks up to the specified number of lines" msgstr "" "hiển thị ngữ cảnh giữa các khúc khác biệt khi đạt đến số lượng dòng đã chỉ " @@ -15313,13 +15899,13 @@ msgid "<char>" msgstr "<ký_tá»±>" msgid "specify the character to indicate a new line instead of '+'" -msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t dòng được thêm má»›i thay cho “+â€" +msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t dòng được thêm má»›i thay cho '+'" msgid "specify the character to indicate an old line instead of '-'" -msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t dòng đã cÅ© thay cho “-â€" +msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t dòng đã cÅ© thay cho '-'" msgid "specify the character to indicate a context instead of ' '" -msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t ngữ cảnh thay cho “â€" +msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t ngữ cảnh thay cho ''" msgid "Diff rename options" msgstr "Tùy chá»n khác biệt đổi tên" @@ -15365,13 +15951,13 @@ msgid "produce the smallest possible diff" msgstr "sản sinh khác biệt Ãt nhất có thể" msgid "ignore whitespace when comparing lines" -msgstr "lá» Ä‘i sá»± thay đổi do khoảng trắng gây ra khi so sánh các dòng" +msgstr "bá» qua sá»± thay đổi do khoảng trắng gây ra khi so sánh các dòng" msgid "ignore changes in amount of whitespace" -msgstr "lá» Ä‘i sá»± thay đổi do số lượng khoảng trắng gây ra" +msgstr "bá» qua sá»± thay đổi do số lượng khoảng trắng gây ra" msgid "ignore changes in whitespace at EOL" -msgstr "lá» Ä‘i sá»± thay đổi do khoảng trắng gây ra khi ở cuối dòng EOL" +msgstr "bá» qua sá»± thay đổi do khoảng trắng gây ra khi ở cuối dòng EOL" msgid "ignore carrier-return at the end of line" msgstr "bá» qua ký tá»± vỠđầu dòng tại cuối dòng" @@ -15394,12 +15980,6 @@ msgstr "tạo khác biệt sá» dung thuáºt toán \"patience diff\"" msgid "generate diff using the \"histogram diff\" algorithm" msgstr "tạo khác biệt sá» dung thuáºt toán \"histogram diff\"" -msgid "<algorithm>" -msgstr "<thuáºt toán>" - -msgid "choose a diff algorithm" -msgstr "chá»n má»™t thuáºt toán khác biệt" - msgid "<text>" msgstr "<văn bản>" @@ -15446,7 +16026,7 @@ msgid "disable all output of the program" msgstr "tắt má»i kết xuất của chÆ°Æ¡ng trình" msgid "allow an external diff helper to be executed" -msgstr "cho phép má»™ bá»™ há»— trợ xuất khác biệt ở bên ngoà i được phép thá»±c thi" +msgstr "cho phép má»™ helper xuất khác biệt ở bên ngoà i được phép thá»±c thi" msgid "run external text conversion filters when comparing binary files" msgstr "" @@ -15466,10 +16046,10 @@ msgid "specify how differences in submodules are shown" msgstr "chi định khác biệt bao nhiêu trong các mô Ä‘un con được hiển thị" msgid "hide 'git add -N' entries from the index" -msgstr "ẩn các mục “git add -N†từ bảng mục lục" +msgstr "ẩn các mục 'git add -N' từ chỉ mục" msgid "treat 'git add -N' entries as real in the index" -msgstr "coi các mục “git add -N†nhÆ° là có tháºt trong bảng mục lục" +msgstr "coi các mục 'git add -N' nhÆ° là có tháºt trong chỉ mục" msgid "<string>" msgstr "<chuá»—i>" @@ -15492,19 +16072,19 @@ msgid "show all changes in the changeset with -S or -G" msgstr "hiển thị tất cả các thay đổi trong má»™t bá»™ các thay đổi vá»›i -S hay -G" msgid "treat <string> in -S as extended POSIX regular expression" -msgstr "coi <chuá»—i> trong -S nhÆ° là biểu thức chÃnh qui POSIX có mở rá»™ng" +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 kết xuất" +msgstr "Ä‘iá»u khiển thứ tá»± xuất hiện các táºp tin trong đầu ra" msgid "<path>" msgstr "<Ä‘Æ°á»ng-dẫn>" msgid "show the change in the specified path first" -msgstr "hiển thị các thay đổi trong Ä‘Æ°á»ng dẫn đã cho đầu tiên" +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 đến Ä‘Æ°á»ng dẫn đã cho" +msgstr "bá» qua đầu ra vá»›i Ä‘Æ°á»ng dẫn đã cho" msgid "<object-id>" msgstr "<mã-số-đối-tượng>" @@ -15512,42 +16092,38 @@ msgstr "<mã-số-đối-tượng>" msgid "" "look for differences that change the number of occurrences of the specified " "object" -msgstr "" -"tìm các khác biệt cái mà thay đổi số lượng xảy ra của các phát sinh của đối " -"tượng được chỉ ra" +msgstr "tìm các diff có thay đổi số lượng xuất hiện của đối tượng" msgid "[(A|C|D|M|R|T|U|X|B)...[*]]" -msgstr "[(A|C|D|M|R|T|U|X|B)…[*]]" +msgstr "[(A|C|D|M|R|T|U|X|B)...[*]]" msgid "select files by diff type" msgstr "chá»n các táºp tin theo kiểu khác biệt" msgid "<file>" -msgstr "<táºp_tin>" +msgstr "<táºp tin>" msgid "output to a specific file" -msgstr "xuất ra má»™t táºp tin cụ thể" +msgstr "xuất ra táºp tin nà y" msgid "exhaustive rename detection was skipped due to too many files." -msgstr "nháºn thấy đổi tên toà n diện đã bị bá» qua bởi có quá nhiá»u táºp tin." +msgstr "bá» tìm tất cả các lần đổi tên vì có quá nhiá»u táºp tin." msgid "only found copies from modified paths due to too many files." msgstr "" -"chỉ tìm thấy các bản sao từ Ä‘Æ°á»ng dẫn đã sá»a đổi bởi vì có quá nhiá»u táºp tin." +"chỉ tìm các lần sao chép từ Ä‘Æ°á»ng dẫn đã sá»a đổi vì có quá nhiá»u táºp tin." #, c-format msgid "" "you may want to set your %s variable to at least %d and retry the command." -msgstr "" -"bạn có lẽ muốn đặt biến %s của bạn thà nh Ãt nhất là %d và thá» lại lệnh lần " -"nữa." +msgstr "bạn có lẽ muốn đặt biến %s của bạn thà nh Ãt nhất là %d và thá» lại." #, c-format msgid "failed to read orderfile '%s'" -msgstr "gặp lá»—i khi Ä‘á»c táºp-tin-thứ-tá»± “%sâ€" +msgstr "gặp lá»—i khi Ä‘á»c orderfile '%s'" msgid "Performing inexact rename detection" -msgstr "Äang thá»±c hiện dò tìm đổi tên không chÃnh xác" +msgstr "Äang thá»±c hiện inexact rename detection (tìm sÆ¡ bá»™ các lần đổi tên)" #, c-format msgid "No such path '%s' in the diff" @@ -15555,43 +16131,43 @@ msgstr "Không có Ä‘Æ°á»ng dẫn %s trong diff" #, c-format msgid "pathspec '%s' did not match any file(s) known to git" -msgstr "đặc tả Ä‘Æ°á»ng dẫn “%s†không khá»›p vá»›i bất kỳ táºp tin nà o mà git biết" +msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' không khá»›p vá»›i bất kỳ táºp tin nà o mà git biết" #, c-format msgid "unrecognized pattern: '%s'" -msgstr "mẫu không được thừa nháºn: “%sâ€" +msgstr "không hiểu mẫu: '%s'" #, c-format msgid "unrecognized negative pattern: '%s'" -msgstr "mẫu âm không được thừa nháºn: “%sâ€" +msgstr "không hiểu mẫu loại trừ: '%s'" #, c-format msgid "your sparse-checkout file may have issues: pattern '%s' is repeated" -msgstr "táºp tin sparse-checkout của bạn có lẽ gặp lá»—i: mẫu “%s†đã bị lặp lại" +msgstr "táºp tin sparse-checkout của bạn có lẽ gặp lá»—i: mẫu '%s' đã bị lặp lại" msgid "disabling cone pattern matching" -msgstr "vô hiệu khá»›p mẫu nón" +msgstr "vô hiệu cone pattern matching (khá»›p mẫu nón)" #, c-format msgid "cannot use %s as an exclude file" -msgstr "không thể dùng %s nhÆ° là má»™t táºp tin loại trừ" +msgstr "không thể dùng %s nhÆ° là táºp tin loại trừ" msgid "failed to get kernel name and information" -msgstr "gặp lá»—i khi lấy tên và thông tin của nhân" +msgstr "gặp lá»—i khi lấy tên và thông tin của kernel" msgid "untracked cache is disabled on this system or location" -msgstr "bá»™ nhá»› tạm không theo vết bị tắt trên hệ thống hay vị trà nà y" +msgstr "bá»™ nhá»› tạm không theo vết bị vô hiệu trên hệ thống hay vị trà nà y" msgid "" "No directory name could be guessed.\n" "Please specify a directory on the command line" msgstr "" "Không Ä‘oán được thÆ° mục tên là gì.\n" -"Vui lòng chỉ định tên má»™t thÆ° mục trên dòng lệnh" +"Vui lòng chỉ định tên thÆ° mục trên dòng lệnh" #, c-format msgid "index file corrupt in repo %s" -msgstr "táºp tin ghi bảng mục lục bị há»ng trong kho %s" +msgstr "táºp tin ghi chỉ mục bị há»ng trong kho %s" #, c-format msgid "could not create directories for %s" @@ -15599,18 +16175,26 @@ msgstr "không thể tạo thÆ° mục cho %s" #, c-format msgid "could not migrate git directory from '%s' to '%s'" -msgstr "không thể di dá»i thÆ° mục git từ “%s†sang “%sâ€" +msgstr "không thể di dá»i thÆ° mục git từ '%s' sang '%s'" #, c-format msgid "hint: Waiting for your editor to close the file...%c" -msgstr "gợi ý: Chá» trình biên soạn của bạn đóng táºp tin…%c" +msgstr "gợi ý: Chá» trình biên soạn của bạn đóng táºp tin...%c" + +#, c-format +msgid "could not write to '%s'" +msgstr "không thể ghi và o '%s'" + +#, c-format +msgid "could not edit '%s'" +msgstr "không thể sá»a '%s'" msgid "Filtering content" msgstr "Ná»™i dung lá»c" #, c-format msgid "could not stat file '%s'" -msgstr "không thể lấy thống kê táºp tin “%sâ€" +msgstr "không thể lấy thống kê táºp tin '%s'" #, c-format msgid "bad git namespace path \"%s\"" @@ -15624,17 +16208,20 @@ msgid "git fetch-pack: expected shallow list" msgstr "git fetch-pack: cần danh sách shallow" msgid "git fetch-pack: expected a flush packet after shallow list" -msgstr "git fetch-pack: cần má»™t gói đẩy sau danh sách shallow" +msgstr "git fetch-pack: cần má»™t gói flush sau danh sách shallow" msgid "git fetch-pack: expected ACK/NAK, got a flush packet" msgstr "git fetch-pack: cần ACK/NAK, nhÆ°ng lại nháºn được má»™t gói flush" #, c-format msgid "git fetch-pack: expected ACK/NAK, got '%s'" -msgstr "git fetch-pack: cần ACK/NAK, nhÆ°ng lại nháºn được “%sâ€" +msgstr "git fetch-pack: cần ACK/NAK, nhÆ°ng lại nháºn được '%s'" msgid "unable to write to remote" -msgstr "không thể ghi lên máy phục vụ" +msgstr "không thể ghi lên máy chủ" + +msgid "Server supports filter" +msgstr "Máy chủ há»— trợ bá»™ lá»c" #, c-format msgid "invalid shallow line: %s" @@ -15658,7 +16245,7 @@ msgstr "không tìm shallow nà o: %s" #, c-format msgid "expected shallow/unshallow, got %s" -msgstr "cần shallow/unshallow, nhÆ°ng lại nháºn được %s" +msgstr "cần shallow/unshallow, nhÆ°ng lại có %s" #, c-format msgid "got %s %d %s" @@ -15741,28 +16328,25 @@ msgstr "các thuáºt toán không khá»›p nhau: máy khách %s; máy chủ %s" #, c-format msgid "the server does not support algorithm '%s'" -msgstr "máy chủ không há»— trợ thuáºt toán “%sâ€" +msgstr "máy chủ không há»— trợ thuáºt toán '%s'" msgid "Server does not support shallow requests" msgstr "Máy chủ không há»— trợ yêu cầu shallow" -msgid "Server supports filter" -msgstr "Máy chủ há»— trợ bá»™ lá»c" - msgid "unable to write request to remote" -msgstr "không thể ghi các yêu cầu lên máy phục vụ" +msgstr "không thể ghi các yêu cầu lên máy chủ" #, c-format msgid "expected '%s', received '%s'" -msgstr "cần “%sâ€, nhÆ°ng lại nháºn “%sâ€" +msgstr "cần '%s', nhÆ°ng lại nháºn '%s'" #, c-format msgid "expected '%s'" -msgstr "cần “%sâ€" +msgstr "cần '%s'" #, c-format msgid "unexpected acknowledgment line: '%s'" -msgstr "gặp dòng không được thừa nháºn: “%sâ€" +msgstr "gặp dòng không được thừa nháºn: '%s'" #, c-format msgid "error processing acks: %d" @@ -15773,14 +16357,14 @@ msgstr "gặp lá»—i khi xá» lý tÃn hiệu trả lá»i: %d" #. #, c-format msgid "expected packfile to be sent after '%s'" -msgstr "cần táºp tin gói để gá»i sau “%sâ€" +msgstr "cần táºp tin gói để gá»i sau '%s'" #. TRANSLATORS: The parameter will be 'ready', a protocol #. keyword. #. #, c-format msgid "expected no other sections to be sent after no '%s'" -msgstr "không cần thêm phần nà o để gá»i sau không “%sâ€" +msgstr "không có phần nà o để gá»i khi không có '%s'" #, c-format msgid "error processing shallow info: %d" @@ -15788,11 +16372,11 @@ msgstr "lá»—i xá» lý thông tin shallow: %d" #, c-format msgid "expected wanted-ref, got '%s'" -msgstr "cần wanted-ref, nhÆ°ng lại nháºn được “%sâ€" +msgstr "cần wanted-ref, nhÆ°ng lại nháºn được '%s'" #, c-format msgid "unexpected wanted-ref: '%s'" -msgstr "wanted-ref không được mong đợi: “%sâ€" +msgstr "wanted-ref không được mong đợi: '%s'" #, c-format msgid "error processing wanted refs: %d" @@ -15805,7 +16389,7 @@ msgid "no matching remote head" msgstr "không khá»›p phần đầu máy chủ" msgid "unexpected 'ready' from remote" -msgstr "gặp “ready†đột xuất từ máy chủ" +msgstr "gặp 'ready' Ä‘á»™t xuất từ máy chủ" #, c-format msgid "no such remote ref %s" @@ -15813,8 +16397,7 @@ msgstr "không có máy chủ tham chiếu nà o nhÆ° %s" #, c-format msgid "Server does not allow request for unadvertised object %s" -msgstr "" -"Máy phục vụ không cho phép yêu cầu cho đối tượng không được báo trÆ°á»›c %s" +msgstr "máy chủ không cho phép yêu cầu cho đối tượng không được báo trÆ°á»›c %s" #, c-format msgid "fsmonitor_ipc__send_query: invalid path '%s'" @@ -15833,7 +16416,7 @@ msgstr "không thể gá»i lệnh '%s' đến fsmonitor--daemon" #, c-format msgid "bare repository '%s' is incompatible with fsmonitor" -msgstr "kho thuần '%s' là không tÆ°Æ¡ng thÃch vá»›i fsmonitor" +msgstr "kho bare '%s' là không tÆ°Æ¡ng thÃch vá»›i fsmonitor" #, c-format msgid "repository '%s' is incompatible with fsmonitor due to errors" @@ -15849,8 +16432,11 @@ msgstr "kho ảo '%s' là không tÆ°Æ¡ng thÃch vá»›i fsmonitor" #, c-format msgid "" -"repository '%s' is incompatible with fsmonitor due to lack of Unix sockets" -msgstr "kho '%s' là không tÆ°Æ¡ng thÃch vá»›i fsmonitor bởi vì thiếu Unix sockets" +"socket directory '%s' is incompatible with fsmonitor due to lack of Unix " +"sockets support" +msgstr "" +"thÆ° mục socket '%s' không tÆ°Æ¡ng thÃch vá»›i fsmonitor bởi vì thiếu há»— trợ Unix " +"socket" msgid "" "git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" @@ -15858,18 +16444,16 @@ msgid "" " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--" "bare]\n" " [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" -" [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n" -" <command> [<args>]" +" [--config-env=<name>=<envvar>] <command> [<args>]" msgstr "" -"git [--version] [-h | --help] [-C </Ä‘Æ°á»ng/dẫn/>] [-c <tên>=<giá trị>]\n" +"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" -" [--super-prefix=</Ä‘Æ°á»ng/dẫn/>] [--config-env=<tên>=<envvar>]\n" -" <lệnh> [<các tham số>]" +" [--config-env=<tên>=<envvar>] <lệnh> [<các tham số>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -15877,14 +16461,14 @@ msgid "" "to read about a specific subcommand or concept.\n" "See 'git help git' for an overview of the system." msgstr "" -"“git help -a†và “git help -g†liệt kê các câu lệnh con sẵn có và má»™t số\n" -"hÆ°á»›ng dẫn vá» khái niệm. Xem “git help <lệnh>†hay “git help <khái-niệm>â€\n" +"'git help -a' và 'git help -g' liệt kê các câu lệnh con sẵn có và má»™t số\n" +"hÆ°á»›ng dẫn vá» khái niệm. Xem 'git help <lệnh>' hay 'git help <khái-niệm>'\n" "để xem các đặc tả cho lệnh hay khái niệm cụ thể.\n" -"Xem “git help git†để biết tổng quan của hệ thống." +"Xem 'git help git' để biết tổng quan của hệ thống." #, c-format msgid "unsupported command listing type '%s'" -msgstr "không há»— trợ liệt kê lệnh kiểu “%sâ€" +msgstr "không há»— trợ liệt kê lệnh kiểu '%s'" #, c-format msgid "no directory given for '%s' option\n" @@ -15895,10 +16479,6 @@ msgid "no namespace given for --namespace\n" msgstr "chÆ°a Ä‘Æ°a ra không gian là m việc cho --namespace\n" #, c-format -msgid "no prefix given for --super-prefix\n" -msgstr "chÆ°a Ä‘Æ°a ra tiá»n tố cho --super-prefix\n" - -#, c-format msgid "-c expects a configuration string\n" msgstr "-c cần má»™t chuá»—i cấu hình\n" @@ -15907,20 +16487,24 @@ msgid "no config key given for --config-env\n" msgstr "không Ä‘Æ°a ra khóa cấu hình cho --config-env\n" #, c-format +msgid "no attribute source given for --attr-source\n" +msgstr "không Ä‘Æ°a ra nguồn thuá»™c tÃnh cho --attr-source\n" + +#, c-format msgid "unknown option: %s\n" msgstr "không hiểu tùy chá»n: %s\n" #, c-format msgid "while expanding alias '%s': '%s'" -msgstr "trong khi triển khai bà danh “%sâ€: “%sâ€" +msgstr "trong khi triển khai bà danh '%s': '%s'" #, c-format msgid "" "alias '%s' changes environment variables.\n" "You can use '!git' in the alias to do this" msgstr "" -"bà danh “%s†thay đổi biến môi trÆ°á»ng.\n" -"Bạn có thể sá» dụng “!git†trong đặt bà danh để là m việc nà y" +"bà danh '%s' thay đổi biến môi trÆ°á»ng.\n" +"Bạn có thể sá» dụng '!git' trong đặt bà danh để là m việc nà y" #, c-format msgid "empty alias for %s" @@ -15931,22 +16515,22 @@ msgid "recursive alias: %s" msgstr "đệ quy các bà danh: %s" msgid "write failure on standard output" -msgstr "lá»—i ghi nghiêm trong trên đầu ra tiêu chuẩn" +msgstr "lá»—i khi ghi ra stdout" msgid "unknown write failure on standard output" -msgstr "lá»—i nghiêm trá»ng chÆ°a biết khi ghi ra đầu ra tiêu chuẩn" +msgstr "lá»—i không rõ khi ghi ra stdout" msgid "close failed on standard output" -msgstr "gặp lá»—i khi đóng đầu ra tiêu chuẩn" +msgstr "lá»—i khi đóng stdout" #, c-format msgid "alias loop detected: expansion of '%s' does not terminate:%s" msgstr "" -"dò tìm thấy các bà danh quẩn tròn: biểu thức của “%s†không có Ä‘iểm kết:%s" +"dò tìm thấy các bà danh quẩn tròn: biểu thức của '%s' không có Ä‘iểm kết:%s" #, c-format msgid "cannot handle %s as a builtin" -msgstr "không thể xá» lý %s nhÆ° là má»™t phần bổ sung" +msgstr "không thể xá» lý %s nhÆ° là builtin" #, c-format msgid "" @@ -15958,18 +16542,18 @@ msgstr "" #, c-format msgid "expansion of alias '%s' failed; '%s' is not a git command\n" -msgstr "gặp lá»—i khi khai triển bà danh “%sâ€; “%s†không phải là lệnh git\n" +msgstr "gặp lá»—i khi khai triển bà danh '%s'; '%s' không phải là lệnh git\n" #, c-format msgid "failed to run command '%s': %s\n" -msgstr "gặp lá»—i khi chạy lệnh “%sâ€: %s\n" +msgstr "gặp lá»—i khi chạy lệnh '%s': %s\n" msgid "could not create temporary file" msgstr "không thể tạo táºp tin tạm thá»i" #, c-format msgid "failed writing detached signature to '%s'" -msgstr "gặp lá»—i khi ghi chữ ký Ä‘Ãnh kèm và o “%sâ€" +msgstr "gặp lá»—i khi ghi chữ ký Ä‘Ãnh kèm và o '%s'" msgid "" "gpg.ssh.allowedSignersFile needs to be configured and exist for ssh " @@ -15991,11 +16575,11 @@ msgstr "táºp tin thu hồi chữ ký ssh đã được cấu hình nhÆ°ng khôn #, c-format msgid "bad/incompatible signature '%s'" -msgstr "chữ sai / không tÆ°Æ¡ng thÃch “%sâ€" +msgstr "chữ sai / không tÆ°Æ¡ng thÃch '%s'" #, c-format msgid "failed to get the ssh fingerprint for key '%s'" -msgstr "gặp lá»—i khi lấy dấu vân tay ssh cho khóa “%sâ€" +msgstr "gặp lá»—i khi lấy dấu vân tay ssh cho khóa '%s'" msgid "" "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured" @@ -16011,19 +16595,24 @@ msgstr "" msgid "gpg.ssh.defaultKeyCommand failed: %s %s" msgstr "gpg.ssh.defaultKeyCommand gặp lá»—i: %s %s" -msgid "gpg failed to sign the data" -msgstr "gpg gặp lá»—i khi ký dữ liệu" +#, c-format +msgid "" +"gpg failed to sign the data:\n" +"%s" +msgstr "" +"gpg gặp lá»—i khi ký dữ liệu:\n" +"%s" msgid "user.signingKey needs to be set for ssh signing" msgstr "user.signingKey cần được đặt cho ký ssh" #, c-format msgid "failed writing ssh signing key to '%s'" -msgstr "gặp lá»—i khi ghi chìa khóa ký ssh và o “%sâ€" +msgstr "gặp lá»—i khi ghi chìa khóa ký ssh và o '%s'" #, c-format msgid "failed writing ssh signing key buffer to '%s'" -msgstr "gặp lá»—i khi ghi bá»™ đệm chìa khóa ký ssh và o “%sâ€" +msgstr "gặp lá»—i khi ghi bá»™ đệm chìa khóa ký ssh và o '%s'" msgid "" "ssh-keygen -Y sign is needed for ssh signing (available in openssh version " @@ -16034,11 +16623,11 @@ msgstr "" #, c-format msgid "failed reading ssh signing data buffer from '%s'" -msgstr "gặp lá»—i khi Ä‘á»c bá»™ đệm dữ liệu chữ ký ssh từ “%sâ€" +msgstr "gặp lá»—i khi Ä‘á»c bá»™ đệm dữ liệu chữ ký ssh từ '%s'" #, c-format msgid "ignored invalid color '%.*s' in log.graphColors" -msgstr "bá» qua mà u không hợp lệ “%.*s†trong log.graphColors" +msgstr "bá» qua mà u không hợp lệ '%.*s' trong log.graphColors" msgid "" "given pattern contains NULL byte (via -f <file>). This is only supported " @@ -16049,11 +16638,11 @@ msgstr "" #, c-format msgid "'%s': unable to read %s" -msgstr "“%sâ€: không thể Ä‘á»c %s" +msgstr "'%s': không thể Ä‘á»c %s" #, c-format msgid "'%s': short read" -msgstr "“%sâ€: Ä‘á»c ngắn" +msgstr "'%s': Ä‘á»c ngắn" msgid "start a working area (see also: git help tutorial)" msgstr "bắt đầu má»™t vùng là m việc (xem thêm: git help tutorial)" @@ -16094,9 +16683,15 @@ msgstr "Lệnh/Äồng bá»™ kho ở mức thấp" msgid "Low-level Commands / Internal Helpers" msgstr "Lệnh/Há»— trợ ná»™i tại ở mức thấp" +msgid "User-facing repository, command and file interfaces" +msgstr "Các giao diện kho, lệnh và táºp tin hÆ°á»›ng ngÆ°á»i dùng" + +msgid "Developer-facing file formats, protocols and other interfaces" +msgstr "Các giao diện táºp tin, giao thức và khác cho láºp trình viên" + #, c-format msgid "available git commands in '%s'" -msgstr "các lệnh git sẵn có trong thÆ° mục “%sâ€:" +msgstr "các lệnh git sẵn có trong thÆ° mục '%s':" msgid "git commands available from elsewhere on your $PATH" msgstr "các lệnh git sẵn có từ má»™t nÆ¡i khác trong $PATH của bạn" @@ -16107,6 +16702,12 @@ msgstr "Có các lệnh Git chung được sá» dụng trong các tình huống msgid "The Git concept guides are:" msgstr "Các chỉ dẫn khái niệm vá» Git là :" +msgid "User-facing repository, command and file interfaces:" +msgstr "Các giao diện kho, lệnh và táºp tin hÆ°á»›ng ngÆ°á»i dùng" + +msgid "File formats, protocols and other developer interfaces:" +msgstr "Các giao diện táºp tin, giao thức và khác cho láºp trình viên" + msgid "External commands" msgstr "Các lệnh bên ngoà i" @@ -16114,38 +16715,38 @@ msgid "Command aliases" msgstr "Các bà danh lệnh" msgid "See 'git help <command>' to read about a specific subcommand" -msgstr "Xem “git help <lệnh>†để Ä‘á»c các đặc tả của lệnh con" +msgstr "Xem 'git help <lệnh>' để Ä‘á»c các đặc tả của lệnh con" #, c-format msgid "" "'%s' appears to be a git command, but we were not\n" "able to execute it. Maybe git-%s is broken?" msgstr "" -"“%s†trông nhÆ° là má»™t lệnh git, nhÆ°ng chúng tôi không\n" +"'%s' trông nhÆ° là má»™t lệnh git, nhÆ°ng chúng tôi không\n" "thể thá»±c thi nó. Có lẽ là lệnh git-%s đã bị há»ng?" #, c-format msgid "git: '%s' is not a git command. See 'git --help'." -msgstr "git: “%s†không phải là má»™t lệnh của git. Xem “git --helpâ€." +msgstr "git: '%s' không phải là má»™t lệnh của git. Xem 'git --help'." msgid "Uh oh. Your system reports no Git commands at all." msgstr "á»i chà . Hệ thống của bạn báo rằng chẳng có lệnh Git nà o cả." #, c-format msgid "WARNING: You called a Git command named '%s', which does not exist." -msgstr "CẢNH BÃO: Bạn đã gá»i lệnh Git có tên “%sâ€, mà nó lại không có sẵn." +msgstr "CẢNH BÃO: Bạn đã gá»i lệnh Git có tên '%s', mà nó lại không có sẵn." #, c-format msgid "Continuing under the assumption that you meant '%s'." -msgstr "Tiếp tục và coi rằng ý bạn là “%sâ€." +msgstr "Tiếp tục và coi rằng ý bạn là '%s'." #, c-format msgid "Run '%s' instead [y/N]? " -msgstr "Chạy “%s†để thay thế? (y/N)? " +msgstr "Chạy '%s' để thay thế? (y/N)? " #, c-format msgid "Continuing in %0.1f seconds, assuming that you meant '%s'." -msgstr "Tiếp tục trong %0.1f giây,và coi rằng ý bạn là “%sâ€." +msgstr "Tiếp tục trong %0.1f giây,và coi rằng ý bạn là '%s'." msgid "" "\n" @@ -16157,8 +16758,8 @@ msgstr[0] "" "\n" "Những lệnh giống nhất là " -msgid "git version [<options>]" -msgstr "git version [<các tùy chá»n>]" +msgid "git version [--build-options]" +msgstr "git version [--build-options]" #, c-format msgid "%s: %s - %s" @@ -16179,16 +16780,12 @@ 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" -"Bạn có thể tắt cảnh báo nà y bằng “git config advice.ignoredHook false“." - -#, c-format -msgid "Couldn't start hook '%s'\n" -msgstr "Không thể khởi chạy móc “%sâ€\n" +"Móc '%s' bị bá» qua bởi vì nó không thể đặt là thá»±c thi được.\n" +"Bạn có thể tắt cảnh báo nà y bằng 'git config advice.ignoredHook false'." #, 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ệ (nháºn được “%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" @@ -16209,18 +16806,18 @@ msgstr "CURLSSLOPT_NO_REVOKE không được há»— trợ vá»›i cURL < 7.44.0" #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "" -"Không há»— trợ ứng dụng SSL chạy phÃa sau “%sâ€. Há»— trợ ứng dụng SSL chạy phÃa " +"Không há»— trợ ứng dụng SSL chạy phÃa sau '%s'. Há»— trợ ứng dụng SSL chạy phÃa " "sau:" #, c-format msgid "Could not set SSL backend to '%s': cURL was built without SSL backends" msgstr "" -"Không thể đặt ứng dụng chạy SSL phÃa sau “%sâ€: cURL được biên dịch không có " +"Không thể đặt ứng dụng chạy SSL phÃa sau '%s': cURL được biên dịch không có " "sá»± há»— trợ ứng dụng chạy phÃa sau SSL" #, c-format 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" +msgstr "Không thể đặt ứng dụng chạy sau SSL cho '%s': đã đặt rồi" #, c-format msgid "" @@ -16268,14 +16865,14 @@ msgstr "không Ä‘Æ°a ra địa chỉ thÆ° Ä‘iện tá» và auto-detection bị t #, c-format msgid "unable to auto-detect email address (got '%s')" -msgstr "không thể tá»± dò tìm địa chỉ thÆ° Ä‘iện tá» (nháºn “%sâ€)" +msgstr "không thể tá»± dò tìm địa chỉ thÆ° Ä‘iện tá» (nháºn '%s')" msgid "no name was given and auto-detection is disabled" msgstr "chÆ°a chỉ ra tên và tá»±-Ä‘á»™ng-dò-tìm bị tắt" #, c-format msgid "unable to auto-detect name (got '%s')" -msgstr "không thể dò-tìm-tá»± Ä‘á»™ng tên (đã nháºn “%sâ€)" +msgstr "không thể dò-tìm-tá»± Ä‘á»™ng tên (đã nháºn '%s')" #, c-format msgid "empty ident name (for <%s>) not allowed" @@ -16286,22 +16883,22 @@ msgid "name consists only of disallowed characters: %s" msgstr "tên chỉ được phép bao gồm các ký tá»± sau: %s" msgid "expected 'tree:<depth>'" -msgstr "cần “tree:<depth>â€" +msgstr "cần 'tree:<depth>'" msgid "sparse:path filters support has been dropped" -msgstr "việc há»— trợ bá»™ lá»c sparse:Ä‘Æ°á»ng/dẫn đã bị bá»" +msgstr "há»— trợ bá»™ lá»c sparse:Ä‘Æ°á»ng/dẫn đã không còn" #, c-format msgid "'%s' for 'object:type=<type>' is not a valid object type" -msgstr "“%s†dà nh cho “object:type=<type>†không phải là kiểu đối tượng hợp lệ" +msgstr "'%s' dà nh cho 'object:type=<type>' không phải là kiểu đối tượng hợp lệ" #, c-format msgid "invalid filter-spec '%s'" -msgstr "đặc tả bá»™ lá»c không hợp lệ “%sâ€" +msgstr "đặc tả bá»™ lá»c không hợp lệ '%s'" #, c-format msgid "must escape char in sub-filter-spec: '%c'" -msgstr "phải thoát char trong sub-filter-spec: “%câ€" +msgstr "phải thoát char trong sub-filter-spec: '%c'" msgid "expected something after combine:" msgstr "mong đợi má»™t cái gì đó sau khi kết hợp:" @@ -16320,23 +16917,23 @@ msgstr "lá»c đối tượng" #, c-format msgid "unable to access sparse blob in '%s'" -msgstr "không thể truy cáºp các blob rải rác trong “%sâ€" +msgstr "không thể truy cáºp các blob rải rác trong '%s'" #, c-format msgid "unable to parse sparse filter data in %s" -msgstr "không thể phân tÃch dữ liệu bá»™ lá»c rải rác trong %s" +msgstr "không thể Ä‘á»c dữ liệu bá»™ lá»c rải rác trong %s" #, c-format msgid "entry '%s' in tree %s has tree mode, but is not a tree" -msgstr "mục “%s†trong cây %s có nút cây, nhÆ°ng không phải là má»™t cây" +msgstr "mục '%s' trong cây %s có nút cây, nhÆ°ng không phải là má»™t cây" #, c-format msgid "entry '%s' in tree %s has blob mode, but is not a blob" -msgstr "mục “%s†trong cây %s có nút blob, nhÆ°ng không phải là má»™t blob" +msgstr "mục '%s' trong cây %s có nút blob, nhÆ°ng không phải là má»™t blob" #, c-format msgid "unable to load root tree for commit %s" -msgstr "không thể tải cây gốc cho lần chuyển giao “%sâ€" +msgstr "không thể tải cây gốc cho lần chuyển giao '%s'" #, c-format msgid "" @@ -16348,21 +16945,29 @@ msgid "" "may have crashed in this repository earlier:\n" "remove the file manually to continue." msgstr "" -"Không thể tạo “%s.lockâ€: %s.\n" +"Không thể tạo '%s.lock': %s.\n" "\n" "Tiến trình git khác có lẽ Ä‘ang chạy ở kho nà y, và dụ\n" -"má»™t trình soạn thảo được mở bởi “git commitâ€. Vui lòng chắc chắn\n" -"rằng má»i tiến trình đã chấm dứt và sau đó thá» lại. Nếu vẫn lá»—i,\n" -"má»™t tiến trình git có lẽ đã đổ vỡ khi thá»±c hiện ở kho nà y trÆ°á»›c đó:\n" +"má»™t trình soạn thảo được mở bởi 'git commit'. Vui lòng chắc chắn\n" +"rằng má»i tiến trình đã kết thúc và sau đó thá» lại. Nếu vẫn lá»—i,\n" +"má»™t tiến trình git có lẽ đã crash khi thá»±c hiện ở kho nà y trÆ°á»›c đó:\n" "gõ bá» táºp tin má»™t cách thủ công để tiếp tục." #, c-format msgid "Unable to create '%s.lock': %s" -msgstr "Không thể tạo “%s.lockâ€: %s" +msgstr "Không thể tạo '%s.lock': %s" + +#, 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" #, c-format msgid "unexpected line: '%s'" -msgstr "dòng không cần: “%sâ€" +msgstr "dòng bất thÆ°á»ng: '%s'" msgid "expected flush after ls-refs arguments" msgstr "cần đẩy dữ liệu lên Ä‘Ä©a sau tham số ls-refs (liệt kê tham chiếu)" @@ -16371,73 +16976,57 @@ msgid "quoted CRLF detected" msgstr "phát hiện CRLF được trÃch dẫn" #, c-format -msgid "" -"Your local changes to the following files would be overwritten by merge:\n" -" %s" -msgstr "" -"Các thay đổi ná»™i bá»™ của bạn vá»›i các táºp tin sau đây sẽ bị ghi đè bởi lệnh " -"hòa trá»™n:\n" -" %s" +msgid "unable to format message: %s" +msgstr "không thể định dạng thông Ä‘iệp: %s" #, c-format msgid "Failed to merge submodule %s (not checked out)" -msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%s†(không lấy ra được)" +msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (không checkout được)" + +#, c-format +msgid "Failed to merge submodule %s (no merge base)" +msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (không có gốc hoà trá»™n)" #, c-format 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)" +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)" #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" -"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%s†(lần chuyển giao không theo sau ná»n-hòa-" +"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (lần chuyển giao không theo sau gốc-hòa-" "trá»™n)" #, c-format msgid "Note: Fast-forwarding submodule %s to %s" -msgstr "Chú ý: Chuyển-tiếp-nhanh mô-Ä‘un-con “%s†sang “%sâ€" +msgstr "Chú ý: Chuyển-tiếp-nhanh mô-Ä‘un-con %s sang %s" #, c-format msgid "Failed to merge submodule %s" -msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%sâ€" +msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s" #, c-format msgid "" -"Failed to merge submodule %s, but a possible merge resolution exists:\n" -"%s\n" -msgstr "" -"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%sâ€, nhÆ°ng có cách giải quyết:\n" -"%s\n" - -#, c-format -msgid "" -"If this is correct simply add it to the index for example\n" -"by using:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"which will accept this suggestion.\n" -msgstr "" -"Nếu đây là đúng Ä‘Æ¡n giản thêm nó và o mục lục và dụ\n" -"bằng cách dùng:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"cái mà sẽ chấp nháºn gợi ý nà y.\n" +"Failed to merge submodule %s, but a possible merge resolution exists: %s" +msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s, nhÆ°ng có cách giải quyết: %s" #, c-format msgid "" "Failed to merge submodule %s, but multiple possible merges exist:\n" "%s" 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" +"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" +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" +msgid "unable to add %s to database" msgstr "Không thể thêm %s và o cÆ¡ sở dữ liệu" #, c-format @@ -16449,16 +17038,16 @@ msgid "" "CONFLICT (implicit dir rename): Existing file/dir at %s in the way of " "implicit directory rename(s) putting the following path(s) there: %s." msgstr "" -"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Táºp tin/thÆ° mục đã sẵn có tại %s theo cách " -"của các đổi tên thÆ° mục ngầm đặt (các) Ä‘Æ°á»ng dẫn sau ở đây: %s." +"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Táºp tin/thÆ° mục đã sẵn có tại %s do việc " +"đổi tên thÆ° mục sẽ đặt các Ä‘Æ°á»ng dẫn sau ở đó: %s." #, c-format msgid "" "CONFLICT (implicit dir rename): Cannot map more than one path to %s; " "implicit directory renames tried to put these paths there: %s" msgstr "" -"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Không thể ánh xạ má»™t Ä‘Æ°á»ng dẫn thà nh %s; " -"các đổi tên thÆ° mục ngầm cố đặt các Ä‘Æ°á»ng dẫn ở đây: %s" +"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Không thể ánh xạ hÆ¡n má»™t Ä‘Æ°á»ng dẫn thà nh " +"%s; việc đổi tên thÆ° mục sẽ đặt các Ä‘Æ°á»ng dẫn sau ở đó: %s" #, c-format msgid "" @@ -16466,17 +17055,17 @@ msgid "" "renamed to multiple other directories, with no destination getting a " "majority of the files." msgstr "" -"XUNG ÄỘT: (thÆ° mục đổi tên chia tách): Không rõ rà ng nÆ¡i để đổi tên %s " -"thà nh; nó đã bị đổi tên thà nh nhiá»u thÆ° mục khác, vá»›i không Ä‘Ãch đến nháºn " -"má»™t phần nhiá»u của các táºp tin." +"XUNG ÄỘT: (phân hoá đổi tên thÆ° mục): Không rõ đổi tên %s vỠđâu; nó đã bị " +"đổi tên thà nh nhiá»u thÆ° mục khác, mà không bên nà o nháºn phần lá»›n các táºp tin " +"gốc." #, c-format msgid "" "WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was " "renamed." msgstr "" -"CẢNH BÃO: tránh áp dụng %s -> %s đổi thên thà nh %s, bởi vì bản thân %s cÅ©ng " -"bị đổi tên." +"CẢNH BÃO: Tránh áp dụng đổi tên %s -> %s cho %s, bởi vì bản thân %s đã bị " +"đổi tên." #, c-format msgid "" @@ -16484,7 +17073,7 @@ msgid "" "moving it to %s." msgstr "" "ÄÆ°á»ng dẫn đã được cáºp nháºt: %s được thêm và o trong %s bên trong má»™t thÆ° mục " -"đã được đổi tên trong %s; di chuyển nó đến %s." +"đã được đổi tên trong %s; sẽ di chuyển nó đến %s." #, c-format msgid "" @@ -16492,14 +17081,14 @@ msgid "" "%s; moving it to %s." msgstr "" "ÄÆ°á»ng dẫn đã được cáºp nháºt: %s được đổi tên thà nh %s trong %s, bên trong má»™t " -"thÆ° mục đã được đổi tên trong %s; di chuyển nó đến %s." +"thÆ° mục đã được đổi tên trong %s; sẽ di chuyển nó đến %s." #, c-format msgid "" "CONFLICT (file location): %s added in %s inside a directory that was renamed " "in %s, suggesting it should perhaps be moved to %s." msgstr "" -"XUNG ÄỘT (vị trà tệp): %s được thêm và o trong %s trong má»™t thÆ° mục đã được " +"XUNG ÄỘT (vị trà táºp): %s được thêm và o trong %s trong má»™t thÆ° mục đã được " "đổi tên thà nh %s, Ä‘oán là nó nên được di chuyển đến %s." #, c-format @@ -16507,7 +17096,7 @@ msgid "" "CONFLICT (file location): %s renamed to %s in %s, inside a directory that " "was renamed in %s, suggesting it should perhaps be moved to %s." msgstr "" -"XUNG ÄỘT (vị trà tệp): %s được đổi tên thà nh %s trong %s, bên trong má»™t thÆ° " +"XUNG ÄỘT (vị trà táºp): %s được đổi tên thà nh %s trong %s, bên trong má»™t thÆ° " "mục đã được đổi tên thà nh %s, Ä‘oán là nó nên được di chuyển đến %s." #, c-format @@ -16583,13 +17172,43 @@ msgstr "" "XUNG ÄỘT (sá»a/xóa): %s bị xóa trong %s và sá»a trong %s. Phiên bản %s của %s " "còn lại trong cây (tree)." +#. TRANSLATORS: This is a line of advice to resolve a merge +#. 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" +#. +#, c-format +msgid "" +" - go to submodule (%s), and either merge commit %s\n" +" or update to an existing commit which has merged those changes\n" +msgstr "" +" - Ä‘i tá»›i mô-Ä‘un con (%s), và hoà trá»™n lần chuyển giao %s\n" +" hoặc cáºp nháºt tá»›i má»™t lần chuyển giao đã có hoà trá»™n các thay đổi\n" + #, c-format msgid "" -"Note: %s not up to date and in way of checking out conflicted version; old " -"copy renamed to %s" +"Recursive merging with submodules currently only supports trivial cases.\n" +"Please manually handle the merging of each conflicted submodule.\n" +"This can be accomplished with the following steps:\n" +"%s - come back to superproject and run:\n" +"\n" +" git add %s\n" +"\n" +" to record the above merge or update\n" +" - resolve any other conflicts in the superproject\n" +" - commit the resulting index in the superproject\n" msgstr "" -"LÆ°u ý: %s không được cáºp nháºt và theo cách lấy ra phiên bản xung Ä‘á»™t; bản " -"sao cÅ© được đổi tên thà nh %s" +"Hoà trá»™n đệ quy vá»›i mô-Ä‘un con hiện chỉ há»— trợ các trÆ°á»ng hợp Ä‘Æ¡n giản.\n" +"Vui lòng hoà trá»™n các mô-Ä‘un con có xung Ä‘á»™t bằng tay.\n" +"Bạn có thể thá»±c hiện theo các bÆ°á»›c sau:\n" +"%s - trở vá» project cha và chạy lệnh:\n" +"\n" +" git add %s\n" +"\n" +" để ghi lại hoà trá»™n hoặc cáºp nháºt\n" +" - giải quyết các xung Ä‘á»™t trong project cha\n" +" - chuyển giao kết quả trong project cha\n" #. TRANSLATORS: The %s arguments are: 1) tree hash of a merge #. base, and 2-3) the trees for the two trees we're merging. @@ -16603,74 +17222,90 @@ msgstr "(commit sai)\n" #, c-format msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "add_cacheinfo gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn “%sâ€; việc hòa trá»™n bị bãi bá»." +msgstr "add_cacheinfo gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn '%s'; huá»· bá» việc hòa trá»™n." #, c-format msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." msgstr "" -"add_cacheinfo gặp lá»—i khi là m má»›i đối vá»›i Ä‘Æ°á»ng dẫn “%sâ€; việc hòa trá»™n bị " -"bãi bá»." +"add_cacheinfo gặp lá»—i khi là m má»›i đối vá»›i Ä‘Æ°á»ng dẫn '%s'; huá»· bá» việc hòa " +"trá»™n." #, c-format msgid "failed to create path '%s'%s" -msgstr "gặp lá»—i khi tạo Ä‘Æ°á»ng dẫn “%sâ€%s" +msgstr "gặp lá»—i khi tạo Ä‘Æ°á»ng dẫn '%s'%s" #, c-format msgid "Removing %s to make room for subdirectory\n" msgstr "Gỡ bá» %s để tạo chá»— (room) cho thÆ° mục con\n" msgid ": perhaps a D/F conflict?" -msgstr ": có lẽ là má»™t xung Ä‘á»™t D/F?" +msgstr ": có lẽ là xung Ä‘á»™t D/F (táºp tin/thÆ° mục)?" #, c-format msgid "refusing to lose untracked file at '%s'" -msgstr "từ chối đóng táºp tin không được theo dõi tại “%sâ€" +msgstr "từ chối đóng táºp tin không được theo dõi tại '%s'" #, c-format msgid "blob expected for %s '%s'" -msgstr "mong đợi đối tượng blob cho %s “%sâ€" +msgstr "mong đợi đối tượng blob cho %s '%s'" #, c-format msgid "failed to open '%s': %s" -msgstr "gặp lá»—i khi mở “%sâ€: %s" +msgstr "gặp lá»—i khi mở '%s': %s" #, c-format msgid "failed to symlink '%s': %s" -msgstr "gặp lá»—i khi tạo liên kết má»m (symlink) “%sâ€: %s" +msgstr "gặp lá»—i khi tạo liên kết má»m (symlink) '%s': %s" #, c-format 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â€" +msgstr "không hiểu phải là m gì vá»›i %06o %s '%s'" #, 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:" +msgstr "Chuyển-tiếp-nhanh mô-Ä‘un-con '%s' đến lần chuyển giao sau đây:" #, c-format msgid "Fast-forwarding submodule %s" -msgstr "Chuyển-tiếp-nhanh mô-Ä‘un-con “%sâ€" +msgstr "Chuyển-tiếp-nhanh mô-Ä‘un-con '%s'" #, c-format msgid "Failed to merge submodule %s (merge following commits not found)" msgstr "" -"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%s†(không tìm thấy các lần chuyển giao " +"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con '%s' (không tìm thấy các lần chuyển giao " "theo sau hòa trá»™n)" #, c-format msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%s†(không chuyển tiếp nhanh được)" +msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con '%s' (không chuyển tiếp nhanh được)" msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Tìm thấy má»™t giải pháp hòa trá»™n có thể cho mô-Ä‘un-con:\n" +msgstr "Tìm thấy má»™t giải pháp hòa trá»™n khả thi cho mô-Ä‘un-con:\n" + +#, c-format +msgid "" +"If this is correct simply add it to the index for example\n" +"by using:\n" +"\n" +" git update-index --cacheinfo 160000 %s \"%s\"\n" +"\n" +"which will accept this suggestion.\n" +msgstr "" +"Nếu đây là đúng Ä‘Æ¡n giản thêm nó và o chỉ mục và dụ\n" +"bằng cách dùng:\n" +"\n" +" git update-index --cacheinfo 160000 %s \"%s\"\n" +"\n" +"cái mà sẽ chấp nháºn gợi ý nà y.\n" #, c-format 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)" +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)" #, c-format msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." msgstr "" -"Lá»—i: từ chối đóng táºp tin không được theo dõi tại “%sâ€; thay và o đó ghi và o " +"Lá»—i: từ chối đóng táºp tin không được theo dõi tại '%s'; thay và o đó ghi và o " "%s." #, c-format @@ -16713,12 +17348,12 @@ msgstr "đã đổi tên" #, c-format msgid "Refusing to lose dirty file at %s" -msgstr "Từ chối đóng táºp tin không được theo dõi tại “%sâ€" +msgstr "Từ chối đóng táºp tin không được theo dõi tại '%s'" #, c-format msgid "Refusing to lose untracked file at %s, even though it's in the way." msgstr "" -"Từ chối đóng táºp tin không được theo dõi tại “%sâ€, ngay cả khi nó ở trên " +"Từ chối đóng táºp tin không được theo dõi tại '%s', ngay cả khi nó ở trên " "Ä‘Æ°á»ng." #, c-format @@ -16733,13 +17368,13 @@ msgstr "%s là má»™t thÆ° mục trong %s thay và o đó thêm và o nhÆ° là %s" #, c-format msgid "Refusing to lose untracked file at %s; adding as %s instead" msgstr "" -"Từ chối đóng táºp tin không được theo dõi tại “%sâ€; thay và o đó Ä‘ang thêm " +"Từ chối đóng táºp tin không được theo dõi tại '%s'; thay và o đó Ä‘ang thêm " "thà nh %s" #, c-format msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s" -"\"->\"%s\" in \"%s\"%s" +"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " +"\"%s\"->\"%s\" in \"%s\"%s" msgstr "" "XUNG ÄỘT (đổi-tên/đổi-tên): Äổi tên \"%s\"->\"%s\" trong nhánh \"%s\" đổi " "tên \"%s\"->\"%s\" trong \"%s\"%s" @@ -16758,9 +17393,9 @@ msgid "" "directory %s was renamed to multiple other directories, with no destination " "getting a majority of the files." msgstr "" -"XUNG ÄỘT: (thÆ° mục đổi tên chia tách): Không rõ rà ng để đặt địa Ä‘iểm %s bởi " -"vì thÆ° mục %s đã bị đổi tên thà nh nhiá»u thÆ° mục khác, vá»›i không Ä‘Ãch đến " -"nháºn má»™t phần nhiá»u của các táºp tin." +"XUNG ÄỘT: (phân hoá đổi tên thÆ° mục): Không rõ đặt %s ở đâu bởi vì thÆ° mục " +"%s đã bị đổi tên thà nh nhiá»u thÆ° mục khác, mà không bên nà o nháºn phần lá»›n " +"các táºp tin gốc." #, c-format msgid "" @@ -16825,75 +17460,33 @@ msgstr "hòa trá»™n không trả vá» lần chuyển giao nà o" #, c-format msgid "Could not parse object '%s'" -msgstr "Không thể phân tÃch đối tượng “%sâ€" +msgstr "Không thể Ä‘á»c đối tượng '%s'" msgid "failed to read the cache" msgstr "gặp lá»—i khi Ä‘á»c bá»™ nhá»› đệm" -msgid "multi-pack-index OID fanout is of the wrong size" -msgstr "fanout OID nhiá»u gói chỉ mục có kÃch thÆ°á»›c sai" - -#, c-format -msgid "multi-pack-index file %s is too small" -msgstr "táºp tin đồ thị multi-pack-index %s quá nhá»" - -#, c-format -msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x" -msgstr "chữ ký multi-pack-index 0x%08x không khá»›p chữ ký 0x%08x" - -#, c-format -msgid "multi-pack-index version %d not recognized" -msgstr "không nháºn ra phiên bản %d của multi-pack-index" - -#, c-format -msgid "multi-pack-index hash version %u does not match version %u" -msgstr "phiên bản băm multi-pack-index %u không khá»›p phiên bản %u" - -msgid "multi-pack-index missing required pack-name chunk" -msgstr "multi-pack-index thiếu mảnh pack-name cần thiết" - -msgid "multi-pack-index missing required OID fanout chunk" -msgstr "multi-pack-index thiếu mảnh OID fanout cần thiết" - -msgid "multi-pack-index missing required OID lookup chunk" -msgstr "multi-pack-index thiếu mảnh OID lookup cần thiết" - -msgid "multi-pack-index missing required object offsets chunk" -msgstr "multi-pack-index thiếu mảnh các khoảng bù đối tượng cần thiết" - -#, c-format -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â€" - -#, c-format -msgid "bad pack-int-id: %u (%u total packs)" -msgstr "pack-int-id sai: %u (%u các gói tổng)" - -msgid "multi-pack-index stores a 64-bit offset, but off_t is too small" -msgstr "multi-pack-index lÆ°u trữ má»™t khoảng bù 64-bÃt, nhÆ°ng off_t là quá nhá»" - #, 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 táºp tin gói '%s'" #, c-format msgid "failed to open pack-index '%s'" -msgstr "gặp lá»—i khi mở pack-index “%sâ€" +msgstr "gặp lá»—i khi mở pack-index '%s'" #, c-format msgid "failed to locate object %d in packfile" -msgstr "gặp lá»—i khi phân bổ đối tượng “%d†trong táºp tin gói" +msgstr "gặp lá»—i khi phân bổ đối tượng '%d' trong táºp tin gói" msgid "cannot store reverse index file" -msgstr "không thể lÆ°u trữ táºp tin ghi mục lục đảo ngược" +msgstr "không thể lÆ°u trữ táºp tin ghi chỉ mục đảo ngược" #, c-format msgid "could not parse line: %s" -msgstr "không thể phân tÃch cú pháp dòng: %s" +msgstr "không hiểu cú pháp dòng: %s" #, c-format msgid "malformed line: %s" -msgstr "dòng dị hình: %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" @@ -16903,7 +17496,7 @@ msgstr "không thể tải gói" #, c-format msgid "could not open index for %s" -msgstr "không thể mở mục lục cho %s" +msgstr "không thể mở chỉ mục cho %s" msgid "Adding packfiles to multi-pack-index" msgstr "Äang thêm táºp tin gói từ multi-pack-index" @@ -16918,30 +17511,109 @@ msgstr "không thể chá»n gói Æ°a dùng %s vá»›i không đối tượng nà o" #, c-format msgid "did not see pack-file %s to drop" -msgstr "đã không thấy táºp tin gói %s để mà xóa" +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 mục lục." +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 "could not write multi-pack bitmap" -msgstr "không thể ghi “multi-pack bitmapâ€" +msgstr "không thể ghi 'multi-pack bitmap'" msgid "could not write multi-pack-index" -msgstr "không thể ghi “multi-pack-indexâ€" +msgstr "không thể ghi 'multi-pack-index'" + +msgid "Counting referenced objects" +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 "could not start pack-objects" +msgstr "không thể khởi chạy pack-objects" + +msgid "could not finish pack-objects" +msgstr "không thể hoà n thiện pack-objects" + +msgid "multi-pack-index OID fanout is of the wrong size" +msgstr "fanout OID multi-pack-index có kÃch thÆ°á»›c sai" + +#, c-format +msgid "" +"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]" +msgstr "fanout cÅ© sai thứ tá»±: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]" + +msgid "multi-pack-index OID lookup chunk is the wrong size" +msgstr "OID lookup chunk multi-pack-index có kÃch thÆ°á»›c sai" + +msgid "multi-pack-index object offset chunk is the wrong size" +msgstr "object offset chunk multi-pack-index có kÃch thÆ°á»›c sai" + +#, c-format +msgid "multi-pack-index file %s is too small" +msgstr "táºp tin đồ thị multi-pack-index %s quá nhá»" + +#, c-format +msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x" +msgstr "chữ ký multi-pack-index 0x%08x không khá»›p chữ ký 0x%08x" + +#, c-format +msgid "multi-pack-index version %d not recognized" +msgstr "không nháºn ra phiên bản %d của multi-pack-index" + +#, c-format +msgid "multi-pack-index hash version %u does not match version %u" +msgstr "phiên bản băm multi-pack-index %u không khá»›p phiên bản %u" + +msgid "multi-pack-index required pack-name chunk missing or corrupted" +msgstr "multi-pack-index thiếu chunk pack-name cần thiết hoặc bị há»ng" + +msgid "multi-pack-index required OID fanout chunk missing or corrupted" +msgstr "multi-pack-index thiếu chunk OID fanout cần thiết hoặc bị há»ng" + +msgid "multi-pack-index required OID lookup chunk missing or corrupted" +msgstr "multi-pack-index thiếu chunk OID lookup cần thiết hoặc bị há»ng" + +msgid "multi-pack-index required object offsets chunk missing or corrupted" +msgstr "" +"multi-pack-index thiếu chunk các khoảng bù đối tượng cần thiết hoặc bị há»ng" + +msgid "multi-pack-index pack-name chunk is too short" +msgstr "táºp tin đồ thị multi-pack-index %s quá nhá»" + +#, c-format +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'" + +#, c-format +msgid "bad pack-int-id: %u (%u total packs)" +msgstr "pack-int-id sai: %u (%u các gói tổng)" + +msgid "MIDX does not contain the BTMP chunk" +msgstr "MIDX không chứa chunk BTMP" + +#, c-format +msgid "could not load bitmapped pack %<PRIu32>" +msgstr "không thể Ä‘á»c gói bitmap %<PRIu32>" + +msgid "multi-pack-index stores a 64-bit offset, but off_t is too small" +msgstr "multi-pack-index lÆ°u trữ má»™t offset 64-bÃt, nhÆ°ng off_t là quá nhá»" + +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 phân tÃch cú pháp" +msgstr "đã có táºp tin multi-pack-index, nhÆ°ng gặp lá»—i khi Ä‘á»c cú pháp" msgid "incorrect checksum" msgstr "tổng kiểm không đúng" @@ -16949,11 +17621,6 @@ msgstr "tổng kiểm không đúng" msgid "Looking for referenced packfiles" msgstr "Äang khóa cho các gói bị tham chiếu" -#, c-format -msgid "" -"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]" -msgstr "fanout cÅ© sai thứ tá»±: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]" - msgid "the midx contains no oid" msgstr "midx chẳng chứa oid nà o" @@ -16983,18 +17650,6 @@ msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "" "khoảng bù đối tượng không đúng cho oid[%d] = %s: %<PRIx64> != %<PRIx64>" -msgid "Counting referenced objects" -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 "could not start pack-objects" -msgstr "không thể lấy thông tin thống kê vá» các đối tượng gói" - -msgid "could not finish pack-objects" -msgstr "không thể hoà n thiện các đối tượng gói" - #, c-format msgid "unable to create lazy_dir thread: %s" msgstr "không thể tạo tuyến lazy_dir: %s" @@ -17013,10 +17668,9 @@ msgid "" "Please, use 'git notes merge --commit' or 'git notes merge --abort' to " "commit/abort the previous merge before you start a new notes merge." msgstr "" -"Bạn đã chÆ°a hoà n tất hòa trá»™n ghi chú trÆ°á»›c đây (%s vẫn còn).\n" -"Vui lòng dùng “git notes merge --commit†hay “git notes merge --abort†để " -"chuyển giao hay bãi bá» lần hòa trá»™n trÆ°á»›c đây và bắt đầu má»™t hòa trá»™n ghi " -"chú má»›i." +"Bạn chÆ°a hoà n tất lần hòa trá»™n ghi chú trÆ°á»›c (%s vẫn còn).\n" +"Vui lòng dùng 'git notes merge --commit' hay 'git notes merge --abort' để " +"chuyển giao hay huá»· bá» lần hòa trá»™n trÆ°á»›c và bắt đầu hòa trá»™n ghi chú má»›i." #, c-format msgid "You have not concluded your notes merge (%s exists)." @@ -17029,7 +17683,7 @@ msgstr "" #, c-format msgid "Bad notes.rewriteMode value: '%s'" -msgstr "Giá trị notes.rewriteMode sai: “%sâ€" +msgstr "Giá trị notes.rewriteMode sai: '%s'" #, c-format msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" @@ -17041,7 +17695,26 @@ msgstr "Từ chối ghi đè ghi chú trong %s (nằm ngoà i refs/notes/)" #. #, c-format msgid "Bad %s value: '%s'" -msgstr "Giá trị %s sai: “%sâ€" +msgstr "Giá trị %s sai: '%s'" + +msgid "failed to decode tree entry" +msgstr "giải mã mục cây thất bại" + +#, c-format +msgid "failed to map tree entry for %s" +msgstr "ánh xạ mục cây cho %s thất bại" + +#, c-format +msgid "bad %s in commit" +msgstr "ký tá»± không đúng %s trong lần chuyển giao" + +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "không thể ánh xạ %s %s trong đối tượng chuyển giao" + +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Chuyển đổi đối tượng từ %s sang %s thất bại" #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" @@ -17050,16 +17723,12 @@ msgstr "" #, c-format msgid "unable to normalize alternate object path: %s" -msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn đối tượng thay thế: “%sâ€" +msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn đối tượng thay thế: '%s'" #, c-format msgid "%s: ignoring alternate object stores, nesting too deep" msgstr "%s: Ä‘ang bá» qua kho đối tượng thay thế, lồng nhau quá sâu" -#, c-format -msgid "unable to normalize object directory: %s" -msgstr "không thể chuẩn hóa thÆ° mục đối tượng: “%sâ€" - msgid "unable to fdopen alternates lockfile" msgstr "không thể fdopen táºp tin khóa thay thế" @@ -17071,31 +17740,31 @@ msgstr "không thể di chuyển táºp tin thay thế và o chá»—" #, c-format msgid "path '%s' does not exist" -msgstr "Ä‘Æ°á»ng dẫn “%s†không tồn tại" +msgstr "Ä‘Æ°á»ng dẫn '%s' không tồn tại" #, c-format msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "kho tham chiếu “%s†nhÆ° là lấy ra liên kết vẫn chÆ°a được há»— trợ." +msgstr "kho tham chiếu '%s' nhÆ° là checkout liên kết vẫn chÆ°a được há»— trợ." #, c-format msgid "reference repository '%s' is not a local repository." -msgstr "kho tham chiếu “%s†không phải là má»™t kho ná»™i bá»™." +msgstr "kho tham chiếu '%s' không phải là má»™t kho ná»™i bá»™." #, c-format msgid "reference repository '%s' is shallow" -msgstr "kho tham chiếu “%s†là nông" +msgstr "kho tham chiếu '%s' là nông" #, c-format msgid "reference repository '%s' is grafted" -msgstr "kho tham chiếu “%s†bị cấy ghép" +msgstr "kho tham chiếu '%s' bị cấy ghép" #, c-format msgid "could not find object directory matching %s" -msgstr "không thể tìm thấy thÆ° mục đối tượng khá»›p vá»›i “%sâ€" +msgstr "không thể tìm thấy thÆ° mục đối tượng khá»›p vá»›i '%s'" #, c-format msgid "invalid line while parsing alternate refs: %s" -msgstr "dòng không hợp lệ trong khi phân tÃch các tham chiếu thay thế: %s" +msgstr "dòng không hợp lệ trong khi Ä‘á»c các tham chiếu thay thế: %s" #, c-format msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" @@ -17111,15 +17780,19 @@ msgstr "táºp tin đối tượng %s trống rá»—ng" #, c-format msgid "corrupt loose object '%s'" -msgstr "đối tượng mất há»ng “%sâ€" +msgstr "đối tượng mất há»ng '%s'" #, c-format msgid "garbage at end of loose object '%s'" -msgstr "gặp rác tại cuối của đối tượng bị mất “%sâ€" +msgstr "gặp rác tại cuối của đối tượng bị mất '%s'" + +#, c-format +msgid "unable to open loose object %s" +msgstr "không thể mở đối tượng mất %s" #, c-format msgid "unable to parse %s header" -msgstr "không thể phân tÃch phần đầu của “%sâ€" +msgstr "không thể Ä‘á»c phần đầu của '%s'" msgid "invalid object type" msgstr "kiểu đối tượng không hợp lệ" @@ -17133,31 +17806,28 @@ msgid "header for %s too long, exceeds %d bytes" msgstr "phần đầu cho %s quá dà i, vượt quá %d byte" #, c-format -msgid "failed to read object %s" -msgstr "gặp lá»—i khi Ä‘á»c đối tượng “%sâ€" +msgid "loose object %s (stored in %s) is corrupt" +msgstr "đối tượng mất %s (được lÆ°u trong %s) bị há»ng" #, c-format msgid "replacement %s not found for %s" msgstr "c%s thay thế không được tìm thấy cho %s" #, c-format -msgid "loose object %s (stored in %s) is corrupt" -msgstr "đối tượng mất %s (được lÆ°u trong %s) bị há»ng" - -#, c-format msgid "packed object %s (stored in %s) is corrupt" msgstr "đối tượng đã đóng gói %s (được lÆ°u trong %s) bị há»ng" #, c-format +msgid "missing mapping of %s to %s" +msgstr "thiếu ánh xạ %s sang %s" + +#, c-format msgid "unable to write file %s" msgstr "không thể ghi táºp tin %s" #, c-format msgid "unable to set permission to '%s'" -msgstr "không thể đặt quyá»n thà nh “%sâ€" - -msgid "file write error" -msgstr "lá»—i ghi táºp tin" +msgstr "không thể đặt quyá»n thà nh '%s'" msgid "error when closing loose object file" msgstr "gặp lá»—i trong khi đóng táºp tin đối tượng" @@ -17175,7 +17845,7 @@ msgstr "không thể ghi táºp tin đối tượng đã mất" #, c-format msgid "unable to deflate new object %s (%d)" -msgstr "không thể xả nén đối tượng má»›i %s (%d)" +msgstr "không thể giải nén đối tượng má»›i %s (%d)" #, c-format msgid "deflateEnd on object %s failed (%d)" @@ -17186,22 +17856,43 @@ msgid "confused by unstable object source data for %s" msgstr "chÆ°a rõ rà ng baowir dữ liệu nguồn đối tượng không ổn định cho %s" #, c-format +msgid "write stream object %ld != %<PRIuMAX>" +msgstr "đối tượng ghi dòng %ld != %<PRIuMAX>" + +#, c-format +msgid "unable to stream deflate new object (%d)" +msgstr "không thể stream deflate đối tượng má»›i (%d)" + +#, c-format +msgid "deflateEnd on stream object failed (%d)" +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" + +#, c-format msgid "cannot read object for %s" msgstr "không thể Ä‘á»c đối tượng cho %s" -msgid "corrupt commit" -msgstr "lần chuyển giao sai há»ng" +#, c-format +msgid "cannot map object %s to %s" +msgstr "không thể ánh xạ đối tượng %s sang %s" + +#, c-format +msgid "object fails fsck: %s" +msgstr "đối tượng không qua fsck (kiểm tra toà n vẹn): %s" -msgid "corrupt tag" -msgstr "thẻ sai há»ng" +msgid "refusing to create malformed object" +msgstr "Từ chối tạo đối tượng lá»—i" #, c-format msgid "read error while indexing %s" -msgstr "gặp lá»—i Ä‘á»c khi đánh mục lục %s" +msgstr "gặp lá»—i Ä‘á»c khi đánh chỉ mục %s" #, c-format msgid "short read while indexing %s" -msgstr "không Ä‘á»c ngắn khi đánh mục lục %s" +msgstr "không Ä‘á»c ngắn khi đánh chỉ mục %s" #, c-format msgid "%s: failed to insert into database" @@ -17213,7 +17904,7 @@ msgstr "%s: kiểu táºp tin không được há»— trợ" #, c-format msgid "%s is not a valid '%s' object" -msgstr "%s không phải là má»™t đối tượng “%s†hợp lệ" +msgstr "%s không phải là má»™t đối tượng '%s' hợp lệ" #, c-format msgid "unable to open %s" @@ -17229,15 +17920,15 @@ msgstr "không thể mmap %s" #, c-format msgid "unable to unpack header of %s" -msgstr "không thể giải gói phần đầu của “%sâ€" +msgstr "không thể giải gói phần đầu của '%s'" #, c-format msgid "unable to parse header of %s" -msgstr "không thể phân tÃch phần đầu của “%sâ€" +msgstr "không thể Ä‘á»c phần đầu của '%s'" #, c-format msgid "unable to unpack contents of %s" -msgstr "không thể giải gói ná»™i dung của “%sâ€" +msgstr "không thể giải gói ná»™i dung của '%s'" #. TRANSLATORS: This is a line of ambiguous object #. output shown when we cannot look up or parse the @@ -17279,7 +17970,7 @@ msgstr "%s thẻ %s - %s" #. #, c-format msgid "%s [bad tag, could not parse it]" -msgstr "%s [thẻ sai, không thể phân tÃch cú pháp nó]" +msgstr "%s [thẻ sai, không hiểu cú pháp nó]" #. TRANSLATORS: This is a line of ambiguous <type> #. object output. E.g. "deadbeef tree". @@ -17322,65 +18013,64 @@ msgid "" "examine these refs and maybe delete them. Turn this message off by\n" "running \"git config advice.objectNameWarning false\"" msgstr "" -"Git thÆ°á»ng không bao giá» tạo tham chiếu mà nó kết thúc vá»›i 40 ký tá»± hex\n" -"bởi vì nó sẽ bị bá» qua khi bạn chỉ định 40-hex. Những tham chiếu nà y\n" -"có lẽ được tạo ra bởi má»™t sai sót nà o đó. Và dụ,\n" +"Git thÆ°á»ng không bao giá» tạo tham chiếu kết thúc vá»›i 40 ký tá»± hex\n" +"bởi vì nó sẽ bị bá» qua khi bạn chỉ định 40 ký tá»± hex. Những tham chiếu\n" +"nà y có lẽ đã được tạo nhầm. Và dụ,\n" "\n" -" git switch -c $br $(git rev-parse …)\n" +" git switch -c $br $(git rev-parse ...)\n" "\n" -"vá»›i \"$br\" không hiểu lý do vì sao trống rá»—ng và má»™t tham chiếu 40-hex được " -"tạo ra.\n" -"Xin hãy kiểm tra những tham chiếu nà y và có thể xóa chúng Ä‘i. Tắt lá»i nhắn " -"nà y\n" -"bằng cách chạy lệnh \"git config advice.objectNameWarning false\"" +"vá»›i \"$br\" không hiểu lý do vì sao rá»—ng và tạo ra tham chiếu 40-hex.\n" +" Xin hãy kiểm tra những tham chiếu nà y và xóa chúng Ä‘i nếu cần. Tắt\n" +"lá»i nhắn nà y bằng cách chạy lệnh \"git config advice.objectNameWarning " +"false\"" #, c-format msgid "log for '%.*s' only goes back to %s" -msgstr "nháºt ký cho “%.*s†chỉ trở lại đến %s" +msgstr "nháºt ký cho '%.*s' chỉ kéo dà i đến %s" #, c-format msgid "log for '%.*s' only has %d entries" -msgstr "nháºt ký cho “%.*s†chỉ có %d mục" +msgstr "nháºt ký cho '%.*s' chỉ có %d mục" #, c-format msgid "path '%s' exists on disk, but not in '%.*s'" -msgstr "Ä‘Æ°á»ng dẫn “%s†có ở trên Ä‘Ä©a, nhÆ°ng không trong “%.*sâ€" +msgstr "Ä‘Æ°á»ng dẫn '%s' có ở trên Ä‘Ä©a, nhÆ°ng không trong '%.*s'" #, c-format msgid "" "path '%s' exists, but not '%s'\n" "hint: Did you mean '%.*s:%s' aka '%.*s:./%s'?" msgstr "" -"Ä‘Æ°á»ng dẫn “%s†tồn tại, nhÆ°ng không phải “%sâ€\n" -"gợi ý: Có phải ý bạn là “%.*s:%s†aka “%.*s:./%sâ€?" +"Ä‘Æ°á»ng dẫn '%s' tồn tại, nhÆ°ng không phải '%s'\n" +"gợi ý: Có phải ý bạn là '%.*s:%s' aka '%.*s:./%s'?" #, c-format msgid "path '%s' does not exist in '%.*s'" -msgstr "Ä‘Æ°á»ng dẫn “%s†không tồn tại trong “%.*sâ€" +msgstr "Ä‘Æ°á»ng dẫn '%s' không tồn tại trong '%.*s'" #, c-format msgid "" "path '%s' is in the index, but not at stage %d\n" "hint: Did you mean ':%d:%s'?" msgstr "" -"Ä‘Æ°á»ng dẫn “%s†nằm trong chỉ mục, nhÆ°ng không phải ở giai Ä‘oạn %d\n" -"gợi ý: Có phải ý bạn là “:%d:%sâ€?" +"Ä‘Æ°á»ng dẫn '%s' nằm trong chỉ mục, nhÆ°ng không phải ở giai Ä‘oạn %d\n" +"gợi ý: Có phải ý bạn là ':%d:%s'?" #, c-format msgid "" "path '%s' is in the index, but not '%s'\n" "hint: Did you mean ':%d:%s' aka ':%d:./%s'?" msgstr "" -"Ä‘Æ°á»ng dẫn “%s†nằm trong chỉ mục, nhÆ°ng không phải “%sâ€\n" -"gợi ý: Có phải ý bạn là “:% d:%s “ aka “:%d:./%sâ€?" +"Ä‘Æ°á»ng dẫn '%s' nằm trong chỉ mục, nhÆ°ng không phải '%s'\n" +"gợi ý: Có phải ý bạn là ':% d:%s ' aka ':%d:./%s'?" #, c-format msgid "path '%s' exists on disk, but not in the index" -msgstr "Ä‘Æ°á»ng dẫn “%s†tồn tại trên Ä‘Ä©a, nhÆ°ng không có trong chỉ mục" +msgstr "Ä‘Æ°á»ng dẫn '%s' tồn tại trên Ä‘Ä©a, nhÆ°ng không có trong chỉ mục" #, c-format msgid "path '%s' does not exist (neither on disk nor in the index)" -msgstr "Ä‘Æ°á»ng dẫn “%s†không tồn tại (không trên Ä‘Ä©a cÅ©ng không trong mục lục)" +msgstr "Ä‘Æ°á»ng dẫn '%s' không tồn tại (không trên Ä‘Ä©a cÅ©ng không trong chỉ mục)" msgid "relative path syntax can't be used outside working tree" msgstr "cú pháp Ä‘Æ°á»ng dẫn tÆ°Æ¡ng đối không thể thể dùng ngoà i cây là m việc" @@ -17391,7 +18081,7 @@ msgstr "<object>:<path> cần cả hai, nhÆ°ng chỉ <object> '%s' được Ä‘Æ° #, c-format msgid "invalid object name '%.*s'." -msgstr "“%.*s†không phải là tên đối tượng hợp lệ." +msgstr "'%.*s' không phải là tên đối tượng hợp lệ." #, c-format msgid "invalid object type \"%s\"" @@ -17407,26 +18097,134 @@ msgstr "đối tượng %s có mã kiểu %d chÆ°a biết" #, c-format msgid "unable to parse object: %s" -msgstr "không thể phân tÃch đối tượng: “%sâ€" +msgstr "không thể Ä‘á»c đối tượng: '%s'" #, c-format msgid "hash mismatch %s" msgstr "mã băm không khá»›p %s" +msgid "trying to write commit not in index" +msgstr "đã thá» ghi lần chuyển giao nằm ngoà i chỉ mục" + +msgid "failed to load bitmap index (corrupted?)" +msgstr "không thể Ä‘á»c chỉ mục bitmap (bị há»ng?)" + +msgid "corrupted bitmap index (too small)" +msgstr "chỉ mục bitmap bị há»ng (quá nhá»)" + +msgid "corrupted bitmap index file (wrong header)" +msgstr "táºp tin chỉ mục bitmap bị há»ng (sai phần đầu)" + +#, c-format +msgid "unsupported version '%d' for bitmap index file" +msgstr "không há»— trợ táºp tin chỉ mục bitmap phiên bản '%d'" + +msgid "corrupted bitmap index file (too short to fit hash cache)" +msgstr "táºp tin chỉ mục bitmap bị há»ng (quá ngắn để chứa bá»™ đệm mã băm)" + +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)" + +#, c-format +msgid "duplicate entry in bitmap index: '%s'" +msgstr "đối tượng trùng lặp trong bitmap: '%s'" + +#, c-format +msgid "corrupt ewah bitmap: truncated header for entry %d" +msgstr "ewah bitmap bị há»ng: phần đầu bị cắt ngắn cho mục thứ %d" + +#, c-format +msgid "corrupt ewah bitmap: commit index %u out of range" +msgstr "ewah bitmap bị há»ng: mục chuyển giao thứ %u nằm ngoà i phạm vi" + +msgid "corrupted bitmap pack index" +msgstr "chỉ mục gói bitmap bị há»ng" + +msgid "invalid XOR offset in bitmap pack index" +msgstr "XOR offset không hợp lệ trong chỉ mục gói bitmap" + +msgid "cannot fstat bitmap file" +msgstr "không thể fstat file bitmap" + +msgid "checksum doesn't match in MIDX and bitmap" +msgstr "tổng kiểm ra trong MIDX và bitmap không khá»›p" + msgid "multi-pack bitmap is missing required reverse index" -msgstr "ánh xạ multi-pack thiếu mục lục để dà nh cần thiết" +msgstr "bitmap multi-pack thiếu chỉ mục để dà nh cần thiết" #, c-format msgid "could not open pack %s" -msgstr "không thể mở gói “%sâ€" +msgstr "không thể mở gói '%s'" + +msgid "could not determine MIDX preferred pack" +msgstr "không thể xác định gói MIDX Æ°a dùng" #, c-format msgid "preferred pack (%s) is invalid" -msgstr "\"preferred pack\" (%s) không hợp lệ" +msgstr "preferred pack (%s) không hợp lệ" + +msgid "corrupt bitmap lookup table: triplet position out of index" +msgstr "bảng tìm kiếm bitmap bị há»ng: vị trà bá»™ ba nằm ngoà i chỉ mục" + +msgid "corrupt bitmap lookup table: xor chain exceeds entry count" +msgstr "bảng tìm kiếm bitmap bị há»ng: chuá»—i xor vượt quá số lượng mục" #, 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>" +msgid "corrupt bitmap lookup table: commit index %u out of range" +msgstr "bảng tìm kiếm bitmap bị há»ng: mục chuyển giao thứ %u nằm ngoà i phạm vi" + +#, c-format +msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\"" +msgstr "" +"ewah bitmap bị há»ng: bitmap lần chuyển giao \"%s\" có phần đầu bị cắt ngắn" + +#, c-format +msgid "unable to load pack: '%s', disabling pack-reuse" +msgstr "không thể Ä‘á»c gói: '%s', vô hiệu sá» dụng lại gói" + +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "không thể tÃnh giá trị gói Æ°a dùng, vô hiệu sá» dụng lại gói" + +#, c-format +msgid "object '%s' not found in type bitmaps" +msgstr "không tìm thấy đối tượng '%s' trong type bitmap" + +#, c-format +msgid "object '%s' does not have a unique type" +msgstr "đối tượng '%s' không có kiểu Ä‘á»™c nhất" + +#, c-format +msgid "object '%s': real type '%s', expected: '%s'" +msgstr "đối tượng '%s': kiểu '%s', cần: '%s'" + +#, c-format +msgid "object not in bitmap: '%s'" +msgstr "không tìm thấy đối tượng trong bitmap: %s" + +msgid "failed to load bitmap indexes" +msgstr "Ä‘á»c chỉ mục bitmap thất bại" + +msgid "you must specify exactly one commit to test" +msgstr "bạn phải chỉ định các lần chuyển giao muốn kiểm tra" + +#, c-format +msgid "commit '%s' doesn't have an indexed bitmap" +msgstr "lần chuyển giao '%s' không có chỉ mục bitmap" + +msgid "mismatch in bitmap results" +msgstr "kết quả bitmap không khá»›p" + +#, 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>" + +#, c-format +msgid "unable to get disk usage of '%s'" +msgstr "không thể lấy dung lượng Ä‘Ä©a đã dùng của %s" + +#, c-format +msgid "bitmap file '%s' has invalid checksum" +msgstr "file bitmap '%s' có checksum không hợp lệ" #, c-format msgid "mtimes file %s is too small" @@ -17438,7 +18236,7 @@ msgstr "táºp tin mtimes %s có chữ ký chÆ°a biết" #, c-format msgid "mtimes file %s has unsupported version %<PRIu32>" -msgstr "tệp mtimes %s có phiên bản không được há»— trợ %<PRIu32>" +msgstr "táºp mtimes %s có phiên bản không được há»— trợ %<PRIu32>" #, c-format msgid "mtimes file %s has unsupported hash id %<PRIu32>" @@ -17462,18 +18260,31 @@ msgstr "táºp tin reverse-index %s có chữ ký chÆ°a biết" #, c-format msgid "reverse-index file %s has unsupported version %<PRIu32>" -msgstr "tệp chỉ mục ngược %s có phiên bản không được há»— trợ %<PRIu32>" +msgstr "táºp chỉ mục ngược %s có phiên bản không được há»— trợ %<PRIu32>" #, c-format msgid "reverse-index file %s has unsupported hash id %<PRIu32>" -msgstr "tệp chỉ mục ngược %s có id mã băm không được há»— trợ %<PRIu32>" +msgstr "táºp chỉ mục ngược %s có id mã băm không được há»— trợ %<PRIu32>" + +msgid "invalid checksum" +msgstr "checksum không hợp lệ" + +#, c-format +msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>" +msgstr "vị trà mục xét duyệt không hợp lệ %<PRIu64>: %<PRIu32> != %<PRIu32>" + +msgid "multi-pack-index reverse-index chunk is the wrong size" +msgstr "chunk chỉ mục ngược của chỉ mục Ä‘a gói có kÃch thÆ°á»›c sai" + +msgid "could not determine preferred pack" +msgstr "không thể xác định gói Æ°a dùng" msgid "cannot both write and verify reverse index" -msgstr "không thể cùng lúc Ä‘á»c và xác minh được bảng mục lục đảo ngược" +msgstr "không thể cùng lúc gh và xác minh chỉ mục ngược" #, c-format msgid "could not stat: %s" -msgstr "không thể lấy thông tin thống kê: %s" +msgstr "không thể stat: %s" #, c-format msgid "failed to make %s readable" @@ -17481,7 +18292,7 @@ msgstr "gặp lá»—i là m cho %s Ä‘á»c được" #, c-format msgid "could not write '%s' promisor file" -msgstr "không thể ghi táºp tin promisor “%sâ€" +msgstr "không thể ghi táºp tin promisor '%s'" msgid "offset before end of packfile (broken .idx?)" msgstr "vị trà tÆ°Æ¡ng đối trÆ°á»›c Ä‘iểm kết thúc của táºp tin gói (.idx há»ng à ?)" @@ -17492,44 +18303,36 @@ msgstr "táºp tin gói %s không thể được ánh xạ %s" #, c-format msgid "offset before start of pack index for %s (corrupt index?)" -msgstr "vị trà tÆ°Æ¡ng đối nằm trÆ°á»›c chỉ mục gói cho %s (mục lục bị há»ng à ?)" +msgstr "vị trà tÆ°Æ¡ng đối nằm trÆ°á»›c chỉ mục gói cho %s (chỉ mục bị há»ng à ?)" #, c-format msgid "offset beyond end of pack index for %s (truncated index?)" msgstr "" -"vị trà tÆ°Æ¡ng đối vượt quá cuối của chỉ mục gói cho %s (mục lục bị cắt cụt à ?)" +"vị trà tÆ°Æ¡ng đối vượt quá cuối của chỉ mục gói cho %s (chỉ mục bị cắt cụt à ?)" #, c-format msgid "malformed expiration date '%s'" -msgstr "ngà y tháng hết hạn dị hình “%sâ€" +msgstr "ngà y tháng hết hạn sai quy cách '%s'" #, c-format msgid "option `%s' expects \"always\", \"auto\", or \"never\"" -msgstr "tùy chá»n “%s†cần \"always\", \"auto\", hoặc \"never\"" +msgstr "tùy chá»n '%s' cần \"always\", \"auto\", hoặc \"never\"" #, c-format msgid "malformed object name '%s'" -msgstr "tên đối tượng dị hình “%sâ€" +msgstr "tên đối tượng sai quy cách '%s'" #, c-format msgid "option `%s' expects \"%s\" or \"%s\"" -msgstr "tùy chá»n “%s†cần \"%s\" hoặc \"%s\"" +msgstr "tùy chá»n '%s' cần \"%s\" hoặc \"%s\"" #, c-format msgid "%s requires a value" -msgstr "“%s†yêu cầu má»™t giá trị" - -#, c-format -msgid "%s is incompatible with %s" -msgstr "%s là xung khắc vá»›i %s" - -#, c-format -msgid "%s : incompatible with something else" -msgstr "%s : xung khắc vá»›i các cái khác" +msgstr "'%s' yêu cầu má»™t giá trị" #, c-format msgid "%s takes no value" -msgstr "%s k nháºn giá trị" +msgstr "%s không nháºn giá trị" #, c-format msgid "%s isn't available" @@ -17545,26 +18348,29 @@ msgstr "tùy chá»n chÆ°a rõ rang: %s (nên là --%s%s hay --%s%s)" #, c-format msgid "did you mean `--%s` (with two dashes)?" -msgstr "có phải ý bạn là “--%s“ (vá»›i hai dấu gạch ngang)?" +msgstr "có phải ý bạn là '--%s' (vá»›i hai dấu gạch ngang)?" #, c-format msgid "alias of --%s" msgstr "bà danh của --%s" +msgid "need a subcommand" +msgstr "cần câu lệnh con" + #, c-format msgid "unknown option `%s'" -msgstr "không hiểu tùy chá»n “%sâ€" +msgstr "không hiểu tùy chá»n '%s'" #, c-format msgid "unknown switch `%c'" -msgstr "không hiểu tùy chá»n “%câ€" +msgstr "không hiểu tùy chá»n '%c'" #, c-format msgid "unknown non-ascii option in string: `%s'" -msgstr "không hiểu tùy chá»n non-ascii trong chuá»—i: “%sâ€" +msgstr "không hiểu tùy chá»n non-ascii trong chuá»—i: '%s'" msgid "..." -msgstr "…" +msgstr "..." #, c-format msgid "usage: %s" @@ -17607,6 +18413,10 @@ msgstr " %s" msgid "-NUM" msgstr "-Sá»" +#, c-format +msgid "opposite of --no-%s" +msgstr "ngược lại vá»›i --no-%s" + msgid "expiry-date" msgstr "ngà y hết hạn" @@ -17622,8 +18432,11 @@ msgstr "im lặng hÆ¡n nữa" msgid "use <n> digits to display object names" msgstr "sá» dụng <n> chữ số để hiển thị tên đối tượng" +msgid "prefixed path to initial superproject" +msgstr "Ä‘Æ°á»ng dẫn tiá»n tố đến project cha ban đầu" + msgid "how to strip spaces and #comments from message" -msgstr "là m thế nà o để cắt bá» khoảng trắng và #ghichú từ mẩu tin nhắn" +msgstr "là m thế nà o để cắt bá» khoảng trắng và #ghi-chú từ tin nhắn" msgid "read pathspec from file" msgstr "Ä‘á»c đặc tả Ä‘Æ°á»ng dẫn từ táºp tin" @@ -17635,15 +18448,23 @@ msgstr "" "tá»± NULL" #, c-format +msgid "bad boolean environment value '%s' for '%s'" +msgstr "sai giá trị kiểu boolean của cấu hình '%s' cho '%s'" + +#, c-format +msgid "failed to parse %s" +msgstr "gặp lá»—i khi Ä‘á»c cú pháp %s" + +#, c-format msgid "Could not make %s writable by group" msgstr "Không thể là m %s được ghi bởi nhóm" msgid "Escape character '\\' not allowed as last character in attr value" msgstr "" -"Ký tá»± thoát chuá»—i “\\†không được phép là ký tá»± cuối trong giá trị thuá»™c tÃnh" +"Ký tá»± thoát chuá»—i '\\' không được phép là ký tá»± cuối trong giá trị thuá»™c tÃnh" msgid "Only one 'attr:' specification is allowed." -msgstr "Chỉ có má»™t đặc tả “attr:†là được phép." +msgstr "Chỉ có má»™t đặc tả 'attr:' là được phép." msgid "attr spec must not be empty" msgstr "đặc tả attr phải không được để trống" @@ -17653,42 +18474,45 @@ msgid "invalid attribute name %s" msgstr "tên thuá»™c tÃnh không hợp lệ %s" msgid "global 'glob' and 'noglob' pathspec settings are incompatible" -msgstr "" -"các cà i đặt đặc tả Ä‘Æ°á»ng dẫn “glob†và “noglob†toà n cục là xung khắc nhau" +msgstr "các cà i đặt đặc tả Ä‘Æ°á»ng dẫn 'glob' và 'noglob' toà n cục là xung khắc" msgid "" "global 'literal' pathspec setting is incompatible with all other global " "pathspec settings" msgstr "" -"cà i đặt đặc tả Ä‘Æ°á»ng dẫn “literal†toà n cục là xung khắc vá»›i các cà i đặt đặc " -"tả Ä‘Æ°á»ng dẫn toà n cục khác" +"cà i đặt đặc tả Ä‘Æ°á»ng dẫn 'literal' toà n cục không tÆ°Æ¡ng thÃch vá»›i các cà i " +"đặt đặc tả Ä‘Æ°á»ng dẫn toà n cục khác" msgid "invalid parameter for pathspec magic 'prefix'" -msgstr "tham số không hợp lệ cho “tiá»n tố†mà u nhiệm đặc tả Ä‘Æ°á»ng đẫn" +msgstr "tham số không hợp lệ cho đặc tả Ä‘Æ°á»ng đẫn đặc biệt 'prefix'" #, c-format msgid "Invalid pathspec magic '%.*s' in '%s'" -msgstr "Số mà u nhiệm đặc tả Ä‘Æ°á»ng dẫn không hợp lệ “%.*s†trong “%sâ€" +msgstr "Äặc tả Ä‘Æ°á»ng dẫn không hợp lệ '%.*s' trong '%s'" #, c-format msgid "Missing ')' at the end of pathspec magic in '%s'" -msgstr "Thiếu “)†tại cuối của số mà u nhiệm đặc tả Ä‘Æ°á»ng dẫn trong “%sâ€" +msgstr "Thiếu ')' tại cuối của đặc tả Ä‘Æ°á»ng dẫn trong '%s'" #, c-format msgid "Unimplemented pathspec magic '%c' in '%s'" -msgstr "ChÆ°a viết mã cho số mà u nhiệm đặc tả Ä‘Æ°á»ng dẫn “%c†trong “%sâ€" +msgstr "ChÆ°a há»— trợ đặc tả Ä‘Æ°á»ng dẫn '%c' trong '%s'" #, c-format msgid "%s: 'literal' and 'glob' are incompatible" -msgstr "%s: “literal†và “glob†xung khắc nhau" +msgstr "%s: 'literal' và 'glob' xung khắc" + +#, c-format +msgid "'%s' is outside the directory tree" +msgstr "'%s' nằm ngoà i cây thÆ° mục" #, c-format msgid "%s: '%s' is outside repository at '%s'" -msgstr "%s: “%s†ngoà i má»™t kho chứa tại “%sâ€" +msgstr "%s: '%s' nằm ngoà i má»™t kho chứa tại '%s'" #, c-format msgid "'%s' (mnemonic: '%c')" -msgstr "“%s†(mnemonic: “%câ€)" +msgstr "'%s' (mnemonic: '%c')" #, c-format msgid "%s: pathspec magic not supported by this command: %s" @@ -17696,7 +18520,7 @@ msgstr "%s: số mầu nhiệm đặc tả Ä‘Æ°á»ng dẫn chÆ°a được há»— t #, c-format msgid "pathspec '%s' is beyond a symbolic link" -msgstr "đặc tả Ä‘Æ°á»ng dẫn “%s†vượt ra ngoà i liên kết má»m" +msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' vượt ra ngoà i liên kết má»m" #, c-format msgid "line is badly quoted: %s" @@ -17746,14 +18570,14 @@ msgid "remote error: %s" msgstr "lá»—i máy chủ: %s" msgid "Refreshing index" -msgstr "Là m má»›i bảng mục lục" +msgstr "Là m má»›i chỉ mục" #, c-format msgid "unable to create threaded lstat: %s" -msgstr "không thể tạo tuyến trình lstat: %s" +msgstr "không thể tạo tiến trình lstat: %s" msgid "unable to parse --pretty format" -msgstr "không thể phân tÃch định dạng --pretty" +msgstr "không thể Ä‘á»c định dạng --pretty" msgid "promisor-remote: unable to fork off fetch subprocess" msgstr "promisor-remote: không thể rẽ nhánh tuyến trình con fetch" @@ -17762,12 +18586,15 @@ msgid "promisor-remote: could not write to fetch subprocess" msgstr "promisor-remote: không thể ghi tiến trình con fetch" msgid "promisor-remote: could not close stdin to fetch subprocess" -msgstr "" -"promisor-remote: không thể đóng đầu và o tiêu chuẩn tiến trình con fetch" +msgstr "promisor-remote: không thể đóng stdin tiến trình con fetch" #, c-format msgid "promisor remote name cannot begin with '/': %s" -msgstr "tên máy chủ hứa hẹn không thể bắt đầu bằng “/â€: %s" +msgstr "tên máy chủ promisor không thể bắt đầu bằng '/': %s" + +#, c-format +msgid "could not fetch %s from promisor remote" +msgstr "không thể tải %s từ máy chủ promisor" msgid "object-info: expected flush after arguments" msgstr "object-info: cần đẩy dữ liệu lên Ä‘Ä©a sau các tham số" @@ -17776,38 +18603,44 @@ msgid "Removing duplicate objects" msgstr "Äang gỡ các đối tượng trùng lặp" msgid "could not start `log`" -msgstr "không thể lấy thông tin thống kê vỠ“log“" +msgstr "không thể khởi chạy `log`" msgid "could not read `log` output" -msgstr "không thể Ä‘á»c kết xuất “logâ€" +msgstr "không thể Ä‘á»c đầu ra `log`" #, c-format msgid "could not parse commit '%s'" -msgstr "không thể phân tÃch lần chuyển giao “%sâ€" +msgstr "không thể Ä‘á»c lần chuyển giao '%s'" #, c-format msgid "" "could not parse first line of `log` output: did not start with 'commit ': " "'%s'" msgstr "" -"không thể phân tÃch cú pháp dòng đầu tiên của đầu ra “logâ€: không bắt đầu " -"bằng “commit â€: “%sâ€" +"không hiểu cú pháp dòng đầu tiên của đầu ra 'log': không bắt đầu bằng " +"'commit ': '%s'" #, c-format msgid "could not parse git header '%.*s'" -msgstr "không thể phân tÃch cú pháp phần đầu git “%.*sâ€" +msgstr "không hiểu cú pháp phần đầu git '%.*s'" msgid "failed to generate diff" msgstr "gặp lá»—i khi tạo khác biệt" #, c-format msgid "could not parse log for '%s'" -msgstr "không thể phân tÃch nháºt ký cho “%sâ€" +msgstr "không thể Ä‘á»c nháºt ký cho '%s'" + +#, c-format +msgid "invalid extra cruft tip: '%s'" +msgstr "extra cruft tip không hợp lệ: '%s'" + +msgid "unable to enumerate additional recent objects" +msgstr "không thể đếm các đối tượng má»›i thêm" #, c-format msgid "will not add file alias '%s' ('%s' already exists in index)" -msgstr "" -"sẽ không thêm các bà danh “%s†(“%s†đã có từ trÆ°á»›c trong bảng mục lục)" +msgstr "sẽ không thêm các bà danh '%s' ('%s' đã có từ trÆ°á»›c trong chỉ mục)" msgid "cannot create an empty blob in the object database" msgstr "không thể tạo má»™t blob rá»—ng trong cÆ¡ sở dữ liệu đối tượng" @@ -17819,22 +18652,18 @@ msgstr "" #, c-format msgid "unable to index file '%s'" -msgstr "không thể đánh mục lục táºp tin “%sâ€" +msgstr "không thể đánh chỉ mục táºp tin '%s'" #, c-format msgid "unable to add '%s' to index" -msgstr "không thể thêm %s và o bảng mục lục" - -#, c-format -msgid "unable to stat '%s'" -msgstr "không thể lấy thống kê “%sâ€" +msgstr "không thể thêm %s và o chỉ mục" #, c-format msgid "'%s' appears as both a file and as a directory" -msgstr "%s có vẻ không phải là táºp tin và cÅ©ng chẳng phải là má»™t thÆ° mục" +msgstr "%s có vẻ vừa là táºp tin và cÅ©ng vừa là thÆ° mục" msgid "Refresh index" -msgstr "Là m tÆ°Æ¡i má»›i bảng mục lục" +msgstr "Là m má»›i chỉ mục" #, c-format msgid "" @@ -17858,37 +18687,37 @@ msgstr "chữ ký sai 0x%08x" #, c-format msgid "bad index version %d" -msgstr "phiên bản mục lục sai %d" +msgstr "phiên bản chỉ mục sai %d" msgid "bad index file sha1 signature" -msgstr "chữ ký dạng sha1 cho táºp tin mục lục không đúng" +msgstr "chữ ký dạng sha1 cho táºp tin chỉ mục không đúng" #, c-format msgid "index uses %.4s extension, which we do not understand" -msgstr "mục lục dùng phần mở rá»™ng %.4s, cái mà chúng tôi không hiểu được" +msgstr "chỉ mục dùng phần mở rá»™ng %.4s, cái mà chúng tôi không hiểu được" #, c-format msgid "ignoring %.4s extension" -msgstr "Ä‘ang lá» Ä‘i phần mở rá»™ng %.4s" +msgstr "Ä‘ang bá» qua phần mở rá»™ng %.4s" #, c-format msgid "unknown index entry format 0x%08x" -msgstr "không hiểu định dạng mục lục 0x%08x" +msgstr "không hiểu định dạng chỉ mục 0x%08x" #, c-format msgid "malformed name field in the index, near path '%s'" -msgstr "trÆ°á»ng tên sai sạng trong mục lục, gần Ä‘Æ°á»ng dẫn “%sâ€" +msgstr "trÆ°á»ng tên sai sạng trong chỉ mục, gần Ä‘Æ°á»ng dẫn '%s'" msgid "unordered stage entries in index" -msgstr "các mục tin stage không đúng thứ tá»± trong mục lục" +msgstr "các mục tin stage không đúng thứ tá»± trong chỉ mục" #, c-format msgid "multiple stage entries for merged file '%s'" -msgstr "nhiá»u mục stage cho táºp tin hòa trá»™n “%sâ€" +msgstr "nhiá»u mục stage cho táºp tin hòa trá»™n '%s'" #, c-format msgid "unordered stage entries for '%s'" -msgstr "các mục tin stage không đúng thứ tá»± cho “%sâ€" +msgstr "các mục tin stage không đúng thứ tá»± cho '%s'" #, c-format msgid "unable to create load_cache_entries thread: %s" @@ -17900,19 +18729,19 @@ msgstr "không thể gia nháºp tuyến load_cache_entries: %s" #, c-format msgid "%s: index file open failed" -msgstr "%s: mở táºp tin mục lục gặp lá»—i" +msgstr "%s: mở táºp tin chỉ mục gặp lá»—i" #, c-format msgid "%s: cannot stat the open index" -msgstr "%s: không thể lấy thống kê bảng mục lục đã mở" +msgstr "%s: không thể stat chỉ mục đã mở" #, c-format msgid "%s: index file smaller than expected" -msgstr "%s: táºp tin mục lục nhá» hÆ¡n mong đợi" +msgstr "%s: táºp tin chỉ mục nhá» hÆ¡n mong đợi" #, c-format msgid "%s: unable to map index file%s" -msgstr "%s: không thể ánh xạ táºp tin mục lục%s" +msgstr "%s: không thể ánh xạ táºp tin chỉ mục%s" #, c-format msgid "unable to create load_index_extensions thread: %s" @@ -17924,46 +18753,50 @@ msgstr "không thể gia nháºp tuyến load_index_extensions: %s" #, c-format msgid "could not freshen shared index '%s'" -msgstr "không thể là m tÆ°Æ¡i má»›i mục lục đã chia sẻ “%sâ€" +msgstr "không thể là m tÆ°Æ¡i má»›i chỉ mục đã chia sẻ '%s'" #, c-format msgid "broken index, expect %s in %s, got %s" -msgstr "mục lục bị há»ng, cần %s trong %s, nhÆ°ng lại nháºn được %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 mục lụ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\"" #, c-format -msgid "could not stat '%s'" -msgstr "không thể lấy thông tin thống kê vỠ“%sâ€" - -#, c-format msgid "unable to open git dir: %s" msgstr "không thể mở thÆ° mục git: %s" #, c-format msgid "unable to unlink: %s" -msgstr "không thể bá» liên kết (unlink): “%sâ€" +msgstr "không thể bá» liên kết (unlink): '%s'" #, c-format msgid "cannot fix permission bits on '%s'" -msgstr "không thể sá»a các bÃt phân quyá»n trên “%sâ€" +msgstr "không thể sá»a các bÃt phân quyá»n trên '%s'" #, c-format msgid "%s: cannot drop to stage #0" msgstr "%s: không thể xóa bá» stage #0" +#, c-format +msgid "unexpected diff status %c" +msgstr "trạng thái lệnh diff không nhÆ° mong đợi %c" + +#, c-format +msgid "remove '%s'\n" +msgstr "gỡ bá» '%s'\n" + msgid "" "You can fix this with 'git rebase --edit-todo' and then run 'git rebase --" "continue'.\n" "Or you can abort the rebase with 'git rebase --abort'.\n" msgstr "" -"Bạn có thể sá»a nó bằng “git rebase --edit-todo†và sau đó chạy “git rebase --" -"continueâ€.\n" -"Hoặc là bạn có thể bãi bá» việc cải tổ bằng “git rebase --abortâ€.\n" +"Bạn có thể sá»a nó bằng 'git rebase --edit-todo' và sau đó chạy 'git rebase --" +"continue'.\n" +"Hoặc là bạn có thể huá»· bá» việc cải tổ bằng 'git rebase --abort'.\n" #, c-format msgid "" @@ -17988,9 +18821,12 @@ msgid "" "l, label <label> = label current HEAD with a name\n" "t, reset <label> = reset HEAD to a label\n" "m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]\n" -". create a merge commit using the original merge commit's\n" -". message (or the oneline, if no original merge commit was\n" -". specified); use -c <commit> to reword the commit message\n" +" create a merge commit using the original merge commit's\n" +" message (or the oneline, if no original merge commit was\n" +" specified); use -c <commit> to reword the commit message\n" +"u, update-ref <ref> = track a placeholder for the <ref> to be updated\n" +" to this position in the new commits. The <ref> is\n" +" updated at the end of the rebase\n" "\n" "These lines can be re-ordered; they are executed from top to bottom.\n" msgstr "" @@ -17998,7 +18834,7 @@ msgstr "" "Các lệnh:\n" "p, pick <commit> = dùng lần chuyển giao\n" "r, reword <commit> = dùng lần chuyển giao, nhÆ°ng sá»a lại phần chú thÃch\n" -"e, edit <commit> = dùng lần chuyển giao, nhÆ°ng dừng lại để tu bổ (amend)\n" +"e, edit <commit> = dùng lần chuyển giao, nhÆ°ng dừng lại để tu bổ\n" "s, squash <commit> = dùng lần chuyển giao, nhÆ°ng trá»™n và o lần chuyển giao kế " "trÆ°á»›c\n" "f, fixup [-C | -c] <commit> = giống nhÆ° \"squash\", nhÆ°ng chỉ giữ lại phần " @@ -18009,33 +18845,35 @@ msgstr "" "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" -"b, break = dừng tại đây (tiếp tục cải tổ sau nà y bằng “git rebase --" -"continueâ€)\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" -"l, label <label> = đánh nhãn HEAD hiện tại bằng má»™t tên\n" -"t, reset <label> = đặt lại HEAD thà nh má»™t nhãn\n" +"l, label <label> = đánh tên nhãn HEAD hiện tại\n" +"t, reset <label> = đặt lại HEAD vá» má»™t nhãn\n" "m, merge [-C <commit> | -c <commit>] <nhãn> [# <má»™t_dòng>]\n" ". tạo má»™t lần chuyển giao hòa trá»™n sá» dụng chú thÃch của lần chuyển\n" ". giao hòa trá»™n gốc (hoặc má»™t_dòng, nếu không chỉ định lần chuyển giao " "hòa\n" ". trá»™n gốc). Dùng -c <commit> để reword chú thÃch của lần chuyển " "giao.\n" +"u, update-ref <ref> = track a placeholder for the <ref> to be updated\n" +" to this position in the new commits. The <ref> is\n" +" updated at the end of the rebase\n" "\n" -"Những dòng nà y có thể được thay đổi thứ tá»±; chúng chạy từ trên đỉnh xuống " -"dÆ°á»›i đáy.\n" +"Những dòng nà y có thể được thay đổi thứ tá»±; chúng được thá»±c thi từ trên " +"xuống dÆ°á»›i.\n" #, c-format msgid "Rebase %s onto %s (%d command)" msgid_plural "Rebase %s onto %s (%d commands)" -msgstr[0] "Cải tổ %s và o %s (%d lệnh )" +msgstr[0] "Cải tổ %s và o %s (%d lệnh)" msgid "" "\n" "Do not remove any line. Use 'drop' explicitly to remove a commit.\n" msgstr "" "\n" -"Äừng xóa bất kỳ dòng nà o. Dùng “drop†má»™t cách rõ rà ng để xóa bá» má»™t lần " -"chuyển giao.\n" +"Äừng xóa bất kỳ dòng nà o. Dùng 'drop' để xóa bá» má»™t lần chuyển giao.\n" msgid "" "\n" @@ -18063,12 +18901,12 @@ msgid "" "\n" msgstr "" "\n" -"Tuy nhiên, nếu bạn xóa bá» má»i thứ, việc cải tổ sẽ bị bãi bá».\n" +"Tuy nhiên, nếu bạn xóa bá» má»i thứ, việc cải tổ sẽ bị huá»· bá».\n" "\n" #, c-format msgid "could not write '%s'." -msgstr "không thể ghi “%sâ€." +msgstr "không thể ghi '%s'." #, c-format msgid "" @@ -18090,29 +18928,37 @@ msgstr "" "Äể tránh thông báo nà y, dùng \"drop\" má»™t cách rõ rà ng để xóa bá» má»™t lần " "chuyển giao.\n" "\n" -"Dùng “git config rebase.missingCommitsCheck†để thay đổi mức Ä‘á»™ của cảnh " +"Dùng 'git config rebase.missingCommitsCheck' để thay đổi mức Ä‘á»™ của cảnh " "báo.\n" "Cánh ứng xá» có thể là : ignore, warn, error.\n" "\n" #, c-format msgid "%s: 'preserve' superseded by 'merges'" -msgstr "%s: “preserve†bị cấm bởi “mergesâ€" +msgstr "%s: 'preserve' bị thay bởi 'merges'" msgid "gone" -msgstr "đã ra Ä‘i" +msgstr "đã xoá" #, c-format msgid "ahead %d" -msgstr "phÃa trÆ°á»›c %d" +msgstr "đứng trÆ°á»›c %d" #, c-format msgid "behind %d" -msgstr "đằng sau %d" +msgstr "đứng sau %d" #, c-format msgid "ahead %d, behind %d" -msgstr "trÆ°á»›c %d, sau %d" +msgstr "đứng trÆ°á»›c %d, đứng sau %d" + +#, c-format +msgid "%%(%.*s) does not take arguments" +msgstr "%%(%.*s) không nháºn các đối số" + +#, c-format +msgid "unrecognized %%(%.*s) argument: %s" +msgstr "đối số không được thừa nháºn %%(%.*s): %s" #, c-format msgid "expected format: %%(color:<color>)" @@ -18131,40 +18977,36 @@ msgid "Integer value expected refname:rstrip=%s" msgstr "Giá trị nguyên cần tên tham chiếu:rstrip=%s" #, c-format -msgid "unrecognized %%(%s) argument: %s" -msgstr "đối số không được thừa nháºn %%(%s): %s" +msgid "expected %%(trailers:key=<value>)" +msgstr "cần %%(trailers:key=<giá trị>)" #, c-format -msgid "%%(objecttype) does not take arguments" -msgstr "%%(objecttype) không nháºn các đối số" +msgid "unknown %%(trailers) argument: %s" +msgstr "không hiểu tham số %%(trailers): %s" #, c-format -msgid "%%(deltabase) does not take arguments" -msgstr "%%(deltabase) không nháºn các đối số" +msgid "positive value expected contents:lines=%s" +msgstr "cần ná»™i dung mang giá trị dÆ°Æ¡ng:lines=%s" #, c-format -msgid "%%(body) does not take arguments" -msgstr "%%(body) không nháºn các đối số" +msgid "argument expected for %s" +msgstr "cần đối số cho %s" #, c-format -msgid "expected %%(trailers:key=<value>)" -msgstr "cần %%(trailers:key=<giá trị>)" +msgid "positive value expected %s=%s" +msgstr "cần giá trị dÆ°Æ¡ng %s=%s" #, c-format -msgid "unknown %%(trailers) argument: %s" -msgstr "không hiểu tham số %%(trailers): %s" +msgid "cannot fully parse %s=%s" +msgstr "không hiểu %s=%s" #, c-format -msgid "positive value expected contents:lines=%s" -msgstr "cần ná»™i dung mang giá trị dÆ°Æ¡ng:lines=%s" +msgid "value expected %s=" +msgstr "cần %s=" #, c-format msgid "positive value expected '%s' in %%(%s)" -msgstr "cần giá trị dÆ°Æ¡ng “%s†trong %%(%s)" - -#, c-format -msgid "unrecognized email option: %s" -msgstr "không nháºn ra tùy chá»n thÆ° Ä‘iện tá»: “%sâ€" +msgstr "cần giá trị dÆ°Æ¡ng '%s' trong %%(%s)" #, c-format msgid "expected format: %%(align:<width>,<position>)" @@ -18179,16 +19021,20 @@ msgid "unrecognized width:%s" msgstr "chiá»u rá»™ng không được thừa nháºn:%s" #, c-format +msgid "unrecognized %%(%s) argument: %s" +msgstr "đối số không được thừa nháºn %%(%s): %s" + +#, c-format msgid "positive width expected with the %%(align) atom" -msgstr "cần giá trị Ä‘á»™ rá»™ng dÆ°Æ¡ng vá»›i nguyên tá» %%(align)" +msgstr "cần giá trị Ä‘á»™ rá»™ng dÆ°Æ¡ng vá»›i atom %%(align)" #, c-format -msgid "%%(rest) does not take arguments" -msgstr "%%(rest) không nháºn các đối số" +msgid "expected format: %%(ahead-behind:<committish>)" +msgstr "cần định dạng: %%(ahead-behind:<committish>)" #, c-format msgid "malformed field name: %.*s" -msgstr "tên trÆ°á»ng dị hình: %.*s" +msgstr "tên trÆ°á»ng sai quy cách: %.*s" #, c-format msgid "unknown field name: %.*s" @@ -18198,32 +19044,32 @@ msgstr "không hiểu tên trÆ°á»ng: %.*s" msgid "" "not a git repository, but the field '%.*s' requires access to object data" msgstr "" -"không phải là má»™t kho git, nhÆ°ng trÆ°á»ng “%.*s†yêu cầu truy cáºp và o dữ liệu " +"không phải là má»™t kho git, nhÆ°ng trÆ°á»ng '%.*s' yêu cầu truy cáºp và o dữ liệu " "đối tượng" #, c-format msgid "format: %%(%s) atom used without a %%(%s) atom" -msgstr "định dạng: nguyên tá» %%(%s) được dùng mà không có nguyên tá» %%(%s)" +msgstr "định dạng: atom %%(%s) được dùng mà không có atom %%(%s)" #, c-format msgid "format: %%(then) atom used more than once" -msgstr "định dạng: nguyên tá» %%(then) được dùng nhiá»u hÆ¡n má»™t lần" +msgstr "định dạng: atom %%(then) được dùng nhiá»u hÆ¡n má»™t lần" #, c-format msgid "format: %%(then) atom used after %%(else)" -msgstr "định dạng: nguyên tá» %%(then) được dùng sau %%(else)" +msgstr "định dạng: atom %%(then) được dùng sau %%(else)" #, c-format msgid "format: %%(else) atom used more than once" -msgstr "định dạng: nguyên tá» %%(else) được dùng nhiá»u hÆ¡n má»™t lần" +msgstr "định dạng: atom %%(else) được dùng nhiá»u hÆ¡n má»™t lần" #, c-format msgid "format: %%(end) atom used without corresponding atom" -msgstr "định dạng: nguyên tá» %%(end) được dùng mà không có nguyên tá» tÆ°Æ¡ng ứng" +msgstr "định dạng: atom %%(end) được dùng mà không có atom tÆ°Æ¡ng ứng" #, c-format msgid "malformed format string %s" -msgstr "chuá»—i định dạng dị hình %s" +msgstr "chuá»—i định dạng sai quy cách %s" #, c-format msgid "this command reject atom %%(%.*s)" @@ -18233,6 +19079,9 @@ msgstr "lệnh nà y từ chối atom %%(%.*s)" msgid "--format=%.*s cannot be used with --python, --shell, --tcl" msgstr "--format=%.*s không thể được dùng vá»›i --python, --shell, --tcl" +msgid "failed to run 'describe'" +msgstr "gặp lá»—i khi chạy 'describe'" + #, c-format msgid "(no branch, rebasing %s)" msgstr "(không nhánh, Ä‘ang cải tổ %s)" @@ -18266,27 +19115,27 @@ msgstr "parse_object_buffer gặp lá»—i trên %s cho %s" #, c-format msgid "malformed object at '%s'" -msgstr "đối tượng dị hình tại “%sâ€" +msgstr "đối tượng sai quy cách tại '%s'" #, c-format msgid "ignoring ref with broken name %s" -msgstr "Ä‘ang lá» Ä‘i tham chiếu vá»›i tên há»ng %s" +msgstr "Ä‘ang bá» qua tham chiếu vá»›i tên há»ng %s" #, c-format msgid "ignoring broken ref %s" -msgstr "Ä‘ang lá» Ä‘i tham chiếu há»ng %s" +msgstr "Ä‘ang bá» qua tham chiếu há»ng %s" #, c-format msgid "format: %%(end) atom missing" -msgstr "định dạng: thiếu nguyên tá» %%(end)" +msgstr "định dạng: thiếu atom %%(end)" #, c-format msgid "malformed object name %s" -msgstr "tên đối tượng dị hình %s" +msgstr "tên đối tượng sai quy cách %s" #, c-format msgid "option `%s' must point to a commit" -msgstr "tùy chá»n “%s†phải chỉ đến má»™t lần chuyển giao" +msgstr "tùy chá»n '%s' phải chỉ đến má»™t lần chuyển giao" msgid "key" msgstr "khóa" @@ -18294,17 +19143,20 @@ msgstr "khóa" msgid "field name to sort on" msgstr "tên trÆ°á»ng cần sắp xếp" +msgid "exclude refs which match pattern" +msgstr "không bao gồm các tham chiếu khá»›p vá»›i mẫu" + #, c-format msgid "not a reflog: %s" msgstr "không phải má»™t reflog: %s" #, c-format msgid "no reflog for '%s'" -msgstr "không reflog cho “%sâ€" +msgstr "không reflog cho '%s'" #, c-format msgid "%s does not point to a valid object!" -msgstr "“%s†không chỉ đến má»™t lần chuyển giao hợp lệ nà o cả!" +msgstr "'%s' không chỉ đến má»™t lần chuyển giao hợp lệ nà o cả!" #, c-format msgid "" @@ -18319,20 +19171,20 @@ msgid "" "\n" "\tgit branch -m <name>\n" msgstr "" -"Sá» dụng “%s†là m tên cho nhánh ban đầu. Tên nhánh mặc định nà y\n" +"Sá» dụng '%s' là m tên cho nhánh ban đầu. Tên nhánh mặc định nà y\n" "có thể thay đổi. Äể cấu hình tên nhánh khởi đầu sá» dụng trong tất cả\n" "kho lÆ°u trữ má»›i của bạn, cái mà sẽ ngăn chặn cảnh báo nà y, gá»i lệnh:\n" "\n" "\tgit config --global init.defaultBranch <tên>\n" "\n" -"Tên thÆ°á»ng được chá»n thay cho “master†là “mainâ€, “trunk†và \n" -"“developmentâ€. Nhánh vừa tạo có thể được đổi tên thông qua lệnh:\n" +"Tên thÆ°á»ng được chá»n thay cho 'master' là 'main', 'trunk' và \n" +"'development'. Nhánh vừa tạo có thể được đổi tên thông qua lệnh:\n" "\n" "\tgit branch -m <tên>\n" #, c-format msgid "could not retrieve `%s`" -msgstr "không thể lấy vỠ“%sâ€" +msgstr "không thể lấy vá» '%s'" #, c-format msgid "invalid branch name: %s = %s" @@ -18340,7 +19192,7 @@ msgstr "tên nhánh không hợp lệ: %s = %s" #, c-format msgid "ignoring dangling symref %s" -msgstr "Ä‘ang lá» Ä‘i tham chiếu má»m thừa %s" +msgstr "Ä‘ang bá» qua tham chiếu má»m thừa %s" #, c-format msgid "log for ref %s has gap after %s" @@ -18356,33 +19208,29 @@ msgstr "nháºt ký cho %s trống rá»—ng" #, 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â€" +msgstr "từ chối cáºp nháºt tham chiếu vá»›i tên sai '%s'" #, c-format msgid "update_ref failed for ref '%s': %s" -msgstr "update_ref bị lá»—i cho ref “%sâ€: %s" +msgstr "update_ref bị lá»—i cho ref '%s': %s" #, c-format msgid "multiple updates for ref '%s' not allowed" -msgstr "không cho phép Ä‘a cáºp nháºt cho tham chiếu “%sâ€" +msgstr "không cho phép Ä‘a cáºp nháºt cho tham chiếu '%s'" msgid "ref updates forbidden inside quarantine environment" msgstr "cáºp nháºt tham chiếu bị cấm trong môi trÆ°á»ng kiểm tra" msgid "ref updates aborted by hook" -msgstr "các cáºp nháºt tham chiếu bị bãi bá» bởi móc" +msgstr "các cáºp nháºt tham chiếu bị huá»· bá» bởi móc" #, c-format msgid "'%s' exists; cannot create '%s'" -msgstr "“%s†sẵn có; không thể tạo “%sâ€" +msgstr "'%s' sẵn có; không thể tạo '%s'" #, c-format msgid "cannot process '%s' and '%s' at the same time" -msgstr "không thể xá» lý “%s†và “%s†cùng má»™t lúc" - -#, c-format -msgid "could not remove reference %s" -msgstr "không thể gỡ bá» tham chiếu: %s" +msgstr "không thể xá» lý '%s' và '%s' cùng má»™t lúc" #, c-format msgid "could not delete reference %s: %s" @@ -18393,12 +19241,83 @@ msgid "could not delete references: %s" msgstr "không thể xóa bá» tham chiếu: %s" #, c-format +msgid "refname is dangerous: %s" +msgstr "tên tham chiếu không an toà n: %s" + +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "thá» ghi tham chiếu '%s' tá»›i đối tượng %s không tồn tại" + +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "thá» ghi đối tượng không phải chuyển giao %s tá»›i nhánh '%s'" + +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"không cho phép Ä‘a cáºp nháºt cho tham chiếu HEAD (bao gồm cả thông qua tham " +"chiếu '%s')" + +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "không thể khoá tham chiếu '%s': không thể phân giải tham chiếu '%s'" + +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "không thể khoá tham chiếu '%s': lá»—i khi Ä‘á»c tham chiếu" + +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"không cho phép Ä‘a cáºp nháºt cho tham chiếu '%s' (bao gồm cả thông qua tham " +"chiếu biểu trÆ°ng '%s')" + +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "không thể lock tham chiếu '%s': tham chiếu đã tồn tại" + +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "không thể lock tham chiếu '%s': không tồn tại tham chiếu nhÆ°ng cần %s" + +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "không thể lock tham chiếu '%s': Ä‘ang ở %s nhÆ°ng cần %s" + +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "reftable: chuẩn bị chuyển giao: %s" + +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "reftable: chuyển giao thất bại: %s" + +#, c-format +msgid "unable to compact stack: %s" +msgstr "không thể nén stack: %s" + +#, c-format +msgid "refname %s not found" +msgstr "không tìm thấy tên tham chiếu %s" + +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "tên tham chiếu %s là tham chiếu biểu trÆ°ng, không há»— trợ sao chép" + +#, c-format msgid "invalid refspec '%s'" -msgstr "refspec không hợp lệ “%sâ€" +msgstr "refspec không hợp lệ '%s'" #, c-format msgid "invalid quoting in push-option value: '%s'" -msgstr "sai trÃch dẫn trong giá trị push-option :“%sâ€" +msgstr "sai trÃch dẫn trong giá trị push-option :'%s'" + +#, c-format +msgid "unknown value for object-format: %s" +msgstr "không hiểu giá trị cho object-format: %s" #, c-format msgid "%sinfo/refs not valid: is this a git repository?" @@ -18406,38 +19325,37 @@ msgstr "%sinfo/refs không hợp lệ: đây có phải là má»™t kho git?" msgid "invalid server response; expected service, got flush packet" msgstr "" -"đáp ứng từ máy phục vụ không hợp lệ; cần dịch vụ, nhÆ°ng lại nháºn được gói " -"flush" +"phản hồi từ máy chủ không hợp lệ; cần dịch vụ, nhÆ°ng lại nháºn được gói flush" #, c-format msgid "invalid server response; got '%s'" -msgstr "trả vá» của máy phục vụ không hợp lệ; nháºn được %s" +msgstr "phản hồi từ máy chủ không hợp lệ; nháºn được %s" #, c-format msgid "repository '%s' not found" -msgstr "không tìm thấy kho “%sâ€" +msgstr "không tìm thấy kho '%s'" #, c-format msgid "Authentication failed for '%s'" -msgstr "Xác thá»±c gặp lá»—i cho “%sâ€" +msgstr "Xác thá»±c gặp lá»—i cho '%s'" #, c-format msgid "unable to access '%s' with http.pinnedPubkey configuration: %s" -msgstr "không thể truy cáºp “%s†vá»›i cấu hình http.pinnedPubkey: %s" +msgstr "không thể truy cáºp '%s' vá»›i cấu hình http.pinnedPubkey: %s" #, c-format msgid "unable to access '%s': %s" -msgstr "không thể truy cáºp “%sâ€: %s" +msgstr "không thể truy cáºp '%s': %s" #, c-format msgid "redirecting to %s" msgstr "chuyển hÆ°á»›ng đến %s" msgid "shouldn't have EOF when not gentle on EOF" -msgstr "không nên có EOF khi không gentle trên EOF" +msgstr "không nên có EOF khi không thể xá» lý EOF" msgid "remote server sent unexpected response end packet" -msgstr "máy phục vụ gá»i gói kết thúc không cần" +msgstr "máy chủ gá»i gói kết thúc bất thÆ°á»ng" msgid "unable to rewind rpc post data - try increasing http.postBuffer" msgstr "không thể tua lại dữ liệu post rpc - thá» tăng http.postBuffer" @@ -18454,15 +19372,15 @@ msgid "RPC failed; %s" msgstr "RPC gặp lá»—i; %s" msgid "cannot handle pushes this big" -msgstr "không thể xá» lý đẩy cái lá»›n nà y" +msgstr "không thể xá» lý đẩy lá»›n cỡ nà y" #, c-format msgid "cannot deflate request; zlib deflate error %d" -msgstr "không thể giải nén yêu cầu; có lá»—i khi giải nén của zlib %d" +msgstr "không thể giải nén yêu cầu; lá»—i zlib deflate %d" #, c-format msgid "cannot deflate request; zlib end error %d" -msgstr "không thể giải nén yêu cầu; có lá»—i ở cuối %d" +msgstr "không thể giải nén yêu cầu; lá»—i zlib end %d" #, c-format msgid "%d bytes of length header were received" @@ -18483,12 +19401,19 @@ msgstr "không thể lấy vá» bằng sha1 thông qua smart http" #, c-format msgid "protocol error: expected sha/ref, got '%s'" -msgstr "lá»—i giao thức: cần sha/ref, nhÆ°ng lại nháºn được “%sâ€" +msgstr "lá»—i giao thức: cần sha/ref, nhÆ°ng lại nháºn được '%s'" #, c-format msgid "http transport does not support %s" msgstr "váºn chuyển http không há»— trợ %s" +msgid "protocol error: expected '<url> <path>', missing space" +msgstr "lá»—i giao thức: cần '<url> <path>', thiếu dấu cách" + +#, c-format +msgid "failed to download file at URL '%s'" +msgstr "gặp lá»—i khi tải táºp tin tại URL '%s'" + msgid "git-http-push failed" msgstr "git-http-push gặp lá»—i" @@ -18503,11 +19428,11 @@ msgstr "remote-curl: đã cố gắng fetch mà không có kho ná»™i bá»™" #, c-format msgid "remote-curl: unknown command '%s' from git" -msgstr "remote-curl: không hiểu lệnh “%s†từ git" +msgstr "remote-curl: không hiểu lệnh '%s' từ git" #, c-format msgid "config remote shorthand cannot begin with '/': %s" -msgstr "cấu hình viết tắt máy chủ không thể bắt đầu bằng “/â€: %s" +msgstr "cấu hình viết tắt máy chủ không thể bắt đầu bằng '/': %s" msgid "more than one receivepack given, using the first" msgstr "đã Ä‘Æ°a ra nhiá»u hÆ¡n má»™t gói nháºn vá», Ä‘ang sá» dụng cái đầu tiên" @@ -18537,19 +19462,19 @@ msgstr "%s theo dõi cả %s và %s" #, c-format msgid "key '%s' of pattern had no '*'" -msgstr "khóa “%s†của mẫu k có “*â€" +msgstr "khóa '%s' của mẫu k có '*'" #, c-format msgid "value '%s' of pattern has no '*'" -msgstr "giá trị “%s†của mẫu k có “*â€" +msgstr "giá trị '%s' của mẫu k có '*'" #, c-format msgid "src refspec %s does not match any" -msgstr "refspec %s nguồn không khá»›p bất kỳ cái gì" +msgstr "refspec (đặc tả tham chiếu) nguồn %s không khá»›p bất kỳ cái gì" #, c-format msgid "src refspec %s matches more than one" -msgstr "refspec %s nguồn khá»›p nhiá»u hÆ¡n má»™t" +msgstr "refspec (đặc tả tham chiếu) nguồn %s khá»›p nhiá»u hÆ¡n má»™t" #. TRANSLATORS: "matches '%s'%" is the <dst> part of "git push #. <remote> <src>:<dst>" push, and "being pushed ('%s')" is @@ -18567,17 +19492,16 @@ msgid "" "\n" "Neither worked, so we gave up. You must fully qualify the ref." msgstr "" -"ÄÃch bạn đã cung cấp không phải tên tham chiếu đầy đủ (tức là \n" -"bắt đầu bằng \"refs/\"). Chúng tôi đã cố suy luáºn rằng ý của bạn là :\n" +"ÄÃch bạn đã cung cấp không phải tên tham chiếu đầy đủ\n" +"(bắt đầu bằng \"refs/\"). Chúng tôi đã thá» Ä‘oán ý của bạn theo hai cách:\n" "\n" -"- Tìm kiếm má»™t tham chiếu mà nó khá»›p “%s†bên phÃa máy chủ.\n" -"- Kiểm tra xem <src> được đẩy lên (“%sâ€)\n" -" là má»™t tham chiếu trong \"refs/{heads,tags}/\". Nếu thế chúng tôi thêm má»™t " -"tiá»n tố\n" -" refs/{heads,tags}/ tÆ°Æ¡ng ứng bên phÃa máy chủ.\n" +"- Tìm kiếm má»™t tham chiếu khá»›p '%s' bên phÃa máy chủ.\n" +"- Kiểm tra xem <nguồn> được đẩy lên ('%s')\n" +" có là má»™t tham chiếu trong \"refs/{heads,tags}/\", và nếu váºy thêm\n" +" tiá»n tố refs/{heads,tags}/ tÆ°Æ¡ng ứng bên phÃa máy chủ.\n" "\n" -"Nếu cả hai là không thể, thì chúng tôi cÅ©ng chịu thua. Bạn phải dùng tham " -"chiếu dạng đầy đủ." +"Vì cả hai Ä‘á»u không thể, chúng tôi chịu. Bạn phải dùng tham chiếu dạng đầy " +"đủ." #, c-format msgid "" @@ -18585,9 +19509,9 @@ msgid "" "Did you mean to create a new branch by pushing to\n" "'%s:refs/heads/%s'?" msgstr "" -"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng lần chuyển giao.\n" +"Phần <src> của đặc tả tham chiếu là má»™t đối tượng lần chuyển giao.\n" "Có phải ý bạn là má»™t tạo má»™t nhánh má»›i bằng cách đẩy lên\n" -"“%s:refs/heads/%sâ€?" +"'%s:refs/heads/%s'?" #, c-format msgid "" @@ -18595,9 +19519,9 @@ msgid "" "Did you mean to create a new tag by pushing to\n" "'%s:refs/tags/%s'?" msgstr "" -"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng thẻ.\n" +"Phần <nguồn> của đặc tả tham chiếu là má»™t đối tượng thẻ.\n" "Có phải ý bạn là má»™t tạo má»™t thẻ má»›i bằng cách đẩy lên\n" -"“%s:refs/tags/%sâ€?" +"'%s:refs/tags/%s'?" #, c-format msgid "" @@ -18605,9 +19529,9 @@ msgid "" "Did you mean to tag a new tree by pushing to\n" "'%s:refs/tags/%s'?" msgstr "" -"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng cây.\n" +"Phần <nguồn> của đặc tả tham chiếu là má»™t đối tượng cây.\n" "Có phải ý bạn là má»™t tạo má»™t cây má»›i bằng cách đẩy lên\n" -"“%s:refs/tags/%sâ€?" +"'%s:refs/tags/%s'?" #, c-format msgid "" @@ -18615,17 +19539,17 @@ msgid "" "Did you mean to tag a new blob by pushing to\n" "'%s:refs/tags/%s'?" msgstr "" -"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng blob.\n" +"Phần <nguồn> của đặc tả tham chiếu là má»™t đối tượng blob.\n" "Có phải ý bạn là má»™t tạo má»™t blob má»›i bằng cách đẩy lên\n" -"“%s:refs/tags/%sâ€?" +"'%s:refs/tags/%s'?" #, c-format msgid "%s cannot be resolved to branch" -msgstr "“%s†không thể được phân giải thà nh nhánh" +msgstr "'%s' không thể được phân giải thà nh nhánh" #, c-format msgid "unable to delete '%s': remote ref does not exist" -msgstr "không thể xóa “%sâ€: tham chiếu trên máy chủ không tồn tại" +msgstr "không thể xóa '%s': tham chiếu trên máy chủ không tồn tại" #, c-format msgid "dst refspec %s matches more than one" @@ -18640,34 +19564,34 @@ msgstr "HEAD không chỉ đến má»™t nhánh nà o cả" #, c-format msgid "no such branch: '%s'" -msgstr "không có nhánh nà o nhÆ° thế: “%sâ€" +msgstr "không có nhánh nà o nhÆ° thế: '%s'" #, c-format msgid "no upstream configured for branch '%s'" -msgstr "không có thượng nguồn được cấu hình cho nhánh “%sâ€" +msgstr "không có thượng nguồn được cấu hình cho nhánh '%s'" #, c-format msgid "upstream branch '%s' not stored as a remote-tracking branch" msgstr "" -"nhánh thượng nguồn “%s†không được lÆ°u lại nhÆ° là má»™t nhánh theo dõi máy chủ" +"nhánh thượng nguồn '%s' không được lÆ°u lại nhÆ° là má»™t nhánh theo dõi máy chủ" #, c-format msgid "push destination '%s' on remote '%s' has no local tracking branch" -msgstr "đẩy lên Ä‘Ãch “%s†trên máy chủ “%s†không có nhánh theo dõi ná»™i bá»™" +msgstr "đẩy lên Ä‘Ãch '%s' trên máy chủ '%s' không có nhánh theo dõi ná»™i bá»™" #, c-format msgid "branch '%s' has no remote for pushing" -msgstr "nhánh “%s†không có máy chủ để đẩy lên" +msgstr "nhánh '%s' không có máy chủ để đẩy lên" #, c-format msgid "push refspecs for '%s' do not include '%s'" -msgstr "đẩy refspecs cho “%s†không bao gồm “%sâ€" +msgstr "đẩy refspecs cho '%s' không bao gồm '%s'" msgid "push has no destination (push.default is 'nothing')" -msgstr "đẩy lên mà không có Ä‘Ãch (push.default là “nothingâ€)" +msgstr "đẩy lên mà không có Ä‘Ãch (push.default là 'nothing')" msgid "cannot resolve 'simple' push to a single destination" -msgstr "không thể phân giải đẩy “đơn giản†đến má»™t Ä‘Ãch Ä‘Æ¡n" +msgstr "không thể phân giải đẩy 'Ä‘Æ¡n giản' đến má»™t Ä‘Ãch Ä‘Æ¡n" #, c-format msgid "couldn't find remote ref %s" @@ -18675,23 +19599,23 @@ 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 thú vị ná»™i bá»™ '%s'" #, c-format msgid "Your branch is based on '%s', but the upstream is gone.\n" msgstr "" -"Nhánh của bạn dá»±a trên cÆ¡ sở là “%sâ€, nhÆ°ng trên thượng nguồn không còn.\n" +"Nhánh của bạn dá»±a trên cÆ¡ sở là '%s', nhÆ°ng trên thượng nguồn không còn.\n" msgid " (use \"git branch --unset-upstream\" to fixup)\n" msgstr " (dùng \" git branch --unset-upstream\" để sá»a)\n" #, c-format msgid "Your branch is up to date with '%s'.\n" -msgstr "Nhánh của bạn đã cáºp nháºt vá»›i “%sâ€.\n" +msgstr "Nhánh của bạn đã cáºp nháºt vá»›i '%s'.\n" #, c-format msgid "Your branch and '%s' refer to different commits.\n" -msgstr "Nhánh của bạn và “%s†tham chiếu đến các lần chuyển giao khác nhau.\n" +msgstr "Nhánh của bạn và '%s' tham chiếu đến các lần chuyển giao khác nhau.\n" #, c-format msgid " (use \"%s\" for details)\n" @@ -18700,7 +19624,7 @@ msgstr " (dùng \"%s\" để biết thêm chi tiết)\n" #, 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] "Nhánh của bạn đứng trÆ°á»›c “%s†%d lần chuyển giao.\n" +msgstr[0] "Nhánh của bạn đứng trÆ°á»›c '%s' %d lần chuyển giao.\n" msgid " (use \"git push\" to publish your local commits)\n" msgstr " (dùng \"git push\" để xuất bản các lần chuyển giao ná»™i bá»™ của bạn)\n" @@ -18710,8 +19634,8 @@ msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n" msgid_plural "" "Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n" msgstr[0] "" -"Nhánh của bạn đứng đằng sau “%s†%d lần chuyển giao, và có thể được chuyển-" -"tiếp-nhanh.\n" +"Nhánh của bạn đứng sau '%s' %d lần chuyển giao, và có thể được chuyển-tiếp-" +"nhanh.\n" msgid " (use \"git pull\" to update your local branch)\n" msgstr " (dùng \"git pull\" để cáºp nháºt nhánh ná»™i bá»™ của bạn)\n" @@ -18724,22 +19648,21 @@ msgid_plural "" "Your branch and '%s' have diverged,\n" "and have %d and %d different commits each, respectively.\n" msgstr[0] "" -"Nhánh của bạn và “%s†bị phân kỳ,\n" -"và có %d và %d lần chuyển giao khác nhau cho từng cái,\n" -"tÆ°Æ¡ng ứng vá»›i má»—i lần.\n" +"Nhánh của bạn và '%s' bị phân kỳ,\n" +"và tÆ°Æ¡ng ứng có %d và %d lần chuyển giao khác nhau cho từng nhánh.\n" -msgid " (use \"git pull\" to merge the remote branch into yours)\n" +msgid "" +" (use \"git pull\" if you want to integrate the remote branch with yours)\n" msgstr "" -" (dùng \"git pull\" để hòa trá»™n nhánh trên máy chủ và o trong nhánh của " -"bạn)\n" +" (dùng \"git pull\" để hòa trá»™n nhánh trên máy chủ và o nhánh của bạn)\n" #, c-format msgid "cannot parse expected object name '%s'" -msgstr "không thể phân tÃch tên đối tượng mong muốn “%sâ€" +msgstr "không thể Ä‘á»c tên đối tượng mong muốn '%s'" #, c-format msgid "cannot strip one component off url '%s'" -msgstr "không thể cắt bá» má»™t thà nh phần ra khá»i “%s†url" +msgstr "không thể cắt bá» má»™t thà nh phần ra khá»i '%s' url" #, c-format msgid "bad replace ref name: %s" @@ -18761,65 +19684,61 @@ msgstr "không thể ghi bản ghi rerere" #, c-format msgid "there were errors while writing '%s' (%s)" -msgstr "gặp lá»—i Ä‘á»c khi Ä‘ang ghi “%s†(%s)" +msgstr "gặp lá»—i Ä‘á»c khi Ä‘ang ghi '%s' (%s)" #, c-format msgid "could not parse conflict hunks in '%s'" -msgstr "không thể phân tÃch các mảnh xung Ä‘á»™t trong “%sâ€" +msgstr "không thể Ä‘á»c các khúc xung Ä‘á»™t trong '%s'" #, c-format msgid "failed utime() on '%s'" -msgstr "gặp lá»—i utime() trên “%sâ€" +msgstr "gặp lá»—i utime() trên '%s'" #, c-format msgid "writing '%s' failed" -msgstr "gặp lá»—i khi Ä‘ang ghi “%sâ€" +msgstr "gặp lá»—i khi Ä‘ang ghi '%s'" #, c-format msgid "Staged '%s' using previous resolution." -msgstr "Äã tạm cất “%s†sá» dụng cách phân giải kế trÆ°á»›c." +msgstr "Äã tạm cất '%s' sá» dụng cách phân giải kế trÆ°á»›c." #, c-format msgid "Recorded resolution for '%s'." -msgstr "Cách giải quyết đã ghi lại cho “%sâ€." +msgstr "Cách giải quyết đã ghi lại cho '%s'." #, c-format msgid "Resolved '%s' using previous resolution." -msgstr "Äã phân giải giải “%s†sá» dụng cách giải quyết kế trÆ°á»›c." +msgstr "Äã phân giải giải '%s' sá» dụng cách giải quyết kế trÆ°á»›c." #, c-format msgid "cannot unlink stray '%s'" -msgstr "không thể unlink stray “%sâ€" +msgstr "không thể unlink stray '%s'" #, c-format msgid "Recorded preimage for '%s'" -msgstr "Preimage đã được ghi lại cho “%sâ€" +msgstr "Preimage đã được ghi lại cho '%s'" #, c-format msgid "failed to update conflicted state in '%s'" -msgstr "gặp lá»—i khi chạy cáºp nháºt trạng thái bị xung Ä‘á»™t trong “%sâ€" +msgstr "gặp lá»—i khi chạy cáºp nháºt trạng thái bị xung Ä‘á»™t trong '%s'" #, c-format msgid "no remembered resolution for '%s'" -msgstr "đừng nhó các giải quyết cho “%sâ€" - -#, c-format -msgid "cannot unlink '%s'" -msgstr "không thể unlink “%sâ€" +msgstr "đừng nhó các giải quyết cho '%s'" #, c-format msgid "Updated preimage for '%s'" -msgstr "Äã cáºp nháºt preimage cho “%sâ€" +msgstr "Äã cáºp nháºt preimage cho '%s'" #, c-format msgid "Forgot resolution for '%s'\n" -msgstr "Quên phân giải cho “%sâ€\n" +msgstr "Quên phân giải cho '%s'\n" msgid "unable to open rr-cache directory" msgstr "không thể mở thÆ° mục rr-cache" msgid "update the index with reused conflict resolution if possible" -msgstr "cáºp nháºt bảng mục lục vá»›i phân giải xung Ä‘á»™t dùng lại nếu được" +msgstr "cáºp nháºt chỉ mục vá»›i phân giải xung Ä‘á»™t dùng lại nếu được" msgid "could not determine HEAD revision" msgstr "không thể dò tìm Ä‘iểm xét duyệt HEAD" @@ -18828,15 +19747,45 @@ msgstr "không thể dò tìm Ä‘iểm xét duyệt HEAD" msgid "failed to find tree of %s" msgstr "gặp lá»—i khi tìm cây của %s" +#, c-format +msgid "unsupported section for hidden refs: %s" +msgstr "không há»— trợ mục cho tham chiếu ẩn: %s" + +msgid "--exclude-hidden= passed more than once" +msgstr "--exclude-hidden= được dùng hÆ¡n má»™t lần" + +#, c-format +msgid "resolve-undo records `%s` which is missing" +msgstr "resolve-undo ghi nháºn '%s' bị thiếu" + +#, c-format +msgid "%s exists but is a symbolic ref" +msgstr "%s có tồn tại nhÆ°ng là tham chiếu biểu trÆ°ng" + +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge yêu cầu tham chiếu ảo MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD hoặc " +"REBASE_HEAD" + +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "không tìm thấy lần chuyển giao ứng vá»›i đối số --ancestry-path %s" + msgid "--unpacked=<packfile> no longer supported" msgstr "--unpacked=<packfile> không còn được há»— trợ nữa" +#, c-format +msgid "invalid option '%s' in --stdin mode" +msgstr "tùy chá»n không hợp lệ '%s' trong chế Ä‘á»™ --stdin" + msgid "your current branch appears to be broken" msgstr "nhánh hiện tại của bạn có vẻ nhÆ° bị há»ng" #, c-format msgid "your current branch '%s' does not have any commits yet" -msgstr "nhánh hiện tại của bạn “%s†không có má»™t lần chuyển giao nà o cả" +msgstr "nhánh hiện tại của bạn '%s' không có má»™t lần chuyển giao nà o cả" msgid "object filtering requires --objects" msgstr "lá»c đối tượng yêu cầu --objects" @@ -18848,13 +19797,210 @@ msgstr "-L vẫn chÆ°a há»— trợ định dạng khác biệt nà o ngoà i -p và msgid "cannot create async thread: %s" 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" + +#, c-format +msgid "could not switch to '%s'" +msgstr "không thể chuyển đến '%s'" + +msgid "need a working directory" +msgstr "cần má»™t thÆ° mục là m việc" + +msgid "Scalar enlistments require a worktree" +msgstr "'Scalar enlistments' cần má»™t cây là m việc" + +#, c-format +msgid "could not configure %s=%s" +msgstr "không thể đóng cấu hình %s=%s" + +msgid "could not configure log.excludeDecoration" +msgstr "không thể cấu hình log.excludeDecoration" + +msgid "could not add enlistment" +msgstr "không thể thêm enlistment" + +msgid "could not set recommended config" +msgstr "không thể đặt cấu hình Ä‘á» nghị" + +msgid "could not turn on maintenance" +msgstr "không thể báºt chế Ä‘á»™ bảo trì" + +msgid "could not start the FSMonitor daemon" +msgstr "không thể khởi chạy tiến trình ná»n FSMonitor" + +msgid "could not turn off maintenance" +msgstr "không thể tắt chế Ä‘á»™ bảo trì" + +msgid "could not remove enlistment" +msgstr "không thể bá» enlistment" + +#, c-format +msgid "remote HEAD is not a branch: '%.*s'" +msgstr "HEAD của máy chủ không phải má»™t nhánh: '%.*s'" + +msgid "failed to get default branch name from remote; using local default" +msgstr "gặp lá»—i khi lấy tên nhánh mặc định từ máy chủ; sá» dụng mặc định ná»™i bá»™" + +msgid "failed to get default branch name" +msgstr "gặp lá»—i khi lấy tên nhánh mặc định" + +msgid "failed to unregister repository" +msgstr "gặp lá»—i khi hủy đăng ký kho chứa" + +msgid "failed to stop the FSMonitor daemon" +msgstr "Gặp lá»—i khi dừng tiến trình ná»n FSMonitor" + +msgid "failed to delete enlistment directory" +msgstr "gặp lá»—i khi xóa thÆ° mục enlistment" + +msgid "branch to checkout after clone" +msgstr "nhánh để checkout sau khi nhân bản" + +msgid "when cloning, create full working directory" +msgstr "khi nhân bản, tạo đầy đủ thÆ° mục là m việc" + +msgid "only download metadata for the branch that will be checked out" +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 "" +"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" +"\t[--[no-]src] <url> [<enlistment>]" +msgstr "" +"scalar clone [--single-branch] [--branch <nhánh-chÃnh>] [--full-clone]\n" +"\t[--[no-]src] <url> [<enlistment>]" + +#, c-format +msgid "cannot deduce worktree name from '%s'" +msgstr "không thể suy diá»…n tên cây là m việc từ '%s'" + +#, c-format +msgid "directory '%s' exists already" +msgstr "thÆ° mục '%s' đã sẵn có" + +#, c-format +msgid "failed to get default branch for '%s'" +msgstr "gặp lá»—i khi lấy nhánh mặc định cho '%s'" + +#, c-format +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 configure '%s'" +msgstr "không thể cấu hình '%s'" + +msgid "partial clone failed; attempting full clone" +msgstr "nhân bản từng phần gặp lá»—i; Ä‘ang cố thá» nhân bản đầy đủ" + +msgid "could not configure for full clone" +msgstr "không thể cấu hình cho nhân bản đầy đủ" + +msgid "scalar diagnose [<enlistment>]" +msgstr "scalar diagnose [<enlistment>]" + +msgid "`scalar list` does not take arguments" +msgstr "`scalar list` không nháºn các tham số" + +msgid "scalar register [<enlistment>]" +msgstr "scalar register [<enlistment>]" + +msgid "reconfigure all registered enlistments" +msgstr "cấu hình má»i enlistments đã đăng ký" + +msgid "scalar reconfigure [--all | <enlistment>]" +msgstr "scalar reconfigure [--all | <enlistment>]" + +msgid "--all or <enlistment>, but not both" +msgstr "--all hoặc <enlistment>, không thể là cả hai" + +#, c-format +msgid "could not remove stale scalar.repo '%s'" +msgstr "không thể xoá scalar.repo đã cÅ© '%s'" + +#, c-format +msgid "removed stale scalar.repo '%s'" +msgstr "đã xoá scalar.repo đã cÅ© '%s'" + +#, c-format +msgid "repository at '%s' has different owner" +msgstr "kho '%s' thuá»™c quyá»n sở hữu của ngÆ°á»i khác" + +#, c-format +msgid "repository at '%s' has a format issue" +msgstr "kho '%s' có vấn đỠđịnh dạng" + +#, c-format +msgid "repository not found in '%s'" +msgstr "không tìm thấy kho trong '%s'" + +#, c-format +msgid "" +"to unregister this repository from Scalar, run\n" +"\tgit config --global --unset --fixed-value scalar.repo \"%s\"" +msgstr "" +"để bỠđăng ký kho nà y khá»i Scalar, chạy lệnh\n" +"\tgit config --global --unset --fixed-value scalar.repo \"%s\"" + +msgid "" +"scalar run <task> [<enlistment>]\n" +"Tasks:\n" +msgstr "" +"scalar run <task> [<enlistment>]\n" +"Nhiệm vụ:\n" + +#, c-format +msgid "no such task: '%s'" +msgstr "không có nhiệm vụ nà o nhÆ° thế: '%s'" + +msgid "scalar unregister [<enlistment>]" +msgstr "scalar unregister [<enlistment>]" + +msgid "scalar delete <enlistment>" +msgstr "scalar delete <enlistment>" + +msgid "refusing to delete current working directory" +msgstr "từ chối gỡ bá» thÆ° mục là m việc hiện tại" + +msgid "include Git version" +msgstr "bao gồm phiên bản Git" + +msgid "include Git's build options" +msgstr "bao gồm các tùy chá»n biên dịch của Git" + +msgid "scalar verbose [-v | --verbose] [--build-options]" +msgstr "scalar verbose [-v | --verbose] [--build-options]" + +msgid "-C requires a <directory>" +msgstr "-C cần má»™t <thÆ°_mục>" + +#, c-format +msgid "could not change to '%s'" +msgstr "không thể chuyển sang '%s'" + +msgid "-c requires a <key>=<value> argument" +msgstr "-c cần má»™t tham số <key>=<value>" + +msgid "" +"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n" +"\n" +"Commands:\n" +msgstr "" +"scalar [-C </thÆ°/mục/>] [-c <khóa>=<giá trị>] <lệnh> [<các tùy chá»n>]\n" +"\n" +"Các lệnh:\n" + msgid "unexpected flush packet while reading remote unpack status" msgstr "" -"gặp gói flush không cần trong khi Ä‘á»c tình trạng giải nén gói trên máy chủ" +"gặp gói flush bất thÆ°á»ng trong khi Ä‘á»c tình trạng giải nén gói trên máy chủ" #, c-format msgid "unable to parse remote unpack status: %s" -msgstr "không thể phân tÃch tình trạng unpack máy chủ: %s" +msgstr "không thể Ä‘á»c tình trạng unpack máy chủ: %s" #, c-format msgid "remote unpack failed: %s" @@ -18890,11 +20036,11 @@ msgstr "kết thúc nháºn không há»— trợ các tùy chá»n của lệnh push" #, c-format msgid "invalid commit message cleanup mode '%s'" -msgstr "chế Ä‘á»™ dá»n dẹp ghi chú các lần chuyển giao không hợp lệ “%sâ€" +msgstr "chế Ä‘á»™ dá»n dẹp ghi chú các lần chuyển giao không hợp lệ '%s'" #, c-format msgid "could not delete '%s'" -msgstr "không thể xóa bỠ“%sâ€" +msgstr "không thể xóa bá» '%s'" msgid "revert" msgstr "hoà n nguyên" @@ -18910,11 +20056,25 @@ msgid "unknown action: %d" msgstr "không nháºn ra thao tác: %d" 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 "" +"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" +"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\"." + +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" "sau khi giải quyết các xung Ä‘á»™t, đánh dấu Ä‘Æ°á»ng dẫn đã sá»a\n" -"vá»›i lệnh “git add </các/Ä‘Æ°á»ng/dẫn>†hoặc “git rm </các/Ä‘Æ°á»ng/dẫn>â€" +"vá»›i lệnh 'git add </các/Ä‘Æ°á»ng/dẫn>' hoặc 'git rm </các/Ä‘Æ°á»ng/dẫn>'" msgid "" "After resolving the conflicts, mark them with\n" @@ -18928,7 +20088,7 @@ msgstr "" "\"git add/rm <pathspec>\", sai đó chạy\n" "\"git cherry-pick --continue\".\n" "Bạn có thể bá» qua lần chuyển giao nà y vá»›i \"git cherry-pick --skip\".\n" -"Äể bãi bá» và quay trở lại trạng thái trÆ°á»›c khi \"git cherry-pick\",\n" +"Äể huá»· bá» và quay trở lại trạng thái trÆ°á»›c khi \"git cherry-pick\",\n" "chạy \"git cherry-pick --abort\"." msgid "" @@ -18943,24 +20103,20 @@ msgstr "" "\"git add/rm <đặc_tả_Ä‘Æ°á»ng_dẫn_xung_Ä‘á»™t>\", sau đó chạy\n" "\"git revert --continue\".\n" "Bạn có thể bá» qua lần chuyển giao nà y vá»›i \"git rebase --skip\".\n" -"Äể bãi bá» và quay trở lại trạng thái trÆ°á»›c \"git revert\",\n" +"Äể huá»· bá» và quay trở lại trạng thái trÆ°á»›c \"git revert\",\n" "chạy \"git revert --abort\"." #, c-format msgid "could not lock '%s'" -msgstr "không thể khóa “%sâ€" - -#, c-format -msgid "could not write to '%s'" -msgstr "không thể ghi và o “%sâ€" +msgstr "không thể khóa '%s'" #, c-format msgid "could not write eol to '%s'" -msgstr "không thể ghi eol và o “%sâ€" +msgstr "không thể ghi eol và o '%s'" #, c-format msgid "failed to finalize '%s'" -msgstr "gặp lá»—i khi hoà n thà nh “%sâ€" +msgstr "gặp lá»—i khi hoà n thà nh '%s'" #, c-format msgid "your local changes would be overwritten by %s." @@ -18969,16 +20125,12 @@ msgstr "các thay đổi ná»™i bá»™ của bạn có thể bị ghi đè bởi lá msgid "commit your changes or stash them to proceed." msgstr "chuyển giao các thay đổi của bạn hay tạm cất (stash) chúng để xá» lý." -#, c-format -msgid "%s: fast-forward" -msgstr "%s: chuyển-tiếp-nhanh" - #. TRANSLATORS: %s will be "revert", "cherry-pick" or #. "rebase". #. #, c-format msgid "%s: Unable to write new index file" -msgstr "%s: Không thể ghi táºp tin lÆ°u bảng mục lục má»›i" +msgstr "%s: Không thể ghi táºp tin chỉ mục má»›i" msgid "unable to update cache tree" msgstr "không thể cáºp nháºt cây bá»™ nhá»› đệm" @@ -18988,33 +20140,33 @@ msgstr "không thể phân giải lần chuyển giao HEAD" #, c-format msgid "no key present in '%.*s'" -msgstr "không có khóa hiện diện trong “%.*sâ€" +msgstr "không có khóa hiện diện trong '%.*s'" #, c-format msgid "unable to dequote value of '%s'" -msgstr "không thể giải trÃch dẫn giá trị của “%sâ€" +msgstr "không thể giải trÃch dẫn giá trị của '%s'" msgid "'GIT_AUTHOR_NAME' already given" -msgstr "“GIT_AUTHOR_NAME†đã sẵn Ä‘Æ°a ra rồi" +msgstr "'GIT_AUTHOR_NAME' đã sẵn Ä‘Æ°a ra rồi" msgid "'GIT_AUTHOR_EMAIL' already given" -msgstr "“GIT_AUTHOR_EMAIL†đã sẵn Ä‘Æ°a ra rồi" +msgstr "'GIT_AUTHOR_EMAIL' đã sẵn Ä‘Æ°a ra rồi" msgid "'GIT_AUTHOR_DATE' already given" -msgstr "“GIT_AUTHOR_DATE†đã sẵn Ä‘Æ°a ra rồi" +msgstr "'GIT_AUTHOR_DATE' đã sẵn Ä‘Æ°a ra rồi" #, c-format msgid "unknown variable '%s'" -msgstr "không hiểu biến “%sâ€" +msgstr "không hiểu biến '%s'" msgid "missing 'GIT_AUTHOR_NAME'" -msgstr "thiếu “GIT_AUTHOR_NAMEâ€" +msgstr "thiếu 'GIT_AUTHOR_NAME'" msgid "missing 'GIT_AUTHOR_EMAIL'" -msgstr "thiếu “GIT_AUTHOR_EMAILâ€" +msgstr "thiếu 'GIT_AUTHOR_EMAIL'" msgid "missing 'GIT_AUTHOR_DATE'" -msgstr "thiếu “GIT_AUTHOR_DATEâ€" +msgstr "thiếu 'GIT_AUTHOR_DATE'" #, c-format msgid "" @@ -19045,7 +20197,7 @@ msgstr "" " git rebase --continue\n" msgid "'prepare-commit-msg' hook failed" -msgstr "móc “prepare-commit-msg†bị lá»—i" +msgstr "móc 'prepare-commit-msg' bị lá»—i" msgid "" "Your name and email address were configured automatically based\n" @@ -19108,8 +20260,7 @@ msgid "couldn't look up newly created commit" msgstr "không thể tìm thấy lần chuyển giao má»›i hÆ¡n đã được tạo" msgid "could not parse newly created commit" -msgstr "" -"không thể phân tÃch cú pháp của đối tượng chuyển giao má»›i hÆ¡n đã được tạo" +msgstr "không hiểu cú pháp của đối tượng chuyển giao má»›i hÆ¡n đã được tạo" msgid "unable to resolve HEAD after creating commit" msgstr "không thể phân giải HEAD sau khi tạo lần chuyển giao" @@ -19121,37 +20272,33 @@ msgid " (root-commit)" msgstr " (root-commit)" msgid "could not parse HEAD" -msgstr "không thể phân tÃch HEAD" +msgstr "không thể Ä‘á»c HEAD" #, c-format msgid "HEAD %s is not a commit!" msgstr "HEAD %s không phải là má»™t lần chuyển giao!" msgid "unable to parse commit author" -msgstr "không thể phân tÃch tác giả của lần chuyển giao" +msgstr "không thể Ä‘á»c tác giả của lần chuyển giao" #, c-format msgid "unable to read commit message from '%s'" -msgstr "không thể Ä‘á»c phần chú thÃch (message) từ “%sâ€" +msgstr "không thể Ä‘á»c phần chú thÃch từ '%s'" #, c-format msgid "invalid author identity '%s'" -msgstr "định danh tác giả không hợp lệ “%sâ€" +msgstr "danh tÃnh tác giả không hợp lệ '%s'" msgid "corrupt author: missing date information" -msgstr "tác giả sai há»ng: thiếu thông tin ngà y tháng" +msgstr "há»ng tên tác giả: thiếu thông tin ngà y tháng" #, c-format msgid "could not update %s" msgstr "không thể cáºp nháºt %s" #, c-format -msgid "could not parse commit %s" -msgstr "không thể phân tÃch lần chuyển giao %s" - -#, c-format msgid "could not parse parent commit %s" -msgstr "không thể phân tÃch lần chuyển giao cha mẹ “%sâ€" +msgstr "không thể Ä‘á»c lần chuyển giao mẹ '%s'" #, c-format msgid "unknown command: %d" @@ -19162,14 +20309,14 @@ msgstr "Äây là chú thÃch cho lần chuyển giao thứ nhất:" #, c-format msgid "This is the commit message #%d:" -msgstr "Äây là chú thÃch cho lần chuyển giao thứ #%d:" +msgstr "Äây là chú thÃch cho lần chuyển giao thứ %d:" msgid "The 1st commit message will be skipped:" msgstr "Chú thÃch cho lần chuyển giao thứ nhất sẽ bị bá» qua:" #, c-format msgid "The commit message #%d will be skipped:" -msgstr "Chú thÃch cho lần chuyển giao thứ #%d sẽ bị bá» qua:" +msgstr "Chú thÃch cho lần chuyển giao thứ %d sẽ bị bá» qua:" #, c-format msgid "This is a combination of %d commits." @@ -19177,7 +20324,7 @@ msgstr "Äây là tổ hợp của %d lần chuyển giao." #, c-format msgid "cannot write '%s'" -msgstr "không thể ghi “%sâ€" +msgstr "không thể ghi '%s'" msgid "need a HEAD to fixup" msgstr "cần má»™t HEAD để sá»a" @@ -19186,21 +20333,22 @@ msgid "could not read HEAD" msgstr "không thể Ä‘á»c HEAD" msgid "could not read HEAD's commit message" -msgstr "không thể Ä‘á»c phần chú thÃch (message) của HEAD" +msgstr "không thể Ä‘á»c phần chú thÃch của HEAD" #, c-format msgid "could not read commit message of %s" -msgstr "không thể Ä‘á»c phần chú thÃch (message) của %s" +msgstr "không thể Ä‘á»c phần chú thÃch của %s" msgid "your index file is unmerged." -msgstr "táºp tin lÆ°u mục lục của bạn không được hòa trá»™n." +msgstr "táºp tin chỉ mục của bạn không được hòa trá»™n." msgid "cannot fixup root commit" msgstr "không thể sá»a chữa lần chuyển giao gốc" #, c-format msgid "commit %s is a merge but no -m option was given." -msgstr "lần chuyển giao %s là má»™t lần hòa trá»™n nhÆ°ng không Ä‘Æ°a ra tùy chá»n -m." +msgstr "" +"lần chuyển giao %s là má»™t lần hòa trá»™n nhÆ°ng lệnh không có tùy chá»n -m." #, c-format msgid "commit %s does not have parent %d" @@ -19214,35 +20362,43 @@ msgstr "không thể lấy ghi chú lần chuyển giao cho %s" #. "revert" or "pick", the second %s a SHA1. #, c-format msgid "%s: cannot parse parent commit %s" -msgstr "%s: không thể phân tÃch lần chuyển giao mẹ của %s" - -#, c-format -msgid "could not rename '%s' to '%s'" -msgstr "không thể đổi tên “%s†thà nh “%sâ€" +msgstr "%s: không thể Ä‘á»c lần chuyển giao mẹ của %s" #, c-format msgid "could not revert %s... %s" -msgstr "không thể hoà n nguyên %s… %s" +msgstr "không thể hoà n nguyên %s... %s" #, c-format msgid "could not apply %s... %s" -msgstr "không thể áp dụng miếng vá %s… %s" +msgstr "không thể áp dụng bản vá %s... %s" #, c-format msgid "dropping %s %s -- patch contents already upstream\n" -msgstr "xóa %s %s -- vá ná»™i dung thượng nguồn đã có\n" +msgstr "xóa %s %s -- thượng nguồn đã có bản vá\n" #, c-format msgid "git %s: failed to read the index" -msgstr "git %s: gặp lá»—i Ä‘á»c bảng mục lục" +msgstr "git %s: gặp lá»—i khi Ä‘á»c chỉ mục" #, c-format msgid "git %s: failed to refresh the index" -msgstr "git %s: gặp lá»—i khi là m tÆ°Æ¡i má»›i bảng mục lục" +msgstr "git %s: gặp lá»—i khi là m má»›i chỉ mục" #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s không nháºn các đối số: “%sâ€" +msgid "'%s' is not a valid label" +msgstr "'%s' không phải má»™t nhãn hợp lệ" + +#, c-format +msgid "'%s' is not a valid refname" +msgstr "'%s' không phải tên tham chiếu hợp lệ" + +#, c-format +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 "invalid command '%.*s'" +msgstr "lệnh không hợp lệ '%.*s'" #, c-format msgid "missing arguments for %s" @@ -19250,7 +20406,7 @@ msgstr "thiếu đối số cho %s" #, c-format msgid "could not parse '%s'" -msgstr "không thể phân tÃch cú pháp “%sâ€" +msgstr "không thể Ä‘á»c '%s'" #, c-format msgid "invalid line %d: %.*s" @@ -19258,7 +20414,7 @@ msgstr "dòng không hợp lệ %d: %.*s" #, c-format msgid "cannot '%s' without a previous commit" -msgstr "không thể “%s†thể mà không có lần chuyển giao kế trÆ°á»›c" +msgstr "không thể '%s' thể mà không có lần chuyển giao kế trÆ°á»›c" msgid "cancelling a cherry picking in progress" msgstr "Ä‘ang hủy bá» thao tác cherry pick Ä‘ang thá»±c hiện" @@ -19267,30 +20423,30 @@ msgid "cancelling a revert in progress" msgstr "Ä‘ang hủy bá» các thao tác hoà n nguyên Ä‘ang thá»±c hiện" msgid "please fix this using 'git rebase --edit-todo'." -msgstr "vui lòng sá»a lá»—i nà y bằng cách dùng “git rebase --edit-todoâ€." +msgstr "vui lòng sá»a lá»—i nà y bằng cách dùng 'git rebase --edit-todo'." #, c-format msgid "unusable instruction sheet: '%s'" -msgstr "bảng chỉ thị không thể dùng được: %s" +msgstr "bảng chỉ thị không dùng được: %s" msgid "no commits parsed." -msgstr "không có lần chuyển giao nà o được phân tÃch." +msgstr "không Ä‘á»c được lần chuyển giao nà o." msgid "cannot cherry-pick during a revert." -msgstr "không thể cherry-pick trong khi hoà n nguyên." +msgstr "không thể cherry-pick trong khi Ä‘ang hoà n nguyên." msgid "cannot revert during a cherry-pick." -msgstr "không thể thá»±c hiện việc hoà n nguyên trong khi Ä‘ang cherry-pick." +msgstr "không thể hoà n nguyên trong khi Ä‘ang cherry-pick." msgid "unusable squash-onto" -msgstr "squash-onto không dùng được" +msgstr "không dùng được squash-onto" #, c-format msgid "malformed options sheet: '%s'" -msgstr "bảng tùy chá»n dị hình: “%sâ€" +msgstr "bảng tùy chá»n sai quy cách: '%s'" msgid "empty commit set passed" -msgstr "lần chuyển giao trống rá»—ng đặt là hợp quy cách" +msgstr "được chỉ định má»™t lần chuyển giao trống rá»—ng" msgid "revert is already in progress" msgstr "có thao tác hoà n nguyên Ä‘ang được thá»±c hiện" @@ -19300,7 +20456,7 @@ msgid "try \"git revert (--continue | %s--abort | --quit)\"" msgstr "hãy thá» \"git revert (--continue | %s--abort | --quit)\"" msgid "cherry-pick is already in progress" -msgstr "có thao tác “cherry-pick†đang được thá»±c hiện" +msgstr "có thao tác cherry-pick Ä‘ang được thá»±c hiện" #, c-format msgid "try \"git cherry-pick (--continue | %s--abort | --quit)\"" @@ -19308,62 +20464,57 @@ msgstr "hãy thá» \"git cherry-pick (--continue | %s--abort | --quit)\"" #, c-format msgid "could not create sequencer directory '%s'" -msgstr "không thể tạo thÆ° mục xếp dãy “%sâ€" - -msgid "could not lock HEAD" -msgstr "không thể khóa HEAD" +msgstr "không thể tạo thÆ° mục sequencer '%s'" msgid "no cherry-pick or revert in progress" -msgstr "không cherry-pick hay hoà n nguyên trong tiến trình" +msgstr "không có cherry-pick hay hoà n nguyên Ä‘ang được thá»±c hiện" msgid "cannot resolve HEAD" msgstr "không thể phân giải HEAD" msgid "cannot abort from a branch yet to be born" -msgstr "không thể hủy bá» từ má»™t nhánh mà nó còn chÆ°a được tạo ra" +msgstr "không thể hủy bá» từ má»™t nhánh chÆ°a được tạo ra" #, c-format msgid "cannot read '%s': %s" -msgstr "không thể Ä‘á»c “%sâ€: %s" +msgstr "không thể Ä‘á»c '%s': %s" msgid "unexpected end of file" msgstr "gặp kết thúc táºp tin Ä‘á»™t xuất" #, c-format msgid "stored pre-cherry-pick HEAD file '%s' is corrupt" -msgstr "táºp tin HEAD “pre-cherry-pick†đã lÆ°u “%s†bị há»ng" +msgstr "táºp tin HEAD trÆ°á»›c cherry-pick '%s' bị há»ng" msgid "You seem to have moved HEAD. Not rewinding, check your HEAD!" -msgstr "" -"Bạn có lẽ đã có HEAD đã bị di chuyển Ä‘i, Không thể tua, kiểm tra HEAD của " -"bạn!" +msgstr "Bạn có lẽ đã di chuyển HEAD, Không thể quay lại, hãy kiểm tra HEAD!" msgid "no revert in progress" -msgstr "không có tiến trình hoà n nguyên nà o" +msgstr "không có hoà n nguyên nà o Ä‘ang được thá»±c hiện" msgid "no cherry-pick in progress" msgstr "không có cherry-pick Ä‘ang được thá»±c hiện" msgid "failed to skip the commit" -msgstr "gặp lá»—i khi bá» qua đối tượng chuyển giao" +msgstr "gặp lá»—i khi bá» qua lần chuyển giao" msgid "there is nothing to skip" -msgstr "ở đây không có gì để mà bá» qua cả" +msgstr "ở đây không có gì để bá» qua" #, c-format msgid "" "have you committed already?\n" "try \"git %s --continue\"" msgstr "" -"bạn đã sẵn sà ng chuyển giao chÆ°a?\n" -"thá» \"git %s --continue\"" +"hình nhÆ° bạn đã bắt đầu chuyển giao rồi?\n" +"thá» chạy \"git %s --continue\"" msgid "cannot read HEAD" msgstr "không thể Ä‘á»c HEAD" #, c-format msgid "unable to copy '%s' to '%s'" -msgstr "không thể chép “%s†sang “%sâ€" +msgstr "không thể sao chép '%s' sang '%s'" #, c-format msgid "" @@ -19375,21 +20526,21 @@ msgid "" "\n" " git rebase --continue\n" msgstr "" -"Bạn có thể tu bổ lần chuyển giao ngay bây giá» bằng:\n" +"Bạn có thể tu bổ lần chuyển giao bằng:\n" "\n" " git commit --amend %s\n" "\n" -"Má»™t khi đã hà i lòng vá»›i những thay đổi của mình, thì chạy:\n" +"Sau khi hà i lòng vá»›i những thay đổi của mình, hãy chạy:\n" "\n" " git rebase --continue\n" #, c-format msgid "Could not apply %s... %.*s" -msgstr "Không thể áp dụng %s… %.*s" +msgstr "Không thể áp dụng %s... %.*s" #, c-format msgid "Could not merge %.*s" -msgstr "Không hòa trá»™n %.*s" +msgstr "Không thể hòa trá»™n %.*s" #, c-format msgid "Executing: %s\n" @@ -19404,33 +20555,37 @@ msgid "" "\n" msgstr "" "thá»±c thi gặp lá»—i: %s\n" -"%sBạn có thể sá»a các trục trặc, và sau đó chạy lệnh\n" +"%sBạn có thể sá»a lại, và sau đó chạy lệnh\n" "\n" " git rebase --continue\n" "\n" -msgid "and made changes to the index and/or the working tree\n" -msgstr "và tạo các thay đổi bảng mục lục và /hay cây là m việc\n" +msgid "and made changes to the index and/or the working tree.\n" +msgstr "và thay đổi chỉ mục hay cây là m việc\n" #, c-format msgid "" "execution succeeded: %s\n" -"but left changes to the index and/or the working tree\n" +"but left changes to the index and/or the working tree.\n" "Commit or stash your changes, and then run\n" "\n" " git rebase --continue\n" "\n" msgstr "" "thá»±c thi thà nh công: %s\n" -"nhÆ°ng còn các thay đổi trong mục lục và /hoặc cây là m việc\n" -"Chuyển giao hay tạm cất các thay đổi nà y Ä‘i, rồi chạy\n" +"nhÆ°ng còn các thay đổi trong chỉ mục hay cây là m việc.\n" +"Hãy chuyển giao hay tạm cất các thay đổi nà y, rồi chạy\n" "\n" " git rebase --continue\n" "\n" #, c-format msgid "illegal label name: '%.*s'" -msgstr "tên nhãn dị hình: “%.*sâ€" +msgstr "tên nhãn không hợp lệ: '%.*s'" + +#, c-format +msgid "could not resolve '%s'" +msgstr "không thể phân giải '%s'" msgid "writing fake root commit" msgstr "ghi lần chuyển giao gốc giả" @@ -19438,45 +20593,63 @@ msgstr "ghi lần chuyển giao gốc giả" msgid "writing squash-onto" msgstr "Ä‘ang ghi squash-onto" -#, c-format -msgid "could not resolve '%s'" -msgstr "không thể phân giải “%sâ€" - msgid "cannot merge without a current revision" -msgstr "không thể hòa trá»™n mà không có má»™t Ä‘iểm xét duyệt hiện tại" +msgstr "không thể hòa trá»™n mà không có Ä‘iểm hiệu chỉnh hiện tại" #, c-format msgid "unable to parse '%.*s'" -msgstr "không thể phân tÃch “%.*sâ€" +msgstr "không thể Ä‘á»c '%.*s'" #, c-format msgid "nothing to merge: '%.*s'" -msgstr "chẳng có gì để hòa trá»™n: “%.*sâ€" +msgstr "chẳng có gì để hòa trá»™n: '%.*s'" msgid "octopus merge cannot be executed on top of a [new root]" -msgstr "hòa trá»™n octopus không thể được thá»±c thi trên đỉnh của má»™t [new root]" +msgstr "" +"hòa trá»™n kiểu bạch tuá»™c không thể được thá»±c thi trên đỉnh của [new root]" #, c-format msgid "could not get commit message of '%s'" -msgstr "không thể lấy chú thÃch của lần chuyển giao của “%sâ€" +msgstr "không thể lấy chú thÃch của lần chuyển giao của '%s'" #, c-format msgid "could not even attempt to merge '%.*s'" -msgstr "không thể ngay cả khi thá» hòa trá»™n “%.*sâ€" +msgstr "hoà n toà n không thể hòa trá»™n '%.*s'" msgid "merge: Unable to write new index file" -msgstr "merge: Không thể ghi táºp tin lÆ°u bảng mục lục má»›i" +msgstr "merge: Không thể ghi táºp tin chỉ mục má»›i" + +#, c-format +msgid "" +"another 'rebase' process appears to be running; '%s.lock' already exists" +msgstr "Má»™t lần cải tổ khác Ä‘ang diá»…n ra; %s.lock đã tồn tại" + +#, c-format +msgid "" +"Updated the following refs with %s:\n" +"%s" +msgstr "" +"Äã cáºp nháºt các tham chiếu sau thà nh %s:\n" +"%s" + +#, c-format +msgid "" +"Failed to update the following refs with %s:\n" +"%s" +msgstr "" +"Không thể cáºp nháºt các tham chiếu sau thà nh %s:\n" +"%s" msgid "Cannot autostash" msgstr "Không thể autostash" #, c-format msgid "Unexpected stash response: '%s'" -msgstr "Gặp đáp ứng stash không cần: “%sâ€" +msgstr "Gặp phản hồi stash bất thÆ°á»ng '%s'" #, c-format msgid "Could not create directory for '%s'" -msgstr "Không thể tạo thÆ° mục cho “%sâ€" +msgstr "Không thể tạo thÆ° mục cho '%s'" #, c-format msgid "Created autostash: %s\n" @@ -19491,7 +20664,7 @@ msgstr "Äã áp dụng autostash.\n" #, c-format msgid "cannot store %s" -msgstr "không thá» lÆ°u “%sâ€" +msgstr "không thể lÆ°u '%s'" #, c-format msgid "" @@ -19500,16 +20673,19 @@ msgid "" "You can run \"git stash pop\" or \"git stash drop\" at any time.\n" msgstr "" "%s\n" -"Các thay đổi của bạn an toà n trong stash (tạm cất Ä‘i).\n" +"Các thay đổi của bạn an toà n trong tạm cất.\n" "Bạn có thể chạy lệnh \"git stash pop\" hay \"git stash drop\" bất kỳ lúc " "nà o.\n" msgid "Applying autostash resulted in conflicts." -msgstr "Ãp dụng autostash có hiệu quả trong các xung Ä‘á»™t." +msgstr "Ãp dụng autostash đã gây nên xung Ä‘á»™t." msgid "Autostash exists; creating a new stash entry." msgstr "Autostash đã sẵn có; nên tạo má»™t mục stash má»›i." +msgid "autostash reference is a symref" +msgstr "tham chiếu autostash là symref" + msgid "could not detach HEAD" msgstr "không thể tách rá»i HEAD" @@ -19535,19 +20711,19 @@ msgstr "" "Không thể thá»±c thi lệnh todo\n" "\n" " %.*s\n" -"Nó đã được lên lịch lại: Äể sá»a lệnh trÆ°á»›c khi tiếp tục, vui lòng\n" +"Lệnh đã được lên lịch lại. Äể sá»a lệnh trÆ°á»›c khi tiếp tục, vui lòng\n" "sá»a danh sách todo trÆ°á»›c:\n" "\n" " git rebase --edit-todo\n" " git rebase --continue\n" #, c-format -msgid "Rebasing (%d/%d)%s" -msgstr "Äang cải tổ (%d/%d)%s" +msgid "Stopped at %s... %.*s\n" +msgstr "Dừng lại ở %s... %.*s\n" #, c-format -msgid "Stopped at %s... %.*s\n" -msgstr "Dừng lại ở %s… %.*s\n" +msgid "Rebasing (%d/%d)%s" +msgstr "Äang cải tổ (%d/%d)%s" #, c-format msgid "unknown command %d" @@ -19557,7 +20733,7 @@ msgid "could not read orig-head" msgstr "không thể Ä‘á»c orig-head" msgid "could not read 'onto'" -msgstr "không thể Ä‘á»c “ontoâ€." +msgstr "không thể Ä‘á»c 'onto'." #, c-format msgid "could not update HEAD to %s" @@ -19571,15 +20747,15 @@ 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." msgid "cannot amend non-existing commit" -msgstr "không thể tu bá» má»™t lần chuyển giao không tồn tại" +msgstr "không thể tu sá»a lần chuyển giao không tồn tại" #, c-format msgid "invalid file: '%s'" -msgstr "táºp tin không hợp lệ: “%sâ€" +msgstr "táºp tin không hợp lệ: '%s'" #, c-format msgid "invalid contents: '%s'" -msgstr "ná»™i dung không hợp lệ: “%sâ€" +msgstr "ná»™i dung không hợp lệ: '%s'" msgid "" "\n" @@ -19588,11 +20764,11 @@ msgid "" msgstr "" "\n" "Bạn có các thay đổi chÆ°a chuyển giao trong thÆ° mục là m việc. Vui lòng\n" -"chuyển giao chúng trÆ°á»›c và sau đó chạy lệnh “git rebase --continue†lần nữa." +"chuyển giao chúng trÆ°á»›c rồi sau đó chạy lệnh 'git rebase --continue'." #, c-format msgid "could not write file: '%s'" -msgstr "không thể ghi táºp tin: “%sâ€" +msgstr "không thể ghi táºp tin: '%s'" msgid "could not remove CHERRY_PICK_HEAD" msgstr "không thể xóa bá» CHERRY_PICK_HEAD" @@ -19602,14 +20778,14 @@ msgstr "không thể chuyển giao các thay đổi đã Ä‘Æ°a lên bệ phóng. #, c-format msgid "%s: can't cherry-pick a %s" -msgstr "%s: không thể cherry-pick má»™t %s" +msgstr "%s: không thể cherry-pick %s" #, c-format msgid "%s: bad revision" -msgstr "%s: Ä‘iểm xét duyệt sai" +msgstr "%s: Ä‘iểm hiệu chỉnh không hợp lệ" msgid "can't revert as initial commit" -msgstr "không thể hoà n nguyên má»™t lần chuyển giao khởi tạo" +msgstr "không thể hoà n nguyên lần chuyển giao khởi tạo" #, c-format msgid "skipped previously applied commit %s" @@ -19629,14 +20805,18 @@ msgid "nothing to do" msgstr "không có gì để là m" msgid "could not skip unnecessary pick commands" -msgstr "không thể bá» qua các lệnh cáºy (pick) không cần thiết" +msgstr "không thể bá» qua các lệnh pick không cần thiết" msgid "the script was already rearranged." -msgstr "văn lệnh đã sẵn được sắp đặt rồi." +msgstr "script đã được sắp đặt rồi." + +#, c-format +msgid "update-refs file at '%s' is invalid" +msgstr "táºp tin update-refs '%s' không hợp lệ" #, c-format msgid "'%s' is outside repository at '%s'" -msgstr "“%s†ngoà i má»™t kho chứa tại “%sâ€" +msgstr "'%s' nằm ngoà i kho chứa tại '%s'" #, c-format msgid "" @@ -19644,8 +20824,8 @@ msgid "" "Use 'git <command> -- <path>...' to specify paths that do not exist locally." msgstr "" "%s: không có Ä‘Æ°á»ng dẫn nà o nhÆ° thế ở trong cây là m việc.\n" -"Dùng “git <lệnh> -- <Ä‘Æ°á»ng/dẫn>…†để chỉ định Ä‘Æ°á»ng dẫn mà nó không tồn tại " -"má»™t cách ná»™i bá»™." +"Dùng 'git <lệnh> -- <Ä‘Æ°á»ng/dẫn>...' để chỉ định Ä‘Æ°á»ng dẫn không tồn tại ná»™i " +"bá»™." #, c-format msgid "" @@ -19653,14 +20833,14 @@ msgid "" "Use '--' to separate paths from revisions, like this:\n" "'git <command> [<revision>...] -- [<file>...]'" msgstr "" -"tham số chÆ°a rõ rà ng “%sâ€: chÆ°a biết Ä‘iểm xem xét hay Ä‘Æ°á»ng dẫn không trong " -"cây là m việc.\n" -"Dùng “--†để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xem xét, nhÆ° thế nà y:\n" -"“git <lệnh> [<Ä‘iểm xem xét>…] -- [<táºp tin>…]â€" +"tham số chÆ°a rõ rà ng '%s': chÆ°a biết Ä‘iểm xét duyệt hay Ä‘Æ°á»ng dẫn không " +"trong cây là m việc.\n" +"Dùng '--' để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xét duyệt, nhÆ° thế nà y:\n" +"'git <lệnh> [<Ä‘iểm xét duyệt>...] -- [<táºp tin>...]'" #, c-format msgid "option '%s' must come before non-option arguments" -msgstr "tùy chá»n “%s†phải trÆ°á»›c các đối số đầu tiên không có tùy chá»n" +msgstr "tùy chá»n '%s' phải trÆ°á»›c các đối số đầu tiên không có tùy chá»n" #, c-format msgid "" @@ -19668,16 +20848,20 @@ msgid "" "Use '--' to separate paths from revisions, like this:\n" "'git <command> [<revision>...] -- [<file>...]'" msgstr "" -"tham số chÆ°a rõ rà ng “%sâ€: cả Ä‘iểm xem xét và tên táºp tin.\n" -"Dùng “--†để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xem xét, nhÆ° thế nà y:\n" -"“git <lệnh> [<Ä‘iểm xem xét>…] -- [<táºp tin>…]â€" +"tham số chÆ°a rõ rà ng '%s': cả Ä‘iểm xem xét và tên táºp tin.\n" +"Dùng '--' để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xem xét, nhÆ° thế nà y:\n" +"'git <lệnh> [<Ä‘iểm xem xét>...] -- [<táºp tin>...]'" msgid "unable to set up work tree using invalid config" -msgstr "không thể cà i đặt thÆ° mục là m việc sá» dụng cấu hình không hợp lệ" +msgstr "không thể thiết láºp thÆ° mục là m việc vá»›i cấu hình không hợp lệ" + +#, c-format +msgid "'%s' already specified as '%s'" +msgstr "'%s' đã được chỉ định là '%s' rồi" #, c-format msgid "Expected git repo version <= %d, found %d" -msgstr "Cần phiên bản kho git <= %d, nhÆ°ng lại nháºn được %d" +msgstr "Cần phiên bản kho git <= %d, nhÆ°ng lại là %d" msgid "unknown repository extension found:" msgid_plural "unknown repository extensions found:" @@ -19685,15 +20869,16 @@ msgstr[0] "tìm thấy phần mở rá»™ng kho chÆ°a biết:" msgid "repo version is 0, but v1-only extension found:" msgid_plural "repo version is 0, but v1-only extensions found:" -msgstr[0] "phiên bản kho là 0, nhÆ°ng lại tìm thấy phần mở rá»™ng chỉ v1:" +msgstr[0] "" +"phiên bản kho là 0, nhÆ°ng lại tìm thấy phần mở rá»™ng chỉ dà nh cho v1:" #, c-format msgid "error opening '%s'" -msgstr "gặp lá»—i khi mở “%sâ€" +msgstr "gặp lá»—i khi mở '%s'" #, c-format msgid "too large to be a .git file: '%s'" -msgstr "táºp tin .git là quá lá»›n: “%sâ€" +msgstr "táºp tin .git quá lá»›n: '%s'" #, c-format msgid "error reading %s" @@ -19701,11 +20886,11 @@ msgstr "gặp lá»—i khi Ä‘á»c %s" #, c-format msgid "invalid gitfile format: %s" -msgstr "định dạng táºp tin git không hợp lệ: %s" +msgstr "định dạng gitfile không hợp lệ: %s" #, c-format msgid "no path in gitfile: %s" -msgstr "không có Ä‘Æ°á»ng dẫn trong táºp tin git: %s" +msgstr "không có Ä‘Æ°á»ng dẫn trong gitfile: %s" #, c-format msgid "not a git repository: %s" @@ -19713,56 +20898,61 @@ msgstr "không phải là kho git: %s" #, c-format msgid "'$%s' too big" -msgstr "“$%s†quá lá»›n" +msgstr "'$%s' quá lá»›n" #, c-format msgid "not a git repository: '%s'" -msgstr "không phải là kho git: “%sâ€" +msgstr "không phải là kho git: '%s'" #, c-format msgid "cannot chdir to '%s'" -msgstr "không thể chdir (chuyển đổi thÆ° mục) sang “%sâ€" +msgstr "không thể chdir (chuyển thÆ° mục) sang '%s'" msgid "cannot come back to cwd" -msgstr "không thể quay lại cwd" +msgstr "không thể quay lại thÆ° mục là m việc hiện hà nh" #, c-format msgid "failed to stat '%*s%s%s'" -msgstr "gặp lá»—i khi lấy thống kê vỠ“%*s%s%sâ€" +msgstr "gặp lá»—i khi stat'%*s%s%s'" msgid "Unable to read current working directory" msgstr "Không thể Ä‘á»c thÆ° mục là m việc hiện hà nh" #, c-format msgid "cannot change to '%s'" -msgstr "không thể chuyển sang “%sâ€" +msgstr "không thể chuyển sang '%s'" #, c-format msgid "not a git repository (or any of the parent directories): %s" -msgstr "không phải là kho git (hoặc bất kỳ thÆ° mục cha mẹ nà o): %s" +msgstr "không phải là kho git (các thÆ° mục cha cÅ©ng không phải): %s" #, c-format msgid "" "not a git repository (or any parent up to mount point %s)\n" "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)." msgstr "" -"không phải là kho git (hay bất kỳ cha mẹ nà o đến táºn Ä‘iểm gắn kết %s)\n" +"không phải là kho git (các thÆ° mục cha dÆ°á»›i Ä‘iểm gắn kết %s cÅ©ng không " +"phải)\n" "Dừng tại biên của hệ thống táºp tin (GIT_DISCOVERY_ACROSS_FILESYSTEM chÆ°a " -"đặt)." +"được đặt)." #, c-format msgid "" -"unsafe repository ('%s' is owned by someone else)\n" -"To add an exception for this directory, call:\n" +"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ữ không an toà n ('%s' thuá»™c sở hữu của ngÆ°á»i khác)\n" -"Äể thêm ngoại lệ cho thÆ° mục nà y, hãy gá»i:\n" +"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')" + +#, c-format msgid "" "problem with core.sharedRepository filemode value (0%.3o).\n" "The owner of files must always have read and write permissions." @@ -19771,17 +20961,107 @@ msgstr "" "ngÆ°á»i sở hữu táºp tin phải luôn có quyá»n Ä‘á»c và ghi." msgid "fork failed" -msgstr "gặp lá»—i khi rẽ nhánh tiến trình" +msgstr "gặp lá»—i khi fork" msgid "setsid failed" msgstr "setsid gặp lá»—i" #, c-format +msgid "cannot stat template '%s'" +msgstr "không thể lấy thông tin vá» mẫu '%s'" + +#, c-format +msgid "cannot opendir '%s'" +msgstr "không thể mở thÆ° mục '%s'" + +#, c-format +msgid "cannot readlink '%s'" +msgstr "không thể Ä‘á»c ná»™i dung liên kết '%s'" + +#, c-format +msgid "cannot symlink '%s' '%s'" +msgstr "không thể tạo liên kết má»m '%s' '%s'" + +#, c-format +msgid "cannot copy '%s' to '%s'" +msgstr "không thể sao chép '%s' sang '%s'" + +#, c-format +msgid "ignoring template %s" +msgstr "Ä‘ang bá» qua mẫu '%s'" + +#, c-format +msgid "templates not found in %s" +msgstr "các mẫu không được tìm thấy trong %s" + +#, c-format +msgid "not copying templates from '%s': %s" +msgstr "không sao chép các mẫu từ '%s': %s" + +#, c-format +msgid "invalid initial branch name: '%s'" +msgstr "tên nhánh khởi tạo không hợp lệ: '%s'" + +#, c-format +msgid "re-init: ignored --initial-branch=%s" +msgstr "re-init: --initial-branch=%s bị bá» qua" + +#, c-format +msgid "unable to handle file type %d" +msgstr "không thể xá» lý (handle) táºp tin kiểu %d" + +#, c-format +msgid "unable to move %s to %s" +msgstr "không di chuyển được %s và o %s" + +msgid "attempt to reinitialize repository with different hash" +msgstr "cố để khởi tạo lại má»™t kho vá»›i kiểu băm dữ liệu khác" + +msgid "" +"attempt to reinitialize repository with different reference storage format" +msgstr "cố khởi tạo lại má»™t kho vá»›i kiểu lÆ°u tham chiếu dữ liệu khác" + +#, c-format +msgid "%s already exists" +msgstr "%s đã có từ trÆ°á»›c rồi" + +#, c-format +msgid "Reinitialized existing shared Git repository in %s%s\n" +msgstr "Äã khởi tạo lại kho Git chia sẻ sẵn có trong %s%s\n" + +#, c-format +msgid "Reinitialized existing Git repository in %s%s\n" +msgstr "Äã khởi tạo lại kho Git sẵn có trong %s%s\n" + +#, c-format +msgid "Initialized empty shared Git repository in %s%s\n" +msgstr "Äã khởi tạo lại kho Git chia sẻ trống rá»—ng sẵn có trong %s%s\n" + +#, c-format +msgid "Initialized empty Git repository in %s%s\n" +msgstr "Äã khởi tạo lại kho Git trống rá»—ng sẵn có trong %s%s\n" + +#, c-format msgid "index entry is a directory, but not sparse (%08x)" -msgstr "mục tin mục lục là má»™t thÆ° mục, nhÆ°ng không \"sparse\" (%08x)" +msgstr "mục tin chỉ mục là má»™t thÆ° mục, nhÆ°ng không \"sparse\" (%08x)" msgid "cannot use split index with a sparse index" -msgstr "không thể sá» dụng bảng mục lục chia tách vá»›i má»™t \"sparse index\"" +msgstr "không thể sá» dụng chỉ mục chia tách vá»›i má»™t \"sparse index\"" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not start with '('" +msgstr "định dạng %s sai: phần tá» '%s' không bắt đầu bằng '('" + +#. TRANSLATORS: The first %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: element '%s' does not end in ')'" +msgstr "định dạng %s sai: phần tá» '%s' không bắt kết thúc bằng ')'" + +#. TRANSLATORS: %s is a command like "ls-tree". +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "định dạng %s sai: %%%.*s" #. TRANSLATORS: IEC 80000-13:2008 gibibyte #, c-format @@ -19826,21 +21106,15 @@ msgid_plural "%u bytes/s" msgstr[0] "%u byte/giây" #, c-format -msgid "could not edit '%s'" -msgstr "không thể sá»a “%sâ€" - -#, c-format msgid "ignoring suspicious submodule name: %s" -msgstr "Ä‘ang lá» Ä‘i tên mô-Ä‘un-con máºp má»: %s" +msgstr "Ä‘ang bá» qua tên mô-Ä‘un-con máºp má»: %s" msgid "negative values not allowed for submodule.fetchJobs" msgstr "không cho phép giá trị âm ở submodule.fetchJobs" #, c-format msgid "ignoring '%s' which may be interpreted as a command-line option: %s" -msgstr "" -"Ä‘ang bá» qua “%s†cái mà có thể được phiên dịch nhÆ° là má»™t tùy chá»n dòng " -"lệnh: %s" +msgstr "Ä‘ang bá» qua '%s' nhÆ°ng có thể được hiểu là tùy chá»n trên dòng lệnh: %s" #, c-format msgid "Could not update .gitmodules entry %s" @@ -19864,11 +21138,11 @@ msgstr "gặp lá»—i khi tổ chức .gitmodules đã cáºp nháºt" #, c-format msgid "in unpopulated submodule '%s'" -msgstr "trong mô-Ä‘un-con không có gì “%sâ€" +msgstr "trong mô-Ä‘un-con không có gì '%s'" #, c-format msgid "Pathspec '%s' is in submodule '%.*s'" -msgstr "Äặc tả Ä‘Æ°á»ng dẫn “%s†thì ở trong mô-Ä‘un-con “%.*sâ€" +msgstr "Äặc tả Ä‘Æ°á»ng dẫn '%s' ở trong mô-Ä‘un-con '%.*s'" #, c-format msgid "bad --ignore-submodules argument: %s" @@ -19879,33 +21153,33 @@ msgid "" "Submodule in commit %s at path: '%s' collides with a submodule named the " "same. Skipping it." msgstr "" -"Mô-Ä‘un-con trong lần chuyển giao %s tại Ä‘Æ°á»ng dẫn: “%s†va chạm vá»›i mô-Ä‘un-" -"con cùng tên. Nên bá» qua nó." +"Mô-Ä‘un-con trong lần chuyển giao %s tại Ä‘Æ°á»ng dẫn: '%s' va chạm vá»›i mô-Ä‘un-" +"con cùng tên. Nên sẽ bá» qua." #, c-format msgid "submodule entry '%s' (%s) is a %s, not a commit" msgstr "" -"mục tin mô-Ä‘un-con “%s†(%s) là má»™t %s, không phải là má»™t lần chuyển giao" +"mục tin mô-Ä‘un-con '%s' (%s) là má»™t %s, không phải là má»™t lần chuyển giao" #, c-format msgid "" "Could not run 'git rev-list <commits> --not --remotes -n 1' command in " "submodule %s" msgstr "" -"Không thể chạy lệnh “git rev-list <các lần chuyển giao> --not --remotes -n " -"1†trong mô-Ä‘un-con “%sâ€" +"Không thể chạy lệnh 'git rev-list <các lần chuyển giao> --not --remotes -n " +"1' trong mô-Ä‘un-con '%s'" #, c-format msgid "process for submodule '%s' failed" -msgstr "xá» lý cho mô-Ä‘un-con “%s†gặp lá»—i" +msgstr "xá» lý cho mô-Ä‘un-con '%s' gặp lá»—i" #, c-format msgid "Pushing submodule '%s'\n" -msgstr "Äẩy lên mô-Ä‘un-con “%sâ€\n" +msgstr "Äẩy lên mô-Ä‘un-con '%s'\n" #, c-format msgid "Unable to push submodule '%s'\n" -msgstr "Không thể đẩy lên mô-Ä‘un-con “%sâ€\n" +msgstr "Không thể đẩy lên mô-Ä‘un-con '%s'\n" #, c-format msgid "Fetching submodule %s%s\n" @@ -19913,11 +21187,11 @@ msgstr "Äang lấy vá» mô-Ä‘un-con %s%s\n" #, c-format msgid "Could not access submodule '%s'\n" -msgstr "Không thể truy cáºp mô-Ä‘un-con “%sâ€\n" +msgstr "Không thể truy cáºp mô-Ä‘un-con '%s'\n" #, c-format msgid "Could not access submodule '%s' at commit %s\n" -msgstr "Không thể truy cáºp mô-Ä‘un-con “%s†ở lần chuyển giao %s\n" +msgstr "Không thể truy cáºp mô-Ä‘un-con '%s' ở lần chuyển giao %s\n" #, c-format msgid "Fetching submodule %s%s at commit %s\n" @@ -19929,65 +21203,65 @@ msgid "" "%s" msgstr "" "Có lá»—i khi lấy vá» mô-Ä‘un-con:\n" -" “%sâ€" +" '%s'" #, c-format msgid "'%s' not recognized as a git repository" -msgstr "không nháºn ra “%s†là má»™t kho git" +msgstr "không nháºn ra '%s' là má»™t kho git" #, c-format msgid "Could not run 'git status --porcelain=2' in submodule %s" -msgstr "Không thể chạy “git status --porcelain=2†trong mô-Ä‘un-con “%sâ€" +msgstr "Không thể chạy 'git status --porcelain=2' trong mô-Ä‘un-con '%s'" #, c-format msgid "'git status --porcelain=2' failed in submodule %s" -msgstr "“git status --porcelain=2†gặp lá»—i trong mô-Ä‘un-con “%sâ€" +msgstr "'git status --porcelain=2' gặp lá»—i trong mô-Ä‘un-con '%s'" #, c-format msgid "could not start 'git status' in submodule '%s'" -msgstr "không thể lấy thống kê “git status†trong mô-Ä‘un-con “%sâ€" +msgstr "không thể khởi chạy 'git status' trong mô-Ä‘un-con '%s'" #, c-format msgid "could not run 'git status' in submodule '%s'" -msgstr "không thể chạy “git status†trong mô-Ä‘un-con “%sâ€" +msgstr "không thể chạy 'git status' trong mô-Ä‘un-con '%s'" #, c-format msgid "Could not unset core.worktree setting in submodule '%s'" -msgstr "Không thể đặt core.worktree trong mô-Ä‘un-con “%sâ€" +msgstr "Không thể đặt core.worktree trong mô-Ä‘un-con '%s'" #, c-format msgid "could not recurse into submodule '%s'" -msgstr "không thể đệ quy và o trong mô-Ä‘un-con “%sâ€" +msgstr "không thể đệ quy và o trong mô-Ä‘un-con '%s'" msgid "could not reset submodule index" -msgstr "không thể đặt lại mục lục của mô-Ä‘un-con" +msgstr "không thể đặt lại chỉ mục của mô-Ä‘un-con" #, c-format msgid "submodule '%s' has dirty index" -msgstr "mô-Ä‘un-con “%s†có mục lục còn bẩn" +msgstr "mô-Ä‘un-con '%s' có chỉ mục không sạch" #, c-format msgid "Submodule '%s' could not be updated." -msgstr "Mô-Ä‘un-con “%s†không thể được cáºp nháºt." +msgstr "Mô-Ä‘un-con '%s' không thể được cáºp nháºt." #, c-format 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â€" +msgstr "thÆ° mục git mô Ä‘un con '%s' là bên trong git DIR '%.*s'" #, c-format msgid "" "relocate_gitdir for submodule '%s' with more than one worktree not supported" msgstr "" -"relocate_gitdir cho mô-Ä‘un-con “%s†vá»›i nhiá»u hÆ¡n má»™t cây là m việc là chÆ°a " +"relocate_gitdir cho mô-Ä‘un-con '%s' vá»›i nhiá»u hÆ¡n má»™t cây là m việc là chÆ°a " "được há»— trợ" #, c-format msgid "could not lookup name for submodule '%s'" -msgstr "không thể tìm kiếm tên cho mô-Ä‘un-con “%sâ€" +msgstr "không thể tìm kiếm tên cho mô-Ä‘un-con '%s'" #, c-format msgid "refusing to move '%s' into an existing git dir" -msgstr "từ chối di chuyển “%s†và o trong má»™t thÆ° mục git sẵn có" +msgstr "từ chối di chuyển '%s' và o trong má»™t thÆ° mục git sẵn có" #, c-format msgid "" @@ -19995,12 +21269,12 @@ msgid "" "'%s' to\n" "'%s'\n" msgstr "" -"Di cÆ° thÆ° mục git của “%s%s†từ\n" -"“%s†sang\n" -"“%sâ€\n" +"Di cÆ° thÆ° mục git của '%s%s' từ\n" +"'%s' sang\n" +"'%s'\n" msgid "could not start ls-files in .." -msgstr "không thể lấy thông tin thống kê vá» ls-files trong .." +msgstr "không thể khởi chạy ls-files trong .." #, c-format msgid "ls-tree returned unexpected return code %d" @@ -20008,13 +21282,26 @@ msgstr "ls-tree trả vá» mã không nhÆ° mong đợi %d" #, c-format msgid "failed to lstat '%s'" -msgstr "gặp lá»—i khi lstat “%sâ€" +msgstr "gặp lá»—i khi lstat '%s'" -msgid "unhandled options" -msgstr "các tùy chá»n được không xá» lý" +msgid "no remote configured to get bundle URIs from" +msgstr "không có máy chủ để lấy URI bundle" -msgid "error preparing revisions" -msgstr "gặp lá»—i khi chuẩn bị các Ä‘iểm xét duyệt" +#, 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" + +msgid "test-tool cache-tree <options> (control|prime|update)" +msgstr "test-tool cache-tree <các tuỳ chá»n> (control|prime|update)" + +msgid "clear the cache tree before each iteration" +msgstr "dá»n cây nhá»› tạm trÆ°á»›c má»—i chu kỳ" + +msgid "number of entries in the cache tree to invalidate (default 0)" +msgstr "số mục cần huá»· trong câu nhá»› tạm (mặc định 0)" #, c-format msgid "commit %s is not marked reachable" @@ -20027,7 +21314,7 @@ msgid "test-tool serve-v2 [<options>]" msgstr "test-tool serve-v2 [<các tùy chá»n>]" msgid "exit immediately after advertising capabilities" -msgstr "thoát ngay sau khi khởi tạo quảng cáo capabilities" +msgstr "thoát ngay sau khi quảng bá capabilities" msgid "test-helper simple-ipc is-active [<name>] [<options>]" msgstr "test-helper simple-ipc is-active [<tên>] [<các tùy chá»n>]" @@ -20062,7 +21349,7 @@ msgid "named-pipe name" msgstr "tên named-pipe" msgid "number of threads in server thread pool" -msgstr "số lượng tiến trình trong kho tiến trình máy phục vụ" +msgstr "số lượng tiến trình trong kho tiến trình máy chủ" msgid "seconds to wait for daemon to start or stop" msgstr "số giây mà dịch vụ chạy ná»n chá» khi khởi Ä‘á»™ng hoặc dừng" @@ -20083,67 +21370,44 @@ msgid "token" 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 phục vụ" +msgstr "thẻ bà i lệnh để gá»i lên cho máy chủ" #, 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 kéo theo '%s' gặp lá»—i" #, c-format msgid "unknown value '%s' for key '%s'" -msgstr "không hiểu giá trị “%s†cho khóa “%sâ€" +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â€" - -#, c-format -msgid "could not read input file '%s'" -msgstr "không Ä‘á»c được táºp tin đầu và o “%sâ€" - -#, c-format -msgid "could not stat %s" -msgstr "không thể lấy thông tin thống kê vá» %s" - -#, c-format -msgid "file %s is not a regular file" -msgstr "\"%s\" không phải là táºp tin bình thÆ°á»ng" - -#, c-format -msgid "file %s is not writable by user" -msgstr "táºp tin %s ngÆ°á»i dùng không thể ghi được" - -msgid "could not open temporary file" -msgstr "không thể tạo táºp tin tạm thá»i" - -#, c-format -msgid "could not rename temporary file to %s" -msgstr "không thể đổi tên táºp tin tạm thá»i thà nh %s" +msgstr "thẻ thừa trống rá»—ng trong phần thừa '%.*s'" msgid "full write to remote helper failed" -msgstr "ghi đầy đủ lên bá»™ há»— trợ máy chủ gặp lá»—i" +msgstr "ghi đầy đủ lên helper máy chủ gặp lá»—i" #, c-format msgid "unable to find remote helper for '%s'" -msgstr "không thể tìm thấy bá»™ há»— trợ máy chủ cho “%sâ€" +msgstr "không thể tìm thấy helper máy chủ cho '%s'" msgid "can't dup helper output fd" -msgstr "không thể nhân đôi fd dầu ra bá»™ há»— trợ" +msgstr "không thể nhân đôi fd dầu ra helper" #, c-format msgid "" "unknown mandatory capability %s; this remote helper probably needs newer " "version of Git" msgstr "" -"không hiểu capability bắt buá»™c %s; bá»™ há»— trợ máy chủ nà y gần nhÆ° chắc chắn " -"là cần phiên bản Git má»›i hÆ¡n" +"không hiểu capability bắt buá»™c %s; helper máy chủ nà y gần nhÆ° chắc chắn là " +"cần phiên bản Git má»›i hÆ¡n" msgid "this remote helper should implement refspec capability" -msgstr "bá»™ há»— trợ máy chủ nà y cần phải thá»±c thi capability đặc tả tham chiếu" +msgstr "remote helper nà y cần há»— trợ capability đặc tả tham chiếu" #, c-format msgid "%s unexpectedly said: '%s'" -msgstr "%s said bất ngá»: “%sâ€" +msgstr "%s bất ngá» trả lá»i: '%s'" #, c-format msgid "%s also locked %s" @@ -20169,9 +21433,6 @@ msgstr "giao thức nà y không há»— trợ cà i đặt Ä‘Æ°á»ng dẫn dịch vá msgid "invalid remote service path" msgstr "Ä‘Æ°á»ng dẫn dịch vụ máy chủ không hợp lệ" -msgid "operation not supported by protocol" -msgstr "thao tác không được gia thức há»— trợ" - #, c-format msgid "can't connect to subservice %s" msgstr "không thể kết nối đến dịch vụ phụ %s" @@ -20180,15 +21441,15 @@ msgid "--negotiate-only requires protocol v2" msgstr "--negotiate-only cần giao thức v2" msgid "'option' without a matching 'ok/error' directive" -msgstr "“option†không có chỉ thị “ok/error†tÆ°Æ¡ng ứng" +msgstr "'option' không có chỉ thị 'ok/error' tÆ°Æ¡ng ứng" #, c-format msgid "expected ok/error, helper said '%s'" -msgstr "cần ok/error, nhÆ°ng bá»™ há»— trợ lại nói “%sâ€" +msgstr "cần ok/error, nhÆ°ng helper lại nói '%s'" #, c-format msgid "helper reported unexpected status of %s" -msgstr "bá»™ há»— trợ báo cáo rằng không cần tình trạng của %s" +msgstr "helper báo cáo tình trạng bất thÆ°á»ng của %s" #, c-format msgid "helper %s does not support dry-run" @@ -20212,14 +21473,14 @@ msgstr "helper %s không há»— trợ --%s" #, c-format msgid "helper %s does not support 'push-option'" -msgstr "helper %s không há»— trợ “push-optionâ€" +msgstr "helper %s không há»— trợ 'push-option'" msgid "remote-helper doesn't support push; refspec needed" msgstr "remote-helper không há»— trợ push; cần đặc tả tham chiếu" #, c-format -msgid "helper %s does not support 'force'" -msgstr "helper %s không há»— trợ “forceâ€" +msgid "helper %s does not support '--force'" +msgstr "helper %s không há»— trợ '--force'" msgid "couldn't run fast-export" msgstr "không thể chạy fast-export" @@ -20238,7 +21499,7 @@ msgstr "" #, c-format msgid "unsupported object format '%s'" -msgstr "không há»— trợ định dạng đối tượng “%sâ€" +msgstr "không há»— trợ định dạng đối tượng '%s'" #, c-format msgid "malformed response in ref list: %s" @@ -20277,18 +21538,18 @@ msgstr "không thể khởi chạy tuyến trình cho việc chép dữ liệu" #, c-format msgid "Would set upstream of '%s' to '%s' of '%s'\n" -msgstr "Không thể đặt thượng nguồn của “%s†thà nh “%s†của “%sâ€\n" +msgstr "Không thể đặt thượng nguồn của '%s' thà nh '%s' của '%s'\n" #, c-format msgid "could not read bundle '%s'" -msgstr "không thể Ä‘á»c bó “%sâ€" +msgstr "không thể Ä‘á»c bó '%s'" #, c-format msgid "transport: invalid depth option '%s'" -msgstr "váºn chuyển: tùy chá»n Ä‘á»™ sâu “%s†không hợp lệ" +msgstr "váºn chuyển: tùy chá»n Ä‘á»™ sâu '%s' không hợp lệ" msgid "see protocol.version in 'git help config' for more details" -msgstr "xem protocol.version trong “git help config†để có thêm thông tin" +msgstr "xem protocol.version trong 'git help config' để có thêm thông tin" msgid "server options require protocol version 2 or later" msgstr "các tùy chá»n máy chủ yêu cầu giao thức phiên bản 2 hoặc má»›i hÆ¡n" @@ -20297,18 +21558,14 @@ msgid "server does not support wait-for-done" msgstr "máy chủ không há»— trợ wait-for-done" msgid "could not parse transport.color.* config" -msgstr "không thể phân tÃch cú pháp cấu hình transport.color.*" +msgstr "không hiểu cú pháp cấu hình transport.color.*" msgid "support for protocol v2 not implemented yet" -msgstr "việc há»— trợ giao thức v2 chÆ°a được thá»±c hiện" - -#, c-format -msgid "unknown value for config '%s': %s" -msgstr "không hiểu giá trị cho cho cấu hình “%sâ€: %s" +msgstr "chÆ°a há»— trợ giao thức v2" #, c-format msgid "transport '%s' not allowed" -msgstr "không cho phép phÆ°Æ¡ng thức váºn chuyển “%sâ€" +msgstr "không cho phép phÆ°Æ¡ng thức váºn chuyển '%s'" msgid "git-over-rsync is no longer supported" msgstr "git-over-rsync không còn được há»— trợ nữa" @@ -20319,7 +21576,7 @@ msgid "" "not be found on any remote:\n" msgstr "" "Các Ä‘Æ°á»ng dẫn mô-Ä‘un-con sau đây có chứa các thay đổi cái mà \n" -"có thể được tìm thấy trên má»i máy phục vụ:\n" +"có thể được tìm thấy trên má»i máy chủ:\n" #, c-format msgid "" @@ -20344,20 +21601,29 @@ msgstr "" "\n" "\tgit push\n" "\n" -"để đẩy chúng lên máy phục vụ.\n" +"để đẩy chúng lên máy chủ.\n" "\n" msgid "Aborting." -msgstr "Bãi bá»." +msgstr "huá»· bá»." msgid "failed to push all needed submodules" msgstr "gặp lá»—i khi đẩy dữ liệu của tất cả các mô-Ä‘un-con cần thiết" +msgid "bundle-uri operation not supported by protocol" +msgstr "thao tác bundle-uri không được giao thức há»— trợ" + +msgid "could not retrieve server-advertised bundle-uri list" +msgstr "không thể lấy vá» danh sách bundle-uri do phÃa máy chủ quảng bá" + +msgid "operation not supported by protocol" +msgstr "thao tác không được giao thức há»— trợ" + msgid "too-short tree object" msgstr "đối tượng cây quá ngắn" msgid "malformed mode in tree entry" -msgstr "chế Ä‘á»™ dị hình trong Ä‘á» mục cây" +msgstr "chế Ä‘á»™ sai quy cách trong Ä‘á» mục cây" msgid "empty filename in tree entry" msgstr "tên táºp tin trống rá»—ng trong mục tin cây" @@ -20452,7 +21718,7 @@ msgid "" "The following untracked working tree files would be removed by checkout:\n" "%%s" msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị gỡ bá» bởi lệnh " +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị xoá bá» bởi lệnh " "checkout:\n" "%%s" @@ -20461,17 +21727,17 @@ msgid "" "The following untracked working tree files would be removed by merge:\n" "%%sPlease move or remove them before you merge." msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị gỡ bá» bởi lệnh hòa " -"trá»™n:\n" -"%%sVui lòng di chuyển hay gỡ bá» chúng trÆ°á»›c khi bạn hòa trá»™n." +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị xoá bá» bởi lệnh " +"hòa trá»™n:\n" +"%%sVui lòng di chuyển hay xoá bá» chúng trÆ°á»›c khi bạn hòa trá»™n." #, c-format msgid "" "The following untracked working tree files would be removed by merge:\n" "%%s" msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị gỡ bá» bởi lệnh hòa " -"trá»™n:\n" +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị xoá bá» bởi lệnh " +"hòa trá»™n:\n" "%%s" #, c-format @@ -20479,15 +21745,15 @@ msgid "" "The following untracked working tree files would be removed by %s:\n" "%%sPlease move or remove them before you %s." msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị gỡ bá» bởi %s:\n" -"%%sVui lòng di chuyển hay gỡ bá» chúng trÆ°á»›c khi bạn %s." +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị xoá bá» bởi %s:\n" +"%%sVui lòng di chuyển hay xoá bá» chúng trÆ°á»›c khi bạn %s." #, c-format msgid "" "The following untracked working tree files would be removed by %s:\n" "%%s" msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị gỡ bá» bởi %s:\n" +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị xoá bá» bởi %s:\n" "%%s" #, c-format @@ -20496,9 +21762,9 @@ msgid "" "checkout:\n" "%%sPlease move or remove them before you switch branches." msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị ghi đè bởi lệnh " +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị ghi đè bởi lệnh " "checkout:\n" -"%%sVui lòng di chuyển hay gỡ bá» chúng trÆ°á»›c khi bạn chuyển nhánh." +"%%sVui lòng di chuyển hay xoá bá» chúng trÆ°á»›c khi bạn chuyển nhánh." #, c-format msgid "" @@ -20506,7 +21772,7 @@ msgid "" "checkout:\n" "%%s" msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị ghi đè bởi lệnh " +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị ghi đè bởi lệnh " "checkout:\n" "%%s" @@ -20515,16 +21781,16 @@ msgid "" "The following untracked working tree files would be overwritten by merge:\n" "%%sPlease move or remove them before you merge." msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị ghi đè bởi lệnh " +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị ghi đè bởi lệnh " "hòa trá»™n:\n" -"%%sVui lòng di chuyển hay gỡ bá» chúng trÆ°á»›c khi bạn hòa trá»™n." +"%%sVui lòng di chuyển hay xoá bá» chúng trÆ°á»›c khi bạn hòa trá»™n." #, c-format msgid "" "The following untracked working tree files would be overwritten by merge:\n" "%%s" msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị ghi đè bởi lệnh " +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị ghi đè bởi lệnh " "hòa trá»™n:\n" "%%s" @@ -20533,22 +21799,22 @@ msgid "" "The following untracked working tree files would be overwritten by %s:\n" "%%sPlease move or remove them before you %s." msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị ghi đè bởi lệnh " +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị ghi đè bởi lệnh " "%s:\n" -"%%sVui lòng di chuyển hay gỡ bá» chúng trÆ°á»›c khi bạn %s." +"%%sVui lòng di chuyển hay xoá chúng trÆ°á»›c khi bạn %s." #, c-format msgid "" "The following untracked working tree files would be overwritten by %s:\n" "%%s" msgstr "" -"Các táºp tin cây là m việc chÆ°a được theo dõi sau đây sẽ bị ghi đè bởi lệnh " +"Các táºp tin trong cây là m việc chÆ°a được theo dõi sau sẽ bị ghi đè bởi lệnh " "%s:\n" "%%s" #, c-format msgid "Entry '%s' overlaps with '%s'. Cannot bind." -msgstr "Mục “%s†đè lên “%sâ€. Không thể buá»™c." +msgstr "Mục '%s' đè lên '%s'. Không thể bind." #, c-format msgid "" @@ -20564,7 +21830,7 @@ msgid "" "patterns:\n" "%s" msgstr "" -"Các Ä‘Æ°á»ng dẫn sau đây không được cáºp nháºt và vẫn được để lại bất chấp các " +"Các Ä‘Æ°á»ng dẫn sau đây chÆ°a được cáºp nháºt và vẫn được để lại mặc dù khá»›p các " "mẫu sparse:\n" "%s" @@ -20583,21 +21849,21 @@ msgid "" "patterns:\n" "%s" msgstr "" -"Các Ä‘Æ°á»ng dẫn sau đây đã sẵn hiện diện và nhÆ° váºy không được cáºp nháºt bất " -"cấp các mẫu sparse:\n" +"Các Ä‘Æ°á»ng dẫn sau đây đã tồn tại và nhÆ° váºy không được cáºp nháºt mặc dù khá»›p " +"các mẫu sparse:\n" "%s" #, c-format msgid "Aborting\n" -msgstr "Bãi bá»\n" +msgstr "Huá»· bá»\n" #, c-format msgid "" "After fixing the above paths, you may want to run `git sparse-checkout " "reapply`.\n" msgstr "" -"Sau khi sá»a các Ä‘Æ°á»ng dẫn phÃa trên, bạn có thể chạy “git sparse-checkout " -"reapply“.\n" +"Sau khi sá»a các Ä‘Æ°á»ng dẫn phÃa trên, bạn có thể chạy 'git sparse-checkout " +"reapply'.\n" msgid "Updating files" msgstr "Äang cáºp nháºt các táºp tin" @@ -20607,12 +21873,12 @@ msgid "" "on a case-insensitive filesystem) and only one from the same\n" "colliding group is in the working tree:\n" msgstr "" -"các Ä‘Æ°á»ng dẫn sau đây có xung Ä‘á»™t(vd: các Ä‘Æ°á»ng dẫn phân biệt\n" -"HOA/thÆ°á»ng trên má»™t hệ thống táºp tin không phân biệt HOA/thÆ°á»ng)\n" -"và chỉ má»™t từ cùng má»™t nhóm xung Ä‘á»™t là trong cây là m việc hiện tại:\n" +"các Ä‘Æ°á»ng dẫn sau đây có xung Ä‘á»™t (vd: các Ä‘Æ°á»ng dẫn phân biệt HOA/thÆ°á»ng\n" +"trên hệ thống táºp tin không phân biệt HOA/thÆ°á»ng) và chỉ má»™t Ä‘Æ°á»ng dẫn\n" +"trong nhóm xung Ä‘á»™t nằm trong cây là m việc hiện tại:\n" msgid "Updating index flags" -msgstr "Äang cáºp nháºt các cá» mục lục" +msgstr "Äang cáºp nháºt các cá» chỉ mục" #, c-format msgid "worktree and untracked commit have duplicate entries: %s" @@ -20623,17 +21889,17 @@ msgid "expected flush after fetch arguments" msgstr "cần đẩy dữ liệu lên Ä‘Ä©a sau các tham số của lệnh fetch" msgid "invalid URL scheme name or missing '://' suffix" -msgstr "tên lược đồ URL không hợp lệ, hoặc thiếu háºu tố “://â€" +msgstr "tên lược đồ URL không hợp lệ, hoặc thiếu háºu tố '://'" #, c-format msgid "invalid %XX escape sequence" msgstr "thoát chuá»—i %XX không hợp lệ" msgid "missing host and scheme is not 'file:'" -msgstr "thiếu máy chủ và lược đồ thì không phải là giao thức “file:â€" +msgstr "thiếu máy chủ và lược đồ không phải là 'file:'" msgid "a 'file:' URL may not have a port number" -msgstr "má»™t URL kiểu “file:†không được chứa cổng" +msgstr "URL kiểu 'file:' không được chứa cổng" msgid "invalid characters in host name" msgstr "có các ký tá»± không hợp lệ trong tên máy" @@ -20642,27 +21908,43 @@ msgid "invalid port number" msgstr "tên cổng không hợp lệ" msgid "invalid '..' path segment" -msgstr "Ä‘oạn Ä‘Æ°á»ng dẫn “..†không hợp lệ" +msgstr "Ä‘oạn Ä‘Æ°á»ng dẫn '..' không hợp lệ" + +#, c-format +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" + +msgid "fatal: " +msgstr "lá»—i nghiêm trá»ng: " + +msgid "error: " +msgstr "lá»—i: " + +msgid "warning: " +msgstr "cảnh báo: " msgid "Fetching objects" msgstr "Äang lấy vá» các đối tượng" #, c-format msgid "'%s' at main working tree is not the repository directory" -msgstr "“%s†tại cây là m việc chình không phải là thÆ° mục kho" +msgstr "'%s' tại cây là m việc chÃnh không phải là thÆ° mục kho" #, c-format msgid "'%s' file does not contain absolute path to the working tree location" msgstr "" -"táºp tin “%s†không chứa Ä‘Æ°á»ng dẫn tuyệt đối đến vị trà cây là m việc hiện" +"táºp tin '%s' không chứa Ä‘Æ°á»ng dẫn tuyệt đối đến vị trà cây là m việc hiện" #, c-format msgid "'%s' is not a .git file, error code %d" -msgstr "“%s†không phải là táºp tin .git, mã lá»—i %d" +msgstr "'%s' không phải là táºp tin .git, mã lá»—i %d" #, c-format msgid "'%s' does not point back to '%s'" -msgstr "“%s†không chỉ ngược đến “%sâ€" +msgstr "'%s' không chỉ ngược đến '%s'" msgid "not a directory" msgstr "không phải thÆ° mục" @@ -20671,7 +21953,7 @@ msgid ".git is not a file" msgstr ".git không phải là má»™t táºp tin" msgid ".git file broken" -msgstr "tệp .git bị há»ng" +msgstr "táºp tin .git bị há»ng" msgid ".git file incorrect" msgstr "táºp tin .git không chÃnh xác" @@ -20680,13 +21962,13 @@ msgid "not a valid path" msgstr "không phải là má»™t Ä‘Æ°á»ng dẫn hợp lệ" msgid "unable to locate repository; .git is not a file" -msgstr "không thể phân bổ kho chứa; .git không phải là má»™t táºp tin" +msgstr "không thể định vị kho chứa; .git không phải là má»™t táºp tin" msgid "unable to locate repository; .git file does not reference a repository" -msgstr "không thể phân bổ kho chứa; táºp tin .git tham chiếu đến má»™t kho" +msgstr "không thể định vị kho chứa; táºp tin .git không chỉ đến má»™t kho" msgid "unable to locate repository; .git file broken" -msgstr "không thể phân bổ kho chứa; táºp tin .git bị há»ng" +msgstr "không thể định vị kho chứa; táºp tin .git bị há»ng" msgid "gitdir unreadable" msgstr "gitdir không thể Ä‘á»c được" @@ -20716,7 +21998,7 @@ msgstr "táºp tin gitdir chỉ đến vị trà không tồn tại" #, c-format msgid "unable to set %s in '%s'" -msgstr "không thể đặt %s trong “%sâ€" +msgstr "không thể đặt %s trong '%s'" #, c-format msgid "unable to unset %s in '%s'" @@ -20727,48 +22009,49 @@ msgstr "gặp lá»—i khi đặt cà i đặt extensions.worktreeConfig" #, c-format msgid "could not setenv '%s'" -msgstr "không thể setenv “%sâ€" +msgstr "không thể setenv '%s'" #, c-format msgid "unable to create '%s'" -msgstr "không thể tạo “%sâ€" +msgstr "không thể tạo '%s'" #, c-format msgid "could not open '%s' for reading and writing" -msgstr "không thể mở “%s†để Ä‘á»c và ghi" +msgstr "không thể mở '%s' để Ä‘á»c và ghi" #, c-format msgid "unable to access '%s'" -msgstr "không thể truy cáºp “%sâ€" +msgstr "không thể truy cáºp '%s'" msgid "unable to get current working directory" msgstr "không thể lấy thÆ° mục là m việc hiện hà nh" +msgid "unable to get random bytes" +msgstr "không thể lấy byte ngẫu nhiên" + 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 bệ phóng)" #, c-format msgid " (use \"git restore --source=%s --staged <file>...\" to unstage)" msgstr "" -" (dùng \"git restore --source=%s --staged <táºp-tin>…\" để bá» ra khá»i bệ " +" (dùng \"git restore --source=%s --staged <táºp-tin>...\" để bá» ra khá»i bệ " "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 bệ phóng)" msgid " (use \"git add <file>...\" to mark resolution)" -msgstr " (dùng \"git add <táºp-tin>…\" để đánh dấu là cần giải quyết)" +msgstr " (dùng \"git add <táºp-tin>...\" để đánh dấu là muốn thêm)" msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)" -msgstr "" -" (dùng \"git add/rm <táºp-tin>…\" nhÆ° là má»™t cách thÃch hợp để đánh dấu là " -"cần được giải quyết)" +msgstr " (dùng \"git add/rm <táºp-tin>...\" để đánh dấu là muốn thêm/xoá)" msgid " (use \"git rm <file>...\" to mark resolution)" -msgstr " (dùng \"git rm <táºp-tin>…\" để đánh dấu là cần giải quyết)" +msgstr " (dùng \"git rm <táºp-tin>...\" để đánh dấu là muốn xoá)" msgid "Changes to be committed:" msgstr "Những thay đổi sẽ được chuyển giao:" @@ -20777,45 +22060,46 @@ msgid "Changes not staged for commit:" msgstr "Các thay đổi chÆ°a được đặt lên bệ phóng để chuyển giao:" msgid " (use \"git add <file>...\" to update what will be committed)" -msgstr " (dùng \"git add <táºp-tin>…\" để cáºp nháºt những gì sẽ chuyển giao)" +msgstr "" +" (dùng \"git add <táºp-tin>...\" để cáºp nháºt những gì sẽ được chuyển giao)" msgid " (use \"git add/rm <file>...\" to update what will be committed)" msgstr "" -" (dùng \"git add/rm <táºp-tin>…\" để cáºp nháºt những gì sẽ được chuyển giao)" +" (dùng \"git add/rm <táºp-tin>...\" để cáºp nháºt những gì sẽ được chuyển giao)" msgid "" " (use \"git restore <file>...\" to discard changes in working directory)" msgstr "" -" (dùng \"git restore <táºp-tin>…\" để loại bá» các thay đổi trong thÆ° mục là m " -"việc)" +" (dùng \"git restore <táºp-tin>...\" để loại bá» các thay đổi trong thÆ° mục " +"là m việc)" msgid " (commit or discard the untracked or modified content in submodules)" msgstr "" " (chuyển giao hoặc là loại bá» các ná»™i dung chÆ°a được theo dõi hay đã sá»a " -"chữa trong mô-Ä‘un-con)" +"trong mô-Ä‘un-con)" #, c-format msgid " (use \"git %s <file>...\" to include in what will be committed)" msgstr "" -" (dùng \"git %s <táºp-tin>…\" để thêm và o những gì cần được chuyển giao)" +" (dùng \"git %s <táºp-tin>...\" để thêm và o những gì cần được chuyển giao)" msgid "both deleted:" -msgstr "bị xóa bởi cả hai:" +msgstr "bị cả hai xóa Ä‘i:" msgid "added by us:" -msgstr "được thêm và o bởi chúng ta:" +msgstr "được ta thêm và o:" msgid "deleted by them:" -msgstr "bị xóa Ä‘i bởi há»:" +msgstr "bị há» xóa Ä‘i:" msgid "added by them:" -msgstr "được thêm và o bởi há»:" +msgstr "được há» thêm và o:" msgid "deleted by us:" -msgstr "bị xóa bởi chúng ta:" +msgstr "bị ta xóa Ä‘i:" msgid "both added:" -msgstr "được thêm và o bởi cả hai:" +msgstr "được cả hai thêm và o:" msgid "both modified:" msgstr "bị sá»a bởi cả hai:" @@ -20836,10 +22120,10 @@ msgid "renamed:" msgstr "đã đổi tên:" msgid "typechange:" -msgstr "đổi-kiểu:" +msgstr "đổi kiểu:" msgid "unknown:" -msgstr "không hiểu:" +msgstr "không rõ:" msgid "unmerged:" msgstr "chÆ°a hòa trá»™n:" @@ -20856,20 +22140,20 @@ msgstr "ná»™i dung chÆ°a được theo dõi, " #, c-format msgid "Your stash currently has %d entry" msgid_plural "Your stash currently has %d entries" -msgstr[0] "Bạn hiện nay ở trong phần cất Ä‘i Ä‘ang có %d mục" +msgstr[0] "Hiện trong phần cất Ä‘i Ä‘ang có %d mục" msgid "Submodules changed but not updated:" msgstr "Những mô-Ä‘un-con đã bị thay đổi nhÆ°ng chÆ°a được cáºp nháºt:" msgid "Submodule changes to be committed:" -msgstr "Những mô-Ä‘un-con thay đổi đã được chuyển giao:" +msgstr "Những thay đổi mô-Ä‘un-con sẽ được chuyển giao:" msgid "" "Do not modify or remove the line above.\n" "Everything below it will be ignored." msgstr "" "Không sá»a hay xóa bá» Ä‘Æ°á»ng ở trên.\n" -"Má»i thứ phÃa dÆ°á»›i sẽ được xóa bá»." +"Má»i thứ phÃa dÆ°á»›i sẽ được bá» qua." #, c-format msgid "" @@ -20878,8 +22162,8 @@ msgid "" "You can use '--no-ahead-behind' to avoid this.\n" msgstr "" "\n" -"Nó cần %.2f giây để tÃnh toán giá trị của trÆ°á»›c/sau của nhánh.\n" -"Bạn có thể dùng “--no-ahead-behind†tránh phải Ä‘iá»u nà y.\n" +"Cần tá»›i %.2f giây để tÃnh toán giá trị đứng trÆ°á»›c/sau của nhánh.\n" +"Bạn có thể dùng '--no-ahead-behind' để bá» qua.\n" msgid "You have unmerged paths." msgstr "Bạn có những Ä‘Æ°á»ng dẫn chÆ°a được hòa trá»™n." @@ -20888,7 +22172,7 @@ msgid " (fix conflicts and run \"git commit\")" msgstr " (sá»a các xung Ä‘á»™t rồi chạy \"git commit\")" msgid " (use \"git merge --abort\" to abort the merge)" -msgstr " (dùng \"git merge --abort\" để bãi bá» việc hòa trá»™n)" +msgstr " (dùng \"git merge --abort\" để huá»· bá» việc hòa trá»™n)" msgid "All conflicts fixed but you are still merging." msgstr "Tất cả các xung Ä‘á»™t đã được giải quyết nhÆ°ng bạn vẫn Ä‘ang hòa trá»™n." @@ -20897,112 +22181,107 @@ msgid " (use \"git commit\" to conclude merge)" msgstr " (dùng \"git commit\" để hoà n tất việc hòa trá»™n)" msgid "You are in the middle of an am session." -msgstr "Bạn Ä‘ang ở giữa của má»™t phiên “amâ€." +msgstr "Bạn Ä‘ang trong má»™t phiên 'am' (áp dụng bản vá từ hòm thÆ°)." msgid "The current patch is empty." -msgstr "Miếng vá hiện tại bị trống rá»—ng." +msgstr "bản vá hiện tại bị trống." msgid " (fix conflicts and then run \"git am --continue\")" msgstr " (sá»a các xung Ä‘á»™t và sau đó chạy lệnh \"git am --continue\")" msgid " (use \"git am --skip\" to skip this patch)" -msgstr " (dùng \"git am --skip\" để bá» qua miếng vá nà y)" +msgstr " (dùng \"git am --skip\" để bá» qua bản vá nà y)" msgid "" " (use \"git am --allow-empty\" to record this patch as an empty commit)" msgstr "" -" (dùng \"git am --allow-empty\" ghi miếng vá nà y nhÆ° má»™t lần chuyển giao " +" (dùng \"git am --allow-empty\" để ghi bản vá nà y thà nh má»™t lần chuyển giao " "rá»—ng)" msgid " (use \"git am --abort\" to restore the original branch)" -msgstr " (dùng \"git am --abort\" để phục hồi lại nhánh nguyên thủy)" +msgstr " (dùng \"git am --abort\" để phục hồi lại nhánh gốc)" msgid "git-rebase-todo is missing." msgstr "thiếu git-rebase-todo." msgid "No commands done." -msgstr "Không thá»±c hiện lệnh nà o." +msgstr "ChÆ°a thá»±c hiện lệnh nà o." #, c-format msgid "Last command done (%<PRIuMAX> command done):" msgid_plural "Last commands done (%<PRIuMAX> commands done):" -msgstr[0] "Lệnh thá»±c hiện cuối (%<PRIuMAX> lệnh được thá»±c thi):" +msgstr[0] "Lệnh thá»±c hiện cuối (đã thá»±c thi %<PRIuMAX> lệnh):" #, c-format msgid " (see more in file %s)" msgstr " (xem thêm trong %s)" msgid "No commands remaining." -msgstr "Không có lệnh nà o còn lại." +msgstr "Không còn lệnh nà o." #, c-format msgid "Next command to do (%<PRIuMAX> remaining command):" msgid_plural "Next commands to do (%<PRIuMAX> remaining commands):" -msgstr[0] "Lệnh cần là m kế tiếp (%<PRIuMAX> lệnh còn lại):" +msgstr[0] "Lệnh cần là m kế tiếp (còn %<PRIuMAX> lệnh):" msgid " (use \"git rebase --edit-todo\" to view and edit)" msgstr " (dùng lệnh \"git rebase --edit-todo\" để xem và sá»a)" #, c-format msgid "You are currently rebasing branch '%s' on '%s'." -msgstr "Bạn hiện nay Ä‘ang thá»±c hiện việc “rebase†nhánh “%s†trên “%sâ€." +msgstr "Bạn hiện Ä‘ang thá»±c hiện rebase (cải tổ) nhánh '%s' lên '%s'." msgid "You are currently rebasing." -msgstr "Bạn hiện nay Ä‘ang thá»±c hiện việc “rebase†(cải tổ)." +msgstr "Bạn hiện Ä‘ang thá»±c hiện rebase (cải tổ)." msgid " (fix conflicts and then run \"git rebase --continue\")" -msgstr "" -" (sá»a các xung Ä‘á»™t và sau đó chạy lệnh “cải tổ†\"git rebase --continue\")" +msgstr " (sá»a các xung Ä‘á»™t và sau đó chạy lệnh \"git rebase --continue\")" msgid " (use \"git rebase --skip\" to skip this patch)" -msgstr " (dùng lệnh “cải tổ†\"git rebase --skip\" để bá» qua lần vá nà y)" +msgstr " (dùng lệnh \"git rebase --skip\" để bá» qua bản vá nà y)" msgid " (use \"git rebase --abort\" to check out the original branch)" -msgstr "" -" (dùng lệnh “cải tổ†\"git rebase --abort\" để check-out nhánh nguyên thủy)" +msgstr " (dùng lệnh \"git rebase --abort\" để check-out nhánh gốc)" msgid " (all conflicts fixed: run \"git rebase --continue\")" msgstr "" -" (khi tất cả các xung Ä‘á»™t đã sá»a xong: chạy lệnh “cải tổ†\"git rebase --" -"continue\")" +" (khi tất cả các xung Ä‘á»™t đã sá»a xong: chạy lệnh \"git rebase --continue\")" #, c-format msgid "" "You are currently splitting a commit while rebasing branch '%s' on '%s'." msgstr "" -"Bạn hiện nay Ä‘ang thá»±c hiện việc chia tách má»™t lần chuyển giao trong khi " -"Ä‘ang “rebase†nhánh “%s†trên “%sâ€." +"Bạn hiện Ä‘ang chia nhá» má»™t lần chuyển giao trong khi Ä‘ang rebase nhánh '%s' " +"lên '%s'." msgid "You are currently splitting a commit during a rebase." msgstr "" -"Bạn hiện tại Ä‘ang cắt đôi má»™t lần chuyển giao trong khi Ä‘ang thá»±c hiện việc " -"rebase." +"Bạn hiện Ä‘ang chia nhá» má»™t lần chuyển giao trong khi Ä‘ang thá»±c hiện rebase." msgid " (Once your working directory is clean, run \"git rebase --continue\")" msgstr "" -" (Má»™t khi thÆ° mục là m việc của bạn đã gá»n gà ng, chạy lệnh “cải tổ†\"git " -"rebase --continue\")" +" (Sau khi thÆ° mục là m việc đã ổn, chạy lệnh \"git rebase --continue\")" #, c-format msgid "You are currently editing a commit while rebasing branch '%s' on '%s'." msgstr "" -"Bạn hiện nay Ä‘ang thá»±c hiện việc sá»a chữa má»™t lần chuyển giao trong khi Ä‘ang " -"rebase nhánh “%s†trên “%sâ€." +"Bạn hiện Ä‘ang thá»±c hiện sá»a chữa má»™t lần chuyển giao trong khi Ä‘ang rebase " +"nhánh '%s' lên '%s'." msgid "You are currently editing a commit during a rebase." -msgstr "Bạn hiện Ä‘ang sá»a má»™t lần chuyển giao trong khi bạn thá»±c hiện rebase." +msgstr "Bạn hiện Ä‘ang sá»a má»™t lần chuyển giao trong khi Ä‘ang thá»±c hiện rebase." msgid " (use \"git commit --amend\" to amend the current commit)" -msgstr " (dùng \"git commit --amend\" để “tu bổ†lần chuyển giao hiện tại)" +msgstr " (dùng \"git commit --amend\" để tu bổ lần chuyển giao hiện tại)" msgid "" " (use \"git rebase --continue\" once you are satisfied with your changes)" msgstr "" -" (chạy lệnh “cải tổ†\"git rebase --continue\" má»™t khi bạn cảm thấy hà i " -"lòng vá» những thay đổi của mình)" +" (chạy lệnh \"git rebase --continue\" khi bạn cảm thấy hà i lòng vá» những " +"thay đổi của mình)" msgid "Cherry-pick currently in progress." -msgstr "Cherry-pick hiện tại Ä‘ang được thá»±c hiện." +msgstr "Cherry-pick hiện Ä‘ang được thá»±c hiện." #, c-format msgid "You are currently cherry-picking commit %s." @@ -21021,17 +22300,17 @@ msgstr "" "continue\")" msgid " (use \"git cherry-pick --skip\" to skip this patch)" -msgstr " (dùng \"git cherry-pick --skip\" để bá» qua miếng vá nà y)" +msgstr " (dùng \"git cherry-pick --skip\" để bá» qua bản vá nà y)" msgid " (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)" msgstr " (dùng \"git cherry-pick --abort\" để hủy bá» thao tác cherry-pick)" msgid "Revert currently in progress." -msgstr "Hoà n nguyên hiện tại Ä‘ang thá»±c hiện." +msgstr "Hoà n nguyên hiện Ä‘ang được thá»±c hiện." #, c-format msgid "You are currently reverting commit %s." -msgstr "Bạn hiện nay Ä‘ang thá»±c hiện thao tác hoà n nguyên lần chuyển giao “%sâ€." +msgstr "Bạn hiện nay Ä‘ang thá»±c hiện thao tác hoà n nguyên lần chuyển giao '%s'." msgid " (fix conflicts and run \"git revert --continue\")" msgstr " (sá»a các xung Ä‘á»™t và sau đó chạy lệnh \"git revert --continue\")" @@ -21053,7 +22332,7 @@ msgstr " (dùng \"git revert --abort\" để hủy bá» thao tác hoà n nguyên msgid "You are currently bisecting, started from branch '%s'." msgstr "" "Bạn hiện nay Ä‘ang thá»±c hiện thao tác di chuyển ná»a bÆ°á»›c (bisect), bắt đầu từ " -"nhánh “%sâ€." +"nhánh '%s'." msgid "You are currently bisecting." msgstr "Bạn hiện tại Ä‘ang thá»±c hiện việc bisect (di chuyển ná»a bÆ°á»›c)." @@ -21062,19 +22341,18 @@ msgid " (use \"git bisect reset\" to get back to the original branch)" msgstr " (dùng \"git bisect reset\" để quay trở lại nhánh nguyên thủy)" msgid "You are in a sparse checkout." -msgstr "Bạn Ä‘ang trong lần lấy ra sparse." +msgstr "Bạn Ä‘ang ở trong lần checkout thÆ°a." #, c-format msgid "You are in a sparse checkout with %d%% of tracked files present." msgstr "" -"Bạn Ä‘ang ở trong lần lấy ra sparser %d%% của các táºp tin được theo dõi hiện " -"tại." +"Bạn Ä‘ang ở trong lần checkout thÆ°a vá»›i %d%% táºp tin hiện được theo dõi." msgid "On branch " msgstr "Trên nhánh " msgid "interactive rebase in progress; onto " -msgstr "rebase ở chế Ä‘á»™ tÆ°Æ¡ng tác Ä‘ang được thá»±c hiện; lên trên " +msgstr "rebase có tÆ°Æ¡ng tác Ä‘ang được thá»±c hiện; lên trên " msgid "rebase in progress; onto " msgstr "rebase Ä‘ang được thá»±c hiện: lên trên " @@ -21098,33 +22376,37 @@ msgid "Untracked files" msgstr "Những táºp tin chÆ°a được theo dõi" msgid "Ignored files" -msgstr "Những táºp tin bị lá» Ä‘i" +msgstr "Những táºp tin bị bá» qua" #, c-format msgid "" -"It took %.2f seconds to enumerate untracked files. 'status -uno'\n" -"may speed it up, but you have to be careful not to forget to add\n" -"new files yourself (see 'git help status')." +"It took %.2f seconds to enumerate untracked files,\n" +"but the results were cached, and subsequent runs may be faster." msgstr "" -"Cần %.2f giây để liệt kê tất cả các táºp tin chÆ°a được theo dõi. “status -" -"unoâ€\n" -"có lẽ là m nó nhanh hÆ¡n, nhÆ°ng bạn phải cẩn tháºn đừng quên mình phải\n" -"tá»± thêm các táºp tin má»›i (xem “git help statusâ€.." +"Cần %.2f để duyệt các táºp tin không được theo dõi,\n" +"nhÆ°ng đã ghi nhá»› kết quả, và các lần chạy sau sẽ nhanh hÆ¡n." + +#, c-format +msgid "It took %.2f seconds to enumerate untracked files." +msgstr "Cần %.2f để duyệt các táºp tin không được theo dõi." + +msgid "See 'git help status' for information on how to improve this." +msgstr "Xem 'git help status' để biết cách cải thiện việc nà y." #, c-format msgid "Untracked files not listed%s" -msgstr "Những táºp tin chÆ°a được theo dõi không được liệt kê ra %s" +msgstr "Không liệt kê những táºp tin chÆ°a được theo dõi%s" msgid " (use -u option to show untracked files)" -msgstr " (dùng tùy chá»n -u để hiển thị các táºp tin chÆ°a được theo dõi)" +msgstr " (dùng tùy chá»n -u để hiển thị những táºp tin chÆ°a được theo dõi)" msgid "No changes" -msgstr "Không có thay đổi nà o" +msgstr "Không có thay đổi" #, c-format msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" msgstr "" -"không có thay đổi nà o được thêm và o để chuyển giao (dùng \"git add\" và /hoặc " +"không có thay đổi nà o được thêm và o để chuyển giao (dùng \"git add\" hoặc " "\"git commit -a\")\n" #, c-format @@ -21136,14 +22418,14 @@ msgid "" "nothing added to commit but untracked files present (use \"git add\" to " "track)\n" msgstr "" -"không có gì được thêm và o lần chuyển giao nhÆ°ng có những táºp tin chÆ°a được " -"theo dõi hiện diện (dùng \"git add\" để Ä‘Æ°a và o theo dõi)\n" +"không có gì được thêm và o để chuyển giao nhÆ°ng hiện có những táºp tin chÆ°a " +"được theo dõi (dùng \"git add\" để Ä‘Æ°a và o theo dõi)\n" #, c-format msgid "nothing added to commit but untracked files present\n" msgstr "" -"không có gì được thêm và o lần chuyển giao nhÆ°ng có những táºp tin chÆ°a được " -"theo dõi hiện diện\n" +"không có gì được thêm và o lần chuyển giao nhÆ°ng có những táºp tin hiện chÆ°a " +"được theo dõi\n" #, c-format msgid "nothing to commit (create/copy files and use \"git add\" to track)\n" @@ -21158,26 +22440,27 @@ msgstr "không có gì để chuyển giao\n" #, c-format msgid "nothing to commit (use -u to show untracked files)\n" msgstr "" -"không có gì để chuyển giao (dùng -u xem các táºp tin chÆ°a được theo dõi)\n" +"không có gì để chuyển giao (dùng -u để xem những táºp tin chÆ°a được theo " +"dõi)\n" #, c-format msgid "nothing to commit, working tree clean\n" msgstr "không có gì để chuyển giao, thÆ° mục là m việc sạch sẽ\n" msgid "No commits yet on " -msgstr "Vẫn không thá»±c hiện lệnh chuyển giao nà o " +msgstr "ChÆ°a thá»±c hiện lệnh chuyển giao nà o trên" msgid "HEAD (no branch)" msgstr "HEAD (không nhánh)" msgid "different" -msgstr "khác" +msgstr "khác nhau" msgid "behind " -msgstr "đằng sau " +msgstr "đứng sau " msgid "ahead " -msgstr "phÃa trÆ°á»›c " +msgstr "đứng trÆ°á»›c " #. TRANSLATORS: the action is e.g. "pull with rebase" #, c-format @@ -21185,26 +22468,29 @@ 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." msgid "additionally, your index contains uncommitted changes." -msgstr "" -"thêm và o đó, bảng mục lục của bạn có chứa các thay đổi chÆ°a được chuyển giao." +msgstr "ngoà i ra, chỉ mục của bạn có chứa các thay đổi chÆ°a được chuyển giao." #, c-format msgid "cannot %s: Your index contains uncommitted changes." msgstr "" -"không thể %s: Mục lục của bạn có chứa các thay đổi chÆ°a được chuyển giao." +"không thể %s: chỉ mục của bạn có chứa các thay đổi chÆ°a được chuyển giao." + +#, c-format +msgid "unknown style '%s' given for '%s'" +msgstr "không hiểu style '%s' cho '%s'" msgid "" "Error: Your local changes to the following files would be overwritten by " "merge" msgstr "" -"Lá»—i: Các thay đổi ná»™i bá»™ của bạn vá»›i các táºp tin sau đây sẽ bị ghi đè bởi " -"lệnh hòa trá»™n" +"Lá»—i: Các thay đổi ná»™i bá»™ của bạn vá»›i các táºp tin sau đây sẽ bị ghi đè khi " +"hòa trá»™n" msgid "Automated merge did not work." -msgstr "Hòa trá»™n má»™t cách tá»± Ä‘á»™ng không là m việc." +msgstr "Hòa trá»™n tá»± Ä‘á»™ng không thà nh công." msgid "Should not be doing an octopus." -msgstr "Không thể thá»±c hiện má»™t octopus." +msgstr "Không thể thá»±c hiện hoà trá»™n kiểu bạch tuá»™c." #, sh-format msgid "Unable to find common commit with $pretty_name" @@ -21223,7 +22509,7 @@ msgid "Trying simple merge with $pretty_name" msgstr "Äang thá» hòa trá»™n Ä‘Æ¡n giản vá»›i $pretty_name" msgid "Simple merge did not work, trying automatic merge." -msgstr "Hòa trá»™n Ä‘Æ¡n giản không là m việc, thá» hòa trá»™n tá»± Ä‘á»™ng." +msgstr "Hòa trá»™n Ä‘Æ¡n giản không thà nh công, thá» hòa trá»™n tá»± Ä‘á»™ng." #, sh-format msgid "usage: $dashless $USAGE" @@ -21231,14 +22517,12 @@ msgstr "cách dùng: $dashless $USAGE" #, sh-format msgid "Cannot chdir to $cdup, the toplevel of the working tree" -msgstr "" -"Không thể chuyển thÆ° mục (chdir) sang $cdup, thÆ° mục ở mức cao nhất của cây " -"là m việc" +msgstr "Không thể chuyển thÆ° mục sang $cdup, ở mức cao nhất của cây là m việc" #, sh-format msgid "fatal: $program_name cannot be used without a working tree." msgstr "" -"lá»—i nghiêm trá»ng: $program_name không thể được dùng ngoaoif thÆ° mục là m việc." +"lá»—i nghiêm trá»ng: $program_name không thể được dùng ngoà i thÆ° mục là m việc." msgid "Cannot rewrite branches: You have unstaged changes." msgstr "" @@ -21251,12 +22535,11 @@ msgstr "Không thể $action: Bạn có các thay đổi chÆ°a được Ä‘Æ°a là #, sh-format msgid "Cannot $action: Your index contains uncommitted changes." msgstr "" -"Không thể $action: Mục lục của bạn có chứa các thay đổi chÆ°a được chuyển " +"Không thể $action: chỉ mục của bạn có chứa các thay đổi chÆ°a được chuyển " "giao." msgid "Additionally, your index contains uncommitted changes." -msgstr "" -"Thêm và o đó, bảng mục lục của bạn có chứa các thay đổi chÆ°a được chuyển giao." +msgstr "Ngoà i ra, chỉ mục của bạn có chứa các thay đổi chÆ°a được chuyển giao." msgid "You need to run this command from the toplevel of the working tree." msgstr "Bạn cần chạy lệnh nà y từ thÆ° mục ở mức cao nhất của cây là m việc." @@ -21264,360 +22547,73 @@ msgstr "Bạn cần chạy lệnh nà y từ thÆ° mục ở mức cao nhất củ msgid "Unable to determine absolute path of git directory" msgstr "Không thể dò tìm Ä‘Æ°á»ng dẫn tuyệt đối của thÆ° mục git" -#. TRANSLATORS: you can adjust this to align "git add -i" status menu -#, perl-format -msgid "%12s %12s %s" -msgstr "%12s %12s %s" - -#, perl-format -msgid "touched %d path\n" -msgid_plural "touched %d paths\n" -msgstr[0] "%d Ä‘Æ°á»ng dẫn đã touch (chạm)\n" - -msgid "" -"If the patch applies cleanly, the edited hunk will immediately be\n" -"marked for staging." -msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức\n" -"được đánh dấu để chuyển lên bệ phóng." - -msgid "" -"If the patch applies cleanly, the edited hunk will immediately be\n" -"marked for stashing." -msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức\n" -"được đánh dấu để tạm cất." - -msgid "" -"If the patch applies cleanly, the edited hunk will immediately be\n" -"marked for unstaging." -msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức\n" -"được đánh dấu để bá» chuyển lên bệ phóng." - -msgid "" -"If the patch applies cleanly, the edited hunk will immediately be\n" -"marked for applying." -msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức\n" -"được đánh dấu để áp dụng." - -msgid "" -"If the patch applies cleanly, the edited hunk will immediately be\n" -"marked for discarding." -msgstr "" -"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sá»a sẽ ngay láºp tức\n" -"được đánh dấu để loại bá»." - -#, perl-format -msgid "failed to open hunk edit file for writing: %s" -msgstr "gặp lá»—i khi táºp tin sá»a khúc để ghi: %s" - -#, perl-format -msgid "" -"---\n" -"To remove '%s' lines, make them ' ' lines (context).\n" -"To remove '%s' lines, delete them.\n" -"Lines starting with %s will be removed.\n" -msgstr "" -"---\n" -"Äể gỡ bá» các dòng “%sâ€, là m chúng thà nh những dòng “ “ (ná»™i dung).\n" -"Äể xóa bá» dòng “%sâ€, xóa chúng Ä‘i.\n" -"Những dòng bắt đầu bằng %s sẽ bị loại bá».\n" - -#, perl-format -msgid "failed to open hunk edit file for reading: %s" -msgstr "gặp lá»—i khi mở táºp tin khúc để Ä‘á»c: %s" - -msgid "" -"y - stage this hunk\n" -"n - do not stage this hunk\n" -"q - quit; do not stage this hunk or any of the remaining ones\n" -"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" -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 cÅ©ng nhÆ° 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 cÅ©ng nhÆ° bất kỳ cái nà o còn lại trong táºp " -"tin" - -msgid "" -"y - stash this hunk\n" -"n - do not stash this hunk\n" -"q - quit; do not stash this hunk or any of the remaining ones\n" -"a - stash this hunk and all later hunks in the file\n" -"d - do not stash this hunk or any of the later hunks in the file" -msgstr "" -"y - tạm cất khúc nà y\n" -"n - đừng tạm cất khúc nà y\n" -"q - thoát; đừng tạm cất khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" -"a - tạm cất khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng tạm cất khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại trong táºp tin" - -msgid "" -"y - unstage this hunk\n" -"n - do not unstage this hunk\n" -"q - quit; do not unstage this hunk or any of the remaining ones\n" -"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" -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 cÅ©ng nhÆ° 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 cÅ©ng nhÆ° bất kỳ cái nà o còn lại trong " -"táºp tin" - -msgid "" -"y - apply this hunk to index\n" -"n - do not apply this hunk to index\n" -"q - quit; do not apply this hunk or any of the remaining ones\n" -"a - apply this hunk and all later hunks in the file\n" -"d - do not apply this hunk or any of the later hunks in the file" -msgstr "" -"y - áp dụng khúc nà y và o mục lục\n" -"n - đừng áp dụng khúc nà y và o mục lục\n" -"q - thoát; đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" -"a - áp dụng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin" - -msgid "" -"y - discard this hunk from worktree\n" -"n - do not discard this hunk from worktree\n" -"q - quit; do not discard this hunk or any of the remaining ones\n" -"a - discard this hunk and all later hunks in the file\n" -"d - do not discard this hunk or any of the later hunks in the file" -msgstr "" -"y - loại bá» khúc nà y khá»i cây là m việc\n" -"n - đừng loại bá» khúc khá»i cây là m việc\n" -"q - thoát; đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" -"a - loại bá» khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin" - -msgid "" -"y - discard this hunk from index and worktree\n" -"n - do not discard this hunk from index and worktree\n" -"q - quit; do not discard this hunk or any of the remaining ones\n" -"a - discard this hunk and all later hunks in the file\n" -"d - do not discard this hunk or any of the later hunks in the file" -msgstr "" -"y - loại bá» khúc nà y khá»i mục lục và cây là m việc\n" -"n - đừng loại bá» khúc khá»i mục lục và cây là m việc\n" -"q - thoát; đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" -"a - loại bá» khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng loại bá» khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin" - -msgid "" -"y - apply this hunk to index and worktree\n" -"n - do not apply this hunk to index and worktree\n" -"q - quit; do not apply this hunk or any of the remaining ones\n" -"a - apply this hunk and all later hunks in the file\n" -"d - do not apply this hunk or any of the later hunks in the file" -msgstr "" -"y - áp dụng khúc nà y và o mục lục và cây là m việc\n" -"n - đừng áp dụng khúc và o mục lục và cây là m việc\n" -"q - thoát; đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" -"a - áp dụng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin" - -msgid "" -"y - apply this hunk to worktree\n" -"n - do not apply this hunk to worktree\n" -"q - quit; do not apply this hunk or any of the remaining ones\n" -"a - apply this hunk and all later hunks in the file\n" -"d - do not apply this hunk or any of the later hunks in the file" -msgstr "" -"y - áp dụng khúc nà y và o cây là m việc\n" -"n - đừng áp dụng khúc và o cây là m việc\n" -"q - thoát; đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o còn lại\n" -"a - áp dụng khúc nà y và tất cả các khúc sau nà y trong táºp tin\n" -"d - đừng áp dụng khúc nà y cÅ©ng nhÆ° bất kỳ cái nà o sau nà y trong táºp tin" - -msgid "" -"g - select a hunk to go to\n" -"/ - search for a hunk matching the given regex\n" -"j - leave this hunk undecided, see next undecided hunk\n" -"J - leave this hunk undecided, see next hunk\n" -"k - leave this hunk undecided, see previous undecided hunk\n" -"K - leave this hunk undecided, see previous hunk\n" -"s - split the current hunk into smaller hunks\n" -"e - manually edit the current hunk\n" -"? - print help\n" -msgstr "" -"g - chá»n má»™t khúc muốn tá»›i\n" -"/ - tìm má»™t khúc khá»›p vá»›i biểu thức chÃnh quy Ä‘Æ°a ra\n" -"j - để lại khúc nà y là chÆ°a quyết định, xem khúc chÆ°a quyết định kế\n" -"J - để lại khúc nà y là chÆ°a quyết định, xem khúc kế\n" -"k - để lại khúc nà y là chÆ°a quyết định, xem khúc chÆ°a quyết định kế trÆ°á»›c\n" -"K - để lại khúc nà y là chÆ°a quyết định, xem khúc kế trÆ°á»›c\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" -"? - in trợ giúp\n" - -msgid "The selected hunks do not apply to the index!\n" -msgstr "Các khúc đã chá»n không được áp dụng và o bảng mục lục!\n" - -#, perl-format -msgid "ignoring unmerged: %s\n" -msgstr "bá» qua những thứ chÆ°a hòa trá»™n: %s\n" - -#, perl-format -msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho cây là m việc [y,n,q,a,d%s,?]? " - -#, perl-format -msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng việc xóa cho cây là m việc [y,n,q,a,d%s,?]? " - -#, perl-format -msgid "Apply addition to worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng việc thêm cho cây là m việc [y,n,q,a,d%s,?]? " - -#, perl-format -msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? " -msgstr "Ãp dụng khúc nà y và o cây là m việc [y,n,q,a,d%s,?]? " - -msgid "No other hunks to goto\n" -msgstr "Không còn khúc nà o để mà nhảy đến\n" - -#, perl-format -msgid "Invalid number: '%s'\n" -msgstr "Số không hợp lệ: “%sâ€\n" - -#, perl-format -msgid "Sorry, only %d hunk available.\n" -msgid_plural "Sorry, only %d hunks available.\n" -msgstr[0] "Rất tiếc, chỉ có sẵn %d khúc.\n" - -msgid "No other hunks to search\n" -msgstr "Không còn khúc nà o để mà tìm kiếm\n" - -#, perl-format -msgid "Malformed search regexp %s: %s\n" -msgstr "Äịnh dạng tìm kiếm của biểu thức chÃnh quy không đúng %s: %s\n" - -msgid "No hunk matches the given pattern\n" -msgstr "Không thấy khúc nà o khá»›p mẫu đã cho\n" - -msgid "No previous hunk\n" -msgstr "Không có khúc kế trÆ°á»›c\n" - -msgid "No next hunk\n" -msgstr "Không có khúc kế tiếp\n" - -msgid "Sorry, cannot split this hunk\n" -msgstr "Rất tiếc, không thể chia nhá» khúc nà y\n" - -#, perl-format -msgid "Split into %d hunk.\n" -msgid_plural "Split into %d hunks.\n" -msgstr[0] "Chi nhá» thà nh %d khúc.\n" - -msgid "Sorry, cannot edit this hunk\n" -msgstr "Rất tiếc, không thể sá»a khúc nà y\n" - -#. TRANSLATORS: please do not translate the command names -#. 'status', 'update', 'revert', etc. -msgid "" -"status - show paths with changes\n" -"update - add working tree state to the staged set of changes\n" -"revert - revert staged set of changes back to the HEAD version\n" -"patch - pick hunks and update selectively\n" -"diff - view diff between HEAD and index\n" -"add untracked - add contents of untracked files to the staged set of " -"changes\n" -msgstr "" -"status - hiển thị các Ä‘Æ°á»ng dẫn vá»›i các thay đổi\n" -"update - đặt trạng thái cây là m việc thà nh táºp hợp các thay đổi đã " -"đặt lên bệ phóng\n" -"revert - hoà n nguyên táºp hợp các thay đổi đã đặt lên bệ phóng trở lại " -"phiên bản HEAD\n" -"patch - cáºy các khúc và cáºp nháºt có lá»±a chá»n\n" -"diff\t - xem khác biệt giữa HEAD và mục lục\n" -"add untracked - thêm ná»™i dung các các táºp tin chÆ°a theo dõi và táºp hợp các " -"thay đổi đã đặt lên bệ phóng\n" - -msgid "missing --" -msgstr "thiếu --" - -#, perl-format -msgid "unknown --patch mode: %s" -msgstr "không hiểu chế Ä‘á»™ --patch: %s" - -#, perl-format -msgid "invalid argument %s, expecting --" -msgstr "đối số không hợp lệ %s, cần --" - msgid "local zone differs from GMT by a non-minute interval\n" -msgstr "múi giá» ná»™i bá»™ khác biệt vá»›i GMT bởi khoảng thá»i gian không-phút\n" +msgstr "múi giá» ná»™i bá»™ lệch vá»›i GMT má»™t khoảng thá»i gian không-tròn-phút\n" msgid "local time offset greater than or equal to 24 hours\n" -msgstr "khoảng bù thá»i gian ná»™i bá»™ lá»›n hÆ¡n hoặc bằng 24 giá»\n" +msgstr "Ä‘á»™ lệch thá»i gian ná»™i bá»™ lá»›n hÆ¡n hoặc bằng 24 giá»\n" #, perl-format msgid "fatal: command '%s' died with exit code %d" -msgstr "lá»—i nghiêm trá»ng: lệnh “%s†chết vá»›i mã thoát %d" +msgstr "lá»—i nghiêm trá»ng: lệnh '%s' đã thoát vá»›i mã %d" msgid "the editor exited uncleanly, aborting everything" -msgstr "trình soạn thảo thoát không sạch sẽ, bãi bá» má»i thứ" +msgstr "trình soạn thảo thoát không thà nh công, huá»· bá» các thay đổi" #, perl-format msgid "" "'%s' contains an intermediate version of the email you were composing.\n" -msgstr "“%s†có chÆ°a má»™t phiên bản trung gian của thÆ° bạn đã soạn.\n" +msgstr "'%s' có chứa má»™t phiên bản trung gian của email bạn đã soạn.\n" #, perl-format msgid "'%s.final' contains the composed email.\n" -msgstr "“%s.final†chứa thÆ° Ä‘iện tỠđã soạn thảo.\n" +msgstr "'%s.final' chứa emal đã soạn thảo.\n" msgid "--dump-aliases incompatible with other options\n" -msgstr "--dump-aliases xung khắc vá»›i các tùy chá»n khác\n" +msgstr "--dump-aliases không tÆ°Æ¡ng thÃch vá»›i các tùy chá»n khác\n" msgid "" "fatal: found configuration options for 'sendmail'\n" "git-send-email is configured with the sendemail.* options - note the 'e'.\n" "Set sendemail.forbidSendmailVariables to false to disable this check.\n" msgstr "" -"lá»—i nghiêm trá»ng: tìm thấy các tùy chá»n cấu hình cho “sendmailâ€\n" -"git-send-email được cấu hình vá»›i các tùy chá»n sendemail.* - chú ý “eâ€.\n" +"lá»—i nghiêm trá»ng: tìm thấy các tùy chá»n cấu hình có tên 'sendmail'\n" +"git-send-email được cấu hình vá»›i các tùy chá»n sendemail.* - chú ý chữ 'e'.\n" "Äặt sendemail.forbidSendmailVariables thà nh false để tắt kiểm tra nà y.\n" msgid "Cannot run git format-patch from outside a repository\n" -msgstr "Không thể chạy git format-patch ở ngoà i má»™t kho chứa\n" +msgstr "Không thể chạy git format-patch ở ngoà i kho chứa\n" msgid "" "`batch-size` and `relogin` must be specified together (via command-line or " "configuration option)\n" msgstr "" -"“batch-size†và “relogin†phải được chỉ định cùng vá»›i nhau (thông qua dòng " -"lệnh hoặc tùy chá»n cấu hình)\n" +"'batch-size' và 'relogin' phải được chỉ định cùng nhau (thông qua dòng lệnh " +"hoặc tùy chá»n cấu hình)\n" #, perl-format msgid "Unknown --suppress-cc field: '%s'\n" -msgstr "Không hiểu trÆ°á»ng --suppress-cc: “%sâ€\n" +msgstr "Không hiểu trÆ°á»ng --suppress-cc: '%s'\n" #, perl-format msgid "Unknown --confirm setting: '%s'\n" -msgstr "Không hiểu cà i đặt --confirm: “%sâ€\n" +msgstr "Không hiểu cà i đặt --confirm: '%s'\n" #, perl-format msgid "warning: sendmail alias with quotes is not supported: %s\n" -msgstr "cảnh báo: bà danh sendmail vá»›i dấu trÃch dẫn không được há»— trợ: %s\n" +msgstr "cảnh báo: không há»— trợ bà danh sendmail vá»›i dấu trÃch dẫn: %s\n" #, perl-format msgid "warning: `:include:` not supported: %s\n" -msgstr "cảnh báo: “:include:“ không được há»— trợ: %s\n" +msgstr "cảnh báo: không há»— trợ ':include:': %s\n" #, perl-format msgid "warning: `/file` or `|pipe` redirection not supported: %s\n" -msgstr "cảnh báo: chuyển hÆ°á»›ng “/file“ hay “|pipe“ không được há»— trợ: %s\n" +msgstr "cảnh báo: không há»— trợ chuyển hÆ°á»›ng '/file' hay '|pipe': %s\n" #, perl-format msgid "warning: sendmail line is not recognized: %s\n" -msgstr "cảnh báo: dòng sendmail không nháºn ra được: %s\n" +msgstr "cảnh báo: không hiểu dòng cấu hình sendmail: %s\n" #, perl-format msgid "" @@ -21627,15 +22623,15 @@ msgid "" " * Saying \"./%s\" if you mean a file; or\n" " * Giving --format-patch option if you mean a range.\n" msgstr "" -"Táºp tin “%s†đã có sẵn nhÆ°ng nó có lẽ cÅ©ng là chuẩn bị của\n" -"các miếng vá tạo lần chuyển giao. Vui lòng là m rõ ý bằng…\n" +"Táºp tin '%s' có tồn tại nhÆ°ng cÅ©ng có thể hiểu là cần tạo bản vá cho\n" +"má»™t khoảng các lần chuyển giao. Vui lòng là m rõ ý của bạn bằng...\n" "\n" -" * Nói \"./%s\" nếu ý bạn là má»™t táºp tin; hoặc\n" -" * ÄÆ°a ra tùy chá»n --format-patch nếu ý bạn là chuẩn bị.\n" +" * Ghi \"./%s\" nếu ý bạn là táºp tin; hoặc\n" +" * ÄÆ°a ra tùy chá»n --format-patch nếu ý bạn là tạo bản vá.\n" #, perl-format msgid "Failed to opendir %s: %s" -msgstr "Gặp lá»—i khi mở thÆ° mục “%sâ€: %s" +msgstr "Gặp lá»—i khi opendir %s: %s" msgid "" "\n" @@ -21643,7 +22639,7 @@ msgid "" "\n" msgstr "" "\n" -"ChÆ°a chỉ định các táºp tin miếng vá!\n" +"ChÆ°a chỉ định các táºp tin bản vá!\n" "\n" #, perl-format @@ -21652,7 +22648,7 @@ msgstr "Không có dòng chủ Ä‘á» trong %s?" #, perl-format msgid "Failed to open for writing %s: %s" -msgstr "Gặp lá»—i khi mở “%s†để ghi: %s" +msgstr "Gặp lá»—i khi mở %s để ghi: %s" msgid "" "Lines beginning in \"GIT:\" will be removed.\n" @@ -21662,21 +22658,21 @@ msgid "" "Clear the body content if you don't wish to send a summary.\n" msgstr "" "Các dòng bắt đầu bằng \"GIT:\" sẽ bị xóa bá».\n" -"Cân nhắc bao gồm má»™t thống kê diff toà n thể hay bảng ná»™i dung\n" -"cho miếng vá mà bạn Ä‘ang viết.\n" +"Hãy cân nhắc bao gồm má»™t bản diffstat hay chỉ mục\n" +"cho bản vá bạn Ä‘ang viết.\n" "\n" "Xóa ná»™i dung phần thân nếu bạn không muốn gá»i tóm tắt.\n" #, perl-format -msgid "Failed to open %s: %s" -msgstr "Gặp lá»—i khi mở “%sâ€: %s" - -#, perl-format msgid "Failed to open %s.final: %s" msgstr "Gặp lá»—i khi mở %s.final: %s" +#, perl-format +msgid "Failed to open %s: %s" +msgstr "Gặp lá»—i khi mở %s: %s" + msgid "Summary email is empty, skipping it\n" -msgstr "ThÆ° tổng thể là trống rá»—ng, nên bá» qua nó\n" +msgstr "ThÆ° tóm tắt trống, nên sẽ bá» qua\n" #. TRANSLATORS: please keep [y/N] as is. #, perl-format @@ -21687,11 +22683,10 @@ msgid "" "The following files are 8bit, but do not declare a Content-Transfer-" "Encoding.\n" msgstr "" -"Các trÆ°á»ng sau đây là 8bit, nhÆ°ng không khai báo má»™t Content-Transfer-" -"Encoding.\n" +"Các trÆ°á»ng sau đây là 8bit, nhÆ°ng không khai báo Content-Transfer-Encoding.\n" msgid "Which 8bit encoding should I declare [UTF-8]? " -msgstr "Bảng mã 8bit nà o tôi nên khai báo [UTF-8]? " +msgstr "Nên khai báo bảng mã 8bit nà o [UTF-8]? " #, perl-format msgid "" @@ -21700,24 +22695,24 @@ msgid "" "has the template subject '*** SUBJECT HERE ***'. Pass --force if you really " "want to send.\n" msgstr "" -"Từ chối gá»i bởi vì miếng vá\n" +"Từ chối gá»i vì bản vá\n" "\t%s\n" -"có chủ đỠở dạng mẫu “*** SUBJECT HERE ***â€. Dùng --force nếu bạn thá»±c sá»± " +"có chủ đỠở dạng mẫu '*** SUBJECT HERE ***'. Dùng --force nếu bạn thá»±c sá»± " "muốn gá»i.\n" msgid "To whom should the emails be sent (if anyone)?" -msgstr "Tá»›i ngÆ°á»i mà thÆ° được gá»i (nếu có)?" +msgstr "Gá»i email đến ai (nếu có)?" #, perl-format msgid "fatal: alias '%s' expands to itself\n" -msgstr "nghiêm trá»ng: bà danh “%s†được khai triển thà nh chÃnh nó\n" +msgstr "lá»—i nghiêm trá»ng: khai triển bà danh '%s' lại thà nh chÃnh nó\n" msgid "Message-ID to be used as In-Reply-To for the first email (if any)? " -msgstr "Message-ID được dùng nhÆ° là In-Reply-To cho thÆ° đầu tiên (nếu có)? " +msgstr "Dùng Message-ID nhÆ° In-Reply-To cho email đầu tiên (nếu có)? " #, perl-format msgid "error: unable to extract a valid address from: %s\n" -msgstr "lá»—i: không thể rút trÃch má»™t địa chỉ hợp lệ từ: %s\n" +msgstr "lá»—i: không thể trÃch xuất địa chỉ hợp lệ từ: %s\n" #. TRANSLATORS: Make sure to include [q] [d] [e] in your #. translation. The program will only accept English input @@ -21727,7 +22722,7 @@ msgstr "Là m gì vá»›i địa chỉ nà y? (thoát[q]|xóa[d]|sá»a[e]): " #, perl-format msgid "CA path \"%s\" does not exist" -msgstr "ÄÆ°á»ng dẫn CA “%s†không tồn tại" +msgstr "CA path '%s' không tồn tại" msgid "" " The Cc list above has been expanded by additional\n" @@ -21741,28 +22736,28 @@ msgid "" " run 'git config --global sendemail.confirm auto'.\n" "\n" msgstr "" -" Danh sách Cc ở trên được diá»…n giải bằng các địa chỉ phụ\n" -" thêm tìm thấy trong lá»i ghi chú lần chuyển giao của miếng vá.\n" -" Theo mặc định send-email sẽ nhắc trÆ°á»›c khi gá»i bất cứ khi\n" -" nà o Ä‘iá»u nà y xảy ra. Cách hà nh xá» nà y được Ä‘iá»u khiển bởi cà i\n" +" Danh sách Cc ở trên đã được thêm các địa chỉ có trong\n" +" ná»™i dung lần chuyển giao của bản vá. Theo mặc định\n" +" send-email sẽ nhắc bạn trÆ°á»›c khi gá»i má»—i khi Ä‘iá»u nà y \n" +" xảy ra. Bạn có thể Ä‘iá»u chỉnh hà nh vi nà y qua cà i\n" " đặt cấu hình sendemail.confirm.\n" "\n" -" Äể biết thêm chi tiết, hãy chạy lệnh “git send-email --helpâ€.\n" -" Äể giữ lại cách hà nh xá» hiện nay, là m hết lá»i nhắn nà y,\n" -" chạy “git config --global sendemail.confirm autoâ€.\n" +" Äể biết thêm chi tiết, hãy chạy lệnh 'git send-email --help'.\n" +" Äể tiếp tục sá» dụng hà nh vi nà y, nhÆ°ng bá» hiển thị lá»i nhắc,\n" +" chạy 'git config --global sendemail.confirm auto'.\n" "\n" #. TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your #. 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 thÆ° 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): " msgid "Send this email reply required" -msgstr "Gá»i thÆ° nà y trả lá»i yêu cầu" +msgstr "Hãy trả lá»i yêu cầu gá»i email" msgid "The required SMTP server is not properly defined." -msgstr "Máy phục vụ SMTP chÆ°a được định nghÄ©a má»™t cách thÃch hợp." +msgstr "Máy chủ SMTP chÆ°a được định nghÄ©a đúng cách." #, perl-format msgid "Server does not support STARTTLS! %s" @@ -21774,8 +22769,7 @@ msgstr "STARTTLS gặp lá»—i! %s" msgid "Unable to initialize SMTP properly. Check config and use --smtp-debug." msgstr "" -"Không thể khởi tạo SMTP má»™t cách đúng đắn. Kiểm tra cấu hình và dùng --smtp-" -"debug." +"Không thể khởi tạo SMTP đúng cách. Kiểm tra cấu hình và dùng --smtp-debug." #, perl-format msgid "Failed to send %s\n" @@ -21790,51 +22784,55 @@ msgid "Sent %s\n" msgstr "Gá»i %s\n" msgid "Dry-OK. Log says:\n" -msgstr "Dry-OK. Nháºt ký nói rằng:\n" +msgstr "Thá» gá»i OK. Nháºt ký ghi lại:\n" msgid "OK. Log says:\n" -msgstr "OK. Nháºt ký nói rằng:\n" +msgstr "OK. Nháºt ký ghi lại:\n" msgid "Result: " msgstr "Kết quả: " msgid "Result: OK\n" -msgstr "Kết quả: Tốt\n" +msgstr "Kết quả: OK\n" #, perl-format msgid "can't open file %s" -msgstr "không thể mở táºp tin “%sâ€" +msgstr "không thể mở táºp tin '%s'" #, perl-format msgid "(mbox) Adding cc: %s from line '%s'\n" -msgstr "(mbox) Thêm cc: %s từ dòng “%sâ€\n" +msgstr "(mbox) Thêm cc: %s từ dòng '%s'\n" #, perl-format msgid "(mbox) Adding to: %s from line '%s'\n" -msgstr "(mbox) Äang thêm to: %s từ dòng “%sâ€\n" +msgstr "(mbox) Thêm to: %s từ dòng '%s'\n" #, perl-format msgid "(non-mbox) Adding cc: %s from line '%s'\n" -msgstr "(non-mbox) Thêm cc: %s từ dòng “%sâ€\n" +msgstr "(non-mbox) Thêm cc: %s từ dòng '%s'\n" #, perl-format msgid "(body) Adding cc: %s from line '%s'\n" -msgstr "(body) Thêm cc: %s từ dòng “%sâ€\n" +msgstr "(body) Thêm cc: %s từ dòng '%s'\n" #, perl-format msgid "(%s) Could not execute '%s'" -msgstr "(%s) Không thể thá»±c thi “%sâ€" +msgstr "(%s) Không thể thá»±c thi '%s'" #, perl-format -msgid "(%s) Adding %s: %s from: '%s'\n" -msgstr "(%s) Äang thêm %s: %s từ: “%sâ€\n" +msgid "(%s) Malformed output from '%s'" +msgstr "(%s) Dòng đầu ra sai quy cách từ '%s'" #, perl-format msgid "(%s) failed to close pipe to '%s'" -msgstr "(%s) gặp lá»—i khi đóng Ä‘Æ°á»ng ống đến “%sâ€" +msgstr "(%s) gặp lá»—i khi đóng pipe đến '%s'" + +#, perl-format +msgid "(%s) Adding %s: %s from: '%s'\n" +msgstr "(%s) Thêm %s: %s từ: '%s'\n" msgid "cannot send message as 7bit" -msgstr "không thể lấy gá»i thÆ° dạng 7 bÃt" +msgstr "không thể gá»i thÆ° dạng 7bit" msgid "invalid transfer encoding" msgstr "bảng mã truyá»n không hợp lệ" @@ -21845,9 +22843,9 @@ msgid "" "%s\n" "warning: no patches were sent\n" msgstr "" -"nghiêm trá»ng: %s: bị từ chối bởi móc %s\n" +"nghiêm trá»ng: %s: bị từ chối bởi hook %s\n" "%s\n" -"cảnh báo: không có miếng vá nà o được gá»i Ä‘i\n" +"cảnh báo: không gá»i Ä‘i bản vá nà o\n" #, perl-format msgid "unable to open %s: %s\n" @@ -21858,307 +22856,14 @@ msgid "" "fatal: %s:%d is longer than 998 characters\n" "warning: no patches were sent\n" msgstr "" -"nghiêm trá»ng: %s: %d là dà i hÆ¡n 998 ký tá»±\n" -"cảnh báo: không có miếng vá nà o được gá»i Ä‘i\n" +"nghiêm trá»ng: %s: %d dà i hÆ¡n 998 ký tá»±\n" +"cảnh báo: không có bản vá nà o được gá»i Ä‘i\n" #, perl-format msgid "Skipping %s with backup suffix '%s'.\n" -msgstr "Bá» qua %s vá»›i háºu tố sao lÆ°u dá»± phòng “%sâ€.\n" +msgstr "Bá» qua %s vá»›i háºu tố sao lÆ°u '%s'.\n" #. TRANSLATORS: please keep "[y|N]" as is. #, perl-format msgid "Do you really want to send %s? [y|N]: " msgstr "Bạn có thá»±c sá»± muốn gá»i %s? [y|N](có/KHÔNG): " - -#~ msgid "--preserve-merges was replaced by --rebase-merges" -#~ msgstr "--preserve-merges đã bị thay thế bằng --rebase-merges" - -#, c-format -#~ msgid "" -#~ "CRLF will be replaced by LF in %s.\n" -#~ "The file will have its original line endings in your working directory" -#~ msgstr "" -#~ "CRLF sẽ bị thay thế bằng LF trong %s.\n" -#~ "Táºp tin sẽ có kiểu xuống dòng nhÆ° bản gốc trong thÆ° mục là m việc của bạn" - -#, c-format -#~ msgid "" -#~ "LF will be replaced by CRLF in %s.\n" -#~ "The file will have its original line endings in your working directory" -#~ msgstr "" -#~ "LF sẽ bị thay thế bằng CRLF trong %s.\n" -#~ "Táºp tin sẽ có kiểu xuống dòng nhÆ° bản gốc trong thÆ° mục là m việc của bạn" - -#, c-format -#~ msgid "error reading section header '%s'" -#~ msgstr "gặp lá»—i khi Ä‘á»c phần đầu của Ä‘oạn %s" - -#~ msgid "load_reverse_index: could not open pack" -#~ msgstr "load_reverse_index: không thể mở gói" - -#, perl-format -#~ msgid "fatal: %s: rejected by %s hook\n" -#~ msgstr "lá»—i nghiêm trá»ng: %s: bị từ chối bởi móc %s\n" - -#~ msgid "git archive --list" -#~ msgstr "git archive --list" - -#, c-format -#~ msgid "unknown value for --diff-merges: %s" -#~ msgstr "không hiểu giá trị cho --diff-merges: %s" - -#, c-format -#~ msgid "invalid value '%s' for lsrefs.unborn" -#~ msgstr "giá trị “%s†không hợp lệ cho lsrefs.unborn" - -#~ msgid "backend for `git stash -p`" -#~ msgstr "ứng dụng chạy phÃa sau cho “git stash -pâ€" - -#, c-format -#~ msgid "Invalid value for --empty: %s" -#~ msgstr "Giá trị cho --empty không hợp lệ: %s" - -#, c-format -#~ msgid "Invalid value for --patch-format: %s" -#~ msgstr "Giá trị không hợp lệ cho --patch-format: %s" - -#, c-format -#~ msgid "Invalid value for --show-current-patch: %s" -#~ msgstr "Giá trị không hợp lệ cho --show-current-patch: %s" - -#~ msgid "" -#~ "git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad " -#~ "| --term-new]" -#~ msgstr "" -#~ "git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad " -#~ "| --term-new]" - -#~ msgid "git bisect--helper --bisect-next" -#~ msgstr "git bisect--helper --bisect-next" - -#~ msgid "git bisect--helper --bisect-visualize" -#~ msgstr "git bisect--helper --bisect-visualize" - -#, c-format -#~ msgid "invalid color '%s' in color.blame.repeatedLines" -#~ msgstr "mà u không hợp lệ “%s†trong color.blame.repeatedLines" - -#~ msgid "invalid value for blame.coloring" -#~ msgstr "mà u không hợp lệ cho blame.coloring" - -#~ msgid "" -#~ "git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e " -#~ "| -p | <type> | --textconv | --filters) [--path=<path>] <object>" -#~ msgstr "" -#~ "git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e " -#~ "| -p | <kiểu> | --textconv) | --filters) [--path=<Ä‘Æ°á»ng/dẫn>] <đối_tượng>" - -#~ msgid "show object type" -#~ msgstr "hiển thị kiểu đối tượng" - -#~ msgid "exit with zero when there's no error" -#~ msgstr "thoát vá»›i 0 khi không có lá»—i" - -#~ msgid "show info and content of objects fed from the standard input" -#~ msgstr "" -#~ "hiển thị thông tin và ná»™i dung của các đối tượng lấy từ đầu và o tiêu chuẩn" - -#~ msgid "show info about objects fed from the standard input" -#~ msgstr "hiển thị các thông tin vỠđối tượng fed từ đầu và o tiêu chuẩn" - -#~ msgid "follow in-tree symlinks (used with --batch or --batch-check)" -#~ msgstr "" -#~ "theo liên kết má»m trong-cây (được dùng vá»›i --batch hay --batch-check)" - -#~ msgid "show all objects with --batch or --batch-check" -#~ msgstr "hiển thị má»i đối tượng vá»›i --batch hay --batch-check" - -#~ msgid "do not order --batch-all-objects output" -#~ msgstr "đừng sắp xếp đầu ra --batch-all-objects" - -#~ msgid "set up tracking mode (see git-pull(1))" -#~ msgstr "cà i đặt chế Ä‘á»™ theo dõi (xem git-pull(1))" - -#~ msgid "Using both --reset-author and --author does not make sense" -#~ msgstr "Sá» dụng cả hai tùy chá»n --reset-author và --author không hợp lý" - -#~ msgid "Options --squash and --fixup cannot be used together" -#~ msgstr "Các tùy chá»n --squash và --fixup không thể sá» dụng cùng vá»›i nhau" - -#~ msgid "Only one of -c/-C/-F/--fixup can be used." -#~ msgstr "Chỉ được dùng má»™t trong số tùy chá»n trong số -c/-C/-F/--fixup." - -#~ msgid "Option -m cannot be combined with -c/-C/-F." -#~ msgstr "Tùy chá»n -m không thể được tổ hợp cùng vá»›i -c/-C/-F." - -#~ msgid "" -#~ "Only one of --include/--only/--all/--interactive/--patch can be used." -#~ msgstr "" -#~ "Chỉ má»™t trong các tùy chá»n --include/--only/--all/--interactive/--patch " -#~ "được sá» dụng." - -#~ msgid "git count-objects [-v] [-H | --human-readable]" -#~ msgstr "git count-objects [-v] [-H | --human-readable]" - -#, c-format -#~ msgid "configuration fetch.output contains invalid value %s" -#~ msgstr "phần cấu hình fetch.output có chứa giá-trị không hợp lệ %s" - -#~ msgid "--cached or --untracked cannot be used with --no-index" -#~ msgstr "--cached hay --untracked không được sá» dụng vá»›i --no-index" - -#~ msgid "--untracked cannot be used with --cached" -#~ msgstr "--untracked không thể được sá» dụng vá»›i tùy chá»n --cached" - -#~ msgid "git hash-object --stdin-paths" -#~ msgstr "git hash-object --stdin-paths" - -#~ msgid "git help [-g|--guides]" -#~ msgstr "git help [-g|--guides]" - -#~ msgid "git help [-c|--config]" -#~ msgstr "git help [-c|--config]" - -#~ msgid "git mktag" -#~ msgstr "git mktag" - -#~ msgid "git mktree [-z] [--missing] [--batch]" -#~ msgstr "git mktree [-z] [--missing] [--batch]" - -#~ msgid "read from stdin" -#~ msgstr "Ä‘á»c từ đầu và o tiêu chuẩn" - -#~ msgid "git notes merge --commit [-v | -q]" -#~ msgstr "git notes merge --commit [-v | -q]" - -#~ msgid "git notes merge --abort [-v | -q]" -#~ msgstr "git notes merge --abort [-v | -q]" - -#~ msgid "git notes get-ref" -#~ msgstr "git notes get-ref" - -#~ msgid "invalid value for --missing" -#~ msgstr "giá trị cho --missing không hợp lệ" - -#~ msgid "git prune-packed [-n | --dry-run] [-q | --quiet]" -#~ msgstr "git prune-packed [-n | --dry-run] [-q | --quiet]" - -#, c-format -#~ msgid "Invalid value for %s: %s" -#~ msgstr "Giá trị không hợp lệ %s: %s" - -#, c-format -#~ msgid "Invalid value for pull.ff: %s" -#~ msgstr "Giá trị không hợp lệ cho pull.ff: %s" - -#~ msgid "git rebase --continue | --abort | --skip | --edit-todo" -#~ msgstr "git rebase --continue | --abort | --skip | --edit-todo" - -#, c-format -#~ msgid "'%s' is not a valid timestamp" -#~ msgstr "“%s†không phải là dấu thá»i gian hợp lệ" - -#~ msgid "git reflog [ show | expire | delete | exists ]" -#~ msgstr "git reflog [ show | expire | delete | exists ]" - -#~ msgid "git remote [-v | --verbose]" -#~ msgstr "git remote [-v | --verbose]" - -#~ msgid "git replace [-f] --convert-graft-file" -#~ msgstr "git replace [-f] --convert-graft-file" - -#, c-format -#~ msgid "" -#~ "\n" -#~ "It took %.2f seconds to enumerate unstaged changes after reset. You can\n" -#~ "use '--quiet' to avoid this. Set the config setting reset.quiet to true\n" -#~ "to make this the default.\n" -#~ msgstr "" -#~ "\n" -#~ "Cần %.2f giây để kiểm đếm các thay đổi chÆ°a Ä‘Æ°a lên bệ phóng sau khi đặt " -#~ "lại.\n" -#~ "Bạn có thể sá» dụng “--quiet†để tránh việc nà y. Äặt reset.quiet thà nh " -#~ "true trong\n" -#~ "cà i đặt config nếu bạn muốn thá»±c hiện nó nhÆ° là mặc định.\n" - -#~ msgid "git sparse-checkout list" -#~ msgstr "git sparse-checkout list" - -#~ msgid "unable to upgrade repository format to enable worktreeConfig" -#~ msgstr "" -#~ "không thể nâng cấp định dạng kho lÆ°u trữ để kÃch hoạt worktreeConfig" - -#~ msgid "git sparse-checkout init [--cone] [--[no-]sparse-index]" -#~ msgstr "git sparse-checkout init [--cone] [--[no-]sparse-index]" - -#~ msgid "git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]" -#~ msgstr "git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]" - -#~ msgid "git sparse-checkout disable" -#~ msgstr "git sparse-checkout disable" - -#~ msgid "" -#~ "the stash.useBuiltin support has been removed!\n" -#~ "See its entry in 'git help config' for details." -#~ msgstr "" -#~ "việc há»— trợ stash.useBuiltin đã bị xóa!\n" -#~ "Xem mục tin của nó trong “git help config†để biết chi tiết." - -#~ msgid "git stripspace [-s | --strip-comments]" -#~ msgstr "git stripspace [-s | --strip-comments]" - -#~ msgid "git stripspace [-c | --comment-lines]" -#~ msgstr "git stripspace [-c | --comment-lines]" - -#~ msgid "submodule--helper print-default-remote takes no arguments" -#~ msgstr "submodule--helper print-default-remote takes không nháºn tham số" - -#~ msgid "git submodule--helper update-clone [--prefix=<path>] [<path>...]" -#~ msgstr "" -#~ "git submodule--helper update-clone [--prefix=</Ä‘Æ°á»ng/dẫn>] [</Ä‘Æ°á»ng/dẫn>…]" - -#~ msgid "suppress output for update by rebase or merge" -#~ msgstr "chặn kết xuất cho cáºp nháºt bởi cải tổ hoặc hòa trá»™n" - -#~ msgid "overrides update mode in case the repository is a fresh clone" -#~ msgstr "ghi đè chế Ä‘á»™ cáºp nháºt trong trÆ°á»ng hợp kho lÆ°u trữ là bản sao má»›i" - -#~ msgid "depth for shallow fetch" -#~ msgstr "chiá»u sâu lịch sá» muốn lấy vá»" - -#~ msgid "sha1" -#~ msgstr "sha1" - -#~ msgid "SHA1 expected by superproject" -#~ msgstr "SHA1 là cần thiết cho superproject" - -#~ msgid "subsha1" -#~ msgstr "subsha1" - -#~ msgid "SHA1 of submodule's HEAD" -#~ msgstr "SHA1 của HEAD của mô-Ä‘un-con" - -#~ msgid "git submodule--helper run-update-procedure [<options>] <path>" -#~ msgstr "" -#~ "git submodule--helper run-update-procedure [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn>" - -#~ msgid "git submodule--helper config --check-writeable" -#~ msgstr "git submodule--helper config --check-writeable" - -#~ msgid "git update-server-info [--force]" -#~ msgstr "git update-server-info [--force]" - -#~ msgid "Initialize and modify the sparse-checkout" -#~ msgstr "Khởi tạo và sá»a đổi sparse-checkout" - -#, sh-format -#~ msgid "" -#~ "Unable to find current ${remote_name}/${branch} revision in submodule " -#~ "path '$sm_path'" -#~ msgstr "" -#~ "Không thể tìm thấy Ä‘iểm xét duyệt hiện hà nh ${remote_name}/${branch} " -#~ "trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “$sm_pathâ€" - -#, sh-format -#~ msgid "Failed to recurse into submodule path '$displaypath'" -#~ msgstr "Gặp lá»—i khi đệ quy và o trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “$displaypathâ€" diff --git a/po/zh_CN.po b/po/zh_CN.po index 39efaf1012..4838c19b0b 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -103,6 +103,7 @@ # preferred pack | 首选包(多包索引ä¸å¼•å…¥çš„首选包概念) # promisor | 承诺者 # prune | 清除 +# pseudorefs | 伪引用 # pull | æ‹‰ï¼Œæ‹‰å– # push | æŽ¨ï¼ŒæŽ¨é€ # reachable | å¯è¾¾ @@ -153,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-02-16 14:27+0800\n" -"PO-Revision-Date: 2024-02-18 11:47+0800\n" +"POT-Creation-Date: 2024-04-28 19:59+0800\n" +"PO-Revision-Date: 2024-04-28 20:31+0800\n" "Last-Translator: Teng Long <dyroneteng@gmail.com>\n" "Language-Team: GitHub <https://github.com/dyrone/git/>\n" "Language: zh_CN\n" @@ -726,12 +727,12 @@ 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" "è¦åˆ 除 '%c' 开始的行,使其æˆä¸º ' ' 开始的行(上下文)。\n" "è¦åˆ 除 '%c' å¼€å§‹çš„è¡Œï¼Œåˆ é™¤å®ƒä»¬ã€‚\n" -"以 %c å¼€å§‹çš„è¡Œå°†è¢«åˆ é™¤ã€‚\n" +"以 %s å¼€å§‹çš„è¡Œå°†è¢«åˆ é™¤ã€‚\n" #: add-patch.c msgid "" @@ -783,6 +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" "? - print help\n" msgstr "" "j - ç»´æŒè¯¥å—未决状æ€ï¼ŒæŸ¥çœ‹ä¸‹ä¸€ä¸ªæœªå†³å—\n" @@ -793,6 +795,7 @@ msgstr "" "/ - 查找和给定æ£åˆ™è¡¨è¾¾å¼åŒ¹é…çš„å—\n" "s - 拆分当å‰å—为更å°çš„å—\n" "e - 手动编辑当å‰å—\n" +"p - 显示当å‰å—\n" "? - 显示帮助\n" #: add-patch.c @@ -872,8 +875,8 @@ msgstr "" #: advice.c #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sæ示:%.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sæ示:%s%.*s%s\n" #: advice.c msgid "Cherry-picking is not possible because you have unmerged files." @@ -1471,11 +1474,6 @@ msgstr[1] "应用 %%s 个补ä¸ï¼Œå…¶ä¸ %d 个被拒ç»..." #: apply.c #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "æˆªçŸ .rej 文件å为 %.*s.rej" - -#: apply.c -#, c-format msgid "cannot open %s" msgstr "ä¸èƒ½æ‰“å¼€ %s" @@ -2013,6 +2011,11 @@ msgstr "需è¦ä¸€ä¸ª %s 版本" msgid "could not create file '%s'" msgstr "ä¸èƒ½åˆ›å»ºæ–‡ä»¶ '%s'" +#: bisect.c builtin/notes.c +#, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "ä¸èƒ½ä¸ºå¯¹è±¡ '%s' 开始 'show'" + #: bisect.c builtin/merge.c #, c-format msgid "could not read file '%s'" @@ -2062,8 +2065,8 @@ 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 -#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c -#: sequencer.c submodule.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 "版本é历åˆå§‹åŒ–失败" @@ -2180,6 +2183,10 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "'%s' ä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„分支å称" +#: branch.c builtin/branch.c +msgid "See `man git check-ref-format`" +msgstr "查阅 `man git check-ref-format`" + #: branch.c #, c-format msgid "a branch named '%s' already exists" @@ -2410,14 +2417,8 @@ msgid "adding embedded git repository: %s" msgstr "æ£åœ¨æ·»åŠ åµŒå…¥å¼ git 仓库:%s" #: builtin/add.c -msgid "" -"Use -f if you really want to add them.\n" -"Turn this message off by running\n" -"\"git config advice.addIgnoredFile false\"" -msgstr "" -"如果您确实è¦æ·»åŠ 它们,使用 -f å‚数。\n" -"è¿è¡Œä¸‹é¢çš„命令æ¥å…³é—本消æ¯\n" -"\"git config advice.addIgnoredFile false\"" +msgid "Use -f if you really want to add them." +msgstr "å¦‚æžœæ‚¨ç¡®å®žæƒ³æ·»åŠ å®ƒä»¬ï¼Œè¯·ä½¿ç”¨ -f 选项。" #: builtin/add.c msgid "adding files failed" @@ -2440,14 +2441,8 @@ msgid "Nothing specified, nothing added.\n" msgstr "æ²¡æœ‰æŒ‡å®šæ–‡ä»¶ï¼Œä¹Ÿæ²¡æœ‰æ–‡ä»¶è¢«æ·»åŠ ã€‚\n" #: builtin/add.c -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"也许您想è¦æ‰§è¡Œ 'git add .'?\n" -"è¿è¡Œä¸‹é¢çš„命令æ¥å…³é—本消æ¯\n" -"\"git config advice.addEmptyPathspec false\"" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "也许您想è¦æ‰§è¡Œ '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 @@ -2467,8 +2462,8 @@ msgid "bad action '%s' for '%s'" msgstr "'%2$s' 的错误动作 '%1$s'" #: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c -#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c -#: parallel-checkout.c sequencer.c setup.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'" @@ -2552,18 +2547,19 @@ msgstr "æ— æ³•æ‹†åˆ†è¡¥ä¸ã€‚" #: builtin/am.c #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "当您解决这一问题,执行 \"%s --continue\"。" +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "当您解决这一问题之åŽï¼Œæ‰§è¡Œ \"%s --continue\"。\n" #: builtin/am.c #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "如果您想è¦è·³è¿‡è¿™ä¸€è¡¥ä¸ï¼Œåˆ™æ‰§è¡Œ \"%s --skip\"。" +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "如果您想è¦è·³è¿‡è¿™ä¸€è¡¥ä¸ï¼Œåˆ™æ‰§è¡Œ \"%s --skip\"。\n" #: builtin/am.c #, c-format -msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"." -msgstr "è‹¥è¦æŠŠç©ºè¡¥ä¸è®°å½•ä¸ºç©ºæ交,执行 \"%s --allow-empty\"。" +msgid "" +"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n" +msgstr "è‹¥è¦æŠŠç©ºè¡¥ä¸è®°å½•ä¸ºç©ºæ交,执行 \"%s --allow-empty\"。\n" #: builtin/am.c #, c-format @@ -3623,11 +3619,11 @@ msgstr "分支已拷è´ï¼Œä½†æ›´æ–°é…置文件失败" 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 "" "请编辑分支的æè¿°\n" " %s\n" -"以 '%c' 开头的行将被过滤。\n" +"以 '%s' 开头的行将被过滤。\n" #: builtin/branch.c msgid "Generic options" @@ -3883,10 +3879,12 @@ msgstr "ä¸æ˜¯åœ¨ git 仓库ä¸æ‰§è¡Œ - 没有å¯æ˜¾ç¤ºçš„é’©å\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 <文件>] [(-s|--suffix) <æ ¼å¼>]\n" +"git bugreport [-o | --output-directory <文件>]\n" +" [(-s | --suffix) <æ ¼å¼> | --no-suffix]\n" " [--diagnose[=<模å¼>]" #: builtin/bugreport.c @@ -4488,6 +4486,12 @@ msgstr "'%s'ã€'%s' 或 '%s' ä¸èƒ½åœ¨æ£€å‡ºä¸€ä¸ªæ ‘时使用" msgid "path '%s' is unmerged" 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 +#, c-format +msgid "unable to read tree (%s)" +msgstr "æ— æ³•è¯»å–æ ‘ï¼ˆ%s)" + #: builtin/checkout.c msgid "you need to resolve your current index first" msgstr "您需è¦å…ˆè§£å†³å½“å‰ç´¢å¼•çš„冲çª" @@ -4755,6 +4759,11 @@ msgid "missing branch or commit argument" msgstr "缺少分支或æ交å‚æ•°" #: builtin/checkout.c +#, c-format +msgid "unknown conflict style '%s'" +msgstr "未知的冲çªé£Žæ ¼ '%s'" + +#: builtin/checkout.c msgid "perform a 3-way merge with the new branch" msgstr "和新的分支执行三方åˆå¹¶" @@ -5074,18 +5083,8 @@ msgid "remove only ignored files" msgstr "åªåˆ 除忽略的文件" #: builtin/clean.c -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce 设置为 true 且未æä¾› -iã€-n 或 -f 选项,拒ç»æ‰§è¡Œæ¸…ç†åŠ¨ä½œ" - -#: builtin/clean.c -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" -msgstr "" -"clean.requireForce 默认为 true 且未æä¾› -iã€-n 或 -f 选项,拒ç»æ‰§è¡Œæ¸…ç†åŠ¨ä½œ" +msgid "clean.requireForce is true and -f not given: refusing to clean" +msgstr "clean.requireForce 设置为 true 且未æä¾› -f 选项:拒ç»æ‰§è¡Œæ¸…ç†åŠ¨ä½œ" #: builtin/clone.c msgid "git clone [<options>] [--] <repo> [<dir>]" @@ -5104,8 +5103,8 @@ msgid "create a bare repository" msgstr "创建一个纯仓库" #: builtin/clone.c -msgid "create a mirror repository (implies bare)" -msgstr "创建一个镜åƒä»“库(也是纯仓库)" +msgid "create a mirror repository (implies --bare)" +msgstr "创建一个镜åƒä»“库(éšå« --bare)" #: builtin/clone.c msgid "to clone from a local repository" @@ -5507,6 +5506,11 @@ msgid "padding space between columns" msgstr "两列之间的填充空间" #: builtin/column.c +#, c-format +msgid "%s must be non-negative" +msgstr "%s 必须为éžè´Ÿæ•´æ•°" + +#: builtin/column.c msgid "--command must be the first argument" msgstr "--command 必须是第一个å‚æ•°" @@ -5839,7 +5843,7 @@ msgid "" "in the current commit message" msgstr "æ— æ³•é€‰æ‹©ä¸€ä¸ªæœªè¢«å½“å‰æ交说明使用的注释å—符" -#: builtin/commit.c builtin/merge-tree.c +#: builtin/commit.c #, c-format msgid "could not lookup commit '%s'" msgstr "ä¸èƒ½æŸ¥è¯¢æ交 '%s'" @@ -5884,35 +5888,35 @@ msgstr "ä¸èƒ½å†™æ交模版" #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" -"with '%c' will be ignored.\n" -msgstr "请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被忽略。\n" +"with '%s' will be ignored.\n" +msgstr "请为您的å˜æ›´è¾“å…¥æ交说明。以 '%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 "" -"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被忽略,而一个空的æ交\n" +"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%s' 开始的行将被忽略,而一个空的æ交\n" "说明将会终æ¢æ交。\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 "" -"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n" +"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%s' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n" "也å¯ä»¥åˆ 除它们。\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 "" -"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n" +"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%s' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n" "也å¯ä»¥åˆ 除它们。一个空的æ交说明将会终æ¢æ交。\n" #: builtin/commit.c @@ -6141,7 +6145,7 @@ msgstr "日期" msgid "override date for commit" msgstr "æ交时覆盖日期" -#: builtin/commit.c builtin/merge-tree.c parse-options.h ref-filter.h +#: builtin/commit.c parse-options.h ref-filter.h msgid "commit" msgstr "æ交" @@ -6466,6 +6470,10 @@ msgid "with --get, use default value when missing entry" msgstr "使用 --get å‚数,当缺少设置时使用默认值" #: builtin/config.c +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "人类å¯è¯»çš„注释å—符串(# å°†æ ¹æ®éœ€è¦æ·»åŠ 到å‰é¢ï¼‰" + +#: builtin/config.c #, c-format msgid "wrong number of arguments, should be %d" msgstr "错误的å‚数个数,应该为 %d 个" @@ -6578,6 +6586,10 @@ 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/config.c msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value 仅适用于有 '值模å¼'" @@ -6843,7 +6855,7 @@ msgstr "--merge-base 仅适用于两个æ交" #: builtin/diff.c #, c-format msgid "'%s': not a regular file or symlink" -msgstr "'%s':ä¸æ˜¯ä¸€ä¸ªæ£è§„文件或符å·é“¾æŽ¥" +msgstr "'%s':ä¸æ˜¯ä¸€ä¸ªæ™®é€šæ–‡ä»¶æˆ–符å·é“¾æŽ¥" #: builtin/diff.c msgid "no merge given, only parents." @@ -7623,6 +7635,10 @@ msgid "read reference patterns from stdin" msgstr "ä»Žæ ‡å‡†è¾“å…¥è¯»å–引用的模å¼" #: builtin/for-each-ref.c +msgid "also include HEAD ref and pseudorefs" +msgstr "还包括 HEAD 引用和伪引用" + +#: builtin/for-each-ref.c msgid "unknown arguments supplied with --stdin" msgstr "为 --stdin æ供了未知的命令å‚æ•°" @@ -8397,11 +8413,6 @@ msgstr "没有线程支æŒï¼Œå¿½ç•¥ %s" #: builtin/grep.c #, c-format -msgid "unable to read tree (%s)" -msgstr "æ— æ³•è¯»å–æ ‘ï¼ˆ%s)" - -#: builtin/grep.c -#, c-format msgid "unable to read tree %s" msgstr "æ— æ³•è¯»å–æ ‘ %s" @@ -9164,13 +9175,46 @@ msgstr "--separate-git-dir ä¸èƒ½ç”¨äºŽçº¯ä»“库" #: 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 (<é”®|键别å>)[(=|:)<值>])...]\n" " [--parse] [<文件>...]" +#: builtin/interpret-trailers.c wrapper.c +#, c-format +msgid "could not stat %s" +msgstr "ä¸èƒ½å¯¹ %s 调用 stat" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not a regular file" +msgstr "文件 %s ä¸æ˜¯ä¸€ä¸ªæ™®é€šæ–‡ä»¶" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not writable by user" +msgstr "文件 %s 用户ä¸å¯å†™" + +#: builtin/interpret-trailers.c +msgid "could not open temporary file" +msgstr "ä¸èƒ½æ‰“开临时文件" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not read input file '%s'" +msgstr "ä¸èƒ½è¯»å–输入文件 '%s'" + +#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c +msgid "could not read from stdin" +msgstr "ä¸èƒ½è‡ªæ ‡å‡†è¾“入读å–" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not rename temporary file to %s" +msgstr "ä¸èƒ½é‡å‘½å临时文件为 %s" + #: builtin/interpret-trailers.c msgid "edit files in place" msgstr "在原ä½ç¼–辑文件" @@ -9669,21 +9713,6 @@ msgid "could not get object info about '%s'" msgstr "æ— æ³•èŽ·å¾—å…³äºŽ '%s' 的对象信æ¯" #: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "åçš„ ls-files æ ¼å¼ï¼šå…ƒç´ '%s' 没有以 '(' 开头" - -#: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "åçš„ ls-files æ ¼å¼ï¼šå…ƒç´ '%s' 没有以 ')' 结尾" - -#: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "åçš„ ls-files æ ¼å¼: %%%.*s" - -#: builtin/ls-files.c msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<选项>] [<文件>...]" @@ -9775,7 +9804,7 @@ msgstr "显示相对于顶级目录的文件å" msgid "if any <file> is not in the index, treat this as an error" msgstr "如果任何 <文件> 都ä¸åœ¨ç´¢å¼•åŒºï¼Œè§†ä¸ºé”™è¯¯" -#: builtin/ls-files.c +#: builtin/ls-files.c builtin/merge-tree.c msgid "tree-ish" msgstr "æ ‘å¯¹è±¡" @@ -9854,21 +9883,6 @@ msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<选项>] <æ ‘å¯¹è±¡> [<路径>...]" #: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "åçš„ ls-tree æ ¼å¼ï¼šå…ƒç´ '%s' 没有以 '(' 开头" - -#: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "åçš„ ls-tree æ ¼å¼ï¼šå…ƒç´ '%s' 没有以 ')' 结尾" - -#: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "åçš„ ls-tree æ ¼å¼: %%%.*s" - -#: builtin/ls-tree.c msgid "only show trees" msgstr "åªæ˜¾ç¤ºæ ‘" @@ -10018,7 +10032,9 @@ msgstr "" msgid "" "option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and " "\"histogram\"" -msgstr "选项 diff-algorithm 接å—å‚æ•° \"myers\"ã€\"minimal\"ã€\"patience\" å’Œ \"histogram\"" +msgstr "" +"选项 diff-algorithm 接å—å‚æ•° \"myers\"ã€\"minimal\"ã€\"patience\" å’Œ " +"\"histogram\"" #: builtin/merge-file.c msgid "send results to standard output" @@ -10108,6 +10124,11 @@ msgstr "æ— æ³•è§£æžå¼•ç”¨ '%s'" msgid "Merging %s with %s\n" msgstr "åˆå¹¶ %s å’Œ %s\n" +#: builtin/merge-tree.c +#, c-format +msgid "could not parse as tree '%s'" +msgstr "æ— æ³•è§£æžä¸ºæ ‘对象 '%s'" + #: builtin/merge-tree.c builtin/merge.c msgid "not something we can merge" msgstr "ä¸æ˜¯å¯ä»¥åˆå¹¶çš„东西" @@ -10370,9 +10391,9 @@ msgstr "空的æ交说明会终æ¢æ交。\n" #: 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 "以 '%c' 开始的行将被忽略,而空的æ交说明将终æ¢æ交。\n" +msgstr "以 '%s' 开始的行将被忽略,而空的æ交说明将终æ¢æ交。\n" #: builtin/merge.c msgid "Empty commit message." @@ -10565,10 +10586,6 @@ msgstr "ä¸èƒ½è¯»å–è¢«æ ‡è®°çš„å¯¹è±¡ '%s'" msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "对象 '%s' è¢«æ ‡è®°ä¸º '%s',然而是一个 '%s' 类型" -#: builtin/mktag.c imap-send.c trailer.c -msgid "could not read from stdin" -msgstr "ä¸èƒ½è‡ªæ ‡å‡†è¾“入读å–" - #: builtin/mktag.c msgid "tag on stdin did not pass our strict fsck check" msgstr "æ ‡å‡†è¾“å…¥ä¸Šçš„æ ‡ç¾æœªé€šè¿‡æˆ‘ä»¬ä¸¥æ ¼çš„ fsck 检查" @@ -10901,11 +10918,6 @@ msgid "Write/edit the notes for the following object:" msgstr "为下é¢çš„对象写/编辑说明:" #: builtin/notes.c -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "ä¸èƒ½ä¸ºå¯¹è±¡ '%s' 开始 'show'" - -#: builtin/notes.c msgid "could not read 'show' output" msgstr "ä¸èƒ½è¯»å– 'show' 的输出" @@ -11677,10 +11689,11 @@ msgstr "æ‹’ç»åœ¨æœªæŒ‡å®š --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 <模å¼>] [--exclude <模å¼>]" +"git pack-refs [--all] [--no-prune] [--auto] [--include <模å¼>] [--exclude <模" +"å¼>]" #: builtin/pack-refs.c msgid "pack everything" @@ -11691,6 +11704,10 @@ msgid "prune loose refs (default)" msgstr "清除æ¾æ•£çš„引用(默认)" #: builtin/pack-refs.c +msgid "auto-pack refs as needed" +msgstr "按需对引用自动打包" + +#: builtin/pack-refs.c msgid "references to include" msgstr "需包å«çš„引用" @@ -12451,19 +12468,6 @@ msgid "could not remove '%s'" msgstr "æ— æ³•åˆ é™¤ '%s'" #: builtin/rebase.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 "" -"手工解决所有冲çªï¼Œæ‰§è¡Œ \"git add/rm <冲çªçš„文件>\" æ ‡è®°\n" -"冲çªå·²è§£å†³ï¼Œç„¶åŽæ‰§è¡Œ \"git rebase --continue\"。您也å¯ä»¥æ‰§è¡Œ\n" -"\"git rebase --skip\" 命令跳过这个æ交。如果想è¦ç»ˆæ¢æ‰§è¡Œå¹¶å›žåˆ°\n" -"\"git rebase\" 执行之å‰çš„状æ€ï¼Œæ‰§è¡Œ \"git rebase --abort\"。" - -#: builtin/rebase.c #, c-format msgid "" "\n" @@ -12496,11 +12500,15 @@ msgid "apply options and merge options cannot be used together" msgstr "应用选项和åˆå¹¶é€‰é¡¹ä¸èƒ½åŒæ—¶ä½¿ç”¨" #: builtin/rebase.c +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask 已弃用;请使用 '--empty=stop'。" + +#: builtin/rebase.c #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." -msgstr "æ— æ³•è¯†åˆ«çš„ç©ºç±»åž‹ '%s';有效值有 \"drop\"ã€\"keep\" å’Œ \"ask\"。" +"\"stop\"." +msgstr "æ— æ³•è¯†åˆ«çš„ç©ºç±»åž‹ '%s';有效值有 \"drop\"ã€\"keep\" å’Œ \"stop\"。" #: builtin/rebase.c msgid "" @@ -12642,7 +12650,7 @@ msgstr "让用户编辑è¦å˜åŸºçš„æ交列表" msgid "(REMOVED) was: try to recreate merges instead of ignoring them" msgstr "ï¼ˆå·²åˆ é™¤ï¼‰æ›¾æ˜¯ï¼šå°è¯•é‡å»ºåˆå¹¶æ交而éžå¿½ç•¥å®ƒä»¬" -#: builtin/rebase.c +#: builtin/rebase.c builtin/revert.c msgid "how to handle commits that become empty" msgstr "如何处ç†æˆä¸ºç©ºæ交的æ交" @@ -12723,8 +12731,8 @@ msgstr "" "å–而代之请使用 'merges'" #: builtin/rebase.c -msgid "No rebase in progress?" -msgstr "没有æ£åœ¨è¿›è¡Œçš„å˜åŸºï¼Ÿ" +msgid "no rebase in progress" +msgstr "没有æ£åœ¨è¿›è¡Œçš„å˜åŸº" #: builtin/rebase.c msgid "The --edit-todo action can only be used during interactive rebase." @@ -12941,6 +12949,10 @@ msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<log 选项>] [<引用>]" #: 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" @@ -12969,6 +12981,11 @@ msgstr "git reflog exists <引用>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "ç»™ '--%2$s' 的时间戳 '%1$s' æ— æ•ˆ" +#: builtin/reflog.c sequencer.c +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s ä¸æŽ¥å—å‚数:'%s'" + #: builtin/reflog.c msgid "do not actually prune any entries" msgstr "ä¸è¦å®žé™…清除任何æ¡ç›®" @@ -13128,8 +13145,8 @@ msgstr "" #: builtin/remote.c #, c-format -msgid "unknown mirror argument: %s" -msgstr "未知的镜åƒå‚数:%s" +msgid "unknown --mirror argument: %s" +msgstr "未知的 --mirror å‚数:%s" #: builtin/remote.c msgid "fetch the remote branches" @@ -13580,6 +13597,10 @@ msgid "could not start pack-objects to repack promisor objects" msgstr "æ— æ³•å¼€å§‹ pack-objects æ¥é‡æ–°æ‰“包 promisor 对象" #: builtin/repack.c +msgid "failed to feed promisor objects to pack-objects" +msgstr "æ— æ³•å°†æ‰¿è¯ºè€…å¯¹è±¡æ供给 pack-objects" + +#: builtin/repack.c msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "repack:期望æ¥è‡ª pack-objects 的完整åå…进制对象 ID。" @@ -14030,7 +14051,9 @@ msgstr "ä¸èƒ½éšå¼åœ°ç¡®å®š --onto æ£ç¡®çš„基线" msgid "" "(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance " "<branch>) <revision-range>..." -msgstr "(试验ä¸ï¼ï¼‰git replay ([--contained] --onto <新基线> | --advance <分支>) <版本范围>..." +msgstr "" +"(试验ä¸ï¼ï¼‰git replay ([--contained] --onto <新基线> | --advance <分支>) <版" +"本范围>..." #: builtin/replay.c msgid "make replay advance given branch" @@ -14053,7 +14076,8 @@ 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" @@ -14322,6 +14346,15 @@ msgid "--prefix requires an argument" msgstr "--prefix 需è¦ä¸€ä¸ªå‚æ•°" #: builtin/rev-parse.c +msgid "no object format specified" +msgstr "æœªæŒ‡å®šå¯¹è±¡æ ¼å¼" + +#: builtin/rev-parse.c +#, c-format +msgid "unsupported object format: %s" +msgstr "ä¸æ”¯æŒçš„å¯¹è±¡æ ¼å¼ï¼š'%s'" + +#: builtin/rev-parse.c #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "未知的 --abbrev-ref 模å¼ï¼š%s" @@ -14425,8 +14458,8 @@ msgid "allow commits with empty messages" msgstr "å…许æ交说明为空" #: builtin/revert.c -msgid "keep redundant, empty commits" -msgstr "ä¿æŒå¤šä½™çš„ã€ç©ºçš„æ交" +msgid "deprecated: use --empty=keep instead" +msgstr "已弃用:å–而代之使用 --empty=keep" #: builtin/revert.c msgid "use the 'reference' format to refer to commits" @@ -14877,7 +14910,7 @@ msgstr "åˆå§‹åŒ–稀ç–检出为锥形模å¼" msgid "toggle the use of a sparse index" msgstr "切æ¢ç¨€ç–索引的使用" -#: builtin/sparse-checkout.c commit-graph.c midx.c sequencer.c +#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c #, c-format msgid "unable to create leading directories of %s" msgstr "ä¸èƒ½ä¸º %s 创建先导目录" @@ -16041,12 +16074,12 @@ 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" "è¾“å…¥ä¸€ä¸ªæ ‡ç¾è¯´æ˜Žï¼š\n" " %s\n" -"以 '%c' 开头的行将被忽略。\n" +"以 '%s' 开头的行将被忽略。\n" #: builtin/tag.c #, c-format @@ -16054,13 +16087,13 @@ 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" "è¾“å…¥ä¸€ä¸ªæ ‡ç¾è¯´æ˜Žï¼š\n" " %s\n" -"以 '%c' 开头的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„也å¯ä»¥åˆ 除它们。\n" +"以 '%s' 开头的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„也å¯ä»¥åˆ 除它们。\n" #: builtin/tag.c msgid "unable to sign the tag" @@ -16169,6 +16202,10 @@ msgid "print only tags of the object" msgstr "åªæ‰“å°æŒ‡å‘è¯¥å¯¹è±¡çš„æ ‡ç¾" #: builtin/tag.c +msgid "could not start 'git column'" +msgstr "æ— æ³•å¯åŠ¨ 'git column'" + +#: builtin/tag.c #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "'%s' 选项åªå…许用在列表显示模å¼" @@ -16473,12 +16510,12 @@ msgid "fsmonitor disabled" msgstr "fsmonitor 被ç¦ç”¨" #: builtin/update-ref.c -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<选项>] -d <引用å> [<旧值>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<选项>] -d <引用å> [<旧对象>]" #: builtin/update-ref.c -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "git update-ref [<选项>] <引用å> <新值> [<旧值>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "git update-ref [<选项>] <引用å> <新对象> [<旧对象>]" #: builtin/update-ref.c msgid "git update-ref [<options>] --stdin [-z]" @@ -18101,7 +18138,8 @@ 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 @@ -18189,6 +18227,11 @@ msgstr "æ交图具有零和éžé›¶çš„世代(例如:æ交 '%s' å’Œ '%s')" msgid "Verifying commits in commit graph" msgstr "æ£åœ¨æ ¡éªŒæ交图ä¸çš„æ交" +#: commit-reach.c sequencer.c +#, c-format +msgid "could not parse commit %s" +msgstr "ä¸èƒ½è§£æžæ交 %s" + #: commit.c #, c-format msgid "%s %s is not a commit!" @@ -18716,8 +18759,14 @@ msgid "bad zlib compression level %d" msgstr "错误的 zlib 压缩级别 %d" #: config.c -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar 应该是一个 ASCII ç¼–ç çš„å—符" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s ä¸èƒ½åŒ…å«æ¢è¡Œç¬¦" + +#: config.c +#, c-format +msgid "%s must have at least one character" +msgstr "%s 必须至少有一个å—符" #: config.c #, c-format @@ -18807,6 +18856,11 @@ msgstr "æ— æ³•å†™å…¥æ–°çš„é…置文件 %s" #: config.c #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "ä¸å…许多行注释:'%s'" + +#: config.c +#, c-format msgid "could not lock config file %s" msgstr "ä¸èƒ½é”定é…置文件 %s" @@ -20983,6 +21037,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "ä¸èƒ½åˆ›å»º '%s.lock':%s" +#: loose.c +#, c-format +msgid "could not write loose object index %s" +msgstr "ä¸èƒ½å†™å…¥æ¾æ•£å¯¹è±¡ç´¢å¼• %s" + +#: loose.c +#, c-format +msgid "failed to write loose object index %s\n" +msgstr "æ— æ³•å†™å…¥æ¾æ•£å¯¹è±¡ç´¢å¼• %s\n" + #: ls-refs.c #, c-format msgid "unexpected line: '%s'" @@ -20996,6 +21060,11 @@ msgstr "在 ls-refs å‚æ•°åŽåº”该有一个 flush 包" msgid "quoted CRLF detected" msgstr "检测到被引用的 CRLF" +#: mem-pool.c strbuf.c wrapper.c +#, c-format +msgid "unable to format message: %s" +msgstr "æ— æ³•æ ¼å¼åŒ–消æ¯ï¼š%s" + #: merge-ort.c merge-recursive.c #, c-format msgid "Failed to merge submodule %s (not checked out)" @@ -21013,6 +21082,11 @@ msgstr "æ— æ³•åˆå¹¶å模组 %s(æ交ä¸å˜åœ¨ï¼‰" #: merge-ort.c merge-recursive.c #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "æ— æ³•åˆå¹¶å模组 %s(仓库æŸå)" + +#: merge-ort.c merge-recursive.c +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "æ— æ³•åˆå¹¶å模组 %s (æ交未跟éšåˆå¹¶åŸºçº¿ï¼‰" @@ -21541,6 +21615,104 @@ msgstr "ä¸èƒ½è§£æžå¯¹è±¡ '%s'" msgid "failed to read the cache" msgstr "æ— æ³•è¯»å–缓å˜" +#: midx-write.c +#, c-format +msgid "failed to add packfile '%s'" +msgstr "æ— æ³•æ·»åŠ åŒ…æ–‡ä»¶ '%s'" + +#: midx-write.c +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "æ— æ³•æ‰“å¼€åŒ…ç´¢å¼• '%s'" + +#: midx-write.c +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "æ— æ³•åœ¨åŒ…æ–‡ä»¶ä¸å®šä½å¯¹è±¡ %d" + +#: midx-write.c +msgid "cannot store reverse index file" +msgstr "æ— æ³•å˜å‚¨åå‘索引文件" + +#: midx-write.c +#, c-format +msgid "could not parse line: %s" +msgstr "ä¸èƒ½è§£æžè¡Œï¼š%s" + +#: midx-write.c +#, c-format +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 "ä¸èƒ½è½½å…¥åŒ…" + +#: midx-write.c +#, c-format +msgid "could not open index for %s" +msgstr "ä¸èƒ½æ‰“å¼€ %s 的索引" + +#: midx-write.c +msgid "Adding packfiles to multi-pack-index" +msgstr "æ·»åŠ åŒ…æ–‡ä»¶åˆ°å¤šåŒ…ç´¢å¼•" + +#: midx-write.c +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "未知的首选包:'%s'" + +#: midx-write.c +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "ä¸èƒ½é€‰æ‹©æ²¡æœ‰å¯¹è±¡çš„首选包 %s" + +#: midx-write.c +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "没有看到è¦ä¸¢å¼ƒçš„包文件 %s" + +#: midx-write.c +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "首选包 '%s' 已过期" + +#: midx-write.c +msgid "no pack files to index." +msgstr "没有è¦ç´¢å¼•çš„包文件。" + +#: midx-write.c +msgid "refusing to write multi-pack .bitmap without any objects" +msgstr "æ‹’ç»å†™å…¥æ²¡æœ‰ä»»ä½•å¯¹è±¡çš„多包ä½å›¾" + +#: midx-write.c +msgid "could not write multi-pack bitmap" +msgstr "æ— æ³•å†™å…¥å¤šåŒ…ä½å›¾" + +#: midx-write.c +msgid "could not write multi-pack-index" +msgstr "æ— æ³•å†™å…¥å¤šåŒ…ç´¢å¼•" + +#: midx-write.c +msgid "Counting referenced objects" +msgstr "æ£åœ¨å¯¹å¼•ç”¨å¯¹è±¡è®¡æ•°" + +#: midx-write.c +msgid "Finding and deleting unreferenced packfiles" +msgstr "æ£åœ¨æŸ¥æ‰¾å’Œåˆ 除未引用的包文件" + +#: midx-write.c +msgid "could not start pack-objects" +msgstr "ä¸èƒ½å¼€å§‹ pack-objects" + +#: midx-write.c +msgid "could not finish pack-objects" +msgstr "ä¸èƒ½ç»“æŸ pack-objects" + #: midx.c msgid "multi-pack-index OID fanout is of the wrong size" msgstr "多包索引的对象 ID 扇出表大å°é”™è¯¯" @@ -21628,88 +21800,6 @@ msgstr "多包索引大å移区越界" #: midx.c #, c-format -msgid "failed to add packfile '%s'" -msgstr "æ— æ³•æ·»åŠ åŒ…æ–‡ä»¶ '%s'" - -#: midx.c -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "æ— æ³•æ‰“å¼€åŒ…ç´¢å¼• '%s'" - -#: midx.c -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "æ— æ³•åœ¨åŒ…æ–‡ä»¶ä¸å®šä½å¯¹è±¡ %d" - -#: midx.c -msgid "cannot store reverse index file" -msgstr "æ— æ³•å˜å‚¨åå‘索引文件" - -#: midx.c -#, c-format -msgid "could not parse line: %s" -msgstr "ä¸èƒ½è§£æžè¡Œï¼š%s" - -#: midx.c -#, c-format -msgid "malformed line: %s" -msgstr "æ ¼å¼é”™è¯¯çš„行:%s" - -#: midx.c -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "忽略已å˜åœ¨çš„å¤šåŒ…ç´¢å¼•ï¼Œæ ¡éªŒç ä¸åŒ¹é…" - -#: midx.c -msgid "could not load pack" -msgstr "ä¸èƒ½è½½å…¥åŒ…" - -#: midx.c -#, c-format -msgid "could not open index for %s" -msgstr "ä¸èƒ½æ‰“å¼€ %s 的索引" - -#: midx.c -msgid "Adding packfiles to multi-pack-index" -msgstr "æ·»åŠ åŒ…æ–‡ä»¶åˆ°å¤šåŒ…ç´¢å¼•" - -#: midx.c -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "未知的首选包:'%s'" - -#: midx.c -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "ä¸èƒ½é€‰æ‹©æ²¡æœ‰å¯¹è±¡çš„首选包 %s" - -#: midx.c -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "没有看到è¦ä¸¢å¼ƒçš„包文件 %s" - -#: midx.c -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "首选包 '%s' 已过期" - -#: midx.c -msgid "no pack files to index." -msgstr "没有è¦ç´¢å¼•çš„包文件。" - -#: midx.c -msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "æ‹’ç»å†™å…¥æ²¡æœ‰ä»»ä½•å¯¹è±¡çš„多包ä½å›¾ .bitmap" - -#: midx.c -msgid "could not write multi-pack bitmap" -msgstr "æ— æ³•å†™å…¥å¤šåŒ…ä½å›¾" - -#: midx.c -msgid "could not write multi-pack-index" -msgstr "æ— æ³•å†™å…¥å¤šåŒ…ç´¢å¼•" - -#: midx.c -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "æ— æ³•æ¸…ç†ä½äºŽ %s 的多包索引" @@ -21761,22 +21851,6 @@ msgstr "æ— æ³•ä¸ºåŒ…æ–‡ä»¶ %s åŠ è½½åŒ…ç´¢å¼•" msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "oid[%d] = %s 错误的对象å移:%<PRIx64> != %<PRIx64>" -#: midx.c -msgid "Counting referenced objects" -msgstr "æ£åœ¨å¯¹å¼•ç”¨å¯¹è±¡è®¡æ•°" - -#: midx.c -msgid "Finding and deleting unreferenced packfiles" -msgstr "æ£åœ¨æŸ¥æ‰¾å’Œåˆ 除未引用的包文件" - -#: midx.c -msgid "could not start pack-objects" -msgstr "ä¸èƒ½å¼€å§‹ pack-objects" - -#: midx.c -msgid "could not finish pack-objects" -msgstr "ä¸èƒ½ç»“æŸ pack-objects" - #: name-hash.c #, c-format msgid "unable to create lazy_dir thread: %s" @@ -21831,6 +21905,30 @@ msgstr "æ‹’ç»å‘ %s(在 refs/notes/ 之外)写入注解" msgid "Bad %s value: '%s'" msgstr "åçš„ %s 值:'%s'" +#: object-file-convert.c +msgid "failed to decode tree entry" +msgstr "æ— æ³•è§£ç æ ‘å¯¹è±¡" + +#: object-file-convert.c +#, c-format +msgid "failed to map tree entry for %s" +msgstr "æ— æ³•ä¸º %s æ˜ å°„æ ‘å¯¹è±¡" + +#: object-file-convert.c +#, c-format +msgid "bad %s in commit" +msgstr "æ交ä¸æœ‰é”™è¯¯çš„ %s" + +#: object-file-convert.c +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "æ— æ³•å°† %s %s æ˜ å°„åˆ°æ交对象ä¸" + +#: object-file-convert.c +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "æ— æ³•å°†å¯¹è±¡ä»Ž %s 转æ¢ä¸º %s" + #: object-file.c #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" @@ -21959,6 +22057,11 @@ msgstr "打包对象 %s(ä¿å˜åœ¨ %s)已æŸå" #: object-file.c #, c-format +msgid "missing mapping of %s to %s" +msgstr "缺少 %s 到 %s çš„æ˜ å°„" + +#: object-file.c +#, c-format msgid "unable to write file %s" msgstr "æ— æ³•å†™æ–‡ä»¶ %s" @@ -22026,6 +22129,11 @@ msgstr "ä¸èƒ½è¯»å–对象 %s" #: object-file.c #, c-format +msgid "cannot map object %s to %s" +msgstr "æ— æ³•å°†å¯¹è±¡ %s æ˜ å°„åˆ° %s" + +#: object-file.c +#, c-format msgid "object fails fsck: %s" msgstr "对象 fsck 失败:%s" @@ -22387,6 +22495,10 @@ msgid "unable to load pack: '%s', disabling pack-reuse" msgstr "æ— æ³•æ‰“å¼€åŒ…ï¼š'%s',ç¦ç”¨åŒ…é‡ç”¨" #: pack-bitmap.c +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "æ— æ³•è®¡ç®—é¦–é€‰åŒ…ï¼Œç¦ç”¨åŒ…é‡ç”¨" + +#: pack-bitmap.c #, c-format msgid "object '%s' not found in type bitmaps" msgstr "对象 %s 为在类型ä½å›¾ä¸æ‰¾åˆ°" @@ -23656,6 +23768,84 @@ msgstr "æ— æ³•åˆ é™¤å¼•ç”¨ %s:%s" msgid "could not delete references: %s" msgstr "æ— æ³•åˆ é™¤å¼•ç”¨ï¼š%s" +#: refs/reftable-backend.c +#, c-format +msgid "refname is dangerous: %s" +msgstr "å±é™©çš„引用å称:%s" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "试图用ä¸å˜åœ¨çš„对象 %2$s 写入引用 '%1$s'" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "å°è¯•å°†éžæ交对象 %s 写入分支 '%s'" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "ä¸å…许对 'HEAD' 进行多次更新(包括通过其引用 '%s' 进行的更新)" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "æ— æ³•é”定引用 '%s'ï¼šæ— æ³•è§£æžå¼•ç”¨ '%s'" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "æ— æ³•é”定引用 '%s':读å–引用时出错" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "ä¸å…许对 '%s' 进行多次更新(包括通过符å·å¼•ç”¨ '%s' 更新)" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "æ— æ³•é”定引用 '%s':引用已å˜åœ¨" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "æ— æ³•é”定 '%s' 引用:引用丢失,但预期为 %s" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "æ— æ³•é”定 '%s' 引用:ä½äºŽ %s,但预期为 %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "reftable: 事务准备:%s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "reftable: 事务失败:%s" + +#: refs/reftable-backend.c +#, c-format +msgid "unable to compact stack: %s" +msgstr "æ— æ³•åŽ‹ç¼©æ ˆï¼š%s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s not found" +msgstr "引用å称 %s 未找到" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "引用å %s 是一个符å·å¼•ç”¨ï¼Œä¸æ”¯æŒå¤åˆ¶" + #: refspec.c #, c-format msgid "invalid refspec '%s'" @@ -23668,6 +23858,11 @@ msgstr "在 push-option å–值ä¸æ— 效的引å·ï¼š'%s'" #: remote-curl.c #, c-format +msgid "unknown value for object-format: %s" +msgstr "å¯¹è±¡æ ¼å¼çš„未知å–值:%s" + +#: remote-curl.c +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs æ— æ•ˆï¼šè¿™æ˜¯ git 仓库么?" @@ -24203,8 +24398,21 @@ msgstr "resolve-undo 记录 `%s`,现缺失" #: revision.c #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "æ— æ³•èŽ·å¾— ancestry-path å‚æ•° %s çš„æ交" +msgid "%s exists but is a symbolic ref" +msgstr "%s å˜åœ¨ä½†æ˜¯ä¸€ä¸ªç¬¦å·å¼•ç”¨" + +#: revision.c +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge 选项需è¦æŒ‡å®š MERGE_HEADã€CHERRY_PICK_HEADã€REVERT_HEAD 或 " +"REBASE_HEAD ä¸çš„一个伪引用" + +#: revision.c +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "æ— æ³•èŽ·å¾— --ancestry-path å‚æ•° %s çš„æ交" #: revision.c msgid "--unpacked=<packfile> no longer supported" @@ -24565,6 +24773,19 @@ msgstr "未知动作:%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 "" +"手工解决所有冲çªï¼Œæ‰§è¡Œ \"git add/rm <冲çªçš„文件>\" æ ‡è®°\n" +"冲çªå·²è§£å†³ï¼Œç„¶åŽæ‰§è¡Œ \"git rebase --continue\"。您也å¯ä»¥æ‰§è¡Œ\n" +"\"git rebase --skip\" 命令跳过这个æ交。如果想è¦ç»ˆæ¢æ‰§è¡Œå¹¶å›žåˆ°\n" +"\"git rebase\" 执行之å‰çš„状æ€ï¼Œæ‰§è¡Œ \"git rebase --abort\"。" + +#: sequencer.c +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -24813,11 +25034,6 @@ msgstr "ä¸èƒ½æ›´æ–° %s" #: sequencer.c #, c-format -msgid "could not parse commit %s" -msgstr "ä¸èƒ½è§£æžæ交 %s" - -#: sequencer.c -#, c-format msgid "could not parse parent commit %s" msgstr "ä¸èƒ½è§£æžçˆ¶æ交 %s" @@ -24948,11 +25164,6 @@ msgstr "æ— æ•ˆå‘½ä»¤ '%.*s'" #: sequencer.c #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s ä¸æŽ¥å—å‚数:'%s'" - -#: sequencer.c -#, c-format msgid "missing arguments for %s" msgstr "缺少 %s çš„å‚æ•°" @@ -25502,6 +25713,11 @@ msgstr "æ— æ³•ä½¿ç”¨æ— æ•ˆé…ç½®æ¥åˆ›å»ºå·¥ä½œåŒº" #: setup.c #, c-format +msgid "'%s' already specified as '%s'" +msgstr "'%s' 已指定为 '%s'" + +#: setup.c +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "期望 git 仓库版本 <= %d,å´å¾—到 %d" @@ -25732,6 +25948,24 @@ msgstr "索引æ¡ç›®æ˜¯ä¸€ä¸ªç›®å½•ï¼Œä½†ä¸æ˜¯ç¨€ç–çš„ (%08x)" msgid "cannot use split index with a sparse index" msgstr "æ‹†åˆ†ç´¢å¼•æ— æ³•ä¸Žç¨€ç–索引一起使用" +#. 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 "åçš„ %s æ ¼å¼ï¼šå…ƒç´ '%s' 没有以 '(' 开头" + +#. 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 "åçš„ %s æ ¼å¼ï¼šå…ƒç´ '%s' 没有以 ')' 结尾" + +#. TRANSLATORS: %s is a command like "ls-tree". +#: strbuf.c +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "åçš„ %s æ ¼å¼: %%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #: strbuf.c #, c-format @@ -26123,35 +26357,6 @@ msgstr "é”® '%2$s' 的未知å–值 '%1$s'" msgid "empty trailer token in trailer '%.*s'" msgstr "尾注 '%.*s' 的键为空" -#: trailer.c -#, c-format -msgid "could not read input file '%s'" -msgstr "ä¸èƒ½è¯»å–输入文件 '%s'" - -#: trailer.c wrapper.c -#, c-format -msgid "could not stat %s" -msgstr "ä¸èƒ½å¯¹ %s 调用 stat" - -#: trailer.c -#, c-format -msgid "file %s is not a regular file" -msgstr "文件 %s ä¸æ˜¯ä¸€ä¸ªæ£è§„文件" - -#: trailer.c -#, c-format -msgid "file %s is not writable by user" -msgstr "文件 %s 用户ä¸å¯å†™" - -#: trailer.c -msgid "could not open temporary file" -msgstr "ä¸èƒ½æ‰“开临时文件" - -#: trailer.c -#, c-format -msgid "could not rename temporary file to %s" -msgstr "ä¸èƒ½é‡å‘½å临时文件为 %s" - #: transport-helper.c msgid "full write to remote helper failed" msgstr "完整写入远程助手失败" @@ -26271,8 +26476,8 @@ msgstr "remote-heper ä¸æ”¯æŒæŽ¨é€ï¼Œéœ€è¦å¼•ç”¨è§„æ ¼" #: transport-helper.c #, c-format -msgid "helper %s does not support 'force'" -msgstr "助手 %s ä¸æ”¯æŒ 'force'" +msgid "helper %s does not support '--force'" +msgstr "助手 %s ä¸æ”¯æŒ '--force'" #: transport-helper.c msgid "couldn't run fast-export" @@ -26747,6 +26952,11 @@ msgid "invalid '..' path segment" msgstr "æ— æ•ˆçš„ '..' 路径片段" #: usage.c +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "é”™è¯¯ï¼šæ— æ³•æ ¼å¼åŒ–消æ¯ï¼š%s\n" + +#: usage.c msgid "usage: " msgstr "用法:" diff --git a/po/zh_TW.po b/po/zh_TW.po index 312dd128a4..f554381a7a 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -22,12 +22,13 @@ # Yi-Jyun Pan <pan93412@gmail.com>, 2021, 2022, 2023, 2024. # Kaiyang Wu <self@origincode.me>, 2022. # lumynou5 <lumynou5.tw@gmail.com>, 2023, 2024. +# Kisaragi Hiu <mail@kisaragi-hiu.com>, 2024. msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2024-02-18 20:48+0800\n" -"PO-Revision-Date: 2024-02-18 20:50+0800\n" +"POT-Creation-Date: 2024-04-28 18:52+0800\n" +"PO-Revision-Date: 2024-04-28 18:44+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" @@ -601,12 +602,12 @@ 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" -"è¦åˆªé™¤ “%c†開é 的列,請將列首(上下文)改æˆç©ºç™½ã€‚\n" -"è¦åˆªé™¤ “%c†開é 的列,請直接刪除。\n" -"é–‹é 是 %c 的列將會被移除。\n" +"è¦åˆªé™¤ã€Œ%cã€é–‹é 的列,請將列首(上下文)改æˆç©ºç™½ã€‚\n" +"è¦åˆªé™¤ã€Œ%cã€é–‹é 的列,請直接刪除。\n" +"é–‹é 是 %s 的列將會被移除。\n" #: add-patch.c msgid "" @@ -659,16 +660,18 @@ 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" "? - print help\n" msgstr "" -"j - ç¶æŒæ¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–下一個未決定å€å¡Š\n" -"J - ç¶æŒæ¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–下一個å€å¡Š\n" -"k - ç¶æŒæ¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–上一個未決定å€å¡Š\n" -"K - ç¶æŒæ¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–上一個å€å¡Š\n" +"j - ç¶æŒæ¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–下一個未決定å€å¡Š\n" +"J - ç¶æŒæ¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–下一個å€å¡Š\n" +"k - ç¶æŒæ¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–上一個未決定å€å¡Š\n" +"K - ç¶æŒæ¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–上一個å€å¡Š\n" "g - é¸æ“‡è¦è·³è½‰è‡³çš„å€å¡Š\n" "/ - 尋找符åˆæ供之常è¦è¡¨ç¤ºå¼çš„å€å¡Š\n" "s - 分割目å‰å€å¡Šç‚ºæ›´å°çš„å€å¡Š\n" "e - 手動編輯目å‰å€å¡Š\n" +"p - 輸出目å‰å€å¡Š\n" "? - 顯示說明\n" #: add-patch.c @@ -747,8 +750,8 @@ msgstr "" #: advice.c #, c-format -msgid "%shint: %.*s%s\n" -msgstr "%sæ示:%.*s%s\n" +msgid "%shint:%s%.*s%s\n" +msgstr "%sæ示:%s%.*s%s\n" #: advice.c msgid "Cherry-picking is not possible because you have unmerged files." @@ -1345,11 +1348,6 @@ msgstr[0] "套用 %%s å€‹ä¿®è£œæª”ï¼Œå…¶ä¸ %d 個被拒絕……" #: apply.c #, c-format -msgid "truncating .rej filename to %.*s.rej" -msgstr "æ£åœ¨å°‡ .rej 檔案å稱截çŸç‚º %.*s.rej" - -#: apply.c -#, c-format msgid "cannot open %s" msgstr "無法開啟 %s" @@ -1884,6 +1882,11 @@ msgstr "需è¦ä¸€å€‹ %s 修訂版" msgid "could not create file '%s'" msgstr "無法建立 “%s†檔案" +#: bisect.c builtin/notes.c +#, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "ä¸èƒ½ç‚ºç‰©ä»¶ '%s' 開始 'show'" + #: bisect.c builtin/merge.c #, c-format msgid "could not read file '%s'" @@ -1931,8 +1934,8 @@ 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 -#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c -#: sequencer.c submodule.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 "修訂版éæ·è¨å®šå¤±æ•—" @@ -2007,10 +2010,12 @@ msgid "not tracking: ambiguous information for ref '%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 @@ -2049,6 +2054,10 @@ msgstr "" msgid "'%s' is not a valid branch name" msgstr "“%s†ä¸æ˜¯æœ‰æ•ˆçš„分支å稱" +#: branch.c builtin/branch.c +msgid "See `man git check-ref-format`" +msgstr "è«‹åƒé–±ã€Œman git check-ref-formatã€" + #: branch.c #, c-format msgid "a branch named '%s' already exists" @@ -2283,14 +2292,8 @@ msgid "adding embedded git repository: %s" msgstr "æ£åœ¨åŠ å…¥åµŒå…¥å¼ git 版本庫:%s" #: builtin/add.c -msgid "" -"Use -f if you really want to add them.\n" -"Turn this message off by running\n" -"\"git config advice.addIgnoredFile false\"" -msgstr "" -"è‹¥æ‚¨çœŸçš„æƒ³åŠ å…¥ï¼Œè«‹å‚³å…¥ -f。\n" -"如è¦é—œé–‰æ¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\n" -"“git config advice.addIgnoredFile falseâ€" +msgid "Use -f if you really want to add them." +msgstr "如果您確定想è¦åŠ 入他們,請使用「-fã€ã€‚" #: builtin/add.c msgid "adding files failed" @@ -2313,14 +2316,8 @@ msgid "Nothing specified, nothing added.\n" msgstr "æ²’æœ‰æŒ‡å®šï¼Œäº¦æœªåŠ å…¥æª”æ¡ˆã€‚\n" #: builtin/add.c -msgid "" -"Maybe you wanted to say 'git add .'?\n" -"Turn this message off by running\n" -"\"git config advice.addEmptyPathspec false\"" -msgstr "" -"å¯èƒ½æ‚¨æƒ³åš “git add .â€ï¼Ÿ\n" -"如è¦é—œé–‰æ¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\n" -"“git config advice.addEmptyPathspec falseâ€" +msgid "Maybe you wanted to say 'git add .'?" +msgstr "也許您想è¦åŸ·è¡Œçš„是「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 @@ -2340,8 +2337,8 @@ msgid "bad action '%s' for '%s'" msgstr "“%sâ€ å‹•ä½œå° â€œ%s†無效" #: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c -#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c -#: parallel-checkout.c sequencer.c setup.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â€" @@ -2425,18 +2422,19 @@ msgstr "無法切割修補檔。" #: builtin/am.c #, c-format -msgid "When you have resolved this problem, run \"%s --continue\"." -msgstr "解決æ¤å•é¡Œå¾Œï¼Œè«‹åŸ·è¡Œ “%s --continueâ€ã€‚" +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "解決æ¤å•é¡Œå¾Œï¼Œè«‹åŸ·è¡Œã€Œ%s --continueã€ã€‚\n" #: builtin/am.c #, c-format -msgid "If you prefer to skip this patch, run \"%s --skip\" instead." -msgstr "è‹¥è¦ç•¥éŽæ¤ä¿®è£œï¼Œè«‹æ”¹åŸ·è¡Œ “%s --skipâ€ã€‚" +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "è‹¥è¦ç•¥éŽæ¤ä¿®è£œï¼Œè«‹æ”¹åŸ·è¡Œã€Œ%s --skipã€ã€‚\n" #: builtin/am.c #, c-format -msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"." -msgstr "è‹¥è¦å°‡ç©ºç™½ä¿®è£œæª”錄入為空白æ交,請執行 “%s --allow-emptyâ€ã€‚" +msgid "" +"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n" +msgstr "è‹¥è¦å°‡ç©ºç™½ä¿®è£œæª”錄入為空白æ交,請執行「%s --allow-emptyã€ã€‚\n" #: builtin/am.c #, c-format @@ -3503,11 +3501,11 @@ msgstr "分支已拷è²ï¼Œä½†ç„¡æ³•æ›´æ–°çµ„態檔案" 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 "" "請編輯下述分支的æè¿°\n" " %s\n" -"é–‹é 是 “%c†的列將被刪除。\n" +"é–‹é 是「%sã€çš„列將被刪除。\n" #: builtin/branch.c msgid "Generic options" @@ -3763,10 +3761,12 @@ msgstr "ä¸æ˜¯åœ¨ git 版本庫執行 — 沒有å¯é¡¯ç¤ºçš„掛鉤\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) <path>] [(-s | --suffix) <format>]\n" +"git bugreport [(-o | --output-directory) <path>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" " [--diagnose[=<mode>]]" #: builtin/bugreport.c @@ -4366,6 +4366,12 @@ msgstr "“%sâ€ã€â€œ%s†或 “%s†無法在簽出樹狀物件時使用" msgid "path '%s' is unmerged" 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 +#, c-format +msgid "unable to read tree (%s)" +msgstr "無法讀å–樹(%s)" + #: builtin/checkout.c msgid "you need to resolve your current index first" msgstr "您需è¦å…ˆè§£æ±ºç›®å‰ç´¢å¼•å€çš„è¡çª" @@ -4625,6 +4631,11 @@ msgid "missing branch or commit argument" msgstr "缺少分支或æ交引數" #: builtin/checkout.c +#, c-format +msgid "unknown conflict style '%s'" +msgstr "未知的è¡çªè¼¸å‡ºé¢¨æ ¼ã€Œ%sã€" + +#: builtin/checkout.c msgid "perform a 3-way merge with the new branch" msgstr "和新分支進行三方åˆä½µ" @@ -4945,18 +4956,8 @@ msgid "remove only ignored files" msgstr "åªç§»é™¤å¿½ç•¥çš„檔案" #: builtin/clean.c -msgid "" -"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " -"clean" -msgstr "" -"clean.requireForce è¨å®šç‚º true 且未æä¾› -iã€-n 或 -f é¸é …,拒絕執行清ç†å‹•ä½œ" - -#: builtin/clean.c -msgid "" -"clean.requireForce defaults to true and neither -i, -n, nor -f given; " -"refusing to clean" -msgstr "" -"clean.requireForce é è¨ç‚º true 且未æä¾› -iã€-n 或 -f é¸é …,拒絕執行清ç†å‹•ä½œ" +msgid "clean.requireForce is true and -f not given: refusing to clean" +msgstr "clean.requireForce 是 true 且未給定 -f é¸é …:拒絕清ç†" #: builtin/clone.c msgid "git clone [<options>] [--] <repo> [<dir>]" @@ -4975,8 +4976,8 @@ msgid "create a bare repository" msgstr "建立裸版本庫" #: builtin/clone.c -msgid "create a mirror repository (implies bare)" -msgstr "建立é¡åƒç‰ˆæœ¬åº«ï¼ˆäº¦å³è£¸ç‰ˆæœ¬åº«ï¼‰" +msgid "create a mirror repository (implies --bare)" +msgstr "建立é¡åƒç‰ˆæœ¬åº«ï¼ˆéš±å« --bare)" #: builtin/clone.c msgid "to clone from a local repository" @@ -5378,6 +5379,11 @@ msgid "padding space between columns" msgstr "兩直行之間的填充空間" #: builtin/column.c +#, c-format +msgid "%s must be non-negative" +msgstr "%s ä¸å¾—ç‚ºè² æ•¸" + +#: builtin/column.c msgid "--command must be the first argument" msgstr "--command å¿…é ˆæ˜¯ç¬¬ä¸€å€‹åƒæ•¸" @@ -5710,7 +5716,7 @@ msgid "" "in the current commit message" msgstr "無法é¸æ“‡ä¸€å€‹æœªè¢«ç›®å‰æ交說明使用的備註å—å…ƒ" -#: builtin/commit.c builtin/merge-tree.c +#: builtin/commit.c #, c-format msgid "could not lookup commit '%s'" msgstr "無法查詢æ交 “%sâ€" @@ -5745,7 +5751,7 @@ msgstr "ä¸èƒ½è®€å– MERGE_MSG" #: builtin/commit.c bundle.c rerere.c sequencer.c #, c-format msgid "could not open '%s'" -msgstr "ä¸èƒ½é–‹å•Ÿ '%s'" +msgstr "無法開啟「%sã€" #: builtin/commit.c msgid "could not write commit template" @@ -5755,38 +5761,38 @@ msgstr "ä¸èƒ½å¯«æ交範本" #, 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 "" "請輸入æ述您變更的æ交訊æ¯ã€‚\n" -"é–‹é 是「%cã€çš„行皆會忽略。\n" +"é–‹é 是「%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 "" -"請輸入æ述您變更的æ交訊æ¯ã€‚é–‹é 是「%cã€\n" -"的行皆會忽略。æ交訊æ¯ç©ºç™½å‰‡å–消本次æ交作æ¥ã€‚\n" +"請輸入æ述您變更的æ交訊æ¯ã€‚é–‹é 是「%sã€çš„列\n" +"皆會忽略。æ交訊æ¯ç©ºç™½å‰‡å–消本次æ交作æ¥ã€‚\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 "" -"請輸入æ述您變更的æ交訊æ¯ã€‚會ä¿ç•™é–‹é 是「%cã€\n" -"的行,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›è¡Œã€‚\n" +"請輸入æ述您變更的æ交訊æ¯ã€‚會ä¿ç•™é–‹é 是「%sã€\n" +"的列,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›åˆ—。\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 "" "請輸入æ述您變更的æ交訊æ¯ã€‚會ä¿ç•™é–‹é 是\n" -"「%cã€çš„行,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›è¡Œã€‚\n" +"「%sã€çš„列,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›åˆ—。\n" "æ交訊æ¯ç©ºç™½å‰‡å–消本次æ交作æ¥ã€‚\n" #: builtin/commit.c @@ -6018,7 +6024,7 @@ msgstr "日期" msgid "override date for commit" msgstr "æ交時覆蓋日期" -#: builtin/commit.c builtin/merge-tree.c parse-options.h ref-filter.h +#: builtin/commit.c parse-options.h ref-filter.h msgid "commit" msgstr "æ交" @@ -6345,6 +6351,10 @@ msgid "with --get, use default value when missing entry" msgstr "使用 --get 但未指定åƒæ•¸æ™‚所使用的é è¨å€¼" #: builtin/config.c +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "人類å¯è®€çš„備註å—串(將按需æ’å…¥ # 至å‰æ–¹ï¼‰" + +#: builtin/config.c #, c-format msgid "wrong number of arguments, should be %d" msgstr "錯誤的åƒæ•¸å€‹æ•¸ï¼Œæ‡‰è©²ç‚º %d 個" @@ -6457,6 +6467,10 @@ 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/config.c msgid "--fixed-value only applies with 'value-pattern'" msgstr "--fixed-value 僅套用至 'value-pattern'" @@ -7025,7 +7039,7 @@ msgstr "來自 %.*s\n" #: builtin/fetch.c #, c-format msgid "object %s not found" -msgstr "物件 %s 未發ç¾" +msgstr "找ä¸åˆ°ç‰©ä»¶ %s" #: builtin/fetch.c msgid "[up to date]" @@ -7505,6 +7519,10 @@ msgid "read reference patterns from stdin" msgstr "從 stdin 讀å–引用模å¼" #: builtin/for-each-ref.c +msgid "also include HEAD ref and pseudorefs" +msgstr "åŒ…å« HEAD 引用和å½å¼•ç”¨" + +#: builtin/for-each-ref.c msgid "unknown arguments supplied with --stdin" msgstr "為 --stdin æ供的引數未知" @@ -8266,6 +8284,7 @@ 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 @@ -8277,11 +8296,6 @@ msgstr "沒有執行緒支æ´ï¼Œå¿½ç•¥ %s" #: builtin/grep.c #, c-format -msgid "unable to read tree (%s)" -msgstr "無法讀å–樹(%s)" - -#: builtin/grep.c -#, c-format msgid "unable to read tree %s" msgstr "ç„¡æ³•è®€å– %s 樹狀物件" @@ -9039,13 +9053,46 @@ msgstr "--separate-git-dir 與純版本庫ä¸ç›¸å®¹" #: 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" +" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n" " [--parse] [<file>...]" +#: builtin/interpret-trailers.c wrapper.c +#, c-format +msgid "could not stat %s" +msgstr "ä¸èƒ½å° %s å‘¼å« stat" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not a regular file" +msgstr "檔案 %s ä¸æ˜¯ä¸€å€‹æ£è¦æª”案" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not writable by user" +msgstr "檔案 %s 使用者ä¸å¯å¯«" + +#: builtin/interpret-trailers.c +msgid "could not open temporary file" +msgstr "ä¸èƒ½é–‹å•Ÿæš«å˜æª”" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not read input file '%s'" +msgstr "ä¸èƒ½è®€å–輸入檔案 '%s'" + +#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c +msgid "could not read from stdin" +msgstr "ä¸èƒ½è‡ªæ¨™æº–輸入讀å–" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not rename temporary file to %s" +msgstr "ä¸èƒ½é‡æ–°å‘½åæš«å˜æª”為 %s" + #: builtin/interpret-trailers.c msgid "edit files in place" msgstr "在原ä½ç·¨è¼¯æª”案" @@ -9148,7 +9195,7 @@ msgstr "追蹤 <開始>,<çµæŸ> 範åœä¸æ©«åˆ—或 <檔案> ä¸> :<函數å稱 #: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c #, c-format msgid "unrecognized argument: %s" -msgstr "無法è˜åˆ¥çš„åƒæ•¸ï¼š%s" +msgstr "無法è˜åˆ¥çš„引數:%s" #: builtin/log.c msgid "-L<range>:<file> cannot be used with pathspec" @@ -9544,21 +9591,6 @@ msgid "could not get object info about '%s'" msgstr "無法å–得「%sã€ç›¸é—œçš„物件資訊" #: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: element '%s' does not start with '('" -msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%sâ€ å…ƒç´ ä¸ä»¥ “(†開é " - -#: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: element '%s' does not end in ')'" -msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%sâ€ å…ƒç´ ä¸ä»¥ “)†çµå°¾" - -#: builtin/ls-files.c -#, c-format -msgid "bad ls-files format: %%%.*s" -msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼š%%%.*s" - -#: builtin/ls-files.c msgid "git ls-files [<options>] [<file>...]" msgstr "git ls-files [<é¸é …>] [<檔案>...]" @@ -9650,7 +9682,7 @@ msgstr "顯示相å°æ–¼é ‚級目錄的檔案å" msgid "if any <file> is not in the index, treat this as an error" msgstr "如果任何 <檔案> 都ä¸åœ¨ç´¢å¼•å€ï¼Œè¦–為錯誤" -#: builtin/ls-files.c +#: builtin/ls-files.c builtin/merge-tree.c msgid "tree-ish" msgstr "樹或æ交" @@ -9728,21 +9760,6 @@ msgid "git ls-tree [<options>] <tree-ish> [<path>...]" msgstr "git ls-tree [<é¸é …>] <樹或æ交> [<路徑>...]" #: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: element '%s' does not start with '('" -msgstr "無效的 ls-tree æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„é–‹é ä¸æ˜¯ã€Œ(ã€" - -#: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: element '%s' does not end in ')'" -msgstr "無效的 ls-tree æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„çµå°¾ä¸æ˜¯ã€Œ)ã€" - -#: builtin/ls-tree.c -#, c-format -msgid "bad ls-tree format: %%%.*s" -msgstr "無效的 ls-tree æ ¼å¼ï¼š%%%.*s" - -#: builtin/ls-tree.c msgid "only show trees" msgstr "åªé¡¯ç¤ºæ¨¹" @@ -9982,6 +9999,11 @@ msgstr "無法解æžå¼•ç”¨ '%s'" msgid "Merging %s with %s\n" msgstr "åˆä½µ %s å’Œ %s\n" +#: builtin/merge-tree.c +#, c-format +msgid "could not parse as tree '%s'" +msgstr "無法解æžç‚ºæ¨¹ç‹€ç‰©ä»¶ã€Œ%sã€" + #: builtin/merge-tree.c builtin/merge.c msgid "not something we can merge" msgstr "ä¸èƒ½åˆä½µ" @@ -10245,9 +10267,9 @@ msgstr "空的æ交說明會終æ¢æ交。\n" #: 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 "以 '%c' 開始的行將被忽略,而空的æ交說明將終æ¢æ交。\n" +msgstr "以「%sã€é–‹å§‹çš„列將被忽略,æ交說明留空則會終æ¢æ交。\n" #: builtin/merge.c msgid "Empty commit message." @@ -10440,10 +10462,6 @@ msgstr "無法讀å–有標籤的物件「%sã€" msgid "object '%s' tagged as '%s', but is a '%s' type" msgstr "「%sã€å·²æ¨™ç‚ºã€Œ%sã€ï¼Œä½†å»æ˜¯ã€Œ%sã€é¡žåž‹" -#: builtin/mktag.c imap-send.c trailer.c -msgid "could not read from stdin" -msgstr "ä¸èƒ½è‡ªæ¨™æº–輸入讀å–" - #: builtin/mktag.c msgid "tag on stdin did not pass our strict fsck check" msgstr "stdin 上的標籤未通éŽæˆ‘å€‘çš„åš´æ ¼ fsck 檢查" @@ -10656,7 +10674,7 @@ msgstr "列出å¯ä»¥å¾žæ‰€æœ‰å¼•ç”¨å˜å–çš„æ交" #: builtin/name-rev.c msgid "deprecated: use --annotate-stdin instead" -msgstr "已廢棄:請改用 --annotate-stdin" +msgstr "已棄用:請改用 --annotate-stdin" #: builtin/name-rev.c msgid "annotate text from stdin" @@ -10776,11 +10794,6 @@ msgid "Write/edit the notes for the following object:" msgstr "為下é¢çš„物件寫/編輯說明:" #: builtin/notes.c -#, c-format -msgid "unable to start 'show' for object '%s'" -msgstr "ä¸èƒ½ç‚ºç‰©ä»¶ '%s' 開始 'show'" - -#: builtin/notes.c msgid "could not read 'show' output" msgstr "ä¸èƒ½è®€å– 'show' 的輸出" @@ -10923,8 +10936,8 @@ msgid "" "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" msgstr "" -"å指令 'edit' çš„é¸é … -m/-F/-c/-C 已棄用。\n" -"è«‹æ›ç”¨ 'git notes add -f -m/-F/-c/-C'。\n" +"å指令「editã€çš„é¸é … -m/-F/-c/-C 已棄用。\n" +"è«‹æ›ç”¨ã€Œgit notes add -f -m/-F/-c/-Cã€ã€‚\n" #: builtin/notes.c msgid "failed to delete ref NOTES_MERGE_PARTIAL" @@ -11210,8 +11223,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 @@ -11553,10 +11566,10 @@ msgstr "傳入 --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 <pattern>] [--exclude " +"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude " "<pattern>]" #: builtin/pack-refs.c @@ -11568,6 +11581,10 @@ msgid "prune loose refs (default)" msgstr "剪除鬆散引用(é è¨å€¼ï¼‰" #: builtin/pack-refs.c +msgid "auto-pack refs as needed" +msgstr "按需自動å°è£å¼•ç”¨" + +#: builtin/pack-refs.c msgid "references to include" msgstr "è¦åŒ…å«çš„引用" @@ -12331,19 +12348,6 @@ msgid "could not remove '%s'" msgstr "無法刪除 '%s'" #: builtin/rebase.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 "" -"手動解決所有è¡çªï¼ŒåŸ·è¡Œ \"git add/rm <è¡çªçš„檔案>\" 標記\n" -"è¡çªå·²è§£æ±ºï¼Œç„¶å¾ŒåŸ·è¡Œ \"git rebase --continue\"。您也å¯ä»¥åŸ·è¡Œ\n" -"\"git rebase --skip\" 指令略éŽé€™å€‹æ交。如果想è¦çµ‚æ¢åŸ·è¡Œä¸¦å›žåˆ°\n" -"\"git rebase\" 執行之å‰çš„狀態,執行 \"git rebase --abort\"。" - -#: builtin/rebase.c #, c-format msgid "" "\n" @@ -12376,11 +12380,15 @@ msgid "apply options and merge options cannot be used together" msgstr "套用é¸é …與åˆä½µé¸é …ä¸å¾—åŒæ™‚使用" #: builtin/rebase.c +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "--empty=ask 已棄用。請改用「--empty=stopã€ã€‚" + +#: builtin/rebase.c #, c-format msgid "" "unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " -"\"ask\"." -msgstr "無法è˜åˆ¥çš„ '%s' 空類型;有效的數值有 \"drop\"ã€\"keep\" è·Ÿ \"ask\"。" +"\"stop\"." +msgstr "無法è˜åˆ¥ç©ºé¡žåž‹ã€Œ%sã€ï¼›æœ‰æ•ˆçš„數值有「dropã€ã€ã€Œkeepã€è·Ÿã€Œstopã€ã€‚" #: builtin/rebase.c msgid "" @@ -12522,7 +12530,7 @@ msgstr "讓使用者編輯è¦é‡å®šåŸºåº•çš„æ交列表" msgid "(REMOVED) was: try to recreate merges instead of ignoring them" msgstr "(已移除)曾為:嘗試é‡æ–°å»ºç«‹ï¼Œè€Œéžå¿½ç•¥åˆä½µ" -#: builtin/rebase.c +#: builtin/rebase.c builtin/revert.c msgid "how to handle commits that become empty" msgstr "處ç†ç©ºç™½æ交的方å¼" @@ -12603,8 +12611,8 @@ msgstr "" "請改用 “mergesâ€" #: builtin/rebase.c -msgid "No rebase in progress?" -msgstr "沒有æ£åœ¨é€²è¡Œçš„é‡å®šåŸºåº•ï¼Ÿ" +msgid "no rebase in progress" +msgstr "沒有進行ä¸çš„é‡å®šåŸºåº•æµç¨‹" #: builtin/rebase.c msgid "The --edit-todo action can only be used during interactive rebase." @@ -12821,6 +12829,10 @@ msgid "git reflog [show] [<log-options>] [<ref>]" msgstr "git reflog [show] [<log-options>] [<ref>]" #: 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" @@ -12849,6 +12861,11 @@ msgstr "git reflog exists <引用>" msgid "invalid timestamp '%s' given to '--%s'" msgstr "傳入「--%sã€çš„時間戳「%sã€ç„¡æ•ˆ" +#: builtin/reflog.c sequencer.c +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "%s ä¸æŽ¥å—åƒæ•¸ï¼š'%s'" + #: builtin/reflog.c msgid "do not actually prune any entries" msgstr "ä¸å¯¦éš›å‰ªé™¤ä»»ä½•é …ç›®" @@ -13003,13 +13020,13 @@ msgid "" "--mirror is dangerous and deprecated; please\n" "\t use --mirror=fetch or --mirror=push instead" msgstr "" -"--mirror é¸é …å±éšªä¸”éŽæ™‚,請使用 --mirror=fetch\n" +"--mirror é¸é …å±éšªä¸”已棄用,請使用 --mirror=fetch\n" "\t 或 --mirror=push" #: builtin/remote.c #, c-format -msgid "unknown mirror argument: %s" -msgstr "未知的é¡åƒåƒæ•¸ï¼š%s" +msgid "unknown --mirror argument: %s" +msgstr "未知的 --mirror 引數:%s" #: builtin/remote.c msgid "fetch the remote branches" @@ -13459,6 +13476,10 @@ msgid "could not start pack-objects to repack promisor objects" msgstr "無法開始 pack-objects 來é‡æ–°æ‰“包 promisor 物件" #: builtin/repack.c +msgid "failed to feed promisor objects to pack-objects" +msgstr "無法將承諾者物件喂給 pack-objects" + +#: builtin/repack.c msgid "repack: Expecting full hex object ID lines only from pack-objects." msgstr "repack:期望來自 pack-objects 的完整åå…進ä½ç‰©ä»¶ ID。" @@ -13960,7 +13981,7 @@ msgstr "在索引ä¸è¨»å†Šä¹¾æ·¨çš„解決方案" #: builtin/rerere.c msgid "'git rerere forget' without paths is deprecated" -msgstr "沒有路徑的 'git rerere forget' 已經éŽæ™‚" +msgstr "沒有路徑的「git rerere forgetã€å·²ç¶“棄用" #: builtin/rerere.c #, c-format @@ -14070,7 +14091,7 @@ msgstr "無法將 '%s' 解æžç‚ºä¸€å€‹æœ‰æ•ˆçš„樹狀物件。" #: builtin/reset.c msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead." -msgstr "--mixed 帶路徑已棄用,而是用 'git reset -- <路徑>'。" +msgstr "--mixed 帶路徑已棄用,請改用「git reset -- <路徑>ã€ã€‚" # è¯è€…:漢å—ä¹‹é–“ç„¡ç©ºæ ¼ï¼Œæ•…åˆªé™¤%så‰å¾Œç©ºæ ¼ #: builtin/reset.c @@ -14206,6 +14227,15 @@ msgid "--prefix requires an argument" msgstr "--prefix éœ€è¦ 1 個引數" #: builtin/rev-parse.c +msgid "no object format specified" +msgstr "æœªæŒ‡å®šç‰©ä»¶æ ¼å¼" + +#: builtin/rev-parse.c +#, c-format +msgid "unsupported object format: %s" +msgstr "ä¸æ”¯æ´çš„ç‰©ä»¶æ ¼å¼ï¼š%s" + +#: builtin/rev-parse.c #, c-format msgid "unknown mode for --abbrev-ref: %s" msgstr "--abbrev-ref 的模å¼æœªçŸ¥ï¼š%s" @@ -14310,8 +14340,8 @@ msgid "allow commits with empty messages" msgstr "å…許æ交說明為空" #: builtin/revert.c -msgid "keep redundant, empty commits" -msgstr "ä¿æŒå¤šé¤˜çš„ã€ç©ºçš„æ交" +msgid "deprecated: use --empty=keep instead" +msgstr "已棄用:請改用 --empty=keep" #: builtin/revert.c msgid "use the 'reference' format to refer to commits" @@ -14756,7 +14786,7 @@ msgstr "以 cone 模å¼åˆå§‹åŒ–稀ç–簽出" msgid "toggle the use of a sparse index" msgstr "切æ›æ˜¯å¦ä½¿ç”¨ç¨€ç–索引" -#: builtin/sparse-checkout.c commit-graph.c midx.c sequencer.c +#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c #, c-format msgid "unable to create leading directories of %s" msgstr "ä¸èƒ½ç‚º %s 建立先導目錄" @@ -15922,12 +15952,12 @@ 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" -"輸入一個標籤說明:\n" +"為標籤輸入說明訊æ¯ï¼š\n" " %s\n" -"以 '%c' é–‹é 的行將被忽略。\n" +"以「%sã€é–‹é 的列將被忽略。\n" #: builtin/tag.c #, c-format @@ -15935,13 +15965,13 @@ 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" -"輸入一個標籤說明:\n" +"為標籤輸入說明訊æ¯ï¼š\n" " %s\n" -"以 '%c' é–‹é 的行將被ä¿ç•™ï¼Œå¦‚果您願æ„也å¯ä»¥åˆªé™¤å®ƒå€‘。\n" +"以「%sã€é–‹é 的列將被ä¿ç•™ï¼›éœ€è¦çš„話您å¯ä»¥è‡ªå·±åˆªé™¤ã€‚\n" #: builtin/tag.c msgid "unable to sign the tag" @@ -16050,6 +16080,10 @@ msgid "print only tags of the object" msgstr "åªåˆ—å°æŒ‡å‘該物件的標籤" #: builtin/tag.c +msgid "could not start 'git column'" +msgstr "無法啟動 “git columnâ€" + +#: builtin/tag.c #, c-format msgid "the '%s' option is only allowed in list mode" msgstr "「%sã€é¸é …åªèƒ½åœ¨åˆ—表顯示模å¼ä½¿ç”¨" @@ -16352,12 +16386,12 @@ msgid "fsmonitor disabled" msgstr "fsmonitor 被åœç”¨" #: builtin/update-ref.c -msgid "git update-ref [<options>] -d <refname> [<old-val>]" -msgstr "git update-ref [<é¸é …>] -d <引用å> [<舊值>]" +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "git update-ref [<options>] -d <refname> [<old-oid>]" #: builtin/update-ref.c -msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]" -msgstr "git update-ref [<é¸é …>] <引用å> <新值> [<舊值>]" +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" #: builtin/update-ref.c msgid "git update-ref [<options>] --stdin [-z]" @@ -16667,7 +16701,7 @@ msgstr "「%sã€ã€ã€Œ%sã€å’Œã€Œ%sã€é¸é …ä¸å¾—åŒæ™‚使用" #: builtin/worktree.c #, c-format msgid "option '%s' and commit-ish cannot be used together" -msgstr "“%s†é¸é …å’Œæ交號ä¸å¾—åŒæ™‚使用" +msgstr "「%sã€é¸é …å’Œæ交編號ä¸å¾—åŒæ™‚使用" #: builtin/worktree.c msgid "added with --lock" @@ -16905,7 +16939,7 @@ msgstr "無法è˜åˆ¥çš„套件包雜湊演算法:%s" #: bundle.c #, c-format msgid "unknown capability '%s'" -msgstr "未知功能 '%s'" +msgstr "未知功能「%sã€" #: bundle.c #, c-format @@ -16915,7 +16949,7 @@ msgstr "“%s†ä¸åƒæ˜¯ä¸€å€‹ v2 或 v3 版本的套件包檔案" #: bundle.c #, c-format msgid "unrecognized header: %s%s (%d)" -msgstr "無法è˜åˆ¥çš„包é :%s%s (%d)" +msgstr "無法è˜åˆ¥çš„標é :%s%s (%d)" #: bundle.c msgid "Repository lacks these prerequisite commits:" @@ -16963,7 +16997,7 @@ msgstr "無法複製套件包æè¿°å…ƒ" #: bundle.c msgid "Could not spawn pack-objects" -msgstr "ä¸èƒ½ç”Ÿæˆ pack-objects 進程" +msgstr "無法 spawn pack-objects 處ç†ç¨‹åº" #: bundle.c msgid "pack-objects died" @@ -16972,7 +17006,7 @@ msgstr "pack-objects 終æ¢" #: bundle.c #, c-format msgid "ref '%s' is excluded by the rev-list options" -msgstr "引用 '%s' 被 rev-list é¸é …排除" +msgstr "引用「%sã€è¢« rev-list é¸é …排除" #: bundle.c #, c-format @@ -16991,7 +17025,7 @@ msgstr "ä¸èƒ½å»ºç«‹ç©ºå¥—件包。" #: bundle.c #, c-format msgid "cannot create '%s'" -msgstr "ä¸èƒ½å»ºç«‹ '%s'" +msgstr "無法建立「%sã€" #: bundle.c msgid "index-pack died" @@ -16999,7 +17033,7 @@ msgstr "index-pack 終æ¢" #: chunk-format.c msgid "terminating chunk id appears earlier than expected" -msgstr "終æ¢å€å¡Š id 出ç¾çš„時間早於é 期" +msgstr "終æ¢å€å¡Š ID 比é 期還早出ç¾" #: chunk-format.c #, c-format @@ -18064,6 +18098,11 @@ msgstr "æ交圖形ä¸åŒ…å« 0 å’Œéž 0 兩個世代號(例如 “%s†和 â msgid "Verifying commits in commit graph" msgstr "æ£åœ¨é©—è‰æ交圖ä¸çš„æ交" +#: commit-reach.c sequencer.c +#, c-format +msgid "could not parse commit %s" +msgstr "ä¸èƒ½è§£æžæ交 %s" + #: commit.c #, c-format msgid "%s %s is not a commit!" @@ -18080,14 +18119,14 @@ msgid "" "Turn this message off by running\n" "\"git config advice.graftFileDeprecated false\"" msgstr "" -"å° <GIT_DIR>/info/grafts 的支æ´å·²è¢«æ£„用,並將在\n" -"未來的Git版本ä¸è¢«ç§»é™¤ã€‚\n" +"å° <GIT_DIR>/info/grafts 的支æ´å·²æ£„用,並將在\n" +"未來的 Git 版本ä¸è¢«ç§»é™¤ã€‚\n" "\n" -"請使用 \"git replace --convert-graft-file\" å°‡\n" +"請使用「git replace --convert-graft-fileã€å°‡\n" "grafts 轉æ›ç‚ºå–代引用。\n" "\n" -"è¨å®š \"git config advice.graftFileDeprecated false\"\n" -"å¯é—œé–‰æœ¬æ¶ˆæ¯" +"è¨å®šã€Œgit config advice.graftFileDeprecated falseã€\n" +"å¯ä»¥å°‡æœ¬è¨Šæ¯é—œé–‰" #: commit.c #, c-format @@ -18591,8 +18630,14 @@ msgid "bad zlib compression level %d" msgstr "錯誤的 zlib 壓縮級別 %d" #: config.c -msgid "core.commentChar should only be one ASCII character" -msgstr "core.commentChar 應該是一個 ASCII å—å…ƒ" +#, c-format +msgid "%s cannot contain newline" +msgstr "%s ä¸èƒ½åŒ…å«æ›è¡Œç¬¦è™Ÿ" + +#: config.c +#, c-format +msgid "%s must have at least one character" +msgstr "%s 得有至少 1 個å—å…ƒ" #: config.c #, c-format @@ -18601,7 +18646,7 @@ msgstr "忽略未知的 core.fsyncMethod 值「%sã€" #: config.c msgid "core.fsyncObjectFiles is deprecated; use core.fsync instead" -msgstr "core.fsyncObjectFiles 已被å–代。請改用 core.fsync" +msgstr "core.fsyncObjectFiles 已棄用。請改用 core.fsync" #: config.c #, c-format @@ -18682,6 +18727,11 @@ msgstr "寫入新的è¨å®šæª”案 %s 失敗" #: config.c #, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "ä¸å…許多列備註:「%sã€" + +#: config.c +#, c-format msgid "could not lock config file %s" msgstr "ä¸èƒ½éŽ–定è¨å®šæª”案 %s" @@ -19419,7 +19469,6 @@ msgid "output only the last line of --stat" msgstr "åªè¼¸å‡º --stat 的最後一行" #: diff.c -#| msgid "<param1,param2>..." msgid "<param1>,<param2>..." msgstr "<param1>,<param2>..." @@ -20845,6 +20894,16 @@ msgstr "" msgid "Unable to create '%s.lock': %s" msgstr "ä¸èƒ½å»ºç«‹ '%s.lock':%s" +#: loose.c +#, c-format +msgid "could not write loose object index %s" +msgstr "無法寫入鬆散物件索引 %s" + +#: loose.c +#, c-format +msgid "failed to write loose object index %s\n" +msgstr "寫入鬆散物件索引 %s 失敗\n" + #: ls-refs.c #, c-format msgid "unexpected line: '%s'" @@ -20858,6 +20917,11 @@ msgstr "在 ls-refs 引數之後應該有一個 flush 包" msgid "quoted CRLF detected" msgstr "åµæ¸¬åˆ°ç”±å¯åˆ—å°å—å…ƒ (quoted) 所組æˆçš„ CRLF" +#: mem-pool.c strbuf.c wrapper.c +#, c-format +msgid "unable to format message: %s" +msgstr "ç„¡æ³•æ ¼å¼åŒ–訊æ¯ï¼š%s" + #: merge-ort.c merge-recursive.c #, c-format msgid "Failed to merge submodule %s (not checked out)" @@ -20875,6 +20939,11 @@ msgstr "無法åˆä½µå模組 %s(æ交ä¸å˜åœ¨ï¼‰" #: merge-ort.c merge-recursive.c #, c-format +msgid "Failed to merge submodule %s (repository corrupt)" +msgstr "無法åˆä½µå模組 %s (版本庫æ壞)" + +#: merge-ort.c merge-recursive.c +#, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "無法åˆä½µå模組 %s (æ交未跟隨åˆä½µåŸºç¤Žï¼‰" @@ -21185,7 +21254,7 @@ msgstr "快轉å模組 %s" #: merge-recursive.c #, c-format msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "無法åˆä½µå模組 %s (沒發ç¾åˆä½µè·Ÿéš¨çš„æ交)" +msgstr "無法åˆä½µå模組 %s (找ä¸åˆ°åˆä½µè·Ÿéš¨çš„æ交)" #: merge-recursive.c #, c-format @@ -21405,6 +21474,104 @@ msgstr "ä¸èƒ½è§£æžç‰©ä»¶ '%s'" msgid "failed to read the cache" msgstr "讀å–å¿«å–失敗" +#: midx-write.c +#, c-format +msgid "failed to add packfile '%s'" +msgstr "新增 packfile '%s' 失敗" + +#: midx-write.c +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "開啟包索引 '%s' 失敗" + +#: midx-write.c +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "在 packfile ä¸å®šä½ç‰©ä»¶ %d 失敗" + +#: midx-write.c +msgid "cannot store reverse index file" +msgstr "無法儲å˜å€’排索引檔案" + +#: midx-write.c +#, c-format +msgid "could not parse line: %s" +msgstr "無法解æžæ©«åˆ—:%s" + +#: midx-write.c +#, c-format +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 "無法載入包" + +#: midx-write.c +#, c-format +msgid "could not open index for %s" +msgstr "無法開啟 %s 的索引" + +#: midx-write.c +msgid "Adding packfiles to multi-pack-index" +msgstr "æ£åœ¨æ–°å¢ž packfile 至多包索引" + +#: midx-write.c +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "未知å好包:「%sã€" + +#: midx-write.c +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "無法é¸å–å好,沒有物件的 %s 包" + +#: midx-write.c +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "沒有看到è¦æ¨æ£„çš„ packfile %s" + +#: midx-write.c +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "å好包「%sã€å·²ç¶“éŽæœŸ" + +#: midx-write.c +msgid "no pack files to index." +msgstr "沒有è¦ç´¢å¼•çš„ pack 檔案。" + +#: midx-write.c +msgid "refusing to write multi-pack .bitmap without any objects" +msgstr "拒絕寫入無任何物件的多包 .bitmap" + +#: midx-write.c +msgid "could not write multi-pack bitmap" +msgstr "無法寫入多包ä½åœ–" + +#: midx-write.c +msgid "could not write multi-pack-index" +msgstr "無法寫入多包索引" + +#: midx-write.c +msgid "Counting referenced objects" +msgstr "æ£åœ¨è¨ˆç®—引用物件" + +#: midx-write.c +msgid "Finding and deleting unreferenced packfiles" +msgstr "æ£åœ¨å°‹æ‰¾ä¸¦åˆªé™¤æ²’有引用的 packfile" + +#: midx-write.c +msgid "could not start pack-objects" +msgstr "ä¸èƒ½é–‹å§‹ pack-objects" + +#: midx-write.c +msgid "could not finish pack-objects" +msgstr "ä¸èƒ½çµæŸ pack-objects" + #: midx.c msgid "multi-pack-index OID fanout is of the wrong size" msgstr "多包索引的物件 ID fanout 大å°éŒ¯èª¤" @@ -21492,88 +21659,6 @@ msgstr "多包索引的最大å移超出邊界" #: midx.c #, c-format -msgid "failed to add packfile '%s'" -msgstr "新增 packfile '%s' 失敗" - -#: midx.c -#, c-format -msgid "failed to open pack-index '%s'" -msgstr "開啟包索引 '%s' 失敗" - -#: midx.c -#, c-format -msgid "failed to locate object %d in packfile" -msgstr "在 packfile ä¸å®šä½ç‰©ä»¶ %d 失敗" - -#: midx.c -msgid "cannot store reverse index file" -msgstr "無法儲å˜å€’排索引檔案" - -#: midx.c -#, c-format -msgid "could not parse line: %s" -msgstr "無法解æžæ©«åˆ—:%s" - -#: midx.c -#, c-format -msgid "malformed line: %s" -msgstr "æ©«åˆ—æ ¼å¼éŒ¯èª¤ï¼š%s" - -#: midx.c -msgid "ignoring existing multi-pack-index; checksum mismatch" -msgstr "忽略ç¾æœ‰çš„多包索引:總和檢查碼ä¸ç¬¦" - -#: midx.c -msgid "could not load pack" -msgstr "無法載入包" - -#: midx.c -#, c-format -msgid "could not open index for %s" -msgstr "無法開啟 %s 的索引" - -#: midx.c -msgid "Adding packfiles to multi-pack-index" -msgstr "æ£åœ¨æ–°å¢ž packfile 至多包索引" - -#: midx.c -#, c-format -msgid "unknown preferred pack: '%s'" -msgstr "未知å好包:「%sã€" - -#: midx.c -#, c-format -msgid "cannot select preferred pack %s with no objects" -msgstr "無法é¸å–å好,沒有物件的 %s 包" - -#: midx.c -#, c-format -msgid "did not see pack-file %s to drop" -msgstr "沒有看到è¦æ¨æ£„çš„ packfile %s" - -#: midx.c -#, c-format -msgid "preferred pack '%s' is expired" -msgstr "å好包「%sã€å·²ç¶“éŽæœŸ" - -#: midx.c -msgid "no pack files to index." -msgstr "沒有è¦ç´¢å¼•çš„ pack 檔案。" - -#: midx.c -msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "拒絕寫入無任何物件的多包 .bitmap" - -#: midx.c -msgid "could not write multi-pack bitmap" -msgstr "無法寫入多包ä½åœ–" - -#: midx.c -msgid "could not write multi-pack-index" -msgstr "無法寫入多包索引" - -#: midx.c -#, c-format msgid "failed to clear multi-pack-index at %s" msgstr "清ç†ä½æ–¼ %s 的多包索引失敗" @@ -21625,22 +21710,6 @@ msgstr "為 packfile %s 載入包索引失敗" msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" msgstr "oid[%d] = %s 錯誤的物件ä½ç§»ï¼š%<PRIx64> != %<PRIx64>" -#: midx.c -msgid "Counting referenced objects" -msgstr "æ£åœ¨è¨ˆç®—引用物件" - -#: midx.c -msgid "Finding and deleting unreferenced packfiles" -msgstr "æ£åœ¨å°‹æ‰¾ä¸¦åˆªé™¤æ²’有引用的 packfile" - -#: midx.c -msgid "could not start pack-objects" -msgstr "ä¸èƒ½é–‹å§‹ pack-objects" - -#: midx.c -msgid "could not finish pack-objects" -msgstr "ä¸èƒ½çµæŸ pack-objects" - #: name-hash.c #, c-format msgid "unable to create lazy_dir thread: %s" @@ -21695,6 +21764,30 @@ msgstr "æ‹’çµ•å‘ %s(在 refs/notes/ 之外)寫入註解" msgid "Bad %s value: '%s'" msgstr "壞的 %s 值:'%s'" +#: object-file-convert.c +msgid "failed to decode tree entry" +msgstr "ç„¡æ³•è§£ç¢¼æ¨¹ç‹€ç‰©ä»¶é …ç›®" + +#: object-file-convert.c +#, c-format +msgid "failed to map tree entry for %s" +msgstr "無法為 %s æ˜ å°„æ¨¹ç‹€ç‰©ä»¶é …ç›®" + +#: object-file-convert.c +#, c-format +msgid "bad %s in commit" +msgstr "æ交ä¸æœ‰ç„¡æ•ˆçš„ %s" + +#: object-file-convert.c +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "無法在æ交物件ä¸æ˜ å°„ %s %s" + +#: object-file-convert.c +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "無法將物件從 %s 轉æ›ç‚º %s" + #: object-file.c #, c-format msgid "object directory %s does not exist; check .git/objects/info/alternates" @@ -21823,6 +21916,11 @@ msgstr "打包物件 %s(儲å˜åœ¨ %s)已æ壞" #: object-file.c #, c-format +msgid "missing mapping of %s to %s" +msgstr "缺少 %s 到 %s çš„æ˜ å°„" + +#: object-file.c +#, c-format msgid "unable to write file %s" msgstr "無法寫檔案 %s" @@ -21890,6 +21988,11 @@ msgstr "ä¸èƒ½è®€å–物件 %s" #: object-file.c #, c-format +msgid "cannot map object %s to %s" +msgstr "無法將物件 %s æ˜ å°„åˆ° %s" + +#: object-file.c +#, c-format msgid "object fails fsck: %s" msgstr "物件 fsck 失敗:%s" @@ -22252,6 +22355,10 @@ msgid "unable to load pack: '%s', disabling pack-reuse" msgstr "無法載入「%sã€å°è£ï¼Œåœç”¨ pack-reuse" #: pack-bitmap.c +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "無法計算å好å°è£ï¼Œåœç”¨ pack-reuse" + +#: pack-bitmap.c #, c-format msgid "object '%s' not found in type bitmaps" msgstr "在類型ä½åœ–ä¸ï¼Œæ‰¾ä¸åˆ°ã€Œ%sã€ç‰©ä»¶" @@ -22624,7 +22731,7 @@ msgstr "路徑è¦æ ¼åŒ…å«ç„¡æ•ˆçš„神奇å‰ç¶´" #: pathspec.c #, c-format msgid "Invalid pathspec magic '%.*s' in '%s'" -msgstr "在路徑è¦æ ¼ '%3$s' ä¸ç„¡æ•ˆçš„神奇å‰ç¶´ '%2$.*1$s'" +msgstr "有無效的神奇å‰ç¶´ã€Œ%.*sã€å‡ºç¾åœ¨è·¯å¾‘è¦æ ¼ã€Œ%sã€ä¸" #: pathspec.c #, c-format @@ -23521,6 +23628,84 @@ msgstr "無法刪除引用 %s:%s" msgid "could not delete references: %s" msgstr "無法刪除引用:%s" +#: refs/reftable-backend.c +#, c-format +msgid "refname is dangerous: %s" +msgstr "æ¤å¼•ç”¨å稱是å±éšªçš„:%s" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "嘗試以ä¸å˜åœ¨çš„物件 %s 寫入引用「%sã€" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "嘗試將éžæ交物件 %s 寫入分支「%sã€" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "ä¸å…許å°ã€ŒHEADã€é€²è¡Œå¤šæ¬¡æ›´æ–°ï¼ˆåŒ…å«é€éŽå…¶ã€Œ%sã€å¼•ç”¨é€²è¡Œçš„更新)" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "無法鎖定引用「%sã€ï¼šç„¡æ³•è§£æžå¼•ç”¨ã€Œ%sã€" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "無法鎖定引用「%sã€ï¼šç„¡æ³•è®€å–引用" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "ä¸å…許å°ã€Œ%sã€é€²è¡Œå¤šæ¬¡æ›´æ–°ï¼ˆåŒ…å«é€éŽã€Œ%sã€ç¬¦è™Ÿå¼•ç”¨é€²è¡Œçš„更新)" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "無法鎖定引用「%sã€ï¼šå¼•ç”¨å·²ç¶“å˜åœ¨" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "無法鎖定引用「%sã€ï¼šç¼ºå°‘引用但é 期的是 %s" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "無法鎖定引用「%sã€ï¼šä½æ–¼ %s 但é 期的是 %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "引用表:準備事務:%s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "引用表:事務失敗:%s" + +#: refs/reftable-backend.c +#, c-format +msgid "unable to compact stack: %s" +msgstr "ç„¡æ³•å£“ç¸®å †ç–Šï¼š%s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s not found" +msgstr "找ä¸åˆ°å¼•ç”¨å稱 %s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "引用å稱 %s 是符號引用,ä¸æ”¯æ´è¤‡è£½" + #: refspec.c #, c-format msgid "invalid refspec '%s'" @@ -23533,6 +23718,11 @@ msgstr "在 push-option å–值ä¸ç„¡æ•ˆçš„引號:'%s'" #: remote-curl.c #, c-format +msgid "unknown value for object-format: %s" +msgstr "未知的 object-format 值:%s" + +#: remote-curl.c +#, c-format msgid "%sinfo/refs not valid: is this a git repository?" msgstr "%sinfo/refs 無效:這是一個 git 版本庫嗎?" @@ -24067,8 +24257,21 @@ msgstr "resolve-undo ä¸å˜åœ¨çš„「%sã€è¨˜éŒ„" #: revision.c #, c-format -msgid "could not get commit for ancestry-path argument %s" -msgstr "無法å–å¾— ancestry-path 引數 %s çš„æ交" +msgid "%s exists but is a symbolic ref" +msgstr "%s å˜åœ¨ä½†å±¬æ–¼ç¬¦è™Ÿé€£çµ" + +#: revision.c +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"--merge 需è¦å…¶ä¸ä¸€ç¨®å½å¼•ç”¨ MERGE_HEADã€CHERRY_PICK_HEADã€REVERT_HEAD 或 " +"REBASE_HEAD" + +#: revision.c +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "無法å–å¾— --ancestry-path 引數 %s çš„æ交" #: revision.c msgid "--unpacked=<packfile> no longer supported" @@ -24429,6 +24632,19 @@ msgstr "未知動作:%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 "" +"手動解決所有è¡çªï¼ŒåŸ·è¡Œ \"git add/rm <è¡çªçš„檔案>\" 標記\n" +"è¡çªå·²è§£æ±ºï¼Œç„¶å¾ŒåŸ·è¡Œ \"git rebase --continue\"。您也å¯ä»¥åŸ·è¡Œ\n" +"\"git rebase --skip\" 指令略éŽé€™å€‹æ交。如果想è¦çµ‚æ¢åŸ·è¡Œä¸¦å›žåˆ°\n" +"\"git rebase\" 執行之å‰çš„狀態,執行 \"git rebase --abort\"。" + +#: sequencer.c +msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add <paths>' or 'git rm <paths>'" msgstr "" @@ -24681,11 +24897,6 @@ msgstr "ä¸èƒ½æ›´æ–° %s" #: sequencer.c #, c-format -msgid "could not parse commit %s" -msgstr "ä¸èƒ½è§£æžæ交 %s" - -#: sequencer.c -#, c-format msgid "could not parse parent commit %s" msgstr "ä¸èƒ½è§£æžçˆ¶æ交 %s" @@ -24816,11 +25027,6 @@ msgstr "無效的命令 “%.*sâ€" #: sequencer.c #, c-format -msgid "%s does not accept arguments: '%s'" -msgstr "%s ä¸æŽ¥å—åƒæ•¸ï¼š'%s'" - -#: sequencer.c -#, c-format msgid "missing arguments for %s" msgstr "缺少 %s çš„åƒæ•¸" @@ -25371,6 +25577,11 @@ msgstr "無法使用無效è¨å®šä¾†å»ºç«‹å·¥ä½œå€" #: setup.c #, c-format +msgid "'%s' already specified as '%s'" +msgstr "「%sã€å·²ç¶“指定為「%sã€" + +#: setup.c +#, c-format msgid "Expected git repo version <= %d, found %d" msgstr "期望 git 版本庫版本 <= %d,å»å¾—到 %d" @@ -25599,6 +25810,24 @@ msgstr "ç´¢å¼•é …ç›®æ˜¯è³‡æ–™å¤¾ï¼Œä½†ä¸æ˜¯ç¨€ç–資料夾(%08x)" msgid "cannot use split index with a sparse index" msgstr "無法在稀ç–索引使用索引分割" +#. 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 "無效的 %s æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„é–‹é ä¸æ˜¯ã€Œ(ã€" + +#. 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 "無效的 %s æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„çµå°¾ä¸æ˜¯ã€Œ)ã€" + +#. TRANSLATORS: %s is a command like "ls-tree". +#: strbuf.c +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "無效的 %s æ ¼å¼ï¼š%%%.*s" + #. TRANSLATORS: IEC 80000-13:2008 gibibyte #: strbuf.c #, c-format @@ -25988,35 +26217,6 @@ msgstr "éµ '%2$s' 的未知å–值 '%1$s'" msgid "empty trailer token in trailer '%.*s'" msgstr "ç°½å '%.*s' çš„éµç‚ºç©º" -#: trailer.c -#, c-format -msgid "could not read input file '%s'" -msgstr "ä¸èƒ½è®€å–輸入檔案 '%s'" - -#: trailer.c wrapper.c -#, c-format -msgid "could not stat %s" -msgstr "ä¸èƒ½å° %s å‘¼å« stat" - -#: trailer.c -#, c-format -msgid "file %s is not a regular file" -msgstr "檔案 %s ä¸æ˜¯ä¸€å€‹æ£è¦æª”案" - -#: trailer.c -#, c-format -msgid "file %s is not writable by user" -msgstr "檔案 %s 使用者ä¸å¯å¯«" - -#: trailer.c -msgid "could not open temporary file" -msgstr "ä¸èƒ½é–‹å•Ÿæš«å˜æª”" - -#: trailer.c -#, c-format -msgid "could not rename temporary file to %s" -msgstr "ä¸èƒ½é‡æ–°å‘½åæš«å˜æª”為 %s" - #: transport-helper.c msgid "full write to remote helper failed" msgstr "完整寫入é 端å”助工具失敗" @@ -26136,8 +26336,8 @@ msgstr "remote-heper ä¸æ”¯æ´ push,需è¦å¼•ç”¨è¦æ ¼" #: transport-helper.c #, c-format -msgid "helper %s does not support 'force'" -msgstr "å”助工具 %s ä¸æ”¯æ´ 'force'" +msgid "helper %s does not support '--force'" +msgstr "å”助工具 %s ä¸æ”¯æ´ã€Œ--forceã€" #: transport-helper.c msgid "couldn't run fast-export" @@ -26612,6 +26812,11 @@ msgid "invalid '..' path segment" msgstr "無效的 '..' 路徑å€å¡Š" #: usage.c +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "éŒ¯èª¤ï¼šç„¡æ³•æ ¼å¼åŒ–訊æ¯ï¼š%s\n" + +#: usage.c msgid "usage: " msgstr "用法: " @@ -27793,6 +27998,53 @@ msgstr "ç•¥éŽ %s å«å‚™ä»½å¾Œç¶´ '%s'。\n" msgid "Do you really want to send %s? [y|N]: " msgstr "您真的è¦å‚³é€ %s?[y|N]: " +#, c-format +#~ msgid "truncating .rej filename to %.*s.rej" +#~ msgstr "æ£åœ¨å°‡ .rej 檔案å稱截çŸç‚º %.*s.rej" + +#~ msgid "" +#~ "Use -f if you really want to add them.\n" +#~ "Turn this message off by running\n" +#~ "\"git config advice.addIgnoredFile false\"" +#~ msgstr "" +#~ "è‹¥æ‚¨çœŸçš„æƒ³åŠ å…¥ï¼Œè«‹å‚³å…¥ -f。\n" +#~ "如è¦é—œé–‰æ¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\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 "" +#~ "å¯èƒ½æ‚¨æƒ³åš “git add .â€ï¼Ÿ\n" +#~ "如è¦é—œé–‰æ¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\n" +#~ "“git config advice.addEmptyPathspec falseâ€" + +#~ msgid "" +#~ "clean.requireForce defaults to true and neither -i, -n, nor -f given; " +#~ "refusing to clean" +#~ msgstr "" +#~ "clean.requireForce é è¨ç‚º true 且未æä¾› -iã€-n 或 -f é¸é …,拒絕執行清ç†å‹•" +#~ "作" + +#, c-format +#~ msgid "bad ls-files format: element '%s' does not start with '('" +#~ msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%sâ€ å…ƒç´ ä¸ä»¥ “(†開é " + +#, c-format +#~ msgid "bad ls-files format: element '%s' does not end in ')'" +#~ msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%sâ€ å…ƒç´ ä¸ä»¥ “)†çµå°¾" + +#, c-format +#~ msgid "bad ls-files format: %%%.*s" +#~ msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼š%%%.*s" + +#~ msgid "keep redundant, empty commits" +#~ msgstr "ä¿æŒå¤šé¤˜çš„ã€ç©ºçš„æ交" + +#~ msgid "core.commentChar should only be one ASCII character" +#~ msgstr "core.commentChar 應該是一個 ASCII å—å…ƒ" + #~ msgid "-x and -X cannot be used together" #~ msgstr "-x å’Œ -X ä¸èƒ½åŒæ™‚使用" @@ -27838,9 +28090,5 @@ msgstr "您真的è¦å‚³é€ %s?[y|N]: " #~ msgid "%s is incompatible with %s" #~ msgstr "%s 與 %s ä¸ç›¸å®¹" -#, c-format -#~ msgid "could not remove reference %s" -#~ msgstr "無法刪除引用 %s" - #~ msgid "unhandled options" #~ msgstr "未處ç†é¸é …" @@ -147,7 +147,7 @@ static struct cmt_fmt_map *find_commit_format_recursive(const char *sought, for (i = 0; i < commit_formats_len; i++) { size_t match_len; - if (!starts_with(commit_formats[i].name, sought)) + if (!istarts_with(commit_formats[i].name, sought)) continue; match_len = strlen(commit_formats[i].name); @@ -428,7 +428,7 @@ static void add_rfc2047(struct strbuf *sb, const char *line, size_t len, } const char *show_ident_date(const struct ident_split *ident, - const struct date_mode *mode) + struct date_mode mode) { timestamp_t date = 0; long tz = 0; @@ -592,7 +592,7 @@ void pp_user_info(struct pretty_print_context *pp, switch (pp->fmt) { case CMIT_FMT_MEDIUM: strbuf_addf(sb, "Date: %s\n", - show_ident_date(&ident, &pp->date_mode)); + show_ident_date(&ident, pp->date_mode)); break; case CMIT_FMT_EMAIL: case CMIT_FMT_MBOXRD: @@ -601,7 +601,7 @@ void pp_user_info(struct pretty_print_context *pp, break; case CMIT_FMT_FULLER: strbuf_addf(sb, "%sDate: %s\n", what, - show_ident_date(&ident, &pp->date_mode)); + show_ident_date(&ident, pp->date_mode)); break; default: /* notin' */ @@ -775,7 +775,7 @@ static int mailmap_name(const char **email, size_t *email_len, static size_t format_person_part(struct strbuf *sb, char part, const char *msg, int len, - const struct date_mode *dmode) + struct date_mode dmode) { /* currently all placeholders have same length */ const int placeholder_len = 2; @@ -1034,7 +1034,7 @@ static void rewrap_message_tail(struct strbuf *sb, static int format_reflog_person(struct strbuf *sb, char part, struct reflog_walk_info *log, - const struct date_mode *dmode) + struct date_mode dmode) { const char *ident; @@ -1602,7 +1602,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ if (c->pretty_ctx->reflog_info) get_reflog_selector(sb, c->pretty_ctx->reflog_info, - &c->pretty_ctx->date_mode, + c->pretty_ctx->date_mode, c->pretty_ctx->date_mode_explicit, (placeholder[1] == 'd')); return 2; @@ -1617,7 +1617,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ return format_reflog_person(sb, placeholder[1], c->pretty_ctx->reflog_info, - &c->pretty_ctx->date_mode); + c->pretty_ctx->date_mode); } return 0; /* unknown %g placeholder */ case 'N': @@ -1712,11 +1712,11 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ case 'a': /* author ... */ return format_person_part(sb, placeholder[1], msg + c->author.off, c->author.len, - &c->pretty_ctx->date_mode); + c->pretty_ctx->date_mode); case 'c': /* committer ... */ return format_person_part(sb, placeholder[1], msg + c->committer.off, c->committer.len, - &c->pretty_ctx->date_mode); + c->pretty_ctx->date_mode); case 'e': /* encoding */ if (c->commit_encoding) strbuf_addstr(sb, c->commit_encoding); @@ -1759,7 +1759,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ goto trailer_out; } if (*arg == ')') { - format_trailers_from_commit(sb, msg + c->subject_off, &opts); + format_trailers_from_commit(&opts, msg + c->subject_off, sb); ret = arg - placeholder + 1; } trailer_out: @@ -2077,11 +2077,11 @@ static void pp_header(struct pretty_print_context *pp, } } -void pp_title_line(struct pretty_print_context *pp, - const char **msg_p, - struct strbuf *sb, - const char *encoding, - int need_8bit_cte) +void pp_email_subject(struct pretty_print_context *pp, + const char **msg_p, + struct strbuf *sb, + const char *encoding, + int need_8bit_cte) { static const int max_length = 78; /* per rfc2047 */ struct strbuf title; @@ -2091,19 +2091,14 @@ void pp_title_line(struct pretty_print_context *pp, pp->preserve_subject ? "\n" : " "); strbuf_grow(sb, title.len + 1024); - if (pp->print_email_subject) { - if (pp->rev) - fmt_output_email_subject(sb, pp->rev); - if (pp->encode_email_headers && - needs_rfc2047_encoding(title.buf, title.len)) - add_rfc2047(sb, title.buf, title.len, - encoding, RFC2047_SUBJECT); - else - strbuf_add_wrapped_bytes(sb, title.buf, title.len, + fmt_output_email_subject(sb, pp->rev); + if (pp->encode_email_headers && + needs_rfc2047_encoding(title.buf, title.len)) + add_rfc2047(sb, title.buf, title.len, + encoding, RFC2047_SUBJECT); + else + strbuf_add_wrapped_bytes(sb, title.buf, title.len, -last_line_length(sb), 1, max_length); - } else { - strbuf_addbuf(sb, &title); - } strbuf_addch(sb, '\n'); if (need_8bit_cte == 0) { @@ -2126,9 +2121,8 @@ void pp_title_line(struct pretty_print_context *pp, if (pp->after_subject) { strbuf_addstr(sb, pp->after_subject); } - if (cmit_fmt_is_mail(pp->fmt)) { - strbuf_addch(sb, '\n'); - } + + strbuf_addch(sb, '\n'); if (pp->in_body_headers.nr) { int i; @@ -2320,7 +2314,7 @@ void pretty_print_commit(struct pretty_print_context *pp, } pp_header(pp, encoding, commit, &msg, sb); - if (pp->fmt != CMIT_FMT_ONELINE && !pp->print_email_subject) { + if (pp->fmt != CMIT_FMT_ONELINE && !cmit_fmt_is_mail(pp->fmt)) { strbuf_addch(sb, '\n'); } @@ -2328,8 +2322,11 @@ void pretty_print_commit(struct pretty_print_context *pp, msg = skip_blank_lines(msg); /* These formats treat the title line specially. */ - if (pp->fmt == CMIT_FMT_ONELINE || cmit_fmt_is_mail(pp->fmt)) - pp_title_line(pp, &msg, sb, encoding, need_8bit_cte); + if (pp->fmt == CMIT_FMT_ONELINE) { + msg = format_subject(sb, msg, " "); + strbuf_addch(sb, '\n'); + } else if (cmit_fmt_is_mail(pp->fmt)) + pp_email_subject(pp, &msg, sb, encoding, need_8bit_cte); beginning_of_body = sb->len; if (pp->fmt != CMIT_FMT_ONELINE) @@ -35,11 +35,10 @@ struct pretty_print_context { */ enum cmit_fmt fmt; int abbrev; - const char *after_subject; + char *after_subject; int preserve_subject; struct date_mode date_mode; unsigned date_mode_explicit:1; - int print_email_subject; int expand_tabs_in_log; int need_8bit_cte; char *notes_message; @@ -96,13 +95,13 @@ void pp_user_info(struct pretty_print_context *pp, const char *what, const char *encoding); /* - * Format title line of commit message taken from "msg_p" and + * Format subject line of commit message taken from "msg_p" and * put it into "sb". * First line of "msg_p" is also affected. */ -void pp_title_line(struct pretty_print_context *pp, const char **msg_p, - struct strbuf *sb, const char *encoding, - int need_8bit_cte); +void pp_email_subject(struct pretty_print_context *pp, const char **msg_p, + struct strbuf *sb, const char *encoding, + int need_8bit_cte); /* * Get current state of commit message from "msg_p" and continue formatting @@ -168,7 +167,7 @@ int format_set_trailers_options(struct process_trailer_options *opts, * a well-known sentinel date if they appear bogus. */ const char *show_ident_date(const struct ident_split *id, - const struct date_mode *mode); + struct date_mode mode); #endif /* PRETTY_H */ diff --git a/read-cache-ll.h b/read-cache-ll.h index 2a50a784f0..09414afd04 100644 --- a/read-cache-ll.h +++ b/read-cache-ll.h @@ -480,8 +480,8 @@ extern int verify_ce_order; int cmp_cache_name_compare(const void *a_, const void *b_); int add_files_to_cache(struct repository *repo, const char *prefix, - const struct pathspec *pathspec, int include_sparse, - int flags); + const struct pathspec *pathspec, char *ps_matched, + int include_sparse, int flags); void overlay_tree_on_index(struct index_state *istate, const char *tree_name, const char *prefix); diff --git a/read-cache.c b/read-cache.c index f546cf7875..e1723ad796 100644 --- a/read-cache.c +++ b/read-cache.c @@ -3958,8 +3958,8 @@ static void update_callback(struct diff_queue_struct *q, } int add_files_to_cache(struct repository *repo, const char *prefix, - const struct pathspec *pathspec, int include_sparse, - int flags) + const struct pathspec *pathspec, char *ps_matched, + int include_sparse, int flags) { struct update_callback_data data; struct rev_info rev; @@ -3971,8 +3971,10 @@ int add_files_to_cache(struct repository *repo, const char *prefix, repo_init_revisions(repo, &rev, prefix); setup_revisions(0, NULL, &rev, NULL); - if (pathspec) + if (pathspec) { copy_pathspec(&rev.prune_data, pathspec); + rev.ps_matched = ps_matched; + } rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = update_callback; rev.diffopt.format_callback_data = &data; diff --git a/rebase-interactive.c b/rebase-interactive.c index d9718409b3..c343e16fcd 100644 --- a/rebase-interactive.c +++ b/rebase-interactive.c @@ -71,14 +71,14 @@ void append_todo_help(int command_count, if (!edit_todo) { strbuf_addch(buf, '\n'); - strbuf_commented_addf(buf, comment_line_char, + strbuf_commented_addf(buf, comment_line_str, Q_("Rebase %s onto %s (%d command)", "Rebase %s onto %s (%d commands)", command_count), shortrevisions, shortonto, command_count); } - strbuf_add_commented_lines(buf, msg, strlen(msg), comment_line_char); + strbuf_add_commented_lines(buf, msg, strlen(msg), comment_line_str); if (get_missing_commit_check_level() == MISSING_COMMIT_CHECK_ERROR) msg = _("\nDo not remove any line. Use 'drop' " @@ -87,7 +87,7 @@ void append_todo_help(int command_count, msg = _("\nIf you remove a line here " "THAT COMMIT WILL BE LOST.\n"); - strbuf_add_commented_lines(buf, msg, strlen(msg), comment_line_char); + strbuf_add_commented_lines(buf, msg, strlen(msg), comment_line_str); if (edit_todo) msg = _("\nYou are editing the todo file " @@ -98,7 +98,7 @@ void append_todo_help(int command_count, msg = _("\nHowever, if you remove everything, " "the rebase will be aborted.\n\n"); - strbuf_add_commented_lines(buf, msg, strlen(msg), comment_line_char); + strbuf_add_commented_lines(buf, msg, strlen(msg), comment_line_str); } int edit_todo_list(struct repository *r, struct todo_list *todo_list, @@ -130,7 +130,7 @@ int edit_todo_list(struct repository *r, struct todo_list *todo_list, if (launch_sequence_editor(todo_file, &new_todo->buf, NULL)) return -2; - strbuf_stripspace(&new_todo->buf, comment_line_char); + strbuf_stripspace(&new_todo->buf, comment_line_str); if (initial && new_todo->buf.len == 0) return -3; diff --git a/ref-filter.c b/ref-filter.c index be14b56e32..59ad6f54dd 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -1627,7 +1627,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam tz = strtol(zone, NULL, 10); if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE) goto bad; - v->s = xstrdup(show_date(timestamp, tz, &date_mode)); + v->s = xstrdup(show_date(timestamp, tz, date_mode)); v->value = timestamp; date_mode_release(&date_mode); return; @@ -1991,7 +1991,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp struct strbuf s = STRBUF_INIT; /* Format the trailer info according to the trailer_opts given */ - format_trailers_from_commit(&s, subpos, &atom->u.contents.trailer_opts); + format_trailers_from_commit(&atom->u.contents.trailer_opts, subpos, &s); v->s = strbuf_detach(&s, NULL); } else if (atom->u.contents.option == C_BARE) @@ -2628,6 +2628,12 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, each_ref_fn cb, void *cb_data) { + if (filter->kind == FILTER_REFS_KIND_MASK) { + /* In this case, we want to print all refs including root refs. */ + return refs_for_each_include_root_refs(get_main_ref_store(the_repository), + cb, cb_data); + } + if (!filter->match_as_path) { /* * in this case, the patterns are applied after @@ -2750,6 +2756,9 @@ static int ref_kind_from_refname(const char *refname) return ref_kind[i].kind; } + if (is_pseudoref(get_main_ref_store(the_repository), refname)) + return FILTER_REFS_PSEUDOREFS; + return FILTER_REFS_OTHERS; } @@ -2781,7 +2790,16 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct /* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */ kind = filter_ref_kind(filter, refname); - if (!(kind & filter->kind)) + + /* + * Generally HEAD refs are printed with special description denoting a rebase, + * detached state and so forth. This is useful when only printing the HEAD ref + * But when it is being printed along with other pseudorefs, it makes sense to + * keep the formatting consistent. So we mask the type to act like a pseudoref. + */ + if (filter->kind == FILTER_REFS_KIND_MASK && kind == FILTER_REFS_DETACHED_HEAD) + kind = FILTER_REFS_PSEUDOREFS; + else if (!(kind & filter->kind)) return NULL; if (!filter_pattern_match(filter, refname)) @@ -3047,9 +3065,15 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref ret = for_each_fullref_in("refs/remotes/", fn, cb_data); else if (filter->kind == FILTER_REFS_TAGS) ret = for_each_fullref_in("refs/tags/", fn, cb_data); - else if (filter->kind & FILTER_REFS_ALL) + else if (filter->kind & FILTER_REFS_REGULAR) ret = for_each_fullref_in_pattern(filter, fn, cb_data); - if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD)) + + /* + * When printing all ref types, HEAD is already included, + * so we don't want to print HEAD again. + */ + if (!ret && (filter->kind != FILTER_REFS_KIND_MASK) && + (filter->kind & FILTER_REFS_DETACHED_HEAD)) head_ref(fn, cb_data); } diff --git a/ref-filter.h b/ref-filter.h index 07cd6f6da3..0ca28d2bba 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -19,10 +19,13 @@ #define FILTER_REFS_BRANCHES 0x0004 #define FILTER_REFS_REMOTES 0x0008 #define FILTER_REFS_OTHERS 0x0010 -#define FILTER_REFS_ALL (FILTER_REFS_TAGS | FILTER_REFS_BRANCHES | \ +#define FILTER_REFS_REGULAR (FILTER_REFS_TAGS | FILTER_REFS_BRANCHES | \ FILTER_REFS_REMOTES | FILTER_REFS_OTHERS) #define FILTER_REFS_DETACHED_HEAD 0x0020 -#define FILTER_REFS_KIND_MASK (FILTER_REFS_ALL | FILTER_REFS_DETACHED_HEAD) +#define FILTER_REFS_PSEUDOREFS 0x0040 +#define FILTER_REFS_ROOT_REFS (FILTER_REFS_DETACHED_HEAD | FILTER_REFS_PSEUDOREFS) +#define FILTER_REFS_KIND_MASK (FILTER_REFS_REGULAR | FILTER_REFS_DETACHED_HEAD | \ + FILTER_REFS_PSEUDOREFS) struct atom_value; struct ref_sorting; diff --git a/reflog-walk.c b/reflog-walk.c index d216f6f966..66484f4f32 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -223,7 +223,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info, void get_reflog_selector(struct strbuf *sb, struct reflog_walk_info *reflog_info, - const struct date_mode *dmode, int force_date, + struct date_mode dmode, int force_date, int shorten) { struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog; @@ -297,7 +297,7 @@ timestamp_t get_reflog_timestamp(struct reflog_walk_info *reflog_info) } void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline, - const struct date_mode *dmode, int force_date) + struct date_mode dmode, int force_date) { if (reflog_info && reflog_info->last_commit_reflog) { struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog; diff --git a/reflog-walk.h b/reflog-walk.h index 4d93a26957..989583dc55 100644 --- a/reflog-walk.h +++ b/reflog-walk.h @@ -10,14 +10,14 @@ void reflog_walk_info_release(struct reflog_walk_info *info); int add_reflog_for_walk(struct reflog_walk_info *info, struct commit *commit, const char *name); void show_reflog_message(struct reflog_walk_info *info, int, - const struct date_mode *, int force_date); + struct date_mode, int force_date); void get_reflog_message(struct strbuf *sb, struct reflog_walk_info *reflog_info); const char *get_reflog_ident(struct reflog_walk_info *reflog_info); timestamp_t get_reflog_timestamp(struct reflog_walk_info *reflog_info); void get_reflog_selector(struct strbuf *sb, struct reflog_walk_info *reflog_info, - const struct date_mode *dmode, int force_date, + struct date_mode dmode, int force_date, int shorten); int reflog_walk_empty(struct reflog_walk_info *walk); @@ -39,7 +39,7 @@ static int tree_is_complete(const struct object_id *oid) tree->buffer = data; tree->size = size; } - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); complete = 1; while (tree_entry(&desc, &entry)) { if (!repo_has_object_file(the_repository, &entry.oid) || @@ -35,6 +35,7 @@ */ static const struct ref_storage_be *refs_backends[] = { [REF_STORAGE_FORMAT_FILES] = &refs_be_files, + [REF_STORAGE_FORMAT_REFTABLE] = &refs_be_reftable, }; static const struct ref_storage_be *find_ref_storage_backend(unsigned int ref_storage_format) @@ -859,6 +860,47 @@ static int is_pseudoref_syntax(const char *refname) return 1; } +int is_pseudoref(struct ref_store *refs, const char *refname) +{ + static const char *const irregular_pseudorefs[] = { + "AUTO_MERGE", + "BISECT_EXPECTED_REV", + "NOTES_MERGE_PARTIAL", + "NOTES_MERGE_REF", + "MERGE_AUTOSTASH", + }; + struct object_id oid; + size_t i; + + if (!is_pseudoref_syntax(refname)) + return 0; + + if (ends_with(refname, "_HEAD")) { + refs_resolve_ref_unsafe(refs, refname, + RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + &oid, NULL); + return !is_null_oid(&oid); + } + + for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++) + if (!strcmp(refname, irregular_pseudorefs[i])) { + refs_resolve_ref_unsafe(refs, refname, + RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + &oid, NULL); + return !is_null_oid(&oid); + } + + return 0; +} + +int is_headref(struct ref_store *refs, const char *refname) +{ + if (!strcmp(refname, "HEAD")) + return refs_ref_exists(refs, refname); + + return 0; +} + static int is_current_worktree_ref(const char *ref) { return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref); } @@ -1038,55 +1080,40 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid, const char *message, void *cb_data) { struct read_ref_at_cb *cb = cb_data; - int reached_count; cb->tz = tz; cb->date = timestamp; - /* - * It is not possible for cb->cnt == 0 on the first iteration because - * that special case is handled in read_ref_at(). - */ - if (cb->cnt > 0) - cb->cnt--; - reached_count = cb->cnt == 0 && !is_null_oid(ooid); - if (timestamp <= cb->at_time || reached_count) { + if (timestamp <= cb->at_time || cb->cnt == 0) { set_read_ref_cutoffs(cb, timestamp, tz, message); /* * we have not yet updated cb->[n|o]oid so they still * hold the values for the previous record. */ - if (!is_null_oid(&cb->ooid) && !oideq(&cb->ooid, noid)) - warning(_("log for ref %s has gap after %s"), + if (!is_null_oid(&cb->ooid)) { + oidcpy(cb->oid, noid); + if (!oideq(&cb->ooid, noid)) + warning(_("log for ref %s has gap after %s"), cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822))); - if (reached_count) - oidcpy(cb->oid, ooid); - else if (!is_null_oid(&cb->ooid) || cb->date == cb->at_time) + } + else if (cb->date == cb->at_time) oidcpy(cb->oid, noid); else if (!oideq(noid, cb->oid)) warning(_("log for ref %s unexpectedly ended on %s"), cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822))); + cb->reccnt++; + oidcpy(&cb->ooid, ooid); + oidcpy(&cb->noid, noid); cb->found_it = 1; + return 1; } cb->reccnt++; oidcpy(&cb->ooid, ooid); oidcpy(&cb->noid, noid); - return cb->found_it; -} - -static int read_ref_at_ent_newest(struct object_id *ooid UNUSED, - struct object_id *noid, - const char *email UNUSED, - timestamp_t timestamp, int tz, - const char *message, void *cb_data) -{ - struct read_ref_at_cb *cb = cb_data; - - set_read_ref_cutoffs(cb, timestamp, tz, message); - oidcpy(cb->oid, noid); - /* We just want the first entry */ - return 1; + if (cb->cnt > 0) + cb->cnt--; + return 0; } static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid, @@ -1098,7 +1125,7 @@ static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid set_read_ref_cutoffs(cb, timestamp, tz, message); oidcpy(cb->oid, ooid); - if (is_null_oid(cb->oid)) + if (cb->at_time && is_null_oid(cb->oid)) oidcpy(cb->oid, noid); /* We just want the first entry */ return 1; @@ -1121,14 +1148,24 @@ int read_ref_at(struct ref_store *refs, const char *refname, cb.cutoff_cnt = cutoff_cnt; cb.oid = oid; - if (cb.cnt == 0) { - refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent_newest, &cb); - return 0; - } - refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb); if (!cb.reccnt) { + if (cnt == 0) { + /* + * The caller asked for ref@{0}, and we had no entries. + * It's a bit subtle, but in practice all callers have + * prepped the "oid" field with the current value of + * the ref, which is the most reasonable fallback. + * + * We'll put dummy values into the out-parameters (so + * they're not just uninitialized garbage), and the + * caller can take our return value as a hint that + * we did not find any such reflog. + */ + set_read_ref_cutoffs(&cb, 0, 0, "empty reflog"); + return 1; + } if (flags & GET_OID_QUIETLY) exit(128); else @@ -1593,10 +1630,6 @@ struct ref_iterator *refs_ref_iterator_begin( if (trim) iter = prefix_ref_iterator_begin(iter, "", trim); - /* Sanity check for subclasses: */ - if (!iter->ordered) - BUG("reference iterator is not ordered"); - return iter; } @@ -1723,6 +1756,13 @@ 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); } +int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn, + void *cb_data) +{ + return do_for_each_ref(refs, "", NULL, fn, 0, + DO_FOR_EACH_INCLUDE_ROOT_REFS, cb_data); +} + static int qsort_strcmp(const void *va, const void *vb) { const char *a = *(const char **)va; @@ -2515,18 +2555,33 @@ cleanup: return ret; } -int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data) +struct do_for_each_reflog_help { + each_reflog_fn *fn; + void *cb_data; +}; + +static int do_for_each_reflog_helper(struct repository *r UNUSED, + const char *refname, + const struct object_id *oid UNUSED, + int flags, + void *cb_data) +{ + struct do_for_each_reflog_help *hp = cb_data; + return hp->fn(refname, hp->cb_data); +} + +int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data) { struct ref_iterator *iter; - struct do_for_each_ref_help hp = { fn, cb_data }; + struct do_for_each_reflog_help hp = { fn, cb_data }; iter = refs->be->reflog_iterator_begin(refs); return do_for_each_repo_ref_iterator(the_repository, iter, - do_for_each_ref_helper, &hp); + do_for_each_reflog_helper, &hp); } -int for_each_reflog(each_ref_fn fn, void *cb_data) +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); } @@ -66,12 +66,6 @@ const char *ref_storage_format_to_name(unsigned int ref_storage_format); #define RESOLVE_REF_NO_RECURSE 0x02 #define RESOLVE_REF_ALLOW_BAD_NAME 0x04 -struct pack_refs_opts { - unsigned int flags; - struct ref_exclusions *exclusions; - struct string_list *includes; -}; - const char *refs_resolve_ref_unsafe(struct ref_store *refs, const char *refname, int resolve_flags, @@ -399,6 +393,12 @@ int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data); int for_each_rawref(each_ref_fn fn, void *cb_data); /* + * Iterates over all refs including root refs, i.e. pseudorefs and HEAD. + */ +int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn, + void *cb_data); + +/* * Normalizes partial refs to their fully qualified form. * Will prepend <prefix> to the <pattern> if it doesn't start with 'refs/'. * <prefix> will default to 'refs/' if NULL. @@ -422,10 +422,18 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, /* * Flags for controlling behaviour of pack_refs() * PACK_REFS_PRUNE: Prune loose refs after packing - * PACK_REFS_ALL: Pack _all_ refs, not just tags and already packed refs + * PACK_REFS_AUTO: Pack refs on a best effort basis. The heuristics and end + * result are decided by the ref backend. Backends may ignore + * this flag and fall back to a normal repack. */ -#define PACK_REFS_PRUNE 0x0001 -#define PACK_REFS_ALL 0x0002 +#define PACK_REFS_PRUNE (1 << 0) +#define PACK_REFS_AUTO (1 << 1) + +struct pack_refs_opts { + unsigned int flags; + struct ref_exclusions *exclusions; + struct string_list *includes; +}; /* * Write a packed-refs file for the current repository. @@ -440,7 +448,20 @@ int refs_create_reflog(struct ref_store *refs, const char *refname, struct strbuf *err); int safe_create_reflog(const char *refname, struct strbuf *err); -/** Reads log for the value of ref during at_time. **/ +/** + * Reads log for the value of ref during at_time (in which case "cnt" should be + * negative) or the reflog "cnt" entries from the top (in which case "at_time" + * should be 0). + * + * If we found the reflog entry in question, returns 0 (and details of the + * entry can be found in the out-parameters). + * + * If we ran out of reflog entries, the out-parameters are filled with the + * details of the oldest entry we did find, and the function returns 1. Note + * that there is one important special case here! If the reflog was empty + * and the caller asked for the 0-th cnt, we will return "1" but leave the + * "oid" field untouched. + **/ int read_ref_at(struct ref_store *refs, const char *refname, unsigned int flags, timestamp_t at_time, int cnt, @@ -535,11 +556,18 @@ int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_dat int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data); /* + * The signature for the callback function for the {refs_,}for_each_reflog() + * functions below. The memory pointed to by the refname argument is only + * guaranteed to be valid for the duration of a single callback invocation. + */ +typedef int each_reflog_fn(const char *refname, void *cb_data); + +/* * Calls the specified function for each reflog file until it returns nonzero, * and returns the value. Reflog file order is unspecified. */ -int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data); -int for_each_reflog(each_ref_fn fn, void *cb_data); +int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data); +int for_each_reflog(each_reflog_fn fn, void *cb_data); #define REFNAME_ALLOW_ONELEVEL 1 #define REFNAME_REFSPEC_PATTERN 2 @@ -1023,4 +1051,7 @@ extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT]; */ void update_ref_namespace(enum ref_namespace namespace, char *ref); +int is_pseudoref(struct ref_store *refs, const char *refname); +int is_headref(struct ref_store *refs, const char *refname); + #endif /* REFS_H */ diff --git a/refs/debug.c b/refs/debug.c index 634681ca44..c7531b17f0 100644 --- a/refs/debug.c +++ b/refs/debug.c @@ -181,7 +181,6 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator) trace_printf_key(&trace_refs, "iterator_advance: %s (0)\n", diter->iter->refname); - diter->base.ordered = diter->iter->ordered; diter->base.refname = diter->iter->refname; diter->base.oid = diter->iter->oid; diter->base.flags = diter->iter->flags; @@ -222,7 +221,7 @@ debug_ref_iterator_begin(struct ref_store *ref_store, const char *prefix, drefs->refs->be->iterator_begin(drefs->refs, prefix, exclude_patterns, flags); struct debug_ref_iterator *diter = xcalloc(1, sizeof(*diter)); - base_ref_iterator_init(&diter->base, &debug_ref_iterator_vtable, 1); + base_ref_iterator_init(&diter->base, &debug_ref_iterator_vtable); diter->iter = res; trace_printf_key(&trace_refs, "ref_iterator_begin: \"%s\" (0x%x)\n", prefix, flags); diff --git a/refs/files-backend.c b/refs/files-backend.c index 75dcc21ecb..a098d14ea0 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -229,6 +229,38 @@ static void add_per_worktree_entries_to_dir(struct ref_dir *dir, const char *dir } } +static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs, + const char *refname, + struct ref_dir *dir) +{ + struct object_id oid; + int flag; + + if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING, + &oid, &flag)) { + oidclr(&oid); + flag |= REF_ISBROKEN; + } else if (is_null_oid(&oid)) { + /* + * It is so astronomically unlikely + * that null_oid is the OID of an + * actual object that we consider its + * appearance in a loose reference + * file to be repo corruption + * (probably due to a software bug). + */ + flag |= REF_ISBROKEN; + } + + if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { + if (!refname_is_safe(refname)) + die("loose refname is dangerous: %s", refname); + oidclr(&oid); + flag |= REF_BAD_NAME | REF_ISBROKEN; + } + add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag)); +} + /* * Read the loose references from the namespace dirname into dir * (without recursing). dirname must end with '/'. dir must be the @@ -257,8 +289,6 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, strbuf_add(&refname, dirname, dirnamelen); while ((de = readdir(d)) != NULL) { - struct object_id oid; - int flag; unsigned char dtype; if (de->d_name[0] == '.') @@ -274,33 +304,7 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, create_dir_entry(dir->cache, refname.buf, refname.len)); } else if (dtype == DT_REG) { - if (!refs_resolve_ref_unsafe(&refs->base, - refname.buf, - RESOLVE_REF_READING, - &oid, &flag)) { - oidclr(&oid); - flag |= REF_ISBROKEN; - } else if (is_null_oid(&oid)) { - /* - * It is so astronomically unlikely - * that null_oid is the OID of an - * actual object that we consider its - * appearance in a loose reference - * file to be repo corruption - * (probably due to a software bug). - */ - flag |= REF_ISBROKEN; - } - - if (check_refname_format(refname.buf, - REFNAME_ALLOW_ONELEVEL)) { - if (!refname_is_safe(refname.buf)) - die("loose refname is dangerous: %s", refname.buf); - oidclr(&oid); - flag |= REF_BAD_NAME | REF_ISBROKEN; - } - add_entry_to_dir(dir, - create_ref_entry(refname.buf, &oid, flag)); + loose_fill_ref_dir_regular_file(refs, refname.buf, dir); } strbuf_setlen(&refname, dirnamelen); } @@ -311,9 +315,59 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, add_per_worktree_entries_to_dir(dir, dirname); } -static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs) +/* + * Add pseudorefs to the ref dir by parsing the directory for any files + * which follow the pseudoref syntax. + */ +static void add_pseudoref_and_head_entries(struct ref_store *ref_store, + struct ref_dir *dir, + const char *dirname) +{ + struct files_ref_store *refs = + files_downcast(ref_store, REF_STORE_READ, "fill_ref_dir"); + struct strbuf path = STRBUF_INIT, refname = STRBUF_INIT; + struct dirent *de; + size_t dirnamelen; + DIR *d; + + files_ref_path(refs, &path, dirname); + + d = opendir(path.buf); + if (!d) { + strbuf_release(&path); + return; + } + + strbuf_addstr(&refname, dirname); + dirnamelen = refname.len; + + while ((de = readdir(d)) != NULL) { + unsigned char dtype; + + if (de->d_name[0] == '.') + continue; + if (ends_with(de->d_name, ".lock")) + continue; + strbuf_addstr(&refname, de->d_name); + + dtype = get_dtype(de, &path, 1); + if (dtype == DT_REG && (is_pseudoref(ref_store, de->d_name) || + is_headref(ref_store, de->d_name))) + loose_fill_ref_dir_regular_file(refs, refname.buf, dir); + + strbuf_setlen(&refname, dirnamelen); + } + strbuf_release(&refname); + strbuf_release(&path); + closedir(d); +} + +static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs, + unsigned int flags) { if (!refs->loose) { + struct ref_dir *dir; + /* * Mark the top-level directory complete because we * are about to read the only subdirectory that can @@ -324,12 +378,17 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs) /* We're going to fill the top level ourselves: */ refs->loose->root->flag &= ~REF_INCOMPLETE; + dir = get_ref_dir(refs->loose->root); + + if (flags & DO_FOR_EACH_INCLUDE_ROOT_REFS) + add_pseudoref_and_head_entries(dir->cache->ref_store, dir, + refs->loose->root->name); + /* * Add an incomplete entry for "refs/" (to be filled * lazily): */ - add_entry_to_dir(get_ref_dir(refs->loose->root), - create_dir_entry(refs->loose, "refs/", 5)); + add_entry_to_dir(dir, create_dir_entry(refs->loose, "refs/", 5)); } return refs->loose; } @@ -857,7 +916,7 @@ static struct ref_iterator *files_ref_iterator_begin( * disk, and re-reads it if not. */ - loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), + loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, flags), prefix, ref_store->repo, 1); /* @@ -879,8 +938,7 @@ static struct ref_iterator *files_ref_iterator_begin( CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; - base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable, - overlay_iter->ordered); + base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable); iter->iter0 = overlay_iter; iter->repo = ref_store->repo; iter->flags = flags; @@ -1218,7 +1276,7 @@ static int files_pack_refs(struct ref_store *ref_store, packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err); - iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL, + iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL, the_repository, 0); while ((ok = ref_iterator_advance(iter)) == ITER_OK) { /* @@ -2116,10 +2174,8 @@ static int files_for_each_reflog_ent(struct ref_store *ref_store, struct files_reflog_iterator { struct ref_iterator base; - struct ref_store *ref_store; struct dir_iterator *dir_iterator; - struct object_id oid; }; static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) @@ -2130,25 +2186,13 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) int ok; while ((ok = dir_iterator_advance(diter)) == ITER_OK) { - int flags; - if (!S_ISREG(diter->st.st_mode)) continue; - if (diter->basename[0] == '.') + if (check_refname_format(diter->basename, + REFNAME_ALLOW_ONELEVEL)) continue; - if (ends_with(diter->basename, ".lock")) - continue; - - if (!refs_resolve_ref_unsafe(iter->ref_store, - diter->relative_path, 0, - &iter->oid, &flags)) { - error("bad ref for %s", diter->path.buf); - continue; - } iter->base.refname = diter->relative_path; - iter->base.oid = &iter->oid; - iter->base.flags = flags; return ITER_OK; } @@ -2193,7 +2237,7 @@ static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, strbuf_addf(&sb, "%s/logs", gitdir); - diter = dir_iterator_begin(sb.buf, 0); + diter = dir_iterator_begin(sb.buf, DIR_ITERATOR_SORTED); if (!diter) { strbuf_release(&sb); return empty_ref_iterator_begin(); @@ -2202,7 +2246,7 @@ static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; - base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable, 0); + base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable); iter->dir_iterator = diter; iter->ref_store = ref_store; strbuf_release(&sb); @@ -2210,32 +2254,6 @@ static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, return ref_iterator; } -static enum iterator_selection reflog_iterator_select( - struct ref_iterator *iter_worktree, - struct ref_iterator *iter_common, - void *cb_data UNUSED) -{ - if (iter_worktree) { - /* - * We're a bit loose here. We probably should ignore - * common refs if they are accidentally added as - * per-worktree refs. - */ - return ITER_SELECT_0; - } else if (iter_common) { - if (parse_worktree_ref(iter_common->refname, NULL, NULL, - NULL) == REF_WORKTREE_SHARED) - return ITER_SELECT_1; - - /* - * The main ref store may contain main worktree's - * per-worktree refs, which should be ignored - */ - return ITER_SKIP_1; - } else - return ITER_DONE; -} - static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store) { struct files_ref_store *refs = @@ -2246,9 +2264,9 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st return reflog_iterator_begin(ref_store, refs->gitcommondir); } else { return merge_ref_iterator_begin( - 0, reflog_iterator_begin(ref_store, refs->base.gitdir), + reflog_iterator_begin(ref_store, refs->base.gitdir), reflog_iterator_begin(ref_store, refs->gitcommondir), - reflog_iterator_select, refs); + ref_iterator_select, refs); } } diff --git a/refs/iterator.c b/refs/iterator.c index 6b680f610e..9db8b056d5 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -25,11 +25,9 @@ int ref_iterator_abort(struct ref_iterator *ref_iterator) } void base_ref_iterator_init(struct ref_iterator *iter, - struct ref_iterator_vtable *vtable, - int ordered) + struct ref_iterator_vtable *vtable) { iter->vtable = vtable; - iter->ordered = !!ordered; iter->refname = NULL; iter->oid = NULL; iter->flags = 0; @@ -74,7 +72,7 @@ struct ref_iterator *empty_ref_iterator_begin(void) struct empty_ref_iterator *iter = xcalloc(1, sizeof(*iter)); struct ref_iterator *ref_iterator = &iter->base; - base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable, 1); + base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable); return ref_iterator; } @@ -98,6 +96,49 @@ struct merge_ref_iterator { struct ref_iterator **current; }; +enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree, + struct ref_iterator *iter_common, + void *cb_data UNUSED) +{ + if (iter_worktree && !iter_common) { + /* + * Return the worktree ref if there are no more common refs. + */ + return ITER_SELECT_0; + } else if (iter_common) { + /* + * In case we have pending worktree and common refs we need to + * yield them based on their lexicographical order. Worktree + * refs that have the same name as common refs shadow the + * latter. + */ + if (iter_worktree) { + int cmp = strcmp(iter_worktree->refname, + iter_common->refname); + if (cmp < 0) + return ITER_SELECT_0; + else if (!cmp) + return ITER_SELECT_0_SKIP_1; + } + + /* + * We now know that the lexicographically-next ref is a common + * ref. When the common ref is a shared one we return it. + */ + if (parse_worktree_ref(iter_common->refname, NULL, NULL, + NULL) == REF_WORKTREE_SHARED) + return ITER_SELECT_1; + + /* + * Otherwise, if the common ref is a per-worktree ref we skip + * it because it would belong to the main worktree, not ours. + */ + return ITER_SKIP_1; + } else { + return ITER_DONE; + } +} + static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) { struct merge_ref_iterator *iter = @@ -207,7 +248,6 @@ static struct ref_iterator_vtable merge_ref_iterator_vtable = { }; struct ref_iterator *merge_ref_iterator_begin( - int ordered, struct ref_iterator *iter0, struct ref_iterator *iter1, ref_iterator_select_fn *select, void *cb_data) { @@ -222,7 +262,7 @@ struct ref_iterator *merge_ref_iterator_begin( * references through only if they exist in both iterators. */ - base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable, ordered); + base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable); iter->iter0 = iter0; iter->iter1 = iter1; iter->select = select; @@ -271,12 +311,9 @@ struct ref_iterator *overlay_ref_iterator_begin( } else if (is_empty_ref_iterator(back)) { ref_iterator_abort(back); return front; - } else if (!front->ordered || !back->ordered) { - BUG("overlay_ref_iterator requires ordered inputs"); } - return merge_ref_iterator_begin(1, front, back, - overlay_iterator_select, NULL); + return merge_ref_iterator_begin(front, back, overlay_iterator_select, NULL); } struct prefix_ref_iterator { @@ -315,16 +352,12 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator) if (cmp > 0) { /* - * If the source iterator is ordered, then we + * As the source iterator is ordered, we * can stop the iteration as soon as we see a * refname that comes after the prefix: */ - if (iter->iter0->ordered) { - ok = ref_iterator_abort(iter->iter0); - break; - } else { - continue; - } + ok = ref_iterator_abort(iter->iter0); + break; } if (iter->trim) { @@ -396,7 +429,7 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; - base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable, iter0->ordered); + base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable); iter->iter0 = iter0; iter->prefix = xstrdup(prefix); diff --git a/refs/packed-backend.c b/refs/packed-backend.c index a499a91c7e..4e826c05ff 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -1111,7 +1111,7 @@ static struct ref_iterator *packed_ref_iterator_begin( CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; - base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable, 1); + base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable); if (exclude_patterns) populate_excluded_jump_list(iter, snapshot, exclude_patterns); diff --git a/refs/ref-cache.c b/refs/ref-cache.c index a372a00941..9f9797209a 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -486,7 +486,7 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; - base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable, 1); + base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable); ALLOC_GROW(iter->levels, 10, iter->levels_alloc); iter->levels_nr = 1; diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 82219829b0..56641aa57a 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -260,6 +260,12 @@ enum do_for_each_ref_flags { * INCLUDE_BROKEN, since they are otherwise not included at all. */ DO_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2), + + /* + * Include root refs i.e. HEAD and pseudorefs along with the regular + * refs. + */ + DO_FOR_EACH_INCLUDE_ROOT_REFS = (1 << 3), }; /* @@ -312,13 +318,6 @@ enum do_for_each_ref_flags { */ struct ref_iterator { struct ref_iterator_vtable *vtable; - - /* - * Does this `ref_iterator` iterate over references in order - * by refname? - */ - unsigned int ordered : 1; - const char *refname; const struct object_id *oid; unsigned int flags; @@ -387,14 +386,21 @@ typedef enum iterator_selection ref_iterator_select_fn( void *cb_data); /* + * An implementation of ref_iterator_select_fn that merges worktree and common + * refs. Per-worktree refs from the common iterator are ignored, worktree refs + * override common refs. Refs are selected lexicographically. + */ +enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree, + struct ref_iterator *iter_common, + void *cb_data); + +/* * Iterate over the entries from iter0 and iter1, with the values * interleaved as directed by the select function. The iterator takes * ownership of iter0 and iter1 and frees them when the iteration is - * over. A derived class should set `ordered` to 1 or 0 based on - * whether it generates its output in order by reference name. + * over. */ struct ref_iterator *merge_ref_iterator_begin( - int ordered, struct ref_iterator *iter0, struct ref_iterator *iter1, ref_iterator_select_fn *select, void *cb_data); @@ -423,8 +429,6 @@ struct ref_iterator *overlay_ref_iterator_begin( * As an convenience to callers, if prefix is the empty string and * trim is zero, this function returns iter0 directly, without * wrapping it. - * - * The resulting ref_iterator is ordered if iter0 is. */ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, const char *prefix, @@ -435,14 +439,11 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, /* * Base class constructor for ref_iterators. Initialize the * ref_iterator part of iter, setting its vtable pointer as specified. - * `ordered` should be set to 1 if the iterator will iterate over - * references in order by refname; otherwise it should be set to 0. * This is meant to be called only by the initializers of derived * classes. */ void base_ref_iterator_init(struct ref_iterator *iter, - struct ref_iterator_vtable *vtable, - int ordered); + struct ref_iterator_vtable *vtable); /* * Base class destructor for ref_iterators. Destroy the ref_iterator @@ -693,6 +694,7 @@ struct ref_storage_be { }; extern struct ref_storage_be refs_be_files; +extern struct ref_storage_be refs_be_reftable; extern struct ref_storage_be refs_be_packed; /* diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c new file mode 100644 index 0000000000..1cda48c504 --- /dev/null +++ b/refs/reftable-backend.c @@ -0,0 +1,2242 @@ +#include "../git-compat-util.h" +#include "../abspath.h" +#include "../chdir-notify.h" +#include "../environment.h" +#include "../gettext.h" +#include "../hash.h" +#include "../hex.h" +#include "../iterator.h" +#include "../ident.h" +#include "../lockfile.h" +#include "../object.h" +#include "../path.h" +#include "../refs.h" +#include "../reftable/reftable-stack.h" +#include "../reftable/reftable-record.h" +#include "../reftable/reftable-error.h" +#include "../reftable/reftable-iterator.h" +#include "../reftable/reftable-merged.h" +#include "../setup.h" +#include "../strmap.h" +#include "parse.h" +#include "refs-internal.h" + +/* + * Used as a flag in ref_update::flags when the ref_update was via an + * update to HEAD. + */ +#define REF_UPDATE_VIA_HEAD (1 << 8) + +struct reftable_ref_store { + struct ref_store base; + + /* + * The main stack refers to the common dir and thus contains common + * refs as well as refs of the main repository. + */ + struct reftable_stack *main_stack; + /* + * The worktree stack 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; + /* + * Map of worktree stacks by their respective worktree names. The map + * is populated lazily when we try to resolve `worktrees/$worktree` refs. + */ + struct strmap worktree_stacks; + struct reftable_write_options write_options; + + unsigned int store_flags; + int err; +}; + +/* + * Downcast ref_store to reftable_ref_store. Die if ref_store is not a + * reftable_ref_store. required_flags is compared with ref_store's store_flags + * to ensure the ref_store has all required capabilities. "caller" is used in + * any necessary error messages. + */ +static struct reftable_ref_store *reftable_be_downcast(struct ref_store *ref_store, + unsigned int required_flags, + const char *caller) +{ + struct reftable_ref_store *refs; + + if (ref_store->be != &refs_be_reftable) + BUG("ref_store is type \"%s\" not \"reftables\" in %s", + ref_store->be->name, caller); + + refs = (struct reftable_ref_store *)ref_store; + + if ((refs->store_flags & required_flags) != required_flags) + BUG("operation %s requires abilities 0x%x, but only have 0x%x", + caller, required_flags, refs->store_flags); + + return refs; +} + +/* + * Some refs are global to the repository (refs/heads/{*}), while others are + * local to the worktree (eg. HEAD, refs/bisect/{*}). We solve this by having + * multiple separate databases (ie. multiple reftable/ directories), one for + * the shared refs, one for the current worktree refs, and one for each + * additional worktree. For reading, we merge the view of both the shared and + * the current worktree's refs, when necessary. + * + * This function also optionally assigns the rewritten reference name that is + * local to the stack. This translation is required when using worktree refs + * 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) +{ + const char *wtname; + int wtname_len; + + if (!refname) + return store->main_stack; + + 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 + * allocate the worktree name whenever we look up a reference. + * This could be avoided if the strmap interface knew how to + * handle keys with a length. + */ + strbuf_reset(&wtname_buf); + strbuf_add(&wtname_buf, wtname, wtname_len); + + /* + * 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 + * 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) { + 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); + assert(store->err != REFTABLE_API_ERROR); + strmap_put(&store->worktree_stacks, wtname_buf.buf, stack); + } + + strbuf_release(&wt_dir); + return stack; + } + 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; + case REF_WORKTREE_MAIN: + case REF_WORKTREE_SHARED: + return store->main_stack; + default: + BUG("unhandled worktree reference type"); + } +} + +static int should_write_log(struct 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; + + switch (log_all_ref_updates) { + case LOG_REFS_NONE: + return refs_reflog_exists(refs, refname); + case LOG_REFS_ALWAYS: + return 1; + case LOG_REFS_NORMAL: + if (should_autocreate_reflog(refname)) + return 1; + return refs_reflog_exists(refs, refname); + default: + BUG("unhandled core.logAllRefUpdates value %d", log_all_ref_updates); + } +} + +static void fill_reftable_log_record(struct reftable_log_record *log) +{ + const char *info = git_committer_info(0); + struct ident_split split = {0}; + int sign = 1; + + if (split_ident_line(&split, info, strlen(info))) + BUG("failed splitting committer info"); + + reftable_log_record_release(log); + log->value_type = REFTABLE_LOG_UPDATE; + log->value.update.name = + xstrndup(split.name_begin, split.name_end - split.name_begin); + log->value.update.email = + xstrndup(split.mail_begin, split.mail_end - split.mail_begin); + log->value.update.time = atol(split.date_begin); + if (*split.tz_begin == '-') { + sign = -1; + split.tz_begin++; + } + if (*split.tz_begin == '+') { + sign = 1; + split.tz_begin++; + } + + log->value.update.tz_offset = sign * atoi(split.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)); + } 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 struct ref_store *reftable_be_init(struct repository *repo, + const char *gitdir, + unsigned int store_flags) +{ + struct reftable_ref_store *refs = xcalloc(1, sizeof(*refs)); + struct strbuf path = STRBUF_INIT; + int is_worktree; + mode_t mask; + + mask = umask(0); + umask(mask); + + base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable); + strmap_init(&refs->worktree_stacks); + refs->store_flags = store_flags; + refs->write_options.block_size = 4096; + refs->write_options.hash_id = 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); + + /* + * Set up the main reftable stack that is hosted in GIT_COMMON_DIR. + * This stack contains both the shared and the main worktree refs. + * + * Note that we don't try to resolve the path in case we have a + * worktree because `get_common_dir_noenv()` already does it for us. + */ + is_worktree = get_common_dir_noenv(&path, gitdir); + if (!is_worktree) { + strbuf_reset(&path); + strbuf_realpath(&path, gitdir, 0); + } + strbuf_addstr(&path, "/reftable"); + refs->err = reftable_new_stack(&refs->main_stack, path.buf, + refs->write_options); + if (refs->err) + goto done; + + /* + * If we're in a worktree we also need to set up the worktree reftable + * stack that is contained in the per-worktree GIT_DIR. + * + * Ideally, we would also add the stack to our worktree stack map. But + * we have no way to figure out the worktree name here and thus can't + * do it efficiently. + */ + if (is_worktree) { + strbuf_reset(&path); + strbuf_addf(&path, "%s/reftable", gitdir); + + refs->err = reftable_new_stack(&refs->worktree_stack, path.buf, + refs->write_options); + if (refs->err) + goto done; + } + + chdir_notify_reparent("reftables-backend $GIT_DIR", &refs->base.gitdir); + +done: + assert(refs->err != REFTABLE_API_ERROR); + strbuf_release(&path); + return &refs->base; +} + +static int reftable_be_init_db(struct ref_store *ref_store, + int flags UNUSED, + struct strbuf *err UNUSED) +{ + struct reftable_ref_store *refs = + reftable_be_downcast(ref_store, REF_STORE_WRITE, "init_db"); + struct strbuf sb = STRBUF_INIT; + + strbuf_addf(&sb, "%s/reftable", refs->base.gitdir); + safe_create_dir(sb.buf, 1); + strbuf_reset(&sb); + + strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir); + write_file(sb.buf, "ref: refs/heads/.invalid"); + adjust_shared_perm(sb.buf); + strbuf_reset(&sb); + + strbuf_addf(&sb, "%s/refs", refs->base.gitdir); + safe_create_dir(sb.buf, 1); + strbuf_reset(&sb); + + strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir); + write_file(sb.buf, "this repository uses the reftable format"); + adjust_shared_perm(sb.buf); + + strbuf_release(&sb); + return 0; +} + +struct reftable_ref_iterator { + struct ref_iterator base; + struct reftable_ref_store *refs; + struct reftable_iterator iter; + struct reftable_ref_record ref; + struct object_id oid; + + const char *prefix; + size_t prefix_len; + unsigned int flags; + int err; +}; + +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; + + while (!iter->err) { + int flags = 0; + + iter->err = reftable_iterator_next_ref(&iter->iter, &iter->ref); + if (iter->err) + break; + + /* + * The files backend only lists references contained in "refs/" unless + * the root refs are to be included. We emulate the same behaviour here. + */ + if (!starts_with(iter->ref.refname, "refs/") && + !(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS && + (is_pseudoref(&iter->refs->base, iter->ref.refname) || + is_headref(&iter->refs->base, iter->ref.refname)))) { + continue; + } + + if (iter->prefix_len && + strncmp(iter->prefix, iter->ref.refname, iter->prefix_len)) { + iter->err = 1; + break; + } + + if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY && + parse_worktree_ref(iter->ref.refname, NULL, NULL, NULL) != + REF_WORKTREE_CURRENT) + continue; + + switch (iter->ref.value_type) { + case REFTABLE_REF_VAL1: + oidread(&iter->oid, iter->ref.value.val1); + break; + case REFTABLE_REF_VAL2: + oidread(&iter->oid, iter->ref.value.val2.value); + 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); + break; + default: + BUG("unhandled reference value type %d", iter->ref.value_type); + } + + if (is_null_oid(&iter->oid)) + flags |= REF_ISBROKEN; + + 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); + flags |= REF_BAD_NAME | REF_ISBROKEN; + } + + if (iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS && + flags & REF_ISSYMREF && + flags & REF_ISBROKEN) + continue; + + if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) && + !ref_resolves_to_object(iter->ref.refname, refs->base.repo, + &iter->oid, flags)) + continue; + + iter->base.refname = iter->ref.refname; + iter->base.oid = &iter->oid; + iter->base.flags = flags; + + break; + } + + if (iter->err > 0) { + if (ref_iterator_abort(ref_iterator) != ITER_DONE) + return ITER_ERROR; + return ITER_DONE; + } + + if (iter->err < 0) { + ref_iterator_abort(ref_iterator); + return ITER_ERROR; + } + + return ITER_OK; +} + +static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator, + struct object_id *peeled) +{ + struct reftable_ref_iterator *iter = + (struct reftable_ref_iterator *)ref_iterator; + + if (iter->ref.value_type == REFTABLE_REF_VAL2) { + oidread(peeled, iter->ref.value.val2.target_value); + return 0; + } + + return -1; +} + +static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator) +{ + struct reftable_ref_iterator *iter = + (struct reftable_ref_iterator *)ref_iterator; + reftable_ref_record_release(&iter->ref); + reftable_iterator_destroy(&iter->iter); + free(iter); + return ITER_DONE; +} + +static struct ref_iterator_vtable reftable_ref_iterator_vtable = { + .advance = reftable_ref_iterator_advance, + .peel = reftable_ref_iterator_peel, + .abort = reftable_ref_iterator_abort +}; + +static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_store *refs, + struct reftable_stack *stack, + const char *prefix, + int flags) +{ + struct reftable_merged_table *merged_table; + struct reftable_ref_iterator *iter; + int ret; + + iter = xcalloc(1, sizeof(*iter)); + base_ref_iterator_init(&iter->base, &reftable_ref_iterator_vtable); + iter->prefix = prefix; + iter->prefix_len = prefix ? strlen(prefix) : 0; + iter->base.oid = &iter->oid; + iter->flags = flags; + iter->refs = refs; + + ret = refs->err; + if (ret) + goto done; + + ret = reftable_stack_reload(stack); + if (ret) + goto done; + + merged_table = reftable_stack_merged_table(stack); + + ret = reftable_merged_table_seek_ref(merged_table, &iter->iter, prefix); + if (ret) + goto done; + +done: + iter->err = ret; + return iter; +} + +static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_store, + const char *prefix, + const char **exclude_patterns, + unsigned int flags) +{ + struct reftable_ref_iterator *main_iter, *worktree_iter; + struct reftable_ref_store *refs; + unsigned int required_flags = REF_STORE_READ; + + if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) + 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); + + /* + * 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) + 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); + return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base, + ref_iterator_select, NULL); +} + +static int reftable_be_read_raw_ref(struct ref_store *ref_store, + const char *refname, + struct object_id *oid, + struct strbuf *referent, + unsigned int *type, + int *failure_errno) +{ + 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); + int ret; + + if (refs->err < 0) + return refs->err; + + ret = reftable_stack_reload(stack); + if (ret) + return ret; + + ret = read_ref_without_reload(stack, refname, oid, referent, type); + if (ret < 0) + return ret; + if (ret > 0) { + *failure_errno = ENOENT; + return -1; + } + + return 0; +} + +static int reftable_be_read_symbolic_ref(struct ref_store *ref_store, + const char *refname, + struct strbuf *referent) +{ + 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}; + int ret; + + ret = reftable_stack_reload(stack); + 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 = -1; + + reftable_ref_record_release(&ref); + return ret; +} + +/* + * Return the refname under which update was originally requested. + */ +static const char *original_update_refname(struct ref_update *update) +{ + while (update->parent_update) + update = update->parent_update; + return update->refname; +} + +struct reftable_transaction_update { + struct ref_update *update; + struct object_id current_oid; +}; + +struct write_transaction_table_arg { + struct reftable_ref_store *refs; + struct reftable_stack *stack; + struct reftable_addition *addition; + struct reftable_transaction_update *updates; + size_t updates_nr; + size_t updates_alloc; + size_t updates_expected; +}; + +struct reftable_transaction_data { + struct write_transaction_table_arg *args; + size_t args_nr, args_alloc; +}; + +static void free_transaction_data(struct reftable_transaction_data *tx_data) +{ + if (!tx_data) + return; + for (size_t i = 0; i < tx_data->args_nr; i++) { + reftable_addition_destroy(tx_data->args[i].addition); + free(tx_data->args[i].updates); + } + free(tx_data->args); + free(tx_data); +} + +/* + * Prepare transaction update for the given reference update. This will cause + * us to lock the corresponding reftable stack for concurrent modification. + */ +static int prepare_transaction_update(struct write_transaction_table_arg **out, + struct reftable_ref_store *refs, + struct reftable_transaction_data *tx_data, + struct ref_update *update, + struct strbuf *err) +{ + struct reftable_stack *stack = stack_for(refs, update->refname, NULL); + struct write_transaction_table_arg *arg = NULL; + size_t i; + int 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) + arg = &tx_data->args[i]; + + if (!arg) { + struct reftable_addition *addition; + + ret = reftable_stack_reload(stack); + if (ret) + return ret; + + ret = reftable_stack_new_addition(&addition, stack); + if (ret) { + if (ret == REFTABLE_LOCK_ERROR) + strbuf_addstr(err, "cannot lock references"); + return ret; + } + + ALLOC_GROW(tx_data->args, tx_data->args_nr + 1, + tx_data->args_alloc); + arg = &tx_data->args[tx_data->args_nr++]; + arg->refs = refs; + arg->stack = stack; + arg->addition = addition; + arg->updates = NULL; + arg->updates_nr = 0; + arg->updates_alloc = 0; + arg->updates_expected = 0; + } + + arg->updates_expected++; + + if (out) + *out = arg; + + return 0; +} + +/* + * Queue a reference update for the correct stack. We potentially need to + * handle multiple stack updates in a single transaction when it spans across + * multiple worktrees. + */ +static int queue_transaction_update(struct reftable_ref_store *refs, + struct reftable_transaction_data *tx_data, + struct ref_update *update, + struct object_id *current_oid, + struct strbuf *err) +{ + struct write_transaction_table_arg *arg = NULL; + int ret; + + if (update->backend_data) + BUG("reference update queued more than once"); + + ret = prepare_transaction_update(&arg, refs, tx_data, update, err); + if (ret < 0) + return ret; + + ALLOC_GROW(arg->updates, arg->updates_nr + 1, + arg->updates_alloc); + arg->updates[arg->updates_nr].update = update; + oidcpy(&arg->updates[arg->updates_nr].current_oid, current_oid); + update->backend_data = &arg->updates[arg->updates_nr++]; + + return 0; +} + +static int reftable_be_transaction_prepare(struct ref_store *ref_store, + struct ref_transaction *transaction, + struct strbuf *err) +{ + struct reftable_ref_store *refs = + reftable_be_downcast(ref_store, REF_STORE_WRITE|REF_STORE_MAIN, "ref_transaction_prepare"); + 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 object_id head_oid; + unsigned int head_type = 0; + size_t i; + int ret; + + ret = refs->err; + if (ret < 0) + goto done; + + tx_data = xcalloc(1, sizeof(*tx_data)); + + /* + * Preprocess all updates. For one we check that there are no duplicate + * reference updates in this transaction. Second, we lock all stacks + * that will be modified during the transaction. + */ + for (i = 0; i < transaction->nr; i++) { + ret = prepare_transaction_update(NULL, refs, tx_data, + transaction->updates[i], err); + if (ret) + goto done; + + string_list_append(&affected_refnames, + transaction->updates[i]->refname); + } + + /* + * Now that we have counted updates per stack we can preallocate their + * arrays. This avoids having to reallocate many times. + */ + for (i = 0; i < tx_data->args_nr; i++) { + CALLOC_ARRAY(tx_data->args[i].updates, tx_data->args[i].updates_expected); + tx_data->args[i].updates_alloc = tx_data->args[i].updates_expected; + } + + /* + * Fail if a refname appears more than once in the transaction. + * This code is taken from the files backend and is a good candidate to + * be moved into the generic layer. + */ + string_list_sort(&affected_refnames); + if (ref_update_reject_duplicates(&affected_refnames, err)) { + ret = TRANSACTION_GENERIC_ERROR; + goto done; + } + + ret = read_ref_without_reload(stack_for(refs, "HEAD", NULL), "HEAD", &head_oid, + &head_referent, &head_type); + if (ret < 0) + goto done; + ret = 0; + + 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); + + /* Verify that the new object ID is valid. */ + if ((u->flags & REF_HAVE_NEW) && !is_null_oid(&u->new_oid) && + !(u->flags & REF_SKIP_OID_VERIFICATION) && + !(u->flags & REF_LOG_ONLY)) { + struct object *o = parse_object(refs->base.repo, &u->new_oid); + if (!o) { + strbuf_addf(err, + _("trying to write ref '%s' with nonexistent object %s"), + u->refname, oid_to_hex(&u->new_oid)); + ret = -1; + goto done; + } + + if (o->type != OBJ_COMMIT && is_branch(u->refname)) { + strbuf_addf(err, _("trying to write non-commit object %s to branch '%s'"), + oid_to_hex(&u->new_oid), u->refname); + ret = -1; + goto done; + } + } + + /* + * When we update the reference that HEAD points to we enqueue + * a second log-only update for HEAD so that its reflog is + * updated accordingly. + */ + if (head_type == REF_ISSYMREF && + !(u->flags & REF_LOG_ONLY) && + !(u->flags & REF_UPDATE_VIA_HEAD) && + !strcmp(rewritten_ref, head_referent.buf)) { + struct ref_update *new_update; + + /* + * First make sure that HEAD is not already in the + * transaction. This check is O(lg N) in the transaction + * size, but it happens at most once per transaction. + */ + if (string_list_has_string(&affected_refnames, "HEAD")) { + /* An entry already existed */ + strbuf_addf(err, + _("multiple updates for 'HEAD' (including one " + "via its referent '%s') are not allowed"), + u->refname); + ret = TRANSACTION_NAME_CONFLICT; + goto done; + } + + new_update = ref_transaction_add_update( + transaction, "HEAD", + u->flags | REF_LOG_ONLY | REF_NO_DEREF, + &u->new_oid, &u->old_oid, u->msg); + string_list_insert(&affected_refnames, new_update->refname); + } + + ret = read_ref_without_reload(stack, rewritten_ref, + ¤t_oid, &referent, &u->type); + if (ret < 0) + goto done; + if (ret > 0 && (!(u->flags & REF_HAVE_OLD) || is_null_oid(&u->old_oid))) { + /* + * The reference does not exist, and we either have no + * old object ID or expect the reference to not exist. + * We can thus skip below safety checks as well as the + * symref splitting. But we do want to verify that + * there is no conflicting reference here so that we + * can output a proper error message instead of failing + * at a later point. + */ + ret = refs_verify_refname_available(ref_store, u->refname, + &affected_refnames, NULL, err); + if (ret < 0) + goto done; + + /* + * There is no need to write the reference deletion + * when the reference in question doesn't exist. + */ + if (u->flags & REF_HAVE_NEW && !is_null_oid(&u->new_oid)) { + ret = queue_transaction_update(refs, tx_data, u, + ¤t_oid, err); + if (ret) + goto done; + } + + continue; + } + if (ret > 0) { + /* The reference does not exist, but we expected it to. */ + strbuf_addf(err, _("cannot lock ref '%s': " + "unable to resolve reference '%s'"), + original_update_refname(u), u->refname); + ret = -1; + goto done; + } + + if (u->type & REF_ISSYMREF) { + /* + * The reftable stack is locked at this point already, + * so it is safe to call `refs_resolve_ref_unsafe()` + * here without causing races. + */ + const char *resolved = refs_resolve_ref_unsafe(&refs->base, u->refname, 0, + ¤t_oid, NULL); + + if (u->flags & REF_NO_DEREF) { + if (u->flags & REF_HAVE_OLD && !resolved) { + strbuf_addf(err, _("cannot lock ref '%s': " + "error reading reference"), u->refname); + ret = -1; + goto done; + } + } else { + struct ref_update *new_update; + int new_flags; + + new_flags = u->flags; + if (!strcmp(rewritten_ref, "HEAD")) + new_flags |= REF_UPDATE_VIA_HEAD; + + /* + * If we are updating a symref (eg. HEAD), we should also + * update the branch that the symref points to. + * + * This is generic functionality, and would be better + * done in refs.c, but the current implementation is + * intertwined with the locking in files-backend.c. + */ + new_update = ref_transaction_add_update( + transaction, referent.buf, new_flags, + &u->new_oid, &u->old_oid, u->msg); + new_update->parent_update = u; + + /* + * Change the symbolic ref update to log only. Also, it + * doesn't need to check its old OID value, as that will be + * done when new_update is processed. + */ + u->flags |= REF_LOG_ONLY | REF_NO_DEREF; + u->flags &= ~REF_HAVE_OLD; + + if (string_list_has_string(&affected_refnames, new_update->refname)) { + strbuf_addf(err, + _("multiple updates for '%s' (including one " + "via symref '%s') are not allowed"), + referent.buf, u->refname); + ret = TRANSACTION_NAME_CONFLICT; + goto done; + } + string_list_insert(&affected_refnames, new_update->refname); + } + } + + /* + * Verify that the old object matches our expectations. Note + * that the error messages here do not make a lot of sense in + * the context of the reftable backend as we never lock + * individual refs. But the error messages match what the files + * backend returns, which keeps our tests happy. + */ + if (u->flags & REF_HAVE_OLD && !oideq(¤t_oid, &u->old_oid)) { + if (is_null_oid(&u->old_oid)) + strbuf_addf(err, _("cannot lock ref '%s': " + "reference already exists"), + original_update_refname(u)); + else if (is_null_oid(¤t_oid)) + strbuf_addf(err, _("cannot lock ref '%s': " + "reference is missing but expected %s"), + original_update_refname(u), + oid_to_hex(&u->old_oid)); + else + strbuf_addf(err, _("cannot lock ref '%s': " + "is at %s but expected %s"), + original_update_refname(u), + oid_to_hex(¤t_oid), + oid_to_hex(&u->old_oid)); + ret = -1; + goto done; + } + + /* + * If all of the following conditions are true: + * + * - We're not about to write a symref. + * - We're not about to write a log-only entry. + * - Old and new object ID are different. + * + * Then we're essentially doing a no-op update that can be + * skipped. This is not only for the sake of efficiency, but + * also skips writing unneeded reflog entries. + */ + if ((u->type & REF_ISSYMREF) || + (u->flags & REF_LOG_ONLY) || + (u->flags & REF_HAVE_NEW && !oideq(¤t_oid, &u->new_oid))) { + ret = queue_transaction_update(refs, tx_data, u, + ¤t_oid, err); + if (ret) + goto done; + } + } + + transaction->backend_data = tx_data; + transaction->state = REF_TRANSACTION_PREPARED; + +done: + assert(ret != REFTABLE_API_ERROR); + if (ret < 0) { + free_transaction_data(tx_data); + transaction->state = REF_TRANSACTION_CLOSED; + if (!err->len) + strbuf_addf(err, _("reftable: transaction prepare: %s"), + reftable_error_str(ret)); + } + string_list_clear(&affected_refnames, 0); + strbuf_release(&referent); + strbuf_release(&head_referent); + + return ret; +} + +static int reftable_be_transaction_abort(struct ref_store *ref_store, + struct ref_transaction *transaction, + struct strbuf *err) +{ + struct reftable_transaction_data *tx_data = transaction->backend_data; + free_transaction_data(tx_data); + transaction->state = REF_TRANSACTION_CLOSED; + return 0; +} + +static int transaction_update_cmp(const void *a, const void *b) +{ + return strcmp(((struct reftable_transaction_update *)a)->update->refname, + ((struct reftable_transaction_update *)b)->update->refname); +} + +static int write_transaction_table(struct reftable_writer *writer, void *cb_data) +{ + struct write_transaction_table_arg *arg = cb_data; + struct reftable_merged_table *mt = + reftable_stack_merged_table(arg->stack); + uint64_t ts = reftable_stack_next_update_index(arg->stack); + struct reftable_log_record *logs = NULL; + size_t logs_nr = 0, logs_alloc = 0, i; + int ret = 0; + + QSORT(arg->updates, arg->updates_nr, transaction_update_cmp); + + reftable_writer_set_limits(writer, ts, ts); + + for (i = 0; i < arg->updates_nr; i++) { + struct reftable_transaction_update *tx_update = &arg->updates[i]; + struct ref_update *u = tx_update->update; + + /* + * Write a reflog entry when updating a ref to point to + * something new in either of the following cases: + * + * - The reference is about to be deleted. We always want to + * delete the reflog in that case. + * - REF_FORCE_CREATE_REFLOG is set, asking us to always create + * the reflog entry. + * - `core.logAllRefUpdates` tells us to create the reflog for + * the given ref. + */ + if (u->flags & REF_HAVE_NEW && !(u->type & REF_ISSYMREF) && is_null_oid(&u->new_oid)) { + struct reftable_log_record log = {0}; + struct reftable_iterator it = {0}; + + /* + * When deleting refs we also delete all reflog entries + * with them. While it is not strictly required to + * delete reflogs together with their refs, this + * matches the behaviour of the files backend. + * + * Unfortunately, we have no better way than to delete + * all reflog entries one by one. + */ + ret = reftable_merged_table_seek_log(mt, &it, u->refname); + while (ret == 0) { + struct reftable_log_record *tombstone; + + ret = reftable_iterator_next_log(&it, &log); + if (ret < 0) + break; + if (ret > 0 || strcmp(log.refname, u->refname)) { + ret = 0; + break; + } + + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + tombstone = &logs[logs_nr++]; + tombstone->refname = xstrdup(u->refname); + tombstone->value_type = REFTABLE_LOG_DELETION; + tombstone->update_index = log.update_index; + } + + reftable_log_record_release(&log); + reftable_iterator_destroy(&it); + + if (ret) + goto done; + } else if (u->flags & REF_HAVE_NEW && + (u->flags & REF_FORCE_CREATE_REFLOG || + should_write_log(&arg->refs->base, u->refname))) { + struct reftable_log_record *log; + + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + log = &logs[logs_nr++]; + memset(log, 0, sizeof(*log)); + + fill_reftable_log_record(log); + log->update_index = ts; + log->refname = xstrdup(u->refname); + memcpy(log->value.update.new_hash, u->new_oid.hash, GIT_MAX_RAWSZ); + memcpy(log->value.update.old_hash, tx_update->current_oid.hash, GIT_MAX_RAWSZ); + log->value.update.message = + xstrndup(u->msg, arg->refs->write_options.block_size / 2); + } + + if (u->flags & REF_LOG_ONLY) + continue; + + if (u->flags & REF_HAVE_NEW && is_null_oid(&u->new_oid)) { + struct reftable_ref_record ref = { + .refname = (char *)u->refname, + .update_index = ts, + .value_type = REFTABLE_REF_DELETION, + }; + + ret = reftable_writer_add_ref(writer, &ref); + if (ret < 0) + goto done; + } else if (u->flags & REF_HAVE_NEW) { + struct reftable_ref_record ref = {0}; + struct object_id peeled; + int peel_error; + + ref.refname = (char *)u->refname; + ref.update_index = ts; + + peel_error = peel_object(&u->new_oid, &peeled); + if (!peel_error) { + ref.value_type = REFTABLE_REF_VAL2; + memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ); + memcpy(ref.value.val2.value, u->new_oid.hash, GIT_MAX_RAWSZ); + } else if (!is_null_oid(&u->new_oid)) { + ref.value_type = REFTABLE_REF_VAL1; + memcpy(ref.value.val1, u->new_oid.hash, GIT_MAX_RAWSZ); + } + + ret = reftable_writer_add_ref(writer, &ref); + if (ret < 0) + goto done; + } + } + + /* + * Logs are written at the end so that we do not have intermixed ref + * and log blocks. + */ + if (logs) { + ret = reftable_writer_add_logs(writer, logs, logs_nr); + if (ret < 0) + goto done; + } + +done: + assert(ret != REFTABLE_API_ERROR); + for (i = 0; i < logs_nr; i++) + reftable_log_record_release(&logs[i]); + free(logs); + return ret; +} + +static int reftable_be_transaction_finish(struct ref_store *ref_store, + struct ref_transaction *transaction, + struct strbuf *err) +{ + struct reftable_transaction_data *tx_data = transaction->backend_data; + int ret = 0; + + for (size_t i = 0; i < tx_data->args_nr; i++) { + ret = reftable_addition_add(tx_data->args[i].addition, + write_transaction_table, &tx_data->args[i]); + if (ret < 0) + goto done; + + ret = reftable_addition_commit(tx_data->args[i].addition); + if (ret < 0) + goto done; + } + +done: + assert(ret != REFTABLE_API_ERROR); + free_transaction_data(tx_data); + transaction->state = REF_TRANSACTION_CLOSED; + + if (ret) { + strbuf_addf(err, _("reftable: transaction failure: %s"), + reftable_error_str(ret)); + return -1; + } + 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) +{ + struct reftable_ref_store *refs = + reftable_be_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB, "pack_refs"); + struct reftable_stack *stack; + int ret; + + if (refs->err) + return refs->err; + + stack = refs->worktree_stack; + if (!stack) + stack = refs->main_stack; + + if (opts->flags & PACK_REFS_AUTO) + ret = reftable_stack_auto_compact(stack); + else + ret = reftable_stack_compact_all(stack, NULL); + if (ret < 0) { + ret = error(_("unable to compact stack: %s"), + reftable_error_str(ret)); + goto out; + } + + ret = reftable_stack_clean(stack); + if (ret) + goto out; + +out: + return ret; +} + +struct write_create_symref_arg { + struct reftable_ref_store *refs; + struct reftable_stack *stack; + const char *refname; + const char *target; + const char *logmsg; +}; + +static int write_create_symref_table(struct reftable_writer *writer, void *cb_data) +{ + struct write_create_symref_arg *create = cb_data; + uint64_t ts = reftable_stack_next_update_index(create->stack); + struct reftable_ref_record ref = { + .refname = (char *)create->refname, + .value_type = REFTABLE_REF_SYMREF, + .value.symref = (char *)create->target, + .update_index = ts, + }; + struct reftable_log_record log = {0}; + struct object_id new_oid; + struct object_id old_oid; + int ret; + + reftable_writer_set_limits(writer, ts, ts); + + ret = reftable_writer_add_ref(writer, &ref); + if (ret) + return ret; + + /* + * Note that it is important to try and resolve the reference before we + * write the log entry. This is because `should_write_log()` will munge + * `core.logAllRefUpdates`, which is undesirable when we create a new + * repository because it would be written into the config. As HEAD will + * not resolve for new repositories this ordering will ensure that this + * never happens. + */ + if (!create->logmsg || + !refs_resolve_ref_unsafe(&create->refs->base, create->target, + RESOLVE_REF_READING, &new_oid, NULL) || + !should_write_log(&create->refs->base, create->refname)) + return 0; + + fill_reftable_log_record(&log); + log.refname = xstrdup(create->refname); + log.update_index = ts; + log.value.update.message = xstrndup(create->logmsg, + create->refs->write_options.block_size / 2); + memcpy(log.value.update.new_hash, new_oid.hash, GIT_MAX_RAWSZ); + if (refs_resolve_ref_unsafe(&create->refs->base, create->refname, + RESOLVE_REF_READING, &old_oid, NULL)) + memcpy(log.value.update.old_hash, old_oid.hash, GIT_MAX_RAWSZ); + + ret = reftable_writer_add_log(writer, &log); + reftable_log_record_release(&log); + return ret; +} + +static int reftable_be_create_symref(struct ref_store *ref_store, + const char *refname, + const char *target, + const char *logmsg) +{ + struct reftable_ref_store *refs = + reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_symref"); + struct reftable_stack *stack = stack_for(refs, refname, &refname); + struct write_create_symref_arg arg = { + .refs = refs, + .stack = stack, + .refname = refname, + .target = target, + .logmsg = logmsg, + }; + int ret; + + ret = refs->err; + if (ret < 0) + goto done; + + ret = reftable_stack_reload(stack); + if (ret) + goto done; + + ret = reftable_stack_add(stack, &write_create_symref_table, &arg); + +done: + assert(ret != REFTABLE_API_ERROR); + if (ret) + error("unable to write symref for %s: %s", refname, + reftable_error_str(ret)); + return ret; +} + +struct write_copy_arg { + struct reftable_ref_store *refs; + struct reftable_stack *stack; + const char *oldname; + const char *newname; + const char *logmsg; + int delete_old; +}; + +static int write_copy_table(struct reftable_writer *writer, void *cb_data) +{ + struct write_copy_arg *arg = cb_data; + uint64_t deletion_ts, creation_ts; + struct reftable_merged_table *mt = reftable_stack_merged_table(arg->stack); + struct reftable_ref_record old_ref = {0}, refs[2] = {0}; + struct reftable_log_record old_log = {0}, *logs = NULL; + struct reftable_iterator it = {0}; + struct string_list skip = STRING_LIST_INIT_NODUP; + struct strbuf errbuf = STRBUF_INIT; + size_t logs_nr = 0, logs_alloc = 0, i; + int ret; + + if (reftable_stack_read_ref(arg->stack, arg->oldname, &old_ref)) { + ret = error(_("refname %s not found"), arg->oldname); + goto done; + } + if (old_ref.value_type == REFTABLE_REF_SYMREF) { + ret = error(_("refname %s is a symbolic ref, copying it is not supported"), + arg->oldname); + goto done; + } + + /* + * There's nothing to do in case the old and new name are the same, so + * we exit early in that case. + */ + if (!strcmp(arg->oldname, arg->newname)) { + ret = 0; + goto done; + } + + /* + * Verify that the new refname is available. + */ + string_list_insert(&skip, arg->oldname); + ret = refs_verify_refname_available(&arg->refs->base, arg->newname, + NULL, &skip, &errbuf); + if (ret < 0) { + error("%s", errbuf.buf); + goto done; + } + + /* + * When deleting the old reference we have to use two update indices: + * once to delete the old ref and its reflog, and once to create the + * new ref and its reflog. They need to be staged with two separate + * indices because the new reflog needs to encode both the deletion of + * 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); + if (arg->delete_old) + creation_ts++; + reftable_writer_set_limits(writer, deletion_ts, creation_ts); + + /* + * Add the new reference. If this is a rename then we also delete the + * old reference. + */ + refs[0] = old_ref; + refs[0].refname = (char *)arg->newname; + refs[0].update_index = creation_ts; + if (arg->delete_old) { + refs[1].refname = (char *)arg->oldname; + refs[1].value_type = REFTABLE_REF_DELETION; + refs[1].update_index = deletion_ts; + } + ret = reftable_writer_add_refs(writer, refs, arg->delete_old ? 2 : 1); + if (ret < 0) + goto done; + + /* + * When deleting the old branch we need to create a reflog entry on the + * new branch name that indicates that the old branch has been deleted + * and then recreated. This is a tad weird, but matches what the files + * backend does. + */ + if (arg->delete_old) { + struct strbuf head_referent = STRBUF_INIT; + struct object_id head_oid; + int append_head_reflog; + unsigned head_type = 0; + + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + memset(&logs[logs_nr], 0, sizeof(logs[logs_nr])); + fill_reftable_log_record(&logs[logs_nr]); + logs[logs_nr].refname = (char *)arg->newname; + logs[logs_nr].update_index = deletion_ts; + logs[logs_nr].value.update.message = + xstrndup(arg->logmsg, arg->refs->write_options.block_size / 2); + 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); + if (ret < 0) + goto done; + append_head_reflog = (head_type & REF_ISSYMREF) && !strcmp(head_referent.buf, arg->oldname); + strbuf_release(&head_referent); + + /* + * The files backend uses `refs_delete_ref()` to delete the old + * branch name, which will append a reflog entry for HEAD in + * case it points to the old branch. + */ + if (append_head_reflog) { + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + logs[logs_nr] = logs[logs_nr - 1]; + logs[logs_nr].refname = "HEAD"; + logs_nr++; + } + } + + /* + * Create the reflog entry for the newly created branch. + */ + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + memset(&logs[logs_nr], 0, sizeof(logs[logs_nr])); + fill_reftable_log_record(&logs[logs_nr]); + logs[logs_nr].refname = (char *)arg->newname; + logs[logs_nr].update_index = creation_ts; + logs[logs_nr].value.update.message = + xstrndup(arg->logmsg, arg->refs->write_options.block_size / 2); + memcpy(logs[logs_nr].value.update.new_hash, old_ref.value.val1, GIT_MAX_RAWSZ); + logs_nr++; + + /* + * In addition to writing the reflog entry for the new branch, we also + * 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. + */ + ret = reftable_merged_table_seek_log(mt, &it, arg->oldname); + if (ret < 0) + goto done; + + while (1) { + ret = reftable_iterator_next_log(&it, &old_log); + if (ret < 0) + goto done; + if (ret > 0 || strcmp(old_log.refname, arg->oldname)) { + ret = 0; + break; + } + + free(old_log.refname); + + /* + * Copy over the old reflog entry with the new refname. + */ + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + logs[logs_nr] = old_log; + logs[logs_nr].refname = (char *)arg->newname; + logs_nr++; + + /* + * Delete the old reflog entry in case we are renaming. + */ + if (arg->delete_old) { + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + memset(&logs[logs_nr], 0, sizeof(logs[logs_nr])); + logs[logs_nr].refname = (char *)arg->oldname; + logs[logs_nr].value_type = REFTABLE_LOG_DELETION; + logs[logs_nr].update_index = old_log.update_index; + logs_nr++; + } + + /* + * Transfer ownership of the log record we're iterating over to + * the array of log records. Otherwise, the pointers would get + * free'd or reallocated by the iterator. + */ + memset(&old_log, 0, sizeof(old_log)); + } + + ret = reftable_writer_add_logs(writer, logs, logs_nr); + if (ret < 0) + goto done; + +done: + assert(ret != REFTABLE_API_ERROR); + reftable_iterator_destroy(&it); + string_list_clear(&skip, 0); + strbuf_release(&errbuf); + for (i = 0; i < logs_nr; i++) { + if (!strcmp(logs[i].refname, "HEAD")) + continue; + logs[i].refname = NULL; + reftable_log_record_release(&logs[i]); + } + free(logs); + reftable_ref_record_release(&old_ref); + reftable_log_record_release(&old_log); + return ret; +} + +static int reftable_be_rename_ref(struct ref_store *ref_store, + const char *oldrefname, + const char *newrefname, + const char *logmsg) +{ + 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, + .delete_old = 1, + }; + int ret; + + ret = refs->err; + if (ret < 0) + goto done; + + ret = reftable_stack_reload(stack); + if (ret) + goto done; + ret = reftable_stack_add(stack, &write_copy_table, &arg); + +done: + assert(ret != REFTABLE_API_ERROR); + return ret; +} + +static int reftable_be_copy_ref(struct ref_store *ref_store, + const char *oldrefname, + const char *newrefname, + const char *logmsg) +{ + 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, + }; + int ret; + + ret = refs->err; + if (ret < 0) + goto done; + + ret = reftable_stack_reload(stack); + if (ret) + goto done; + ret = reftable_stack_add(stack, &write_copy_table, &arg); + +done: + assert(ret != REFTABLE_API_ERROR); + return ret; +} + +struct reftable_reflog_iterator { + struct ref_iterator base; + struct reftable_ref_store *refs; + struct reftable_iterator iter; + struct reftable_log_record log; + struct strbuf last_name; + int err; +}; + +static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator) +{ + struct reftable_reflog_iterator *iter = + (struct reftable_reflog_iterator *)ref_iterator; + + while (!iter->err) { + iter->err = reftable_iterator_next_log(&iter->iter, &iter->log); + if (iter->err) + break; + + /* + * We want the refnames that we have reflogs for, so we skip if + * we've already produced this name. This could be faster by + * seeking directly to reflog@update_index==0. + */ + if (!strcmp(iter->log.refname, iter->last_name.buf)) + continue; + + if (check_refname_format(iter->log.refname, + REFNAME_ALLOW_ONELEVEL)) + continue; + + strbuf_reset(&iter->last_name); + strbuf_addstr(&iter->last_name, iter->log.refname); + iter->base.refname = iter->log.refname; + + break; + } + + if (iter->err > 0) { + if (ref_iterator_abort(ref_iterator) != ITER_DONE) + return ITER_ERROR; + return ITER_DONE; + } + + if (iter->err < 0) { + ref_iterator_abort(ref_iterator); + return ITER_ERROR; + } + + return ITER_OK; +} + +static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator, + struct object_id *peeled) +{ + BUG("reftable reflog iterator cannot be peeled"); + return -1; +} + +static int reftable_reflog_iterator_abort(struct ref_iterator *ref_iterator) +{ + struct reftable_reflog_iterator *iter = + (struct reftable_reflog_iterator *)ref_iterator; + reftable_log_record_release(&iter->log); + reftable_iterator_destroy(&iter->iter); + strbuf_release(&iter->last_name); + free(iter); + return ITER_DONE; +} + +static struct ref_iterator_vtable reftable_reflog_iterator_vtable = { + .advance = reftable_reflog_iterator_advance, + .peel = reftable_reflog_iterator_peel, + .abort = reftable_reflog_iterator_abort +}; + +static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs, + struct reftable_stack *stack) +{ + struct reftable_merged_table *merged_table; + struct reftable_reflog_iterator *iter; + int ret; + + iter = xcalloc(1, sizeof(*iter)); + base_ref_iterator_init(&iter->base, &reftable_reflog_iterator_vtable); + strbuf_init(&iter->last_name, 0); + iter->refs = refs; + + ret = refs->err; + if (ret) + goto done; + + ret = reftable_stack_reload(stack); + if (ret < 0) + goto done; + + merged_table = reftable_stack_merged_table(stack); + + ret = reftable_merged_table_seek_log(merged_table, &iter->iter, ""); + if (ret < 0) + goto done; + +done: + iter->err = ret; + return iter; +} + +static struct ref_iterator *reftable_be_reflog_iterator_begin(struct ref_store *ref_store) +{ + struct reftable_ref_store *refs = + 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) + return &main_iter->base; + + worktree_iter = reflog_iterator_for_stack(refs, refs->worktree_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, + 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); + oidread(&new_oid, log->value.update.new_hash); + + /* + * When both the old object ID and the new object ID are null + * then this is the reflog existence marker. The caller must + * not be aware of it. + */ + if (is_null_oid(&old_oid) && is_null_oid(&new_oid)) + return 0; + + full_committer = fmt_ident(log->value.update.name, log->value.update.email, + WANT_COMMITTER_IDENT, NULL, IDENT_NO_DATE); + return fn(&old_oid, &new_oid, full_committer, + log->value.update.time, log->value.update.tz_offset, + log->value.update.message, cb_data); +} + +static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store, + const char *refname, + each_reflog_ent_fn fn, + void *cb_data) +{ + 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_merged_table *mt = NULL; + struct reftable_log_record log = {0}; + struct reftable_iterator it = {0}; + int ret; + + if (refs->err < 0) + return refs->err; + + mt = reftable_stack_merged_table(stack); + ret = reftable_merged_table_seek_log(mt, &it, refname); + while (!ret) { + ret = reftable_iterator_next_log(&it, &log); + if (ret < 0) + break; + if (ret > 0 || strcmp(log.refname, refname)) { + ret = 0; + break; + } + + ret = yield_log_record(&log, fn, cb_data); + if (ret) + break; + } + + reftable_log_record_release(&log); + reftable_iterator_destroy(&it); + return ret; +} + +static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store, + const char *refname, + each_reflog_ent_fn fn, + void *cb_data) +{ + 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_merged_table *mt = NULL; + struct reftable_log_record *logs = NULL; + struct reftable_iterator it = {0}; + size_t logs_alloc = 0, logs_nr = 0, i; + int ret; + + if (refs->err < 0) + return refs->err; + + mt = reftable_stack_merged_table(stack); + ret = reftable_merged_table_seek_log(mt, &it, refname); + while (!ret) { + struct reftable_log_record log = {0}; + + ret = reftable_iterator_next_log(&it, &log); + if (ret < 0) + goto done; + if (ret > 0 || strcmp(log.refname, refname)) { + reftable_log_record_release(&log); + ret = 0; + break; + } + + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + logs[logs_nr++] = log; + } + + for (i = logs_nr; i--;) { + ret = yield_log_record(&logs[i], fn, cb_data); + if (ret) + goto done; + } + +done: + reftable_iterator_destroy(&it); + for (i = 0; i < logs_nr; i++) + reftable_log_record_release(&logs[i]); + free(logs); + return ret; +} + +static int reftable_be_reflog_exists(struct ref_store *ref_store, + const char *refname) +{ + 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_merged_table *mt = reftable_stack_merged_table(stack); + struct reftable_log_record log = {0}; + struct reftable_iterator it = {0}; + int ret; + + ret = refs->err; + if (ret < 0) + goto done; + + ret = reftable_stack_reload(stack); + if (ret < 0) + goto done; + + ret = reftable_merged_table_seek_log(mt, &it, refname); + if (ret < 0) + goto done; + + /* + * Check whether we get at least one log record for the given ref name. + * If so, the reflog exists, otherwise it doesn't. + */ + ret = reftable_iterator_next_log(&it, &log); + if (ret < 0) + goto done; + if (ret > 0) { + ret = 0; + goto done; + } + + ret = strcmp(log.refname, refname) == 0; + +done: + reftable_iterator_destroy(&it); + reftable_log_record_release(&log); + if (ret < 0) + ret = 0; + return ret; +} + +struct write_reflog_existence_arg { + struct reftable_ref_store *refs; + const char *refname; + struct reftable_stack *stack; +}; + +static int write_reflog_existence_table(struct reftable_writer *writer, + void *cb_data) +{ + struct write_reflog_existence_arg *arg = cb_data; + uint64_t ts = reftable_stack_next_update_index(arg->stack); + struct reftable_log_record log = {0}; + int ret; + + ret = reftable_stack_read_log(arg->stack, arg->refname, &log); + if (ret <= 0) + goto done; + + reftable_writer_set_limits(writer, ts, ts); + + /* + * The existence entry has both old and new object ID set to the the + * null object ID. Our iterators are aware of this and will not present + * them to their callers. + */ + log.refname = xstrdup(arg->refname); + log.update_index = ts; + log.value_type = REFTABLE_LOG_UPDATE; + ret = reftable_writer_add_log(writer, &log); + +done: + assert(ret != REFTABLE_API_ERROR); + reftable_log_record_release(&log); + return ret; +} + +static int reftable_be_create_reflog(struct ref_store *ref_store, + const char *refname, + struct strbuf *errmsg) +{ + 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 write_reflog_existence_arg arg = { + .refs = refs, + .stack = stack, + .refname = refname, + }; + int ret; + + ret = refs->err; + if (ret < 0) + goto done; + + ret = reftable_stack_reload(stack); + if (ret) + goto done; + + ret = reftable_stack_add(stack, &write_reflog_existence_table, &arg); + +done: + return ret; +} + +struct write_reflog_delete_arg { + struct reftable_stack *stack; + const char *refname; +}; + +static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_data) +{ + struct write_reflog_delete_arg *arg = cb_data; + struct reftable_merged_table *mt = + reftable_stack_merged_table(arg->stack); + struct reftable_log_record log = {0}, tombstone = {0}; + struct reftable_iterator it = {0}; + uint64_t ts = reftable_stack_next_update_index(arg->stack); + int ret; + + reftable_writer_set_limits(writer, ts, ts); + + /* + * In order to delete a table we need to delete all reflog entries one + * by one. This is inefficient, but the reftable format does not have a + * better marker right now. + */ + ret = reftable_merged_table_seek_log(mt, &it, arg->refname); + while (ret == 0) { + ret = reftable_iterator_next_log(&it, &log); + if (ret < 0) + break; + if (ret > 0 || strcmp(log.refname, arg->refname)) { + ret = 0; + break; + } + + tombstone.refname = (char *)arg->refname; + tombstone.value_type = REFTABLE_LOG_DELETION; + tombstone.update_index = log.update_index; + + ret = reftable_writer_add_log(writer, &tombstone); + } + + reftable_log_record_release(&log); + reftable_iterator_destroy(&it); + return ret; +} + +static int reftable_be_delete_reflog(struct ref_store *ref_store, + const char *refname) +{ + 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 write_reflog_delete_arg arg = { + .stack = stack, + .refname = refname, + }; + int ret; + + ret = reftable_stack_reload(stack); + if (ret) + return ret; + ret = reftable_stack_add(stack, &write_reflog_delete_table, &arg); + + assert(ret != REFTABLE_API_ERROR); + return ret; +} + +struct reflog_expiry_arg { + struct reftable_stack *stack; + struct reftable_log_record *records; + struct object_id update_oid; + const char *refname; + size_t len; +}; + +static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_data) +{ + struct reflog_expiry_arg *arg = cb_data; + uint64_t ts = reftable_stack_next_update_index(arg->stack); + uint64_t live_records = 0; + size_t i; + int ret; + + for (i = 0; i < arg->len; i++) + if (arg->records[i].value_type == REFTABLE_LOG_UPDATE) + live_records++; + + reftable_writer_set_limits(writer, ts, ts); + + if (!is_null_oid(&arg->update_oid)) { + struct reftable_ref_record ref = {0}; + struct object_id peeled; + + ref.refname = (char *)arg->refname; + ref.update_index = ts; + + if (!peel_object(&arg->update_oid, &peeled)) { + ref.value_type = REFTABLE_REF_VAL2; + memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ); + memcpy(ref.value.val2.value, arg->update_oid.hash, GIT_MAX_RAWSZ); + } else { + ref.value_type = REFTABLE_REF_VAL1; + memcpy(ref.value.val1, arg->update_oid.hash, GIT_MAX_RAWSZ); + } + + ret = reftable_writer_add_ref(writer, &ref); + if (ret < 0) + return ret; + } + + /* + * When there are no more entries left in the reflog we empty it + * completely, but write a placeholder reflog entry that indicates that + * the reflog still exists. + */ + if (!live_records) { + struct reftable_log_record log = { + .refname = (char *)arg->refname, + .value_type = REFTABLE_LOG_UPDATE, + .update_index = ts, + }; + + ret = reftable_writer_add_log(writer, &log); + if (ret) + return ret; + } + + for (i = 0; i < arg->len; i++) { + ret = reftable_writer_add_log(writer, &arg->records[i]); + if (ret) + return ret; + } + + return 0; +} + +static int reftable_be_reflog_expire(struct ref_store *ref_store, + 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) +{ + /* + * For log expiry, we write tombstones for every single reflog entry + * that is to be expired. This means that the entries are still + * retrievable by delving into the stack, and expiring entries + * paradoxically takes extra memory. This memory is only reclaimed when + * compacting the reftable stack. + * + * It would be better if the refs backend supported an API that sets a + * criterion for all refs, passing the criterion to pack_refs(). + * + * On the plus side, because we do the expiration per ref, we can easily + * insert the reflog existence dummies. + */ + 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_merged_table *mt = reftable_stack_merged_table(stack); + 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 object_id oid = {0}; + uint8_t *last_hash = NULL; + size_t logs_nr = 0, logs_alloc = 0, i; + int ret; + + if (refs->err < 0) + return refs->err; + + ret = reftable_stack_reload(stack); + if (ret < 0) + goto done; + + ret = reftable_merged_table_seek_log(mt, &it, refname); + if (ret < 0) + goto done; + + ret = reftable_stack_new_addition(&add, stack); + if (ret < 0) + goto done; + + ret = reftable_stack_read_ref(stack, refname, &ref_record); + if (ret < 0) + goto done; + if (reftable_ref_record_val1(&ref_record)) + oidread(&oid, reftable_ref_record_val1(&ref_record)); + prepare_fn(refname, &oid, policy_cb_data); + + while (1) { + struct reftable_log_record log = {0}; + struct object_id old_oid, new_oid; + + ret = reftable_iterator_next_log(&it, &log); + if (ret < 0) + goto done; + if (ret > 0 || strcmp(log.refname, refname)) { + reftable_log_record_release(&log); + break; + } + + oidread(&old_oid, log.value.update.old_hash); + oidread(&new_oid, log.value.update.new_hash); + + /* + * Skip over the reflog existence marker. We will add it back + * in when there are no live reflog records. + */ + if (is_null_oid(&old_oid) && is_null_oid(&new_oid)) { + reftable_log_record_release(&log); + continue; + } + + ALLOC_GROW(logs, logs_nr + 1, logs_alloc); + logs[logs_nr++] = log; + } + + /* + * We need to rewrite all reflog entries according to the pruning + * callback function: + * + * - If a reflog entry shall be pruned we mark the record for + * deletion. + * + * - Otherwise we may have to rewrite the chain of reflog entries so + * that gaps created by just-deleted records get backfilled. + */ + CALLOC_ARRAY(rewritten, logs_nr); + for (i = logs_nr; i--;) { + struct reftable_log_record *dest = &rewritten[i]; + struct object_id old_oid, new_oid; + + *dest = logs[i]; + oidread(&old_oid, logs[i].value.update.old_hash); + oidread(&new_oid, logs[i].value.update.new_hash); + + if (should_prune_fn(&old_oid, &new_oid, logs[i].value.update.email, + (timestamp_t)logs[i].value.update.time, + logs[i].value.update.tz_offset, + logs[i].value.update.message, + policy_cb_data)) { + dest->value_type = REFTABLE_LOG_DELETION; + } else { + if ((flags & EXPIRE_REFLOGS_REWRITE) && last_hash) + memcpy(dest->value.update.old_hash, last_hash, GIT_MAX_RAWSZ); + last_hash = logs[i].value.update.new_hash; + } + } + + if (flags & EXPIRE_REFLOGS_UPDATE_REF && last_hash && + reftable_ref_record_val1(&ref_record)) + oidread(&arg.update_oid, last_hash); + + arg.records = rewritten; + arg.len = logs_nr; + arg.stack = stack, + arg.refname = refname, + + ret = reftable_addition_add(add, &write_reflog_expiry_table, &arg); + if (ret < 0) + goto done; + + /* + * Future improvement: we could skip writing records that were + * not changed. + */ + if (!(flags & EXPIRE_REFLOGS_DRY_RUN)) + ret = reftable_addition_commit(add); + +done: + if (add) + 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]); + free(logs); + free(rewritten); + return ret; +} + +struct ref_storage_be refs_be_reftable = { + .name = "reftable", + .init = reftable_be_init, + .init_db = reftable_be_init_db, + .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, + .create_symref = reftable_be_create_symref, + .rename_ref = reftable_be_rename_ref, + .copy_ref = reftable_be_copy_ref, + + .iterator_begin = reftable_be_iterator_begin, + .read_raw_ref = reftable_be_read_raw_ref, + .read_symbolic_ref = reftable_be_read_symbolic_ref, + + .reflog_iterator_begin = reftable_be_reflog_iterator_begin, + .for_each_reflog_ent = reftable_be_for_each_reflog_ent, + .for_each_reflog_ent_reverse = reftable_be_for_each_reflog_ent_reverse, + .reflog_exists = reftable_be_reflog_exists, + .create_reflog = reftable_be_create_reflog, + .delete_reflog = reftable_be_delete_reflog, + .reflog_expire = reftable_be_reflog_expire, +}; diff --git a/reftable/basics.c b/reftable/basics.c index 0785aff941..fea711db7e 100644 --- a/reftable/basics.c +++ b/reftable/basics.c @@ -27,7 +27,7 @@ void put_be16(uint8_t *out, uint16_t i) out[1] = (uint8_t)(i & 0xff); } -int binsearch(size_t sz, int (*f)(size_t k, void *args), void *args) +size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args) { size_t lo = 0; size_t hi = sz; @@ -39,8 +39,11 @@ int binsearch(size_t sz, int (*f)(size_t k, void *args), void *args) */ while (hi - lo > 1) { size_t mid = lo + (hi - lo) / 2; + int ret = f(mid, args); + if (ret < 0) + return sz; - if (f(mid, args)) + if (ret > 0) hi = mid; else lo = mid; diff --git a/reftable/basics.h b/reftable/basics.h index 91f3533efe..523ecd5307 100644 --- a/reftable/basics.h +++ b/reftable/basics.h @@ -22,13 +22,14 @@ uint32_t get_be24(uint8_t *in); void put_be16(uint8_t *out, uint16_t i); /* - * find smallest index i in [0, sz) at which f(i) is true, assuming - * that f is ascending. Return sz if f(i) is false for all indices. + * find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is + * ascending. Return sz if `f(i) == 0` for all indices. The search is aborted + * and `sz` is returned in case `f(i) < 0`. * * Contrary to bsearch(3), this returns something useful if the argument is not * found. */ -int binsearch(size_t sz, int (*f)(size_t k, void *args), void *args); +size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args); /* * Frees a NULL terminated array of malloced strings. The array itself is also diff --git a/reftable/basics_test.c b/reftable/basics_test.c index 1fcd229725..997c4d9e01 100644 --- a/reftable/basics_test.c +++ b/reftable/basics_test.c @@ -12,40 +12,47 @@ https://developers.google.com/open-source/licenses/bsd #include "test_framework.h" #include "reftable-tests.h" -struct binsearch_args { - int key; - int *arr; +struct integer_needle_lesseq_args { + int needle; + int *haystack; }; -static int binsearch_func(size_t i, void *void_args) +static int integer_needle_lesseq(size_t i, void *_args) { - struct binsearch_args *args = void_args; - - return args->key < args->arr[i]; + struct integer_needle_lesseq_args *args = _args; + return args->needle <= args->haystack[i]; } static void test_binsearch(void) { - int arr[] = { 2, 4, 6, 8, 10 }; - size_t sz = ARRAY_SIZE(arr); - struct binsearch_args args = { - .arr = arr, + 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 i = 0; - int i = 0; - for (i = 1; i < 11; i++) { - int res; - args.key = i; - res = binsearch(sz, &binsearch_func, &args); + for (i = 0; i < ARRAY_SIZE(testcases); i++) { + struct integer_needle_lesseq_args args = { + .haystack = haystack, + .needle = testcases[i].needle, + }; + size_t idx; - if (res < sz) { - EXPECT(args.key < arr[res]); - if (res > 0) { - EXPECT(args.key >= arr[res - 1]); - } - } else { - EXPECT(args.key == 10 || args.key == 11); - } + idx = binsearch(ARRAY_SIZE(haystack), &integer_needle_lesseq, &args); + EXPECT(idx == testcases[i].expected_idx); } } diff --git a/reftable/block.c b/reftable/block.c index ce8a7d24f3..3e87460cba 100644 --- a/reftable/block.c +++ b/reftable/block.c @@ -175,11 +175,6 @@ int block_writer_finish(struct block_writer *w) return w->next; } -uint8_t block_reader_type(struct block_reader *r) -{ - return r->block.data[r->header_off]; -} - int block_reader_init(struct block_reader *br, struct reftable_block *block, uint32_t header_off, uint32_t table_block_size, int hash_size) @@ -191,7 +186,8 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, uint16_t restart_count = 0; uint32_t restart_start = 0; uint8_t *restart_bytes = NULL; - uint8_t *uncompressed = NULL; + + reftable_block_done(&br->block); if (!reftable_is_block_type(typ)) { err = REFTABLE_FORMAT_ERROR; @@ -199,37 +195,57 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, } if (typ == BLOCK_TYPE_LOG) { - int block_header_skip = 4 + header_off; - uLongf dst_len = sz - block_header_skip; /* total size of dest - buffer. */ - uLongf src_len = block->len - block_header_skip; + uint32_t block_header_skip = 4 + header_off; + uLong dst_len = sz - block_header_skip; + uLong src_len = block->len - block_header_skip; /* Log blocks specify the *uncompressed* size in their header. */ - REFTABLE_ALLOC_ARRAY(uncompressed, sz); + REFTABLE_ALLOC_GROW(br->uncompressed_data, sz, + br->uncompressed_cap); /* Copy over the block header verbatim. It's not compressed. */ - memcpy(uncompressed, block->data, block_header_skip); + memcpy(br->uncompressed_data, block->data, block_header_skip); - /* Uncompress */ - if (Z_OK != - uncompress2(uncompressed + block_header_skip, &dst_len, - block->data + block_header_skip, &src_len)) { + if (!br->zstream) { + REFTABLE_CALLOC_ARRAY(br->zstream, 1); + err = inflateInit(br->zstream); + } else { + err = inflateReset(br->zstream); + } + if (err != Z_OK) { err = REFTABLE_ZLIB_ERROR; goto done; } - if (dst_len + block_header_skip != sz) { + br->zstream->next_in = block->data + block_header_skip; + br->zstream->avail_in = src_len; + br->zstream->next_out = br->uncompressed_data + block_header_skip; + br->zstream->avail_out = dst_len; + + /* + * We know both input as well as output size, and we know that + * the sizes should never be bigger than `uInt_MAX` because + * blocks can at most be 16MB large. We can thus use `Z_FINISH` + * here to instruct zlib to inflate the data in one go, which + * is more efficient than using `Z_NO_FLUSH`. + */ + err = inflate(br->zstream, Z_FINISH); + if (err != Z_STREAM_END) { + err = REFTABLE_ZLIB_ERROR; + goto done; + } + err = 0; + + if (br->zstream->total_out + block_header_skip != sz) { err = REFTABLE_FORMAT_ERROR; goto done; } /* We're done with the input data. */ reftable_block_done(block); - block->data = uncompressed; - uncompressed = NULL; + block->data = br->uncompressed_data; block->len = sz; - block->source = malloc_block_source(); - full_block_size = src_len + block_header_skip; + full_block_size = src_len + block_header_skip - br->zstream->avail_in; } else if (full_block_size == 0) { full_block_size = sz; } else if (sz < full_block_size && sz < block->len && @@ -257,171 +273,242 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, br->restart_bytes = restart_bytes; done: - reftable_free(uncompressed); return err; } -static uint32_t block_reader_restart_offset(struct block_reader *br, int i) +void block_reader_release(struct block_reader *br) +{ + inflateEnd(br->zstream); + reftable_free(br->zstream); + reftable_free(br->uncompressed_data); + reftable_block_done(&br->block); +} + +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 off = br->header_off + 4, n; + struct string_view in = { + .buf = br->block.data + off, + .len = br->block_len - off, + }; + uint8_t extra = 0; + + strbuf_reset(key); + + n = reftable_decode_key(key, &extra, in); + if (n < 0) + return n; + if (!key->len) + return REFTABLE_FORMAT_ERROR; + + return 0; +} + +static uint32_t block_reader_restart_offset(const struct block_reader *br, int i) { return get_be24(br->restart_bytes + 3 * i); } -void block_reader_start(struct block_reader *br, struct block_iter *it) +void block_iter_seek_start(struct block_iter *it, const struct block_reader *br) { - it->br = br; + it->block = br->block.data; + it->block_len = br->block_len; + it->hash_size = br->hash_size; strbuf_reset(&it->last_key); it->next_off = br->header_off + 4; } -struct restart_find_args { +struct restart_needle_less_args { int error; - struct strbuf key; - struct block_reader *r; + struct strbuf needle; + const struct block_reader *reader; }; -static int restart_key_less(size_t idx, void *args) +static int restart_needle_less(size_t idx, void *_args) { - struct restart_find_args *a = args; - uint32_t off = block_reader_restart_offset(a->r, idx); + struct restart_needle_less_args *args = _args; + uint32_t off = block_reader_restart_offset(args->reader, idx); struct string_view in = { - .buf = a->r->block.data + off, - .len = a->r->block_len - off, + .buf = args->reader->block.data + off, + .len = args->reader->block_len - off, }; - - /* the restart key is verbatim in the block, so this could avoid the - alloc for decoding the key */ - struct strbuf rkey = STRBUF_INIT; - struct strbuf last_key = STRBUF_INIT; - uint8_t unused_extra; - int n = reftable_decode_key(&rkey, &unused_extra, last_key, in); - int result; - if (n < 0) { - a->error = 1; + uint64_t prefix_len, suffix_len; + uint8_t extra; + int n; + + /* + * Records at restart points are stored without prefix compression, so + * there is no need to fully decode the record key here. This removes + * the need for allocating memory. + */ + n = reftable_decode_keylen(in, &prefix_len, &suffix_len, &extra); + if (n < 0 || prefix_len) { + args->error = 1; return -1; } - result = strbuf_cmp(&a->key, &rkey); - strbuf_release(&rkey); - return result; -} + string_view_consume(&in, n); + if (suffix_len > in.len) { + args->error = 1; + return -1; + } -void block_iter_copy_from(struct block_iter *dest, struct block_iter *src) -{ - dest->br = src->br; - dest->next_off = src->next_off; - strbuf_reset(&dest->last_key); - strbuf_addbuf(&dest->last_key, &src->last_key); + n = memcmp(args->needle.buf, in.buf, + args->needle.len < suffix_len ? args->needle.len : suffix_len); + if (n) + return n < 0; + return args->needle.len < suffix_len; } int block_iter_next(struct block_iter *it, struct reftable_record *rec) { struct string_view in = { - .buf = it->br->block.data + it->next_off, - .len = it->br->block_len - it->next_off, + .buf = (unsigned char *) it->block + it->next_off, + .len = it->block_len - it->next_off, }; struct string_view start = in; uint8_t extra = 0; int n = 0; - if (it->next_off >= it->br->block_len) + if (it->next_off >= it->block_len) return 1; - n = reftable_decode_key(&it->key, &extra, it->last_key, in); + n = reftable_decode_key(&it->last_key, &extra, in); if (n < 0) return -1; - - if (!it->key.len) + if (!it->last_key.len) return REFTABLE_FORMAT_ERROR; string_view_consume(&in, n); - n = reftable_record_decode(rec, it->key, extra, in, it->br->hash_size); + n = reftable_record_decode(rec, it->last_key, extra, in, it->hash_size, + &it->scratch); if (n < 0) return -1; string_view_consume(&in, n); - strbuf_reset(&it->last_key); - strbuf_addbuf(&it->last_key, &it->key); it->next_off += start.len - in.len; return 0; } -int block_reader_first_key(struct block_reader *br, struct strbuf *key) -{ - struct strbuf empty = STRBUF_INIT; - int off = br->header_off + 4; - struct string_view in = { - .buf = br->block.data + off, - .len = br->block_len - off, - }; - - uint8_t extra = 0; - int n = reftable_decode_key(key, &extra, empty, in); - if (n < 0) - return n; - if (!key->len) - return REFTABLE_FORMAT_ERROR; - - return 0; -} - -int block_iter_seek(struct block_iter *it, struct strbuf *want) +void block_iter_reset(struct block_iter *it) { - return block_reader_seek(it->br, it, want); + strbuf_reset(&it->last_key); + it->next_off = 0; + it->block = NULL; + it->block_len = 0; + it->hash_size = 0; } void block_iter_close(struct block_iter *it) { strbuf_release(&it->last_key); - strbuf_release(&it->key); + strbuf_release(&it->scratch); } -int block_reader_seek(struct block_reader *br, struct block_iter *it, - struct strbuf *want) +int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, + struct strbuf *want) { - struct restart_find_args args = { - .key = *want, - .r = br, + struct restart_needle_less_args args = { + .needle = *want, + .reader = br, }; - struct block_iter next = BLOCK_ITER_INIT; struct reftable_record rec; - int err = 0, i; - + int err = 0; + size_t i; + + /* + * Perform a binary search over the block's restart points, which + * avoids doing a linear scan over the whole block. Like this, we + * identify the section of the block that should contain our key. + * + * Note that we explicitly search for the first restart point _greater_ + * than the sought-after record, not _greater or equal_ to it. In case + * the sought-after record is located directly at the restart point we + * would otherwise start doing the linear search at the preceding + * restart point. While that works alright, we would end up scanning + * too many record. + */ + i = binsearch(br->restart_count, &restart_needle_less, &args); if (args.error) { err = REFTABLE_FORMAT_ERROR; goto done; } - i = binsearch(br->restart_count, &restart_key_less, &args); + /* + * Now there are multiple cases: + * + * - `i == 0`: The wanted record is smaller than the record found at + * the first restart point. As the first restart point is the first + * record in the block, our wanted record cannot be located in this + * block at all. We still need to position the iterator so that the + * next call to `block_iter_next()` will yield an end-of-iterator + * signal. + * + * - `i == restart_count`: The wanted record was not found at any of + * the restart points. As there is no restart point at the end of + * the section the record may thus be contained in the last block. + * + * - `i > 0`: The wanted record must be contained in the section + * before the found restart point. We thus do a linear search + * starting from the preceding restart point. + */ if (i > 0) it->next_off = block_reader_restart_offset(br, i - 1); else it->next_off = br->header_off + 4; - it->br = br; + it->block = br->block.data; + it->block_len = br->block_len; + it->hash_size = br->hash_size; reftable_record_init(&rec, block_reader_type(br)); - /* We're looking for the last entry less/equal than the wanted key, so - we have to go one entry too far and then back up. - */ + /* + * We're looking for the last entry less than the wanted key so that + * the next call to `block_reader_next()` would yield the wanted + * record. We thus don't want to position our reader at the sought + * after record, but one before. To do so, we have to go one entry too + * far and then back up. + */ while (1) { - block_iter_copy_from(&next, it); - err = block_iter_next(&next, &rec); + size_t prev_off = it->next_off; + + err = block_iter_next(it, &rec); if (err < 0) goto done; - - reftable_record_key(&rec, &it->key); - if (err > 0 || strbuf_cmp(&it->key, want) >= 0) { + if (err > 0) { + it->next_off = prev_off; err = 0; goto done; } - block_iter_copy_from(it, &next); + /* + * Check whether the current key is greater or equal to the + * sought-after key. In case it is greater we know that the + * record does not exist in the block and can thus abort early. + * In case it is equal to the sought-after key we have found + * the desired record. + * + * Note that we store the next record's key record directly in + * `last_key` without restoring the key of the preceding record + * in case we need to go one record back. This is safe to do as + * `block_iter_next()` would return the ref whose key is equal + * 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) { + it->next_off = prev_off; + goto done; + } } done: - block_iter_close(&next); reftable_record_release(&rec); - return err; } diff --git a/reftable/block.h b/reftable/block.h index 17481e6331..ea4384a7e2 100644 --- a/reftable/block.h +++ b/reftable/block.h @@ -56,6 +56,8 @@ int block_writer_finish(struct block_writer *w); /* clears out internally allocated block_writer members. */ void block_writer_release(struct block_writer *bw); +struct z_stream; + /* Read a block. */ struct block_reader { /* offset of the block header; nonzero for the first block in a @@ -66,6 +68,11 @@ struct block_reader { struct reftable_block block; int hash_size; + /* Uncompressed data for log entries. */ + z_stream *zstream; + unsigned char *uncompressed_data; + size_t uncompressed_cap; + /* size of the data, excluding restart data. */ uint32_t block_len; uint8_t *restart_bytes; @@ -76,47 +83,49 @@ struct block_reader { uint32_t full_block_size; }; +/* initializes a block reader. */ +int block_reader_init(struct block_reader *br, struct reftable_block *bl, + uint32_t header_off, uint32_t table_block_size, + int hash_size); + +void block_reader_release(struct block_reader *br); + +/* Returns the block type (eg. 'r' for refs) */ +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); + /* Iterate over entries in a block */ struct block_iter { /* offset within the block of the next entry to read. */ uint32_t next_off; - struct block_reader *br; + const unsigned char *block; + size_t block_len; + int hash_size; /* key for last entry we read. */ struct strbuf last_key; - struct strbuf key; + struct strbuf scratch; }; #define BLOCK_ITER_INIT { \ .last_key = STRBUF_INIT, \ - .key = STRBUF_INIT, \ + .scratch = STRBUF_INIT, \ } -/* initializes a block reader. */ -int block_reader_init(struct block_reader *br, struct reftable_block *bl, - uint32_t header_off, uint32_t table_block_size, - int hash_size); - /* Position `it` at start of the block */ -void block_reader_start(struct block_reader *br, struct block_iter *it); +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_reader_seek(struct block_reader *br, struct block_iter *it, - struct strbuf *want); - -/* Returns the block type (eg. 'r' for refs) */ -uint8_t block_reader_type(struct block_reader *r); - -/* Decodes the first key in the block */ -int block_reader_first_key(struct block_reader *br, struct strbuf *key); - -void block_iter_copy_from(struct block_iter *dest, struct block_iter *src); +int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, + struct strbuf *want); /* return < 0 for error, 0 for OK, > 0 for EOF. */ int block_iter_next(struct block_iter *it, struct reftable_record *rec); -/* Seek to `want` with in the block pointed to by `it` */ -int block_iter_seek(struct block_iter *it, struct strbuf *want); +/* Reset the block iterator to pristine state without releasing its memory. */ +void block_iter_reset(struct block_iter *it); /* deallocate memory for `it`. The block reader and its block is left intact. */ void block_iter_close(struct block_iter *it); diff --git a/reftable/block_test.c b/reftable/block_test.c index e162c6e33f..26a9cfbc83 100644 --- a/reftable/block_test.c +++ b/reftable/block_test.c @@ -69,7 +69,7 @@ static void test_block_read_write(void) block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); - block_reader_start(&br, &it); + block_iter_seek_start(&it, &br); while (1) { int r = block_iter_next(&it, &rec); @@ -89,7 +89,7 @@ static void test_block_read_write(void) strbuf_reset(&want); strbuf_addstr(&want, names[i]); - n = block_reader_seek(&br, &it, &want); + n = block_iter_seek_key(&it, &br, &want); EXPECT(n == 0); n = block_iter_next(&it, &rec); @@ -98,7 +98,7 @@ static void test_block_read_write(void) EXPECT_STREQ(names[i], rec.u.ref.refname); want.len--; - n = block_reader_seek(&br, &it, &want); + n = block_iter_seek_key(&it, &br, &want); EXPECT(n == 0); n = block_iter_next(&it, &rec); diff --git a/reftable/error.c b/reftable/error.c index 0d1766735e..cfb7a0fda4 100644 --- a/reftable/error.c +++ b/reftable/error.c @@ -22,7 +22,7 @@ const char *reftable_error_str(int err) case REFTABLE_NOT_EXIST_ERROR: return "file does not exist"; case REFTABLE_LOCK_ERROR: - return "data is outdated"; + return "data is locked"; case REFTABLE_API_ERROR: return "misuse of the reftable API"; case REFTABLE_ZLIB_ERROR: @@ -35,6 +35,8 @@ const char *reftable_error_str(int err) return "invalid refname"; case REFTABLE_ENTRY_TOO_BIG_ERROR: return "entry too large"; + case REFTABLE_OUTDATED_ERROR: + return "data concurrently modified"; case -1: return "general error"; default: diff --git a/reftable/iter.c b/reftable/iter.c index 8b5ebf6183..aa9ac199b1 100644 --- a/reftable/iter.c +++ b/reftable/iter.c @@ -16,11 +16,6 @@ https://developers.google.com/open-source/licenses/bsd #include "reader.h" #include "reftable-error.h" -int iterator_is_null(struct reftable_iterator *it) -{ - return !it->ops; -} - static void filtering_ref_iterator_close(void *iter_arg) { struct filtering_ref_iterator *fri = iter_arg; @@ -120,7 +115,7 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) /* indexed block does not exist. */ return REFTABLE_FORMAT_ERROR; } - block_reader_start(&it->block_reader, &it->cur); + block_iter_seek_start(&it->cur, &it->block_reader); return 0; } diff --git a/reftable/iter.h b/reftable/iter.h index 47d67d84df..537431baba 100644 --- a/reftable/iter.h +++ b/reftable/iter.h @@ -16,10 +16,6 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable-iterator.h" #include "reftable-generic.h" -/* Returns true for a zeroed out iterator, such as the one returned from - * iterator_destroy. */ -int iterator_is_null(struct reftable_iterator *it); - /* iterator that produces only ref records that point to `oid` */ struct filtering_ref_iterator { int double_check; diff --git a/reftable/merged.c b/reftable/merged.c index a0f222e07b..f85a24c678 100644 --- a/reftable/merged.c +++ b/reftable/merged.c @@ -17,23 +17,37 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable-error.h" #include "system.h" +struct merged_subiter { + struct reftable_iterator iter; + struct reftable_record rec; +}; + +struct merged_iter { + struct merged_subiter *subiters; + struct merged_iter_pqueue pq; + uint32_t hash_id; + size_t stack_len; + uint8_t typ; + int suppress_deletions; + ssize_t advance_index; +}; + static int merged_iter_init(struct merged_iter *mi) { for (size_t i = 0; i < mi->stack_len; i++) { struct pq_entry e = { .index = i, + .rec = &mi->subiters[i].rec, }; int err; - reftable_record_init(&e.rec, mi->typ); - err = iterator_next(&mi->stack[i], &e.rec); + reftable_record_init(&mi->subiters[i].rec, mi->typ); + err = iterator_next(&mi->subiters[i].iter, + &mi->subiters[i].rec); if (err < 0) return err; - if (err > 0) { - reftable_iterator_destroy(&mi->stack[i]); - reftable_record_release(&e.rec); + if (err > 0) continue; - } merged_iter_pqueue_add(&mi->pq, &e); } @@ -46,56 +60,66 @@ 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++) - reftable_iterator_destroy(&mi->stack[i]); - reftable_free(mi->stack); - strbuf_release(&mi->key); - strbuf_release(&mi->entry_key); + for (size_t i = 0; i < mi->stack_len; i++) { + reftable_iterator_destroy(&mi->subiters[i].iter); + reftable_record_release(&mi->subiters[i].rec); + } + reftable_free(mi->subiters); } -static int merged_iter_advance_nonnull_subiter(struct merged_iter *mi, - size_t idx) +static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx) { struct pq_entry e = { .index = idx, + .rec = &mi->subiters[idx].rec, }; int err; - reftable_record_init(&e.rec, mi->typ); - err = iterator_next(&mi->stack[idx], &e.rec); - if (err < 0) + err = iterator_next(&mi->subiters[idx].iter, &mi->subiters[idx].rec); + if (err) return err; - if (err > 0) { - reftable_iterator_destroy(&mi->stack[idx]); - reftable_record_release(&e.rec); - return 0; - } - merged_iter_pqueue_add(&mi->pq, &e); return 0; } -static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx) -{ - if (iterator_is_null(&mi->stack[idx])) - return 0; - return merged_iter_advance_nonnull_subiter(mi, idx); -} - static int merged_iter_next_entry(struct merged_iter *mi, struct reftable_record *rec) { struct pq_entry entry = { 0 }; - int err = 0; + int err = 0, empty; + + empty = merged_iter_pqueue_is_empty(mi->pq); + + if (mi->advance_index >= 0) { + /* + * When there are no pqueue entries then we only have a single + * subiter left. There is no need to use the pqueue in that + * case anymore as we know that the subiter will return entries + * in the correct order already. + * + * While this may sound like a very specific edge case, it may + * happen more frequently than you think. Most repositories + * will end up having a single large base table that contains + * most of the refs. It's thus likely that we exhaust all + * subiters but the one from that base ref. + */ + if (empty) + return iterator_next(&mi->subiters[mi->advance_index].iter, + rec); + + err = merged_iter_advance_subiter(mi, mi->advance_index); + if (err < 0) + return err; + if (!err) + empty = 0; + mi->advance_index = -1; + } - if (merged_iter_pqueue_is_empty(mi->pq)) + if (empty) return 1; entry = merged_iter_pqueue_remove(&mi->pq); - err = merged_iter_advance_subiter(mi, entry.index); - if (err < 0) - return err; /* One can also use reftable as datacenter-local storage, where the ref @@ -105,55 +129,38 @@ static int merged_iter_next_entry(struct merged_iter *mi, such a deployment, the loop below must be changed to collect all entries for the same key, and return new the newest one. */ - reftable_record_key(&entry.rec, &mi->entry_key); while (!merged_iter_pqueue_is_empty(mi->pq)) { struct pq_entry top = merged_iter_pqueue_top(mi->pq); - int cmp = 0; - - reftable_record_key(&top.rec, &mi->key); + int cmp; - cmp = strbuf_cmp(&mi->key, &mi->entry_key); + cmp = reftable_record_cmp(top.rec, entry.rec); if (cmp > 0) break; merged_iter_pqueue_remove(&mi->pq); err = merged_iter_advance_subiter(mi, top.index); if (err < 0) - goto done; - reftable_record_release(&top.rec); + return err; } - reftable_record_release(rec); - *rec = entry.rec; - -done: - if (err) - reftable_record_release(&entry.rec); - return err; + mi->advance_index = entry.index; + SWAP(*rec, *entry.rec); + return 0; } -static int merged_iter_next(struct merged_iter *mi, struct reftable_record *rec) +static int merged_iter_next_void(void *p, struct reftable_record *rec) { + struct merged_iter *mi = p; while (1) { int err = merged_iter_next_entry(mi, rec); - if (err == 0 && mi->suppress_deletions && - reftable_record_is_deletion(rec)) { + if (err) + return err; + if (mi->suppress_deletions && reftable_record_is_deletion(rec)) continue; - } - - return err; + return 0; } } -static int merged_iter_next_void(void *p, struct reftable_record *rec) -{ - struct merged_iter *mi = p; - if (merged_iter_pqueue_is_empty(mi->pq)) - return 1; - - return merged_iter_next(mi, rec); -} - static struct reftable_iterator_vtable merged_iter_vtable = { .next = &merged_iter_next_void, .close = &merged_iter_close, @@ -243,16 +250,15 @@ static int merged_table_seek_record(struct reftable_merged_table *mt, .typ = reftable_record_type(rec), .hash_id = mt->hash_id, .suppress_deletions = mt->suppress_deletions, - .key = STRBUF_INIT, - .entry_key = STRBUF_INIT, + .advance_index = -1, }; struct merged_iter *p; int err; - REFTABLE_CALLOC_ARRAY(merged.stack, mt->stack_len); + REFTABLE_CALLOC_ARRAY(merged.subiters, mt->stack_len); for (size_t i = 0; i < mt->stack_len; i++) { err = reftable_table_seek_record(&mt->stack[i], - &merged.stack[merged.stack_len], rec); + &merged.subiters[merged.stack_len].iter, rec); if (err < 0) goto out; if (!err) diff --git a/reftable/merged.h b/reftable/merged.h index d5b39dfe7f..a2571dbc99 100644 --- a/reftable/merged.h +++ b/reftable/merged.h @@ -9,7 +9,7 @@ https://developers.google.com/open-source/licenses/bsd #ifndef MERGED_H #define MERGED_H -#include "pq.h" +#include "system.h" struct reftable_merged_table { struct reftable_table *stack; @@ -24,17 +24,6 @@ struct reftable_merged_table { uint64_t max; }; -struct merged_iter { - struct reftable_iterator *stack; - uint32_t hash_id; - size_t stack_len; - uint8_t typ; - int suppress_deletions; - struct merged_iter_pqueue pq; - struct strbuf key; - struct strbuf entry_key; -}; - void merged_table_release(struct reftable_merged_table *mt); #endif diff --git a/reftable/merged_test.c b/reftable/merged_test.c index d0f77a3b8f..530fc82d1c 100644 --- a/reftable/merged_test.c +++ b/reftable/merged_test.c @@ -289,16 +289,13 @@ merged_table_from_log_records(struct reftable_log_record **logs, static void test_merged_logs(void) { - uint8_t hash1[GIT_SHA1_RAWSZ] = { 1 }; - uint8_t hash2[GIT_SHA1_RAWSZ] = { 2 }; - uint8_t hash3[GIT_SHA1_RAWSZ] = { 3 }; struct reftable_log_record r1[] = { { .refname = "a", .update_index = 2, .value_type = REFTABLE_LOG_UPDATE, .value.update = { - .old_hash = hash2, + .old_hash = { 2 }, /* deletion */ .name = "jane doe", .email = "jane@invalid", @@ -310,8 +307,8 @@ static void test_merged_logs(void) .update_index = 1, .value_type = REFTABLE_LOG_UPDATE, .value.update = { - .old_hash = hash1, - .new_hash = hash2, + .old_hash = { 1 }, + .new_hash = { 2 }, .name = "jane doe", .email = "jane@invalid", .message = "message1", @@ -324,7 +321,7 @@ static void test_merged_logs(void) .update_index = 3, .value_type = REFTABLE_LOG_UPDATE, .value.update = { - .new_hash = hash3, + .new_hash = { 3 }, .name = "jane doe", .email = "jane@invalid", .message = "message3", diff --git a/reftable/pq.c b/reftable/pq.c index 2461daf5ff..7fb45d8c60 100644 --- a/reftable/pq.c +++ b/reftable/pq.c @@ -14,33 +14,12 @@ https://developers.google.com/open-source/licenses/bsd int pq_less(struct pq_entry *a, struct pq_entry *b) { - struct strbuf ak = STRBUF_INIT; - struct strbuf bk = STRBUF_INIT; - int cmp = 0; - reftable_record_key(&a->rec, &ak); - reftable_record_key(&b->rec, &bk); - - cmp = strbuf_cmp(&ak, &bk); - - strbuf_release(&ak); - strbuf_release(&bk); - + int cmp = reftable_record_cmp(a->rec, b->rec); if (cmp == 0) return a->index > b->index; - return cmp < 0; } -struct pq_entry merged_iter_pqueue_top(struct merged_iter_pqueue pq) -{ - return pq.heap[0]; -} - -int merged_iter_pqueue_is_empty(struct merged_iter_pqueue pq) -{ - return pq.len == 0; -} - struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq) { int i = 0; @@ -93,10 +72,6 @@ void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry void merged_iter_pqueue_release(struct merged_iter_pqueue *pq) { - int i = 0; - for (i = 0; i < pq->len; i++) { - reftable_record_release(&pq->heap[i].rec); - } FREE_AND_NULL(pq->heap); - pq->len = pq->cap = 0; + memset(pq, 0, sizeof(*pq)); } diff --git a/reftable/pq.h b/reftable/pq.h index e85bac9b52..f796c23179 100644 --- a/reftable/pq.h +++ b/reftable/pq.h @@ -12,8 +12,8 @@ https://developers.google.com/open-source/licenses/bsd #include "record.h" struct pq_entry { - int index; - struct reftable_record rec; + size_t index; + struct reftable_record *rec; }; struct merged_iter_pqueue { @@ -22,12 +22,20 @@ struct merged_iter_pqueue { size_t cap; }; -struct pq_entry merged_iter_pqueue_top(struct merged_iter_pqueue pq); -int merged_iter_pqueue_is_empty(struct merged_iter_pqueue pq); 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); void merged_iter_pqueue_release(struct merged_iter_pqueue *pq); int pq_less(struct pq_entry *a, struct pq_entry *b); +static inline struct pq_entry merged_iter_pqueue_top(struct merged_iter_pqueue pq) +{ + return pq.heap[0]; +} + +static inline int merged_iter_pqueue_is_empty(struct merged_iter_pqueue pq) +{ + return pq.len == 0; +} + #endif diff --git a/reftable/pq_test.c b/reftable/pq_test.c index c202eff848..b7d3c80cc7 100644 --- a/reftable/pq_test.c +++ b/reftable/pq_test.c @@ -27,48 +27,43 @@ void merged_iter_pqueue_check(struct merged_iter_pqueue pq) static void test_pq(void) { - char *names[54] = { NULL }; - int N = ARRAY_SIZE(names) - 1; - struct merged_iter_pqueue pq = { NULL }; + struct reftable_record recs[54]; + int N = ARRAY_SIZE(recs) - 1, i; char *last = NULL; - int i = 0; for (i = 0; i < N; i++) { - char name[100]; - snprintf(name, sizeof(name), "%02d", i); - names[i] = xstrdup(name); + 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 = { .type = BLOCK_TYPE_REF, - .u.ref = { - .refname = names[i], - } } }; + 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); - struct reftable_record *rec = &e.rec; merged_iter_pqueue_check(pq); - EXPECT(reftable_record_type(rec) == BLOCK_TYPE_REF); - if (last) { - EXPECT(strcmp(last, rec->u.ref.refname) < 0); - } - /* this is names[i], so don't dealloc. */ - last = rec->u.ref.refname; - rec->u.ref.refname = NULL; - reftable_record_release(rec); - } - for (i = 0; i < N; i++) { - reftable_free(names[i]); + 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); } diff --git a/reftable/reader.c b/reftable/reader.c index 2663b03938..481dff10d4 100644 --- a/reftable/reader.c +++ b/reftable/reader.c @@ -220,6 +220,7 @@ struct table_iter { struct reftable_reader *r; uint8_t typ; uint64_t block_off; + struct block_reader br; struct block_iter bi; int is_finished; }; @@ -227,16 +228,6 @@ struct table_iter { .bi = BLOCK_ITER_INIT \ } -static void table_iter_copy_from(struct table_iter *dest, - struct table_iter *src) -{ - dest->r = src->r; - dest->typ = src->typ; - dest->block_off = src->block_off; - dest->is_finished = src->is_finished; - block_iter_copy_from(&dest->bi, &src->bi); -} - static int table_iter_next_in_block(struct table_iter *ti, struct reftable_record *rec) { @@ -250,14 +241,8 @@ static int table_iter_next_in_block(struct table_iter *ti, static void table_iter_block_done(struct table_iter *ti) { - if (!ti->bi.br) { - return; - } - reftable_block_done(&ti->bi.br->block); - FREE_AND_NULL(ti->bi.br); - - ti->bi.last_key.len = 0; - ti->bi.next_off = 0; + block_reader_release(&ti->br); + block_iter_reset(&ti->bi); } static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off, @@ -321,32 +306,27 @@ done: return err; } -static int table_iter_next_block(struct table_iter *dest, - struct table_iter *src) +static void table_iter_close(struct table_iter *ti) { - uint64_t next_block_off = src->block_off + src->bi.br->full_block_size; - struct block_reader br = { 0 }; - int err = 0; + table_iter_block_done(ti); + block_iter_close(&ti->bi); +} - dest->r = src->r; - dest->typ = src->typ; - dest->block_off = next_block_off; +static int table_iter_next_block(struct table_iter *ti) +{ + uint64_t next_block_off = ti->block_off + ti->br.full_block_size; + int err; - err = reader_init_block_reader(src->r, &br, next_block_off, src->typ); - if (err > 0) { - dest->is_finished = 1; - return 1; - } - if (err != 0) + err = reader_init_block_reader(ti->r, &ti->br, next_block_off, ti->typ); + if (err > 0) + ti->is_finished = 1; + if (err) return err; - else { - struct block_reader *brp = - reftable_malloc(sizeof(struct block_reader)); - *brp = br; - dest->is_finished = 0; - block_reader_start(brp, &dest->bi); - } + ti->block_off = next_block_off; + ti->is_finished = 0; + block_iter_seek_start(&ti->bi, &ti->br); + return 0; } @@ -356,27 +336,30 @@ static int table_iter_next(struct table_iter *ti, struct reftable_record *rec) return REFTABLE_API_ERROR; while (1) { - struct table_iter next = TABLE_ITER_INIT; - int err = 0; - if (ti->is_finished) { + int err; + + if (ti->is_finished) return 1; - } + /* + * Check whether the current block still has more records. If + * so, return it. If the iterator returns positive then the + * current block has been exhausted. + */ err = table_iter_next_in_block(ti, rec); - if (err <= 0) { + if (err <= 0) return err; - } - err = table_iter_next_block(&next, ti); - if (err != 0) { + /* + * Otherwise, we need to continue to the next block in the + * table and retry. If there are no more blocks then the + * iterator is drained. + */ + err = table_iter_next_block(ti); + if (err) { ti->is_finished = 1; - } - table_iter_block_done(ti); - if (err != 0) { return err; } - table_iter_copy_from(ti, &next); - block_iter_close(&next.bi); } } @@ -385,16 +368,14 @@ static int table_iter_next_void(void *ti, struct reftable_record *rec) return table_iter_next(ti, rec); } -static void table_iter_close(void *p) +static void table_iter_close_void(void *ti) { - struct table_iter *ti = p; - table_iter_block_done(ti); - block_iter_close(&ti->bi); + table_iter_close(ti); } static struct reftable_iterator_vtable table_iter_vtable = { .next = &table_iter_next_void, - .close = &table_iter_close, + .close = &table_iter_close_void, }; static void iterator_from_table_iter(struct reftable_iterator *it, @@ -409,19 +390,16 @@ static int reader_table_iter_at(struct reftable_reader *r, struct table_iter *ti, uint64_t off, uint8_t typ) { - struct block_reader br = { 0 }; - struct block_reader *brp = NULL; + int err; - int err = reader_init_block_reader(r, &br, off, typ); + err = reader_init_block_reader(r, &ti->br, off, typ); if (err != 0) return err; - brp = reftable_malloc(sizeof(struct block_reader)); - *brp = br; ti->r = r; - ti->typ = block_reader_type(brp); + ti->typ = block_reader_type(&ti->br); ti->block_off = off; - block_reader_start(brp, &ti->bi); + block_iter_seek_start(&ti->bi, &ti->br); return 0; } @@ -446,23 +424,52 @@ static int reader_seek_linear(struct table_iter *ti, { struct strbuf want_key = STRBUF_INIT; struct strbuf got_key = STRBUF_INIT; - struct table_iter next = TABLE_ITER_INIT; struct reftable_record rec; int err = -1; reftable_record_init(&rec, reftable_record_type(want)); reftable_record_key(want, &want_key); + /* + * First we need to locate the block that must contain our record. To + * do so we scan through blocks linearly until we find the first block + * whose first key is bigger than our wanted key. Once we have found + * that block we know that the key must be contained in the preceding + * block. + * + * This algorithm is somewhat unfortunate because it means that we + * always have to seek one block too far and then back up. But as we + * can only decode the _first_ key of a block but not its _last_ key we + * have no other way to do this. + */ while (1) { - err = table_iter_next_block(&next, ti); + struct table_iter next = *ti; + + /* + * We must be careful to not modify underlying data of `ti` + * because we may find that `next` does not contain our desired + * block, but that `ti` does. In that case, we would discard + * `next` and continue with `ti`. + * + * This also means that we cannot reuse allocated memory for + * `next` here. While it would be great if we could, it should + * in practice not be too bad given that we should only ever + * end up doing linear seeks with at most three blocks. As soon + * as we have more than three blocks we would have an index, so + * we would not do a linear search there anymore. + */ + memset(&next.br.block, 0, sizeof(next.br.block)); + next.br.zstream = NULL; + next.br.uncompressed_data = NULL; + next.br.uncompressed_cap = 0; + + err = table_iter_next_block(&next); if (err < 0) goto done; - - if (err > 0) { + if (err > 0) break; - } - err = block_reader_first_key(next.bi.br, &got_key); + err = block_reader_first_key(&next.br, &got_key); if (err < 0) goto done; @@ -472,16 +479,20 @@ static int reader_seek_linear(struct table_iter *ti, } table_iter_block_done(ti); - table_iter_copy_from(ti, &next); + *ti = next; } - err = block_iter_seek(&ti->bi, &want_key); + /* + * We have located the block that must contain our record, so we seek + * the wanted key inside of it. If the block does not contain our key + * we know that the corresponding record does not exist. + */ + err = block_iter_seek_key(&ti->bi, &ti->br, &want_key); if (err < 0) goto done; err = 0; done: - block_iter_close(&next.bi); reftable_record_release(&rec); strbuf_release(&want_key); strbuf_release(&got_key); @@ -500,6 +511,7 @@ static int reader_seek_indexed(struct reftable_reader *r, .u.idx = { .last_key = STRBUF_INIT }, }; struct table_iter index_iter = TABLE_ITER_INIT; + struct table_iter empty = TABLE_ITER_INIT; struct table_iter next = TABLE_ITER_INIT; int err = 0; @@ -541,7 +553,6 @@ static int reader_seek_indexed(struct reftable_reader *r, * not exist. */ err = table_iter_next(&index_iter, &index_result); - table_iter_block_done(&index_iter); if (err != 0) goto done; @@ -550,7 +561,7 @@ static int reader_seek_indexed(struct reftable_reader *r, if (err != 0) goto done; - err = block_iter_seek(&next.bi, &want_index.u.idx.last_key); + err = block_iter_seek_key(&next.bi, &next.br, &want_index.u.idx.last_key); if (err < 0) goto done; @@ -564,18 +575,20 @@ static int reader_seek_indexed(struct reftable_reader *r, break; } - table_iter_copy_from(&index_iter, &next); + table_iter_close(&index_iter); + index_iter = next; + next = empty; } if (err == 0) { - struct table_iter empty = TABLE_ITER_INIT; struct table_iter *malloced = reftable_calloc(1, sizeof(*malloced)); - *malloced = empty; - table_iter_copy_from(malloced, &next); + *malloced = next; + next = empty; iterator_from_table_iter(it, malloced); } + done: - block_iter_close(&next.bi); + table_iter_close(&next); table_iter_close(&index_iter); reftable_record_release(&want_index); reftable_record_release(&index_result); @@ -589,25 +602,28 @@ static int reader_seek_internal(struct reftable_reader *r, struct reftable_reader_offsets *offs = reader_offsets_for(r, reftable_record_type(rec)); uint64_t idx = offs->index_offset; - struct table_iter ti = TABLE_ITER_INIT; - int err = 0; + struct table_iter ti = TABLE_ITER_INIT, *p; + int err; + if (idx > 0) return reader_seek_indexed(r, it, rec); err = reader_start(r, &ti, reftable_record_type(rec), 0); if (err < 0) - return err; + goto out; + err = reader_seek_linear(&ti, rec); if (err < 0) - return err; - else { - struct table_iter *p = - reftable_malloc(sizeof(struct table_iter)); - *p = ti; - iterator_from_table_iter(it, p); - } + goto out; - return 0; + REFTABLE_ALLOC_ARRAY(p, 1); + *p = ti; + iterator_from_table_iter(it, p); + +out: + if (err) + table_iter_close(&ti); + return err; } static int reader_seek(struct reftable_reader *r, struct reftable_iterator *it, diff --git a/reftable/readwrite_test.c b/reftable/readwrite_test.c index 363fe0f998..a6dbd214c5 100644 --- a/reftable/readwrite_test.c +++ b/reftable/readwrite_test.c @@ -77,18 +77,15 @@ static void write_table(char ***names, struct strbuf *buf, int N, } for (i = 0; i < N; i++) { - uint8_t hash[GIT_SHA256_RAWSZ] = { 0 }; char name[100]; int n; - set_test_hash(hash, i); - snprintf(name, sizeof(name), "refs/heads/branch%02d", i); log.refname = name; log.update_index = update_index; log.value_type = REFTABLE_LOG_UPDATE; - log.value.update.new_hash = hash; + set_test_hash(log.value.update.new_hash, i); log.value.update.message = "message"; n = reftable_writer_add_log(w, &log); @@ -137,13 +134,10 @@ static void test_log_buffer_size(void) /* This tests buffer extension for log compression. Must use a random hash, to ensure that the compressed part is larger than the original. */ - uint8_t hash1[GIT_SHA1_RAWSZ], hash2[GIT_SHA1_RAWSZ]; for (i = 0; i < GIT_SHA1_RAWSZ; i++) { - hash1[i] = (uint8_t)(git_rand() % 256); - hash2[i] = (uint8_t)(git_rand() % 256); + log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256); + log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256); } - log.value.update.old_hash = hash1; - log.value.update.new_hash = hash2; reftable_writer_set_limits(w, update_index, update_index); err = reftable_writer_add_log(w, &log); EXPECT_ERR(err); @@ -161,25 +155,26 @@ static void test_log_overflow(void) .block_size = ARRAY_SIZE(msg), }; int err; - struct reftable_log_record - log = { .refname = "refs/heads/master", - .update_index = 0xa, - .value_type = REFTABLE_LOG_UPDATE, - .value = { .update = { - .name = "Han-Wen Nienhuys", - .email = "hanwen@google.com", - .tz_offset = 100, - .time = 0x5e430672, - .message = msg, - } } }; + struct reftable_log_record log = { + .refname = "refs/heads/master", + .update_index = 0xa, + .value_type = REFTABLE_LOG_UPDATE, + .value = { + .update = { + .old_hash = { 1 }, + .new_hash = { 2 }, + .name = "Han-Wen Nienhuys", + .email = "hanwen@google.com", + .tz_offset = 100, + .time = 0x5e430672, + .message = msg, + }, + }, + }; struct reftable_writer *w = reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); - uint8_t hash1[GIT_SHA1_RAWSZ] = {1}, hash2[GIT_SHA1_RAWSZ] = { 2 }; - memset(msg, 'x', sizeof(msg) - 1); - log.value.update.old_hash = hash1; - log.value.update.new_hash = hash2; reftable_writer_set_limits(w, update_index, update_index); err = reftable_writer_add_log(w, &log); EXPECT(err == REFTABLE_ENTRY_TOO_BIG_ERROR); @@ -219,16 +214,13 @@ static void test_log_write_read(void) EXPECT_ERR(err); } for (i = 0; i < N; i++) { - uint8_t hash1[GIT_SHA1_RAWSZ], hash2[GIT_SHA1_RAWSZ]; struct reftable_log_record log = { NULL }; - set_test_hash(hash1, i); - set_test_hash(hash2, i + 1); log.refname = names[i]; log.update_index = i; log.value_type = REFTABLE_LOG_UPDATE; - log.value.update.old_hash = hash1; - log.value.update.new_hash = hash2; + 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); @@ -298,18 +290,15 @@ static void test_log_zlib_corruption(void) struct reftable_writer *w = reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); const struct reftable_stats *stats = NULL; - uint8_t hash1[GIT_SHA1_RAWSZ] = { 1 }; - uint8_t hash2[GIT_SHA1_RAWSZ] = { 2 }; char message[100] = { 0 }; int err, i, n; - struct reftable_log_record log = { .refname = "refname", .value_type = REFTABLE_LOG_UPDATE, .value = { .update = { - .new_hash = hash1, - .old_hash = hash2, + .new_hash = { 1 }, + .old_hash = { 2 }, .name = "My Name", .email = "myname@invalid", .message = message, @@ -821,13 +810,12 @@ static void test_write_multiple_indices(void) } for (i = 0; i < 100; i++) { - unsigned char hash[GIT_SHA1_RAWSZ] = {i}; struct reftable_log_record log = { .update_index = 1, .value_type = REFTABLE_LOG_UPDATE, .value.update = { - .old_hash = hash, - .new_hash = hash, + .old_hash = { i }, + .new_hash = { i }, }, }; diff --git a/reftable/record.c b/reftable/record.c index 26c5e43f9b..5506f3e913 100644 --- a/reftable/record.c +++ b/reftable/record.c @@ -159,34 +159,49 @@ int reftable_encode_key(int *restart, struct string_view dest, return start.len - dest.len; } -int reftable_decode_key(struct strbuf *key, uint8_t *extra, - struct strbuf last_key, struct string_view in) +int reftable_decode_keylen(struct string_view in, + uint64_t *prefix_len, + uint64_t *suffix_len, + uint8_t *extra) { - int start_len = in.len; - uint64_t prefix_len = 0; - uint64_t suffix_len = 0; - int n = get_var_int(&prefix_len, &in); + size_t start_len = in.len; + int n; + + n = get_var_int(prefix_len, &in); if (n < 0) return -1; string_view_consume(&in, n); - if (prefix_len > last_key.len) - return -1; - - n = get_var_int(&suffix_len, &in); + n = get_var_int(suffix_len, &in); if (n <= 0) return -1; string_view_consume(&in, n); - *extra = (uint8_t)(suffix_len & 0x7); - suffix_len >>= 3; + *extra = (uint8_t)(*suffix_len & 0x7); + *suffix_len >>= 3; - if (in.len < suffix_len) + return start_len - in.len; +} + +int reftable_decode_key(struct strbuf *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; + + n = reftable_decode_keylen(in, &prefix_len, &suffix_len, extra); + if (n < 0) return -1; + string_view_consume(&in, n); - strbuf_reset(key); - strbuf_add(key, last_key.buf, prefix_len); - strbuf_add(key, in.buf, suffix_len); + if (in.len < suffix_len || + prefix_len > last_key->len) + return -1; + + strbuf_setlen(last_key, prefix_len); + strbuf_add(last_key, in.buf, suffix_len); string_view_consume(&in, suffix_len); return start_len - in.len; @@ -205,14 +220,26 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec, { struct reftable_ref_record *ref = rec; const struct reftable_ref_record *src = src_rec; + char *refname = NULL; + size_t refname_cap = 0; + assert(hash_size > 0); - /* This is simple and correct, but we could probably reuse the hash - * fields. */ + SWAP(refname, ref->refname); + SWAP(refname_cap, ref->refname_cap); reftable_ref_record_release(ref); + SWAP(ref->refname, refname); + SWAP(ref->refname_cap, refname_cap); + if (src->refname) { - ref->refname = xstrdup(src->refname); + size_t refname_len = strlen(src->refname); + + REFTABLE_ALLOC_GROW(ref->refname, refname_len + 1, + ref->refname_cap); + memcpy(ref->refname, src->refname, refname_len); + ref->refname[refname_len] = 0; } + ref->update_index = src->update_index; ref->value_type = src->value_type; switch (src->value_type) { @@ -363,24 +390,33 @@ static int reftable_ref_record_encode(const void *rec, struct string_view s, static int reftable_ref_record_decode(void *rec, struct strbuf key, uint8_t val_type, struct string_view in, - int hash_size) + int hash_size, struct strbuf *scratch) { struct reftable_ref_record *r = rec; struct string_view start = in; uint64_t update_index = 0; - int n = get_var_int(&update_index, &in); + const char *refname = NULL; + size_t refname_cap = 0; + int n; + + assert(hash_size > 0); + + n = get_var_int(&update_index, &in); if (n < 0) return n; string_view_consume(&in, n); + SWAP(refname, r->refname); + SWAP(refname_cap, r->refname_cap); reftable_ref_record_release(r); + SWAP(r->refname, refname); + SWAP(r->refname_cap, refname_cap); - assert(hash_size > 0); - - r->refname = reftable_realloc(r->refname, key.len + 1); + REFTABLE_ALLOC_GROW(r->refname, key.len + 1, r->refname_cap); memcpy(r->refname, key.buf, key.len); - r->update_index = update_index; r->refname[key.len] = 0; + + r->update_index = update_index; r->value_type = val_type; switch (val_type) { case REFTABLE_REF_VAL1: @@ -405,13 +441,12 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key, break; case REFTABLE_REF_SYMREF: { - struct strbuf dest = STRBUF_INIT; - int n = decode_string(&dest, in); + int n = decode_string(scratch, in); if (n < 0) { return -1; } string_view_consume(&in, n); - r->value.symref = dest.buf; + r->value.symref = strbuf_detach(scratch, NULL); } break; case REFTABLE_REF_DELETION: @@ -430,7 +465,6 @@ static int reftable_ref_record_is_deletion_void(const void *p) (const struct reftable_ref_record *)p); } - static int reftable_ref_record_equal_void(const void *a, const void *b, int hash_size) { @@ -439,6 +473,13 @@ static int reftable_ref_record_equal_void(const void *a, return reftable_ref_record_equal(ra, rb, hash_size); } +static int reftable_ref_record_cmp_void(const void *_a, const void *_b) +{ + const struct reftable_ref_record *a = _a; + const struct reftable_ref_record *b = _b; + return strcmp(a->refname, b->refname); +} + static void reftable_ref_record_print_void(const void *rec, int hash_size) { @@ -455,6 +496,7 @@ static struct reftable_record_vtable reftable_ref_record_vtable = { .release = &reftable_ref_record_release_void, .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, }; @@ -552,7 +594,7 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s, static int reftable_obj_record_decode(void *rec, struct strbuf key, uint8_t val_type, struct string_view in, - int hash_size) + int hash_size, struct strbuf *scratch UNUSED) { struct string_view start = in; struct reftable_obj_record *r = rec; @@ -561,6 +603,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key, uint64_t last; int j; + reftable_obj_record_release(r); + REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len); memcpy(r->hash_prefix, key.buf, key.len); r->hash_prefix_len = key.len; @@ -627,6 +671,25 @@ static int reftable_obj_record_equal_void(const void *a, const void *b, int hash return 1; } +static int reftable_obj_record_cmp_void(const void *_a, const void *_b) +{ + const struct reftable_obj_record *a = _a; + const struct reftable_obj_record *b = _b; + int cmp; + + cmp = memcmp(a->hash_prefix, b->hash_prefix, + a->hash_prefix_len > b->hash_prefix_len ? + a->hash_prefix_len : b->hash_prefix_len); + if (cmp) + return cmp; + + /* + * When the prefix is the same then the object record that is longer is + * considered to be bigger. + */ + return a->hash_prefix_len - b->hash_prefix_len; +} + static struct reftable_record_vtable reftable_obj_record_vtable = { .key = &reftable_obj_record_key, .type = BLOCK_TYPE_OBJ, @@ -637,6 +700,7 @@ static struct reftable_record_vtable reftable_obj_record_vtable = { .release = &reftable_obj_record_release, .is_deletion = ¬_a_deletion, .equal = &reftable_obj_record_equal_void, + .cmp = &reftable_obj_record_cmp_void, .print = &reftable_obj_record_print, }; @@ -716,16 +780,10 @@ static void reftable_log_record_copy_from(void *rec, const void *src_rec, xstrdup(dst->value.update.message); } - if (dst->value.update.new_hash) { - REFTABLE_ALLOC_ARRAY(dst->value.update.new_hash, hash_size); - memcpy(dst->value.update.new_hash, - src->value.update.new_hash, hash_size); - } - if (dst->value.update.old_hash) { - REFTABLE_ALLOC_ARRAY(dst->value.update.old_hash, hash_size); - memcpy(dst->value.update.old_hash, - src->value.update.old_hash, hash_size); - } + memcpy(dst->value.update.new_hash, + src->value.update.new_hash, hash_size); + memcpy(dst->value.update.old_hash, + src->value.update.old_hash, hash_size); break; } } @@ -743,8 +801,6 @@ void reftable_log_record_release(struct reftable_log_record *r) case REFTABLE_LOG_DELETION: break; case REFTABLE_LOG_UPDATE: - reftable_free(r->value.update.new_hash); - reftable_free(r->value.update.old_hash); reftable_free(r->value.update.name); reftable_free(r->value.update.email); reftable_free(r->value.update.message); @@ -761,33 +817,20 @@ static uint8_t reftable_log_record_val_type(const void *rec) return reftable_log_record_is_deletion(log) ? 0 : 1; } -static uint8_t zero[GIT_SHA256_RAWSZ] = { 0 }; - static int reftable_log_record_encode(const void *rec, struct string_view s, int hash_size) { const struct reftable_log_record *r = rec; struct string_view start = s; int n = 0; - uint8_t *oldh = NULL; - uint8_t *newh = NULL; if (reftable_log_record_is_deletion(r)) return 0; - oldh = r->value.update.old_hash; - newh = r->value.update.new_hash; - if (!oldh) { - oldh = zero; - } - if (!newh) { - newh = zero; - } - if (s.len < 2 * hash_size) return -1; - memcpy(s.buf, oldh, hash_size); - memcpy(s.buf + hash_size, newh, hash_size); + memcpy(s.buf, r->value.update.old_hash, hash_size); + memcpy(s.buf + hash_size, r->value.update.new_hash, hash_size); string_view_consume(&s, 2 * hash_size); n = encode_string(r->value.update.name ? r->value.update.name : "", s); @@ -823,19 +866,18 @@ static int reftable_log_record_encode(const void *rec, struct string_view s, static int reftable_log_record_decode(void *rec, struct strbuf key, uint8_t val_type, struct string_view in, - int hash_size) + int hash_size, struct strbuf *scratch) { struct string_view start = in; struct reftable_log_record *r = rec; uint64_t max = 0; uint64_t ts = 0; - struct strbuf dest = STRBUF_INIT; int n; if (key.len <= 9 || key.buf[key.len - 9] != 0) return REFTABLE_FORMAT_ERROR; - r->refname = reftable_realloc(r->refname, key.len - 8); + REFTABLE_ALLOC_GROW(r->refname, key.len - 8, r->refname_cap); memcpy(r->refname, key.buf, key.len - 8); ts = get_be64(key.buf + key.len - 8); @@ -844,9 +886,8 @@ 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.old_hash); - FREE_AND_NULL(r->value.update.new_hash); 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); break; @@ -862,36 +903,43 @@ static int reftable_log_record_decode(void *rec, struct strbuf key, if (in.len < 2 * hash_size) return REFTABLE_FORMAT_ERROR; - r->value.update.old_hash = - reftable_realloc(r->value.update.old_hash, hash_size); - r->value.update.new_hash = - reftable_realloc(r->value.update.new_hash, hash_size); - memcpy(r->value.update.old_hash, in.buf, hash_size); memcpy(r->value.update.new_hash, in.buf + hash_size, hash_size); string_view_consume(&in, 2 * hash_size); - n = decode_string(&dest, in); + n = decode_string(scratch, in); if (n < 0) goto done; string_view_consume(&in, n); - r->value.update.name = - reftable_realloc(r->value.update.name, dest.len + 1); - memcpy(r->value.update.name, dest.buf, dest.len); - r->value.update.name[dest.len] = 0; + /* + * In almost all cases we can expect the reflog name to not change for + * reflog entries as they are tied to the local identity, not to the + * target commits. As an optimization for this common case we can thus + * skip copying over the name in case it's accurate already. + */ + 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); + memcpy(r->value.update.name, scratch->buf, scratch->len); + r->value.update.name[scratch->len] = 0; + } - strbuf_reset(&dest); - n = decode_string(&dest, in); + n = decode_string(scratch, in); if (n < 0) goto done; string_view_consume(&in, n); - r->value.update.email = - reftable_realloc(r->value.update.email, dest.len + 1); - memcpy(r->value.update.email, dest.buf, dest.len); - r->value.update.email[dest.len] = 0; + /* 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); + memcpy(r->value.update.email, scratch->buf, scratch->len); + r->value.update.email[scratch->len] = 0; + } ts = 0; n = get_var_int(&ts, &in); @@ -905,22 +953,19 @@ static int reftable_log_record_decode(void *rec, struct strbuf key, r->value.update.tz_offset = get_be16(in.buf); string_view_consume(&in, 2); - strbuf_reset(&dest); - n = decode_string(&dest, in); + n = decode_string(scratch, in); if (n < 0) goto done; string_view_consume(&in, n); - r->value.update.message = - reftable_realloc(r->value.update.message, dest.len + 1); - memcpy(r->value.update.message, dest.buf, dest.len); - r->value.update.message[dest.len] = 0; + REFTABLE_ALLOC_GROW(r->value.update.message, scratch->len + 1, + r->value.update.message_cap); + memcpy(r->value.update.message, scratch->buf, scratch->len); + r->value.update.message[scratch->len] = 0; - strbuf_release(&dest); return start.len - in.len; done: - strbuf_release(&dest); return REFTABLE_FORMAT_ERROR; } @@ -936,17 +981,6 @@ static int null_streq(char *a, char *b) return 0 == strcmp(a, b); } -static int zero_hash_eq(uint8_t *a, uint8_t *b, int sz) -{ - if (!a) - a = zero; - - if (!b) - b = zero; - - return !memcmp(a, b, sz); -} - static int reftable_log_record_equal_void(const void *a, const void *b, int hash_size) { @@ -955,6 +989,22 @@ static int reftable_log_record_equal_void(const void *a, hash_size); } +static int reftable_log_record_cmp_void(const void *_a, const void *_b) +{ + const struct reftable_log_record *a = _a; + const struct reftable_log_record *b = _b; + int cmp = strcmp(a->refname, b->refname); + if (cmp) + return cmp; + + /* + * Note that the comparison here is reversed. This is because the + * update index is reversed when comparing keys. For reference, see how + * we handle this in reftable_log_record_key()`. + */ + return b->update_index - a->update_index; +} + int reftable_log_record_equal(const struct reftable_log_record *a, const struct reftable_log_record *b, int hash_size) { @@ -974,10 +1024,10 @@ int reftable_log_record_equal(const struct reftable_log_record *a, b->value.update.email) && null_streq(a->value.update.message, b->value.update.message) && - zero_hash_eq(a->value.update.old_hash, - b->value.update.old_hash, hash_size) && - zero_hash_eq(a->value.update.new_hash, - b->value.update.new_hash, hash_size); + !memcmp(a->value.update.old_hash, + b->value.update.old_hash, hash_size) && + !memcmp(a->value.update.new_hash, + b->value.update.new_hash, hash_size); } abort(); @@ -1004,6 +1054,7 @@ static struct reftable_record_vtable reftable_log_record_vtable = { .release = &reftable_log_record_release_void, .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, }; @@ -1054,7 +1105,7 @@ static int reftable_index_record_encode(const void *rec, struct string_view out, static int reftable_index_record_decode(void *rec, struct strbuf key, uint8_t val_type, struct string_view in, - int hash_size) + int hash_size, struct strbuf *scratch UNUSED) { struct string_view start = in; struct reftable_index_record *r = rec; @@ -1079,6 +1130,13 @@ static int reftable_index_record_equal(const void *a, const void *b, int hash_si return ia->offset == ib->offset && !strbuf_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; @@ -1096,6 +1154,7 @@ static struct reftable_record_vtable reftable_index_record_vtable = { .release = &reftable_index_record_release, .is_deletion = ¬_a_deletion, .equal = &reftable_index_record_equal, + .cmp = &reftable_index_record_cmp, .print = &reftable_index_record_print, }; @@ -1104,11 +1163,6 @@ void reftable_record_key(struct reftable_record *rec, struct strbuf *dest) reftable_record_vtable(rec)->key(reftable_record_data(rec), dest); } -uint8_t reftable_record_type(struct reftable_record *rec) -{ - return rec->type; -} - int reftable_record_encode(struct reftable_record *rec, struct string_view dest, int hash_size) { @@ -1132,10 +1186,12 @@ uint8_t reftable_record_val_type(struct reftable_record *rec) } int reftable_record_decode(struct reftable_record *rec, struct strbuf key, - uint8_t extra, struct string_view src, int hash_size) + uint8_t extra, struct string_view src, int hash_size, + struct strbuf *scratch) { return reftable_record_vtable(rec)->decode(reftable_record_data(rec), - key, extra, src, hash_size); + key, extra, src, hash_size, + scratch); } void reftable_record_release(struct reftable_record *rec) @@ -1149,6 +1205,14 @@ int reftable_record_is_deletion(struct reftable_record *rec) reftable_record_data(rec)); } +int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b) +{ + if (a->type != b->type) + BUG("cannot compare reftable records of different type"); + return reftable_record_vtable(a)->cmp( + reftable_record_data(a), reftable_record_data(b)); +} + int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size) { if (a->type != b->type) @@ -1222,12 +1286,6 @@ int reftable_log_record_is_deletion(const struct reftable_log_record *log) return (log->value_type == REFTABLE_LOG_DELETION); } -void string_view_consume(struct string_view *s, int n) -{ - s->buf += n; - s->len -= n; -} - static void *reftable_record_data(struct reftable_record *rec) { switch (rec->type) { diff --git a/reftable/record.h b/reftable/record.h index e64ed30c80..d778133e6e 100644 --- a/reftable/record.h +++ b/reftable/record.h @@ -25,7 +25,11 @@ struct string_view { }; /* Advance `s.buf` by `n`, and decrease length. */ -void string_view_consume(struct string_view *s, int n); +static inline void string_view_consume(struct string_view *s, int n) +{ + s->buf += n; + s->len -= n; +} /* utilities for de/encoding varints */ @@ -51,7 +55,8 @@ struct reftable_record_vtable { /* decode data from `src` into the record. */ int (*decode)(void *rec, struct strbuf key, uint8_t extra, - struct string_view src, int hash_size); + struct string_view src, int hash_size, + struct strbuf *scratch); /* deallocate and null the record. */ void (*release)(void *rec); @@ -62,6 +67,12 @@ struct reftable_record_vtable { /* Are two records equal? This assumes they have the same type. Returns 0 for non-equal. */ int (*equal)(const void *a, const void *b, int hash_size); + /* + * Compare keys of two records with each other. The records must have + * the same type. + */ + int (*cmp)(const void *a, const void *b); + /* Print on stdout, for debugging. */ void (*print)(const void *rec, int hash_size); }; @@ -75,9 +86,18 @@ int reftable_encode_key(int *is_restart, struct string_view dest, struct strbuf prev_key, struct strbuf key, uint8_t extra); -/* Decode into `key` and `extra` from `in` */ -int reftable_decode_key(struct strbuf *key, uint8_t *extra, - struct strbuf last_key, struct string_view in); +/* Decode a record's key lengths. */ +int reftable_decode_keylen(struct string_view in, + uint64_t *prefix_len, + uint64_t *suffix_len, + uint8_t *extra); + +/* + * 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, + struct string_view in); /* reftable_index_record are used internally to speed up lookups. */ struct reftable_index_record { @@ -114,10 +134,10 @@ struct reftable_record { 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); -uint8_t reftable_record_type(struct reftable_record *rec); void 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); @@ -125,9 +145,14 @@ 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, uint8_t extra, struct string_view src, - int hash_size); + int hash_size, struct strbuf *scratch); int reftable_record_is_deletion(struct reftable_record *rec); +static inline uint8_t reftable_record_type(struct reftable_record *rec) +{ + return rec->type; +} + /* frees and zeroes out the embedded record */ void reftable_record_release(struct reftable_record *rec); diff --git a/reftable/record_test.c b/reftable/record_test.c index a86cff5526..c158ee79ff 100644 --- a/reftable/record_test.c +++ b/reftable/record_test.c @@ -99,6 +99,7 @@ static void set_hash(uint8_t *h, int j) static void test_reftable_ref_record_roundtrip(void) { + struct strbuf scratch = STRBUF_INIT; int i = 0; for (i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) { @@ -140,7 +141,7 @@ static void test_reftable_ref_record_roundtrip(void) EXPECT(n > 0); /* decode into a non-zero reftable_record to test for leaks. */ - m = reftable_record_decode(&out, key, i, dest, GIT_SHA1_RAWSZ); + m = reftable_record_decode(&out, key, i, dest, GIT_SHA1_RAWSZ, &scratch); EXPECT(n == m); EXPECT(reftable_ref_record_equal(&in.u.ref, &out.u.ref, @@ -150,6 +151,8 @@ static void test_reftable_ref_record_roundtrip(void) strbuf_release(&key); reftable_record_release(&out); } + + strbuf_release(&scratch); } static void test_reftable_log_record_equal(void) @@ -175,7 +178,6 @@ static void test_reftable_log_record_equal(void) static void test_reftable_log_record_roundtrip(void) { int i; - struct reftable_log_record in[] = { { .refname = xstrdup("refs/heads/master"), @@ -183,8 +185,6 @@ static void test_reftable_log_record_roundtrip(void) .value_type = REFTABLE_LOG_UPDATE, .value = { .update = { - .old_hash = reftable_malloc(GIT_SHA1_RAWSZ), - .new_hash = reftable_malloc(GIT_SHA1_RAWSZ), .name = xstrdup("han-wen"), .email = xstrdup("hanwen@google.com"), .message = xstrdup("test"), @@ -202,15 +202,10 @@ static void test_reftable_log_record_roundtrip(void) .refname = xstrdup("branch"), .update_index = 33, .value_type = REFTABLE_LOG_UPDATE, - .value = { - .update = { - .old_hash = reftable_malloc(GIT_SHA1_RAWSZ), - .new_hash = reftable_malloc(GIT_SHA1_RAWSZ), - /* rest of fields left empty. */ - }, - }, } }; + struct strbuf scratch = STRBUF_INIT; + set_test_hash(in[0].value.update.new_hash, 1); set_test_hash(in[0].value.update.old_hash, 2); set_test_hash(in[2].value.update.new_hash, 3); @@ -231,8 +226,6 @@ static void test_reftable_log_record_roundtrip(void) .value_type = REFTABLE_LOG_UPDATE, .value = { .update = { - .new_hash = reftable_calloc(GIT_SHA1_RAWSZ, 1), - .old_hash = reftable_calloc(GIT_SHA1_RAWSZ, 1), .name = xstrdup("old name"), .email = xstrdup("old@email"), .message = xstrdup("old message"), @@ -252,7 +245,7 @@ static void test_reftable_log_record_roundtrip(void) EXPECT(n >= 0); valtype = reftable_record_val_type(&rec); m = reftable_record_decode(&out, key, valtype, dest, - GIT_SHA1_RAWSZ); + GIT_SHA1_RAWSZ, &scratch); EXPECT(n == m); EXPECT(reftable_log_record_equal(&in[i], &out.u.log, @@ -261,6 +254,8 @@ static void test_reftable_log_record_roundtrip(void) strbuf_release(&key); reftable_record_release(&out); } + + strbuf_release(&scratch); } static void test_u24_roundtrip(void) @@ -295,7 +290,8 @@ static void test_key_roundtrip(void) EXPECT(!restart); EXPECT(n > 0); - m = reftable_decode_key(&roundtrip, &rt_extra, last_key, dest); + strbuf_addstr(&roundtrip, "refs/heads/master"); + m = reftable_decode_key(&roundtrip, &rt_extra, dest); EXPECT(n == m); EXPECT(0 == strbuf_cmp(&key, &roundtrip)); EXPECT(rt_extra == extra); @@ -309,23 +305,27 @@ static void test_reftable_obj_record_roundtrip(void) { uint8_t testHash1[GIT_SHA1_RAWSZ] = { 1, 2, 3, 4, 0 }; uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 }; - struct reftable_obj_record recs[3] = { { - .hash_prefix = testHash1, - .hash_prefix_len = 5, - .offsets = till9, - .offset_len = 3, - }, - { - .hash_prefix = testHash1, - .hash_prefix_len = 5, - .offsets = till9, - .offset_len = 9, - }, - { - .hash_prefix = testHash1, - .hash_prefix_len = 5, - } }; + struct reftable_obj_record recs[3] = { + { + .hash_prefix = testHash1, + .hash_prefix_len = 5, + .offsets = till9, + .offset_len = 3, + }, + { + .hash_prefix = testHash1, + .hash_prefix_len = 5, + .offsets = till9, + .offset_len = 9, + }, + { + .hash_prefix = testHash1, + .hash_prefix_len = 5, + }, + }; + struct strbuf scratch = STRBUF_INIT; int i = 0; + for (i = 0; i < ARRAY_SIZE(recs); i++) { uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -349,13 +349,15 @@ static void test_reftable_obj_record_roundtrip(void) EXPECT(n > 0); extra = reftable_record_val_type(&in); m = reftable_record_decode(&out, key, extra, dest, - GIT_SHA1_RAWSZ); + GIT_SHA1_RAWSZ, &scratch); EXPECT(n == m); EXPECT(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ)); strbuf_release(&key); reftable_record_release(&out); } + + strbuf_release(&scratch); } static void test_reftable_index_record_roundtrip(void) @@ -372,6 +374,7 @@ static void test_reftable_index_record_roundtrip(void) .buf = buffer, .len = sizeof(buffer), }; + struct strbuf scratch = STRBUF_INIT; struct strbuf key = STRBUF_INIT; struct reftable_record out = { .type = BLOCK_TYPE_INDEX, @@ -389,13 +392,15 @@ static void test_reftable_index_record_roundtrip(void) EXPECT(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, GIT_SHA1_RAWSZ, + &scratch); EXPECT(m == n); EXPECT(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ)); reftable_record_release(&out); strbuf_release(&key); + strbuf_release(&scratch); strbuf_release(&in.u.idx.last_key); } diff --git a/reftable/refname.c b/reftable/refname.c index 7570e4acf9..bbfde15754 100644 --- a/reftable/refname.c +++ b/reftable/refname.c @@ -12,15 +12,15 @@ #include "refname.h" #include "reftable-iterator.h" -struct find_arg { - char **names; - const char *want; +struct refname_needle_lesseq_args { + char **haystack; + const char *needle; }; -static int find_name(size_t k, void *arg) +static int refname_needle_lesseq(size_t k, void *_args) { - struct find_arg *f_arg = arg; - return strcmp(f_arg->names[k], f_arg->want) >= 0; + struct refname_needle_lesseq_args *args = _args; + return strcmp(args->needle, args->haystack[k]) <= 0; } static int modification_has_ref(struct modification *mod, const char *name) @@ -29,25 +29,23 @@ static int modification_has_ref(struct modification *mod, const char *name) int err = 0; if (mod->add_len > 0) { - struct find_arg arg = { - .names = mod->add, - .want = name, + struct refname_needle_lesseq_args args = { + .haystack = mod->add, + .needle = name, }; - int idx = binsearch(mod->add_len, find_name, &arg); - if (idx < mod->add_len && !strcmp(mod->add[idx], name)) { + size_t idx = binsearch(mod->add_len, refname_needle_lesseq, &args); + if (idx < mod->add_len && !strcmp(mod->add[idx], name)) return 0; - } } if (mod->del_len > 0) { - struct find_arg arg = { - .names = mod->del, - .want = name, + struct refname_needle_lesseq_args args = { + .haystack = mod->del, + .needle = name, }; - int idx = binsearch(mod->del_len, find_name, &arg); - if (idx < mod->del_len && !strcmp(mod->del[idx], name)) { + size_t idx = binsearch(mod->del_len, refname_needle_lesseq, &args); + if (idx < mod->del_len && !strcmp(mod->del[idx], name)) return 1; - } } err = reftable_table_read_ref(&mod->tab, name, &ref); @@ -73,11 +71,11 @@ static int modification_has_ref_with_prefix(struct modification *mod, int err = 0; if (mod->add_len > 0) { - struct find_arg arg = { - .names = mod->add, - .want = prefix, + struct refname_needle_lesseq_args args = { + .haystack = mod->add, + .needle = prefix, }; - int idx = binsearch(mod->add_len, find_name, &arg); + size_t idx = binsearch(mod->add_len, refname_needle_lesseq, &args); if (idx < mod->add_len && !strncmp(prefix, mod->add[idx], strlen(prefix))) goto done; @@ -92,15 +90,14 @@ static int modification_has_ref_with_prefix(struct modification *mod, goto done; if (mod->del_len > 0) { - struct find_arg arg = { - .names = mod->del, - .want = ref.refname, + struct refname_needle_lesseq_args args = { + .haystack = mod->del, + .needle = ref.refname, }; - int idx = binsearch(mod->del_len, find_name, &arg); + size_t idx = binsearch(mod->del_len, refname_needle_lesseq, &args); if (idx < mod->del_len && - !strcmp(ref.refname, mod->del[idx])) { + !strcmp(ref.refname, mod->del[idx])) continue; - } } if (strncmp(ref.refname, prefix, strlen(prefix))) { diff --git a/reftable/reftable-error.h b/reftable/reftable-error.h index 4c457aaaf8..e9b07c9f36 100644 --- a/reftable/reftable-error.h +++ b/reftable/reftable-error.h @@ -25,7 +25,7 @@ enum reftable_error { */ REFTABLE_NOT_EXIST_ERROR = -4, - /* Trying to write out-of-date data. */ + /* Trying to access locked data. */ REFTABLE_LOCK_ERROR = -5, /* Misuse of the API: @@ -57,6 +57,9 @@ enum reftable_error { /* Entry does not fit. This can happen when writing outsize reflog messages. */ REFTABLE_ENTRY_TOO_BIG_ERROR = -11, + + /* Trying to write out-of-date data. */ + REFTABLE_OUTDATED_ERROR = -12, }; /* convert the numeric error code to a string. The string should not be diff --git a/reftable/reftable-record.h b/reftable/reftable-record.h index bb6e99acd3..2a2943cd13 100644 --- a/reftable/reftable-record.h +++ b/reftable/reftable-record.h @@ -22,6 +22,7 @@ https://developers.google.com/open-source/licenses/bsd /* reftable_ref_record holds a ref database entry target_value */ struct reftable_ref_record { char *refname; /* Name of the ref, malloced. */ + size_t refname_cap; uint64_t update_index; /* Logical timestamp at which this value is * written */ @@ -73,6 +74,7 @@ int reftable_ref_record_equal(const struct reftable_ref_record *a, /* reftable_log_record holds a reflog entry */ struct reftable_log_record { char *refname; + size_t refname_cap; uint64_t update_index; /* logical timestamp of a transactional update. */ @@ -87,13 +89,14 @@ struct reftable_log_record { union { struct { - uint8_t *new_hash; - uint8_t *old_hash; + unsigned char new_hash[GIT_MAX_RAWSZ]; + unsigned char old_hash[GIT_MAX_RAWSZ]; char *name; char *email; uint64_t time; int16_t tz_offset; char *message; + size_t message_cap; } update; } value; }; diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h index 7c7cae5f99..155bf0bbe2 100644 --- a/reftable/reftable-writer.h +++ b/reftable/reftable-writer.h @@ -46,6 +46,9 @@ struct reftable_write_options { * is a single line, and add '\n' if missing. */ unsigned exact_log_message : 1; + + /* boolean: Prevent auto-compaction of tables. */ + unsigned disable_auto_compact : 1; }; /* reftable_block_stats holds statistics for a single block type */ diff --git a/reftable/stack.c b/reftable/stack.c index b64e55648a..80266bcbab 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -529,9 +529,9 @@ int reftable_stack_add(struct reftable_stack *st, { int err = stack_try_add(st, write, arg); if (err < 0) { - if (err == REFTABLE_LOCK_ERROR) { + if (err == REFTABLE_OUTDATED_ERROR) { /* Ignore error return, we want to propagate - REFTABLE_LOCK_ERROR. + REFTABLE_OUTDATED_ERROR. */ reftable_stack_reload(st); } @@ -590,9 +590,8 @@ static int reftable_stack_init_addition(struct reftable_addition *add, err = stack_uptodate(st); if (err < 0) goto done; - - if (err > 1) { - err = REFTABLE_LOCK_ERROR; + if (err > 0) { + err = REFTABLE_OUTDATED_ERROR; goto done; } @@ -681,8 +680,19 @@ int reftable_addition_commit(struct reftable_addition *add) if (err) goto done; - if (!add->stack->disable_auto_compact) + if (!add->stack->config.disable_auto_compact) { + /* + * Auto-compact the stack to keep the number of tables in + * control. It is possible that a concurrent writer is already + * trying to compact parts of the stack, which would lead to a + * `REFTABLE_LOCK_ERROR` because parts of the stack are locked + * already. This is a benign error though, so we ignore it. + */ err = reftable_stack_auto_compact(add->stack); + if (err < 0 && err != REFTABLE_LOCK_ERROR) + goto done; + err = 0; + } done: reftable_addition_close(add); @@ -713,10 +723,6 @@ static int stack_try_add(struct reftable_stack *st, int err = reftable_stack_init_addition(&add, st); if (err < 0) goto done; - if (err > 0) { - err = REFTABLE_LOCK_ERROR; - goto done; - } err = reftable_addition_add(&add, write_table, arg); if (err < 0) @@ -737,8 +743,9 @@ int reftable_addition_add(struct reftable_addition *add, struct strbuf tab_file_name = STRBUF_INIT; struct strbuf next_name = STRBUF_INIT; struct reftable_writer *wr = NULL; + struct tempfile *tab_file = NULL; int err = 0; - int tab_fd = 0; + int tab_fd; strbuf_reset(&next_name); format_name(&next_name, add->next_update_index, add->next_update_index); @@ -746,17 +753,20 @@ int reftable_addition_add(struct reftable_addition *add, stack_filename(&temp_tab_file_name, add->stack, next_name.buf); strbuf_addstr(&temp_tab_file_name, ".temp.XXXXXX"); - tab_fd = mkstemp(temp_tab_file_name.buf); - if (tab_fd < 0) { + tab_file = mks_tempfile(temp_tab_file_name.buf); + if (!tab_file) { err = REFTABLE_IO_ERROR; goto done; } if (add->stack->config.default_permissions) { - if (chmod(temp_tab_file_name.buf, add->stack->config.default_permissions)) { + if (chmod(get_tempfile_path(tab_file), + add->stack->config.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->config); err = write_table(wr, arg); @@ -771,14 +781,13 @@ int reftable_addition_add(struct reftable_addition *add, if (err < 0) goto done; - err = close(tab_fd); - tab_fd = 0; + err = close_tempfile_gently(tab_file); if (err < 0) { err = REFTABLE_IO_ERROR; goto done; } - err = stack_check_addition(add->stack, temp_tab_file_name.buf); + err = stack_check_addition(add->stack, get_tempfile_path(tab_file)); if (err < 0) goto done; @@ -789,14 +798,13 @@ int reftable_addition_add(struct reftable_addition *add, 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); /* On windows, this relies on rand() picking a unique destination name. Maybe we should do retry loop as well? */ - err = rename(temp_tab_file_name.buf, tab_file_name.buf); + err = rename_tempfile(&tab_file, tab_file_name.buf); if (err < 0) { err = REFTABLE_IO_ERROR; goto done; @@ -806,14 +814,7 @@ int reftable_addition_add(struct reftable_addition *add, add->new_tables_cap); add->new_tables[add->new_tables_len++] = strbuf_detach(&next_name, NULL); done: - if (tab_fd > 0) { - close(tab_fd); - tab_fd = 0; - } - if (temp_tab_file_name.len > 0) { - unlink(temp_tab_file_name.buf); - } - + delete_tempfile(&tab_file); strbuf_release(&temp_tab_file_name); strbuf_release(&tab_file_name); strbuf_release(&next_name); @@ -832,51 +833,56 @@ 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 strbuf *temp_tab, - struct reftable_log_expiry_config *config) + struct reftable_log_expiry_config *config, + struct tempfile **tab_file_out) { struct strbuf next_name = STRBUF_INIT; - int tab_fd = -1; + struct strbuf tab_file_path = STRBUF_INIT; struct reftable_writer *wr = NULL; - int err = 0; + struct tempfile *tab_file; + int tab_fd, err = 0; 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"); - stack_filename(temp_tab, st, next_name.buf); - strbuf_addstr(temp_tab, ".temp.XXXXXX"); + tab_file = mks_tempfile(tab_file_path.buf); + if (!tab_file) { + err = REFTABLE_IO_ERROR; + goto done; + } + tab_fd = get_tempfile_fd(tab_file); - tab_fd = mkstemp(temp_tab->buf); if (st->config.default_permissions && - chmod(temp_tab->buf, st->config.default_permissions) < 0) { + chmod(get_tempfile_path(tab_file), st->config.default_permissions) < 0) { err = REFTABLE_IO_ERROR; goto done; } - wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, &tab_fd, &st->config); - + wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, + &tab_fd, &st->config); err = stack_write_compact(st, wr, first, last, config); if (err < 0) goto done; + err = reftable_writer_close(wr); if (err < 0) goto done; - err = close(tab_fd); - tab_fd = 0; + err = close_tempfile_gently(tab_file); + if (err < 0) + goto done; + + *tab_file_out = tab_file; + tab_file = NULL; done: + delete_tempfile(&tab_file); reftable_writer_free(wr); - if (tab_fd > 0) { - close(tab_fd); - tab_fd = 0; - } - if (err != 0 && temp_tab->len > 0) { - unlink(temp_tab->buf); - strbuf_release(temp_tab); - } strbuf_release(&next_name); + strbuf_release(&tab_file_path); return err; } @@ -978,217 +984,213 @@ done: return err; } -/* < 0: error. 0 == OK, > 0 attempt failed; could retry. */ +/* + * Compact all tables in the range `[first, last)` into a single new table. + * + * This function returns `0` on success or a code `< 0` on failure. When the + * stack or any of the tables in the specified range are already locked then + * this function returns `REFTABLE_LOCK_ERROR`. This is a benign error that + * callers can either ignore, or they may choose to retry compaction after some + * amount of time. + */ static int stack_compact_range(struct reftable_stack *st, size_t first, size_t last, struct reftable_log_expiry_config *expiry) { - char **delete_on_success = NULL, **subtable_locks = NULL, **listp = NULL; - struct strbuf temp_tab_file_name = STRBUF_INIT; + struct strbuf tables_list_buf = STRBUF_INIT; struct strbuf new_table_name = STRBUF_INIT; - struct strbuf lock_file_name = STRBUF_INIT; - struct strbuf ref_list_contents = STRBUF_INIT; struct strbuf new_table_path = STRBUF_INIT; - size_t i, j, compact_count; - int err = 0; - int have_lock = 0; - int lock_file_fd = -1; - int is_empty_table = 0; + 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; + int is_empty_table = 0, err = 0; + size_t i; if (first > last || (!expiry && first == last)) { err = 0; goto done; } - compact_count = last - first + 1; - REFTABLE_CALLOC_ARRAY(delete_on_success, compact_count + 1); - REFTABLE_CALLOC_ARRAY(subtable_locks, compact_count + 1); - st->stats.attempts++; - strbuf_reset(&lock_file_name); - strbuf_addstr(&lock_file_name, st->list_file); - strbuf_addstr(&lock_file_name, ".lock"); - - lock_file_fd = - open(lock_file_name.buf, O_EXCL | O_CREAT | O_WRONLY, 0666); - if (lock_file_fd < 0) { - if (errno == EEXIST) { - err = 1; - } else { + /* + * 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); + if (err < 0) { + if (errno == EEXIST) + err = REFTABLE_LOCK_ERROR; + else err = REFTABLE_IO_ERROR; - } goto done; } - /* Don't want to write to the lock for now. */ - close(lock_file_fd); - lock_file_fd = -1; - have_lock = 1; err = stack_uptodate(st); - if (err != 0) + if (err) goto done; - for (i = first, j = 0; i <= last; i++) { - struct strbuf subtab_file_name = STRBUF_INIT; - struct strbuf subtab_lock = STRBUF_INIT; - int sublock_file_fd = -1; - - stack_filename(&subtab_file_name, st, - reader_name(st->readers[i])); - - strbuf_reset(&subtab_lock); - strbuf_addbuf(&subtab_lock, &subtab_file_name); - strbuf_addstr(&subtab_lock, ".lock"); - - sublock_file_fd = open(subtab_lock.buf, - O_EXCL | O_CREAT | O_WRONLY, 0666); - if (sublock_file_fd >= 0) { - close(sublock_file_fd); - } else if (sublock_file_fd < 0) { - if (errno == EEXIST) { - err = 1; - } else { + /* + * Lock all tables in the user-provided range. This is the slice of our + * stack which we'll compact. + */ + REFTABLE_CALLOC_ARRAY(table_locks, last - first + 1); + for (i = first; i <= last; i++) { + stack_filename(&table_name, st, reader_name(st->readers[i])); + + err = hold_lock_file_for_update(&table_locks[i - first], + table_name.buf, LOCK_NO_DEREF); + if (err < 0) { + if (errno == EEXIST) + err = REFTABLE_LOCK_ERROR; + else err = REFTABLE_IO_ERROR; - } + goto done; } - subtable_locks[j] = subtab_lock.buf; - delete_on_success[j] = subtab_file_name.buf; - j++; - - if (err != 0) + /* + * We need to close the lockfiles as we might otherwise easily + * run into file descriptor exhaustion when we compress a lot + * of tables. + */ + err = close_lock_file_gently(&table_locks[i - first]); + if (err < 0) { + err = REFTABLE_IO_ERROR; goto done; + } } - err = unlink(lock_file_name.buf); - if (err < 0) + /* + * We have locked all tables in our range and can thus release the + * "tables.list" lock while compacting the locked tables. This allows + * concurrent updates to the stack to proceed. + */ + err = rollback_lock_file(&tables_list_lock); + if (err < 0) { + err = REFTABLE_IO_ERROR; goto done; - have_lock = 0; - - err = stack_compact_locked(st, first, last, &temp_tab_file_name, - expiry); - /* Compaction + tombstones can create an empty table out of non-empty - * tables. */ - is_empty_table = (err == REFTABLE_EMPTY_TABLE_ERROR); - if (is_empty_table) { - err = 0; } - if (err < 0) - goto done; - lock_file_fd = - open(lock_file_name.buf, O_EXCL | O_CREAT | O_WRONLY, 0666); - if (lock_file_fd < 0) { - if (errno == EEXIST) { - err = 1; - } else { + /* + * Compact the now-locked tables into a new table. Note that compacting + * these tables may end up with an empty new table in case tombstones + * end up cancelling out all refs in that range. + */ + err = stack_compact_locked(st, first, last, expiry, &new_table); + if (err < 0) { + if (err != REFTABLE_EMPTY_TABLE_ERROR) + goto done; + is_empty_table = 1; + } + + /* + * Now that we have written the new, compacted table we need to re-lock + * "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); + if (err < 0) { + if (errno == EEXIST) + err = REFTABLE_LOCK_ERROR; + else err = REFTABLE_IO_ERROR; - } goto done; } - have_lock = 1; + if (st->config.default_permissions) { - if (chmod(lock_file_name.buf, st->config.default_permissions) < 0) { + if (chmod(get_lock_file_path(&tables_list_lock), + st->config.default_permissions) < 0) { err = REFTABLE_IO_ERROR; goto done; } } - 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); - + /* + * If the resulting compacted table is not empty, then we need to move + * it into place now. + */ if (!is_empty_table) { - /* retry? */ - err = rename(temp_tab_file_name.buf, new_table_path.buf); + 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 = rename_tempfile(&new_table, new_table_path.buf); if (err < 0) { err = REFTABLE_IO_ERROR; goto done; } } - for (i = 0; i < first; i++) { - strbuf_addstr(&ref_list_contents, st->readers[i]->name); - strbuf_addstr(&ref_list_contents, "\n"); - } - if (!is_empty_table) { - strbuf_addbuf(&ref_list_contents, &new_table_name); - strbuf_addstr(&ref_list_contents, "\n"); - } - for (i = last + 1; i < st->merged->stack_len; i++) { - strbuf_addstr(&ref_list_contents, st->readers[i]->name); - strbuf_addstr(&ref_list_contents, "\n"); - } - - err = write_in_full(lock_file_fd, ref_list_contents.buf, ref_list_contents.len); - if (err < 0) { - err = REFTABLE_IO_ERROR; - unlink(new_table_path.buf); - goto done; - } - - err = fsync_component(FSYNC_COMPONENT_REFERENCE, lock_file_fd); + /* + * Write the new "tables.list" contents with the compacted table we + * 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), + tables_list_buf.buf, tables_list_buf.len); if (err < 0) { err = REFTABLE_IO_ERROR; unlink(new_table_path.buf); goto done; } - err = close(lock_file_fd); - lock_file_fd = -1; + err = fsync_component(FSYNC_COMPONENT_REFERENCE, get_lock_file_fd(&tables_list_lock)); if (err < 0) { err = REFTABLE_IO_ERROR; unlink(new_table_path.buf); goto done; } - err = rename(lock_file_name.buf, st->list_file); + err = commit_lock_file(&tables_list_lock); if (err < 0) { err = REFTABLE_IO_ERROR; unlink(new_table_path.buf); goto done; } - have_lock = 0; - /* Reload the stack before deleting. On windows, we can only delete the - files after we closed them. - */ + /* + * Reload the stack before deleting the compacted tables. We can only + * delete the files after we closed them on Windows, so this needs to + * happen first. + */ err = reftable_stack_reload_maybe_reuse(st, first < last); + if (err < 0) + goto done; - listp = delete_on_success; - while (*listp) { - if (strcmp(*listp, new_table_path.buf)) { - unlink(*listp); - } - listp++; + /* + * 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); } done: - free_names(delete_on_success); + rollback_lock_file(&tables_list_lock); + for (i = first; table_locks && i <= last; i++) + rollback_lock_file(&table_locks[i - first]); + reftable_free(table_locks); - if (subtable_locks) { - listp = subtable_locks; - while (*listp) { - unlink(*listp); - listp++; - } - free_names(subtable_locks); - } - if (lock_file_fd >= 0) { - close(lock_file_fd); - lock_file_fd = -1; - } - if (have_lock) { - unlink(lock_file_name.buf); - } + delete_tempfile(&new_table); strbuf_release(&new_table_name); strbuf_release(&new_table_path); - strbuf_release(&ref_list_contents); - strbuf_release(&temp_tab_file_name); - strbuf_release(&lock_file_name); + + strbuf_release(&tables_list_buf); + strbuf_release(&table_name); return err; } @@ -1204,7 +1206,7 @@ static int stack_compact_range_stats(struct reftable_stack *st, struct reftable_log_expiry_config *config) { int err = stack_compact_range(st, first, last, config); - if (err > 0) + if (err == REFTABLE_LOCK_ERROR) st->stats.failures++; return err; } @@ -1214,75 +1216,76 @@ static int segment_size(struct segment *s) return s->end - s->start; } -int fastlog2(uint64_t sz) -{ - int l = 0; - if (sz == 0) - return 0; - for (; sz; sz /= 2) { - l++; - } - return l - 1; -} - -struct segment *sizes_to_segments(size_t *seglen, uint64_t *sizes, size_t n) -{ - struct segment *segs = reftable_calloc(n, sizeof(*segs)); - struct segment cur = { 0 }; - size_t next = 0, i; - - if (n == 0) { - *seglen = 0; - return segs; - } - for (i = 0; i < n; i++) { - int log = fastlog2(sizes[i]); - if (cur.log != log && cur.bytes > 0) { - struct segment fresh = { - .start = i, - }; - - segs[next++] = cur; - cur = fresh; - } - - cur.log = log; - cur.end = i + 1; - cur.bytes += sizes[i]; - } - segs[next++] = cur; - *seglen = next; - return segs; -} - struct segment suggest_compaction_segment(uint64_t *sizes, size_t n) { - struct segment min_seg = { - .log = 64, - }; - struct segment *segs; - size_t seglen = 0, i; - - segs = sizes_to_segments(&seglen, sizes, n); - for (i = 0; i < seglen; i++) { - if (segment_size(&segs[i]) == 1) - continue; + struct segment seg = { 0 }; + uint64_t bytes; + size_t i; - if (segs[i].log < min_seg.log) - min_seg = segs[i]; - } + /* + * If there are no tables or only a single one then we don't have to + * compact anything. The sequence is geometric by definition already. + */ + if (n <= 1) + return seg; - while (min_seg.start > 0) { - size_t prev = min_seg.start - 1; - if (fastlog2(min_seg.bytes) < fastlog2(sizes[prev])) + /* + * Find the ending table of the compaction segment needed to restore the + * geometric sequence. Note that the segment end is exclusive. + * + * To do so, we iterate backwards starting from the most recent table + * until a valid segment end is found. If the preceding table is smaller + * than the current table multiplied by the geometric factor (2), the + * compaction segment end has been identified. + * + * Tables after the ending point are not added to the byte count because + * they are already valid members of the geometric sequence. Due to the + * properties of a geometric sequence, it is not possible for the sum of + * these tables to exceed the value of the ending point table. + * + * Example table size sequence requiring no compaction: + * 64, 32, 16, 8, 4, 2, 1 + * + * Example table size sequence where compaction segment end is set to + * the last table. Since the segment end is exclusive, the last table is + * excluded during subsequent compaction and the table with size 3 is + * the final table included: + * 64, 32, 16, 8, 4, 3, 1 + */ + for (i = n - 1; i > 0; i--) { + if (sizes[i - 1] < sizes[i] * 2) { + seg.end = i + 1; + bytes = sizes[i]; break; + } + } + + /* + * Find the starting table of the compaction segment by iterating + * through the remaining tables and keeping track of the accumulated + * size of all tables seen from the segment end table. The previous + * table is compared to the accumulated size because the tables from the + * segment end are merged backwards recursively. + * + * Note that we keep iterating even after we have found the first + * starting point. This is because there may be tables in the stack + * preceding that first starting point which violate the geometric + * sequence. + * + * Example compaction segment start set to table with size 32: + * 128, 32, 16, 8, 4, 3, 1 + */ + for (; i > 0; i--) { + uint64_t curr = bytes; + bytes += sizes[i - 1]; - min_seg.start = prev; - min_seg.bytes += sizes[prev]; + if (sizes[i - 1] < curr * 2) { + seg.start = i - 1; + seg.bytes = bytes; + } } - reftable_free(segs); - return min_seg; + return seg; } static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st) diff --git a/reftable/stack.h b/reftable/stack.h index d919455669..d43efa4760 100644 --- a/reftable/stack.h +++ b/reftable/stack.h @@ -19,7 +19,6 @@ struct reftable_stack { int list_fd; char *reftable_dir; - int disable_auto_compact; struct reftable_write_options config; @@ -33,12 +32,9 @@ int read_lines(const char *filename, char ***lines); struct segment { size_t start, end; - int log; uint64_t bytes; }; -int fastlog2(uint64_t sz); -struct segment *sizes_to_segments(size_t *seglen, uint64_t *sizes, size_t n); struct segment suggest_compaction_segment(uint64_t *sizes, size_t n); #endif diff --git a/reftable/stack_test.c b/reftable/stack_test.c index 509f486623..1df3ffce52 100644 --- a/reftable/stack_test.c +++ b/reftable/stack_test.c @@ -38,7 +38,17 @@ static int count_dir_entries(const char *dirname) return 0; while ((d = readdir(dir))) { - if (!strcmp(d->d_name, "..") || !strcmp(d->d_name, ".")) + /* + * 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++; } @@ -232,7 +242,7 @@ static void test_reftable_stack_uptodate(void) EXPECT_ERR(err); err = reftable_stack_add(st2, &write_test_ref, &ref2); - EXPECT(err == REFTABLE_LOCK_ERROR); + EXPECT(err == REFTABLE_OUTDATED_ERROR); err = reftable_stack_reload(st2); EXPECT_ERR(err); @@ -315,7 +325,7 @@ static void test_reftable_stack_transaction_api_performs_auto_compaction(void) * we can ensure that we indeed honor this setting and have * better control over when exactly auto compaction runs. */ - st->disable_auto_compact = i != n; + st->config.disable_auto_compact = i != n; err = reftable_stack_new_addition(&add, st); EXPECT_ERR(err); @@ -343,6 +353,49 @@ static void test_reftable_stack_transaction_api_performs_auto_compaction(void) clear_dir(dir); } +static void test_reftable_stack_auto_compaction_fails_gracefully(void) +{ + struct reftable_ref_record ref = { + .refname = "refs/heads/master", + .update_index = 1, + .value_type = REFTABLE_REF_VAL1, + .value.val1 = {0x01}, + }; + struct reftable_write_options cfg = {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, cfg); + 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 void test_reftable_stack_validate_refname(void) { struct reftable_write_options cfg = { 0 }; @@ -444,6 +497,7 @@ static void test_reftable_stack_add(void) struct reftable_write_options cfg = { .exact_log_message = 1, .default_permissions = 0660, + .disable_auto_compact = 1, }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); @@ -455,7 +509,6 @@ static void test_reftable_stack_add(void) err = reftable_new_stack(&st, dir, cfg); EXPECT_ERR(err); - st->disable_auto_compact = 1; for (i = 0; i < N; i++) { char buf[256]; @@ -468,8 +521,6 @@ static void test_reftable_stack_add(void) logs[i].refname = xstrdup(buf); logs[i].update_index = N + i + 1; logs[i].value_type = REFTABLE_LOG_UPDATE; - - logs[i].value.update.new_hash = reftable_malloc(GIT_SHA1_RAWSZ); logs[i].value.update.email = xstrdup("identity@invalid"); set_test_hash(logs[i].value.update.new_hash, i); } @@ -547,16 +598,17 @@ static void test_reftable_stack_log_normalize(void) }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); - - uint8_t h1[GIT_SHA1_RAWSZ] = { 0x01 }, h2[GIT_SHA1_RAWSZ] = { 0x02 }; - - struct reftable_log_record input = { .refname = "branch", - .update_index = 1, - .value_type = REFTABLE_LOG_UPDATE, - .value = { .update = { - .new_hash = h1, - .old_hash = h2, - } } }; + struct reftable_log_record input = { + .refname = "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, }; @@ -627,8 +679,6 @@ static void test_reftable_stack_tombstone(void) logs[i].update_index = 42; if (i % 2 == 0) { logs[i].value_type = REFTABLE_LOG_UPDATE; - logs[i].value.update.new_hash = - reftable_malloc(GIT_SHA1_RAWSZ); set_test_hash(logs[i].value.update.new_hash, i); logs[i].value.update.email = xstrdup("identity@invalid"); @@ -720,59 +770,13 @@ static void test_reftable_stack_hash_id(void) clear_dir(dir); } -static void test_log2(void) -{ - EXPECT(1 == fastlog2(3)); - EXPECT(2 == fastlog2(4)); - EXPECT(2 == fastlog2(5)); -} - -static void test_sizes_to_segments(void) -{ - uint64_t sizes[] = { 2, 3, 4, 5, 7, 9 }; - /* .................0 1 2 3 4 5 */ - - size_t seglen = 0; - struct segment *segs = - sizes_to_segments(&seglen, sizes, ARRAY_SIZE(sizes)); - EXPECT(segs[2].log == 3); - EXPECT(segs[2].start == 5); - EXPECT(segs[2].end == 6); - - EXPECT(segs[1].log == 2); - EXPECT(segs[1].start == 2); - EXPECT(segs[1].end == 5); - reftable_free(segs); -} - -static void test_sizes_to_segments_empty(void) -{ - size_t seglen = 0; - struct segment *segs = sizes_to_segments(&seglen, NULL, 0); - EXPECT(seglen == 0); - reftable_free(segs); -} - -static void test_sizes_to_segments_all_equal(void) -{ - uint64_t sizes[] = { 5, 5 }; - size_t seglen = 0; - struct segment *segs = - sizes_to_segments(&seglen, sizes, ARRAY_SIZE(sizes)); - EXPECT(seglen == 1); - EXPECT(segs[0].start == 0); - EXPECT(segs[0].end == 2); - reftable_free(segs); -} - static void test_suggest_compaction_segment(void) { - uint64_t sizes[] = { 128, 64, 17, 16, 9, 9, 9, 16, 16 }; - /* .................0 1 2 3 4 5 6 */ + uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 }; struct segment min = suggest_compaction_segment(sizes, ARRAY_SIZE(sizes)); - EXPECT(min.start == 2); - EXPECT(min.end == 7); + EXPECT(min.start == 1); + EXPECT(min.end == 10); } static void test_suggest_compaction_segment_nothing(void) @@ -810,7 +814,6 @@ static void test_reflog_expire(void) logs[i].update_index = i; logs[i].value_type = REFTABLE_LOG_UPDATE; logs[i].value.update.time = i; - logs[i].value.update.new_hash = reftable_malloc(GIT_SHA1_RAWSZ); logs[i].value.update.email = xstrdup("identity@invalid"); set_test_hash(logs[i].value.update.new_hash, i); } @@ -884,9 +887,21 @@ static void test_empty_add(void) 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 cfg = { 0 }; + struct reftable_write_options cfg = { + .disable_auto_compact = 1, + }; struct reftable_stack *st = NULL; char *dir = get_tmp_dir(__LINE__); @@ -896,7 +911,6 @@ static void test_reftable_stack_auto_compaction(void) err = reftable_new_stack(&st, dir, cfg); EXPECT_ERR(err); - st->disable_auto_compact = 1; /* call manually below for coverage. */ for (i = 0; i < N; i++) { char name[100]; struct reftable_ref_record ref = { @@ -945,7 +959,7 @@ static void test_reftable_stack_add_performs_auto_compaction(void) * we can ensure that we indeed honor this setting and have * better control over when exactly auto compaction runs. */ - st->disable_auto_compact = i != n; + st->config.disable_auto_compact = i != n; strbuf_reset(&refname); strbuf_addf(&refname, "branch-%04d", i); @@ -1072,7 +1086,6 @@ static void test_reftable_stack_compaction_concurrent_clean(void) int stack_test_main(int argc, const char *argv[]) { RUN_TEST(test_empty_add); - RUN_TEST(test_log2); RUN_TEST(test_names_equal); RUN_TEST(test_parse_names); RUN_TEST(test_read_file); @@ -1089,12 +1102,10 @@ int stack_test_main(int argc, const char *argv[]) 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_reftable_stack_validate_refname); - RUN_TEST(test_sizes_to_segments); - RUN_TEST(test_sizes_to_segments_all_equal); - RUN_TEST(test_sizes_to_segments_empty); RUN_TEST(test_suggest_compaction_segment); RUN_TEST(test_suggest_compaction_segment_nothing); return 0; diff --git a/reftable/system.h b/reftable/system.h index 6b74a81514..5d8b6dede5 100644 --- a/reftable/system.h +++ b/reftable/system.h @@ -12,7 +12,9 @@ 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-ll.h" /* hash ID, sizes.*/ #include "dir.h" /* remove_dir_recursively, for tests.*/ diff --git a/remote-curl.c b/remote-curl.c index 1161dc7fed..0b6d7815fd 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -1,4 +1,5 @@ #include "git-compat-util.h" +#include "git-curl-compat.h" #include "config.h" #include "environment.h" #include "gettext.h" @@ -211,14 +212,9 @@ static int set_option(const char *name, const char *value) options.filter = xstrdup(value); return 0; } else if (!strcmp(name, "object-format")) { - int algo; options.object_format = 1; - if (strcmp(value, "true")) { - algo = hash_algo_by_name(value); - if (algo == GIT_HASH_UNKNOWN) - die("unknown object format '%s'", value); - options.hash_algo = &hash_algos[algo]; - } + if (strcmp(value, "true")) + die(_("unknown value for object-format: %s"), value); return 0; } else { return 1 /* unsupported */; @@ -960,7 +956,9 @@ retry: /* The request body is large and the size cannot be predicted. * We must use chunked encoding to send it. */ +#ifdef GIT_CURL_NEED_TRANSFER_ENCODING_HEADER headers = curl_slist_append(headers, "Transfer-Encoding: chunked"); +#endif rpc->initial_buffer = 1; curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out); curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc); @@ -105,7 +105,7 @@ static int remotes_hash_cmp(const void *cmp_data UNUSED, b = container_of(entry_or_key, const struct remote, ent); if (key) - return strncmp(a->name, key->str, key->len) || a->name[key->len]; + return !!xstrncmpz(a->name, key->str, key->len); else return strcmp(a->name, b->name); } @@ -189,8 +189,7 @@ static int branches_hash_cmp(const void *cmp_data UNUSED, b = container_of(entry_or_key, const struct branch, ent); if (key) - return strncmp(a->name, key->str, key->len) || - a->name[key->len]; + return !!xstrncmpz(a->name, key->str, key->len); else return strcmp(a->name, b->name); } @@ -2680,7 +2679,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote) if (MERGE_BASES_BATCH_SIZE < size) size = MERGE_BASES_BATCH_SIZE; - if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk))) + if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk, 0))) break; } diff --git a/repository.c b/repository.c index 7aacb51b65..e15b416944 100644 --- a/repository.c +++ b/repository.c @@ -14,6 +14,7 @@ #include "read-cache-ll.h" #include "remote.h" #include "setup.h" +#include "loose.h" #include "submodule-config.h" #include "sparse-index.h" #include "trace2.h" @@ -104,6 +105,15 @@ void repo_set_hash_algo(struct repository *repo, int hash_algo) repo->hash_algo = &hash_algos[hash_algo]; } +void repo_set_compat_hash_algo(struct repository *repo, int algo) +{ + if (hash_algo_by_ptr(repo->hash_algo) == algo) + BUG("hash_algo and compat_hash_algo match"); + repo->compat_hash_algo = algo ? &hash_algos[algo] : NULL; + if (repo->compat_hash_algo) + repo_read_loose_object_map(repo); +} + void repo_set_ref_storage_format(struct repository *repo, unsigned int format) { repo->ref_storage_format = format; @@ -189,6 +199,7 @@ int repo_init(struct repository *repo, goto error; repo_set_hash_algo(repo, format.hash_algo); + 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; @@ -199,6 +210,9 @@ int repo_init(struct repository *repo, if (worktree) repo_set_worktree(repo, worktree); + if (repo->compat_hash_algo) + repo_read_loose_object_map(repo); + clear_repository_format(&format); return 0; diff --git a/repository.h b/repository.h index 21949c5a17..268436779c 100644 --- a/repository.h +++ b/repository.h @@ -24,8 +24,9 @@ enum fetch_negotiation_setting { FETCH_NEGOTIATION_NOOP, }; -#define REF_STORAGE_FORMAT_UNKNOWN 0 -#define REF_STORAGE_FORMAT_FILES 1 +#define REF_STORAGE_FORMAT_UNKNOWN 0 +#define REF_STORAGE_FORMAT_FILES 1 +#define REF_STORAGE_FORMAT_REFTABLE 2 struct repo_settings { int initialized; @@ -162,6 +163,9 @@ struct repository { /* Repository's current hash algorithm, as serialized on disk. */ const struct git_hash_algo *hash_algo; + /* Repository's compatibility hash algorithm. */ + const struct git_hash_algo *compat_hash_algo; + /* Repository's reference storage format, as serialized on disk. */ unsigned int ref_storage_format; @@ -204,6 +208,7 @@ void repo_set_gitdir(struct repository *repo, const char *root, const struct set_gitdir_args *extra_args); void repo_set_worktree(struct repository *repo, const char *path); void repo_set_hash_algo(struct repository *repo, int algo); +void repo_set_compat_hash_algo(struct repository *repo, int compat_algo); void repo_set_ref_storage_format(struct repository *repo, unsigned int format); void initialize_the_repository(void); RESULT_MUST_BE_USED @@ -219,6 +219,11 @@ static void read_rr(struct repository *r, struct string_list *rr) buf.buf[hexsz] = '\0'; id = new_rerere_id_hex(buf.buf); id->variant = variant; + /* + * make sure id->collection->status has enough space + * for the variant we are interested in + */ + fit_variant(id->collection, variant); string_list_insert(rr, path)->util = id; } strbuf_release(&buf); @@ -157,6 +157,11 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts) } tree = parse_tree_indirect(oid); + if (!tree) { + ret = error(_("unable to read tree (%s)"), oid_to_hex(oid)); + goto leave_reset_head; + } + prime_cache_tree(r, r->index, tree); if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0) { diff --git a/revision.c b/revision.c index 2424c9bd67..7e45f765d9 100644 --- a/revision.c +++ b/revision.c @@ -81,7 +81,7 @@ static void mark_tree_contents_uninteresting(struct repository *r, if (parse_tree_gently(tree, 1) < 0) return; - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { switch (object_type(entry.mode)) { case OBJ_TREE: @@ -188,7 +188,7 @@ static void add_children_by_path(struct repository *r, if (parse_tree_gently(tree, 1) < 0) return; - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { switch (object_type(entry.mode)) { case OBJ_TREE: @@ -381,13 +381,18 @@ static struct object *get_reference(struct rev_info *revs, const char *name, object = parse_object_with_flags(revs->repo, oid, revs->verify_objects ? 0 : - PARSE_OBJECT_SKIP_HASH_CHECK); + PARSE_OBJECT_SKIP_HASH_CHECK | + PARSE_OBJECT_DISCARD_TREE); if (!object) { if (revs->ignore_missing) - return object; + return NULL; if (revs->exclude_promisor_objects && is_promisor_object(oid)) return NULL; + if (revs->do_not_die_on_missing_objects) { + oidset_insert(&revs->missing_commits, oid); + return NULL; + } die("bad object %s", name); } object->flags |= flags; @@ -415,15 +420,21 @@ static struct commit *handle_commit(struct rev_info *revs, */ while (object->type == OBJ_TAG) { struct tag *tag = (struct tag *) object; + struct object_id *oid; if (revs->tag_objects && !(flags & UNINTERESTING)) add_pending_object(revs, object, tag->tag); - object = parse_object(revs->repo, get_tagged_oid(tag)); + oid = get_tagged_oid(tag); + object = parse_object(revs->repo, oid); if (!object) { if (revs->ignore_missing_links || (flags & UNINTERESTING)) return NULL; if (revs->exclude_promisor_objects && is_promisor_object(&tag->tagged->oid)) return NULL; + if (revs->do_not_die_on_missing_objects && oid) { + oidset_insert(&revs->missing_commits, oid); + return NULL; + } die("bad object %s", oid_to_hex(&tag->tagged->oid)); } object->flags |= flags; @@ -1686,9 +1697,7 @@ static int handle_one_reflog_ent(struct object_id *ooid, struct object_id *noid, return 0; } -static int handle_one_reflog(const char *refname_in_wt, - const struct object_id *oid UNUSED, - int flag UNUSED, void *cb_data) +static int handle_one_reflog(const char *refname_in_wt, void *cb_data) { struct all_refs_cb *cb = cb_data; struct strbuf refname = STRBUF_INIT; @@ -1947,6 +1956,7 @@ void repo_init_revisions(struct repository *r, init_display_notes(&revs->notes_opt); list_objects_filter_init(&revs->filter); init_ref_exclusions(&revs->ref_excludes); + oidset_init(&revs->missing_commits, 0); } static void add_pending_commit_list(struct rev_info *revs, @@ -1961,11 +1971,31 @@ static void add_pending_commit_list(struct rev_info *revs, } } +static const char *lookup_other_head(struct object_id *oid) +{ + int i; + static const char *const other_head[] = { + "MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "REBASE_HEAD" + }; + + for (i = 0; i < ARRAY_SIZE(other_head); i++) + if (!read_ref_full(other_head[i], + RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + oid, NULL)) { + if (is_null_oid(oid)) + die(_("%s exists but is a symbolic ref"), other_head[i]); + return other_head[i]; + } + + die(_("--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD or REBASE_HEAD")); +} + static void prepare_show_merge(struct rev_info *revs) { - struct commit_list *bases; + struct commit_list *bases = NULL; struct commit *head, *other; struct object_id oid; + const char *other_name; const char **prune = NULL; int i, prune_num = 1; /* counting terminating NULL */ struct index_state *istate = revs->repo->index; @@ -1973,12 +2003,12 @@ static void prepare_show_merge(struct rev_info *revs) if (repo_get_oid(the_repository, "HEAD", &oid)) die("--merge without HEAD?"); head = lookup_commit_or_die(&oid, "HEAD"); - if (repo_get_oid(the_repository, "MERGE_HEAD", &oid)) - die("--merge without MERGE_HEAD?"); - other = lookup_commit_or_die(&oid, "MERGE_HEAD"); + other_name = lookup_other_head(&oid); + other = lookup_commit_or_die(&oid, other_name); add_pending_object(revs, &head->object, "HEAD"); - add_pending_object(revs, &other->object, "MERGE_HEAD"); - bases = repo_get_merge_bases(the_repository, head, other); + add_pending_object(revs, &other->object, other_name); + if (repo_get_merge_bases(the_repository, head, other, &bases) < 0) + exit(128); add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM); add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM); free_commit_list(bases); @@ -2066,14 +2096,17 @@ static int handle_dotdot_1(const char *arg, char *dotdot, } else { /* A...B -- find merge bases between the two */ struct commit *a, *b; - struct commit_list *exclude; + struct commit_list *exclude = NULL; a = lookup_commit_reference(revs->repo, &a_obj->oid); b = lookup_commit_reference(revs->repo, &b_obj->oid); if (!a || !b) return dotdot_missing(arg, dotdot, revs, symmetric); - exclude = repo_get_merge_bases(the_repository, a, b); + if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0) { + free_commit_list(exclude); + return -1; + } add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE, flags_exclude); add_pending_commit_list(revs, exclude, flags_exclude); @@ -2178,13 +2211,18 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl if (revarg_opt & REVARG_COMMITTISH) get_sha1_flags |= GET_OID_COMMITTISH; + /* + * Even if revs->do_not_die_on_missing_objects is set, we + * should error out if we can't even get an oid, as + * `--missing=print` should be able to report missing oids. + */ if (get_oid_with_context(revs->repo, arg, get_sha1_flags, &oid, &oc)) return revs->ignore_missing ? 0 : -1; if (!cant_be_filename) verify_non_filename(revs->prefix, arg); object = get_reference(revs, arg, &oid, flags ^ local_flags); if (!object) - return revs->ignore_missing ? 0 : -1; + return (revs->ignore_missing || revs->do_not_die_on_missing_objects) ? 0 : -1; add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags); add_pending_object_with_path(revs, object, arg, oc.mode, oc.path); free(oc.path); @@ -2320,7 +2358,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg } else if (skip_prefix(arg, "--ancestry-path=", &optarg)) { struct commit *c; struct object_id oid; - const char *msg = _("could not get commit for ancestry-path argument %s"); + const char *msg = _("could not get commit for --ancestry-path argument %s"); revs->ancestry_path = 1; revs->simplify_history = 0; @@ -3830,8 +3868,6 @@ int prepare_revision_walk(struct rev_info *revs) FOR_EACH_OBJECT_PROMISOR_ONLY); } - oidset_init(&revs->missing_commits, 0); - if (!revs->reflog_info) prepare_to_use_bloom_filter(revs); if (!revs->unsorted_input) diff --git a/revision.h b/revision.h index 94c43138bc..0e470d1df1 100644 --- a/revision.h +++ b/revision.h @@ -142,6 +142,7 @@ struct rev_info { /* Basic information */ const char *prefix; const char *def; + char *ps_matched; /* optionally record matches of prune_data */ struct pathspec prune_data; /* diff --git a/run-command.c b/run-command.c index 0e7435718a..1b821042b4 100644 --- a/run-command.c +++ b/run-command.c @@ -1793,20 +1793,27 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) trace2_region_leave(tr2_category, tr2_label, NULL); } -int run_auto_maintenance(int quiet) +int prepare_auto_maintenance(int quiet, struct child_process *maint) { int enabled; - struct child_process maint = CHILD_PROCESS_INIT; if (!git_config_get_bool("maintenance.auto", &enabled) && !enabled) return 0; - 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"); + 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"); + + return 1; +} +int run_auto_maintenance(int quiet) +{ + struct child_process maint = CHILD_PROCESS_INIT; + if (!prepare_auto_maintenance(quiet, &maint)) + return 0; return run_command(&maint); } diff --git a/run-command.h b/run-command.h index 1f22cc3827..55f6631a2a 100644 --- a/run-command.h +++ b/run-command.h @@ -218,6 +218,13 @@ int finish_command_in_signal(struct child_process *); int run_command(struct child_process *); /* + * Prepare a `struct child_process` to run auto-maintenance. Returns 1 if the + * process has been prepared and is ready to run, or 0 in case auto-maintenance + * should be skipped. + */ +int prepare_auto_maintenance(int quiet, struct child_process *maint); + +/* * Trigger an auto-gc */ int run_auto_maintenance(int quiet); diff --git a/sequencer.c b/sequencer.c index f49a871ac0..2c19846385 100644 --- a/sequencer.c +++ b/sequencer.c @@ -332,7 +332,7 @@ static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob, sb->buf[sb->len - ignore_footer] = '\0'; } - trailer_info_get(&info, sb->buf, &opts); + trailer_info_get(&opts, sb->buf, &info); if (ignore_footer) sb->buf[sb->len - ignore_footer] = saved_char; @@ -461,13 +461,25 @@ static void free_message(struct commit *commit, struct commit_message *msg) repo_unuse_commit_buffer(the_repository, commit, msg->message); } +const char *rebase_resolvemsg = +N_("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\"."); + static void print_advice(struct repository *r, int show_hint, struct replay_opts *opts) { - char *msg = getenv("GIT_CHERRY_PICK_HELP"); + const char *msg; + + if (is_rebase_i(opts)) + msg = rebase_resolvemsg; + else + msg = getenv("GIT_CHERRY_PICK_HELP"); if (msg) { - advise("%s\n", msg); + advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s", msg); /* * A conflict has occurred but the porcelain * (typically rebase --interactive) wants to take care @@ -480,22 +492,25 @@ static void print_advice(struct repository *r, int show_hint, if (show_hint) { if (opts->no_commit) - advise(_("after resolving the conflicts, mark the corrected paths\n" - "with 'git add <paths>' or 'git rm <paths>'")); + advise_if_enabled(ADVICE_MERGE_CONFLICT, + _("after resolving the conflicts, mark the corrected paths\n" + "with 'git add <paths>' or 'git rm <paths>'")); else if (opts->action == REPLAY_PICK) - advise(_("After resolving the conflicts, mark them with\n" - "\"git add/rm <pathspec>\", then run\n" - "\"git cherry-pick --continue\".\n" - "You can instead skip this commit with \"git cherry-pick --skip\".\n" - "To abort and get back to the state before \"git cherry-pick\",\n" - "run \"git cherry-pick --abort\".")); + advise_if_enabled(ADVICE_MERGE_CONFLICT, + _("After resolving the conflicts, mark them with\n" + "\"git add/rm <pathspec>\", then run\n" + "\"git cherry-pick --continue\".\n" + "You can instead skip this commit with \"git cherry-pick --skip\".\n" + "To abort and get back to the state before \"git cherry-pick\",\n" + "run \"git cherry-pick --abort\".")); else if (opts->action == REPLAY_REVERT) - advise(_("After resolving the conflicts, mark them with\n" - "\"git add/rm <pathspec>\", then run\n" - "\"git revert --continue\".\n" - "You can instead skip this commit with \"git revert --skip\".\n" - "To abort and get back to the state before \"git revert\",\n" - "run \"git revert --abort\".")); + advise_if_enabled(ADVICE_MERGE_CONFLICT, + _("After resolving the conflicts, mark them with\n" + "\"git add/rm <pathspec>\", then run\n" + "\"git revert --continue\".\n" + "You can instead skip this commit with \"git revert --skip\".\n" + "To abort and get back to the state before \"git revert\",\n" + "run \"git revert --abort\".")); else BUG("unexpected pick action in print_advice()"); } @@ -663,15 +678,15 @@ void append_conflicts_hint(struct index_state *istate, if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) { strbuf_addch(msgbuf, '\n'); wt_status_append_cut_line(msgbuf); - strbuf_addch(msgbuf, comment_line_char); + strbuf_addstr(msgbuf, comment_line_str); } strbuf_addch(msgbuf, '\n'); - strbuf_commented_addf(msgbuf, comment_line_char, "Conflicts:\n"); + strbuf_commented_addf(msgbuf, comment_line_str, "Conflicts:\n"); for (i = 0; i < istate->cache_nr;) { const struct cache_entry *ce = istate->cache[i++]; if (ce_stage(ce)) { - strbuf_commented_addf(msgbuf, comment_line_char, + strbuf_commented_addf(msgbuf, comment_line_str, "\t%s\n", ce->name); while (i < istate->cache_nr && !strcmp(ce->name, istate->cache[i]->name)) @@ -707,6 +722,8 @@ static int do_recursive_merge(struct repository *r, o.show_rename_progress = 1; head_tree = parse_tree_indirect(head); + if (!head_tree) + return error(_("unable to read tree (%s)"), oid_to_hex(head)); next_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r); base_tree = base ? repo_get_commit_tree(r, base) : empty_tree(r); @@ -770,29 +787,42 @@ static struct object_id *get_cache_tree_oid(struct index_state *istate) static int is_index_unchanged(struct repository *r) { struct object_id head_oid, *cache_tree_oid; + const struct object_id *head_tree_oid; struct commit *head_commit; struct index_state *istate = r->index; + const char *head_name; + + if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) { + /* Check to see if this is an unborn branch */ + head_name = resolve_ref_unsafe("HEAD", + RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, + &head_oid, NULL); + if (!head_name || + !starts_with(head_name, "refs/heads/") || + !is_null_oid(&head_oid)) + return error(_("could not resolve HEAD commit")); + head_tree_oid = the_hash_algo->empty_tree; + } else { + head_commit = lookup_commit(r, &head_oid); - if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) - return error(_("could not resolve HEAD commit")); - - head_commit = lookup_commit(r, &head_oid); + /* + * If head_commit is NULL, check_commit, called from + * lookup_commit, would have indicated that head_commit is not + * a commit object already. repo_parse_commit() will return failure + * without further complaints in such a case. Otherwise, if + * the commit is invalid, repo_parse_commit() will complain. So + * there is nothing for us to say here. Just return failure. + */ + if (repo_parse_commit(r, head_commit)) + return -1; - /* - * If head_commit is NULL, check_commit, called from - * lookup_commit, would have indicated that head_commit is not - * a commit object already. repo_parse_commit() will return failure - * without further complaints in such a case. Otherwise, if - * the commit is invalid, repo_parse_commit() will complain. So - * there is nothing for us to say here. Just return failure. - */ - if (repo_parse_commit(r, head_commit)) - return -1; + head_tree_oid = get_commit_tree_oid(head_commit); + } if (!(cache_tree_oid = get_cache_tree_oid(istate))) return -1; - return oideq(cache_tree_oid, get_commit_tree_oid(head_commit)); + return oideq(cache_tree_oid, head_tree_oid); } static int write_author_script(const char *message) @@ -1152,7 +1182,7 @@ void cleanup_message(struct strbuf *msgbuf, strbuf_setlen(msgbuf, wt_status_locate_end(msgbuf->buf, msgbuf->len)); if (cleanup_mode != COMMIT_MSG_CLEANUP_NONE) strbuf_stripspace(msgbuf, - cleanup_mode == COMMIT_MSG_CLEANUP_ALL ? comment_line_char : '\0'); + cleanup_mode == COMMIT_MSG_CLEANUP_ALL ? comment_line_str : NULL); } /* @@ -1184,7 +1214,7 @@ int template_untouched(const struct strbuf *sb, const char *template_file, return 0; strbuf_stripspace(&tmpl, - cleanup_mode == COMMIT_MSG_CLEANUP_ALL ? comment_line_char : '\0'); + cleanup_mode == COMMIT_MSG_CLEANUP_ALL ? comment_line_str : NULL); if (!skip_prefix(sb->buf, tmpl.buf, &start)) start = sb->buf; strbuf_release(&tmpl); @@ -1557,7 +1587,7 @@ static int try_to_commit(struct repository *r, if (cleanup != COMMIT_MSG_CLEANUP_NONE) strbuf_stripspace(msg, - cleanup == COMMIT_MSG_CLEANUP_ALL ? comment_line_char : '\0'); + cleanup == COMMIT_MSG_CLEANUP_ALL ? comment_line_str : NULL); if ((flags & EDIT_MSG) && message_is_empty(msg, cleanup)) { res = 1; /* run 'git commit' to display error message */ goto out; @@ -1719,34 +1749,25 @@ static int allow_empty(struct repository *r, int index_unchanged, originally_empty; /* - * Four cases: - * - * (1) we do not allow empty at all and error out. + * For a commit that is initially empty, allow_empty determines if it + * should be kept or not * - * (2) we allow ones that were initially empty, and - * just drop the ones that become empty - * - * (3) we allow ones that were initially empty, but - * halt for the ones that become empty; - * - * (4) we allow both. + * For a commit that becomes empty, keep_redundant_commits and + * drop_redundant_commits determine whether the commit should be kept or + * dropped. If neither is specified, halt. */ - if (!opts->allow_empty) - return 0; /* let "git commit" barf as necessary */ - index_unchanged = is_index_unchanged(r); if (index_unchanged < 0) return index_unchanged; if (!index_unchanged) return 0; /* we do not have to say --allow-empty */ - if (opts->keep_redundant_commits) - return 1; - originally_empty = is_original_commit_empty(commit); if (originally_empty < 0) return originally_empty; if (originally_empty) + return opts->allow_empty; + else if (opts->keep_redundant_commits) return 1; else if (opts->drop_redundant_commits) return 2; @@ -1779,6 +1800,8 @@ static const char *command_to_string(const enum todo_command command) { if (command < TODO_COMMENT) return todo_command_info[command].str; + if (command == TODO_COMMENT) + return comment_line_str; die(_("unknown command: %d"), command); } @@ -1786,7 +1809,7 @@ static char command_to_char(const enum todo_command command) { if (command < TODO_COMMENT) return todo_command_info[command].c; - return comment_line_char; + return 0; } static int is_noop(const enum todo_command command) @@ -1840,7 +1863,7 @@ static int is_fixup_flag(enum todo_command command, unsigned flag) static void add_commented_lines(struct strbuf *buf, const void *str, size_t len) { const char *s = str; - while (len > 0 && s[0] == comment_line_char) { + while (starts_with_mem(s, len, comment_line_str)) { size_t count; const char *n = memchr(s, '\n', len); if (!n) @@ -1851,7 +1874,7 @@ static void add_commented_lines(struct strbuf *buf, const void *str, size_t len) s += count; len -= count; } - strbuf_add_commented_lines(buf, s, len, comment_line_char); + strbuf_add_commented_lines(buf, s, len, comment_line_str); } /* Does the current fixup chain contain a squash command? */ @@ -1946,11 +1969,11 @@ static int append_squash_message(struct strbuf *buf, const char *body, (starts_with(body, "squash!") || starts_with(body, "fixup!")))) commented_len = commit_subject_length(body); - strbuf_addf(buf, "\n%c ", comment_line_char); + strbuf_addf(buf, "\n%s ", comment_line_str); strbuf_addf(buf, _(nth_commit_msg_fmt), ++opts->current_fixup_count + 1); strbuf_addstr(buf, "\n\n"); - strbuf_add_commented_lines(buf, body, commented_len, comment_line_char); + strbuf_add_commented_lines(buf, body, commented_len, comment_line_str); /* buf->buf may be reallocated so store an offset into the buffer */ fixup_off = buf->len; strbuf_addstr(buf, body + commented_len); @@ -2003,10 +2026,10 @@ static int update_squash_messages(struct repository *r, return error(_("could not read '%s'"), rebase_path_squash_msg()); - eol = buf.buf[0] != comment_line_char ? + eol = !starts_with(buf.buf, comment_line_str) ? buf.buf : strchrnul(buf.buf, '\n'); - strbuf_addf(&header, "%c ", comment_line_char); + strbuf_addf(&header, "%s ", comment_line_str); strbuf_addf(&header, _(combined_commit_msg_fmt), opts->current_fixup_count + 2); strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len); @@ -2032,16 +2055,16 @@ static int update_squash_messages(struct repository *r, repo_unuse_commit_buffer(r, head_commit, head_message); return error(_("cannot write '%s'"), rebase_path_fixup_msg()); } - strbuf_addf(&buf, "%c ", comment_line_char); + strbuf_addf(&buf, "%s ", comment_line_str); strbuf_addf(&buf, _(combined_commit_msg_fmt), 2); - strbuf_addf(&buf, "\n%c ", comment_line_char); + strbuf_addf(&buf, "\n%s ", comment_line_str); strbuf_addstr(&buf, is_fixup_flag(command, flag) ? _(skip_first_commit_msg_str) : _(first_commit_msg_str)); strbuf_addstr(&buf, "\n\n"); if (is_fixup_flag(command, flag)) strbuf_add_commented_lines(&buf, body, strlen(body), - comment_line_char); + comment_line_str); else strbuf_addstr(&buf, body); @@ -2056,12 +2079,12 @@ static int update_squash_messages(struct repository *r, if (command == TODO_SQUASH || is_fixup_flag(command, flag)) { res = append_squash_message(&buf, body, command, opts, flag); } else if (command == TODO_FIXUP) { - strbuf_addf(&buf, "\n%c ", comment_line_char); + strbuf_addf(&buf, "\n%s ", comment_line_str); strbuf_addf(&buf, _(skip_nth_commit_msg_fmt), ++opts->current_fixup_count + 1); strbuf_addstr(&buf, "\n\n"); strbuf_add_commented_lines(&buf, body, strlen(body), - comment_line_char); + comment_line_str); } else return error(_("unknown command: %d"), command); repo_unuse_commit_buffer(r, commit, message); @@ -2562,7 +2585,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item, /* left-trim */ bol += strspn(bol, " \t"); - if (bol == eol || *bol == '\r' || *bol == comment_line_char) { + if (bol == eol || *bol == '\r' || starts_with_mem(bol, eol - bol, comment_line_str)) { item->command = TODO_COMMENT; item->commit = NULL; item->arg_offset = bol - buf; @@ -2926,6 +2949,9 @@ static int populate_opts_cb(const char *key, const char *value, else if (!strcmp(key, "options.allow-empty-message")) opts->allow_empty_message = git_config_bool_or_int(key, value, ctx->kvi, &error_flag); + else if (!strcmp(key, "options.drop-redundant-commits")) + opts->drop_redundant_commits = + git_config_bool_or_int(key, value, ctx->kvi, &error_flag); else if (!strcmp(key, "options.keep-redundant-commits")) opts->keep_redundant_commits = git_config_bool_or_int(key, value, ctx->kvi, &error_flag); @@ -3460,54 +3486,57 @@ static int save_opts(struct replay_opts *opts) if (opts->no_commit) res |= git_config_set_in_file_gently(opts_file, - "options.no-commit", "true"); + "options.no-commit", NULL, "true"); if (opts->edit >= 0) - res |= git_config_set_in_file_gently(opts_file, "options.edit", + res |= git_config_set_in_file_gently(opts_file, "options.edit", NULL, opts->edit ? "true" : "false"); if (opts->allow_empty) res |= git_config_set_in_file_gently(opts_file, - "options.allow-empty", "true"); + "options.allow-empty", NULL, "true"); if (opts->allow_empty_message) res |= git_config_set_in_file_gently(opts_file, - "options.allow-empty-message", "true"); + "options.allow-empty-message", NULL, "true"); + if (opts->drop_redundant_commits) + res |= git_config_set_in_file_gently(opts_file, + "options.drop-redundant-commits", NULL, "true"); if (opts->keep_redundant_commits) res |= git_config_set_in_file_gently(opts_file, - "options.keep-redundant-commits", "true"); + "options.keep-redundant-commits", NULL, "true"); if (opts->signoff) res |= git_config_set_in_file_gently(opts_file, - "options.signoff", "true"); + "options.signoff", NULL, "true"); if (opts->record_origin) res |= git_config_set_in_file_gently(opts_file, - "options.record-origin", "true"); + "options.record-origin", NULL, "true"); if (opts->allow_ff) res |= git_config_set_in_file_gently(opts_file, - "options.allow-ff", "true"); + "options.allow-ff", NULL, "true"); if (opts->mainline) { struct strbuf buf = STRBUF_INIT; strbuf_addf(&buf, "%d", opts->mainline); res |= git_config_set_in_file_gently(opts_file, - "options.mainline", buf.buf); + "options.mainline", NULL, buf.buf); strbuf_release(&buf); } if (opts->strategy) res |= git_config_set_in_file_gently(opts_file, - "options.strategy", opts->strategy); + "options.strategy", NULL, opts->strategy); if (opts->gpg_sign) res |= git_config_set_in_file_gently(opts_file, - "options.gpg-sign", opts->gpg_sign); + "options.gpg-sign", NULL, opts->gpg_sign); for (size_t i = 0; i < opts->xopts.nr; i++) res |= git_config_set_multivar_in_file_gently(opts_file, "options.strategy-option", - opts->xopts.v[i], "^$", 0); + opts->xopts.v[i], "^$", NULL, 0); if (opts->allow_rerere_auto) res |= git_config_set_in_file_gently(opts_file, - "options.allow-rerere-auto", + "options.allow-rerere-auto", NULL, opts->allow_rerere_auto == RERERE_AUTOUPDATE ? "true" : "false"); if (opts->explicit_cleanup) res |= git_config_set_in_file_gently(opts_file, - "options.default-msg-cleanup", + "options.default-msg-cleanup", NULL, describe_cleanup_mode(opts->default_msg_cleanup)); return res; } @@ -3882,6 +3911,8 @@ static int do_reset(struct repository *r, } tree = parse_tree_indirect(&oid); + if (!tree) + return error(_("unable to read tree (%s)"), oid_to_hex(&oid)); prime_cache_tree(r, r->index, tree); if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0) @@ -3908,7 +3939,7 @@ static int do_merge(struct repository *r, int run_commit_flags = 0; struct strbuf ref_name = STRBUF_INIT; struct commit *head_commit, *merge_commit, *i; - struct commit_list *bases, *j; + struct commit_list *bases = NULL, *j; struct commit_list *to_merge = NULL, **tail = &to_merge; const char *strategy = !opts->xopts.nr && (!opts->strategy || @@ -4134,7 +4165,11 @@ static int do_merge(struct repository *r, } merge_commit = to_merge->item; - bases = repo_get_merge_bases(r, head_commit, merge_commit); + if (repo_get_merge_bases(r, head_commit, merge_commit, &bases) < 0) { + ret = -1; + goto leave_merge; + } + if (bases && oideq(&merge_commit->object.oid, &bases->item->object.oid)) { ret = 0; @@ -5659,8 +5694,8 @@ static int make_script_with_merges(struct pretty_print_context *pp, oid_to_hex(&commit->object.oid), oneline.buf); if (is_empty) - strbuf_addf(&buf, " %c empty", - comment_line_char); + strbuf_addf(&buf, " %s empty", + comment_line_str); FLEX_ALLOC_STR(entry, string, buf.buf); oidcpy(&entry->entry.oid, &commit->object.oid); @@ -5750,7 +5785,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, entry = oidmap_get(&state.commit2label, &commit->object.oid); if (entry) - strbuf_addf(out, "\n%c Branch %s\n", comment_line_char, entry->string); + strbuf_addf(out, "\n%s Branch %s\n", comment_line_str, entry->string); else strbuf_addch(out, '\n'); @@ -5887,7 +5922,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc, oid_to_hex(&commit->object.oid)); pretty_print_commit(&pp, commit, out); if (is_empty) - strbuf_addf(out, " %c empty", comment_line_char); + strbuf_addf(out, " %s empty", comment_line_str); strbuf_addch(out, '\n'); } if (skipped_commit) diff --git a/sequencer.h b/sequencer.h index dcef7bb99c..437eabd38a 100644 --- a/sequencer.h +++ b/sequencer.h @@ -14,6 +14,8 @@ const char *rebase_path_todo(void); const char *rebase_path_todo_backup(void); const char *rebase_path_dropped(void); +extern const char *rebase_resolvemsg; + #define APPEND_SIGNOFF_DEDUP (1u << 0) enum replay_action { @@ -12,6 +12,7 @@ #include "trace2.h" static int advertise_sid = -1; +static int advertise_object_info = -1; static int client_hash_algo = GIT_HASH_SHA1; static int always_advertise(struct repository *r UNUSED, @@ -67,6 +68,17 @@ static void session_id_receive(struct repository *r UNUSED, trace2_data_string("transfer", NULL, "client-sid", client_sid); } +static int object_info_advertise(struct repository *r, struct strbuf *value UNUSED) +{ + if (advertise_object_info == -1 && + repo_config_get_bool(r, "transfer.advertiseobjectinfo", + &advertise_object_info)) { + /* disabled by default */ + advertise_object_info = 0; + } + return advertise_object_info; +} + struct protocol_capability { /* * The name of the capability. The server uses this name when @@ -135,7 +147,7 @@ static struct protocol_capability capabilities[] = { }, { .name = "object-info", - .advertise = always_advertise, + .advertise = object_info_advertise, .command = cap_object_info, }, { @@ -591,6 +591,25 @@ static enum extension_result handle_extension(const char *var, "extensions.objectformat", value); data->hash_algo = format; return EXTENSION_OK; + } else if (!strcmp(ext, "compatobjectformat")) { + struct string_list_item *item; + int format; + + if (!value) + return config_error_nonbool(var); + format = hash_algo_by_name(value); + if (format == GIT_HASH_UNKNOWN) + return error(_("invalid value for '%s': '%s'"), + "extensions.compatobjectformat", value); + /* For now only support compatObjectFormat being specified once. */ + for_each_string_list_item(item, &data->v1_only_extensions) { + if (!strcmp(item->string, "compatobjectformat")) + return error(_("'%s' already specified as '%s'"), + "extensions.compatobjectformat", + hash_algos[data->compat_hash_algo].name); + } + data->compat_hash_algo = format; + return EXTENSION_OK; } else if (!strcmp(ext, "refstorage")) { unsigned int format; @@ -1243,6 +1262,32 @@ static const char *allowed_bare_repo_to_string( return NULL; } +static int is_implicit_bare_repo(const char *path) +{ + /* + * what we found is a ".git" directory at the root of + * the working tree. + */ + if (ends_with_path_components(path, ".git")) + return 1; + + /* + * we are inside $GIT_DIR of a secondary worktree of a + * non-bare repository. + */ + if (strstr(path, "/.git/worktrees/")) + return 1; + + /* + * we are inside $GIT_DIR of a worktree of a non-embedded + * submodule, whose superproject is not a bare repository. + */ + if (strstr(path, "/.git/modules/")) + return 1; + + return 0; +} + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. @@ -1372,7 +1417,7 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir, if (is_git_directory(dir->buf)) { trace2_data_string("setup", NULL, "implicit-bare-repository", dir->buf); if (get_allowed_bare_repo() == ALLOWED_BARE_REPO_EXPLICIT && - !ends_with_path_components(dir->buf, ".git")) + !is_implicit_bare_repo(dir->buf)) return GIT_DIR_DISALLOWED_BARE; if (!ensure_valid_ownership(NULL, NULL, dir->buf, report)) return GIT_DIR_INVALID_OWNERSHIP; @@ -1577,6 +1622,8 @@ const char *setup_git_directory_gently(int *nongit_ok) } if (startup_info->have_repository) { repo_set_hash_algo(the_repository, repo_fmt.hash_algo); + repo_set_compat_hash_algo(the_repository, + repo_fmt.compat_hash_algo); repo_set_ref_storage_format(the_repository, repo_fmt.ref_storage_format); the_repository->repository_format_worktree_config = @@ -1672,6 +1719,7 @@ void check_repository_format(struct repository_format *fmt) check_repository_format_gently(get_git_dir(), 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); repo_set_ref_storage_format(the_repository, fmt->ref_storage_format); the_repository->repository_format_worktree_config = @@ -1889,6 +1937,13 @@ void initialize_repository_version(int hash_algo, char repo_version_string[10]; int repo_version = GIT_REPO_VERSION; + /* + * Note that we initialize the repository version to 1 when the ref + * storage format is unknown. This is on purpose so that we can add the + * correct object format to the config during git-clone(1). The format + * version will get adjusted by git-clone(1) once it has learned about + * the remote repository's format. + */ if (hash_algo != GIT_HASH_SHA1 || ref_storage_format != REF_STORAGE_FORMAT_FILES) repo_version = GIT_REPO_VERSION_READ; @@ -1898,7 +1953,7 @@ void initialize_repository_version(int hash_algo, "%d", repo_version); git_config_set("core.repositoryformatversion", repo_version_string); - if (hash_algo != GIT_HASH_SHA1) + if (hash_algo != GIT_HASH_SHA1 && hash_algo != GIT_HASH_UNKNOWN) git_config_set("extensions.objectformat", hash_algos[hash_algo].name); else if (reinit) @@ -1961,7 +2016,6 @@ void create_reference_database(unsigned int ref_storage_format, static int create_default_files(const char *template_path, const char *original_git_dir, const struct repository_format *fmt, - int prev_bare_repository, int init_shared_repository) { struct stat st1; @@ -1996,34 +2050,8 @@ static int create_default_files(const char *template_path, */ if (init_shared_repository != -1) set_shared_repository(init_shared_repository); - /* - * TODO: heed core.bare from config file in templates if no - * command-line override given - */ - is_bare_repository_cfg = prev_bare_repository || !work_tree; - /* TODO (continued): - * - * Unfortunately, the line above is equivalent to - * is_bare_repository_cfg = !work_tree; - * which ignores the config entirely even if no `--[no-]bare` - * command line option was present. - * - * To see why, note that before this function, there was this call: - * prev_bare_repository = is_bare_repository() - * expanding the right hand side: - * = is_bare_repository_cfg && !get_git_work_tree() - * = is_bare_repository_cfg && !work_tree - * note that the last simplification above is valid because nothing - * calls repo_init() or set_git_work_tree() between any of the - * relevant calls in the code, and thus the !get_git_work_tree() - * calls will return the same result each time. So, what we are - * interested in computing is the right hand side of the line of - * code just above this comment: - * prev_bare_repository || !work_tree - * = is_bare_repository_cfg && !work_tree || !work_tree - * = !work_tree - * because "A && !B || !B == !B" for all boolean values of A & B. - */ + + is_bare_repository_cfg = !work_tree; /* * We would have created the above under user's umask -- under @@ -2175,7 +2203,6 @@ int init_db(const char *git_dir, const char *real_git_dir, int exist_ok = flags & INIT_DB_EXIST_OK; char *original_git_dir = real_pathdup(git_dir, 1); struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; - int prev_bare_repository; if (real_git_dir) { struct stat st; @@ -2201,7 +2228,6 @@ int init_db(const char *git_dir, const char *real_git_dir, safe_create_dir(git_dir, 0); - prev_bare_repository = is_bare_repository(); /* Check to see if the repository version is right. * Note that a newly created repository does not have @@ -2214,8 +2240,7 @@ int init_db(const char *git_dir, const char *real_git_dir, validate_ref_storage_format(&repo_fmt, ref_storage_format); reinit = create_default_files(template_dir, original_git_dir, - &repo_fmt, prev_bare_repository, - init_shared_repository); + &repo_fmt, init_shared_repository); /* * Now that we have set up both the hash algorithm and the ref storage @@ -115,6 +115,7 @@ struct repository_format { int worktree_config; int is_bare; int hash_algo; + int compat_hash_algo; unsigned int ref_storage_format; int sparse_index; char *work_tree; @@ -794,12 +794,16 @@ static void post_assign_shallow(struct shallow_info *info, if (!*bitmap) continue; for (j = 0; j < bitmap_nr; j++) - if (bitmap[0][j] && - /* Step 7, reachability test at commit level */ - !repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits)) { - update_refstatus(ref_status, info->ref->nr, *bitmap); - dst++; - break; + if (bitmap[0][j]) { + /* Step 7, reachability test at commit level */ + int ret = repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1); + if (ret < 0) + exit(128); + if (!ret) { + update_refstatus(ref_status, info->ref->nr, *bitmap); + dst++; + break; + } } } info->nr_ours = dst; @@ -827,7 +831,10 @@ int delayed_reachability_test(struct shallow_info *si, int c) si->reachable[c] = repo_in_merge_bases_many(the_repository, commit, si->nr_commits, - si->commits); + si->commits, + 1); + if (si->reachable[c] < 0) + exit(128); si->need_reachability_test[c] = 0; } return si->reachable[c]; diff --git a/sideband.c b/sideband.c index 266a67342b..5d8907151f 100644 --- a/sideband.c +++ b/sideband.c @@ -220,7 +220,7 @@ int demultiplex_sideband(const char *me, int status, } strbuf_addch(scratch, *brk); - xwrite(2, scratch->buf, scratch->len); + write_in_full(2, scratch->buf, scratch->len); strbuf_reset(scratch); b = brk + 1; @@ -247,7 +247,7 @@ cleanup: die("%s", scratch->buf); if (scratch->len) { strbuf_addch(scratch, '\n'); - xwrite(2, scratch->buf, scratch->len); + write_in_full(2, scratch->buf, scratch->len); } strbuf_release(scratch); return 1; @@ -24,6 +24,17 @@ int istarts_with(const char *str, const char *prefix) return 0; } +int starts_with_mem(const char *str, size_t len, const char *prefix) +{ + const char *end = str + len; + for (; ; str++, prefix++) { + if (!*prefix) + return 1; + else if (str == end || *str != *prefix) + return 0; + } +} + int skip_to_optional_arg_default(const char *str, const char *prefix, const char **arg, const char *def) { @@ -266,7 +277,7 @@ void strbuf_vinsertf(struct strbuf *sb, size_t pos, const char *fmt, va_list ap) len = vsnprintf(sb->buf + sb->len, 0, fmt, cp); va_end(cp); if (len < 0) - BUG("your vsnprintf is broken (returned %d)", len); + die(_("unable to format message: %s"), fmt); if (!len) return; /* nothing to do */ if (unsigned_add_overflows(sb->len, len)) @@ -340,18 +351,17 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) } static void add_lines(struct strbuf *out, - const char *prefix1, - const char *prefix2, - const char *buf, size_t size) + const char *prefix, + const char *buf, size_t size, + int space_after_prefix) { while (size) { - const char *prefix; const char *next = memchr(buf, '\n', size); next = next ? (next + 1) : (buf + size); - prefix = ((prefix2 && (buf[0] == '\n' || buf[0] == '\t')) - ? prefix2 : prefix1); strbuf_addstr(out, prefix); + if (space_after_prefix && buf[0] != '\n' && buf[0] != '\t') + strbuf_addch(out, ' '); strbuf_add(out, buf, next - buf); size -= next - buf; buf = next; @@ -360,19 +370,12 @@ static void add_lines(struct strbuf *out, } void strbuf_add_commented_lines(struct strbuf *out, const char *buf, - size_t size, char comment_line_char) + size_t size, const char *comment_prefix) { - static char prefix1[3]; - static char prefix2[2]; - - if (prefix1[0] != comment_line_char) { - xsnprintf(prefix1, sizeof(prefix1), "%c ", comment_line_char); - xsnprintf(prefix2, sizeof(prefix2), "%c", comment_line_char); - } - add_lines(out, prefix1, prefix2, buf, size); + add_lines(out, comment_prefix, buf, size, 1); } -void strbuf_commented_addf(struct strbuf *sb, char comment_line_char, +void strbuf_commented_addf(struct strbuf *sb, const char *comment_prefix, const char *fmt, ...) { va_list params; @@ -383,7 +386,7 @@ void strbuf_commented_addf(struct strbuf *sb, char comment_line_char, strbuf_vaddf(&buf, fmt, params); va_end(params); - strbuf_add_commented_lines(sb, buf.buf, buf.len, comment_line_char); + strbuf_add_commented_lines(sb, buf.buf, buf.len, comment_prefix); if (incomplete_line) sb->buf[--sb->len] = '\0'; @@ -401,7 +404,7 @@ void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap) len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp); va_end(cp); if (len < 0) - BUG("your vsnprintf is broken (returned %d)", len); + die(_("unable to format message: %s"), fmt); if (len > strbuf_avail(sb)) { strbuf_grow(sb, len); len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); @@ -442,6 +445,26 @@ size_t strbuf_expand_literal(struct strbuf *sb, const char *placeholder) return 0; } +void strbuf_expand_bad_format(const char *format, const char *command) +{ + const char *end; + + if (*format != '(') + /* TRANSLATORS: The first %s is a command like "ls-tree". */ + die(_("bad %s format: element '%s' does not start with '('"), + command, format); + + end = strchr(format + 1, ')'); + if (!end) + /* TRANSLATORS: The first %s is a command like "ls-tree". */ + die(_("bad %s format: element '%s' does not end in ')'"), + command, format); + + /* TRANSLATORS: %s is a command like "ls-tree". */ + die(_("bad %s format: %%%.*s"), + command, (int)(end - format + 1), format); +} + void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src) { size_t i, len = src->len; @@ -750,7 +773,7 @@ ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint) void strbuf_add_lines(struct strbuf *out, const char *prefix, const char *buf, size_t size) { - add_lines(out, prefix, NULL, buf, size); + add_lines(out, prefix, buf, size, 0); } void strbuf_addstr_xml_quoted(struct strbuf *buf, const char *s) @@ -1005,10 +1028,10 @@ static size_t cleanup(char *line, size_t len) * * If last line does not have a newline at the end, one is added. * - * Pass a non-NUL comment_line_char to skip every line starting + * Pass a non-NULL comment_prefix to skip every line starting * with it. */ -void strbuf_stripspace(struct strbuf *sb, char comment_line_char) +void strbuf_stripspace(struct strbuf *sb, const char *comment_prefix) { size_t empties = 0; size_t i, j, len, newlen; @@ -1021,8 +1044,8 @@ void strbuf_stripspace(struct strbuf *sb, char comment_line_char) eol = memchr(sb->buf + i, '\n', sb->len - i); len = eol ? eol - (sb->buf + i) + 1 : sb->len - i; - if (comment_line_char && len && - sb->buf[i] == comment_line_char) { + if (comment_prefix && len && + starts_with(sb->buf + i, comment_prefix)) { newlen = 0; continue; } @@ -288,7 +288,7 @@ void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, */ void strbuf_add_commented_lines(struct strbuf *out, const char *buf, size_t size, - char comment_line_char); + const char *comment_prefix); /** @@ -338,6 +338,11 @@ size_t strbuf_expand_literal(struct strbuf *sb, const char *placeholder); int strbuf_expand_step(struct strbuf *sb, const char **formatp); /** + * Used with `strbuf_expand_step` to report unknown placeholders. + */ +void strbuf_expand_bad_format(const char *format, const char *command); + +/** * Append the contents of one strbuf to another, quoting any * percent signs ("%") into double-percents ("%%") in the * destination. This is useful for literal data to be fed to either @@ -379,7 +384,7 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...); * blank to the buffer. */ __attribute__((format (printf, 3, 4))) -void strbuf_commented_addf(struct strbuf *sb, char comment_line_char, const char *fmt, ...); +void strbuf_commented_addf(struct strbuf *sb, const char *comment_prefix, const char *fmt, ...); __attribute__((format (printf,2,0))) void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap); @@ -513,11 +518,11 @@ int strbuf_getcwd(struct strbuf *sb); int strbuf_normalize_path(struct strbuf *sb); /** - * Strip whitespace from a buffer. If comment_line_char is non-NUL, + * Strip whitespace from a buffer. If comment_prefix is non-NULL, * then lines beginning with that character are considered comments, * thus removed. */ -void strbuf_stripspace(struct strbuf *buf, char comment_line_char); +void strbuf_stripspace(struct strbuf *buf, const char *comment_prefix); static inline int strbuf_strip_suffix(struct strbuf *sb, const char *suffix) { @@ -673,6 +678,7 @@ char *xstrfmt(const char *fmt, ...); int starts_with(const char *str, const char *prefix); int istarts_with(const char *str, const char *prefix); +int starts_with_mem(const char *str, size_t len, const char *prefix); /* * If the string "str" is the same as the string in "prefix", then the "arg" diff --git a/submodule-config.c b/submodule-config.c index 54130f6a38..11428b4ada 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -978,7 +978,7 @@ int config_set_in_gitmodules_file_gently(const char *key, const char *value) { int ret; - ret = git_config_set_in_file_gently(GITMODULES_FILE, key, value); + ret = git_config_set_in_file_gently(GITMODULES_FILE, key, NULL, value); if (ret < 0) /* Maybe the user already did that, don't error out here */ warning(_("Could not update .gitmodules entry %s"), key); diff --git a/submodule.c b/submodule.c index 213da79f66..ce2d032521 100644 --- a/submodule.c +++ b/submodule.c @@ -592,7 +592,12 @@ static void show_submodule_header(struct diff_options *o, (!is_null_oid(two) && !*right)) message = "(commits not present)"; - *merge_bases = repo_get_merge_bases(sub, *left, *right); + *merge_bases = NULL; + if (repo_get_merge_bases(sub, *left, *right, merge_bases) < 0) { + message = "(corrupt repository)"; + goto output_header; + } + if (*merge_bases) { if ((*merge_bases)->item == *left) fast_forward = 1; @@ -1687,8 +1692,6 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err, task = get_fetch_task_from_changed(spf, err); if (task) { - struct strbuf submodule_prefix = STRBUF_INIT; - child_process_init(cp); cp->dir = task->repo->gitdir; prepare_submodule_repo_env_in_gitdir(&cp->env); @@ -1698,15 +1701,11 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err, strvec_pushv(&cp->args, task->git_args.v); strvec_pushv(&cp->args, spf->args.v); strvec_push(&cp->args, task->default_argv); - strvec_push(&cp->args, "--submodule-prefix"); + strvec_pushf(&cp->args, "--submodule-prefix=%s%s/", + spf->prefix, task->sub->path); - strbuf_addf(&submodule_prefix, "%s%s/", - spf->prefix, - task->sub->path); - strvec_push(&cp->args, submodule_prefix.buf); *task_cb = task; - strbuf_release(&submodule_prefix); string_list_insert(&spf->seen_submodule_names, task->sub->name); return 1; } @@ -1714,12 +1713,8 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err, if (spf->oid_fetch_tasks_nr) { struct fetch_task *task = spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr - 1]; - struct strbuf submodule_prefix = STRBUF_INIT; spf->oid_fetch_tasks_nr--; - strbuf_addf(&submodule_prefix, "%s%s/", - spf->prefix, task->sub->path); - child_process_init(cp); prepare_submodule_repo_env_in_gitdir(&cp->env); cp->git_cmd = 1; @@ -1728,8 +1723,8 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err, strvec_init(&cp->args); strvec_pushv(&cp->args, spf->args.v); strvec_push(&cp->args, "on-demand"); - strvec_push(&cp->args, "--submodule-prefix"); - strvec_push(&cp->args, submodule_prefix.buf); + strvec_pushf(&cp->args, "--submodule-prefix=%s%s/", + spf->prefix, task->sub->path); /* NEEDSWORK: have get_default_remote from submodule--helper */ strvec_push(&cp->args, "origin"); @@ -1737,7 +1732,6 @@ static int get_next_submodule(struct child_process *cp, struct strbuf *err, append_oid_to_argv, &cp->args); *task_cb = task; - strbuf_release(&submodule_prefix); return 1; } @@ -2052,7 +2046,7 @@ void submodule_unset_core_worktree(const struct submodule *sub) submodule_name_to_gitdir(&config_path, the_repository, sub->name); strbuf_addstr(&config_path, "/config"); - if (git_config_set_in_file_gently(config_path.buf, "core.worktree", NULL)) + if (git_config_set_in_file_gently(config_path.buf, "core.worktree", NULL, NULL)) warning(_("Could not unset core.worktree setting in submodule '%s'"), sub->path); @@ -32,6 +32,13 @@ the tests. ok 2 - plain with GIT_WORK_TREE ok 3 - plain bare +t/Makefile defines a target for each test file, such that you can also use +shell pattern matching to run a subset of the tests: + + make *checkout* + +will run all tests with 'checkout' in their filename. + Since the tests all output TAP (see https://testanything.org) they can be run with any TAP harness. Here's an example of parallel testing powered by a recent version of prove(1): @@ -724,6 +731,26 @@ The "do's:" Note that we still &&-chain the loop to propagate failures from earlier commands. + - Repeat tests with slightly different arguments in a loop. + + In some cases it may make sense to re-run the same set of tests with + different options or commands to ensure that the command behaves + despite the different parameters. This can be achieved by looping + around a specific parameter: + + for arg in '' "--foo" + do + test_expect_success "test command ${arg:-without arguments}" ' + command $arg + ' + done + + Note that while the test title uses double quotes ("), the test body + should continue to use single quotes (') to avoid breakage in case the + values contain e.g. quoting characters. The loop variable will be + accessible regardless of the single quotes as the test body is passed + to `eval`. + And here are the "don'ts:" diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 5e21e84f38..87572459e4 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -532,7 +532,7 @@ test_expect_success 'blame -L :funcname with userdiff driver' ' "$(cat file.template)" && test_commit --author "B <B@test.git>" \ "change" "$fortran_file" \ - "$(cat file.template | sed -e s/ChangeMe/IWasChanged/)" && + "$(sed -e s/ChangeMe/IWasChanged/ file.template)" && check_count -f "$fortran_file" -L:RIGHT A 3 B 1 ' diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl index dd8107cd7d..b2b28c2ced 100755 --- a/t/check-non-portable-shell.pl +++ b/t/check-non-portable-shell.pl @@ -47,6 +47,8 @@ while (<>) { /\bgrep\b.*--file\b/ and err 'grep --file FILE is not portable (use grep -f FILE)'; /\b[ef]grep\b/ and err 'egrep/fgrep obsolescent (use grep -E/-F)'; /\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"'; $line = ''; diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 0683d46574..f25512de9a 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -52,7 +52,7 @@ static void show_dates(const char **argv, const char *format) arg++; tz = atoi(arg); - printf("%s -> %s\n", *argv, show_date(t, tz, &mode)); + printf("%s -> %s\n", *argv, show_date(t, tz, mode)); } date_mode_release(&mode); diff --git a/t/helper/test-delete-gpgsig.c b/t/helper/test-delete-gpgsig.c new file mode 100644 index 0000000000..e36831af03 --- /dev/null +++ b/t/helper/test-delete-gpgsig.c @@ -0,0 +1,62 @@ +#include "test-tool.h" +#include "gpg-interface.h" +#include "strbuf.h" + + +int cmd__delete_gpgsig(int argc, const char **argv) +{ + struct strbuf buf = STRBUF_INIT; + const char *pattern = "gpgsig"; + const char *bufptr, *tail, *eol; + int deleting = 0; + size_t plen; + + if (argc >= 2) { + pattern = argv[1]; + argv++; + argc--; + } + + plen = strlen(pattern); + strbuf_read(&buf, 0, 0); + + if (!strcmp(pattern, "trailer")) { + size_t payload_size = parse_signed_buffer(buf.buf, buf.len); + fwrite(buf.buf, 1, payload_size, stdout); + fflush(stdout); + return 0; + } + + bufptr = buf.buf; + tail = bufptr + buf.len; + + while (bufptr < tail) { + /* Find the end of the line */ + eol = memchr(bufptr, '\n', tail - bufptr); + if (!eol) + eol = tail; + + /* Drop continuation lines */ + if (deleting && (bufptr < eol) && (bufptr[0] == ' ')) { + bufptr = eol + 1; + continue; + } + deleting = 0; + + /* Does the line match the prefix? */ + if (((bufptr + plen) < eol) && + !memcmp(bufptr, pattern, plen) && + (bufptr[plen] == ' ')) { + deleting = 1; + bufptr = eol + 1; + continue; + } + + /* Print all other lines */ + fwrite(bufptr, 1, (eol - bufptr) + 1, stdout); + bufptr = eol + 1; + } + fflush(stdout); + + return 0; +} diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index 1e159a754d..1e3b431e3e 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -111,13 +111,16 @@ int cmd__reach(int ac, const char **av) repo_in_merge_bases(the_repository, A, B)); else if (!strcmp(av[1], "in_merge_bases_many")) printf("%s(A,X):%d\n", av[1], - repo_in_merge_bases_many(the_repository, A, X_nr, X_array)); + 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_merge_bases_many")) { - struct commit_list *list = repo_get_merge_bases_many(the_repository, - A, X_nr, - X_array); + struct commit_list *list = NULL; + if (repo_get_merge_bases_many(the_repository, + A, X_nr, + X_array, + &list) < 0) + exit(128); printf("%s(A,X):\n", av[1]); print_sorted_commit_ids(list); } else if (!strcmp(av[1], "reduce_heads")) { diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 702ec1f128..82bbf6e2e6 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -112,25 +112,6 @@ static const char **get_store(const char **argv, struct ref_store **refs) return argv + 1; } -static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE), - FLAG_DEF(PACK_REFS_ALL), - { NULL, 0 } }; - -static int cmd_pack_refs(struct ref_store *refs, const char **argv) -{ - unsigned int flags = arg_flags(*argv++, "flags", pack_flags); - static struct ref_exclusions exclusions = REF_EXCLUSIONS_INIT; - static struct string_list included_refs = STRING_LIST_INIT_NODUP; - struct pack_refs_opts pack_opts = { .flags = flags, - .exclusions = &exclusions, - .includes = &included_refs }; - - if (pack_opts.flags & PACK_REFS_ALL) - string_list_append(pack_opts.includes, "*"); - - return refs_pack_refs(refs, &pack_opts); -} - static int cmd_create_symref(struct ref_store *refs, const char **argv) { const char *refname = notnull(*argv++, "refname"); @@ -221,15 +202,21 @@ static int cmd_verify_ref(struct ref_store *refs, const char **argv) return ret; } +static int each_reflog(const char *refname, void *cb_data UNUSED) +{ + printf("%s\n", refname); + return 0; +} + static int cmd_for_each_reflog(struct ref_store *refs, const char **argv UNUSED) { - return refs_for_each_reflog(refs, each_ref, NULL); + return refs_for_each_reflog(refs, each_reflog, NULL); } -static int each_reflog(struct object_id *old_oid, struct object_id *new_oid, - const char *committer, timestamp_t timestamp, - int tz, const char *msg, void *cb_data UNUSED) +static int each_reflog_ent(struct object_id *old_oid, struct object_id *new_oid, + const char *committer, timestamp_t timestamp, + int tz, const char *msg, void *cb_data UNUSED) { printf("%s %s %s %" PRItime " %+05d%s%s", oid_to_hex(old_oid), oid_to_hex(new_oid), committer, timestamp, tz, @@ -241,14 +228,14 @@ static int cmd_for_each_reflog_ent(struct ref_store *refs, const char **argv) { const char *refname = notnull(*argv++, "refname"); - return refs_for_each_reflog_ent(refs, refname, each_reflog, refs); + return refs_for_each_reflog_ent(refs, refname, each_reflog_ent, refs); } static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv) { const char *refname = notnull(*argv++, "refname"); - return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs); + return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog_ent, refs); } static int cmd_reflog_exists(struct ref_store *refs, const char **argv) @@ -320,7 +307,6 @@ struct command { }; static struct command commands[] = { - { "pack-refs", cmd_pack_refs }, { "create-symref", cmd_create_symref }, { "delete-refs", cmd_delete_refs }, { "rename-ref", cmd_rename_ref }, diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 482a1e58a4..80a946b847 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -20,6 +20,7 @@ static struct test_cmd cmds[] = { { "crontab", cmd__crontab }, { "csprng", cmd__csprng }, { "date", cmd__date }, + { "delete-gpgsig", cmd__delete_gpgsig }, { "delta", cmd__delta }, { "dir-iterator", cmd__dir_iterator }, { "drop-caches", cmd__drop_caches }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index b1be7cfcf5..2808b92419 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -14,6 +14,7 @@ int cmd__crontab(int argc, const char **argv); int cmd__csprng(int argc, const char **argv); int cmd__date(int argc, const char **argv); int cmd__delta(int argc, const char **argv); +int cmd__delete_gpgsig(int argc, const char **argv); int cmd__dir_iterator(int argc, const char **argv); int cmd__drop_caches(int argc, const char **argv); int cmd__dump_cache_tree(int argc, const char **argv); diff --git a/t/lib-credential.sh b/t/lib-credential.sh index 15fc9a31e2..44799c0d38 100644 --- a/t/lib-credential.sh +++ b/t/lib-credential.sh @@ -50,6 +50,7 @@ helper_test_clean() { reject $1 https example.com user-overwrite reject $1 https example.com user-erase1 reject $1 https example.com user-erase2 + reject $1 https victim.example.com user reject $1 http path.tld user reject $1 https timeout.tld user reject $1 https sso.tld diff --git a/t/lib-cvs.sh b/t/lib-cvs.sh index 32b3473379..57b9b2db9b 100644 --- a/t/lib-cvs.sh +++ b/t/lib-cvs.sh @@ -71,8 +71,8 @@ test_cmp_branch_tree () { find . -type d -name .git -prune -o -type f -print ) | sort >module-git-"$1".list && test_cmp module-cvs-"$1".list module-git-"$1".list && - cat module-cvs-"$1".list | while read f + while read f do test_cmp_branch_file "$1" "$f" || return 1 - done + done <module-cvs-"$1".list } diff --git a/t/lib-parallel-checkout.sh b/t/lib-parallel-checkout.sh index acaee9cbb6..8324d6c96d 100644 --- a/t/lib-parallel-checkout.sh +++ b/t/lib-parallel-checkout.sh @@ -20,7 +20,7 @@ test_checkout_workers () { BUG "too few arguments to test_checkout_workers" fi && - local expected_workers=$1 && + local expected_workers="$1" && shift && local trace_file=trace-test-checkout-workers && diff --git a/t/oid-info/hash-info b/t/oid-info/hash-info index d0736dd1a0..b8a5bcb187 100644 --- a/t/oid-info/hash-info +++ b/t/oid-info/hash-info @@ -15,3 +15,15 @@ empty_blob sha256:473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a3037218 empty_tree sha1:4b825dc642cb6eb9a060e54bf8d69288fbee4904 empty_tree sha256:6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321 + +blob17_1 sha1:263 +blob17_1 sha256:34 + +blob17_2 sha1:410 +blob17_2 sha256:174 + +blob17_3 sha1:523 +blob17_3 sha256:313 + +blob17_4 sha1:790 +blob17_4 sha256:481 diff --git a/t/perf/repos/inflate-repo.sh b/t/perf/repos/inflate-repo.sh index fcfc992b5b..412e4b450b 100755 --- a/t/perf/repos/inflate-repo.sh +++ b/t/perf/repos/inflate-repo.sh @@ -33,7 +33,7 @@ do done git ls-tree -r HEAD >GEN_src_list -nr_src_files=$(cat GEN_src_list | wc -l) +nr_src_files=$(wc -l <GEN_src_list) src_branch=$(git symbolic-ref --short HEAD) diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh index 736516cc6a..bf3bf604ab 100755 --- a/t/t0002-gitfile.sh +++ b/t/t0002-gitfile.sh @@ -40,7 +40,7 @@ test_expect_success 'final setup + check rev-parse --git-dir' ' test_expect_success 'check hash-object' ' echo "foo" >bar && - SHA=$(cat bar | git hash-object -w --stdin) && + SHA=$(git hash-object -w --stdin <bar) && test_path_is_file "$REAL/objects/$(objpath $SHA)" ' diff --git a/t/t0006-date.sh b/t/t0006-date.sh index e18b160286..3031256d14 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -46,6 +46,7 @@ check_show () { TIME='1466000000 +0200' check_show iso8601 "$TIME" '2016-06-15 16:13:20 +0200' check_show iso8601-strict "$TIME" '2016-06-15T16:13:20+02:00' +check_show iso8601-strict "$(echo "$TIME" | sed 's/+0200$/+0000/')" '2016-06-15T14:13:20Z' check_show rfc2822 "$TIME" 'Wed, 15 Jun 2016 16:13:20 +0200' check_show short "$TIME" '2016-06-15' check_show default "$TIME" 'Wed Jun 15 16:13:20 2016 +0200' @@ -69,6 +70,14 @@ check_show 'format:%s' '123456789 +1234' 123456789 check_show 'format:%s' '123456789 -1234' 123456789 check_show 'format-local:%s' '123456789 -1234' 123456789 +# negative TZ offset +TIME='1466000000 -0200' +check_show iso8601 "$TIME" '2016-06-15 12:13:20 -0200' +check_show iso8601-strict "$TIME" '2016-06-15T12:13:20-02:00' +check_show rfc2822 "$TIME" 'Wed, 15 Jun 2016 12:13:20 -0200' +check_show default "$TIME" 'Wed Jun 15 12:13:20 2016 -0200' +check_show raw "$TIME" '1466000000 -0200' + # arbitrary time absurdly far in the future FUTURE="5758122296 -0400" check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT,TIME_T_IS_64BIT diff --git a/t/t0010-racy-git.sh b/t/t0010-racy-git.sh index 837c8b7228..84172a3739 100755 --- a/t/t0010-racy-git.sh +++ b/t/t0010-racy-git.sh @@ -10,25 +10,24 @@ TEST_PASSES_SANITIZE_LEAK=true for trial in 0 1 2 3 4 do - rm -f .git/index - echo frotz >infocom - git update-index --add infocom - echo xyzzy >infocom - - files=$(git diff-files -p) - test_expect_success \ - "Racy GIT trial #$trial part A" \ - 'test "" != "$files"' - + test_expect_success "Racy git trial #$trial part A" ' + rm -f .git/index && + echo frotz >infocom && + git update-index --add infocom && + echo xyzzy >infocom && + + git diff-files -p >out && + test_file_not_empty out + ' sleep 1 - echo xyzzy >cornerstone - git update-index --add cornerstone - files=$(git diff-files -p) - test_expect_success \ - "Racy GIT trial #$trial part B" \ - 'test "" != "$files"' + test_expect_success "Racy git trial #$trial part B" ' + echo xyzzy >cornerstone && + git update-index --add cornerstone && + git diff-files -p >out && + test_file_not_empty out + ' done test_done diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh index 1cb6aa6824..46e74ad107 100755 --- a/t/t0011-hashmap.sh +++ b/t/t0011-hashmap.sh @@ -239,7 +239,7 @@ test_expect_success 'grow / shrink' ' echo value40 >> expect && echo size >> in && echo 64 39 >> expect && - cat in | test-tool hashmap > out && + test-tool hashmap <in >out && test_cmp expect out ' diff --git a/t/t0028-working-tree-encoding.sh b/t/t0028-working-tree-encoding.sh index 1b55f59c23..ad151a3467 100755 --- a/t/t0028-working-tree-encoding.sh +++ b/t/t0028-working-tree-encoding.sh @@ -131,8 +131,8 @@ do test_when_finished "rm -f crlf.utf${i}.raw lf.utf${i}.raw" && test_when_finished "git reset --hard HEAD^" && - cat lf.utf8.raw | write_utf${i} >lf.utf${i}.raw && - cat crlf.utf8.raw | write_utf${i} >crlf.utf${i}.raw && + write_utf${i} <lf.utf8.raw >lf.utf${i}.raw && + write_utf${i} <crlf.utf8.raw >crlf.utf${i}.raw && cp crlf.utf${i}.raw eol.utf${i} && cat >expectIndexLF <<-EOF && diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh index d1b3be8725..f10f42ff1e 100755 --- a/t/t0030-stripspace.sh +++ b/t/t0030-stripspace.sh @@ -401,6 +401,21 @@ test_expect_success 'strip comments with changed comment char' ' test -z "$(echo "; comment" | git -c core.commentchar=";" stripspace -s)" ' +test_expect_success 'strip comments with changed comment string' ' + test ! -z "$(echo "// comment" | git -c core.commentchar=// stripspace)" && + test -z "$(echo "// comment" | git -c core.commentchar="//" stripspace -s)" +' + +test_expect_success 'newline as commentchar is forbidden' ' + test_must_fail git -c core.commentChar="$LF" stripspace -s 2>err && + grep "core.commentchar cannot contain newline" err +' + +test_expect_success 'empty commentchar is forbidden' ' + test_must_fail git -c core.commentchar= stripspace -s 2>err && + grep "core.commentchar must have at least one character" err +' + test_expect_success '-c with single line' ' printf "# foo\n" >expect && printf "foo" | git stripspace -c >actual && diff --git a/t/t0035-safe-bare-repository.sh b/t/t0035-safe-bare-repository.sh index 8048856379..d3cb2a1cb9 100755 --- a/t/t0035-safe-bare-repository.sh +++ b/t/t0035-safe-bare-repository.sh @@ -29,9 +29,20 @@ expect_rejected () { grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf" } -test_expect_success 'setup bare repo in worktree' ' +test_expect_success 'setup an embedded bare repo, secondary worktree and submodule' ' git init outer-repo && - git init --bare outer-repo/bare-repo + git init --bare --initial-branch=main outer-repo/bare-repo && + git -C outer-repo worktree add ../outer-secondary && + test_path_is_dir outer-secondary && + ( + cd outer-repo && + test_commit A && + git push bare-repo +HEAD:refs/heads/main && + git -c protocol.file.allow=always \ + submodule add --name subn -- ./bare-repo subd + ) && + test_path_is_dir outer-repo/.git/worktrees/outer-secondary && + test_path_is_dir outer-repo/.git/modules/subn ' test_expect_success 'safe.bareRepository unset' ' @@ -53,8 +64,7 @@ test_expect_success 'safe.bareRepository in the repository' ' # safe.bareRepository must not be "explicit", otherwise # git config fails with "fatal: not in a git directory" (like # safe.directory) - test_config -C outer-repo/bare-repo safe.bareRepository \ - all && + test_config -C outer-repo/bare-repo safe.bareRepository all && test_config_global safe.bareRepository explicit && expect_rejected -C outer-repo/bare-repo ' @@ -86,4 +96,12 @@ test_expect_success 'no trace when "bare repository" is a subdir of .git' ' expect_accepted_implicit -C outer-repo/.git/objects ' +test_expect_success 'no trace in $GIT_DIR of secondary worktree' ' + expect_accepted_implicit -C outer-repo/.git/worktrees/outer-secondary +' + +test_expect_success 'no trace in $GIT_DIR of a submodule' ' + expect_accepted_implicit -C outer-repo/.git/modules/subn +' + test_done diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index ec974867e4..8bb2a8b453 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -210,6 +210,22 @@ test_expect_success 'superfluous value provided: boolean' ' test_cmp expect actual ' +test_expect_success 'superfluous value provided: boolean, abbreviated' ' + cat >expect <<-\EOF && + error: option `yes'\'' takes no value + EOF + test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + test-tool parse-options --ye=hi 2>actual && + test_cmp expect actual && + + cat >expect <<-\EOF && + error: option `no-yes'\'' takes no value + EOF + test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + test-tool parse-options --no-ye=hi 2>actual && + test_cmp expect actual +' + test_expect_success 'superfluous value provided: cmdmode' ' cat >expect <<-\EOF && error: option `mode1'\'' takes no value diff --git a/t/t0204-gettext-reencode-sanity.sh b/t/t0204-gettext-reencode-sanity.sh index 4f2e0dcb02..310a450012 100755 --- a/t/t0204-gettext-reencode-sanity.sh +++ b/t/t0204-gettext-reencode-sanity.sh @@ -82,7 +82,7 @@ test_expect_success GETTEXT_ISO_LOCALE 'gettext.c: git init UTF-8 -> ISO-8859-1' printf "Bjó til tóma Git lind" >expect && LANGUAGE=is LC_ALL="$is_IS_iso_locale" git init repo >actual && test_when_finished "rm -rf repo" && - grep "^$(cat expect | iconv -f UTF-8 -t ISO8859-1) " actual + grep "^$(iconv -f UTF-8 -t ISO8859-1 <expect) " actual ' test_done diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh index 290b6eaaab..13ef69b92f 100755 --- a/t/t0211-trace2-perf.sh +++ b/t/t0211-trace2-perf.sh @@ -287,4 +287,235 @@ test_expect_success 'unsafe URLs are redacted by default' ' grep "d0|main|def_param|.*|remote.origin.url:https://user:pwd@example.com" actual ' +# Confirm that the requested command produces a "cmd_name" and a +# set of "def_param" events. +# +try_simple () { + test_when_finished "rm prop.perf actual" && + + cmd=$1 && + cmd_name=$2 && + + test_config_global "trace2.configParams" "cfg.prop.*" && + test_config_global "trace2.envvars" "ENV_PROP_FOO,ENV_PROP_BAR" && + + test_config_global "cfg.prop.foo" "red" && + + ENV_PROP_FOO=blue \ + GIT_TRACE2_PERF="$(pwd)/prop.perf" \ + $cmd && + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <prop.perf >actual && + grep "d0|main|cmd_name|.*|$cmd_name" actual && + grep "d0|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d0|main|def_param|.*|ENV_PROP_FOO:blue" actual +} + +# Representative mainstream builtin Git command dispatched +# in run_builtin() in git.c +# +test_expect_success 'expect def_params for normal builtin command' ' + try_simple "git version" "version" +' + +# Representative query command dispatched in handle_options() +# in git.c +# +test_expect_success 'expect def_params for query command' ' + try_simple "git --man-path" "_query_" +' + +# remote-curl.c does not use the builtin setup in git.c, so confirm +# that executables built from remote-curl.c emit def_params. +# +# Also tests the dashed-command handling where "git foo" silently +# spawns "git-foo". Make sure that both commands should emit +# def_params. +# +# Pass bogus arguments to remote-https and allow the command to fail +# because we don't actually have a remote to fetch from. We just want +# to see the run-dashed code run an executable built from +# 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_when_finished "rm prop.perf actual" && + + test_config_global "trace2.configParams" "cfg.prop.*" && + test_config_global "trace2.envvars" "ENV_PROP_FOO,ENV_PROP_BAR" && + + test_config_global "cfg.prop.foo" "red" && + + test_might_fail env \ + ENV_PROP_FOO=blue \ + GIT_TRACE2_PERF="$(pwd)/prop.perf" \ + git remote-http x y && + + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <prop.perf >actual && + + grep "d0|main|cmd_name|.*|_run_dashed_" actual && + grep "d0|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d0|main|def_param|.*|ENV_PROP_FOO:blue" actual && + + grep "d1|main|cmd_name|.*|remote-curl" actual && + grep "d1|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d1|main|def_param|.*|ENV_PROP_FOO:blue" actual +' + +# Similarly, `git-http-fetch` is not built from git.c so do a +# trivial fetch so that the main git.c run-dashed code spawns +# 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_when_finished "rm prop.perf actual" && + + test_config_global "trace2.configParams" "cfg.prop.*" && + test_config_global "trace2.envvars" "ENV_PROP_FOO,ENV_PROP_BAR" && + + test_config_global "cfg.prop.foo" "red" && + + test_might_fail env \ + ENV_PROP_FOO=blue \ + GIT_TRACE2_PERF="$(pwd)/prop.perf" \ + git http-fetch --stdin file:/// <<-EOF && + EOF + + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <prop.perf >actual && + + grep "d0|main|cmd_name|.*|_run_dashed_" actual && + grep "d0|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d0|main|def_param|.*|ENV_PROP_FOO:blue" actual && + + grep "d1|main|cmd_name|.*|http-fetch" actual && + grep "d1|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d1|main|def_param|.*|ENV_PROP_FOO:blue" actual +' + +# Historically, alias expansion explicitly emitted the def_param +# events (independent of whether the command was a builtin, a Git +# command or arbitrary shell command) so that it wasn't dependent +# upon the unpeeling of the alias. Let's make sure that we preserve +# the net effect. +# +test_expect_success 'expect def_params during git alias expansion' ' + test_when_finished "rm prop.perf actual" && + + test_config_global "trace2.configParams" "cfg.prop.*" && + test_config_global "trace2.envvars" "ENV_PROP_FOO,ENV_PROP_BAR" && + + test_config_global "cfg.prop.foo" "red" && + + test_config_global "alias.xxx" "version" && + + ENV_PROP_FOO=blue \ + GIT_TRACE2_PERF="$(pwd)/prop.perf" \ + git xxx && + + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <prop.perf >actual && + + # "git xxx" is first mapped to "git-xxx" and the child will fail. + grep "d0|main|cmd_name|.*|_run_dashed_ (_run_dashed_)" actual && + + # We unpeel that and substitute "version" into "xxx" (giving + # "git version") and update the cmd_name event. + grep "d0|main|cmd_name|.*|_run_git_alias_ (_run_dashed_/_run_git_alias_)" actual && + + # These def_param events could be associated with either of the + # above cmd_name events. It does not matter. + grep "d0|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d0|main|def_param|.*|ENV_PROP_FOO:blue" actual && + + # The "git version" child sees a different cmd_name hierarchy. + # Also test the def_param (only for completeness). + grep "d1|main|cmd_name|.*|version (_run_dashed_/_run_git_alias_/version)" actual && + grep "d1|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d1|main|def_param|.*|ENV_PROP_FOO:blue" actual +' + +test_expect_success 'expect def_params during shell alias expansion' ' + test_when_finished "rm prop.perf actual" && + + test_config_global "trace2.configParams" "cfg.prop.*" && + test_config_global "trace2.envvars" "ENV_PROP_FOO,ENV_PROP_BAR" && + + test_config_global "cfg.prop.foo" "red" && + + test_config_global "alias.xxx" "!git version" && + + ENV_PROP_FOO=blue \ + GIT_TRACE2_PERF="$(pwd)/prop.perf" \ + git xxx && + + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <prop.perf >actual && + + # "git xxx" is first mapped to "git-xxx" and the child will fail. + grep "d0|main|cmd_name|.*|_run_dashed_ (_run_dashed_)" actual && + + # We unpeel that and substitute "git version" for "git xxx" (as a + # shell command. Another cmd_name event is emitted as we unpeel. + grep "d0|main|cmd_name|.*|_run_shell_alias_ (_run_dashed_/_run_shell_alias_)" actual && + + # These def_param events could be associated with either of the + # above cmd_name events. It does not matter. + grep "d0|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d0|main|def_param|.*|ENV_PROP_FOO:blue" actual && + + # We get the following only because we used a git command for the + # shell command. In general, it could have been a shell script and + # we would see nothing. + # + # The child knows the cmd_name hierarchy so it includes it. + grep "d1|main|cmd_name|.*|version (_run_dashed_/_run_shell_alias_/version)" actual && + grep "d1|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d1|main|def_param|.*|ENV_PROP_FOO:blue" actual +' + +test_expect_success 'expect def_params during nested git alias expansion' ' + test_when_finished "rm prop.perf actual" && + + test_config_global "trace2.configParams" "cfg.prop.*" && + test_config_global "trace2.envvars" "ENV_PROP_FOO,ENV_PROP_BAR" && + + test_config_global "cfg.prop.foo" "red" && + + test_config_global "alias.xxx" "yyy" && + test_config_global "alias.yyy" "version" && + + ENV_PROP_FOO=blue \ + GIT_TRACE2_PERF="$(pwd)/prop.perf" \ + git xxx && + + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <prop.perf >actual && + + # "git xxx" is first mapped to "git-xxx" and try to spawn "git-xxx" + # and the child will fail. + grep "d0|main|cmd_name|.*|_run_dashed_ (_run_dashed_)" actual && + grep "d0|main|child_start|.*|.* class:dashed argv:\[git-xxx\]" actual && + + # We unpeel that and substitute "yyy" into "xxx" (giving "git yyy") + # and spawn "git-yyy" and the child will fail. + grep "d0|main|alias|.*|alias:xxx argv:\[yyy\]" actual && + grep "d0|main|cmd_name|.*|_run_dashed_ (_run_dashed_/_run_dashed_)" actual && + grep "d0|main|child_start|.*|.* class:dashed argv:\[git-yyy\]" actual && + + # We unpeel that and substitute "version" into "xxx" (giving + # "git version") and update the cmd_name event. + grep "d0|main|alias|.*|alias:yyy argv:\[version\]" actual && + grep "d0|main|cmd_name|.*|_run_git_alias_ (_run_dashed_/_run_dashed_/_run_git_alias_)" actual && + + # These def_param events could be associated with any of the + # above cmd_name events. It does not matter. + grep "d0|main|def_param|.*|cfg.prop.foo:red" actual >actual.matches && + grep "d0|main|def_param|.*|ENV_PROP_FOO:blue" actual && + + # However, we do not want them repeated each time we unpeel. + test_line_count = 1 actual.matches && + + # The "git version" child sees a different cmd_name hierarchy. + # Also test the def_param (only for completeness). + grep "d1|main|cmd_name|.*|version (_run_dashed_/_run_dashed_/_run_git_alias_/version)" actual && + grep "d1|main|def_param|.*|cfg.prop.foo:red" actual && + grep "d1|main|def_param|.*|ENV_PROP_FOO:blue" actual +' + test_done diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh index 8300faadea..f2c146fa2a 100755 --- a/t/t0301-credential-cache.sh +++ b/t/t0301-credential-cache.sh @@ -8,6 +8,14 @@ test -z "$NO_UNIX_SOCKETS" || { skip_all='skipping credential-cache tests, unix sockets not available' test_done } +if test_have_prereq MINGW +then + service_running=$(sc query afunix | grep "4 RUNNING") + test -z "$service_running" || { + skip_all='skipping credential-cache tests, unix sockets not available' + test_done + } +fi uname_s=$(uname -s) case $uname_s in diff --git a/t/t0303-credential-external.sh b/t/t0303-credential-external.sh index 095574bfc6..72ae405c3e 100755 --- a/t/t0303-credential-external.sh +++ b/t/t0303-credential-external.sh @@ -32,9 +32,24 @@ commands. . ./test-lib.sh . "$TEST_DIRECTORY"/lib-credential.sh +# If we're not given a specific external helper to run against, +# there isn't much to test. But we can still run through our +# battery of tests with a fake helper and check that the +# test themselves are self-consistent and clean up after +# themselves. +# +# We'll use the "store" helper, since we can easily inspect +# its state by looking at the on-disk file. But since it doesn't +# implement any caching or expiry logic, we'll cheat and override +# the "check" function to just report all results as OK. if test -z "$GIT_TEST_CREDENTIAL_HELPER"; then - skip_all="used to test external credential helpers" - test_done + GIT_TEST_CREDENTIAL_HELPER=store + GIT_TEST_CREDENTIAL_HELPER_TIMEOUT=store + check () { + test "$1" = "approve" || return 0 + git -c credential.helper=store credential approve + } + check_cleanup=t fi test -z "$GIT_TEST_CREDENTIAL_HELPER_SETUP" || @@ -59,4 +74,11 @@ fi # might be long-term system storage helper_test_clean "$GIT_TEST_CREDENTIAL_HELPER" +if test "$check_cleanup" = "t" +then + test_expect_success 'test cleanup removes everything' ' + test_must_be_empty "$HOME/.git-credentials" + ' +fi + test_done diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh index 6b6424b3df..88a66f0904 100755 --- a/t/t0410-partial-clone.sh +++ b/t/t0410-partial-clone.sh @@ -49,7 +49,7 @@ test_expect_success 'convert shallow clone to partial clone' ' test_cmp_config -C client 1 core.repositoryformatversion ' -test_expect_success SHA1,REFFILES 'convert to partial clone with noop extension' ' +test_expect_success DEFAULT_REPO_FORMAT 'convert to partial clone with noop extension' ' rm -fr server client && test_create_repo server && test_commit -C server my_commit 1 && @@ -60,7 +60,7 @@ test_expect_success SHA1,REFFILES 'convert to partial clone with noop extension' git -C client fetch --unshallow --filter="blob:none" ' -test_expect_success SHA1,REFFILES 'converting to partial clone fails with unrecognized extension' ' +test_expect_success DEFAULT_REPO_FORMAT 'converting to partial clone fails with unrecognized extension' ' rm -fr server client && test_create_repo server && test_commit -C server my_commit 1 && @@ -665,6 +665,21 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' ' git -C partial.git rev-list --objects --missing=print HEAD >out && grep "[?]$FILE_HASH" out && + # The no-lazy-fetch mechanism prevents Git from fetching + test_must_fail env GIT_NO_LAZY_FETCH=1 \ + git -C partial.git cat-file -e "$FILE_HASH" && + + # The same with command line option to "git" + test_must_fail git --no-lazy-fetch -C partial.git cat-file -e "$FILE_HASH" && + + # The same, forcing a subprocess via an alias + test_must_fail git --no-lazy-fetch -C partial.git \ + -c alias.foo="!git cat-file" foo -e "$FILE_HASH" && + + # Sanity check that the file is still missing + git -C partial.git rev-list --objects --missing=print HEAD >out && + grep "[?]$FILE_HASH" out && + git -C full cat-file -s "$FILE_HASH" >expect && test-tool partial-clone object-info partial.git "$FILE_HASH" >actual && test_cmp expect actual && diff --git a/t/t0450-txt-doc-vs-help.sh b/t/t0450-txt-doc-vs-help.sh index cd3969e852..69917d7b84 100755 --- a/t/t0450-txt-doc-vs-help.sh +++ b/t/t0450-txt-doc-vs-help.sh @@ -59,7 +59,9 @@ txt_to_synopsis () { -e '/^\[verse\]$/,/^$/ { /^$/d; /^\[verse\]$/d; - + s/_//g; + s/++//g; + s/`//g; s/{litdd}/--/g; s/'\''\(git[ a-z-]*\)'\''/\1/g; diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh index e6a5f1868f..64214340e7 100755 --- a/t/t0600-reffiles-backend.sh +++ b/t/t0600-reffiles-backend.sh @@ -279,31 +279,31 @@ test_expect_success 'setup worktree' ' # 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()' ' - echo $ZERO_OID > .git/logs/PSEUDO-MAIN && + echo $ZERO_OID >.git/logs/PSEUDO_MAIN_HEAD && mkdir -p .git/logs/refs/bisect && - echo $ZERO_OID > .git/logs/refs/bisect/random && + echo $ZERO_OID >.git/logs/refs/bisect/random && - echo $ZERO_OID > .git/worktrees/wt/logs/PSEUDO-WT && + echo $ZERO_OID >.git/worktrees/wt/logs/PSEUDO_WT_HEAD && mkdir -p .git/worktrees/wt/logs/refs/bisect && - echo $ZERO_OID > .git/worktrees/wt/logs/refs/bisect/wt-random && + echo $ZERO_OID >.git/worktrees/wt/logs/refs/bisect/wt-random && - $RWT for-each-reflog | cut -d" " -f 2- | sort >actual && + $RWT for-each-reflog >actual && cat >expected <<-\EOF && - HEAD 0x1 - PSEUDO-WT 0x0 - refs/bisect/wt-random 0x0 - refs/heads/main 0x0 - refs/heads/wt-main 0x0 + HEAD + PSEUDO_WT_HEAD + refs/bisect/wt-random + refs/heads/main + refs/heads/wt-main EOF test_cmp expected actual && - $RMAIN for-each-reflog | cut -d" " -f 2- | sort >actual && + $RMAIN for-each-reflog >actual && cat >expected <<-\EOF && - HEAD 0x1 - PSEUDO-MAIN 0x0 - refs/bisect/random 0x0 - refs/heads/main 0x0 - refs/heads/wt-main 0x0 + HEAD + PSEUDO_MAIN_HEAD + refs/bisect/random + refs/heads/main + refs/heads/wt-main EOF test_cmp expected actual ' @@ -381,4 +381,95 @@ test_expect_success 'log diagnoses bogus HEAD symref' ' test_grep broken stderr ' +test_expect_success 'empty directory removal' ' + git branch d1/d2/r1 HEAD && + git branch d1/r2 HEAD && + test_path_is_file .git/refs/heads/d1/d2/r1 && + test_path_is_file .git/logs/refs/heads/d1/d2/r1 && + git branch -d d1/d2/r1 && + test_must_fail git show-ref --verify -q refs/heads/d1/d2 && + test_must_fail git show-ref --verify -q logs/refs/heads/d1/d2 && + test_path_is_file .git/refs/heads/d1/r2 && + test_path_is_file .git/logs/refs/heads/d1/r2 +' + +test_expect_success 'symref empty directory removal' ' + git branch e1/e2/r1 HEAD && + git branch e1/r2 HEAD && + git checkout e1/e2/r1 && + test_when_finished "git checkout main" && + test_path_is_file .git/refs/heads/e1/e2/r1 && + test_path_is_file .git/logs/refs/heads/e1/e2/r1 && + git update-ref -d HEAD && + test_must_fail git show-ref --verify -q refs/heads/e1/e2 && + test_must_fail git show-ref --verify -q logs/refs/heads/e1/e2 && + test_path_is_file .git/refs/heads/e1/r2 && + test_path_is_file .git/logs/refs/heads/e1/r2 && + test_path_is_file .git/logs/HEAD +' + +test_expect_success 'directory not created deleting packed ref' ' + git branch d1/d2/r1 HEAD && + git pack-refs --all && + test_path_is_missing .git/refs/heads/d1/d2 && + git update-ref -d refs/heads/d1/d2/r1 && + test_path_is_missing .git/refs/heads/d1/d2 && + test_path_is_missing .git/refs/heads/d1 +' + +test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for u is a symlink' ' + git branch --create-reflog u && + mv .git/logs/refs/heads/u real-u && + ln -s real-u .git/logs/refs/heads/u && + test_must_fail git branch -m u v +' + +test_expect_success SYMLINKS 'git branch -m with symlinked .git/refs' ' + test_when_finished "rm -rf subdir" && + git init --bare subdir && + + rm -rfv subdir/refs subdir/objects subdir/packed-refs && + ln -s ../.git/refs subdir/refs && + ln -s ../.git/objects subdir/objects && + ln -s ../.git/packed-refs subdir/packed-refs && + + git -C subdir rev-parse --absolute-git-dir >subdir.dir && + git rev-parse --absolute-git-dir >our.dir && + ! test_cmp subdir.dir our.dir && + + git -C subdir log && + git -C subdir branch rename-src && + git rev-parse rename-src >expect && + git -C subdir branch -m rename-src rename-dest && + git rev-parse rename-dest >actual && + test_cmp expect actual && + git branch -D rename-dest +' + +test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' ' + git checkout main && + mv .git/logs actual_logs && + cmd //c "mklink /D .git\logs ..\actual_logs" && + git rebase -f HEAD^ && + test -L .git/logs && + rm .git/logs && + mv actual_logs .git/logs +' + +test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' ' + umask 077 && + git config core.sharedRepository group && + git reflog expire --all && + actual="$(ls -l .git/logs/refs/heads/main)" && + case "$actual" in + -rw-rw-*) + : happy + ;; + *) + echo Ooops, .git/logs/refs/heads/main is not 066x [$actual] + false + ;; + esac +' + test_done diff --git a/t/t0601-reffiles-pack-refs.sh b/t/t0601-reffiles-pack-refs.sh index c309d2bae8..7d4ab0b91a 100755 --- a/t/t0601-reffiles-pack-refs.sh +++ b/t/t0601-reffiles-pack-refs.sh @@ -32,11 +32,16 @@ test_expect_success 'prepare a trivial repository' ' HEAD=$(git rev-parse --verify HEAD) ' -test_expect_success 'pack_refs(PACK_REFS_ALL | PACK_REFS_PRUNE)' ' - N=`find .git/refs -type f | wc -l` && +test_expect_success 'pack-refs --prune --all' ' + test_path_is_missing .git/packed-refs && + git pack-refs --no-prune --all && + test_path_is_file .git/packed-refs && + N=$(find .git/refs -type f | wc -l) && test "$N" != 0 && - test-tool ref-store main pack-refs PACK_REFS_PRUNE,PACK_REFS_ALL && - N=`find .git/refs -type f` && + + git pack-refs --prune --all && + test_path_is_file .git/packed-refs && + N=$(find .git/refs -type f) && test -z "$N" ' @@ -159,6 +164,13 @@ 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 && @@ -358,4 +370,14 @@ 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 +' + test_done diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh new file mode 100755 index 0000000000..178791e086 --- /dev/null +++ b/t/t0610-reftable-basics.sh @@ -0,0 +1,1032 @@ +#!/bin/sh +# +# Copyright (c) 2020 Google LLC +# + +test_description='reftable basics' +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +if ! test_have_prereq REFTABLE +then + skip_all='skipping reftable tests; set GIT_TEST_DEFAULT_REF_FORMAT=reftable' + test_done +fi + +INVALID_OID=$(test_oid 001) + +test_expect_success 'init: creates basic reftable structures' ' + test_when_finished "rm -rf repo" && + git init repo && + test_path_is_dir repo/.git/reftable && + test_path_is_file repo/.git/reftable/tables.list && + echo reftable >expect && + git -C repo rev-parse --show-ref-format >actual && + test_cmp expect actual +' + +test_expect_success 'init: sha256 object format via environment variable' ' + test_when_finished "rm -rf repo" && + GIT_DEFAULT_HASH=sha256 git init repo && + cat >expect <<-EOF && + sha256 + reftable + EOF + git -C repo rev-parse --show-object-format --show-ref-format >actual && + test_cmp expect actual +' + +test_expect_success 'init: sha256 object format via option' ' + test_when_finished "rm -rf repo" && + git init --object-format=sha256 repo && + cat >expect <<-EOF && + sha256 + reftable + EOF + git -C repo rev-parse --show-object-format --show-ref-format >actual && + test_cmp expect actual +' + +test_expect_success 'init: reinitializing reftable backend succeeds' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo A && + + git -C repo for-each-ref >expect && + git init --ref-format=reftable repo && + git -C repo for-each-ref >actual && + test_cmp expect actual +' + +test_expect_success 'init: reinitializing files with reftable backend fails' ' + test_when_finished "rm -rf repo" && + git init --ref-format=files repo && + test_commit -C repo file && + + cp repo/.git/HEAD expect && + test_must_fail git init --ref-format=reftable repo && + test_cmp expect repo/.git/HEAD +' + +test_expect_success 'init: reinitializing reftable with files backend fails' ' + test_when_finished "rm -rf repo" && + git init --ref-format=reftable repo && + test_commit -C repo file && + + cp repo/.git/HEAD expect && + test_must_fail git init --ref-format=files repo && + test_cmp expect repo/.git/HEAD +' + +test_expect_perms () { + local perms="$1" + local file="$2" + local actual="$(ls -l "$file")" && + + case "$actual" in + $perms*) + : happy + ;; + *) + echo "$(basename $2) is not $perms but $actual" + false + ;; + esac +} + +test_expect_reftable_perms () { + local umask="$1" + local shared="$2" + local expect="$3" + + test_expect_success POSIXPERM "init: honors --shared=$shared with umask $umask" ' + test_when_finished "rm -rf repo" && + ( + umask $umask && + git init --shared=$shared repo + ) && + test_expect_perms "$expect" repo/.git/reftable/tables.list && + for table in repo/.git/reftable/*.ref + do + test_expect_perms "$expect" "$table" || + return 1 + done + ' + + test_expect_success POSIXPERM "pack-refs: honors --shared=$shared with umask $umask" ' + test_when_finished "rm -rf repo" && + ( + umask $umask && + git init --shared=$shared repo && + test_commit -C repo A && + test_line_count = 2 repo/.git/reftable/tables.list && + git -C repo pack-refs + ) && + test_expect_perms "$expect" repo/.git/reftable/tables.list && + for table in repo/.git/reftable/*.ref + do + test_expect_perms "$expect" "$table" || + return 1 + done + ' +} + +test_expect_reftable_perms 002 umask "-rw-rw-r--" +test_expect_reftable_perms 022 umask "-rw-r--r--" +test_expect_reftable_perms 027 umask "-rw-r-----" + +test_expect_reftable_perms 002 group "-rw-rw-r--" +test_expect_reftable_perms 022 group "-rw-rw-r--" +test_expect_reftable_perms 027 group "-rw-rw----" + +test_expect_reftable_perms 002 world "-rw-rw-r--" +test_expect_reftable_perms 022 world "-rw-rw-r--" +test_expect_reftable_perms 027 world "-rw-rw-r--" + +test_expect_success 'clone: can clone reftable repository' ' + test_when_finished "rm -rf repo clone" && + git init repo && + test_commit -C repo message1 file1 && + + git clone repo cloned && + echo reftable >expect && + git -C cloned rev-parse --show-ref-format >actual && + test_cmp expect actual && + test_path_is_file cloned/file1 +' + +test_expect_success 'clone: can clone reffiles into reftable repository' ' + test_when_finished "rm -rf reffiles reftable" && + git init --ref-format=files reffiles && + test_commit -C reffiles A && + git clone --ref-format=reftable ./reffiles reftable && + + git -C reffiles rev-parse HEAD >expect && + git -C reftable rev-parse HEAD >actual && + test_cmp expect actual && + + git -C reftable rev-parse --show-ref-format >actual && + echo reftable >expect && + test_cmp expect actual && + + git -C reffiles rev-parse --show-ref-format >actual && + echo files >expect && + test_cmp expect actual +' + +test_expect_success 'clone: can clone reftable into reffiles repository' ' + test_when_finished "rm -rf reffiles reftable" && + git init --ref-format=reftable reftable && + test_commit -C reftable A && + git clone --ref-format=files ./reftable reffiles && + + git -C reftable rev-parse HEAD >expect && + git -C reffiles rev-parse HEAD >actual && + test_cmp expect actual && + + git -C reftable rev-parse --show-ref-format >actual && + echo reftable >expect && + test_cmp expect actual && + + git -C reffiles rev-parse --show-ref-format >actual && + echo files >expect && + test_cmp expect actual +' + +test_expect_success 'ref transaction: corrupted tables cause failure' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit file1 && + for f in .git/reftable/*.ref + do + : >"$f" || return 1 + done && + test_must_fail git update-ref refs/heads/main HEAD + ) +' + +test_expect_success 'ref transaction: corrupted tables.list cause failure' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit file1 && + echo garbage >.git/reftable/tables.list && + test_must_fail git update-ref refs/heads/main HEAD + ) +' + +test_expect_success 'ref transaction: refuses to write ref causing F/D conflict' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo file && + test_must_fail git -C repo update-ref refs/heads/main/forbidden +' + +test_expect_success 'ref transaction: deleting ref with invalid name fails' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo file && + test_must_fail git -C repo update-ref -d ../../my-private-file +' + +test_expect_success 'ref transaction: can skip object ID verification' ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID 0 && + test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION +' + +test_expect_success 'ref transaction: updating same ref multiple times fails' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo A && + cat >updates <<-EOF && + update refs/heads/main $A + update refs/heads/main $A + EOF + cat >expect <<-EOF && + fatal: multiple updates for ref ${SQ}refs/heads/main${SQ} not allowed + EOF + test_must_fail git -C repo update-ref --stdin <updates 2>err && + test_cmp expect err +' + +test_expect_success 'ref transaction: can delete symbolic self-reference with git-symbolic-ref(1)' ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo symbolic-ref refs/heads/self refs/heads/self && + git -C repo symbolic-ref -d refs/heads/self +' + +test_expect_success 'ref transaction: deleting symbolic self-reference without --no-deref fails' ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo symbolic-ref refs/heads/self refs/heads/self && + cat >expect <<-EOF && + error: multiple updates for ${SQ}refs/heads/self${SQ} (including one via symref ${SQ}refs/heads/self${SQ}) are not allowed + EOF + test_must_fail git -C repo update-ref -d refs/heads/self 2>err && + test_cmp expect err +' + +test_expect_success 'ref transaction: deleting symbolic self-reference with --no-deref succeeds' ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo symbolic-ref refs/heads/self refs/heads/self && + git -C repo update-ref -d --no-deref refs/heads/self +' + +test_expect_success 'ref transaction: creating symbolic ref fails with F/D conflict' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo A && + cat >expect <<-EOF && + error: unable to write symref for refs/heads: file/directory conflict + EOF + test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err && + test_cmp expect err +' + +test_expect_success 'ref transaction: ref deletion' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit file && + HEAD_OID=$(git show-ref -s --verify HEAD) && + cat >expect <<-EOF && + $HEAD_OID refs/heads/main + $HEAD_OID refs/tags/file + EOF + git show-ref >actual && + test_cmp expect actual && + + test_must_fail git update-ref -d refs/tags/file $INVALID_OID && + git show-ref >actual && + test_cmp expect actual && + + git update-ref -d refs/tags/file $HEAD_OID && + echo "$HEAD_OID refs/heads/main" >expect && + git show-ref >actual && + test_cmp expect actual + ) +' + +test_expect_success 'ref transaction: writes cause auto-compaction' ' + test_when_finished "rm -rf repo" && + + git init repo && + test_line_count = 1 repo/.git/reftable/tables.list && + + test_commit -C repo --no-tag A && + test_line_count = 1 repo/.git/reftable/tables.list && + + test_commit -C repo --no-tag B && + test_line_count = 1 repo/.git/reftable/tables.list +' + +test_expect_success 'ref transaction: env var disables compaction' ' + test_when_finished "rm -rf repo" && + + git init repo && + test_commit -C repo A && + + start=$(wc -l <repo/.git/reftable/tables.list) && + iterations=5 && + expected=$((start + iterations)) && + + for i in $(test_seq $iterations) + do + GIT_TEST_REFTABLE_AUTOCOMPACTION=false \ + git -C repo update-ref branch-$i HEAD || return 1 + done && + test_line_count = $expected repo/.git/reftable/tables.list && + + git -C repo update-ref foo HEAD && + test_line_count -lt $expected repo/.git/reftable/tables.list +' + +test_expect_success 'ref transaction: alternating table sizes are compacted' ' + test_when_finished "rm -rf repo" && + + git init repo && + test_commit -C repo A && + for i in $(test_seq 5) + do + git -C repo branch -f foo && + git -C repo branch -d foo || return 1 + done && + test_line_count = 2 repo/.git/reftable/tables.list +' + +check_fsync_events () { + local trace="$1" && + shift && + + cat >expect && + sed -n \ + -e '/^{"event":"counter",.*"category":"fsync",/ { + s/.*"category":"fsync",//; + s/}$//; + p; + }' \ + <"$trace" >actual && + test_cmp expect actual +} + +test_expect_success 'ref transaction: writes are synced' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo initial && + + GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ + GIT_TEST_FSYNC=true \ + git -C repo -c core.fsync=reference \ + -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD && + check_fsync_events trace2.txt <<-EOF + "name":"hardware-flush","count":4 + EOF +' + +test_expect_success 'ref transaction: empty transaction in empty repo' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo --no-tag A && + git -C repo update-ref -d refs/heads/main && + test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD && + git -C repo update-ref --stdin <<-EOF + prepare + commit + EOF +' + +test_expect_success 'ref transaction: fails gracefully when auto compaction fails' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit A && + for i in $(test_seq 10) + do + git branch branch-$i && + for table in .git/reftable/*.ref + do + touch "$table.lock" || exit 1 + done || + exit 1 + done && + test_line_count = 10 .git/reftable/tables.list + ) +' + +test_expect_success 'pack-refs: compacts tables' ' + test_when_finished "rm -rf repo" && + git init repo && + + test_commit -C repo A && + ls -1 repo/.git/reftable >table-files && + test_line_count = 3 table-files && + test_line_count = 2 repo/.git/reftable/tables.list && + + git -C repo pack-refs && + ls -1 repo/.git/reftable >table-files && + test_line_count = 2 table-files && + test_line_count = 1 repo/.git/reftable/tables.list +' + +test_expect_success 'pack-refs: compaction raises locking errors' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo A && + touch repo/.git/reftable/tables.list.lock && + cat >expect <<-EOF && + error: unable to compact stack: data is locked + EOF + test_must_fail git -C repo pack-refs 2>err && + test_cmp expect err +' + +for command in pack-refs gc "maintenance run --task=pack-refs" +do +test_expect_success "$command: auto compaction" ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit A && + + # We need a bit of setup to ensure that git-gc(1) actually + # triggers, and that it does not write anything to the refdb. + git config gc.auto 1 && + git config gc.autoDetach 0 && + git config gc.reflogExpire never && + git config gc.reflogExpireUnreachable never && + test_oid blob17_1 | git hash-object -w --stdin && + + # The tables should have been auto-compacted, and thus auto + # compaction should not have to do anything. + ls -1 .git/reftable >tables-expect && + test_line_count = 3 tables-expect && + git $command --auto && + ls -1 .git/reftable >tables-actual && + test_cmp tables-expect tables-actual && + + 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 | + while read table + do + touch "$table.lock" || exit 1 + done && + git branch B && + git branch C && + rm .git/reftable/*.lock && + test_line_count = 4 .git/reftable/tables.list && + + git $command --auto && + test_line_count = 1 .git/reftable/tables.list + ) +' +done + +test_expect_success 'pack-refs: prunes stale tables' ' + test_when_finished "rm -rf repo" && + git init repo && + touch repo/.git/reftable/stale-table.ref && + git -C repo pack-refs && + test_path_is_missing repo/.git/reftable/stable-ref.ref +' + +test_expect_success 'pack-refs: does not prune non-table files' ' + test_when_finished "rm -rf repo" && + git init repo && + touch repo/.git/reftable/garbage && + git -C repo pack-refs && + test_path_is_file repo/.git/reftable/garbage +' + +test_expect_success 'packed-refs: writes are synced' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo initial && + test_line_count = 2 table-files && + + : >trace2.txt && + GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ + GIT_TEST_FSYNC=true \ + git -C repo -c core.fsync=reference \ + -c core.fsyncMethod=fsync pack-refs && + check_fsync_events trace2.txt <<-EOF + "name":"hardware-flush","count":2 + EOF +' + +test_expect_success 'ref iterator: bogus names are flagged' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit --no-tag file && + test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + + cat >expect <<-EOF && + $ZERO_OID refs/heads/bogus..name 0xc + $(git rev-parse HEAD) refs/heads/main 0x0 + EOF + test-tool ref-store main for-each-ref "" >actual && + test_cmp expect actual + ) +' + +test_expect_success 'ref iterator: missing object IDs are not flagged' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION && + + cat >expect <<-EOF && + $INVALID_OID refs/heads/broken-hash 0x0 + EOF + test-tool ref-store main for-each-ref "" >actual && + test_cmp expect actual + ) +' + +test_expect_success 'basic: commit and list refs' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo file && + test_write_lines refs/heads/main refs/tags/file >expect && + git -C repo for-each-ref --format="%(refname)" >actual && + test_cmp actual expect +' + +test_expect_success 'basic: can write large commit message' ' + test_when_finished "rm -rf repo" && + git init repo && + perl -e " + print \"this is a long commit message\" x 50000 + " >commit-msg && + git -C repo commit --allow-empty --file=../commit-msg +' + +test_expect_success 'basic: show-ref fails with empty repository' ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail git -C repo show-ref >actual && + test_must_be_empty actual +' + +test_expect_success 'basic: can check out unborn branch' ' + test_when_finished "rm -rf repo" && + git init repo && + git -C repo checkout -b main +' + +test_expect_success 'basic: peeled tags are stored' ' + test_when_finished "rm -rf repo" && + git init repo && + test_commit -C repo file && + git -C repo tag -m "annotated tag" test_tag HEAD && + for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{} + do + echo "$(git -C repo rev-parse "$ref") $ref" || return 1 + done >expect && + git -C repo show-ref -d >actual && + test_cmp expect actual +' + +test_expect_success 'basic: for-each-ref can print symrefs' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit file && + git branch && + git symbolic-ref refs/heads/sym refs/heads/main && + cat >expected <<-EOF && + refs/heads/main + EOF + git for-each-ref --format="%(symref)" refs/heads/sym >actual && + test_cmp expected actual + ) +' + +test_expect_success 'basic: notes' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + write_script fake_editor <<-\EOF && + echo "$MSG" >"$1" + echo "$MSG" >&2 + EOF + + test_commit 1st && + test_commit 2nd && + GIT_EDITOR=./fake_editor MSG=b4 git notes add && + GIT_EDITOR=./fake_editor MSG=b3 git notes edit && + echo b4 >expect && + git notes --ref commits@{1} show >actual && + test_cmp expect actual + ) +' + +test_expect_success 'basic: stash' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit file && + git stash list >expect && + test_line_count = 0 expect && + + echo hoi >>file.t && + git stash push -m stashed && + git stash list >expect && + test_line_count = 1 expect && + + git stash clear && + git stash list >expect && + test_line_count = 0 expect + ) +' + +test_expect_success 'basic: cherry-pick' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit message1 file1 && + test_commit message2 file2 && + git branch source && + git checkout HEAD^ && + test_commit message3 file3 && + git cherry-pick source && + test_path_is_file file2 + ) +' + +test_expect_success 'basic: rebase' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit message1 file1 && + test_commit message2 file2 && + git branch source && + git checkout HEAD^ && + test_commit message3 file3 && + git rebase source && + test_path_is_file file2 + ) +' + +test_expect_success 'reflog: can delete separate reflog entries' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit file && + test_commit file2 && + test_commit file3 && + test_commit file4 && + git reflog >actual && + grep file3 actual && + + git reflog delete HEAD@{1} && + git reflog >actual && + ! grep file3 actual + ) +' + +test_expect_success 'reflog: can switch to previous branch' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit file1 && + git checkout -b branch1 && + test_commit file2 && + git checkout -b branch2 && + git switch - && + git rev-parse --symbolic-full-name HEAD >actual && + echo refs/heads/branch1 >expect && + test_cmp actual expect + ) +' + +test_expect_success 'reflog: copying branch writes reflog entry' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit file1 && + test_commit file2 && + oid=$(git rev-parse --short HEAD) && + git branch src && + cat >expect <<-EOF && + ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst + ${oid} dst@{1}: branch: Created from main + EOF + git branch -c src dst && + git reflog dst >actual && + test_cmp expect actual + ) +' + +test_expect_success 'reflog: renaming branch writes reflog entry' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git symbolic-ref HEAD refs/heads/before && + test_commit file && + git show-ref >expected.refs && + sed s/before/after/g <expected.refs >expected && + git branch -M after && + git show-ref >actual && + test_cmp expected actual && + echo refs/heads/after >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual + ) +' + +test_expect_success 'reflog: can store empty logs' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_must_fail test-tool ref-store main reflog-exists refs/heads/branch && + test-tool ref-store main create-reflog refs/heads/branch && + test-tool ref-store main reflog-exists refs/heads/branch && + test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual && + test_must_be_empty actual + ) +' + +test_expect_success 'reflog: expiry empties reflog' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit initial && + git checkout -b branch && + test_commit fileA && + test_commit fileB && + + cat >expect <<-EOF && + commit: fileB + commit: fileA + branch: Created from HEAD + EOF + git reflog show --format="%gs" refs/heads/branch >actual && + test_cmp expect actual && + + git reflog expire branch --expire=all && + git reflog show --format="%gs" refs/heads/branch >actual && + test_must_be_empty actual && + test-tool ref-store main reflog-exists refs/heads/branch + ) +' + +test_expect_success 'reflog: can be deleted' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit initial && + test-tool ref-store main reflog-exists refs/heads/main && + test-tool ref-store main delete-reflog refs/heads/main && + test_must_fail test-tool ref-store main reflog-exists refs/heads/main + ) +' + +test_expect_success 'reflog: garbage collection deletes reflog entries' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + for count in $(test_seq 1 10) + do + test_commit "number $count" file.t $count number-$count || + return 1 + done && + git reflog refs/heads/main >actual && + test_line_count = 10 actual && + grep "commit (initial): number 1" actual && + grep "commit: number 10" actual && + + git gc && + git reflog refs/heads/main >actual && + test_line_count = 0 actual + ) +' + +test_expect_success 'reflog: updates via HEAD update HEAD reflog' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit main-one && + git checkout -b new-branch && + test_commit new-one && + test_commit new-two && + + echo new-one >expect && + git log -1 --format=%s HEAD@{1} >actual && + test_cmp expect actual + ) +' + +test_expect_success 'worktree: adding worktree creates separate stack' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo A && + + git -C repo worktree add ../worktree && + test_path_is_file repo/.git/worktrees/worktree/refs/heads && + echo "ref: refs/heads/.invalid" >expect && + test_cmp expect repo/.git/worktrees/worktree/HEAD && + test_path_is_dir repo/.git/worktrees/worktree/reftable && + test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list +' + +test_expect_success 'worktree: pack-refs in main repo packs main refs' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo A && + + GIT_TEST_REFTABLE_AUTOCOMPACTION=false \ + git -C repo worktree add ../worktree && + GIT_TEST_REFTABLE_AUTOCOMPACTION=false \ + git -C worktree update-ref refs/worktree/per-worktree HEAD && + + test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 3 repo/.git/reftable/tables.list && + git -C repo pack-refs && + test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list +' + +test_expect_success 'worktree: pack-refs in worktree packs worktree refs' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo A && + + GIT_TEST_REFTABLE_AUTOCOMPACTION=false \ + git -C repo worktree add ../worktree && + GIT_TEST_REFTABLE_AUTOCOMPACTION=false \ + git -C worktree update-ref refs/worktree/per-worktree HEAD && + + test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 3 repo/.git/reftable/tables.list && + git -C worktree pack-refs && + test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 3 repo/.git/reftable/tables.list +' + +test_expect_success 'worktree: creating shared ref updates main stack' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo A && + + git -C repo worktree add ../worktree && + git -C repo pack-refs && + git -C worktree pack-refs && + test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list && + + GIT_TEST_REFTABLE_AUTOCOMPACTION=false \ + git -C worktree update-ref refs/heads/shared HEAD && + test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 2 repo/.git/reftable/tables.list +' + +test_expect_success 'worktree: creating per-worktree ref updates worktree stack' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo A && + + git -C repo worktree add ../worktree && + git -C repo pack-refs && + git -C worktree pack-refs && + test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list && + + git -C worktree update-ref refs/bisect/per-worktree HEAD && + test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list +' + +test_expect_success 'worktree: creating per-worktree ref from main repo' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo A && + + git -C repo worktree add ../worktree && + git -C repo pack-refs && + git -C worktree pack-refs && + test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list && + + git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD && + test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list +' + +test_expect_success 'worktree: creating per-worktree ref from second worktree' ' + test_when_finished "rm -rf repo wt1 wt2" && + git init repo && + test_commit -C repo A && + + git -C repo worktree add ../wt1 && + git -C repo worktree add ../wt2 && + git -C repo pack-refs && + git -C wt1 pack-refs && + git -C wt2 pack-refs && + test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list && + test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list && + + git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD && + test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list && + test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list +' + +test_expect_success 'worktree: can create shared and per-worktree ref in one transaction' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo A && + + git -C repo worktree add ../worktree && + git -C repo pack-refs && + git -C worktree pack-refs && + test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 1 repo/.git/reftable/tables.list && + + cat >stdin <<-EOF && + create worktrees/worktree/refs/bisect/per-worktree HEAD + create refs/branches/shared HEAD + EOF + git -C repo update-ref --stdin <stdin && + test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list && + test_line_count = 2 repo/.git/reftable/tables.list +' + +test_expect_success 'worktree: can access common refs' ' + test_when_finished "rm -rf repo worktree" && + git init repo && + test_commit -C repo file1 && + git -C repo branch branch1 && + git -C repo worktree add ../worktree && + + echo refs/heads/worktree >expect && + git -C worktree symbolic-ref HEAD >actual && + test_cmp expect actual && + git -C worktree checkout branch1 +' + +test_expect_success 'worktree: adds worktree with detached HEAD' ' + test_when_finished "rm -rf repo worktree" && + + git init repo && + test_commit -C repo A && + git -C repo rev-parse main >expect && + + git -C repo worktree add --detach ../worktree main && + git -C worktree rev-parse HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'fetch: accessing FETCH_HEAD special ref works' ' + test_when_finished "rm -rf repo sub" && + + git init sub && + test_commit -C sub two && + git -C sub rev-parse HEAD >expect && + + git init repo && + test_commit -C repo one && + git -C repo fetch ../sub && + git -C repo rev-parse FETCH_HEAD >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t0611-reftable-httpd.sh b/t/t0611-reftable-httpd.sh new file mode 100755 index 0000000000..5e05b9c1f2 --- /dev/null +++ b/t/t0611-reftable-httpd.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description='reftable HTTPD tests' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-httpd.sh + +start_httpd + +REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo" + +test_expect_success 'serving ls-remote' ' + git init --ref-format=reftable -b main "$REPO" && + cd "$REPO" && + test_commit m1 && + >.git/git-daemon-export-ok && + git ls-remote "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" | cut -f 2-2 -d " " >actual && + cat >expect <<-EOF && + HEAD + refs/heads/main + refs/tags/m1 + EOF + test_cmp actual expect +' + +test_done diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index e0c6482797..e12b221972 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -112,65 +112,65 @@ strlen () { run_tests () { type=$1 - sha1=$2 + oid=$2 size=$3 content=$4 pretty_content=$5 - batch_output="$sha1 $type $size + batch_output="$oid $type $size $content" test_expect_success "$type exists" ' - git cat-file -e $sha1 + git cat-file -e $oid ' test_expect_success "Type of $type is correct" ' echo $type >expect && - git cat-file -t $sha1 >actual && + git cat-file -t $oid >actual && test_cmp expect actual ' test_expect_success "Size of $type is correct" ' echo $size >expect && - git cat-file -s $sha1 >actual && + git cat-file -s $oid >actual && test_cmp expect actual ' test_expect_success "Type of $type is correct using --allow-unknown-type" ' echo $type >expect && - git cat-file -t --allow-unknown-type $sha1 >actual && + git cat-file -t --allow-unknown-type $oid >actual && test_cmp expect actual ' test_expect_success "Size of $type is correct using --allow-unknown-type" ' echo $size >expect && - git cat-file -s --allow-unknown-type $sha1 >actual && + git cat-file -s --allow-unknown-type $oid >actual && test_cmp expect actual ' test -z "$content" || test_expect_success "Content of $type is correct" ' echo_without_newline "$content" >expect && - git cat-file $type $sha1 >actual && + git cat-file $type $oid >actual && test_cmp expect actual ' test_expect_success "Pretty content of $type is correct" ' echo_without_newline "$pretty_content" >expect && - git cat-file -p $sha1 >actual && + git cat-file -p $oid >actual && test_cmp expect actual ' test -z "$content" || test_expect_success "--batch output of $type is correct" ' echo "$batch_output" >expect && - echo $sha1 | git cat-file --batch >actual && + echo $oid | git cat-file --batch >actual && test_cmp expect actual ' test_expect_success "--batch-check output of $type is correct" ' - echo "$sha1 $type $size" >expect && - echo_without_newline $sha1 | git cat-file --batch-check >actual && + echo "$oid $type $size" >expect && + echo_without_newline $oid | git cat-file --batch-check >actual && test_cmp expect actual ' @@ -179,33 +179,33 @@ $content" test -z "$content" || test_expect_success "--batch-command $opt output of $type content is correct" ' echo "$batch_output" >expect && - test_write_lines "contents $sha1" | git cat-file --batch-command $opt >actual && + test_write_lines "contents $oid" | git cat-file --batch-command $opt >actual && test_cmp expect actual ' test_expect_success "--batch-command $opt output of $type info is correct" ' - echo "$sha1 $type $size" >expect && - test_write_lines "info $sha1" | + echo "$oid $type $size" >expect && + test_write_lines "info $oid" | git cat-file --batch-command $opt >actual && test_cmp expect actual ' done test_expect_success "custom --batch-check format" ' - echo "$type $sha1" >expect && - echo $sha1 | git cat-file --batch-check="%(objecttype) %(objectname)" >actual && + echo "$type $oid" >expect && + echo $oid | git cat-file --batch-check="%(objecttype) %(objectname)" >actual && test_cmp expect actual ' test_expect_success "custom --batch-command format" ' - echo "$type $sha1" >expect && - echo "info $sha1" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual && + echo "$type $oid" >expect && + echo "info $oid" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual && test_cmp expect actual ' test_expect_success '--batch-check with %(rest)' ' echo "$type this is some extra content" >expect && - echo "$sha1 this is some extra content" | + echo "$oid this is some extra content" | git cat-file --batch-check="%(objecttype) %(rest)" >actual && test_cmp expect actual ' @@ -216,7 +216,7 @@ $content" echo "$size" && echo "$content" } >expect && - echo $sha1 | git cat-file --batch="%(objectsize)" >actual && + echo $oid | git cat-file --batch="%(objectsize)" >actual && test_cmp expect actual ' @@ -226,114 +226,154 @@ $content" echo "$type" && echo "$content" } >expect && - echo $sha1 | git cat-file --batch="%(objecttype)" >actual && + echo $oid | git cat-file --batch="%(objecttype)" >actual && test_cmp expect actual ' } hello_content="Hello World" hello_size=$(strlen "$hello_content") -hello_sha1=$(echo_without_newline "$hello_content" | git hash-object --stdin) +hello_oid=$(echo_without_newline "$hello_content" | git hash-object --stdin) test_expect_success "setup" ' + git config core.repositoryformatversion 1 && + git config extensions.objectformat $test_hash_algo && + git config extensions.compatobjectformat $test_compat_hash_algo && echo_without_newline "$hello_content" > hello && git update-index --add hello ' -run_tests 'blob' $hello_sha1 $hello_size "$hello_content" "$hello_content" +run_blob_tests () { + oid=$1 -test_expect_success '--batch-command --buffer with flush for blob info' ' - echo "$hello_sha1 blob $hello_size" >expect && - test_write_lines "info $hello_sha1" "flush" | + run_tests 'blob' $oid $hello_size "$hello_content" "$hello_content" + + test_expect_success '--batch-command --buffer with flush for blob info' ' + echo "$oid blob $hello_size" >expect && + test_write_lines "info $oid" "flush" | GIT_TEST_CAT_FILE_NO_FLUSH_ON_EXIT=1 \ git cat-file --batch-command --buffer >actual && test_cmp expect actual -' + ' -test_expect_success '--batch-command --buffer without flush for blob info' ' + test_expect_success '--batch-command --buffer without flush for blob info' ' touch output && - test_write_lines "info $hello_sha1" | + test_write_lines "info $oid" | GIT_TEST_CAT_FILE_NO_FLUSH_ON_EXIT=1 \ git cat-file --batch-command --buffer >>output && test_must_be_empty output -' + ' +} + +hello_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $hello_oid) +run_blob_tests $hello_oid +run_blob_tests $hello_compat_oid test_expect_success '--batch-check without %(rest) considers whole line' ' - echo "$hello_sha1 blob $hello_size" >expect && - git update-index --add --cacheinfo 100644 $hello_sha1 "white space" && + echo "$hello_oid blob $hello_size" >expect && + git update-index --add --cacheinfo 100644 $hello_oid "white space" && test_when_finished "git update-index --remove \"white space\"" && echo ":white space" | git cat-file --batch-check >actual && test_cmp expect actual ' -tree_sha1=$(git write-tree) +tree_oid=$(git write-tree) +tree_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tree_oid) tree_size=$(($(test_oid rawsz) + 13)) -tree_pretty_content="100644 blob $hello_sha1 hello${LF}" +tree_compat_size=$(($(test_oid --hash=compat rawsz) + 13)) +tree_pretty_content="100644 blob $hello_oid hello${LF}" +tree_compat_pretty_content="100644 blob $hello_compat_oid hello${LF}" -run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content" +run_tests 'tree' $tree_oid $tree_size "" "$tree_pretty_content" +run_tests 'tree' $tree_compat_oid $tree_compat_size "" "$tree_compat_pretty_content" commit_message="Initial commit" -commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1) +commit_oid=$(echo_without_newline "$commit_message" | git commit-tree $tree_oid) +commit_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $commit_oid) commit_size=$(($(test_oid hexsz) + 137)) -commit_content="tree $tree_sha1 +commit_compat_size=$(($(test_oid --hash=compat hexsz) + 137)) +commit_content="tree $tree_oid +author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + +$commit_message" + +commit_compat_content="tree $tree_compat_oid author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE $commit_message" -run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" +run_tests 'commit' $commit_oid $commit_size "$commit_content" "$commit_content" +run_tests 'commit' $commit_compat_oid $commit_compat_size "$commit_compat_content" "$commit_compat_content" -tag_header_without_timestamp="object $hello_sha1 -type blob +tag_header_without_oid="type blob tag hellotag tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" +tag_header_without_timestamp="object $hello_oid +$tag_header_without_oid" +tag_compat_header_without_timestamp="object $hello_compat_oid +$tag_header_without_oid" tag_description="This is a tag" tag_content="$tag_header_without_timestamp 0 +0000 $tag_description" +tag_compat_content="$tag_compat_header_without_timestamp 0 +0000 -tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w) +$tag_description" + +tag_oid=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w) tag_size=$(strlen "$tag_content") -run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" +tag_compat_oid=$(git rev-parse --output-object-format=$test_compat_hash_algo $tag_oid) +tag_compat_size=$(strlen "$tag_compat_content") + +run_tests 'tag' $tag_oid $tag_size "$tag_content" "$tag_content" +run_tests 'tag' $tag_compat_oid $tag_compat_size "$tag_compat_content" "$tag_compat_content" test_expect_success "Reach a blob from a tag pointing to it" ' echo_without_newline "$hello_content" >expect && - git cat-file blob $tag_sha1 >actual && + git cat-file blob $tag_oid >actual && test_cmp expect actual ' -for batch in batch batch-check batch-command +for oid in $hello_oid $hello_compat_oid do - for opt in t s e p + for batch in batch batch-check batch-command do + for opt in t s e p + do test_expect_success "Passing -$opt with --$batch fails" ' - test_must_fail git cat-file --$batch -$opt $hello_sha1 + test_must_fail git cat-file --$batch -$opt $oid ' test_expect_success "Passing --$batch with -$opt fails" ' - test_must_fail git cat-file -$opt --$batch $hello_sha1 + test_must_fail git cat-file -$opt --$batch $oid ' - done + done - test_expect_success "Passing <type> with --$batch fails" ' - test_must_fail git cat-file --$batch blob $hello_sha1 - ' + test_expect_success "Passing <type> with --$batch fails" ' + test_must_fail git cat-file --$batch blob $oid + ' - test_expect_success "Passing --$batch with <type> fails" ' - test_must_fail git cat-file blob --$batch $hello_sha1 - ' + test_expect_success "Passing --$batch with <type> fails" ' + test_must_fail git cat-file blob --$batch $oid + ' - test_expect_success "Passing sha1 with --$batch fails" ' - test_must_fail git cat-file --$batch $hello_sha1 - ' + test_expect_success "Passing oid with --$batch fails" ' + test_must_fail git cat-file --$batch $oid + ' + done done -for opt in t s e p +for oid in $hello_oid $hello_compat_oid do - test_expect_success "Passing -$opt with --follow-symlinks fails" ' - test_must_fail git cat-file --follow-symlinks -$opt $hello_sha1 + for opt in t s e p + do + test_expect_success "Passing -$opt with --follow-symlinks fails" ' + test_must_fail git cat-file --follow-symlinks -$opt $oid ' + done done test_expect_success "--batch-check for a non-existent named object" ' @@ -360,12 +400,12 @@ test_expect_success "--batch-check for a non-existent hash" ' test_expect_success "--batch for an existent and a non-existent hash" ' cat >expect <<-EOF && - $tag_sha1 tag $tag_size + $tag_oid tag $tag_size $tag_content 0000000000000000000000000000000000000000 missing EOF - printf "$tag_sha1\n0000000000000000000000000000000000000000" >in && + printf "$tag_oid\n0000000000000000000000000000000000000000" >in && git cat-file --batch <in >actual && test_cmp expect actual ' @@ -386,112 +426,102 @@ test_expect_success 'empty --batch-check notices missing object' ' test_cmp expect actual ' -batch_input="$hello_sha1 -$commit_sha1 -$tag_sha1 +batch_tests () { + boid=$1 + loid=$2 + lsize=$3 + coid=$4 + csize=$5 + ccontent=$6 + toid=$7 + tsize=$8 + tcontent=$9 + + batch_input="$boid +$coid +$toid deadbeef " -printf "%s\0" \ - "$hello_sha1 blob $hello_size" \ + printf "%s\0" \ + "$boid blob $hello_size" \ "$hello_content" \ - "$commit_sha1 commit $commit_size" \ - "$commit_content" \ - "$tag_sha1 tag $tag_size" \ - "$tag_content" \ + "$coid commit $csize" \ + "$ccontent" \ + "$toid tag $tsize" \ + "$tcontent" \ "deadbeef missing" \ " missing" >batch_output -test_expect_success '--batch with multiple sha1s gives correct format' ' + test_expect_success '--batch with multiple oids gives correct format' ' tr "\0" "\n" <batch_output >expect && echo_without_newline "$batch_input" >in && git cat-file --batch <in >actual && test_cmp expect actual -' + ' -test_expect_success '--batch, -z with multiple sha1s gives correct format' ' + test_expect_success '--batch, -z with multiple oids gives correct format' ' echo_without_newline_nul "$batch_input" >in && tr "\0" "\n" <batch_output >expect && git cat-file --batch -z <in >actual && test_cmp expect actual -' + ' -test_expect_success '--batch, -Z with multiple sha1s gives correct format' ' + test_expect_success '--batch, -Z with multiple oids gives correct format' ' echo_without_newline_nul "$batch_input" >in && git cat-file --batch -Z <in >actual && test_cmp batch_output actual -' + ' -batch_check_input="$hello_sha1 -$tree_sha1 -$commit_sha1 -$tag_sha1 +batch_check_input="$boid +$loid +$coid +$toid deadbeef " -printf "%s\0" \ - "$hello_sha1 blob $hello_size" \ - "$tree_sha1 tree $tree_size" \ - "$commit_sha1 commit $commit_size" \ - "$tag_sha1 tag $tag_size" \ + printf "%s\0" \ + "$boid blob $hello_size" \ + "$loid tree $lsize" \ + "$coid commit $csize" \ + "$toid tag $tsize" \ "deadbeef missing" \ " missing" >batch_check_output -test_expect_success "--batch-check with multiple sha1s gives correct format" ' + test_expect_success "--batch-check with multiple oids gives correct format" ' tr "\0" "\n" <batch_check_output >expect && echo_without_newline "$batch_check_input" >in && git cat-file --batch-check <in >actual && test_cmp expect actual -' + ' -test_expect_success "--batch-check, -z with multiple sha1s gives correct format" ' + test_expect_success "--batch-check, -z with multiple oids gives correct format" ' tr "\0" "\n" <batch_check_output >expect && echo_without_newline_nul "$batch_check_input" >in && git cat-file --batch-check -z <in >actual && test_cmp expect actual -' + ' -test_expect_success "--batch-check, -Z with multiple sha1s gives correct format" ' + test_expect_success "--batch-check, -Z with multiple oids gives correct format" ' echo_without_newline_nul "$batch_check_input" >in && git cat-file --batch-check -Z <in >actual && test_cmp batch_check_output actual -' - -test_expect_success FUNNYNAMES 'setup with newline in input' ' - touch -- "newline${LF}embedded" && - git add -- "newline${LF}embedded" && - git commit -m "file with newline embedded" && - test_tick && - - printf "HEAD:newline${LF}embedded" >in -' - -test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' ' - git cat-file --batch-check -z <in >actual && - echo "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && - test_cmp expect actual -' - -test_expect_success FUNNYNAMES '--batch-check, -Z with newline in input' ' - git cat-file --batch-check -Z <in >actual && - printf "%s\0" "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && - test_cmp expect actual -' + ' -batch_command_multiple_info="info $hello_sha1 -info $tree_sha1 -info $commit_sha1 -info $tag_sha1 +batch_command_multiple_info="info $boid +info $loid +info $coid +info $toid info deadbeef" -test_expect_success '--batch-command with multiple info calls gives correct format' ' + test_expect_success '--batch-command with multiple info calls gives correct format' ' cat >expect <<-EOF && - $hello_sha1 blob $hello_size - $tree_sha1 tree $tree_size - $commit_sha1 commit $commit_size - $tag_sha1 tag $tag_size + $boid blob $hello_size + $loid tree $lsize + $coid commit $csize + $toid tag $tsize deadbeef missing EOF @@ -510,22 +540,22 @@ test_expect_success '--batch-command with multiple info calls gives correct form git cat-file --batch-command --buffer -Z <in >actual && test_cmp expect_nul actual -' + ' -batch_command_multiple_contents="contents $hello_sha1 -contents $commit_sha1 -contents $tag_sha1 +batch_command_multiple_contents="contents $boid +contents $coid +contents $toid contents deadbeef flush" -test_expect_success '--batch-command with multiple command calls gives correct format' ' + test_expect_success '--batch-command with multiple command calls gives correct format' ' printf "%s\0" \ - "$hello_sha1 blob $hello_size" \ + "$boid blob $hello_size" \ "$hello_content" \ - "$commit_sha1 commit $commit_size" \ - "$commit_content" \ - "$tag_sha1 tag $tag_size" \ - "$tag_content" \ + "$coid commit $csize" \ + "$ccontent" \ + "$toid tag $tsize" \ + "$tcontent" \ "deadbeef missing" >expect_nul && tr "\0" "\n" <expect_nul >expect && @@ -543,6 +573,33 @@ test_expect_success '--batch-command with multiple command calls gives correct f git cat-file --batch-command --buffer -Z <in >actual && test_cmp expect_nul actual + ' + +} + +batch_tests $hello_oid $tree_oid $tree_size $commit_oid $commit_size "$commit_content" $tag_oid $tag_size "$tag_content" +batch_tests $hello_compat_oid $tree_compat_oid $tree_compat_size $commit_compat_oid $commit_compat_size "$commit_compat_content" $tag_compat_oid $tag_compat_size "$tag_compat_content" + + +test_expect_success FUNNYNAMES 'setup with newline in input' ' + touch -- "newline${LF}embedded" && + git add -- "newline${LF}embedded" && + git commit -m "file with newline embedded" && + test_tick && + + printf "HEAD:newline${LF}embedded" >in +' + +test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' ' + git cat-file --batch-check -z <in >actual && + echo "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && + test_cmp expect actual +' + +test_expect_success FUNNYNAMES '--batch-check, -Z with newline in input' ' + git cat-file --batch-check -Z <in >actual && + printf "%s\0" "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && + test_cmp expect actual ' test_expect_success 'setup blobs which are likely to delta' ' @@ -569,7 +626,7 @@ test_expect_success 'confirm that neither loose blob is a delta' ' # we will check only that one of the two objects is a delta # against the other, but not the order. We can do so by just # asking for the base of both, and checking whether either -# sha1 appears in the output. +# oid appears in the output. test_expect_success '%(deltabase) reports packed delta bases' ' git repack -ad && git cat-file --batch-check="%(deltabase)" <blobs >actual && @@ -583,12 +640,12 @@ test_expect_success 'setup bogus data' ' bogus_short_type="bogus" && bogus_short_content="bogus" && bogus_short_size=$(strlen "$bogus_short_content") && - bogus_short_sha1=$(echo_without_newline "$bogus_short_content" | git hash-object -t $bogus_short_type --literally -w --stdin) && + bogus_short_oid=$(echo_without_newline "$bogus_short_content" | git hash-object -t $bogus_short_type --literally -w --stdin) && bogus_long_type="abcdefghijklmnopqrstuvwxyz1234679" && bogus_long_content="bogus" && bogus_long_size=$(strlen "$bogus_long_content") && - bogus_long_sha1=$(echo_without_newline "$bogus_long_content" | git hash-object -t $bogus_long_type --literally -w --stdin) + bogus_long_oid=$(echo_without_newline "$bogus_long_content" | git hash-object -t $bogus_long_type --literally -w --stdin) ' for arg1 in '' --allow-unknown-type @@ -608,9 +665,9 @@ do if test "$arg1" = "--allow-unknown-type" then - git cat-file $arg1 $arg2 $bogus_short_sha1 + git cat-file $arg1 $arg2 $bogus_short_oid else - test_must_fail git cat-file $arg1 $arg2 $bogus_short_sha1 >out 2>actual && + test_must_fail git cat-file $arg1 $arg2 $bogus_short_oid >out 2>actual && test_must_be_empty out && test_cmp expect actual fi @@ -620,21 +677,21 @@ do if test "$arg2" = "-p" then cat >expect <<-EOF - error: header for $bogus_long_sha1 too long, exceeds 32 bytes - fatal: Not a valid object name $bogus_long_sha1 + error: header for $bogus_long_oid too long, exceeds 32 bytes + fatal: Not a valid object name $bogus_long_oid EOF else cat >expect <<-EOF - error: header for $bogus_long_sha1 too long, exceeds 32 bytes + error: header for $bogus_long_oid too long, exceeds 32 bytes fatal: git cat-file: could not get object info EOF fi && if test "$arg1" = "--allow-unknown-type" then - git cat-file $arg1 $arg2 $bogus_short_sha1 + git cat-file $arg1 $arg2 $bogus_short_oid else - test_must_fail git cat-file $arg1 $arg2 $bogus_long_sha1 >out 2>actual && + test_must_fail git cat-file $arg1 $arg2 $bogus_long_oid >out 2>actual && test_must_be_empty out && test_cmp expect actual fi @@ -668,28 +725,28 @@ do done test_expect_success '-e is OK with a broken object without --allow-unknown-type' ' - git cat-file -e $bogus_short_sha1 + git cat-file -e $bogus_short_oid ' test_expect_success '-e can not be combined with --allow-unknown-type' ' - test_expect_code 128 git cat-file -e --allow-unknown-type $bogus_short_sha1 + test_expect_code 128 git cat-file -e --allow-unknown-type $bogus_short_oid ' test_expect_success '-p cannot print a broken object even with --allow-unknown-type' ' - test_must_fail git cat-file -p $bogus_short_sha1 && - test_expect_code 128 git cat-file -p --allow-unknown-type $bogus_short_sha1 + test_must_fail git cat-file -p $bogus_short_oid && + test_expect_code 128 git cat-file -p --allow-unknown-type $bogus_short_oid ' test_expect_success '<type> <hash> does not work with objects of broken types' ' cat >err.expect <<-\EOF && fatal: invalid object type "bogus" EOF - test_must_fail git cat-file $bogus_short_type $bogus_short_sha1 2>err.actual && + test_must_fail git cat-file $bogus_short_type $bogus_short_oid 2>err.actual && test_cmp err.expect err.actual ' test_expect_success 'broken types combined with --batch and --batch-check' ' - echo $bogus_short_sha1 >bogus-oid && + echo $bogus_short_oid >bogus-oid && cat >err.expect <<-\EOF && fatal: invalid object type @@ -711,52 +768,52 @@ test_expect_success 'the --allow-unknown-type option does not consider replaceme cat >expect <<-EOF && $bogus_short_type EOF - git cat-file -t --allow-unknown-type $bogus_short_sha1 >actual && + git cat-file -t --allow-unknown-type $bogus_short_oid >actual && test_cmp expect actual && # Create it manually, as "git replace" will die on bogus # types. head=$(git rev-parse --verify HEAD) && - test_when_finished "test-tool ref-store main delete-refs 0 msg refs/replace/$bogus_short_sha1" && - test-tool ref-store main update-ref msg "refs/replace/$bogus_short_sha1" $head $ZERO_OID REF_SKIP_OID_VERIFICATION && + test_when_finished "test-tool ref-store main delete-refs 0 msg refs/replace/$bogus_short_oid" && + test-tool ref-store main update-ref msg "refs/replace/$bogus_short_oid" $head $ZERO_OID REF_SKIP_OID_VERIFICATION && cat >expect <<-EOF && commit EOF - git cat-file -t --allow-unknown-type $bogus_short_sha1 >actual && + git cat-file -t --allow-unknown-type $bogus_short_oid >actual && test_cmp expect actual ' test_expect_success "Type of broken object is correct" ' echo $bogus_short_type >expect && - git cat-file -t --allow-unknown-type $bogus_short_sha1 >actual && + git cat-file -t --allow-unknown-type $bogus_short_oid >actual && test_cmp expect actual ' test_expect_success "Size of broken object is correct" ' echo $bogus_short_size >expect && - git cat-file -s --allow-unknown-type $bogus_short_sha1 >actual && + git cat-file -s --allow-unknown-type $bogus_short_oid >actual && test_cmp expect actual ' test_expect_success 'clean up broken object' ' - rm .git/objects/$(test_oid_to_path $bogus_short_sha1) + rm .git/objects/$(test_oid_to_path $bogus_short_oid) ' test_expect_success "Type of broken object is correct when type is large" ' echo $bogus_long_type >expect && - git cat-file -t --allow-unknown-type $bogus_long_sha1 >actual && + git cat-file -t --allow-unknown-type $bogus_long_oid >actual && test_cmp expect actual ' test_expect_success "Size of large broken object is correct when type is large" ' echo $bogus_long_size >expect && - git cat-file -s --allow-unknown-type $bogus_long_sha1 >actual && + git cat-file -s --allow-unknown-type $bogus_long_oid >actual && test_cmp expect actual ' test_expect_success 'clean up broken object' ' - rm .git/objects/$(test_oid_to_path $bogus_long_sha1) + rm .git/objects/$(test_oid_to_path $bogus_long_oid) ' test_expect_success 'cat-file -t and -s on corrupt loose object' ' @@ -853,7 +910,7 @@ test_expect_success 'prep for symlink tests' ' test_ln_s_add loop2 loop1 && git add morx dir/subdir/ind2 dir/ind1 && git commit -am "test" && - echo $hello_sha1 blob $hello_size >found + echo $hello_oid blob $hello_size >found ' test_expect_success 'git cat-file --batch-check --follow-symlinks works for non-links' ' @@ -941,7 +998,7 @@ test_expect_success 'git cat-file --batch-check --follow-symlinks works for dir/ echo HEAD:dirlink/morx >>expect && echo HEAD:dirlink/morx | git cat-file --batch-check --follow-symlinks >actual && test_cmp expect actual && - echo $hello_sha1 blob $hello_size >expect && + echo $hello_oid blob $hello_size >expect && echo HEAD:dirlink/ind1 | git cat-file --batch-check --follow-symlinks >actual && test_cmp expect actual ' diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index ac3d173767..64aea38486 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -124,8 +124,8 @@ test_expect_success 'check that appropriate filter is invoke when --path is used path0_sha=$(git hash-object --path=file0 file1) && test "$file0_sha" = "$path0_sha" && test "$file1_sha" = "$path1_sha" && - path1_sha=$(cat file0 | git hash-object --path=file1 --stdin) && - path0_sha=$(cat file1 | git hash-object --path=file0 --stdin) && + path1_sha=$(git hash-object --path=file1 --stdin <file0) && + path0_sha=$(git hash-object --path=file0 --stdin <file1) && test "$file0_sha" = "$path0_sha" && test "$file1_sha" = "$path1_sha" ' @@ -154,7 +154,7 @@ test_expect_success '--path works in a subdirectory' ' test_expect_success 'check that --no-filters option works' ' nofilters_file1=$(git hash-object --no-filters file1) && test "$file0_sha" = "$nofilters_file1" && - nofilters_file1=$(cat file1 | git hash-object --stdin) && + nofilters_file1=$(git hash-object --stdin <file1) && test "$file0_sha" = "$nofilters_file1" ' diff --git a/t/t1016-compatObjectFormat.sh b/t/t1016-compatObjectFormat.sh new file mode 100755 index 0000000000..be3206a16f --- /dev/null +++ b/t/t1016-compatObjectFormat.sh @@ -0,0 +1,281 @@ +#!/bin/sh +# +# Copyright (c) 2023 Eric Biederman +# + +test_description='Test how well compatObjectFormat works' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-gpg.sh + +# All of the follow variables must be defined in the environment: +# GIT_AUTHOR_NAME +# GIT_AUTHOR_EMAIL +# GIT_AUTHOR_DATE +# GIT_COMMITTER_NAME +# GIT_COMMITTER_EMAIL +# GIT_COMMITTER_DATE +# +# The test relies on these variables being set so that the two +# different commits in two different repositories encoded with two +# different hash functions result in the same content in the commits. +# This means that when the commit is translated between hash functions +# the commit is identical to the commit in the other repository. + +compat_hash () { + 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 +} + +tree_oid () { + 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 +} + +commit2_oid () { + 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" +} + + +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" +} + +base=$(pwd) +for hash in sha1 sha256 +do + cd "$base" + mkdir -p repo-$hash + cd repo-$hash + + test_expect_success "setup $hash repository" ' + git init --object-format=$hash && + 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 && + eval hello_${hash}_oid=$(git hash-object hello) && + git update-index --add hello && + git commit -m "Initial commit" && + eval commit_${hash}_oid=$(git rev-parse HEAD) && + eval tree_${hash}_oid=$(git rev-parse HEAD^{tree}) + ' + test_expect_success "create a $hash tagged blob" ' + git tag --no-sign -m "This is a tag" hellotag $(hello_oid $hash) && + eval hellotag_${hash}_oid=$(git rev-parse hellotag) + ' + test_expect_success "create a $hash tagged tree" ' + git tag --no-sign -m "This is a tag" treetag $(tree_oid $hash) && + eval treetag_${hash}_oid=$(git rev-parse treetag) + ' + test_expect_success "create a $hash tagged commit" ' + git tag --no-sign -m "This is a tag" committag $(commit_oid $hash) && + eval committag_${hash}_oid=$(git rev-parse committag) + ' + test_expect_success GPG2 "create a $hash signed commit" ' + git commit --gpg-sign --allow-empty -m "This is a signed commit" && + eval signedcommit_${hash}_oid=$(git rev-parse HEAD) + ' + test_expect_success GPG2 "create a $hash signed tag" ' + git tag -s -m "This is a signed tag" signedtag HEAD && + eval signedtag_${hash}_oid=$(git rev-parse signedtag) + ' + test_expect_success "create a $hash branch" ' + git checkout -b branch $(commit_oid $hash) && + echo "More more more give me more!" > more && + eval more_${hash}_oid=$(git hash-object more) && + 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!" && + eval commit2_${hash}_oid=$(git rev-parse HEAD) && + eval tree2_${hash}_oid=$(git rev-parse HEAD^{tree}) + ' + test_expect_success GPG2 "create another $hash signed tag" ' + git tag -s -m "This is another signed tag" signedtag2 $(commit2_oid $hash) && + eval signedtag2_${hash}_oid=$(git rev-parse signedtag2) + ' + test_expect_success GPG2 "merge the $hash branches together" ' + git merge -S -m "merge some signed tags together" signedtag signedtag2 && + eval signedcommit2_${hash}_oid=$(git rev-parse HEAD) + ' + 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" && + 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 && + eval signedtag3_${hash}_oid=$(git hash-object -t tag -w ../${hash}_signedtag3) && + eval signedtag4_${hash}_oid=$(git hash-object -t tag -w ../${hash}_signedtag4) + ' +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_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 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 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 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 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 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 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" +compare_oids 'tree' tree "$tree_sha1_oid" "$tree_sha256_oid" +compare_oids 'commit' commit "$commit_sha1_oid" "$commit_sha256_oid" +compare_oids GPG2 'commit' signedcommit "$signedcommit_sha1_oid" "$signedcommit_sha256_oid" +compare_oids 'tag' hellotag "$hellotag_sha1_oid" "$hellotag_sha256_oid" +compare_oids 'tag' treetag "$treetag_sha1_oid" "$treetag_sha256_oid" +compare_oids 'tag' committag "$committag_sha1_oid" "$committag_sha256_oid" +compare_oids GPG2 'tag' signedtag "$signedtag_sha1_oid" "$signedtag_sha256_oid" + +compare_oids 'blob' more "$more_sha1_oid" "$more_sha256_oid" +compare_oids 'blob' another "$another_sha1_oid" "$another_sha256_oid" +compare_oids 'tree' tree2 "$tree2_sha1_oid" "$tree2_sha256_oid" +compare_oids 'commit' commit2 "$commit2_sha1_oid" "$commit2_sha256_oid" +compare_oids GPG2 'tag' signedtag2 "$signedtag2_sha1_oid" "$signedtag2_sha256_oid" +compare_oids GPG2 'commit' signedcommit2 "$signedcommit2_sha1_oid" "$signedcommit2_sha256_oid" +compare_oids GPG2 'commit' signedcommit3 "$signedcommit3_sha1_oid" "$signedcommit3_sha256_oid" +compare_oids GPG2 'commit' signedcommit4 "$signedcommit4_sha1_oid" "$signedcommit4_sha256_oid" +compare_oids GPG2 'tag' signedtag3 "$signedtag3_sha1_oid" "$signedtag3_sha256_oid" +compare_oids GPG2 'tag' signedtag4 "$signedtag4_sha1_oid" "$signedtag4_sha256_oid" + +test_done diff --git a/t/t1016/gpg b/t/t1016/gpg new file mode 100755 index 0000000000..2601cb18a5 --- /dev/null +++ b/t/t1016/gpg @@ -0,0 +1,2 @@ +#!/bin/sh +exec gpg --faked-system-time "20230918T154812" "$@" diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index e49b8024ac..ab3a105fff 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -968,7 +968,7 @@ test_expect_success 'check-rules non-cone mode' ' git -C bare sparse-checkout check-rules --no-cone --rules-file ../rules\ >check-rules-file <all-files && - cat rules | git -C repo sparse-checkout set --no-cone --stdin && + git -C repo sparse-checkout set --no-cone --stdin <rules && git -C repo ls-files -t >out && sed -n "/^S /!s/^. //p" out >ls-files && diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 31c3878687..9b65d9eaf5 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -11,6 +11,98 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh +test_expect_success 'setup whitespace config' ' + sed -e "s/^|//" \ + -e "s/[$]$//" \ + -e "s/X/ /g" >.git/config <<-\EOF + [section] + | solid = rock + | sparse = big XX blue + | sparseAndTail = big XX blue $ + | sparseAndTailQuoted = "big XX blue " + | sparseAndBiggerTail = big XX blue X X + | sparseAndBiggerTailQuoted = "big XX blue X X" + | sparseAndBiggerTailQuotedPlus = "big XX blue X X"X $ + | headAndTail = Xbig blue $ + | headAndTailQuoted = "Xbig blue " + | headAndTailQuotedPlus = "Xbig blue " $ + | annotated = big blueX# to be discarded + | annotatedQuoted = "big blue"X# to be discarded + EOF +' + +test_expect_success 'no internal whitespace' ' + echo "rock" >expect && + git config --get section.solid >actual && + test_cmp expect actual +' + +test_expect_success 'internal whitespace' ' + echo "big QQ blue" | q_to_tab >expect && + git config --get section.sparse >actual && + test_cmp expect actual +' + +test_expect_success 'internal and trailing whitespace' ' + echo "big QQ blue" | q_to_tab >expect && + git config --get section.sparseAndTail >actual && + test_cmp expect actual +' + +test_expect_success 'internal and trailing whitespace, all quoted' ' + echo "big QQ blue " | q_to_tab >expect && + git config --get section.sparseAndTailQuoted >actual && + test_cmp expect actual +' + +test_expect_success 'internal and more trailing whitespace' ' + echo "big QQ blue" | q_to_tab >expect && + git config --get section.sparseAndBiggerTail >actual && + test_cmp expect actual +' + +test_expect_success 'internal and more trailing whitespace, all quoted' ' + echo "big QQ blue Q Q" | q_to_tab >expect && + git config --get section.sparseAndBiggerTailQuoted >actual && + test_cmp expect actual +' + +test_expect_success 'internal and more trailing whitespace, not all quoted' ' + echo "big QQ blue Q Q" | q_to_tab >expect && + git config --get section.sparseAndBiggerTailQuotedPlus >actual && + test_cmp expect actual +' + +test_expect_success 'leading and trailing whitespace' ' + echo "big blue" >expect && + git config --get section.headAndTail >actual && + test_cmp expect actual +' + +test_expect_success 'leading and trailing whitespace, all quoted' ' + echo "Qbig blue " | q_to_tab >expect && + git config --get section.headAndTailQuoted >actual && + test_cmp expect actual +' + +test_expect_success 'leading and trailing whitespace, not all quoted' ' + echo "Qbig blue " | q_to_tab >expect && + git config --get section.headAndTailQuotedPlus >actual && + test_cmp expect actual +' + +test_expect_success 'inline comment' ' + echo "big blue" >expect && + git config --get section.annotated >actual && + test_cmp expect actual +' + +test_expect_success 'inline comment, quoted' ' + echo "big blue" >expect && + git config --get section.annotatedQuoted >actual && + test_cmp expect actual +' + test_expect_success 'clear default config' ' rm -f .git/config ' @@ -69,14 +161,32 @@ test_expect_success 'replace with non-match (actually matching)' ' cat > expect << EOF [section] - penguin = very blue Movie = BadPhysics UPPERCASE = true - penguin = kingpin + penguin = gentoo # Pygoscelis papua + disposition = peckish # find fish + foo = bar #abc + spsp = value # and comment + htsp = value # and comment [Sections] WhatEver = Second EOF +test_expect_success 'append comments' ' + git config --replace-all --comment="Pygoscelis papua" section.penguin gentoo && + git config --comment="find fish" section.disposition peckish && + git config --comment="#abc" section.foo bar && + + git config --comment="and comment" section.spsp value && + git config --comment=" # and comment" section.htsp value && + + test_cmp expect .git/config +' + +test_expect_success 'Prohibited LF in comment' ' + test_must_fail git config --comment="a${LF}b" section.k v +' + test_expect_success 'non-match result' 'test_cmp expect .git/config' test_expect_success 'find mixed-case key by canonical name' ' @@ -1066,9 +1176,25 @@ test_expect_success '--null --get-regexp' ' test_cmp expect result ' -test_expect_success 'inner whitespace kept verbatim' ' - git config section.val "foo bar" && - test_cmp_config "foo bar" section.val +test_expect_success 'inner whitespace kept verbatim, spaces only' ' + echo "foo bar" >expect && + git config section.val "foo bar" && + git config --get section.val >actual && + test_cmp expect actual +' + +test_expect_success 'inner whitespace kept verbatim, horizontal tabs only' ' + echo "fooQQbar" | q_to_tab >expect && + git config section.val "$(cat expect)" && + git config --get section.val >actual && + test_cmp expect actual +' + +test_expect_success 'inner whitespace kept verbatim, horizontal tabs and spaces' ' + echo "foo Q bar" | q_to_tab >expect && + git config section.val "$(cat expect)" && + git config --get section.val >actual && + test_cmp expect actual ' test_expect_success SYMLINKS 'symlinked configuration' ' diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh index 8e2c01e760..29cf8a9661 100755 --- a/t/t1301-shared-repo.sh +++ b/t/t1301-shared-repo.sh @@ -52,7 +52,7 @@ test_expect_success 'shared=all' ' test 2 = $(git config core.sharedrepository) ' -test_expect_failure 'template can set core.bare' ' +test_expect_success 'template cannot set core.bare' ' test_when_finished "rm -rf subdir" && test_when_finished "rm -rf templates" && test_config core.bare true && @@ -60,18 +60,7 @@ test_expect_failure 'template can set core.bare' ' mkdir -p templates/ && cp .git/config templates/config && git init --template=templates subdir && - test_path_exists subdir/HEAD -' - -test_expect_success 'template can set core.bare but overridden by command line' ' - test_when_finished "rm -rf subdir" && - test_when_finished "rm -rf templates" && - test_config core.bare true && - umask 0022 && - mkdir -p templates/ && - cp .git/config templates/config && - git init --no-bare --template=templates subdir && - test_path_exists subdir/.git/HEAD + test_path_is_missing subdir/HEAD ' test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' ' @@ -137,22 +126,6 @@ test_expect_success POSIXPERM 'info/refs respects umask in unshared repo' ' test_cmp expect actual ' -test_expect_success REFFILES,POSIXPERM 'git reflog expire honors core.sharedRepository' ' - umask 077 && - git config core.sharedRepository group && - git reflog expire --all && - actual="$(ls -l .git/logs/refs/heads/main)" && - case "$actual" in - -rw-rw-*) - : happy - ;; - *) - echo Ooops, .git/logs/refs/heads/main is not 066x [$actual] - false - ;; - esac -' - test_expect_success POSIXPERM 'forced modes' ' test_when_finished "rm -rf new" && mkdir -p templates/hooks && diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index 78a09abc35..ec3443cc87 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -288,33 +288,6 @@ test_expect_success "set $m (logged by touch)" ' test $A = $(git show-ref -s --verify $m) ' -test_expect_success REFFILES 'empty directory removal' ' - git branch d1/d2/r1 HEAD && - git branch d1/r2 HEAD && - test_path_is_file .git/refs/heads/d1/d2/r1 && - test_path_is_file .git/logs/refs/heads/d1/d2/r1 && - git branch -d d1/d2/r1 && - test_must_fail git show-ref --verify -q refs/heads/d1/d2 && - test_must_fail git show-ref --verify -q logs/refs/heads/d1/d2 && - test_path_is_file .git/refs/heads/d1/r2 && - test_path_is_file .git/logs/refs/heads/d1/r2 -' - -test_expect_success REFFILES 'symref empty directory removal' ' - git branch e1/e2/r1 HEAD && - git branch e1/r2 HEAD && - git checkout e1/e2/r1 && - test_when_finished "git checkout main" && - test_path_is_file .git/refs/heads/e1/e2/r1 && - test_path_is_file .git/logs/refs/heads/e1/e2/r1 && - git update-ref -d HEAD && - test_must_fail git show-ref --verify -q refs/heads/e1/e2 && - test_must_fail git show-ref --verify -q logs/refs/heads/e1/e2 && - test_path_is_file .git/refs/heads/e1/r2 && - test_path_is_file .git/logs/refs/heads/e1/r2 && - test_path_is_file .git/logs/HEAD -' - cat >expect <<EOF $Z $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 Initial Creation $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150260 +0000 Switch @@ -453,15 +426,15 @@ test_expect_success 'Query "main@{2005-05-28}" (past end of history)' ' rm -f expect git update-ref -d $m -test_expect_success REFFILES 'query reflog with gap' ' +test_expect_success 'query reflog with gap' ' test_when_finished "git update-ref -d $m" && - git update-ref $m $F && - cat >.git/logs/$m <<-EOF && - $Z $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 - $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500 - $D $F $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 - EOF + GIT_COMMITTER_DATE="1117150320 -0500" git update-ref $m $A && + GIT_COMMITTER_DATE="1117150380 -0500" git update-ref $m $B && + GIT_COMMITTER_DATE="1117150480 -0500" git update-ref $m $C && + GIT_COMMITTER_DATE="1117150580 -0500" git update-ref $m $D && + GIT_COMMITTER_DATE="1117150680 -0500" git update-ref $m $F && + git reflog delete $m@{2} && git rev-parse --verify "main@{2005-05-26 23:33:01}" >actual 2>stderr && echo "$B" >expect && @@ -649,7 +622,7 @@ test_expect_success 'stdin fails create with no ref' ' test_expect_success 'stdin fails create with no new value' ' echo "create $a" >stdin && test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: create $a: missing <newvalue>" err + grep "fatal: create $a: missing <new-oid>" err ' test_expect_success 'stdin fails create with too many arguments' ' @@ -667,7 +640,7 @@ test_expect_success 'stdin fails update with no ref' ' test_expect_success 'stdin fails update with no new value' ' echo "update $a" >stdin && test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: update $a: missing <newvalue>" err + grep "fatal: update $a: missing <new-oid>" err ' test_expect_success 'stdin fails update with too many arguments' ' @@ -792,21 +765,21 @@ test_expect_success 'stdin update ref fails with wrong old value' ' test_expect_success 'stdin update ref fails with bad old value' ' echo "update $c $m does-not-exist" >stdin && test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: update $c: invalid <oldvalue>: does-not-exist" err && + grep "fatal: update $c: invalid <old-oid>: does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' test_expect_success 'stdin create ref fails with bad new value' ' echo "create $c does-not-exist" >stdin && test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: create $c: invalid <newvalue>: does-not-exist" err && + grep "fatal: create $c: invalid <new-oid>: does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' test_expect_success 'stdin create ref fails with zero new value' ' echo "create $c " >stdin && test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: create $c: zero <newvalue>" err && + grep "fatal: create $c: zero <new-oid>" err && test_must_fail git rev-parse --verify -q $c ' @@ -830,7 +803,7 @@ test_expect_success 'stdin delete ref fails with wrong old value' ' test_expect_success 'stdin delete ref fails with zero old value' ' echo "delete $a " >stdin && test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: delete $a: zero <oldvalue>" err && + grep "fatal: delete $a: zero <old-oid>" err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual @@ -1054,7 +1027,7 @@ test_expect_success 'stdin -z fails create with no ref' ' test_expect_success 'stdin -z fails create with no new value' ' printf $F "create $a" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: create $a: unexpected end of input when reading <newvalue>" err + grep "fatal: create $a: unexpected end of input when reading <new-oid>" err ' test_expect_success 'stdin -z fails create with too many arguments' ' @@ -1072,27 +1045,27 @@ test_expect_success 'stdin -z fails update with no ref' ' test_expect_success 'stdin -z fails update with too few args' ' printf $F "update $a" "$m" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: update $a: unexpected end of input when reading <oldvalue>" err + grep "fatal: update $a: unexpected end of input when reading <old-oid>" err ' test_expect_success 'stdin -z emits warning with empty new value' ' git update-ref $a $m && printf $F "update $a" "" "" >stdin && git update-ref -z --stdin <stdin 2>err && - grep "warning: update $a: missing <newvalue>, treating as zero" err && + grep "warning: update $a: missing <new-oid>, treating as zero" err && test_must_fail git rev-parse --verify -q $a ' test_expect_success 'stdin -z fails update with no new value' ' printf $F "update $a" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: update $a: unexpected end of input when reading <newvalue>" err + grep "fatal: update $a: unexpected end of input when reading <new-oid>" err ' test_expect_success 'stdin -z fails update with no old value' ' printf $F "update $a" "$m" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: update $a: unexpected end of input when reading <oldvalue>" err + grep "fatal: update $a: unexpected end of input when reading <old-oid>" err ' test_expect_success 'stdin -z fails update with too many arguments' ' @@ -1110,7 +1083,7 @@ test_expect_success 'stdin -z fails delete with no ref' ' test_expect_success 'stdin -z fails delete with no old value' ' printf $F "delete $a" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: delete $a: unexpected end of input when reading <oldvalue>" err + grep "fatal: delete $a: unexpected end of input when reading <old-oid>" err ' test_expect_success 'stdin -z fails delete with too many arguments' ' @@ -1128,7 +1101,7 @@ test_expect_success 'stdin -z fails verify with too many arguments' ' test_expect_success 'stdin -z fails verify with no old value' ' printf $F "verify $a" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: verify $a: unexpected end of input when reading <oldvalue>" err + grep "fatal: verify $a: unexpected end of input when reading <old-oid>" err ' test_expect_success 'stdin -z fails option with unknown name' ' @@ -1187,7 +1160,7 @@ test_expect_success 'stdin -z update ref fails with wrong old value' ' test_expect_success 'stdin -z update ref fails with bad old value' ' printf $F "update $c" "$m" "does-not-exist" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: update $c: invalid <oldvalue>: does-not-exist" err && + grep "fatal: update $c: invalid <old-oid>: does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' @@ -1205,14 +1178,14 @@ test_expect_success 'stdin -z create ref fails with bad new value' ' git update-ref -d "$c" && printf $F "create $c" "does-not-exist" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: create $c: invalid <newvalue>: does-not-exist" err && + grep "fatal: create $c: invalid <new-oid>: does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' test_expect_success 'stdin -z create ref fails with empty new value' ' printf $F "create $c" "" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: create $c: missing <newvalue>" err && + grep "fatal: create $c: missing <new-oid>" err && test_must_fail git rev-parse --verify -q $c ' @@ -1236,7 +1209,7 @@ test_expect_success 'stdin -z delete ref fails with wrong old value' ' test_expect_success 'stdin -z delete ref fails with zero old value' ' printf $F "delete $a" "$Z" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: delete $a: zero <oldvalue>" err && + grep "fatal: delete $a: zero <old-oid>" err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual @@ -1668,13 +1641,4 @@ test_expect_success PIPE 'transaction flushes status updates' ' test_cmp expected actual ' -test_expect_success REFFILES 'directory not created deleting packed ref' ' - git branch d1/d2/r1 HEAD && - git pack-refs --all && - test_path_is_missing .git/refs/heads/d1/d2 && - git update-ref -d refs/heads/d1/d2/r1 && - test_path_is_missing .git/refs/heads/d1/d2 && - test_path_is_missing .git/refs/heads/d1 -' - test_done diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh index 00b7013705..98e9158bd2 100755 --- a/t/t1404-update-ref-errors.sh +++ b/t/t1404-update-ref-errors.sh @@ -92,9 +92,6 @@ df_test() { else delname="$delref" fi && - cat >expected-err <<-EOF && - fatal: cannot lock ref $SQ$addname$SQ: $SQ$delref$SQ exists; cannot create $SQ$addref$SQ - EOF $pack && if $add_del then @@ -103,7 +100,7 @@ df_test() { printf "%s\n" "delete $delname" "create $addname $D" fi >commands && test_must_fail git update-ref --stdin <commands 2>output.err && - test_cmp expected-err output.err && + grep "fatal:\( cannot lock ref $SQ$addname$SQ:\)\? $SQ$delref$SQ exists; cannot create $SQ$addref$SQ" output.err && printf "%s\n" "$C $delref" >expected-refs && git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs && test_cmp expected-refs actual-refs @@ -191,69 +188,69 @@ test_expect_success 'one new ref is a simple prefix of another' ' ' -test_expect_success REFFILES 'D/F conflict prevents add long + delete short' ' +test_expect_success 'D/F conflict prevents add long + delete short' ' df_test refs/df-al-ds --add-del foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents add short + delete long' ' +test_expect_success 'D/F conflict prevents add short + delete long' ' df_test refs/df-as-dl --add-del foo foo/bar ' -test_expect_success REFFILES 'D/F conflict prevents delete long + add short' ' +test_expect_success 'D/F conflict prevents delete long + add short' ' df_test refs/df-dl-as --del-add foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents delete short + add long' ' +test_expect_success 'D/F conflict prevents delete short + add long' ' df_test refs/df-ds-al --del-add foo foo/bar ' -test_expect_success REFFILES 'D/F conflict prevents add long + delete short packed' ' +test_expect_success 'D/F conflict prevents add long + delete short packed' ' df_test refs/df-al-dsp --pack --add-del foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents add short + delete long packed' ' +test_expect_success 'D/F conflict prevents add short + delete long packed' ' df_test refs/df-as-dlp --pack --add-del foo foo/bar ' -test_expect_success REFFILES 'D/F conflict prevents delete long packed + add short' ' +test_expect_success 'D/F conflict prevents delete long packed + add short' ' df_test refs/df-dlp-as --pack --del-add foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents delete short packed + add long' ' +test_expect_success 'D/F conflict prevents delete short packed + add long' ' df_test refs/df-dsp-al --pack --del-add foo foo/bar ' # Try some combinations involving symbolic refs... -test_expect_success REFFILES 'D/F conflict prevents indirect add long + delete short' ' +test_expect_success 'D/F conflict prevents indirect add long + delete short' ' df_test refs/df-ial-ds --sym-add --add-del foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents indirect add long + indirect delete short' ' +test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' ' df_test refs/df-ial-ids --sym-add --sym-del --add-del foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents indirect add short + indirect delete long' ' +test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' ' df_test refs/df-ias-idl --sym-add --sym-del --add-del foo foo/bar ' -test_expect_success REFFILES 'D/F conflict prevents indirect delete long + indirect add short' ' +test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' ' df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents indirect add long + delete short packed' ' +test_expect_success 'D/F conflict prevents indirect add long + delete short packed' ' df_test refs/df-ial-dsp --sym-add --pack --add-del foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents indirect add long + indirect delete short packed' ' +test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' ' df_test refs/df-ial-idsp --sym-add --sym-del --pack --add-del foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents add long + indirect delete short packed' ' +test_expect_success 'D/F conflict prevents add long + indirect delete short packed' ' df_test refs/df-al-idsp --sym-del --pack --add-del foo/bar foo ' -test_expect_success REFFILES 'D/F conflict prevents indirect delete long packed + indirect add short' ' +test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' ' df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo ' diff --git a/t/t1405-main-ref-store.sh b/t/t1405-main-ref-store.sh index 976bd71efb..a6bcd62ab6 100755 --- a/t/t1405-main-ref-store.sh +++ b/t/t1405-main-ref-store.sh @@ -33,12 +33,6 @@ test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' ' test_must_fail git rev-parse refs/tags/new-tag -- ' -# In reftable, we keep the reflogs around for deleted refs. -test_expect_success !REFFILES 'delete-reflog(FOO, refs/tags/new-tag)' ' - $RUN delete-reflog FOO && - $RUN delete-reflog refs/tags/new-tag -' - test_expect_success 'rename_refs(main, new-main)' ' git rev-parse main >expected && $RUN rename-ref refs/heads/main refs/heads/new-main && @@ -74,11 +68,11 @@ test_expect_success 'verify_ref(new-main)' ' ' test_expect_success 'for_each_reflog()' ' - $RUN for-each-reflog | sort -k2 | cut -d" " -f 2- >actual && + $RUN for-each-reflog >actual && cat >expected <<-\EOF && - HEAD 0x1 - refs/heads/main 0x0 - refs/heads/new-main 0x0 + HEAD + refs/heads/main + refs/heads/new-main EOF test_cmp expected actual ' diff --git a/t/t1406-submodule-ref-store.sh b/t/t1406-submodule-ref-store.sh index e6a7f7334b..c01f0f14a1 100755 --- a/t/t1406-submodule-ref-store.sh +++ b/t/t1406-submodule-ref-store.sh @@ -63,11 +63,11 @@ test_expect_success 'verify_ref(new-main)' ' ' test_expect_success 'for_each_reflog()' ' - $RUN for-each-reflog | sort | cut -d" " -f 2- >actual && + $RUN for-each-reflog >actual && cat >expected <<-\EOF && - HEAD 0x1 - refs/heads/main 0x0 - refs/heads/new-main 0x0 + HEAD + refs/heads/main + refs/heads/new-main EOF test_cmp expected actual ' diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index d2f5f42e67..5bf883f1e3 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -436,4 +436,112 @@ test_expect_success 'empty reflog' ' test_must_be_empty err ' +test_expect_success 'list reflogs' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + git reflog list >actual && + test_must_be_empty actual && + + test_commit A && + cat >expect <<-EOF && + HEAD + refs/heads/main + EOF + git reflog list >actual && + test_cmp expect actual && + + git branch b && + cat >expect <<-EOF && + HEAD + refs/heads/b + refs/heads/main + EOF + git reflog list >actual && + test_cmp expect actual + ) +' + +test_expect_success 'list reflogs with worktree' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit A && + git worktree add wt && + git -c core.logAllRefUpdates=always \ + update-ref refs/worktree/main HEAD && + git -c core.logAllRefUpdates=always \ + update-ref refs/worktree/per-worktree HEAD && + git -c core.logAllRefUpdates=always -C wt \ + update-ref refs/worktree/per-worktree HEAD && + git -c core.logAllRefUpdates=always -C wt \ + update-ref refs/worktree/worktree HEAD && + + cat >expect <<-EOF && + HEAD + refs/heads/main + refs/heads/wt + refs/worktree/main + refs/worktree/per-worktree + EOF + git reflog list >actual && + test_cmp expect actual && + + cat >expect <<-EOF && + HEAD + refs/heads/main + refs/heads/wt + refs/worktree/per-worktree + refs/worktree/worktree + EOF + git -C wt reflog list >actual && + test_cmp expect actual + ) +' + +test_expect_success 'reflog list returns error with additional args' ' + cat >expect <<-EOF && + error: list does not accept arguments: ${SQ}bogus${SQ} + EOF + test_must_fail git reflog list bogus 2>err && + test_cmp expect err +' + +test_expect_success 'reflog for symref with unborn target can be listed' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + git symbolic-ref HEAD refs/heads/unborn && + cat >expect <<-EOF && + HEAD + refs/heads/main + EOF + git reflog list >actual && + test_cmp expect actual + ) +' + +test_expect_success 'reflog with invalid object ID can be listed' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test-tool ref-store main update-ref msg refs/heads/missing \ + $(test_oid deadbeef) "$ZERO_OID" REF_SKIP_OID_VERIFICATION && + cat >expect <<-EOF && + HEAD + refs/heads/main + refs/heads/missing + EOF + git reflog list >actual && + test_cmp expect actual + ) +' + test_done diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index f0737593c3..b754b9fd74 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -322,4 +322,15 @@ check_invalid_long_option optionspec-neg --no-positive-only check_invalid_long_option optionspec-neg --negative check_invalid_long_option optionspec-neg --no-no-negative +test_expect_success 'ambiguous: --no matches both --noble and --no-noble' ' + cat >spec <<-\EOF && + some-command [options] + -- + noble The feudal switch. + EOF + test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + git rev-parse --parseopt -- <spec 2>err --no && + grep "error: ambiguous option: no (could be --noble or --no-noble)" err +' + test_done diff --git a/t/t1509/prepare-chroot.sh b/t/t1509/prepare-chroot.sh index 6d47e2c725..dc997e0a64 100755 --- a/t/t1509/prepare-chroot.sh +++ b/t/t1509/prepare-chroot.sh @@ -43,7 +43,7 @@ rsync --exclude-from t/t1509/excludes -Ha . "$R$(pwd)" # env might slip through, see test-lib.sh, unset.*PERL_PATH sed 's|^PERL_PATH=.*|PERL_PATH=/bin/true|' GIT-BUILD-OPTIONS > "$R$(pwd)/GIT-BUILD-OPTIONS" for cmd in git $BB;do - ldd $cmd | grep '/' | sed 's,.*\s\(/[^ ]*\).*,\1,' | while read i; do + ldd $cmd | sed -n '/\//s,.*\s\(/[^ ]*\).*,\1,p' | while read i; do mkdir -p "$R$(dirname $i)" cp "$i" "$R/$i" done diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh index 3c8135831b..04f53b1ea1 100755 --- a/t/t2011-checkout-invalid-head.sh +++ b/t/t2011-checkout-invalid-head.sh @@ -29,36 +29,33 @@ test_expect_success REFFILES 'checkout notices failure to lock HEAD' ' test_must_fail git checkout -b other ' -test_expect_success REFFILES 'create ref directory/file conflict scenario' ' +test_expect_success 'create ref directory/file conflict scenario' ' git update-ref refs/heads/outer/inner main && - - # do not rely on symbolic-ref to get a known state, - # as it may use the same code we are testing reset_to_df () { - echo "ref: refs/heads/outer" >.git/HEAD + git symbolic-ref HEAD refs/heads/outer } ' -test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to branch)' ' +test_expect_success 'checkout away from d/f HEAD (unpacked, to branch)' ' reset_to_df && git checkout main ' -test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to detached)' ' +test_expect_success 'checkout away from d/f HEAD (unpacked, to detached)' ' reset_to_df && git checkout --detach main ' -test_expect_success REFFILES 'pack refs' ' +test_expect_success 'pack refs' ' git pack-refs --all --prune ' -test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to branch)' ' +test_expect_success 'checkout away from d/f HEAD (packed, to branch)' ' reset_to_df && git checkout main ' -test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to detached)' ' +test_expect_success 'checkout away from d/f HEAD (packed, to detached)' ' reset_to_df && git checkout --detach main ' diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh index 747eb5563e..c40b661ac1 100755 --- a/t/t2016-checkout-patch.sh +++ b/t/t2016-checkout-patch.sh @@ -2,6 +2,7 @@ test_description='git checkout --patch' +TEST_PASSES_SANITIZE_LEAK=true . ./lib-patch-mode.sh test_expect_success 'setup' ' @@ -38,26 +39,32 @@ test_expect_success 'git checkout -p with staged changes' ' verify_state dir/foo index index ' -test_expect_success 'git checkout -p HEAD with NO staged changes: abort' ' - set_and_save_state dir/foo work head && - test_write_lines n y n | git checkout -p HEAD && - verify_saved_state bar && - verify_saved_state dir/foo -' - -test_expect_success 'git checkout -p HEAD with NO staged changes: apply' ' - test_write_lines n y y | git checkout -p HEAD && - verify_saved_state bar && - verify_state dir/foo head head -' - -test_expect_success 'git checkout -p HEAD with change already staged' ' - set_state dir/foo index index && - # the third n is to get out in case it mistakenly does not apply - test_write_lines n y n | git checkout -p HEAD && - verify_saved_state bar && - verify_state dir/foo head head -' +for opt in "HEAD" "@" +do + test_expect_success "git checkout -p $opt with NO staged changes: abort" ' + set_and_save_state dir/foo work head && + test_write_lines n y n | git checkout -p $opt >output && + verify_saved_state bar && + verify_saved_state dir/foo && + test_grep "Discard" output + ' + + test_expect_success "git checkout -p $opt with NO staged changes: apply" ' + test_write_lines n y y | git checkout -p $opt >output && + verify_saved_state bar && + verify_state dir/foo head head && + test_grep "Discard" output + ' + + test_expect_success "git checkout -p $opt with change already staged" ' + set_state dir/foo index index && + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git checkout -p $opt >output && + verify_saved_state bar && + verify_state dir/foo head head && + test_grep "Discard" output + ' +done test_expect_success 'git checkout -p HEAD^...' ' # the third n is to get out in case it mistakenly does not apply diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index 8202ef8c74..8d90d02850 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -45,6 +45,18 @@ test_expect_success 'checkout branch does not detach' ' check_not_detached ' +for opt in "HEAD" "@" +do + test_expect_success "checkout $opt no-op/don't detach" ' + reset && + cat .git/HEAD >expect && + git checkout $opt && + cat .git/HEAD >actual && + check_not_detached && + test_cmp expect actual + ' +done + test_expect_success 'checkout tag detaches' ' reset && git checkout tag && @@ -164,7 +176,10 @@ test_expect_success 'tracking count is accurate after orphan check' ' git config branch.child.merge refs/heads/main && git checkout child^ && git checkout child >stdout && - test_cmp expect stdout + test_cmp expect stdout && + + git checkout --detach child >stdout && + test_grep ! "can be fast-forwarded\." stdout ' test_expect_success 'no advice given for explicit detached head state' ' diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh index a97416ce65..a3b1449ef1 100755 --- a/t/t2024-checkout-dwim.sh +++ b/t/t2024-checkout-dwim.sh @@ -113,7 +113,7 @@ test_expect_success 'checkout of branch from multiple remotes fails with advice' test_grep ! "^hint: " stderr ' -test_expect_success PERL 'checkout -p with multiple remotes does not print advice' ' +test_expect_success 'checkout -p with multiple remotes does not print advice' ' git checkout -B main && test_might_fail git branch -D foo && diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh index 16d6348b69..ac404945d4 100755 --- a/t/t2070-restore.sh +++ b/t/t2070-restore.sh @@ -5,6 +5,7 @@ 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 b5c5c0ff7e..42d5522119 100755 --- a/t/t2071-restore-patch.sh +++ b/t/t2071-restore-patch.sh @@ -2,9 +2,10 @@ test_description='git restore --patch' +TEST_PASSES_SANITIZE_LEAK=true . ./lib-patch-mode.sh -test_expect_success PERL 'setup' ' +test_expect_success 'setup' ' mkdir dir && echo parent >dir/foo && echo dummy >bar && @@ -16,43 +17,47 @@ test_expect_success PERL 'setup' ' save_head ' -test_expect_success PERL 'restore -p without pathspec is fine' ' +test_expect_success 'restore -p without pathspec is fine' ' echo q >cmd && git restore -p <cmd ' # note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar' -test_expect_success PERL 'saying "n" does nothing' ' +test_expect_success 'saying "n" does nothing' ' set_and_save_state dir/foo work head && test_write_lines n n | git restore -p && verify_saved_state bar && verify_saved_state dir/foo ' -test_expect_success PERL 'git restore -p' ' +test_expect_success 'git restore -p' ' set_and_save_state dir/foo work head && test_write_lines n y | git restore -p && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success PERL 'git restore -p with staged changes' ' +test_expect_success 'git restore -p with staged changes' ' set_state dir/foo work index && test_write_lines n y | git restore -p && verify_saved_state bar && verify_state dir/foo index index ' -test_expect_success PERL 'git restore -p --source=HEAD' ' - set_state dir/foo work index && - # the third n is to get out in case it mistakenly does not apply - test_write_lines n y n | git restore -p --source=HEAD && - verify_saved_state bar && - verify_state dir/foo head index -' - -test_expect_success PERL 'git restore -p --source=HEAD^' ' +for opt in "HEAD" "@" +do + test_expect_success "git restore -p --source=$opt" ' + set_state dir/foo work index && + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git restore -p --source=$opt >output && + verify_saved_state bar && + verify_state dir/foo head index && + test_grep "Discard" output + ' +done + +test_expect_success 'git restore -p --source=HEAD^' ' set_state dir/foo work index && # the third n is to get out in case it mistakenly does not apply test_write_lines n y n | git restore -p --source=HEAD^ && @@ -60,7 +65,7 @@ test_expect_success PERL 'git restore -p --source=HEAD^' ' verify_state dir/foo parent index ' -test_expect_success PERL 'git restore -p --source=HEAD^...' ' +test_expect_success 'git restore -p --source=HEAD^...' ' set_state dir/foo work index && # the third n is to get out in case it mistakenly does not apply test_write_lines n y n | git restore -p --source=HEAD^... && @@ -68,7 +73,7 @@ test_expect_success PERL 'git restore -p --source=HEAD^...' ' verify_state dir/foo parent index ' -test_expect_success PERL 'git restore -p handles deletion' ' +test_expect_success 'git restore -p handles deletion' ' set_state dir/foo work index && rm dir/foo && test_write_lines n y | git restore -p && @@ -81,21 +86,21 @@ test_expect_success PERL 'git restore -p handles deletion' ' # dir/foo. There's always an extra 'n' to reject edits to dir/foo in # the failure case (and thus get out of the loop). -test_expect_success PERL 'path limiting works: dir' ' +test_expect_success 'path limiting works: dir' ' set_state dir/foo work head && test_write_lines y n | git restore -p dir && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success PERL 'path limiting works: -- dir' ' +test_expect_success 'path limiting works: -- dir' ' set_state dir/foo work head && test_write_lines y n | git restore -p -- dir && verify_saved_state bar && verify_state dir/foo head head ' -test_expect_success PERL 'path limiting works: HEAD^ -- dir' ' +test_expect_success 'path limiting works: HEAD^ -- dir' ' set_state dir/foo work head && # the third n is to get out in case it mistakenly does not apply test_write_lines y n n | git restore -p --source=HEAD^ -- dir && @@ -103,7 +108,7 @@ test_expect_success PERL 'path limiting works: HEAD^ -- dir' ' verify_state dir/foo parent head ' -test_expect_success PERL 'path limiting works: foo inside dir' ' +test_expect_success 'path limiting works: foo inside dir' ' set_state dir/foo work head && # the third n is to get out in case it mistakenly does not apply test_write_lines y n n | (cd dir && git restore -p foo) && @@ -111,7 +116,7 @@ test_expect_success PERL 'path limiting works: foo inside dir' ' verify_state dir/foo head head ' -test_expect_success PERL 'none of this moved HEAD' ' +test_expect_success 'none of this moved HEAD' ' verify_saved_head ' diff --git a/t/t2072-restore-pathspec-file.sh b/t/t2072-restore-pathspec-file.sh index 8198a1e578..86c9c88788 100755 --- a/t/t2072-restore-pathspec-file.sh +++ b/t/t2072-restore-pathspec-file.sh @@ -2,6 +2,7 @@ test_description='restore --pathspec-from-file' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_tick diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh index 0bab134d71..7ec7f30b44 100755 --- a/t/t2104-update-index-skip-worktree.sh +++ b/t/t2104-update-index-skip-worktree.sh @@ -11,27 +11,27 @@ TEST_PASSES_SANITIZE_LEAK=true sane_unset GIT_TEST_SPLIT_INDEX test_set_index_version () { - GIT_INDEX_VERSION="$1" - export GIT_INDEX_VERSION + GIT_INDEX_VERSION="$1" + export GIT_INDEX_VERSION } test_set_index_version 3 -cat >expect.full <<EOF -H 1 -H 2 -H sub/1 -H sub/2 -EOF +test_expect_success 'setup' ' + cat >expect.full <<-\EOF && + H 1 + H 2 + H sub/1 + H sub/2 + EOF -cat >expect.skip <<EOF -S 1 -H 2 -S sub/1 -H sub/2 -EOF + cat >expect.skip <<-\EOF && + S 1 + H 2 + S sub/1 + H sub/2 + EOF -test_expect_success 'setup' ' mkdir sub && touch ./1 ./2 sub/1 sub/2 && git add 1 2 sub/1 sub/2 && diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index c01492f33f..df235ac306 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -65,6 +65,16 @@ test_expect_success 'update did not touch untracked files' ' test_must_be_empty out ' +test_expect_success 'error out when passing untracked path' ' + git reset --hard && + echo content >>baz && + echo content >>top && + test_must_fail git add -u baz top 2>err && + test_grep -e "error: pathspec .baz. did not match any file(s) known to git" err && + git diff --cached --name-only >actual && + test_must_be_empty actual +' + test_expect_success 'cache tree has not been corrupted' ' git ls-files -s | diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index c28c04133c..ba320dc417 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -427,7 +427,7 @@ test_expect_success '"add" worktree with orphan branch, lock, and reason' ' # Note: Quoted arguments containing spaces are not supported. test_wt_add_orphan_hint () { local context="$1" && - local use_branch=$2 && + local use_branch="$2" && shift 2 && local opts="$*" && test_expect_success "'worktree add' show orphan hint in bad/orphan HEAD w/ $context" ' diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index de7d3014e4..ccfa6a720d 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -75,13 +75,13 @@ test_expect_success 'git branch HEAD should fail' ' test_must_fail git branch HEAD ' -cat >expect <<EOF -$HEAD refs/heads/d/e/f@{0}: branch: Created from main -EOF test_expect_success 'git branch --create-reflog d/e/f should create a branch and a log' ' GIT_COMMITTER_DATE="2005-05-26 23:30" \ git -c core.logallrefupdates=false branch --create-reflog d/e/f && test_ref_exists refs/heads/d/e/f && + cat >expect <<-EOF && + $HEAD refs/heads/d/e/f@{0}: branch: Created from main + EOF git reflog show --no-abbrev-commit refs/heads/d/e/f >actual && test_cmp expect actual ' @@ -440,10 +440,10 @@ test_expect_success 'git branch --list -v with --abbrev' ' test_expect_success 'git branch --column' ' COLUMNS=81 git branch --column=column >actual && - cat >expect <<\EOF && - a/b/c bam foo l * main n o/p r - abc bar j/k m/m mb o/o q topic -EOF + cat >expect <<-\EOF && + a/b/c bam foo l * main n o/p r + abc bar j/k m/m mb o/o q topic + EOF test_cmp expect actual ' @@ -453,25 +453,25 @@ test_expect_success 'git branch --column with an extremely long branch name' ' test_when_finished "git branch -d $long" && git branch $long && COLUMNS=80 git branch --column=column >actual && - cat >expect <<EOF && - a/b/c - abc - bam - bar - foo - j/k - l - m/m -* main - mb - n - o/o - o/p - q - r - topic - $long -EOF + cat >expect <<-EOF && + a/b/c + abc + bam + bar + foo + j/k + l + m/m + * main + mb + n + o/o + o/p + q + r + topic + $long + EOF test_cmp expect actual ' @@ -481,10 +481,10 @@ test_expect_success 'git branch with column.*' ' COLUMNS=80 git branch >actual && git config --unset column.branch && git config --unset column.ui && - cat >expect <<\EOF && - a/b/c bam foo l * main n o/p r - abc bar j/k m/m mb o/o q topic -EOF + cat >expect <<-\EOF && + a/b/c bam foo l * main n o/p r + abc bar j/k m/m mb o/o q topic + EOF test_cmp expect actual ' @@ -496,39 +496,36 @@ test_expect_success 'git branch -v with column.ui ignored' ' git config column.ui column && COLUMNS=80 git branch -v | cut -c -8 | sed "s/ *$//" >actual && git config --unset column.ui && - cat >expect <<\EOF && - a/b/c - abc - bam - bar - foo - j/k - l - m/m -* main - mb - n - o/o - o/p - q - r - topic -EOF + cat >expect <<-\EOF && + a/b/c + abc + bam + bar + foo + j/k + l + m/m + * main + mb + n + o/o + o/p + q + r + topic + EOF test_cmp expect actual ' -mv .git/config .git/config-saved - test_expect_success DEFAULT_REPO_FORMAT 'git branch -m q q2 without config should succeed' ' + test_when_finished mv .git/config-saved .git/config && + mv .git/config .git/config-saved && git branch -m q q2 && git branch -m q2 q ' -mv .git/config-saved .git/config - -git config branch.s/s.dummy Hello - test_expect_success 'git branch -m s/s s should work when s/t is deleted' ' + git config branch.s/s.dummy Hello && git branch --create-reflog s/s && git reflog exists refs/heads/s/s && git branch --create-reflog s/t && @@ -579,7 +576,7 @@ EOF # ...and that the comments for those sections are also # preserved. - cat config.branch | sed "s/\"source\"/\"dest\"/" >expect && + sed "s/\"source\"/\"dest\"/" config.branch >expect && sed -n -e "/Note the lack/,\$p" .git/config >actual && test_cmp expect actual ' @@ -836,35 +833,6 @@ test_expect_success 'renaming a symref is not allowed' ' test_ref_missing refs/heads/new-topic ' -test_expect_success SYMLINKS,REFFILES 'git branch -m u v should fail when the reflog for u is a symlink' ' - git branch --create-reflog u && - mv .git/logs/refs/heads/u real-u && - ln -s real-u .git/logs/refs/heads/u && - test_must_fail git branch -m u v -' - -test_expect_success SYMLINKS,REFFILES 'git branch -m with symlinked .git/refs' ' - test_when_finished "rm -rf subdir" && - git init --bare subdir && - - rm -rfv subdir/refs subdir/objects subdir/packed-refs && - ln -s ../.git/refs subdir/refs && - ln -s ../.git/objects subdir/objects && - ln -s ../.git/packed-refs subdir/packed-refs && - - git -C subdir rev-parse --absolute-git-dir >subdir.dir && - git rev-parse --absolute-git-dir >our.dir && - ! test_cmp subdir.dir our.dir && - - git -C subdir log && - git -C subdir branch rename-src && - git rev-parse rename-src >expect && - git -C subdir branch -m rename-src rename-dest && - git rev-parse rename-dest >actual && - test_cmp expect actual && - git branch -D rename-dest -' - test_expect_success 'test tracking setup via --track' ' git config remote.local.url . && git config remote.local.fetch refs/heads/*:refs/remotes/local/* && @@ -1141,14 +1109,14 @@ test_expect_success '--set-upstream-to notices an error to set branch as own ups test_cmp expect actual " -# Keep this test last, as it changes the current branch -cat >expect <<EOF -$HEAD refs/heads/g/h/i@{0}: branch: Created from main -EOF test_expect_success 'git checkout -b g/h/i -l should create a branch and a log' ' + test_when_finished git checkout main && GIT_COMMITTER_DATE="2005-05-26 23:30" \ git checkout -b g/h/i -l main && test_ref_exists refs/heads/g/h/i && + cat >expect <<-EOF && + $HEAD refs/heads/g/h/i@{0}: branch: Created from main + EOF git reflog show --no-abbrev-commit refs/heads/g/h/i >actual && test_cmp expect actual ' @@ -1186,9 +1154,9 @@ test_expect_success 'avoid ambiguous track and advise' ' hint: tracking ref '\''refs/heads/main'\'': hint: ambi1 hint: ambi2 - hint: '' + hint: hint: This is typically a configuration error. - hint: '' + hint: hint: To support setting up tracking branches, ensure that hint: different remotes'\'' fetch refspecs map into different hint: tracking namespaces. @@ -1725,4 +1693,14 @@ test_expect_success '--track overrides branch.autoSetupMerge' ' test_cmp_config "" --default "" branch.foo5.merge ' +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" + EOF + test_must_fail git branch foo..bar >actual 2>&1 && + test_cmp expect actual +' + test_done diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh index 6a98b2df76..a1139f79e2 100755 --- a/t/t3202-show-branch.sh +++ b/t/t3202-show-branch.sh @@ -4,9 +4,6 @@ test_description='test show-branch' . ./test-lib.sh -# arbitrary reference time: 2009-08-30 19:20:00 -GIT_TEST_DATE_NOW=1251660000; export GIT_TEST_DATE_NOW - test_expect_success 'error descriptions on empty repository' ' current=$(git branch --show-current) && cat >expect <<-EOF && @@ -187,18 +184,6 @@ test_expect_success 'show branch --merge-base with N arguments' ' test_cmp expect actual ' -test_expect_success 'show branch --reflog=2' ' - sed "s/^> //" >expect <<-\EOF && - > ! [refs/heads/branch10@{0}] (4 years, 5 months ago) commit: branch10 - > ! [refs/heads/branch10@{1}] (4 years, 5 months ago) commit: branch10 - > -- - > + [refs/heads/branch10@{0}] branch10 - > ++ [refs/heads/branch10@{1}] initial - EOF - git show-branch --reflog=2 >actual && - test_cmp actual expect -' - # incompatible options while read combo do @@ -264,4 +249,38 @@ test_expect_success 'error descriptions on orphan branch' ' test_branch_op_in_wt -c new-branch ' +test_expect_success 'setup reflogs' ' + test_commit base && + git checkout -b branch && + test_commit one && + git reset --hard HEAD^ && + test_commit two && + test_commit three +' + +test_expect_success '--reflog shows reflog entries' ' + cat >expect <<-\EOF && + ! [branch@{0}] (0 seconds ago) commit: three + ! [branch@{1}] (60 seconds ago) commit: two + ! [branch@{2}] (2 minutes ago) reset: moving to HEAD^ + ! [branch@{3}] (2 minutes ago) commit: one + ---- + + [branch@{0}] three + ++ [branch@{1}] two + + [branch@{3}] one + ++++ [branch@{2}] base + EOF + # the output always contains relative timestamps; use + # a known time to get deterministic results + GIT_TEST_DATE_NOW=$test_tick \ + git show-branch --reflog branch >actual && + test_cmp expect actual +' + +test_expect_success '--reflog handles missing reflog' ' + git reflog expire --expire=now branch && + git show-branch --reflog branch >actual && + test_must_be_empty actual +' + test_done diff --git a/t/t3321-notes-stripspace.sh b/t/t3321-notes-stripspace.sh index 088a852dd4..beca346056 100755 --- a/t/t3321-notes-stripspace.sh +++ b/t/t3321-notes-stripspace.sh @@ -442,7 +442,7 @@ test_expect_success 'add note by specifying "-C", "--no-stripspace" is the defau ${LF} EOF - cat expect | git hash-object -w --stdin >blob && + git hash-object -w --stdin <expect >blob && git notes add -C $(cat blob) && git notes show >actual && test_cmp expect actual && @@ -468,7 +468,7 @@ test_expect_success 'reuse note by specifying "-C" and "--stripspace"' ' second-line EOF - cat data | git hash-object -w --stdin >blob && + git hash-object -w --stdin <data >blob && git notes add --stripspace -C $(cat blob) && git notes show >actual && test_cmp expect actual @@ -492,7 +492,7 @@ test_expect_success 'reuse with "-C" and add note with "-m", "-m" will stripspac third-line EOF - cat data | git hash-object -w --stdin >blob && + git hash-object -w --stdin <data >blob && git notes add -C $(cat blob) -m "third-line" && git notes show >actual && test_cmp expect actual @@ -511,7 +511,7 @@ test_expect_success 'add note with "-m" and reuse note with "-C", "-C" will not second-line EOF - cat data | git hash-object -w --stdin >blob && + git hash-object -w --stdin <data >blob && git notes add -m "first-line" -C $(cat blob) && git notes show >actual && test_cmp expect actual diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 57f1392926..e1c8c5f701 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -424,16 +424,6 @@ test_expect_success 'refuse to switch to branch checked out elsewhere' ' test_grep "already used by worktree at" err ' -test_expect_success REFFILES,MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' ' - git checkout main && - mv .git/logs actual_logs && - cmd //c "mklink /D .git\logs ..\actual_logs" && - git rebase -f HEAD^ && - test -L .git/logs && - rm .git/logs && - mv actual_logs .git/logs -' - test_expect_success 'rebase when inside worktree subdirectory' ' git init main-wt && ( diff --git a/t/t3424-rebase-empty.sh b/t/t3424-rebase-empty.sh index 5e1045a0af..1ee6b00fd5 100755 --- a/t/t3424-rebase-empty.sh +++ b/t/t3424-rebase-empty.sh @@ -72,6 +72,17 @@ test_expect_success 'rebase --merge --empty=keep' ' test_cmp expect actual ' +test_expect_success 'rebase --merge --empty=stop' ' + git checkout -B testing localmods && + test_must_fail git rebase --merge --empty=stop upstream && + + git rebase --skip && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + test_expect_success 'rebase --merge --empty=ask' ' git checkout -B testing localmods && test_must_fail git rebase --merge --empty=ask upstream && @@ -101,9 +112,9 @@ test_expect_success 'rebase --interactive --empty=keep' ' test_cmp expect actual ' -test_expect_success 'rebase --interactive --empty=ask' ' +test_expect_success 'rebase --interactive --empty=stop' ' git checkout -B testing localmods && - test_must_fail git rebase --interactive --empty=ask upstream && + test_must_fail git rebase --interactive --empty=stop upstream && git rebase --skip && @@ -112,7 +123,7 @@ test_expect_success 'rebase --interactive --empty=ask' ' test_cmp expect actual ' -test_expect_success 'rebase --interactive uses default of --empty=ask' ' +test_expect_success 'rebase --interactive uses default of --empty=stop' ' git checkout -B testing localmods && test_must_fail git rebase --interactive upstream && @@ -167,4 +178,42 @@ test_expect_success 'rebase --merge does not leave state laying around' ' test_path_is_missing .git/MERGE_MSG ' +test_expect_success 'rebase --exec --empty=drop' ' + git checkout -B testing localmods && + git rebase --exec "true" --empty=drop upstream && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --exec --empty=keep' ' + git checkout -B testing localmods && + git rebase --exec "true" --empty=keep upstream && + + test_write_lines D C2 C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --exec uses default of --empty=keep' ' + git checkout -B testing localmods && + git rebase --exec "true" upstream && + + test_write_lines D C2 C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --exec --empty=stop' ' + git checkout -B testing localmods && + test_must_fail git rebase --exec "true" --empty=stop upstream && + + git rebase --skip && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh index e1b1e94764..1bebd1ce74 100755 --- a/t/t3428-rebase-signoff.sh +++ b/t/t3428-rebase-signoff.sh @@ -8,47 +8,45 @@ This test runs git rebase --signoff and make sure that it works. TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -# A simple file to commit -cat >file <<EOF -a -EOF +test_expect_success 'setup' ' + git commit --allow-empty -m "Initial empty commit" && + test_commit first file a && + + ident="$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" && -# Expected commit message for initial commit after rebase --signoff -cat >expected-initial-signed <<EOF -Initial empty commit + # Expected commit message for initial commit after rebase --signoff + cat >expected-initial-signed <<-EOF && + Initial empty commit -Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/") -EOF + Signed-off-by: $ident + EOF -# Expected commit message after rebase --signoff -cat >expected-signed <<EOF -first + # Expected commit message after rebase --signoff + cat >expected-signed <<-EOF && + first -Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/") -EOF + Signed-off-by: $ident + EOF -# Expected commit message after rebase without --signoff (or with --no-signoff) -cat >expected-unsigned <<EOF -first -EOF + # Expected commit message after rebase without --signoff (or with --no-signoff) + cat >expected-unsigned <<-EOF && + first + EOF + git config alias.rbs "rebase --signoff" +' # We configure an alias to do the rebase --signoff so that # on the next subtest we can show that --no-signoff overrides the alias -test_expect_success 'rebase --signoff adds a sign-off line' ' - git commit --allow-empty -m "Initial empty commit" && - git add file && git commit -m first && - git config alias.rbs "rebase --signoff" && - git rbs HEAD^ && - git cat-file commit HEAD | sed -e "1,/^\$/d" > actual && - test_cmp expected-signed actual +test_expect_success 'rebase --apply --signoff adds a sign-off line' ' + git rbs --apply HEAD^ && + test_commit_message HEAD expected-signed ' test_expect_success 'rebase --no-signoff does not add a sign-off line' ' git commit --amend -m "first" && git rbs --no-signoff HEAD^ && - git cat-file commit HEAD | sed -e "1,/^\$/d" > actual && - test_cmp expected-unsigned actual + test_commit_message HEAD expected-unsigned ' test_expect_success 'rebase --exec --signoff adds a sign-off line' ' @@ -56,30 +54,25 @@ test_expect_success 'rebase --exec --signoff adds a sign-off line' ' git commit --amend -m "first" && git rebase --exec "touch exec" --signoff HEAD^ && test_path_is_file exec && - git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && - test_cmp expected-signed actual + test_commit_message HEAD expected-signed ' test_expect_success 'rebase --root --signoff adds a sign-off line' ' git commit --amend -m "first" && git rebase --root --keep-empty --signoff && - git cat-file commit HEAD^ | sed -e "1,/^\$/d" >actual && - test_cmp expected-initial-signed actual && - git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && - test_cmp expected-signed actual + test_commit_message HEAD^ expected-initial-signed && + test_commit_message HEAD expected-signed ' test_expect_success 'rebase -i --signoff fails' ' git commit --amend -m "first" && git rebase -i --signoff HEAD^ && - git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && - test_cmp expected-signed actual + test_commit_message HEAD expected-signed ' test_expect_success 'rebase -m --signoff fails' ' git commit --amend -m "first" && git rebase -m --signoff HEAD^ && - git cat-file commit HEAD | sed -e "1,/^\$/d" >actual && - test_cmp expected-signed actual + test_commit_message HEAD expected-signed ' test_done diff --git a/t/t3438-rebase-broken-files.sh b/t/t3438-rebase-broken-files.sh index c614c4f2e4..821f08e5af 100755 --- a/t/t3438-rebase-broken-files.sh +++ b/t/t3438-rebase-broken-files.sh @@ -58,4 +58,13 @@ test_expect_success 'unknown key in author-script' ' check_resolve_fails ' +test_expect_success POSIXPERM,SANITY 'unwritable rebased-patches does not leak' ' + >.git/rebased-patches && + chmod a-w .git/rebased-patches && + + git checkout -b side HEAD^ && + test_commit unrelated && + test_must_fail git rebase --apply --onto tmp HEAD^ +' + test_done diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index aeab689a98..411027fb58 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -104,11 +104,19 @@ test_expect_success 'revert forbidden on dirty working tree' ' ' test_expect_success 'cherry-pick on unborn branch' ' - git checkout --orphan unborn && + git switch --orphan unborn && git rm --cached -r . && - rm -rf * && git cherry-pick initial && - git diff --quiet initial && + git diff --exit-code initial && + test_cmp_rev ! initial HEAD +' + +test_expect_success 'cherry-pick on unborn branch with --allow-empty' ' + git checkout --detach && + git branch -D unborn && + git switch --orphan unborn && + git cherry-pick initial --allow-empty && + git diff --exit-code initial && test_cmp_rev ! initial HEAD ' @@ -170,6 +178,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" EOF test_commit --append --no-tag "double-add dream" dream dream && test_must_fail git revert HEAD^ 2>actual && diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh index eba3c38d5a..9748443530 100755 --- a/t/t3505-cherry-pick-empty.sh +++ b/t/t3505-cherry-pick-empty.sh @@ -84,7 +84,7 @@ test_expect_success 'cherry-pick a commit that becomes no-op (prep)' ' git commit -m "add file2 on the side" ' -test_expect_success 'cherry-pick a no-op without --keep-redundant' ' +test_expect_success 'cherry-pick a no-op with neither --keep-redundant nor --empty' ' git reset --hard && git checkout fork^0 && test_must_fail git cherry-pick main @@ -99,4 +99,53 @@ test_expect_success 'cherry-pick a no-op with --keep-redundant' ' test_cmp expect actual ' +test_expect_success '--keep-redundant-commits is incompatible with operations' ' + test_must_fail git cherry-pick HEAD 2>output && + test_grep "The previous cherry-pick is now empty" output && + test_must_fail git cherry-pick --keep-redundant-commits --continue 2>output && + test_grep "fatal: cherry-pick: --keep-redundant-commits cannot be used with --continue" output && + test_must_fail git cherry-pick --keep-redundant-commits --skip 2>output && + test_grep "fatal: cherry-pick: --keep-redundant-commits cannot be used with --skip" output && + test_must_fail git cherry-pick --keep-redundant-commits --abort 2>output && + test_grep "fatal: cherry-pick: --keep-redundant-commits cannot be used with --abort" output && + test_must_fail git cherry-pick --keep-redundant-commits --quit 2>output && + test_grep "fatal: cherry-pick: --keep-redundant-commits cannot be used with --quit" output && + git cherry-pick --abort +' + +test_expect_success '--empty is incompatible with operations' ' + test_must_fail git cherry-pick HEAD 2>output && + test_grep "The previous cherry-pick is now empty" output && + test_must_fail git cherry-pick --empty=stop --continue 2>output && + test_grep "fatal: cherry-pick: --empty cannot be used with --continue" output && + test_must_fail git cherry-pick --empty=stop --skip 2>output && + test_grep "fatal: cherry-pick: --empty cannot be used with --skip" output && + test_must_fail git cherry-pick --empty=stop --abort 2>output && + test_grep "fatal: cherry-pick: --empty cannot be used with --abort" output && + test_must_fail git cherry-pick --empty=stop --quit 2>output && + test_grep "fatal: cherry-pick: --empty cannot be used with --quit" output && + git cherry-pick --abort +' + +test_expect_success 'cherry-pick a no-op with --empty=stop' ' + git reset --hard && + git checkout fork^0 && + test_must_fail git cherry-pick --empty=stop main 2>output && + test_grep "The previous cherry-pick is now empty" output +' + +test_expect_success 'cherry-pick a no-op with --empty=drop' ' + git reset --hard && + git checkout fork^0 && + git cherry-pick --empty=drop main && + test_commit_message HEAD -m "add file2 on the side" +' + +test_expect_success 'cherry-pick a no-op with --empty=keep' ' + git reset --hard && + git checkout fork^0 && + git cherry-pick --empty=keep main && + test_commit_message HEAD -m "add file2 on main" +' + test_done diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index c88d597b12..f3947b400a 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -60,6 +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" EOF test_must_fail git cherry-pick picked 2>actual && @@ -74,6 +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\" EOF test_must_fail git cherry-pick --no-commit picked 2>actual && diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh index 72020a51c4..7eb52b12ed 100755 --- a/t/t3510-cherry-pick-sequence.sh +++ b/t/t3510-cherry-pick-sequence.sh @@ -90,6 +90,38 @@ test_expect_success 'cherry-pick persists opts correctly' ' test_cmp expect actual ' +test_expect_success 'cherry-pick persists --empty=stop correctly' ' + pristine_detach yetanotherpick && + # Picking `anotherpick` forces a conflict so that we stop. That + # commit is then skipped, after which we pick `yetanotherpick` + # while already on `yetanotherpick` to cause an empty commit + test_must_fail git cherry-pick --empty=stop anotherpick yetanotherpick && + test_must_fail git cherry-pick --skip 2>msg && + test_grep "The previous cherry-pick is now empty" msg && + rm msg && + git cherry-pick --abort +' + +test_expect_success 'cherry-pick persists --empty=drop correctly' ' + pristine_detach yetanotherpick && + # Picking `anotherpick` forces a conflict so that we stop. That + # commit is then skipped, after which we pick `yetanotherpick` + # while already on `yetanotherpick` to cause an empty commit + test_must_fail git cherry-pick --empty=drop anotherpick yetanotherpick && + git cherry-pick --skip && + test_cmp_rev yetanotherpick HEAD +' + +test_expect_success 'cherry-pick persists --empty=keep correctly' ' + pristine_detach yetanotherpick && + # Picking `anotherpick` forces a conflict so that we stop. That + # commit is then skipped, after which we pick `yetanotherpick` + # while already on `yetanotherpick` to cause an empty commit + test_must_fail git cherry-pick --empty=keep anotherpick yetanotherpick && + git cherry-pick --skip && + test_cmp_rev yetanotherpick HEAD^ +' + test_expect_success 'revert persists opts correctly' ' pristine_detach initial && # to make sure that the session to revert a sequence diff --git a/t/t3700-add.sh b/t/t3700-add.sh index f23d39f0d5..839c904745 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -28,6 +28,16 @@ test_expect_success 'Test of git add' ' touch foo && git add foo ' +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" + EOF + git add 2>actual && + test_cmp expect actual +' + test_expect_success 'Post-check that foo is in the index' ' git ls-files foo | grep foo ' @@ -339,6 +349,40 @@ test_expect_success '"git add ." in empty repo' ' ) ' +test_expect_success '"git add" a embedded repository' ' + rm -fr outer && git init outer && + ( + cd outer && + for i in 1 2 + do + name=inner$i && + git init $name && + git -C $name commit --allow-empty -m $name || + return 1 + done && + git add . 2>actual && + cat >expect <<-EOF && + warning: adding embedded git repository: inner1 + hint: You${SQ}ve added another git repository inside your current repository. + hint: Clones of the outer repository will not contain the contents of + hint: the embedded repository and will not know how to obtain it. + hint: If you meant to add a submodule, use: + hint: + hint: git submodule add <url> inner1 + hint: + hint: If you added this path by mistake, you can remove it from the + hint: index with: + hint: + hint: git rm --cached inner1 + hint: + hint: See "git help submodule" for more information. + hint: Disable this message with "git config advice.addEmbeddedRepo false" + warning: adding embedded git repository: inner2 + EOF + test_cmp expect actual + ) +' + test_expect_success 'error on a repository with no commits' ' rm -fr empty && git init empty && @@ -370,8 +414,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: Turn this message off by running -hint: "git config advice.addIgnoredFile false" +hint: Disable this message with "git config 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 0b5339ac6c..04d8333373 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -4,6 +4,7 @@ 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 @@ -325,9 +326,9 @@ test_expect_success 'different prompts for mode change/deleted' ' git -c core.filemode=true add -p >actual && sed -n "s/^\(([0-9/]*) Stage .*?\).*/\1/p" actual >actual.filtered && cat >expect <<-\EOF && - (1/1) Stage deletion [y,n,q,a,d,?]? - (1/2) Stage mode change [y,n,q,a,d,j,J,g,/,?]? - (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? + (1/1) Stage deletion [y,n,q,a,d,p,?]? + (1/2) Stage mode change [y,n,q,a,d,j,J,g,/,p,?]? + (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? EOF test_cmp expect actual.filtered ' @@ -514,13 +515,13 @@ test_expect_success 'split hunk setup' ' test_expect_success 'goto hunk' ' test_when_finished "git reset" && tr _ " " >expect <<-EOF && - (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? + 1: -1,2 +1,3 +15 + (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? + 1: -1,2 +1,3 +15 _ 2: -2,4 +3,8 +21 go to which hunk? @@ -1,2 +1,3 @@ _10 +15 _20 - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?_ + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_ EOF test_write_lines s y g 1 | git add -p >actual && tail -n 7 <actual >actual.trimmed && @@ -530,11 +531,11 @@ test_expect_success 'goto hunk' ' test_expect_success 'navigate to hunk via regex' ' test_when_finished "git reset" && tr _ " " >expect <<-EOF && - (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? @@ -1,2 +1,3 @@ + (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? @@ -1,2 +1,3 @@ _10 +15 _20 - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?_ + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_ EOF test_write_lines s y /1,2 | git add -p >actual && tail -n 5 <actual >actual.trimmed && @@ -715,21 +716,21 @@ test_expect_success 'colors can be overridden' ' <BLUE>+<RESET><BLUE>new<RESET> <CYAN> more-context<RESET> <BLUE>+<RESET><BLUE>another-one<RESET> - <YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,?]? <RESET><BOLD>Split into 2 hunks.<RESET> + <YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? <RESET><BOLD>Split into 2 hunks.<RESET> <MAGENTA>@@ -1,3 +1,3 @@<RESET> <CYAN> context<RESET> <BOLD>-old<RESET> <BLUE>+<RESET><BLUE>new<RESET> <CYAN> more-context<RESET> - <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET> + <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET> <CYAN> more-context<RESET> <BLUE>+<RESET><BLUE>another-one<RESET> - <YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET> + <YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET> <CYAN> context<RESET> <BOLD>-old<RESET> <BLUE>+new<RESET> <CYAN> more-context<RESET> - <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? <RESET> + <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET> EOF test_cmp expect actual ' diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index accfe3845c..368fc2a6cc 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -3,12 +3,6 @@ test_description='stash -p' . ./lib-patch-mode.sh -if ! test_have_prereq PERL -then - skip_all='skipping stash -p tests, perl not available' - test_done -fi - test_expect_success 'setup' ' mkdir dir && echo parent > dir/foo && diff --git a/t/t3920-crlf-messages.sh b/t/t3920-crlf-messages.sh index 67fd2345af..50ae222f08 100755 --- a/t/t3920-crlf-messages.sh +++ b/t/t3920-crlf-messages.sh @@ -10,7 +10,7 @@ LIB_CRLF_BRANCHES="" create_crlf_ref () { branch="$1" && cat >.crlf-orig-$branch.txt && - cat .crlf-orig-$branch.txt | append_cr >.crlf-message-$branch.txt && + append_cr <.crlf-orig-$branch.txt >.crlf-message-$branch.txt && grep 'Subject' .crlf-orig-$branch.txt | tr '\n' ' ' | sed 's/[ ]*$//' | tr -d '\n' >.crlf-subject-$branch.txt && grep 'Body' .crlf-orig-$branch.txt | append_cr >.crlf-body-$branch.txt && LIB_CRLF_BRANCHES="${LIB_CRLF_BRANCHES} ${branch}" && @@ -97,7 +97,7 @@ test_expect_success 'branch: --verbose works with messages using CRLF' ' git branch -v >tmp && # Remove first two columns, and the line for the currently checked out branch current=$(git branch --show-current) && - grep -v $current <tmp | awk "{\$1=\$2=\"\"}1" >actual && + awk "/$current/ { next } { \$1 = \$2 = \"\" } 1" <tmp >actual && test_cmp expect actual ' diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index 7afc883ec3..cb3307010c 100755 --- a/t/t4002-diff-basic.sh +++ b/t/t4002-diff-basic.sh @@ -405,7 +405,7 @@ test_expect_success 'diff-tree -r B A == diff-tree -r -R A B' ' test_expect_success 'diff can read from stdin' ' test_must_fail git diff --no-index -- MN - < NN | - grep -v "^index" | sed "s#/-#/NN#" >.test-a && + sed "/^index/d; s#/-#/NN#" >.test-a && test_must_fail git diff --no-index -- MN NN | grep -v "^index" >.test-b && test_cmp .test-a .test-b diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index d7a5f7ae78..bc8ba88719 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -13,13 +13,13 @@ TEST_PASSES_SANITIZE_LEAK=true # Print the short OID of a symlink with the given name. symlink_oid () { - local oid=$(printf "%s" "$1" | git hash-object --stdin) && + local oid="$(printf "%s" "$1" | git hash-object --stdin)" && git rev-parse --short "$oid" } # Print the short OID of the given file. short_oid () { - local oid=$(git hash-object "$1") && + local oid="$(git hash-object "$1")" && git rev-parse --short "$oid" } diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 1e3b2dbea4..3855d68dbc 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -633,8 +633,8 @@ check_prefix () { test_cmp expect actual.paths } -test_expect_success 'diff-files does not respect diff.noprefix' ' - git -c diff.noprefix diff-files -p >actual && +test_expect_success 'diff-files does not respect diff.noPrefix' ' + git -c diff.noPrefix diff-files -p >actual && check_prefix actual a/file0 b/file0 ' @@ -643,23 +643,58 @@ test_expect_success 'diff-files respects --no-prefix' ' check_prefix actual file0 file0 ' -test_expect_success 'diff respects diff.noprefix' ' - git -c diff.noprefix diff >actual && +test_expect_success 'diff respects diff.noPrefix' ' + git -c diff.noPrefix diff >actual && check_prefix actual file0 file0 ' -test_expect_success 'diff --default-prefix overrides diff.noprefix' ' - git -c diff.noprefix diff --default-prefix >actual && +test_expect_success 'diff --default-prefix overrides diff.noPrefix' ' + git -c diff.noPrefix diff --default-prefix >actual && check_prefix actual a/file0 b/file0 ' -test_expect_success 'diff respects diff.mnemonicprefix' ' - git -c diff.mnemonicprefix diff >actual && +test_expect_success 'diff respects diff.mnemonicPrefix' ' + git -c diff.mnemonicPrefix diff >actual && check_prefix actual i/file0 w/file0 ' -test_expect_success 'diff --default-prefix overrides diff.mnemonicprefix' ' - git -c diff.mnemonicprefix diff --default-prefix >actual && +test_expect_success 'diff --default-prefix overrides diff.mnemonicPrefix' ' + git -c diff.mnemonicPrefix diff --default-prefix >actual && + check_prefix actual a/file0 b/file0 +' + +test_expect_success 'diff respects diff.srcPrefix' ' + git -c diff.srcPrefix=x/ diff >actual && + check_prefix actual x/file0 b/file0 +' + +test_expect_success 'diff respects diff.dstPrefix' ' + git -c diff.dstPrefix=y/ diff >actual && + check_prefix actual a/file0 y/file0 +' + +test_expect_success 'diff --src-prefix overrides diff.srcPrefix' ' + git -c diff.srcPrefix=y/ diff --src-prefix=z/ >actual && + check_prefix actual z/file0 b/file0 +' + +test_expect_success 'diff --dst-prefix overrides diff.dstPrefix' ' + git -c diff.dstPrefix=y/ diff --dst-prefix=z/ >actual && + check_prefix actual a/file0 z/file0 +' + +test_expect_success 'diff.{src,dst}Prefix ignored with diff.noPrefix' ' + git -c diff.dstPrefix=y/ -c diff.srcPrefix=x/ -c diff.noPrefix diff >actual && + check_prefix actual file0 file0 +' + +test_expect_success 'diff.{src,dst}Prefix ignored with diff.mnemonicPrefix' ' + git -c diff.dstPrefix=x/ -c diff.srcPrefix=y/ -c diff.mnemonicPrefix diff >actual && + check_prefix actual i/file0 w/file0 +' + +test_expect_success 'diff.{src,dst}Prefix ignored with --default-prefix' ' + git -c diff.dstPrefix=x/ -c diff.srcPrefix=y/ diff --default-prefix >actual && check_prefix actual a/file0 b/file0 ' diff --git a/t/t4018/csharp-exclude-assignments b/t/t4018/csharp-exclude-assignments new file mode 100644 index 0000000000..239f312963 --- /dev/null +++ b/t/t4018/csharp-exclude-assignments @@ -0,0 +1,20 @@ +class Example +{ + string Method(int RIGHT) + { + var constantAssignment = "test"; + var methodAssignment = MethodCall(); + var multiLineMethodAssignment = MethodCall( + ); + var multiLine = "first" + + MethodCall() + + + ( MethodCall() + ) + + MethodCall(); + + return "ChangeMe"; + } + + string MethodCall(int a = 0, int b = 0) => "test"; +} diff --git a/t/t4018/csharp-exclude-control-statements b/t/t4018/csharp-exclude-control-statements new file mode 100644 index 0000000000..3a0f404ee1 --- /dev/null +++ b/t/t4018/csharp-exclude-control-statements @@ -0,0 +1,34 @@ +class Example +{ + string Method(int RIGHT) + { + if (false) + { + return "out"; + } + else { } + if (true) MethodCall( + ); + else MethodCall( + ); + switch ("test") + { + case "one": + return MethodCall( + ); + case "two": + break; + } + (int, int) tuple = (1, 4); + switch (tuple) + { + case (1, 4): + MethodCall(); + break; + } + + return "ChangeMe"; + } + + string MethodCall(int a = 0, int b = 0) => "test"; +} diff --git a/t/t4018/csharp-exclude-exceptions b/t/t4018/csharp-exclude-exceptions new file mode 100644 index 0000000000..b1e64256cf --- /dev/null +++ b/t/t4018/csharp-exclude-exceptions @@ -0,0 +1,29 @@ +using System; + +class Example +{ + string Method(int RIGHT) + { + try + { + throw new Exception("fail"); + } + catch (Exception) + { + } + finally + { + } + try { } catch (Exception) {} + try + { + throw GetException( + ); + } + catch (Exception) { } + + return "ChangeMe"; + } + + Exception GetException() => new Exception("fail"); +} diff --git a/t/t4018/csharp-exclude-generic-method-calls b/t/t4018/csharp-exclude-generic-method-calls new file mode 100644 index 0000000000..31af546665 --- /dev/null +++ b/t/t4018/csharp-exclude-generic-method-calls @@ -0,0 +1,12 @@ +class Example +{ + string Method(int RIGHT) + { + GenericMethodCall<int, int>( + ); + + return "ChangeMe"; + } + + string GenericMethodCall<T, T2>() => "test"; +} diff --git a/t/t4018/csharp-exclude-init-dispose b/t/t4018/csharp-exclude-init-dispose new file mode 100644 index 0000000000..2bc8e194e2 --- /dev/null +++ b/t/t4018/csharp-exclude-init-dispose @@ -0,0 +1,22 @@ +using System; + +class Example : IDisposable +{ + string Method(int RIGHT) + { + new Example(); + new Example( + ); + new Example { }; + using (this) + { + } + var def = + this is default( + Example); + + return "ChangeMe"; + } + + public void Dispose() {} +} diff --git a/t/t4018/csharp-exclude-iterations b/t/t4018/csharp-exclude-iterations new file mode 100644 index 0000000000..960aa182ae --- /dev/null +++ b/t/t4018/csharp-exclude-iterations @@ -0,0 +1,26 @@ +using System.Linq; + +class Example +{ + string Method(int RIGHT) + { + do { } while (true); + do MethodCall( + ); while (true); + while (true); + while (true) { + break; + } + for (int i = 0; i < 10; ++i) + { + } + foreach (int i in Enumerable.Range(0, 10)) + { + } + int[] numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0]; + + return "ChangeMe"; + } + + string MethodCall(int a = 0, int b = 0) => "test"; +} diff --git a/t/t4018/csharp-exclude-method-calls b/t/t4018/csharp-exclude-method-calls new file mode 100644 index 0000000000..51e2dc2040 --- /dev/null +++ b/t/t4018/csharp-exclude-method-calls @@ -0,0 +1,20 @@ +class Example +{ + string Method(int RIGHT) + { + MethodCall(); + MethodCall(1, 2); + MethodCall( + 1, 2); + MethodCall( + 1, 2, + 3); + MethodCall( + 1, MethodCall(), + 2); + + return "ChangeMe"; + } + + int MethodCall(int a = 0, int b = 0, int c = 0) => 42; +} diff --git a/t/t4018/csharp-exclude-other b/t/t4018/csharp-exclude-other new file mode 100644 index 0000000000..4d5581cf3e --- /dev/null +++ b/t/t4018/csharp-exclude-other @@ -0,0 +1,18 @@ +class Example +{ + string Method(int RIGHT) + { + lock (this) + { + } + unsafe + { + byte[] bytes = [1, 2, 3]; + fixed (byte* pointerToFirst = bytes) + { + } + } + + return "ChangeMe"; + } +} diff --git a/t/t4018/csharp-method b/t/t4018/csharp-method new file mode 100644 index 0000000000..16b367aca2 --- /dev/null +++ b/t/t4018/csharp-method @@ -0,0 +1,10 @@ +class Example +{ + string Method(int RIGHT) + { + // Filler + // Filler + + return "ChangeMe"; + } +} diff --git a/t/t4018/csharp-method-array b/t/t4018/csharp-method-array new file mode 100644 index 0000000000..1126de8201 --- /dev/null +++ b/t/t4018/csharp-method-array @@ -0,0 +1,10 @@ +class Example +{ + string[] Method(int RIGHT) + { + // Filler + // Filler + + return ["ChangeMe"]; + } +} diff --git a/t/t4018/csharp-method-explicit b/t/t4018/csharp-method-explicit new file mode 100644 index 0000000000..5a710116cc --- /dev/null +++ b/t/t4018/csharp-method-explicit @@ -0,0 +1,12 @@ +using System; + +class Example : IDisposable +{ + void IDisposable.Dispose() // RIGHT + { + // Filler + // Filler + + // ChangeMe + } +} diff --git a/t/t4018/csharp-method-generics b/t/t4018/csharp-method-generics new file mode 100644 index 0000000000..b3216bfb2a --- /dev/null +++ b/t/t4018/csharp-method-generics @@ -0,0 +1,11 @@ +class Example<T1, T2> +{ + Example<int, string> Method<TA, TB>(TA RIGHT, TB b) + { + // Filler + // Filler + + // ChangeMe + return null; + } +} diff --git a/t/t4018/csharp-method-generics-alternate-spaces b/t/t4018/csharp-method-generics-alternate-spaces new file mode 100644 index 0000000000..9583621743 --- /dev/null +++ b/t/t4018/csharp-method-generics-alternate-spaces @@ -0,0 +1,11 @@ +class Example<T1, T2> +{ + Example<int,string> Method<TA ,TB>(TA RIGHT, TB b) + { + // Filler + // Filler + + // ChangeMe + return null; + } +} diff --git a/t/t4018/csharp-method-modifiers b/t/t4018/csharp-method-modifiers new file mode 100644 index 0000000000..caefa8ee99 --- /dev/null +++ b/t/t4018/csharp-method-modifiers @@ -0,0 +1,13 @@ +using System.Threading.Tasks; + +class Example +{ + static internal async Task Method(int RIGHT) + { + // Filler + // Filler + + // ChangeMe + await Task.Delay(1); + } +} diff --git a/t/t4018/csharp-method-multiline b/t/t4018/csharp-method-multiline new file mode 100644 index 0000000000..3983ff42f5 --- /dev/null +++ b/t/t4018/csharp-method-multiline @@ -0,0 +1,10 @@ +class Example +{ + string Method_RIGHT( + int a, + int b, + int c) + { + return "ChangeMe"; + } +} diff --git a/t/t4018/csharp-method-params b/t/t4018/csharp-method-params new file mode 100644 index 0000000000..3f00410ba1 --- /dev/null +++ b/t/t4018/csharp-method-params @@ -0,0 +1,10 @@ +class Example +{ + string Method(int RIGHT, int b, int c = 42) + { + // Filler + // Filler + + return "ChangeMe"; + } +} diff --git a/t/t4018/csharp-method-special-chars b/t/t4018/csharp-method-special-chars new file mode 100644 index 0000000000..e6c7bc01a1 --- /dev/null +++ b/t/t4018/csharp-method-special-chars @@ -0,0 +1,11 @@ +class @Some_Type +{ + @Some_Type @Method_With_Underscore(int RIGHT) + { + // Filler + // Filler + + // ChangeMe + return new @Some_Type(); + } +} diff --git a/t/t4018/csharp-method-with-spacing b/t/t4018/csharp-method-with-spacing new file mode 100644 index 0000000000..233bb976cc --- /dev/null +++ b/t/t4018/csharp-method-with-spacing @@ -0,0 +1,10 @@ +class Example +{ + string Method ( int RIGHT ) + { + // Filler + // Filler + + return "ChangeMe"; + } +} diff --git a/t/t4018/csharp-property b/t/t4018/csharp-property new file mode 100644 index 0000000000..e56dfce34c --- /dev/null +++ b/t/t4018/csharp-property @@ -0,0 +1,11 @@ +class Example +{ + public bool RIGHT + { + get { return true; } + set + { + // ChangeMe + } + } +} diff --git a/t/t4018/csharp-property-braces-same-line b/t/t4018/csharp-property-braces-same-line new file mode 100644 index 0000000000..608131d3d3 --- /dev/null +++ b/t/t4018/csharp-property-braces-same-line @@ -0,0 +1,10 @@ +class Example +{ + public bool RIGHT { + get { return true; } + set + { + // ChangeMe + } + } +} diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index c1ac09ecc7..fdd865f7c3 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -232,7 +232,7 @@ keep_only_cr () { test_expect_success 'external diff with autocrlf = true' ' test_config core.autocrlf true && GIT_EXTERNAL_DIFF=./fake-diff.sh git diff && - test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c) + test $(wc -l <crlfed.txt) = $(keep_only_cr <crlfed.txt | wc -c) ' test_expect_success 'diff --cached' ' diff --git a/t/t4042-diff-textconv-caching.sh b/t/t4042-diff-textconv-caching.sh index bf33aedf4b..8ebfa3c1be 100755 --- a/t/t4042-diff-textconv-caching.sh +++ b/t/t4042-diff-textconv-caching.sh @@ -118,4 +118,26 @@ test_expect_success 'log notes cache and still use cache for -p' ' git log --no-walk -p refs/notes/textconv/magic HEAD ' +test_expect_success 'caching is silently ignored outside repo' ' + mkdir -p non-repo && + echo one >non-repo/one && + echo two >non-repo/two && + echo "* diff=test" >attr && + test_expect_code 1 \ + nongit git -c core.attributesFile="$PWD/attr" \ + -c diff.test.textconv="tr a-z A-Z <" \ + -c diff.test.cachetextconv=true \ + diff --no-index one two >actual && + cat >expect <<-\EOF && + diff --git a/one b/two + index 5626abf..f719efd 100644 + --- a/one + +++ b/two + @@ -1 +1 @@ + -ONE + +TWO + EOF + test_cmp expect actual +' + test_done diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index d370ecfe0d..144619ab87 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -9,6 +9,7 @@ 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 71ef4132d1..dc501aac38 100755 --- a/t/t4104-apply-boundary.sh +++ b/t/t4104-apply-boundary.sh @@ -5,6 +5,7 @@ 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/t4113-apply-ending.sh b/t/t4113-apply-ending.sh index 66fa51591e..2c65c6a169 100755 --- a/t/t4113-apply-ending.sh +++ b/t/t4113-apply-ending.sh @@ -6,6 +6,7 @@ test_description='git apply trying to add an ending line. ' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # setup diff --git a/t/t4117-apply-reject.sh b/t/t4117-apply-reject.sh index c86d05a96f..4d15ccd28e 100755 --- a/t/t4117-apply-reject.sh +++ b/t/t4117-apply-reject.sh @@ -7,6 +7,7 @@ test_description='git apply with rejects ' +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 3ef84619f5..3601c0c5dc 100755 --- a/t/t4123-apply-shrink.sh +++ b/t/t4123-apply-shrink.sh @@ -2,6 +2,7 @@ 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 ece9fae207..56210b5609 100755 --- a/t/t4126-apply-empty.sh +++ b/t/t4126-apply-empty.sh @@ -66,4 +66,28 @@ test_expect_success 'apply --index create' ' git diff --exit-code ' +test_expect_success !MINGW 'apply with no-contents and a funny pathname' ' + test_when_finished "rm -fr \"funny \"; git reset --hard" && + + mkdir "funny " && + >"funny /empty" && + git add "funny /empty" && + git diff HEAD -- "funny /" >sample.patch && + git diff -R HEAD -- "funny /" >elpmas.patch && + + git reset --hard && + + git apply --stat --check --apply sample.patch && + test_must_be_empty "funny /empty" && + + git apply --stat --check --apply elpmas.patch && + test_path_is_missing "funny /empty" && + + git apply -R --stat --check --apply elpmas.patch && + test_must_be_empty "funny /empty" && + + git apply -R --stat --check --apply sample.patch && + test_path_is_missing "funny /empty" +' + test_done diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh index 2775bfadd8..4eb8444029 100755 --- a/t/t4129-apply-samemode.sh +++ b/t/t4129-apply-samemode.sh @@ -103,4 +103,31 @@ test_expect_success POSIXPERM 'do not use core.sharedRepository for working tree ) ' +test_expect_success 'git apply respects core.fileMode' ' + test_config core.fileMode false && + echo true >script.sh && + git add --chmod=+x script.sh && + git ls-files -s script.sh >ls-files-output && + test_grep "^100755" ls-files-output && + test_tick && git commit -m "Add script" && + git ls-tree -r HEAD script.sh >ls-tree-output && + test_grep "^100755" ls-tree-output && + + echo true >>script.sh && + test_tick && git commit -m "Modify script" script.sh && + git format-patch -1 --stdout >patch && + test_grep "^index.*100755$" patch && + + git switch -c branch HEAD^ && + git apply --index patch 2>err && + test_grep ! "has type 100644, expected 100755" err && + git reset --hard && + + git apply patch 2>err && + test_grep ! "has type 100644, expected 100755" err && + + git apply --cached patch 2>err && + test_grep ! "has type 100644, expected 100755" err +' + test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 3b12576269..5e2b6c80ea 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -1224,8 +1224,8 @@ test_expect_success 'record as an empty commit when meeting e-mail message that test_expect_success 'skip an empty patch in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --skip && test_path_is_missing .git/rebase-apply && @@ -1236,8 +1236,8 @@ test_expect_success 'skip an empty patch in the middle of an am session' ' test_expect_success 'record an empty patch as an empty commit in the middle of an am session' ' git checkout empty-commit^ && - test_must_fail git am empty-commit.patch >err && - grep "Patch is empty." err && + test_must_fail git am empty-commit.patch >out 2>err && + grep "Patch is empty." out && grep "To record the empty patch as an empty commit, run \"git am --allow-empty\"." err && git am --allow-empty >output && grep "No changes - recorded it as an empty commit." output && diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index fb53dddf79..b0a3e84984 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -671,4 +671,67 @@ test_expect_success 'test simple stage 1 handling' ' ) ' +test_expect_success 'rerere does not crash with missing preimage' ' + git config rerere.enabled true && + + echo bar >test && + git add test && + git commit -m "one" && + git branch rerere_no_crash && + + echo foo >>test && + git add test && + git commit -m "two" && + + git checkout rerere_no_crash && + echo "bar" >>test && + git add test && + git commit -m "three" && + + test_must_fail git rebase main && + rm .git/rr-cache/*/preimage && + git rebase --abort +' + +test_expect_success 'rerere does not crash with unmatched conflict marker' ' + git config rerere.enabled true && + + echo bar >test && + git add test && + git commit -m "one" && + git branch rerere_no_preimage && + + cat >test <<-EOF && + test + bar + foobar + EOF + git add test && + git commit -m "two" && + + git checkout rerere_no_preimage && + echo "bar" >>test && + git add test && + git commit -m "three" && + + cat >test <<-EOF && + foobar + bar + bar + EOF + git add test && + git commit -m "four" && + + test_must_fail git rebase main && + cat >test <<-EOF && + test + bar + <<<<<<< HEAD + foobar + bar + EOF + git add test && + test_must_fail git rebase --continue +' + test_done diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh index d7382709fc..f698d0c9ad 100755 --- a/t/t4201-shortlog.sh +++ b/t/t4201-shortlog.sh @@ -312,6 +312,38 @@ test_expect_success 'shortlog de-duplicates trailers in a single commit' ' test_cmp expect actual ' +# Trailers that have unfolded (single line) and folded (multiline) values which +# are otherwise identical are treated as the same trailer for de-duplication. +test_expect_success 'shortlog de-duplicates trailers in a single commit (folded/unfolded values)' ' + git commit --allow-empty -F - <<-\EOF && + subject one + + this message has two distinct values, plus a repeat (folded) + + Repeated-trailer: Foo foo foo + Repeated-trailer: Bar + Repeated-trailer: Foo + foo foo + EOF + + git commit --allow-empty -F - <<-\EOF && + subject two + + similar to the previous, but without the second distinct value + + Repeated-trailer: Foo foo foo + Repeated-trailer: Foo + foo foo + EOF + + cat >expect <<-\EOF && + 2 Foo foo foo + 1 Bar + EOF + git shortlog -ns --group=trailer:repeated-trailer -2 HEAD >actual && + test_cmp expect actual +' + test_expect_success 'shortlog can match multiple groups' ' git commit --allow-empty -F - <<-\EOF && subject one diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index e3d655e6b8..158b49d4b6 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -30,40 +30,46 @@ test_expect_success 'set up basic repos' ' >bar && git add foo && test_tick && - git config i18n.commitEncoding $test_encoding && + test_config i18n.commitEncoding $test_encoding && commit_msg $test_encoding | git commit -F - && git add bar && test_tick && - git commit -m "add bar" && - git config --unset i18n.commitEncoding + git commit -m "add bar" ' test_expect_success 'alias builtin format' ' git log --pretty=oneline >expected && - git config pretty.test-alias oneline && + test_config pretty.test-alias oneline && git log --pretty=test-alias >actual && test_cmp expected actual ' test_expect_success 'alias masking builtin format' ' git log --pretty=oneline >expected && - git config pretty.oneline "%H" && + test_config pretty.oneline "%H" && git log --pretty=oneline >actual && test_cmp expected actual ' test_expect_success 'alias user-defined format' ' git log --pretty="format:%h" >expected && - git config pretty.test-alias "format:%h" && + test_config pretty.test-alias "format:%h" && git log --pretty=test-alias >actual && test_cmp expected actual ' +test_expect_success 'alias user-defined format is matched case-insensitively' ' + git log --pretty="format:%h" >expected && + test_config pretty.testone "format:%h" && + test_config pretty.testtwo testOne && + git log --pretty=testTwo >actual && + test_cmp expected actual +' + test_expect_success 'alias user-defined tformat with %s (ISO8859-1 encoding)' ' - git config i18n.logOutputEncoding $test_encoding && + test_config i18n.logOutputEncoding $test_encoding && git log --oneline >expected-s && git log --pretty="tformat:%h %s" >actual-s && - git config --unset i18n.logOutputEncoding && test_cmp expected-s actual-s ' @@ -75,34 +81,34 @@ test_expect_success 'alias user-defined tformat with %s (utf-8 encoding)' ' test_expect_success 'alias user-defined tformat' ' git log --pretty="tformat:%h" >expected && - git config pretty.test-alias "tformat:%h" && + test_config pretty.test-alias "tformat:%h" && git log --pretty=test-alias >actual && test_cmp expected actual ' test_expect_success 'alias non-existent format' ' - git config pretty.test-alias format-that-will-never-exist && + test_config pretty.test-alias format-that-will-never-exist && test_must_fail git log --pretty=test-alias ' test_expect_success 'alias of an alias' ' git log --pretty="tformat:%h" >expected && - git config pretty.test-foo "tformat:%h" && - git config pretty.test-bar test-foo && + test_config pretty.test-foo "tformat:%h" && + test_config pretty.test-bar test-foo && git log --pretty=test-bar >actual && test_cmp expected actual ' test_expect_success 'alias masking an alias' ' git log --pretty=format:"Two %H" >expected && - git config pretty.duplicate "format:One %H" && - git config --add pretty.duplicate "format:Two %H" && + test_config pretty.duplicate "format:One %H" && + test_config pretty.duplicate "format:Two %H" --add && git log --pretty=duplicate >actual && test_cmp expected actual ' test_expect_success 'alias loop' ' - git config pretty.test-foo test-bar && - git config pretty.test-bar test-foo && + test_config pretty.test-foo test-bar && + test_config pretty.test-bar test-foo && test_must_fail git log --pretty=test-foo ' @@ -156,7 +162,7 @@ test_expect_success 'NUL termination with --reflog --pretty=oneline' ' for r in $revs do git show -s --pretty=oneline "$r" >raw && - cat raw | lf_to_nul || return 1 + lf_to_nul <raw || return 1 done >expect && # the trailing NUL is already produced so we do not need to # output another one diff --git a/t/t4210-log-i18n.sh b/t/t4210-log-i18n.sh index d2dfcf164e..75216f19ce 100755 --- a/t/t4210-log-i18n.sh +++ b/t/t4210-log-i18n.sh @@ -64,7 +64,7 @@ test_expect_success 'log --grep does not find non-reencoded values (latin1)' ' ' triggers_undefined_behaviour () { - local engine=$1 + local engine="$1" case $engine in fixed) @@ -85,7 +85,7 @@ triggers_undefined_behaviour () { } mismatched_git_log () { - local pattern=$1 + local pattern="$1" LC_ALL=$is_IS_locale git log --encoding=ISO-8859-1 --format=%s \ --grep=$pattern diff --git a/t/t4252-am-options.sh b/t/t4252-am-options.sh index e758e634a3..5b680dc755 100755 --- a/t/t4252-am-options.sh +++ b/t/t4252-am-options.sh @@ -1,6 +1,8 @@ #!/bin/sh 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/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh index 45f1d4f95e..661feb6070 100755 --- a/t/t4254-am-corrupt.sh +++ b/t/t4254-am-corrupt.sh @@ -59,7 +59,7 @@ test_expect_success setup ' # Also, it had the unwanted side-effect of deleting f. test_expect_success 'try to apply corrupted patch' ' test_when_finished "git am --abort" && - test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual && + test_must_fail git -c advice.amWorkDir=false -c advice.mergeConflict=false am bad-patch.diff 2>actual && echo "error: git diff header lacks filename information (line 4)" >expected && test_path_is_file f && test_cmp expected actual diff --git a/t/t4258-am-quoted-cr.sh b/t/t4258-am-quoted-cr.sh index 201915b45a..3573c9147f 100755 --- a/t/t4258-am-quoted-cr.sh +++ b/t/t4258-am-quoted-cr.sh @@ -2,6 +2,7 @@ test_description='test am --quoted-cr=<action>' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh DATA="$TEST_DIRECTORY/t4258" diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index 12ac436873..eea19907b5 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -313,7 +313,7 @@ test_expect_success 'rename/add handling' ' # First, check that the bar that appears at stage 3 does not # correspond to an individual blob anywhere in history # - hash=$(cat out | tr "\0" "\n" | head -n 3 | grep 3.bar | cut -f 2 -d " ") && + hash=$(tr "\0" "\n" <out | head -n 3 | grep 3.bar | cut -f 2 -d " ") && git rev-list --objects --all >all_blobs && ! grep $hash all_blobs && @@ -380,7 +380,7 @@ test_expect_success SYMLINKS 'rename/add, where add is a mode conflict' ' # First, check that the bar that appears at stage 3 does not # correspond to an individual blob anywhere in history # - hash=$(cat out | tr "\0" "\n" | head -n 3 | grep 3.bar | cut -f 2 -d " ") && + hash=$(tr "\0" "\n" <out | head -n 3 | grep 3.bar | cut -f 2 -d " ") && git rev-list --objects --all >all_blobs && ! grep $hash all_blobs && @@ -630,8 +630,8 @@ test_expect_success 'mod6: chains of rename/rename(1to2) and add/add via collidi # conflict entries do not appear as individual blobs anywhere # in history. # - hash1=$(cat out | tr "\0" "\n" | head | grep 2.four | cut -f 2 -d " ") && - hash2=$(cat out | tr "\0" "\n" | head | grep 3.two | cut -f 2 -d " ") && + hash1=$(tr "\0" "\n" <out | head | grep 2.four | cut -f 2 -d " ") && + hash2=$(tr "\0" "\n" <out | head | grep 3.two | cut -f 2 -d " ") && git rev-list --objects --all >all_blobs && ! grep $hash1 all_blobs && ! grep $hash2 all_blobs && @@ -945,4 +945,49 @@ test_expect_success 'check the input format when --stdin is passed' ' test_cmp expect actual ' +test_expect_success '--merge-base with tree OIDs' ' + git merge-tree --merge-base=side1^ side1 side3 >with-commits && + git merge-tree --merge-base=side1^^{tree} side1^{tree} side3^{tree} >with-trees && + test_cmp with-commits with-trees +' + +test_expect_success 'error out on missing tree objects' ' + git init --bare missing-tree.git && + git rev-list side3 >list && + git rev-parse side3^: >>list && + git pack-objects missing-tree.git/objects/pack/side3-tree-is-missing <list && + side3=$(git rev-parse side3) && + test_must_fail git --git-dir=missing-tree.git merge-tree $side3^ $side3 >actual 2>err && + test_grep "Could not read $(git rev-parse $side3:)" err && + test_must_be_empty actual +' + +test_expect_success 'error out on missing blob objects' ' + echo 1 | git hash-object -w --stdin >blob1 && + echo 2 | git hash-object -w --stdin >blob2 && + echo 3 | git hash-object -w --stdin >blob3 && + printf "100644 blob $(cat blob1)\tblob\n" | git mktree >tree1 && + printf "100644 blob $(cat blob2)\tblob\n" | git mktree >tree2 && + printf "100644 blob $(cat blob3)\tblob\n" | git mktree >tree3 && + git init --bare missing-blob.git && + cat blob1 blob3 tree1 tree2 tree3 | + git pack-objects missing-blob.git/objects/pack/side1-whatever-is-missing && + test_must_fail git --git-dir=missing-blob.git >actual 2>err \ + merge-tree --merge-base=$(cat tree1) $(cat tree2) $(cat tree3) && + test_grep "unable to read blob object $(cat blob2)" err && + test_must_be_empty actual +' + +test_expect_success 'error out on missing commits as well' ' + git init --bare missing-commit.git && + git rev-list --objects side1 side3 >list-including-initial && + grep -v ^$(git rev-parse side1^) <list-including-initial >list && + git pack-objects missing-commit.git/objects/pack/missing-initial <list && + side1=$(git rev-parse side1) && + side3=$(git rev-parse side3) && + test_must_fail git --git-dir=missing-commit.git \ + merge-tree --allow-unrelated-histories $side1 $side3 >actual && + test_must_be_empty actual +' + test_done diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh index 654d8cf3ee..c8d0655454 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -70,7 +70,7 @@ test_expect_success 'respect NULs' ' git mailsplit -d3 -o. "$DATA/nul-plain" && test_cmp "$DATA/nul-plain" 001 && - (cat 001 | git mailinfo msg patch) && + git mailinfo msg patch <001 && test_line_count = 4 patch ' diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index a58f91035d..61e2be2903 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -465,7 +465,7 @@ test_with_bad_commit () { must_pass_arg="$2" && ( cd strict && - test_expect_fail git index-pack "$must_fail_arg" "test-$(cat pack-name).pack" + test_must_fail git index-pack "$must_fail_arg" "test-$(cat pack-name).pack" && git index-pack "$must_pass_arg" "test-$(cat pack-name).pack" ) } diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh index 2ff3eef9a3..79552d6ef7 100755 --- a/t/t5317-pack-objects-filter-objects.sh +++ b/t/t5317-pack-objects-filter-objects.sh @@ -455,7 +455,7 @@ test_expect_success 'setup r1 - delete loose blobs' ' test_parse_ls_files_stage_oids <ls_files_result | sort >expected && - for id in `cat expected | sed "s|..|&/|"` + for id in `sed "s|..|&/|" expected` do rm r1/.git/objects/$id || return 1 done diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh index 70d1b58709..5d7d321840 100755 --- a/t/t5326-multi-pack-bitmaps.sh +++ b/t/t5326-multi-pack-bitmaps.sh @@ -513,4 +513,21 @@ test_expect_success 'corrupt MIDX with bitmap causes fallback' ' ) ' +for allow_pack_reuse in single multi +do + test_expect_success "reading MIDX without BTMP chunk does not complain with $allow_pack_reuse pack reuse" ' + test_when_finished "rm -rf midx-without-btmp" && + git init midx-without-btmp && + ( + cd midx-without-btmp && + test_commit initial && + + git repack -Adbl --write-bitmap-index --write-midx && + GIT_TEST_MIDX_READ_BTMP=false git -c pack.allowPackReuse=$allow_pack_reuse \ + pack-objects --all --use-bitmap-index --stdout </dev/null >/dev/null 2>err && + test_must_be_empty err + ) + ' +done + test_done diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 8b8bc47dc0..d8cadeec73 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -123,7 +123,7 @@ remote: STDOUT post-update remote: STDERR post-update EOF test_expect_success 'send-pack stderr contains hook messages' ' - grep ^remote: send.err | sed "s/ *\$//" >actual && + sed -n "/^remote:/s/ *\$//p" send.err >actual && test_cmp expect actual ' diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh index b4bc24691c..c91a62b77a 100755 --- a/t/t5534-push-signed.sh +++ b/t/t5534-push-signed.sh @@ -303,7 +303,7 @@ test_expect_success GPGSM 'fail without key and heed user.signingkey x509' ' EOF sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert ) >expect.in && - key=$(cat "${GNUPGHOME}/trustlist.txt" | cut -d" " -f1 | tr -d ":") && + key=$(cut -d" " -f1 <"${GNUPGHOME}/trustlist.txt" | tr -d ":") && sed -e "s/^KEY=/KEY=${key}/" expect.in >expect && noop=$(git rev-parse noop) && diff --git a/t/t5555-http-smart-common.sh b/t/t5555-http-smart-common.sh index b1cfe8b7db..3dcb3340a3 100755 --- a/t/t5555-http-smart-common.sh +++ b/t/t5555-http-smart-common.sh @@ -131,7 +131,6 @@ test_expect_success 'git upload-pack --advertise-refs: v2' ' fetch=shallow wait-for-done server-option object-format=$(test_oid algo) - object-info 0000 EOF diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index fb1b9c686d..ca43185681 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -776,6 +776,18 @@ test_expect_success 'batch missing blob request does not inadvertently try to fe . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd +test_expect_success 'clone with includeIf' ' + test_when_finished "rm -rf repo \"$HTTPD_DOCUMENT_ROOT_PATH/repo.git\"" && + git clone --bare --no-local src "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + + test_when_finished "rm \"$HOME\"/.gitconfig" && + cat >"$HOME"/.gitconfig <<-EOF && + [includeIf "onbranch:something"] + path = /does/not/exist.inc + EOF + git clone $HTTPD_URL/smart/repo.git repo +' + test_expect_success 'partial clone using HTTP' ' partial_clone "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server" ' diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh index a400bcca62..e93e0d0cc3 100755 --- a/t/t5606-clone-options.sh +++ b/t/t5606-clone-options.sh @@ -120,14 +120,14 @@ test_expect_success 'prefers -c config over --template config' ' ' -test_expect_failure 'prefers --template config even for core.bare' ' +test_expect_success 'ignore --template config for core.bare' ' template="$TRASH_DIRECTORY/template-with-bare-config" && mkdir "$template" && git config --file "$template/config" core.bare true && git clone "--template=$template" parent clone-bare-config && - test "$(git -C clone-bare-config config --local core.bare)" = "true" && - test_path_is_file clone-bare-config/HEAD + test "$(git -C clone-bare-config config --local core.bare)" = "false" && + test_path_is_missing clone-bare-config/HEAD ' test_expect_success 'prefers config "clone.defaultRemoteName" over default' ' diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index 3591bc2417..c48830de8f 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -20,7 +20,6 @@ test_expect_success 'test capability advertisement' ' fetch=shallow wait-for-done server-option object-format=$(test_oid algo) - object-info EOF cat >expect.trailer <<-EOF && 0000 @@ -323,6 +322,8 @@ test_expect_success 'unexpected lines are not allowed in fetch request' ' # Test the basics of object-info # test_expect_success 'basics of object-info' ' + test_config transfer.advertiseObjectInfo true && + test-tool pkt-line pack >in <<-EOF && command=object-info object-format=$(test_oid algo) @@ -380,4 +381,25 @@ test_expect_success 'basics of bundle-uri: dies if not enabled' ' test_must_be_empty out ' +test_expect_success 'object-info missing from capabilities when disabled' ' + test_config transfer.advertiseObjectInfo false && + + GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \ + --advertise-capabilities >out && + test-tool pkt-line unpack <out >actual && + + ! grep object.info actual +' + +test_expect_success 'object-info commands rejected when disabled' ' + test_config transfer.advertiseObjectInfo false && + + test-tool pkt-line pack >in <<-EOF && + command=object-info + EOF + + test_must_fail test-tool serve-v2 --stateless-rpc <in 2>err && + grep invalid.command err +' + test_done diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 6ef4971845..1ef540f73d 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -778,6 +778,25 @@ test_expect_success 'archive with custom path does not request v2' ' ! grep ^GIT_PROTOCOL env.trace ' +test_expect_success 'reject client packfile-uris if not advertised' ' + { + packetize command=fetch && + packetize object-format=$(test_oid algo) && + printf 0001 && + packetize packfile-uris https && + packetize done && + printf 0000 + } >input && + test_must_fail env GIT_PROTOCOL=version=2 \ + git upload-pack client <input && + test_must_fail env GIT_PROTOCOL=version=2 \ + git -c uploadpack.blobpackfileuri \ + upload-pack client <input && + GIT_PROTOCOL=version=2 \ + git -c uploadpack.blobpackfileuri=anything \ + upload-pack client <input +' + # Test protocol v2 with 'http://' transport # . "$TEST_DIRECTORY"/lib-httpd.sh diff --git a/t/t5801/git-remote-testgit b/t/t5801/git-remote-testgit index 1544d6dc6b..c5b10f5775 100755 --- a/t/t5801/git-remote-testgit +++ b/t/t5801/git-remote-testgit @@ -12,6 +12,11 @@ url=$2 dir="$GIT_DIR/testgit/$alias" +if ! git rev-parse --is-inside-git-dir +then + exit 1 +fi + h_refspec="refs/heads/*:refs/testgit/$alias/heads/*" t_refspec="refs/tags/*:refs/testgit/$alias/tags/*" @@ -25,6 +30,7 @@ GIT_DIR="$url/.git" export GIT_DIR force= +object_format= mkdir -p "$dir" @@ -56,7 +62,8 @@ do echo ;; list) - echo ":object-format $(git rev-parse --show-object-format=storage)" + test -n "$object_format" && + echo ":object-format $(git rev-parse --show-object-format=storage)" git for-each-ref --format='? %(refname)' 'refs/heads/' 'refs/tags/' head=$(git symbolic-ref HEAD) echo "@$head HEAD" diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh index 211672759a..127180e1c9 100755 --- a/t/t6022-rev-list-missing.sh +++ b/t/t6022-rev-list-missing.sh @@ -10,7 +10,10 @@ TEST_PASSES_SANITIZE_LEAK=true test_expect_success 'create repository and alternate directory' ' test_commit 1 && test_commit 2 && - test_commit 3 + test_commit 3 && + git tag -m "tag message" annot_tag HEAD~1 && + git tag regul_tag HEAD~1 && + git branch a_branch HEAD~1 ' # We manually corrupt the repository, which means that the commit-graph may @@ -46,9 +49,10 @@ do git rev-list --objects --no-object-names \ HEAD ^$obj >expect.raw && - # Blobs are shared by all commits, so evethough a commit/tree + # Blobs are shared by all commits, so even though a commit/tree # might be skipped, its blob must be accounted for. - if [ $obj != "HEAD:1.t" ]; then + if test $obj != "HEAD:1.t" + then echo $(git rev-parse HEAD:1.t) >>expect.raw && echo $(git rev-parse HEAD:2.t) >>expect.raw fi && @@ -77,4 +81,69 @@ do done done +for missing_tip in "annot_tag" "regul_tag" "a_branch" "HEAD~1" "HEAD~1^{tree}" "HEAD:1.t" +do + # We want to check that things work when both + # - all the tips passed are missing (case existing_tip = ""), and + # - there is one missing tip and one existing tip (case existing_tip = "HEAD") + for existing_tip in "" "HEAD" + do + for action in "allow-any" "print" + do + test_expect_success "--missing=$action with tip '$missing_tip' missing and tip '$existing_tip'" ' + # Before the object is made missing, we use rev-list to + # get the expected oids. + if test "$existing_tip" = "HEAD" + then + git rev-list --objects --no-object-names \ + HEAD ^$missing_tip >expect.raw + else + >expect.raw + fi && + + # Blobs are shared by all commits, so even though a commit/tree + # might be skipped, its blob must be accounted for. + if test "$existing_tip" = "HEAD" && test $missing_tip != "HEAD:1.t" + then + echo $(git rev-parse HEAD:1.t) >>expect.raw && + echo $(git rev-parse HEAD:2.t) >>expect.raw + fi && + + missing_oid="$(git rev-parse $missing_tip)" && + + if test "$missing_tip" = "annot_tag" + then + oid="$(git rev-parse $missing_tip^{commit})" && + echo "$missing_oid" >>expect.raw + else + oid="$missing_oid" + fi && + + path=".git/objects/$(test_oid_to_path $oid)" && + + mv "$path" "$path.hidden" && + test_when_finished "mv $path.hidden $path" && + + git rev-list --missing=$action --objects --no-object-names \ + $missing_oid $existing_tip >actual.raw && + + # When the action is to print, we should also add the missing + # oid to the expect list. + case $action in + allow-any) + ;; + print) + grep ?$oid actual.raw && + echo ?$oid >>expect.raw + ;; + esac && + + sort actual.raw >actual && + sort expect.raw >expect && + test_cmp expect actual + ' + done + done +done + test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 561080bf24..cdc0270640 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -878,7 +878,7 @@ test_expect_success 'broken branch creation' ' echo "" > expected.ok cat > expected.missing-tree.default <<EOF -fatal: unable to read tree $deleted +fatal: unable to read tree ($deleted) EOF test_expect_success 'bisect fails if tree is broken on start commit' ' diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh index 52822b9461..43e1afd44c 100755 --- a/t/t6112-rev-list-filters-objects.sh +++ b/t/t6112-rev-list-filters-objects.sh @@ -670,7 +670,7 @@ test_expect_success 'rev-list W/ --missing=print' ' awk -f print_2.awk ls_files_result | sort >expected && - for id in `cat expected | sed "s|..|&/|"` + for id in `sed "s|..|&/|" expected` do rm r1/.git/objects/$id || return 1 done && diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index 82f3d1ea0f..948f1bb5f4 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -31,6 +31,37 @@ test_expect_success 'setup some history and refs' ' git update-ref refs/odd/spot main ' +test_expect_success '--include-root-refs pattern prints pseudorefs' ' + cat >expect <<-\EOF && + HEAD + ORIG_HEAD + refs/heads/main + refs/heads/side + refs/odd/spot + refs/tags/annotated-tag + refs/tags/doubly-annotated-tag + refs/tags/doubly-signed-tag + refs/tags/four + refs/tags/one + refs/tags/signed-tag + refs/tags/three + refs/tags/two + EOF + git update-ref ORIG_HEAD main && + git for-each-ref --format="%(refname)" --include-root-refs >actual && + test_cmp expect actual +' + +test_expect_success '--include-root-refs with other patterns' ' + cat >expect <<-\EOF && + HEAD + ORIG_HEAD + EOF + git update-ref ORIG_HEAD main && + git for-each-ref --format="%(refname)" --include-root-refs "*HEAD" >actual && + test_cmp expect actual +' + test_expect_success 'filtering with --points-at' ' cat >expect <<-\EOF && refs/heads/main diff --git a/t/t6413-merge-crlf.sh b/t/t6413-merge-crlf.sh index b4f4a313f4..647ea1e838 100755 --- a/t/t6413-merge-crlf.sh +++ b/t/t6413-merge-crlf.sh @@ -34,14 +34,14 @@ test_expect_success setup ' test_expect_success 'Check "ours" is CRLF' ' git reset --hard initial && git merge side -s ours && - cat file | remove_cr | append_cr >file.temp && + remove_cr <file | append_cr >file.temp && test_cmp file file.temp ' test_expect_success 'Check that conflict file is CRLF' ' git reset --hard a && test_must_fail git merge side && - cat file | remove_cr | append_cr >file.temp && + remove_cr <file | append_cr >file.temp && test_cmp file file.temp ' diff --git a/t/t6418-merge-text-auto.sh b/t/t6418-merge-text-auto.sh index 41288a60ce..48a62cb855 100755 --- a/t/t6418-merge-text-auto.sh +++ b/t/t6418-merge-text-auto.sh @@ -15,6 +15,7 @@ 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/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh index 70650521b0..7a3f1cb27c 100755 --- a/t/t6437-submodule-merge.sh +++ b/t/t6437-submodule-merge.sh @@ -113,7 +113,7 @@ test_expect_success 'merging should conflict for non fast-forward' ' git checkout -b test-nonforward-a b && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then - test_must_fail git merge c >actual && + test_must_fail git merge c 2>actual && sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && grep "$sub_expect" actual else @@ -154,9 +154,9 @@ test_expect_success 'merging should conflict for non fast-forward (resolution ex git rev-parse --short sub-d > ../expect) && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then - test_must_fail git merge c >actual && + test_must_fail git merge c >actual 2>sub-actual && sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && - grep "$sub_expect" actual + grep "$sub_expect" sub-actual else test_must_fail git merge c 2> actual fi && @@ -181,9 +181,9 @@ test_expect_success 'merging should fail for ambiguous common parent' ' ) && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then - test_must_fail git merge c >actual && + test_must_fail git merge c >actual 2>sub-actual && sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" && - grep "$sub_expect" actual + grep "$sub_expect" sub-actual else test_must_fail git merge c 2> actual fi && @@ -227,7 +227,7 @@ test_expect_success 'merging should fail for changes that are backwards' ' git commit -a -m "f" && git checkout -b test-backward e && - test_must_fail git merge f >actual && + test_must_fail git merge f 2>actual && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" && @@ -535,7 +535,7 @@ test_expect_success 'merging should fail with no merge base' ' git checkout -b b init && git add sub && git commit -m "b" && - test_must_fail git merge a >actual && + test_must_fail git merge a 2>actual && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" && diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index 18fe1c25e6..43d40175f8 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -11,23 +11,7 @@ test_expect_success 'setup' ' # behavior, make sure we always pack everything to one pack by # default git config gc.bigPackThreshold 2g && - - # These are simply values which, when hashed as a blob with a newline, - # produce a hash where the first byte is 0x17 in their respective - # algorithms. - test_oid_cache <<-EOF - obj1 sha1:263 - obj1 sha256:34 - - obj2 sha1:410 - obj2 sha256:174 - - obj3 sha1:523 - obj3 sha256:313 - - obj4 sha1:790 - obj4 sha256:481 - EOF + test_oid_init ' test_expect_success 'gc empty repository' ' @@ -114,8 +98,8 @@ test_expect_success 'pre-auto-gc hook can stop auto gc' ' # We need to create two object whose sha1s start with 17 # since this is what git gc counts. As it happens, these # two blobs will do so. - test_commit "$(test_oid obj1)" && - test_commit "$(test_oid obj2)" && + test_commit "$(test_oid blob17_1)" && + test_commit "$(test_oid blob17_2)" && git gc --auto >../out.actual 2>../err.actual ) && @@ -146,13 +130,13 @@ test_expect_success 'auto gc with too many loose objects does not attempt to cre # We need to create two object whose sha1s start with 17 # since this is what git gc counts. As it happens, these # two blobs will do so. - test_commit "$(test_oid obj1)" && - test_commit "$(test_oid obj2)" && + test_commit "$(test_oid blob17_1)" && + test_commit "$(test_oid blob17_2)" && # Our first gc will create a pack; our second will create a second pack git gc --auto && ls .git/objects/pack/pack-*.pack | sort >existing_packs && - test_commit "$(test_oid obj3)" && - test_commit "$(test_oid obj4)" && + test_commit "$(test_oid blob17_3)" && + test_commit "$(test_oid blob17_4)" && git gc --auto 2>err && test_grep ! "^warning:" err && diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index f6aebe92ff..5ab4d41ee7 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -396,10 +396,7 @@ test_expect_success '--prune-empty is able to prune entire branch' ' git branch prune-entire B && git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t B.t" prune-entire && test_must_fail git rev-parse refs/heads/prune-entire && - if test_have_prereq REFFILES - then - test_must_fail git reflog exists refs/heads/prune-entire - fi + test_must_fail git reflog exists refs/heads/prune-entire ' test_expect_success '--remap-to-ancestor with filename filters' ' diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index b41a47eb94..696866d779 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1777,10 +1777,10 @@ test_expect_success '--points-at finds annotated tags of tags' ' ' test_expect_success 'recursive tagging should give advice' ' - sed -e "s/|$//" <<-EOF >expect && + cat >expect <<-EOF && hint: You have created a nested tag. The object referred to by your new tag is hint: already a tag. If you meant to tag the object that it points to, use: - hint: | + hint: hint: git tag -f nested annotated-v4.0^{} hint: Disable this message with "git config advice.nestedTag false" EOF diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh index 05079c7246..f4f3b7a677 100755 --- a/t/t7105-reset-patch.sh +++ b/t/t7105-reset-patch.sh @@ -5,7 +5,7 @@ test_description='git reset --patch' TEST_PASSES_SANITIZE_LEAK=true . ./lib-patch-mode.sh -test_expect_success PERL 'setup' ' +test_expect_success 'setup' ' mkdir dir && echo parent > dir/foo && echo dummy > bar && @@ -19,42 +19,46 @@ test_expect_success PERL 'setup' ' # note: bar sorts before foo, so the first 'n' is always to skip 'bar' -test_expect_success PERL 'saying "n" does nothing' ' +test_expect_success 'saying "n" does nothing' ' set_and_save_state dir/foo work work && test_write_lines n n | git reset -p && verify_saved_state dir/foo && verify_saved_state bar ' -test_expect_success PERL 'git reset -p' ' - test_write_lines n y | git reset -p >output && - verify_state dir/foo work head && - verify_saved_state bar && - test_grep "Unstage" output -' - -test_expect_success PERL 'git reset -p HEAD^' ' +for opt in "HEAD" "@" "" +do + test_expect_success "git reset -p $opt" ' + set_and_save_state dir/foo work work && + test_write_lines n y | git reset -p $opt >output && + verify_state dir/foo work head && + verify_saved_state bar && + test_grep "Unstage" output + ' +done + +test_expect_success 'git reset -p HEAD^' ' test_write_lines n y | git reset -p HEAD^ >output && verify_state dir/foo work parent && verify_saved_state bar && test_grep "Apply" output ' -test_expect_success PERL 'git reset -p HEAD^^{tree}' ' +test_expect_success 'git reset -p HEAD^^{tree}' ' test_write_lines n y | git reset -p HEAD^^{tree} >output && verify_state dir/foo work parent && verify_saved_state bar && test_grep "Apply" output ' -test_expect_success PERL 'git reset -p HEAD^:dir/foo (blob fails)' ' +test_expect_success 'git reset -p HEAD^:dir/foo (blob fails)' ' set_and_save_state dir/foo work work && test_must_fail git reset -p HEAD^:dir/foo && verify_saved_state dir/foo && verify_saved_state bar ' -test_expect_success PERL 'git reset -p aaaaaaaa (unknown fails)' ' +test_expect_success 'git reset -p aaaaaaaa (unknown fails)' ' set_and_save_state dir/foo work work && test_must_fail git reset -p aaaaaaaa && verify_saved_state dir/foo && @@ -66,27 +70,27 @@ test_expect_success PERL 'git reset -p aaaaaaaa (unknown fails)' ' # dir/foo. There's always an extra 'n' to reject edits to dir/foo in # the failure case (and thus get out of the loop). -test_expect_success PERL 'git reset -p dir' ' +test_expect_success 'git reset -p dir' ' set_state dir/foo work work && test_write_lines y n | git reset -p dir && verify_state dir/foo work head && verify_saved_state bar ' -test_expect_success PERL 'git reset -p -- foo (inside dir)' ' +test_expect_success 'git reset -p -- foo (inside dir)' ' set_state dir/foo work work && test_write_lines y n | (cd dir && git reset -p -- foo) && verify_state dir/foo work head && verify_saved_state bar ' -test_expect_success PERL 'git reset -p HEAD^ -- dir' ' +test_expect_success 'git reset -p HEAD^ -- dir' ' test_write_lines y n | git reset -p HEAD^ -- dir && verify_state dir/foo work parent && verify_saved_state bar ' -test_expect_success PERL 'none of this moved HEAD' ' +test_expect_success 'none of this moved HEAD' ' verify_saved_head ' diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh index d20e5709f9..88d1c8adf4 100755 --- a/t/t7106-reset-unborn-branch.sh +++ b/t/t7106-reset-unborn-branch.sh @@ -34,7 +34,7 @@ test_expect_success 'reset $file' ' test_cmp expect actual ' -test_expect_success PERL 'reset -p' ' +test_expect_success 'reset -p' ' rm .git/index && git add a && echo y >yes && diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 10cc6c4605..42352dc0db 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -631,6 +631,72 @@ test_expect_success 'checkout --conflict=diff3' ' test_cmp merged file ' +test_expect_success 'checkout --conflict=diff3 --no-conflict does not merge' ' + setup_conflicting_index && + echo "none of the above" >expect && + cat expect >fild && + cat expect >file && + test_must_fail git checkout --conflict=diff3 --no-conflict -- fild file 2>err && + test_cmp expect file && + test_cmp expect fild && + echo "error: path ${SQ}file${SQ} is unmerged" >expect && + test_cmp expect err +' + +test_expect_success 'checkout --conflict=diff3 --no-merge does not merge' ' + setup_conflicting_index && + echo "none of the above" >expect && + cat expect >fild && + cat expect >file && + test_must_fail git checkout --conflict=diff3 --no-merge -- fild file 2>err && + test_cmp expect file && + test_cmp expect fild && + echo "error: path ${SQ}file${SQ} is unmerged" >expect && + test_cmp expect err +' + +test_expect_success 'checkout --no-merge --conflict=diff3 does merge' ' + setup_conflicting_index && + echo "none of the above" >fild && + echo "none of the above" >file && + git checkout --no-merge --conflict=diff3 -- fild file && + echo "ourside" >expect && + test_cmp expect fild && + cat >expect <<-\EOF && + <<<<<<< ours + ourside + ||||||| base + original + ======= + theirside + >>>>>>> theirs + EOF + test_cmp expect file +' + +test_expect_success 'checkout --merge --conflict=diff3 --no-conflict does merge' ' + setup_conflicting_index && + echo "none of the above" >fild && + echo "none of the above" >file && + git checkout --merge --conflict=diff3 --no-conflict -- fild file && + echo "ourside" >expect && + test_cmp expect fild && + cat >expect <<-\EOF && + <<<<<<< ours + ourside + ======= + theirside + >>>>>>> theirs + EOF + test_cmp expect file +' + +test_expect_success 'checkout with invalid conflict style' ' + test_must_fail git checkout --conflict=bad 2>actual -- file && + echo "error: unknown conflict style ${SQ}bad${SQ}" >expect && + test_cmp expect actual +' + test_expect_success 'failing checkout -b should not break working tree' ' git clean -fd && # Remove untracked files in the way git reset --hard main && diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 611b3dd3ae..0aae0dee67 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -5,6 +5,7 @@ test_description='git clean basic tests' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh git config clean.requireForce no @@ -407,6 +408,12 @@ test_expect_success 'clean.requireForce and -f' ' ' +test_expect_success 'clean.requireForce and --interactive' ' + git clean --interactive </dev/null >output 2>error && + test_grep ! "requireForce is true and" error && + test_grep "\*\*\* Commands \*\*\*" output +' + test_expect_success 'core.excludesfile' ' echo excludes >excludes && diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh index d82a3210a1..4afe53c66a 100755 --- a/t/t7301-clean-interactive.sh +++ b/t/t7301-clean-interactive.sh @@ -25,18 +25,18 @@ test_expect_success 'git clean -i (c: clean hotkey)' ' touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \ docs/manual.txt obj.o build/lib.so && echo c | git clean -i && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f docs/manual.txt && - test ! -f src/part3.c && - test ! -f src/part3.h && - test ! -f src/part4.c && - test ! -f src/part4.h && - 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_file docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_missing src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -46,18 +46,18 @@ test_expect_success 'git clean -i (cl: clean prefix)' ' touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \ docs/manual.txt obj.o build/lib.so && echo cl | git clean -i && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f docs/manual.txt && - test ! -f src/part3.c && - test ! -f src/part3.h && - test ! -f src/part4.c && - test ! -f src/part4.h && - 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_file docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_missing src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -67,18 +67,18 @@ test_expect_success 'git clean -i (quit)' ' touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \ docs/manual.txt obj.o build/lib.so && echo quit | git clean -i && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f docs/manual.txt && - test -f src/part3.c && - test -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_file src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -88,18 +88,18 @@ test_expect_success 'git clean -i (Ctrl+D)' ' touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \ docs/manual.txt obj.o build/lib.so && echo "\04" | git clean -i && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f docs/manual.txt && - test -f src/part3.c && - test -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_file src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -110,18 +110,18 @@ test_expect_success 'git clean -id (filter all)' ' docs/manual.txt obj.o build/lib.so && test_write_lines f "*" "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f docs/manual.txt && - test -f src/part3.c && - test -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_file src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -132,18 +132,18 @@ test_expect_success 'git clean -id (filter patterns)' ' docs/manual.txt obj.o build/lib.so && test_write_lines f "part3.* *.out" "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f docs/manual.txt && - test -f src/part3.c && - test -f src/part3.h && - test ! -f src/part4.c && - test ! -f src/part4.h && - 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 docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_file src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_missing src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -154,18 +154,18 @@ test_expect_success 'git clean -id (filter patterns 2)' ' docs/manual.txt obj.o build/lib.so && test_write_lines f "* !*.out" "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f docs/manual.txt && - test -f src/part3.c && - test -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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_file docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_file src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -176,18 +176,18 @@ test_expect_success 'git clean -id (select - all)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s "*" "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f docs/manual.txt && - test ! -f src/part3.c && - test ! -f src/part3.h && - test ! -f src/part4.c && - test ! -f src/part4.h && - 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 docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_missing src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -198,18 +198,18 @@ test_expect_success 'git clean -id (select - none)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f docs/manual.txt && - test -f src/part3.c && - test -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_file src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -220,18 +220,18 @@ test_expect_success 'git clean -id (select - number)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s 3 "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f docs/manual.txt && - test ! -f src/part3.c && - test -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_file src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -242,18 +242,18 @@ test_expect_success 'git clean -id (select - number 2)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s "2 3" 5 "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f docs/manual.txt && - test ! -f src/part3.c && - test -f src/part3.h && - test ! -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_file src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -264,18 +264,18 @@ test_expect_success 'git clean -id (select - number 3)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s "3,4 5" "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test -f docs/manual.txt && - test ! -f src/part3.c && - test ! -f src/part3.h && - test ! -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -285,11 +285,11 @@ test_expect_success 'git clean -id (select - filenames)' ' touch a.out foo.txt bar.txt baz.txt && test_write_lines s "a.out fo ba bar" "" c | git clean -id && - test -f Makefile && - test ! -f a.out && - test ! -f foo.txt && - test ! -f bar.txt && - test -f baz.txt && + test_path_is_file Makefile && + test_path_is_missing a.out && + test_path_is_missing foo.txt && + test_path_is_missing bar.txt && + test_path_is_file baz.txt && rm baz.txt ' @@ -301,18 +301,18 @@ test_expect_success 'git clean -id (select - range)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s "1,3-4" 2 "" c | git clean -id && - 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/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_missing docs/manual.txt && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -323,18 +323,18 @@ test_expect_success 'git clean -id (select - range 2)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s "4- 1" "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f docs/manual.txt && - test -f src/part3.c && - test ! -f src/part3.h && - test ! -f src/part4.c && - test ! -f src/part4.h && - 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_file docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_missing src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -345,18 +345,18 @@ test_expect_success 'git clean -id (inverse select)' ' docs/manual.txt obj.o build/lib.so && test_write_lines s "*" "-5- 1 -2" "" c | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f docs/manual.txt && - test ! -f src/part3.c && - test ! -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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_file docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -367,18 +367,18 @@ test_expect_success 'git clean -id (ask)' ' docs/manual.txt obj.o build/lib.so && test_write_lines a Y y no yes bad "" | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f docs/manual.txt && - test -f src/part3.c && - test ! -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -389,18 +389,18 @@ test_expect_success 'git clean -id (ask - Ctrl+D)' ' docs/manual.txt obj.o build/lib.so && test_write_lines a Y no yes "\04" | git clean -id && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f docs/manual.txt && - test ! -f src/part3.c && - test -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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_file docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_file src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -412,18 +412,18 @@ test_expect_success 'git clean -id with prefix and path (filter)' ' (cd build/ && test_write_lines f docs "*.h" "" c | git clean -id ..) && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test -f docs/manual.txt && - test ! -f src/part3.c && - test -f src/part3.h && - test ! -f src/part4.c && - test -f src/part4.h && - 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_file docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_file src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -435,18 +435,18 @@ test_expect_success 'git clean -id with prefix and path (select by name)' ' (cd build/ && test_write_lines s ../docs/ ../src/part3.c ../src/part4.c "" c | git clean -id ..) && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test -f a.out && - test ! -f docs/manual.txt && - test ! -f src/part3.c && - test -f src/part3.h && - test ! -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_missing src/part3.c && + test_path_is_file src/part3.h && + test_path_is_missing src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' @@ -458,18 +458,18 @@ test_expect_success 'git clean -id with prefix and path (ask)' ' (cd build/ && test_write_lines a Y y no yes bad "" | git clean -id ..) && - test -f Makefile && - test -f README && - test -f src/part1.c && - test -f src/part2.c && - test ! -f a.out && - test ! -f docs/manual.txt && - test -f src/part3.c && - test ! -f src/part3.h && - test -f src/part4.c && - test -f src/part4.h && - 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 docs/manual.txt && + test_path_is_file src/part3.c && + test_path_is_missing src/part3.h && + test_path_is_file src/part4.c && + test_path_is_file src/part4.h && + test_path_is_file obj.o && + test_path_is_file build/lib.so ' diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 00c1f1aab1..5c4a89df5c 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -212,8 +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: Turn this message off by running - hint: "git config advice.addIgnoredFile false" + hint: Disable this message with "git config advice.addIgnoredFile false" EOF # Does not use test_commit due to the ignore echo "*" > .gitignore && diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh index 2b3c363078..aa2fdc31d1 100755 --- a/t/t7402-submodule-rebase.sh +++ b/t/t7402-submodule-rebase.sh @@ -116,7 +116,7 @@ test_expect_success 'rebasing submodule that should conflict' ' test_tick && git commit -m fourth && - test_must_fail git rebase --onto HEAD^^ HEAD^ HEAD^0 >actual_output && + test_must_fail git rebase --onto HEAD^^ HEAD^ HEAD^0 2>actual_output && git ls-files -s submodule >actual && ( cd submodule && diff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh index bced44a0fc..cc12f99f11 100755 --- a/t/t7501-commit-basic-functionality.sh +++ b/t/t7501-commit-basic-functionality.sh @@ -101,22 +101,8 @@ test_expect_success 'fail to commit untracked file (even with --include/--only)' test_must_fail git commit --only -m "baz" baz 2>err && test_grep -e "$error" err && - # TODO: as for --include, the below command will fail because - # nothing is staged. If something was staged, it would not fail - # even though the provided pathspec does not match any tracked - # path. (However, the untracked paths that match the pathspec are - # not committed and only the staged changes get committed.) - # In either cases, no error is returned to stderr like in (--only - # and without --only/--include) cases. In a similar manner, - # "git add -u baz" also does not error out. - # - # Therefore, the below test is just to document the current behavior - # and is not an endorsement to the current behavior, and we may - # want to fix this. And when that happens, this test should be - # updated accordingly. - test_must_fail git commit --include -m "baz" baz 2>err && - test_must_be_empty err + test_grep -e "$error" err ' test_expect_success 'setup: non-initial commit' ' diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh index a87c211d0b..b37e2018a7 100755 --- a/t/t7502-commit-porcelain.sh +++ b/t/t7502-commit-porcelain.sh @@ -736,6 +736,11 @@ test_expect_success 'message shows date when it is explicitly set' ' .git/COMMIT_EDITMSG ' +test_expect_success 'message does not have multiple scissors lines' ' + git commit --cleanup=scissors -v --allow-empty -e -m foo && + test $(grep -c -e "--- >8 ---" .git/COMMIT_EDITMSG) -eq 1 +' + test_expect_success AUTOIDENT 'message shows committer when it is automatic' ' echo >>negative && diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh index c3281b192e..4c7db19ce7 100755 --- a/t/t7507-commit-verbose.sh +++ b/t/t7507-commit-verbose.sh @@ -101,6 +101,16 @@ test_expect_success 'verbose diff is stripped out with set core.commentChar' ' test_grep "Aborting commit due to empty commit message." err ' +test_expect_success 'verbose diff is stripped with multi-byte comment char' ' + ( + GIT_EDITOR=cat && + export GIT_EDITOR && + test_must_fail git -c core.commentchar="foo>" commit -a -v >out 2>err + ) && + grep "^foo> " out && + test_grep "Aborting commit due to empty commit message." err +' + test_expect_success 'status does not verbose without --verbose' ' git status >actual && ! grep "^diff --git" actual diff --git a/t/t7508-status.sh b/t/t7508-status.sh index a3c18a4fc2..773383fefb 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -419,14 +419,19 @@ Changes not staged for commit: Untracked files not listed (use -u option to show untracked files) EOF git status -uno >output && + test_cmp expect output && + git status -ufalse >output && test_cmp expect output ' -test_expect_success 'status (status.showUntrackedFiles no)' ' - test_config status.showuntrackedfiles no && - git status >output && - test_cmp expect output -' +for no in no false 0 +do + test_expect_success "status (status.showUntrackedFiles $no)" ' + test_config status.showuntrackedfiles "$no" && + git status >output && + test_cmp expect output + ' +done test_expect_success 'status -uno (advice.statusHints false)' ' cat >expect <<EOF && @@ -488,14 +493,21 @@ Untracked files: EOF git status -unormal >output && + test_cmp expect output && + git status -utrue >output && + test_cmp expect output && + git status -uyes >output && test_cmp expect output ' -test_expect_success 'status (status.showUntrackedFiles normal)' ' - test_config status.showuntrackedfiles normal && - git status >output && - test_cmp expect output -' +for normal in normal true 1 +do + test_expect_success "status (status.showUntrackedFiles $normal)" ' + test_config status.showuntrackedfiles $normal && + git status >output && + test_cmp expect output + ' +done cat >expect <<EOF M dir1/modified @@ -1403,7 +1415,9 @@ test_expect_success "status (core.commentchar with submodule summary)" ' test_expect_success "status (core.commentchar with two chars with submodule summary)" ' test_config core.commentchar ";;" && - test_must_fail git -c status.displayCommentPrefix=true status + sed "s/^/;/" <expect >expect.double && + git -c status.displayCommentPrefix=true status >output && + test_cmp expect.double output ' test_expect_success "--ignore-submodules=all suppresses submodule summary" ' diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh index ec9c6de114..3d3e13ccf8 100755 --- a/t/t7513-interpret-trailers.sh +++ b/t/t7513-interpret-trailers.sh @@ -1935,4 +1935,18 @@ test_expect_success 'suppressing --- does not disable cut-line handling' ' test_cmp expected actual ' +test_expect_success 'handling of --- lines in conjunction with cut-lines' ' + echo "my-trailer: here" >expected && + + git interpret-trailers --parse >actual <<-\EOF && + subject + + my-trailer: here + --- + # ------------------------ >8 ------------------------ + EOF + + test_cmp expected actual +' + test_done diff --git a/t/t7514-commit-patch.sh b/t/t7514-commit-patch.sh index 998a2103c7..03ba0c0e73 100755 --- a/t/t7514-commit-patch.sh +++ b/t/t7514-commit-patch.sh @@ -1,13 +1,9 @@ #!/bin/sh test_description='hunk edit with "commit -p -m"' -. ./test-lib.sh -if ! test_have_prereq PERL -then - skip_all="skipping '$test_description' tests, perl not available" - test_done -fi +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh test_expect_success 'setup (initial)' ' echo line1 >file && diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index 363f9dc0e4..730f3c7f81 100755 --- a/t/t7527-builtin-fsmonitor.sh +++ b/t/t7527-builtin-fsmonitor.sh @@ -1037,4 +1037,227 @@ test_expect_success 'split-index and FSMonitor work well together' ' ) ' +# The FSMonitor daemon reports the OBSERVED pathname of modified files +# and thus contains the OBSERVED spelling on case-insensitive file +# systems. The daemon does not (and should not) load the .git/index +# file and therefore does not know the expected case-spelling. Since +# it is possible for the user to create files/subdirectories with the +# incorrect case, a modified file event for a tracked will not have +# the EXPECTED case. This can cause `index_name_pos()` to incorrectly +# report that the file is untracked. This causes the client to fail to +# mark the file as possibly dirty (keeping the CE_FSMONITOR_VALID bit +# set) so that `git status` will avoid inspecting it and thus not +# present in the status output. +# +# The setup is a little contrived. +# +test_expect_success CASE_INSENSITIVE_FS 'fsmonitor subdir case wrong on disk' ' + test_when_finished "stop_daemon_delete_repo subdir_case_wrong" && + + git init subdir_case_wrong && + ( + cd subdir_case_wrong && + echo x >AAA && + echo x >BBB && + + mkdir dir1 && + echo x >dir1/file1 && + mkdir dir1/dir2 && + echo x >dir1/dir2/file2 && + mkdir dir1/dir2/dir3 && + echo x >dir1/dir2/dir3/file3 && + + echo x >yyy && + echo x >zzz && + git add . && + git commit -m "data" && + + # This will cause "dir1/" and everything under it + # to be deleted. + git sparse-checkout set --cone --sparse-index && + + # Create dir2 with the wrong case and then let Git + # repopulate dir3 -- it will not correct the spelling + # of dir2. + mkdir dir1 && + mkdir dir1/DIR2 && + git sparse-checkout add dir1/dir2/dir3 + ) && + + start_daemon -C subdir_case_wrong --tf "$PWD/subdir_case_wrong.trace" && + + # Enable FSMonitor in the client. Run enough commands for + # the .git/index to sync up with the daemon with everything + # marked clean. + git -C subdir_case_wrong config core.fsmonitor true && + git -C subdir_case_wrong update-index --fsmonitor && + git -C subdir_case_wrong status && + + # Make some files dirty so that FSMonitor gets FSEvents for + # each of them. + echo xx >>subdir_case_wrong/AAA && + echo xx >>subdir_case_wrong/dir1/DIR2/dir3/file3 && + echo xx >>subdir_case_wrong/zzz && + + GIT_TRACE_FSMONITOR="$PWD/subdir_case_wrong.log" \ + git -C subdir_case_wrong --no-optional-locks status --short \ + >"$PWD/subdir_case_wrong.out" && + + # "git status" should have gotten file events for each of + # the 3 files. + # + # "dir2" should be in the observed case on disk. + grep "fsmonitor_refresh_callback" \ + <"$PWD/subdir_case_wrong.log" \ + >"$PWD/subdir_case_wrong.log1" && + + grep -q "AAA.*pos 0" "$PWD/subdir_case_wrong.log1" && + grep -q "zzz.*pos 6" "$PWD/subdir_case_wrong.log1" && + + grep -q "dir1/DIR2/dir3/file3.*pos -3" "$PWD/subdir_case_wrong.log1" && + + # Verify that we get a mapping event to correct the case. + grep -q "MAP:.*dir1/DIR2/dir3/file3.*dir1/dir2/dir3/file3" \ + "$PWD/subdir_case_wrong.log1" && + + # The refresh-callbacks should have caused "git status" to clear + # the CE_FSMONITOR_VALID bit on each of those files and caused + # the worktree scan to visit them and mark them as modified. + grep -q " M AAA" "$PWD/subdir_case_wrong.out" && + grep -q " M zzz" "$PWD/subdir_case_wrong.out" && + grep -q " M dir1/dir2/dir3/file3" "$PWD/subdir_case_wrong.out" +' + +test_expect_success CASE_INSENSITIVE_FS 'fsmonitor file case wrong on disk' ' + test_when_finished "stop_daemon_delete_repo file_case_wrong" && + + git init file_case_wrong && + ( + cd file_case_wrong && + echo x >AAA && + echo x >BBB && + + mkdir dir1 && + mkdir dir1/dir2 && + mkdir dir1/dir2/dir3 && + echo x >dir1/dir2/dir3/FILE-3-B && + echo x >dir1/dir2/dir3/XXXX-3-X && + echo x >dir1/dir2/dir3/file-3-a && + echo x >dir1/dir2/dir3/yyyy-3-y && + mkdir dir1/dir2/dir4 && + echo x >dir1/dir2/dir4/FILE-4-A && + echo x >dir1/dir2/dir4/XXXX-4-X && + echo x >dir1/dir2/dir4/file-4-b && + echo x >dir1/dir2/dir4/yyyy-4-y && + + echo x >yyy && + echo x >zzz && + git add . && + git commit -m "data" + ) && + + start_daemon -C file_case_wrong --tf "$PWD/file_case_wrong.trace" && + + # Enable FSMonitor in the client. Run enough commands for + # the .git/index to sync up with the daemon with everything + # marked clean. + git -C file_case_wrong config core.fsmonitor true && + git -C file_case_wrong update-index --fsmonitor && + git -C file_case_wrong status && + + # Make some files dirty so that FSMonitor gets FSEvents for + # each of them. + echo xx >>file_case_wrong/AAA && + echo xx >>file_case_wrong/zzz && + + # Rename some files so that FSMonitor sees a create and delete + # FSEvent for each. (A simple "mv foo FOO" is not portable + # between macOS and Windows. It works on both platforms, but makes + # the test messy, since (1) one platform updates "ctime" on the + # moved file and one does not and (2) it causes a directory event + # on one platform and not on the other which causes additional + # scanning during "git status" which causes a "H" vs "h" discrepancy + # in "git ls-files -f".) So old-school it and move it out of the + # way and copy it to the case-incorrect name so that we get fresh + # "ctime" and "mtime" values. + + mv file_case_wrong/dir1/dir2/dir3/file-3-a file_case_wrong/dir1/dir2/dir3/ORIG && + cp file_case_wrong/dir1/dir2/dir3/ORIG file_case_wrong/dir1/dir2/dir3/FILE-3-A && + rm file_case_wrong/dir1/dir2/dir3/ORIG && + mv file_case_wrong/dir1/dir2/dir4/FILE-4-A file_case_wrong/dir1/dir2/dir4/ORIG && + cp file_case_wrong/dir1/dir2/dir4/ORIG file_case_wrong/dir1/dir2/dir4/file-4-a && + rm file_case_wrong/dir1/dir2/dir4/ORIG && + + # Run status enough times to fully sync. + # + # The first instance should get the create and delete FSEvents + # for each pair. Status should update the index with a new FSM + # token (so the next invocation will not see data for these + # events). + + GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try1.log" \ + git -C file_case_wrong status --short \ + >"$PWD/file_case_wrong-try1.out" && + grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos -3" "$PWD/file_case_wrong-try1.log" && + grep -q "fsmonitor_refresh_callback.*file-3-a.*pos 4" "$PWD/file_case_wrong-try1.log" && + grep -q "fsmonitor_refresh_callback.*FILE-4-A.*pos 6" "$PWD/file_case_wrong-try1.log" && + grep -q "fsmonitor_refresh_callback.*file-4-a.*pos -9" "$PWD/file_case_wrong-try1.log" && + + # FSM refresh will have invalidated the FSM bit and cause a regular + # (real) scan of these tracked files, so they should have "H" status. + # (We will not see a "h" status until the next refresh (on the next + # command).) + + git -C file_case_wrong ls-files -f >"$PWD/file_case_wrong-lsf1.out" && + grep -q "H dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-lsf1.out" && + grep -q "H dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-lsf1.out" && + + + # Try the status again. We assume that the above status command + # advanced the token so that the next one will not see those events. + + GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try2.log" \ + git -C file_case_wrong status --short \ + >"$PWD/file_case_wrong-try2.out" && + ! grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos" "$PWD/file_case_wrong-try2.log" && + ! grep -q "fsmonitor_refresh_callback.*file-3-a.*pos" "$PWD/file_case_wrong-try2.log" && + ! grep -q "fsmonitor_refresh_callback.*FILE-4-A.*pos" "$PWD/file_case_wrong-try2.log" && + ! grep -q "fsmonitor_refresh_callback.*file-4-a.*pos" "$PWD/file_case_wrong-try2.log" && + + # FSM refresh saw nothing, so it will mark all files as valid, + # so they should now have "h" status. + + git -C file_case_wrong ls-files -f >"$PWD/file_case_wrong-lsf2.out" && + grep -q "h dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-lsf2.out" && + grep -q "h dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-lsf2.out" && + + + # We now have files with clean content, but with case-incorrect + # file names. Modify them to see if status properly reports + # them. + + echo xx >>file_case_wrong/dir1/dir2/dir3/FILE-3-A && + echo xx >>file_case_wrong/dir1/dir2/dir4/file-4-a && + + GIT_TRACE_FSMONITOR="$PWD/file_case_wrong-try3.log" \ + git -C file_case_wrong --no-optional-locks status --short \ + >"$PWD/file_case_wrong-try3.out" && + + # Verify that we get a mapping event to correct the case. + grep -q "fsmonitor_refresh_callback MAP:.*dir1/dir2/dir3/FILE-3-A.*dir1/dir2/dir3/file-3-a" \ + "$PWD/file_case_wrong-try3.log" && + grep -q "fsmonitor_refresh_callback MAP:.*dir1/dir2/dir4/file-4-a.*dir1/dir2/dir4/FILE-4-A" \ + "$PWD/file_case_wrong-try3.log" && + + # FSEvents are in observed case. + grep -q "fsmonitor_refresh_callback.*FILE-3-A.*pos -3" "$PWD/file_case_wrong-try3.log" && + grep -q "fsmonitor_refresh_callback.*file-4-a.*pos -9" "$PWD/file_case_wrong-try3.log" && + + # The refresh-callbacks should have caused "git status" to clear + # the CE_FSMONITOR_VALID bit on each of those files and caused + # the worktree scan to visit them and mark them as modified. + grep -q " M dir1/dir2/dir3/file-3-a" "$PWD/file_case_wrong-try3.out" && + grep -q " M dir1/dir2/dir4/FILE-4-A" "$PWD/file_case_wrong-try3.out" +' + test_done diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 94f9f4a1da..127efe99f8 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -629,6 +629,7 @@ 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 && @@ -749,6 +750,7 @@ 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/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh index be3735dff0..71e1ef3a10 100755 --- a/t/t7704-repack-cruft.sh +++ b/t/t7704-repack-cruft.sh @@ -48,7 +48,7 @@ test_expect_success '--expire-to stores pruned objects (now)' ' # ...in other words, the combined contents of this # repository and expired.git should be the same as the # set of objects we started with. - cat expired.objects remaining.objects | sort >actual && + sort expired.objects remaining.objects >actual && test_cmp expect actual && # The "moved" objects (i.e., those in expired.git) diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 6a36be1e63..cc917b257e 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -91,58 +91,67 @@ test_expect_success 'difftool forwards arguments to diff' ' rm for-diff ' -test_expect_success 'difftool ignores exit code' ' - test_config difftool.error.cmd false && - git difftool -y -t error branch -' - -test_expect_success 'difftool forwards exit code with --trust-exit-code' ' - test_config difftool.error.cmd false && - test_must_fail git difftool -y --trust-exit-code -t error branch -' - -test_expect_success 'difftool forwards exit code with --trust-exit-code for built-ins' ' - test_config difftool.vimdiff.path false && - test_must_fail git difftool -y --trust-exit-code -t vimdiff branch -' - -test_expect_success 'difftool honors difftool.trustExitCode = true' ' - test_config difftool.error.cmd false && - test_config difftool.trustExitCode true && - test_must_fail git difftool -y -t error branch -' - -test_expect_success 'difftool honors difftool.trustExitCode = false' ' - test_config difftool.error.cmd false && - test_config difftool.trustExitCode false && - git difftool -y -t error branch -' - -test_expect_success 'difftool ignores exit code with --no-trust-exit-code' ' - test_config difftool.error.cmd false && - test_config difftool.trustExitCode true && - git difftool -y --no-trust-exit-code -t error branch -' - -test_expect_success 'difftool stops on error with --trust-exit-code' ' - test_when_finished "rm -f for-diff .git/fail-right-file" && - test_when_finished "git reset -- for-diff" && - write_script .git/fail-right-file <<-\EOF && - echo failed - exit 1 - EOF - >for-diff && - git add for-diff && - test_must_fail git difftool -y --trust-exit-code \ - --extcmd .git/fail-right-file branch >actual && - test_line_count = 1 actual -' - -test_expect_success 'difftool honors exit status if command not found' ' - test_config difftool.nonexistent.cmd i-dont-exist && - test_config difftool.trustExitCode false && - test_must_fail git difftool -y -t nonexistent branch -' +for opt in '' '--dir-diff' +do + test_expect_success "difftool ${opt:-without options} ignores exit code" ' + test_config difftool.error.cmd false && + git difftool ${opt} -y -t error branch + ' + + test_expect_success "difftool ${opt:-without options} forwards exit code with --trust-exit-code" ' + test_config difftool.error.cmd false && + test_must_fail git difftool ${opt} -y --trust-exit-code -t error branch + ' + + test_expect_success "difftool ${opt:-without options} forwards exit code with --trust-exit-code for built-ins" ' + test_config difftool.vimdiff.path false && + test_must_fail git difftool ${opt} -y --trust-exit-code -t vimdiff branch + ' + + test_expect_success "difftool ${opt:-without options} honors difftool.trustExitCode = true" ' + test_config difftool.error.cmd false && + test_config difftool.trustExitCode true && + test_must_fail git difftool ${opt} -y -t error branch + ' + + test_expect_success "difftool ${opt:-without options} honors difftool.trustExitCode = false" ' + test_config difftool.error.cmd false && + test_config difftool.trustExitCode false && + git difftool ${opt} -y -t error branch + ' + + test_expect_success "difftool ${opt:-without options} ignores exit code with --no-trust-exit-code" ' + test_config difftool.error.cmd false && + test_config difftool.trustExitCode true && + git difftool ${opt} -y --no-trust-exit-code -t error branch + ' + + test_expect_success "difftool ${opt:-without options} stops on error with --trust-exit-code" ' + test_when_finished "rm -f for-diff .git/fail-right-file" && + test_when_finished "git reset -- for-diff" && + write_script .git/fail-right-file <<-\EOF && + echo failed + exit 1 + EOF + >for-diff && + git add for-diff && + test_must_fail git difftool ${opt} -y --trust-exit-code \ + --extcmd .git/fail-right-file branch >actual && + test_line_count = 1 actual + ' + + test_expect_success "difftool ${opt:-without options} honors exit status if command not found" ' + test_config difftool.nonexistent.cmd i-dont-exist && + test_config difftool.trustExitCode false && + if test "${opt}" = --dir-diff + then + expected_code=127 + else + expected_code=128 + fi && + test_expect_code ${expected_code} git difftool ${opt} -y -t nonexistent branch + ' +done test_expect_success 'difftool honors --gui' ' difftool_test_setup && diff --git a/t/t8010-cat-file-filters.sh b/t/t8010-cat-file-filters.sh index ca04242ca0..eb64b766bd 100755 --- a/t/t8010-cat-file-filters.sh +++ b/t/t8010-cat-file-filters.sh @@ -43,7 +43,7 @@ test_expect_success 'cat-file --textconv --path=<path> works' ' sha1=$(git rev-parse -q --verify HEAD:world.txt) && test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" && git cat-file --textconv --path=hello.txt $sha1 >rot13 && - test uryyb = "$(cat rot13 | remove_cr)" + test uryyb = "$(remove_cr <rot13)" ' test_expect_success '--path=<path> complains without --textconv/--filters' ' diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh index 9a03b0f361..dbfbd86e83 100755 --- a/t/t8013-blame-ignore-revs.sh +++ b/t/t8013-blame-ignore-revs.sh @@ -25,11 +25,11 @@ test_expect_success setup ' git blame --line-porcelain file >blame_raw && - grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 1/s/ .*//p" blame_raw >actual && git rev-parse X >expect && test_cmp expect actual && - grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 2/s/ .*//p" blame_raw >actual && git rev-parse X >expect && test_cmp expect actual ' @@ -53,11 +53,11 @@ do test_expect_success "ignore_rev_changing_lines ($I)" ' git blame --line-porcelain --ignore-rev $I file >blame_raw && - grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 1/s/ .*//p" blame_raw >actual && git rev-parse A >expect && test_cmp expect actual && - grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 2/s/ .*//p" blame_raw >actual && git rev-parse B >expect && test_cmp expect actual ' @@ -79,10 +79,10 @@ test_expect_success ignore_rev_adding_unblamable_lines ' git rev-parse Y >expect && git blame --line-porcelain file --ignore-rev Y >blame_raw && - grep -E "^[0-9a-f]+ [0-9]+ 3" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 3/s/ .*//p" blame_raw >actual && test_cmp expect actual && - grep -E "^[0-9a-f]+ [0-9]+ 4" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 4/s/ .*//p" blame_raw >actual && test_cmp expect actual ' @@ -92,11 +92,11 @@ test_expect_success ignore_revs_from_files ' git rev-parse Y >ignore_y && git blame --line-porcelain file --ignore-revs-file ignore_x --ignore-revs-file ignore_y >blame_raw && - grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 1/s/ .*//p" blame_raw >actual && git rev-parse A >expect && test_cmp expect actual && - grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 2/s/ .*//p" blame_raw >actual && git rev-parse B >expect && test_cmp expect actual ' @@ -106,11 +106,11 @@ test_expect_success ignore_revs_from_configs_and_files ' git config --add blame.ignoreRevsFile ignore_x && git blame --line-porcelain file --ignore-revs-file ignore_y >blame_raw && - grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 1/s/ .*//p" blame_raw >actual && git rev-parse A >expect && test_cmp expect actual && - grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 2/s/ .*//p" blame_raw >actual && git rev-parse B >expect && test_cmp expect actual ' @@ -121,10 +121,10 @@ test_expect_success override_ignore_revs_file ' git blame --line-porcelain file --ignore-revs-file "" --ignore-revs-file ignore_y >blame_raw && git rev-parse X >expect && - grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 1/s/ .*//p" blame_raw >actual && test_cmp expect actual && - grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 2/s/ .*//p" blame_raw >actual && test_cmp expect actual ' test_expect_success bad_files_and_revs ' @@ -279,11 +279,11 @@ test_expect_success ignore_merge ' test_merge M B && git blame --line-porcelain file --ignore-rev M >blame_raw && - grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 1/s/ .*//p" blame_raw >actual && git rev-parse B >expect && test_cmp expect actual && - grep -E "^[0-9a-f]+ [0-9]+ 9" blame_raw | sed -e "s/ .*//" >actual && + sed -ne "/^[0-9a-f][0-9a-f]* [0-9][0-9]* 9/s/ .*//p" blame_raw >actual && git rev-parse C >expect && test_cmp expect actual ' diff --git a/t/t9002-column.sh b/t/t9002-column.sh index 348cc40658..d5b98e615b 100755 --- a/t/t9002-column.sh +++ b/t/t9002-column.sh @@ -196,4 +196,15 @@ EOF test_cmp expected actual ' +test_expect_success 'padding must be non-negative' ' + cat >input <<\EOF && +1 2 3 4 5 6 +EOF + cat >expected <<\EOF && +fatal: --padding must be non-negative +EOF + test_must_fail git column --mode=column --padding=-1 <input >actual 2>&1 && + test_cmp expected actual +' + test_done diff --git a/t/t9117-git-svn-init-clone.sh b/t/t9117-git-svn-init-clone.sh index 62de819a44..3b038c338f 100755 --- a/t/t9117-git-svn-init-clone.sh +++ b/t/t9117-git-svn-init-clone.sh @@ -17,32 +17,32 @@ test_expect_success 'setup svnrepo' ' test_expect_success 'basic clone' ' test ! -d trunk && git svn clone "$svnrepo"/project/trunk && - test -d trunk/.git/svn && - test -e trunk/foo && + test_path_is_dir trunk/.git/svn && + test_path_exists trunk/foo && rm -rf trunk ' test_expect_success 'clone to target directory' ' test ! -d target && git svn clone "$svnrepo"/project/trunk target && - test -d target/.git/svn && - test -e target/foo && + test_path_is_dir target/.git/svn && + test_path_exists target/foo && rm -rf target ' test_expect_success 'clone with --stdlayout' ' test ! -d project && git svn clone -s "$svnrepo"/project && - test -d project/.git/svn && - test -e project/foo && + test_path_is_dir project/.git/svn && + test_path_exists project/foo && rm -rf project ' test_expect_success 'clone to target directory with --stdlayout' ' test ! -d target && git svn clone -s "$svnrepo"/project target && - test -d target/.git/svn && - test -e target/foo && + test_path_is_dir target/.git/svn && + test_path_exists target/foo && rm -rf target ' diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh index a159ff96b7..d3261e35b8 100755 --- a/t/t9118-git-svn-funky-branch-names.sh +++ b/t/t9118-git-svn-funky-branch-names.sh @@ -38,7 +38,7 @@ test_expect_success 'setup svnrepo' ' # SVN 1.7 will truncate "not-a%40{0]" to just "not-a". # Look at what SVN wound up naming the branch and use that. # Be sure to escape the @ if it shows up. -non_reflog=$(svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/') +non_reflog=$(svn_cmd ls "$svnrepo/pr ject/branches" | sed -ne '/not-a/ { s/\///; s/@/%40/; p }') test_expect_success 'test clone with funky branch names' ' git svn clone -s "$svnrepo/pr ject" project && diff --git a/t/t9146-git-svn-empty-dirs.sh b/t/t9146-git-svn-empty-dirs.sh index 09606f1b3c..926ac81439 100755 --- a/t/t9146-git-svn-empty-dirs.sh +++ b/t/t9146-git-svn-empty-dirs.sh @@ -20,11 +20,7 @@ test_expect_success 'empty directories exist' ' cd cloned && for i in a b c d d/e d/e/f "weird file name" do - if ! test -d "$i" - then - echo >&2 "$i does not exist" && - exit 1 - fi + test_path_is_dir "$i" || exit 1 done ) ' @@ -37,11 +33,7 @@ test_expect_success 'option automkdirs set to false' ' git svn fetch && for i in a b c d d/e d/e/f "weird file name" do - if test -d "$i" - then - echo >&2 "$i exists" && - exit 1 - fi + test_path_is_missing "$i" || exit 1 done ) ' @@ -52,7 +44,7 @@ test_expect_success 'more emptiness' ' test_expect_success 'git svn rebase creates empty directory' ' ( cd cloned && git svn rebase ) && - test -d cloned/"! !" + test_path_is_dir cloned/"! !" ' test_expect_success 'git svn mkdirs recreates empty directories' ' @@ -62,11 +54,7 @@ test_expect_success 'git svn mkdirs recreates empty directories' ' git svn mkdirs && for i in a b c d d/e d/e/f "weird file name" "! !" do - if ! test -d "$i" - then - echo >&2 "$i does not exist" && - exit 1 - fi + test_path_is_dir "$i" || exit 1 done ) ' @@ -78,25 +66,13 @@ test_expect_success 'git svn mkdirs -r works' ' git svn mkdirs -r7 && for i in a b c d d/e d/e/f "weird file name" do - if ! test -d "$i" - then - echo >&2 "$i does not exist" && - exit 1 - fi + test_path_is_dir "$i" || exit 1 done && - if test -d "! !" - then - echo >&2 "$i should not exist" && - exit 1 - fi && + test_path_is_missing "! !" || exit 1 && git svn mkdirs -r8 && - if ! test -d "! !" - then - echo >&2 "$i not exist" && - exit 1 - fi + test_path_is_dir "! !" || exit 1 ) ' @@ -114,11 +90,7 @@ test_expect_success 'empty directories in trunk exist' ' cd trunk && for i in a "weird file name" do - if ! test -d "$i" - then - echo >&2 "$i does not exist" && - exit 1 - fi + test_path_is_dir "$i" || exit 1 done ) ' @@ -129,7 +101,7 @@ test_expect_success 'remove a top-level directory from svn' ' test_expect_success 'removed top-level directory does not exist' ' git svn clone "$svnrepo" removed && - test ! -e removed/d + test_path_is_missing removed/d ' unhandled=.git/svn/refs/remotes/git-svn/unhandled.log @@ -143,15 +115,11 @@ test_expect_success 'git svn gc-ed files work' ' svn_cmd mkdir -m gz "$svnrepo"/gz && git reset --hard $(git rev-list HEAD | tail -1) && git svn rebase && - test -f "$unhandled".gz && - test -f "$unhandled" && + test_path_is_file "$unhandled".gz && + test_path_is_file "$unhandled" && for i in a b c "weird file name" gz "! !" do - if ! test -d "$i" - then - echo >&2 "$i does not exist" && - exit 1 - fi + test_path_is_dir "$i" || exit 1 done fi ) diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index 4432a30d10..428339e342 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -154,7 +154,14 @@ test_expect_success 'scalar clone' ' test_cmp expect actual && test_path_is_missing 1/2 && - test_must_fail git rev-list --missing=print $second && + + # This relies on the fact that the presence of "--missing" + # on the command line forces lazy fetching off before + # "$second^{blob}" gets parsed. Without "^{blob}", a + # bare object name "$second" is taken into the queue and + # the command may not fail with a fixed "rev-list --missing". + test_must_fail git rev-list --missing=print "$second^{blob}" -- && + git rev-list $second && git cat-file blob $second >actual && echo "second" >expect && diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index dbb5042b0b..1e68426852 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -986,7 +986,7 @@ test_expect_success 'L: nested tree copy does not corrupt deltas' ' test_when_finished "git update-ref -d refs/heads/L2" && git fast-import <input && git ls-tree L2 g/b/ >tmp && - cat tmp | cut -f 2 >actual && + cut -f 2 <tmp >actual && test_cmp expect actual && git fsck $(git rev-parse L2) ' @@ -1059,30 +1059,33 @@ test_expect_success 'M: rename subdirectory to new subdirectory' ' compare_diff_raw expect actual ' -test_expect_success 'M: rename root to subdirectory' ' - cat >input <<-INPUT_END && - commit refs/heads/M4 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - rename root - COMMIT +for root in '""' '' +do + test_expect_success "M: rename root ($root) to subdirectory" ' + cat >input <<-INPUT_END && + commit refs/heads/M4 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + rename root + COMMIT - from refs/heads/M2^0 - R "" sub + from refs/heads/M2^0 + R $root sub - INPUT_END + INPUT_END - cat >expect <<-EOF && - :100644 100644 $oldf $oldf R100 file2/oldf sub/file2/oldf - :100755 100755 $f4id $f4id R100 file4 sub/file4 - :100755 100755 $newf $newf R100 i/am/new/to/you sub/i/am/new/to/you - :100755 100755 $f6id $f6id R100 newdir/exec.sh sub/newdir/exec.sh - :100644 100644 $f5id $f5id R100 newdir/interesting sub/newdir/interesting - EOF - git fast-import <input && - git diff-tree -M -r M4^ M4 >actual && - compare_diff_raw expect actual -' + cat >expect <<-EOF && + :100644 100644 $oldf $oldf R100 file2/oldf sub/file2/oldf + :100755 100755 $f4id $f4id R100 file4 sub/file4 + :100755 100755 $newf $newf R100 i/am/new/to/you sub/i/am/new/to/you + :100755 100755 $f6id $f6id R100 newdir/exec.sh sub/newdir/exec.sh + :100644 100644 $f5id $f5id R100 newdir/interesting sub/newdir/interesting + EOF + git fast-import <input && + git diff-tree -M -r M4^ M4 >actual && + compare_diff_raw expect actual + ' +done ### ### series N @@ -1259,49 +1262,52 @@ test_expect_success PIPE 'N: empty directory reads as missing' ' test_cmp expect actual ' -test_expect_success 'N: copy root directory by tree hash' ' - cat >expect <<-EOF && - :100755 000000 $newf $zero D file3/newf - :100644 000000 $oldf $zero D file3/oldf - EOF - root=$(git rev-parse refs/heads/branch^0^{tree}) && - cat >input <<-INPUT_END && - commit refs/heads/N6 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - copy root directory by tree hash - COMMIT - - from refs/heads/branch^0 - M 040000 $root "" - INPUT_END - git fast-import <input && - git diff-tree -C --find-copies-harder -r N4 N6 >actual && - compare_diff_raw expect actual -' +for root in '""' '' +do + test_expect_success "N: copy root ($root) by tree hash" ' + cat >expect <<-EOF && + :100755 000000 $newf $zero D file3/newf + :100644 000000 $oldf $zero D file3/oldf + EOF + root_tree=$(git rev-parse refs/heads/branch^0^{tree}) && + cat >input <<-INPUT_END && + commit refs/heads/N6 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy root directory by tree hash + COMMIT -test_expect_success 'N: copy root by path' ' - cat >expect <<-EOF && - :100755 100755 $newf $newf C100 file2/newf oldroot/file2/newf - :100644 100644 $oldf $oldf C100 file2/oldf oldroot/file2/oldf - :100755 100755 $f4id $f4id C100 file4 oldroot/file4 - :100755 100755 $f6id $f6id C100 newdir/exec.sh oldroot/newdir/exec.sh - :100644 100644 $f5id $f5id C100 newdir/interesting oldroot/newdir/interesting - EOF - cat >input <<-INPUT_END && - commit refs/heads/N-copy-root-path - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - copy root directory by (empty) path - COMMIT + from refs/heads/branch^0 + M 040000 $root_tree $root + INPUT_END + git fast-import <input && + git diff-tree -C --find-copies-harder -r N4 N6 >actual && + compare_diff_raw expect actual + ' + + test_expect_success "N: copy root ($root) by path" ' + cat >expect <<-EOF && + :100755 100755 $newf $newf C100 file2/newf oldroot/file2/newf + :100644 100644 $oldf $oldf C100 file2/oldf oldroot/file2/oldf + :100755 100755 $f4id $f4id C100 file4 oldroot/file4 + :100755 100755 $f6id $f6id C100 newdir/exec.sh oldroot/newdir/exec.sh + :100644 100644 $f5id $f5id C100 newdir/interesting oldroot/newdir/interesting + EOF + cat >input <<-INPUT_END && + commit refs/heads/N-copy-root-path + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy root directory by (empty) path + COMMIT - from refs/heads/branch^0 - C "" oldroot - INPUT_END - git fast-import <input && - git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual && - compare_diff_raw expect actual -' + from refs/heads/branch^0 + C $root oldroot + INPUT_END + git fast-import <input && + git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual && + compare_diff_raw expect actual + ' +done test_expect_success 'N: delete directory by copying' ' cat >expect <<-\EOF && @@ -1431,98 +1437,102 @@ test_expect_success 'N: reject foo/ syntax in ls argument' ' INPUT_END ' -test_expect_success 'N: copy to root by id and modify' ' - echo "hello, world" >expect.foo && - echo hello >expect.bar && - git fast-import <<-SETUP_END && - commit refs/heads/N7 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - hello, tree - COMMIT - - deleteall - M 644 inline foo/bar - data <<EOF - hello - EOF - SETUP_END - - tree=$(git rev-parse --verify N7:) && - git fast-import <<-INPUT_END && - commit refs/heads/N8 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - copy to root by id and modify - COMMIT +for root in '""' '' +do + test_expect_success "N: copy to root ($root) by id and modify" ' + echo "hello, world" >expect.foo && + echo hello >expect.bar && + git fast-import <<-SETUP_END && + commit refs/heads/N7 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + hello, tree + COMMIT - M 040000 $tree "" - M 644 inline foo/foo - data <<EOF - hello, world - EOF - INPUT_END - git show N8:foo/foo >actual.foo && - git show N8:foo/bar >actual.bar && - test_cmp expect.foo actual.foo && - test_cmp expect.bar actual.bar -' + deleteall + M 644 inline foo/bar + data <<EOF + hello + EOF + SETUP_END -test_expect_success 'N: extract subtree' ' - branch=$(git rev-parse --verify refs/heads/branch^{tree}) && - cat >input <<-INPUT_END && - commit refs/heads/N9 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - extract subtree branch:newdir - COMMIT + tree=$(git rev-parse --verify N7:) && + git fast-import <<-INPUT_END && + commit refs/heads/N8 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy to root by id and modify + COMMIT - M 040000 $branch "" - C "newdir" "" - INPUT_END - git fast-import <input && - git diff --exit-code branch:newdir N9 -' + M 040000 $tree $root + M 644 inline foo/foo + data <<EOF + hello, world + EOF + INPUT_END + git show N8:foo/foo >actual.foo && + git show N8:foo/bar >actual.bar && + test_cmp expect.foo actual.foo && + test_cmp expect.bar actual.bar + ' + + test_expect_success "N: extract subtree to the root ($root)" ' + branch=$(git rev-parse --verify refs/heads/branch^{tree}) && + cat >input <<-INPUT_END && + commit refs/heads/N9 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + extract subtree branch:newdir + COMMIT -test_expect_success 'N: modify subtree, extract it, and modify again' ' - echo hello >expect.baz && - echo hello, world >expect.qux && - git fast-import <<-SETUP_END && - commit refs/heads/N10 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - hello, tree - COMMIT + M 040000 $branch $root + C "newdir" $root + INPUT_END + git fast-import <input && + git diff --exit-code branch:newdir N9 + ' + + test_expect_success "N: modify subtree, extract it to the root ($root), and modify again" ' + echo hello >expect.baz && + echo hello, world >expect.qux && + git fast-import <<-SETUP_END && + commit refs/heads/N10 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + hello, tree + COMMIT - deleteall - M 644 inline foo/bar/baz - data <<EOF - hello - EOF - SETUP_END + deleteall + M 644 inline foo/bar/baz + data <<EOF + hello + EOF + SETUP_END - tree=$(git rev-parse --verify N10:) && - git fast-import <<-INPUT_END && - commit refs/heads/N11 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - copy to root by id and modify - COMMIT + tree=$(git rev-parse --verify N10:) && + git fast-import <<-INPUT_END && + commit refs/heads/N11 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + copy to root by id and modify + COMMIT - M 040000 $tree "" - M 100644 inline foo/bar/qux - data <<EOF - hello, world - EOF - R "foo" "" - C "bar/qux" "bar/quux" - INPUT_END - git show N11:bar/baz >actual.baz && - git show N11:bar/qux >actual.qux && - git show N11:bar/quux >actual.quux && - test_cmp expect.baz actual.baz && - test_cmp expect.qux actual.qux && - test_cmp expect.qux actual.quux' + M 040000 $tree $root + M 100644 inline foo/bar/qux + data <<EOF + hello, world + EOF + R "foo" $root + C "bar/qux" "bar/quux" + INPUT_END + git show N11:bar/baz >actual.baz && + git show N11:bar/qux >actual.qux && + git show N11:bar/quux >actual.quux && + test_cmp expect.baz actual.baz && + test_cmp expect.qux actual.qux && + test_cmp expect.qux actual.quux + ' +done ### ### series O @@ -2007,12 +2017,11 @@ test_expect_success 'Q: verify first notes commit' ' ' test_expect_success 'Q: verify first notes tree' ' - cat >expect.unsorted <<-EOF && + sort >expect <<-EOF && 100644 blob $commit1 100644 blob $commit2 100644 blob $commit3 EOF - cat expect.unsorted | sort >expect && git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]* / /" >actual && test_cmp expect actual ' @@ -2048,12 +2057,11 @@ test_expect_success 'Q: verify second notes commit' ' ' test_expect_success 'Q: verify second notes tree' ' - cat >expect.unsorted <<-EOF && + sort >expect <<-EOF && 100644 blob $commit1 100644 blob $commit2 100644 blob $commit3 EOF - cat expect.unsorted | sort >expect && git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]* / /" >actual && test_cmp expect actual ' @@ -2088,10 +2096,9 @@ test_expect_success 'Q: verify third notes commit' ' ' test_expect_success 'Q: verify third notes tree' ' - cat >expect.unsorted <<-EOF && + sort >expect <<-EOF && 100644 blob $commit1 EOF - cat expect.unsorted | sort >expect && git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]* / /" >actual && test_cmp expect actual ' @@ -2115,10 +2122,9 @@ test_expect_success 'Q: verify fourth notes commit' ' ' test_expect_success 'Q: verify fourth notes tree' ' - cat >expect.unsorted <<-EOF && + sort >expect <<-EOF && 100644 blob $commit2 EOF - cat expect.unsorted | sort >expect && git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual && test_cmp expect actual ' @@ -2146,6 +2152,7 @@ test_expect_success 'Q: deny note on empty branch' ' EOF test_must_fail git fast-import <input ' + ### ### series R (feature and option) ### @@ -2794,7 +2801,7 @@ test_expect_success 'R: blob appears only once' ' ' ### -### series S +### series S (mark and path parsing) ### # # Make sure missing spaces and EOLs after mark references @@ -3064,21 +3071,283 @@ test_expect_success 'S: ls with garbage after sha1 must fail' ' test_grep "space after tree-ish" err ' +# +# Path parsing +# +# There are two sorts of ways a path can be parsed, depending on whether it is +# the last field on the line. Additionally, ls without a <dataref> has a special +# case. Test every occurrence of <path> in the grammar against every error case. +# Paths for the root (empty strings) are tested elsewhere. +# + +# +# Valid paths at the end of a line: filemodify, filedelete, filecopy (dest), +# filerename (dest), and ls. +# +# commit :301 from root -- modify hello.c (for setup) +# commit :302 from :301 -- modify $path +# commit :303 from :302 -- delete $path +# commit :304 from :301 -- copy hello.c $path +# commit :305 from :301 -- rename hello.c $path +# ls :305 $path +# +test_path_eol_success () { + local test="$1" path="$2" unquoted_path="$3" + 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 && + blob + mark :401 + data <<BLOB + hello world + BLOB + + blob + mark :402 + data <<BLOB + hallo welt + BLOB + + commit refs/heads/S-path-eol + mark :301 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + initial commit + COMMIT + M 100644 :401 hello.c + + commit refs/heads/S-path-eol + mark :302 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit filemodify + COMMIT + from :301 + M 100644 :402 $path + + commit refs/heads/S-path-eol + mark :303 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit filedelete + COMMIT + from :302 + D $path + + commit refs/heads/S-path-eol + mark :304 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit filecopy dest + COMMIT + from :301 + C hello.c $path + + commit refs/heads/S-path-eol + mark :305 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit filerename dest + COMMIT + from :301 + R hello.c $path + + ls :305 $path + EOF + + commit_m=$(grep :302 marks.out | cut -d\ -f2) && + commit_d=$(grep :303 marks.out | cut -d\ -f2) && + commit_c=$(grep :304 marks.out | cut -d\ -f2) && + commit_r=$(grep :305 marks.out | cut -d\ -f2) && + blob1=$(grep :401 marks.out | cut -d\ -f2) && + blob2=$(grep :402 marks.out | cut -d\ -f2) && + + ( + printf "100644 blob $blob2\t$unquoted_path\n" && + printf "100644 blob $blob1\thello.c\n" + ) | sort >tree_m.exp && + git ls-tree $commit_m | sort >tree_m.out && + test_cmp tree_m.exp tree_m.out && + + printf "100644 blob $blob1\thello.c\n" >tree_d.exp && + git ls-tree $commit_d >tree_d.out && + test_cmp tree_d.exp tree_d.out && + + ( + printf "100644 blob $blob1\t$unquoted_path\n" && + printf "100644 blob $blob1\thello.c\n" + ) | sort >tree_c.exp && + git ls-tree $commit_c | sort >tree_c.out && + test_cmp tree_c.exp tree_c.out && + + printf "100644 blob $blob1\t$unquoted_path\n" >tree_r.exp && + git ls-tree $commit_r >tree_r.out && + test_cmp tree_r.exp tree_r.out && + + test_cmp out tree_r.exp + ' +} + +test_path_eol_success 'quoted spaces' '" hello world.c "' ' hello world.c ' +test_path_eol_success 'unquoted spaces' ' hello world.c ' ' hello world.c ' +test_path_eol_success 'octal escapes' '"\150\151\056\143"' 'hi.c' + +# +# Valid paths before a space: filecopy (source) and filerename (source). +# +# commit :301 from root -- modify $path (for setup) +# commit :302 from :301 -- copy $path hello2.c +# commit :303 from :301 -- rename $path hello2.c +# +test_path_space_success () { + local test="$1" path="$2" unquoted_path="$3" + 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 && + blob + mark :401 + data <<BLOB + hello world + BLOB + + commit refs/heads/S-path-space + mark :301 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + initial commit + COMMIT + M 100644 :401 $path + + commit refs/heads/S-path-space + mark :302 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit filecopy source + COMMIT + from :301 + C $path hello2.c + + commit refs/heads/S-path-space + mark :303 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit filerename source + COMMIT + from :301 + R $path hello2.c + + EOF + + commit_c=$(grep :302 marks.out | cut -d\ -f2) && + commit_r=$(grep :303 marks.out | cut -d\ -f2) && + blob=$(grep :401 marks.out | cut -d\ -f2) && + + ( + printf "100644 blob $blob\t$unquoted_path\n" && + printf "100644 blob $blob\thello2.c\n" + ) | sort >tree_c.exp && + git ls-tree $commit_c | sort >tree_c.out && + test_cmp tree_c.exp tree_c.out && + + printf "100644 blob $blob\thello2.c\n" >tree_r.exp && + git ls-tree $commit_r >tree_r.out && + test_cmp tree_r.exp tree_r.out + ' +} + +test_path_space_success 'quoted spaces' '" hello world.c "' ' hello world.c ' +test_path_space_success 'no unquoted spaces' 'hello_world.c' 'hello_world.c' +test_path_space_success 'octal escapes' '"\150\151\056\143"' 'hi.c' + +# +# Test a single commit change with an invalid path. Run it with all occurrences +# of <path> in the grammar against all error kinds. +# +test_path_fail () { + local change="$1" what="$2" prefix="$3" path="$4" suffix="$5" err_grep="$6" + test_expect_success "S: $change with $what must fail" ' + test_must_fail git fast-import <<-EOF 2>err && + blob + mark :1 + data <<BLOB + hello world + BLOB + + commit refs/heads/S-path-fail + mark :2 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit setup + COMMIT + M 100644 :1 hello.c + + commit refs/heads/S-path-fail + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + commit with bad path + COMMIT + from :2 + $prefix$path$suffix + EOF + + test_grep "$err_grep" err + ' +} + +test_path_base_fail () { + local change="$1" prefix="$2" field="$3" suffix="$4" + test_path_fail "$change" 'unclosed " in '"$field" "$prefix" '"hello.c' "$suffix" "Invalid $field" + test_path_fail "$change" "invalid escape in quoted $field" "$prefix" '"hello\xff"' "$suffix" "Invalid $field" + test_path_fail "$change" "escaped NUL in quoted $field" "$prefix" '"hello\000"' "$suffix" "NUL in $field" +} +test_path_eol_quoted_fail () { + local change="$1" prefix="$2" field="$3" + test_path_base_fail "$change" "$prefix" "$field" '' + test_path_fail "$change" "garbage after quoted $field" "$prefix" '"hello.c"' 'x' "Garbage after $field" + test_path_fail "$change" "space after quoted $field" "$prefix" '"hello.c"' ' ' "Garbage after $field" +} +test_path_eol_fail () { + local change="$1" prefix="$2" field="$3" + test_path_eol_quoted_fail "$change" "$prefix" "$field" +} +test_path_space_fail () { + local change="$1" prefix="$2" field="$3" + test_path_base_fail "$change" "$prefix" "$field" ' world.c' + test_path_fail "$change" "missing space after quoted $field" "$prefix" '"hello.c"' 'x world.c' "Missing space after $field" + test_path_fail "$change" "missing space after unquoted $field" "$prefix" 'hello.c' '' "Missing space after $field" +} + +test_path_eol_fail filemodify 'M 100644 :1 ' path +test_path_eol_fail filedelete 'D ' path +test_path_space_fail filecopy 'C ' source +test_path_eol_fail filecopy 'C hello.c ' dest +test_path_space_fail filerename 'R ' source +test_path_eol_fail filerename 'R hello.c ' dest +test_path_eol_fail 'ls (in commit)' 'ls :2 ' path + +# When 'ls' has no <dataref>, the <path> must be quoted. +test_path_eol_quoted_fail 'ls (without dataref in commit)' 'ls ' path + ### ### series T (ls) ### # Setup is carried over from series S. -test_expect_success 'T: ls root tree' ' - sed -e "s/Z\$//" >expect <<-EOF && - 040000 tree $(git rev-parse S^{tree}) Z - EOF - sha1=$(git rev-parse --verify S) && - git fast-import --import-marks=marks <<-EOF >actual && - ls $sha1 "" - EOF - test_cmp expect actual -' +for root in '""' '' +do + test_expect_success "T: ls root ($root) tree" ' + sed -e "s/Z\$//" >expect <<-EOF && + 040000 tree $(git rev-parse S^{tree}) Z + EOF + sha1=$(git rev-parse --verify S) && + git fast-import --import-marks=marks <<-EOF >actual && + ls $sha1 $root + EOF + test_cmp expect actual + ' +done test_expect_success 'T: delete branch' ' git branch to-delete && @@ -3180,30 +3449,33 @@ test_expect_success 'U: validate directory delete result' ' compare_diff_raw expect actual ' -test_expect_success 'U: filedelete root succeeds' ' - cat >input <<-INPUT_END && - commit refs/heads/U - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <<COMMIT - must succeed - COMMIT - from refs/heads/U^0 - D "" +for root in '""' '' +do + test_expect_success "U: filedelete root ($root) succeeds" ' + cat >input <<-INPUT_END && + commit refs/heads/U-delete-root + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + must succeed + COMMIT + from refs/heads/U^0 + D $root - INPUT_END + INPUT_END - git fast-import <input -' + git fast-import <input + ' -test_expect_success 'U: validate root delete result' ' - cat >expect <<-EOF && - :100644 000000 $f7id $ZERO_OID D hello.c - EOF + test_expect_success "U: validate root ($root) delete result" ' + cat >expect <<-EOF && + :100644 000000 $f7id $ZERO_OID D hello.c + EOF - git diff-tree -M -r U^1 U >actual && + git diff-tree -M -r U U-delete-root >actual && - compare_diff_raw expect actual -' + compare_diff_raw expect actual + ' +done ### ### series V (checkpoint) diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index e9a12c18bb..1eb035ee4c 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -236,7 +236,7 @@ EOF test_expect_success 'set up faked signed tag' ' - cat signed-tag-import | git fast-import + git fast-import <signed-tag-import ' @@ -537,7 +537,7 @@ test_expect_success 'full-tree re-shows unmodified files' ' test_expect_success 'set-up a few more tags for tag export tests' ' git checkout -f main && - HEAD_TREE=$(git show -s --pretty=raw HEAD | grep tree | sed "s/tree //") && + HEAD_TREE=$(git show -s --pretty=raw HEAD | sed -n "/tree/s/tree //p") && git tag tree_tag -m "tagging a tree" $HEAD_TREE && git tag -a tree_tag-obj -m "tagging a tree" $HEAD_TREE && git tag tag-obj_tag -m "tagging a tag" tree_tag-obj && diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index 003c0b61d0..e499c7f955 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -117,12 +117,12 @@ END VERIFICATION REQUEST EOF test_expect_success 'pserver authentication' ' - cat request-anonymous | git-cvsserver pserver >log 2>&1 && + git-cvsserver pserver <request-anonymous >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' test_expect_success 'pserver authentication failure (non-anonymous user)' ' - if cat request-git | git-cvsserver pserver >log 2>&1 + if git-cvsserver pserver <request-git >log 2>&1 then false else @@ -132,17 +132,17 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' ' ' test_expect_success 'pserver authentication success (non-anonymous user with password)' ' - cat login-git-ok | git-cvsserver pserver >log 2>&1 && + git-cvsserver pserver <login-git-ok >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' test_expect_success 'pserver authentication (login)' ' - cat login-anonymous | git-cvsserver pserver >log 2>&1 && + git-cvsserver pserver <login-anonymous >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' test_expect_success 'pserver authentication failure (login/non-anonymous user)' ' - if cat login-git | git-cvsserver pserver >log 2>&1 + if git-cvsserver pserver <login-git >log 2>&1 then false else @@ -172,7 +172,7 @@ Root $WORKDIR EOF test_expect_success 'req_Root failure (relative pathname)' ' - if cat request-relative | git-cvsserver pserver >log 2>&1 + if git-cvsserver pserver <request-relative >log 2>&1 then echo unexpected success false @@ -183,28 +183,26 @@ test_expect_success 'req_Root failure (relative pathname)' ' ' test_expect_success 'req_Root failure (conflicting roots)' ' - cat request-conflict | git-cvsserver pserver >log 2>&1 && + git-cvsserver pserver <request-conflict >log 2>&1 && tail log | grep "^error 1 Conflicting roots specified$" ' test_expect_success 'req_Root (strict paths)' ' - cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 && + git-cvsserver --strict-paths pserver "$SERVERDIR" <request-anonymous >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' test_expect_success 'req_Root failure (strict-paths)' ' - ! cat request-anonymous | - git-cvsserver --strict-paths pserver "$WORKDIR" >log 2>&1 + ! git-cvsserver --strict-paths pserver "$WORKDIR" <request-anonymous >log 2>&1 ' test_expect_success 'req_Root (w/o strict-paths)' ' - cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 && + git-cvsserver pserver "$WORKDIR/" <request-anonymous >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' test_expect_success 'req_Root failure (w/o strict-paths)' ' - ! cat request-anonymous | - git-cvsserver pserver "$WORKDIR/gitcvs" >log 2>&1 + ! git-cvsserver pserver "$WORKDIR/gitcvs" <request-anonymous >log 2>&1 ' cat >request-base <<EOF @@ -217,27 +215,26 @@ Root /gitcvs.git EOF test_expect_success 'req_Root (base-path)' ' - cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && + git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" <request-base >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' test_expect_success 'req_Root failure (base-path)' ' - ! cat request-anonymous | - git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" >log 2>&1 + ! git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" <request-anonymous >log 2>&1 ' GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false || exit 1 test_expect_success 'req_Root (export-all)' ' - cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 && + git-cvsserver --export-all pserver "$WORKDIR" <request-anonymous >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' test_expect_success 'req_Root failure (export-all w/o directory list)' ' - ! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)' + ! (git-cvsserver --export-all pserver <request-anonymous >log 2>&1 || false)' test_expect_success 'req_Root (everything together)' ' - cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && + git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" <request-base >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$" ' diff --git a/t/t9604-cvsimport-timestamps.sh b/t/t9604-cvsimport-timestamps.sh index 2ff4aa932d..2d03259729 100755 --- a/t/t9604-cvsimport-timestamps.sh +++ b/t/t9604-cvsimport-timestamps.sh @@ -3,11 +3,28 @@ test_description='git cvsimport timestamps' . ./lib-cvs.sh +test_lazy_prereq POSIX_TIMEZONE ' + local tz=XST-1XDT,M3.5.0,M11.1.0 + echo "1711846799 -> 2024-03-31 01:59:59 +0100" >expected && + TZ="$tz" test-tool date show:iso-local 1711846799 >actual && + test_cmp expected actual && + echo "1711846800 -> 2024-03-31 03:00:00 +0200" >expected && + TZ="$tz" test-tool date show:iso-local 1711846800 >actual && + test_cmp expected actual && + echo "1730591999 -> 2024-11-03 01:59:59 +0200" >expected && + TZ="$tz" test-tool date show:iso-local 1730591999 >actual && + test_cmp expected actual && + echo "1730592000 -> 2024-11-03 01:00:00 +0100" >expected && + TZ="$tz" test-tool date show:iso-local 1730592000 >actual && + test_cmp expected actual +' + setup_cvs_test_repository t9604 -test_expect_success PERL 'check timestamps are UTC (TZ=CST6CDT)' ' +test_expect_success PERL,POSIX_TIMEZONE 'check timestamps are UTC' ' - TZ=CST6CDT git cvsimport -p"-x" -C module-1 module && + TZ=CST6CDT,M4.1.0,M10.5.0 \ + git cvsimport -p"-x" -C module-1 module && git cvsimport -p"-x" -C module-1 module && ( cd module-1 && @@ -34,13 +51,13 @@ test_expect_success PERL 'check timestamps are UTC (TZ=CST6CDT)' ' test_cmp expect-1 actual-1 ' -test_expect_success PERL 'check timestamps with author-specific timezones' ' +test_expect_success PERL,POSIX_TIMEZONE 'check timestamps with author-specific timezones' ' cat >cvs-authors <<-EOF && user1=User One <user1@domain.org> - user2=User Two <user2@domain.org> CST6CDT - user3=User Three <user3@domain.org> EST5EDT - user4=User Four <user4@domain.org> MST7MDT + user2=User Two <user2@domain.org> CST6CDT,M4.1.0,M10.5.0 + user3=User Three <user3@domain.org> EST5EDT,M4.1.0,M10.5.0 + user4=User Four <user4@domain.org> MST7MDT,M4.1.0,M10.5.0 EOF git cvsimport -p"-x" -A cvs-authors -C module-2 module && ( diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh index 2a6ee2a467..bb236cd2b5 100755 --- a/t/t9802-git-p4-filetype.sh +++ b/t/t9802-git-p4-filetype.sh @@ -175,7 +175,7 @@ test_expect_success 'keyword file create' ' cp k-text-k k-text-ko && p4 add -t text+ko k-text-ko && - cat k-text-k | iconv -f ascii -t utf-16 >k-utf16-k && + iconv -f ascii -t utf-16 <k-text-k >k-utf16-k && p4 add -t utf16+k k-utf16-k && cp k-utf16-k k-utf16-ko && diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh index af4b286f9d..6ae7ced51b 100755 --- a/t/t9807-git-p4-submit.sh +++ b/t/t9807-git-p4-submit.sh @@ -418,7 +418,7 @@ test_expect_success 'description with Jobs and values on separate lines' ' marshal_dump job0 <change && marshal_dump job1 <change ) | sort >jobs && - cat jobname1 jobname2 | sort >expected && + sort jobname1 jobname2 >expected && test_cmp expected jobs ) ' diff --git a/t/t9824-git-p4-git-lfs.sh b/t/t9824-git-p4-git-lfs.sh index a28dbbdd56..80c8c31e32 100755 --- a/t/t9824-git-p4-git-lfs.sh +++ b/t/t9824-git-p4-git-lfs.sh @@ -17,8 +17,8 @@ test_file_in_lfs () { sed -n '2,2 p' "$FILE" | grep "^oid " && sed -n '3,3 p' "$FILE" | grep "^size " && test_line_count = 3 "$FILE" && - cat "$FILE" | grep "size $SIZE" && - HASH=$(cat "$FILE" | grep "oid sha256:" | sed -e "s/oid sha256://g") && + grep "size $SIZE" "$FILE" && + HASH=$(sed -ne "/oid sha256:/s/oid sha256://gp" "$FILE") && LFS_FILE=".git/lfs/objects/$(echo "$HASH" | cut -c1-2)/$(echo "$HASH" | cut -c3-4)/$HASH" && echo $EXPECTED_CONTENT >expect && test_path_is_file "$FILE" && diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index b16c284181..569cf23104 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -1263,6 +1263,29 @@ test_expect_success '__git_complete_fetch_refspecs - fully qualified & prefix' ' test_cmp expected out ' +test_expect_success '__git_complete_worktree_paths' ' + test_when_finished "git worktree remove other_wt" && + git worktree add --orphan other_wt && + run_completion "git worktree remove " && + grep other_wt out +' + +test_expect_success '__git_complete_worktree_paths - not a git repository' ' + ( + cd non-repo && + GIT_CEILING_DIRECTORIES="$ROOT" && + export GIT_CEILING_DIRECTORIES && + test_completion "git worktree remove " "" + ) +' + +test_expect_success '__git_complete_worktree_paths with -C' ' + test_when_finished "git -C otherrepo worktree remove otherrepo_wt" && + git -C otherrepo worktree add --orphan otherrepo_wt && + run_completion "git -C otherrepo worktree remove " && + grep otherrepo_wt out +' + test_expect_success 'git switch - with no options, complete local branches and unique remote branch names for DWIM logic' ' test_completion "git switch " <<-\EOF branch-in-other Z @@ -2804,6 +2827,20 @@ test_expect_success 'git clone --config= - value' ' EOF ' +test_expect_success 'git reflog show' ' + test_when_finished "git checkout - && git branch -d shown" && + git checkout -b shown && + test_completion "git reflog sho" <<-\EOF && + show Z + shown Z + EOF + test_completion "git reflog show sho" "shown " && + test_completion "git reflog shown sho" "shown " && + test_completion "git reflog --unt" "--until=" && + test_completion "git reflog show --unt" "--until=" && + test_completion "git reflog shown --unt" "--until=" +' + test_expect_success 'options with value' ' test_completion "git merge -X diff-algorithm=" <<-\EOF diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index b5eaf7fdc1..862d80c974 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -385,7 +385,7 @@ test_commit () { shift done && indir=${indir:+"$indir"/} && - local file=${2:-"$1.t"} && + local file="${2:-"$1.t"}" && if test -n "$append" then $echo "${3-$1}" >>"$indir$file" @@ -1263,9 +1263,8 @@ test_cmp_bin () { cmp "$@" } -# Deprecated - do not use this in new code test_i18ngrep () { - test_grep "$@" + BUG "do not use test_i18ngrep---use test_grep instead" } test_grep () { @@ -1656,7 +1655,16 @@ test_set_hash () { # Detect the hash algorithm in use. test_detect_hash () { - test_hash_algo="${GIT_TEST_DEFAULT_HASH:-sha1}" + case "$GIT_TEST_DEFAULT_HASH" in + "sha256") + test_hash_algo=sha256 + test_compat_hash_algo=sha1 + ;; + *) + test_hash_algo=sha1 + test_compat_hash_algo=sha256 + ;; + esac } # Detect the hash algorithm in use. @@ -1713,6 +1721,12 @@ test_oid () { local algo="${test_hash_algo}" && case "$1" in + --hash=storage) + algo="$test_hash_algo" && + shift;; + --hash=compat) + algo="$test_compat_hash_algo" && + shift;; --hash=*) algo="${1#--hash=}" && shift;; @@ -1734,7 +1748,7 @@ test_oid () { # Insert a slash into an object ID so it can be used to reference a location # under ".git/objects". For example, "deadbeef..." becomes "de/adbeef..". test_oid_to_path () { - local basename=${1#??} + local basename="${1#??}" echo "${1%$basename}/$basename" } @@ -1751,7 +1765,7 @@ test_parse_ls_tree_oids () { # Choose a port number based on the test script's number and store it in # the given variable name, unless that variable already contains a number. test_set_port () { - local var=$1 port + local var="$1" port if test $# -ne 1 || test -z "$var" then @@ -1826,7 +1840,7 @@ test_subcommand () { shift fi - local expr=$(printf '"%s",' "$@") + local expr="$(printf '"%s",' "$@")" expr="${expr%,}" if test -n "$negate" @@ -1916,7 +1930,7 @@ test_readlink () { # An optional increment to the magic timestamp may be specified as second # argument. test_set_magic_mtime () { - local inc=${2:-0} && + local inc="${2:-0}" && local mtime=$((1234567890 + $inc)) && test-tool chmtime =$mtime "$1" && test_is_magic_mtime "$1" $inc @@ -1929,7 +1943,7 @@ test_set_magic_mtime () { # argument. Usually, this should be the same increment which was used for # the associated test_set_magic_mtime. test_is_magic_mtime () { - local inc=${2:-0} && + local inc="${2:-0}" && local mtime=$((1234567890 + $inc)) && echo $mtime >.git/test-mtime-expect && test-tool chmtime --get "$1" >.git/test-mtime-actual && diff --git a/t/test-lib.sh b/t/test-lib.sh index 042f557a6f..79d3e0e7d9 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1755,6 +1755,8 @@ esac case "$GIT_DEFAULT_REF_FORMAT" in files) test_set_prereq REFFILES;; +reftable) + test_set_prereq REFTABLE;; *) echo 2>&1 "error: unknown ref format $GIT_DEFAULT_REF_FORMAT" exit 1 @@ -1960,6 +1962,7 @@ test_lazy_prereq DEFAULT_REPO_FORMAT ' # Tests that verify the scheduler integration must set this locally # to avoid errors. GIT_TEST_MAINT_SCHEDULER="none:exit 1" +export GIT_TEST_MAINT_SCHEDULER # Does this platform support `git fsmonitor--daemon` # diff --git a/t/unit-tests/t-ctype.c b/t/unit-tests/t-ctype.c index f315489984..d6ac1fe678 100644 --- a/t/unit-tests/t-ctype.c +++ b/t/unit-tests/t-ctype.c @@ -1,30 +1,19 @@ #include "test-lib.h" -static int is_in(const char *s, int ch) -{ - /* - * We can't find NUL using strchr. Accept it as the first - * character in the spec -- there are no empty classes. - */ - if (ch == '\0') - return ch == *s; - if (*s == '\0') - s++; - return !!strchr(s, ch); -} - -/* Macro to test a character type */ -#define TEST_CTYPE_FUNC(func, string) \ -static void test_ctype_##func(void) { \ - for (int i = 0; i < 256; i++) { \ - if (!check_int(func(i), ==, is_in(string, i))) \ - test_msg(" i: 0x%02x", i); \ +#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)); \ } \ - if (!check(!func(EOF))) \ - test_msg(" i: 0x%02x (EOF)", EOF); \ -} - -#define TEST_CHAR_CLASS(class) TEST(test_ctype_##class(), #class " works") + test__run_end(!skip, TEST_LOCATION(), #class " works"); \ +} while (0) #define DIGIT "0123456789" #define LOWER "abcdefghijklmnopqrstuvwxyz" @@ -44,37 +33,21 @@ static void test_ctype_##func(void) { \ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \ "\x7f" -TEST_CTYPE_FUNC(isdigit, DIGIT) -TEST_CTYPE_FUNC(isspace, " \n\r\t") -TEST_CTYPE_FUNC(isalpha, LOWER UPPER) -TEST_CTYPE_FUNC(isalnum, LOWER UPPER DIGIT) -TEST_CTYPE_FUNC(is_glob_special, "*?[\\") -TEST_CTYPE_FUNC(is_regex_special, "$()*+.?[\\^{|") -TEST_CTYPE_FUNC(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~") -TEST_CTYPE_FUNC(isascii, ASCII) -TEST_CTYPE_FUNC(islower, LOWER) -TEST_CTYPE_FUNC(isupper, UPPER) -TEST_CTYPE_FUNC(iscntrl, CNTRL) -TEST_CTYPE_FUNC(ispunct, PUNCT) -TEST_CTYPE_FUNC(isxdigit, DIGIT "abcdefABCDEF") -TEST_CTYPE_FUNC(isprint, LOWER UPPER DIGIT PUNCT " ") - int cmd_main(int argc, const char **argv) { - /* Run all character type tests */ - TEST_CHAR_CLASS(isspace); - TEST_CHAR_CLASS(isdigit); - TEST_CHAR_CLASS(isalpha); - TEST_CHAR_CLASS(isalnum); - TEST_CHAR_CLASS(is_glob_special); - TEST_CHAR_CLASS(is_regex_special); - TEST_CHAR_CLASS(is_pathspec_magic); - TEST_CHAR_CLASS(isascii); - TEST_CHAR_CLASS(islower); - TEST_CHAR_CLASS(isupper); - TEST_CHAR_CLASS(iscntrl); - TEST_CHAR_CLASS(ispunct); - TEST_CHAR_CLASS(isxdigit); - TEST_CHAR_CLASS(isprint); + TEST_CHAR_CLASS(isspace, " \n\r\t"); + TEST_CHAR_CLASS(isdigit, DIGIT); + TEST_CHAR_CLASS(isalpha, LOWER UPPER); + TEST_CHAR_CLASS(isalnum, LOWER UPPER DIGIT); + TEST_CHAR_CLASS(is_glob_special, "*?[\\"); + TEST_CHAR_CLASS(is_regex_special, "$()*+.?[\\^{|"); + TEST_CHAR_CLASS(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~"); + TEST_CHAR_CLASS(isascii, ASCII); + TEST_CHAR_CLASS(islower, LOWER); + TEST_CHAR_CLASS(isupper, UPPER); + TEST_CHAR_CLASS(iscntrl, CNTRL); + TEST_CHAR_CLASS(ispunct, PUNCT); + TEST_CHAR_CLASS(isxdigit, DIGIT "abcdefABCDEF"); + TEST_CHAR_CLASS(isprint, LOWER UPPER DIGIT PUNCT " "); return test_done(); } diff --git a/t/unit-tests/t-prio-queue.c b/t/unit-tests/t-prio-queue.c index d78b002f9e..7a4e5780e1 100644 --- a/t/unit-tests/t-prio-queue.c +++ b/t/unit-tests/t-prio-queue.c @@ -19,11 +19,13 @@ static int show(int *v) return v ? *v : MISSING; } -static void test_prio_queue(int *input, int *result, size_t input_size) +static void test_prio_queue(int *input, size_t input_size, + int *result, size_t result_size) { struct prio_queue pq = { intcmp }; + int j = 0; - for (int i = 0, j = 0; i < input_size; i++) { + for (int i = 0; i < input_size; i++) { void *peek, *get; switch(input[i]) { case GET: @@ -31,16 +33,22 @@ static void test_prio_queue(int *input, int *result, size_t input_size) get = prio_queue_get(&pq); if (!check(peek == get)) return; - if(!check_int(result[j++], ==, show(get))) - test_msg("failed at result[] index %d", j-1); + if (!check_uint(j, <, result_size)) + break; + if (!check_int(result[j], ==, show(get))) + test_msg(" j: %d", j); + j++; break; case DUMP: while ((peek = prio_queue_peek(&pq))) { get = prio_queue_get(&pq); if (!check(peek == get)) return; - if(!check_int(result[j++], ==, show(get))) - test_msg("failed at result[] index %d", j-1); + if (!check_uint(j, <, result_size)) + break; + if (!check_int(result[j], ==, show(get))) + test_msg(" j: %d", j); + j++; } break; case STACK: @@ -54,45 +62,30 @@ static void test_prio_queue(int *input, int *result, size_t input_size) break; } } + check_uint(j, ==, result_size); clear_prio_queue(&pq); } -#define BASIC_INPUT 2, 6, 3, 10, 9, 5, 7, 4, 5, 8, 1, DUMP -#define BASIC_RESULT 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10 - -#define MIXED_PUT_GET_INPUT 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP -#define MIXED_PUT_GET_RESULT 2, 3, 4, 1, 5, 6 - -#define EMPTY_QUEUE_INPUT 1, 2, GET, GET, GET, 1, 2, GET, GET, GET -#define EMPTY_QUEUE_RESULT 1, 2, MISSING, 1, 2, MISSING - -#define STACK_INPUT STACK, 8, 1, 5, 4, 6, 2, 3, DUMP -#define STACK_RESULT 3, 2, 6, 4, 5, 1, 8 - -#define REVERSE_STACK_INPUT STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP -#define REVERSE_STACK_RESULT 1, 2, 3, 4, 5, 6 - -#define TEST_INPUT(INPUT, RESULT, name) \ - static void test_##name(void) \ -{ \ - int input[] = {INPUT}; \ - int result[] = {RESULT}; \ - test_prio_queue(input, result, ARRAY_SIZE(input)); \ -} - -TEST_INPUT(BASIC_INPUT, BASIC_RESULT, basic) -TEST_INPUT(MIXED_PUT_GET_INPUT, MIXED_PUT_GET_RESULT, mixed) -TEST_INPUT(EMPTY_QUEUE_INPUT, EMPTY_QUEUE_RESULT, empty) -TEST_INPUT(STACK_INPUT, STACK_RESULT, stack) -TEST_INPUT(REVERSE_STACK_INPUT, REVERSE_STACK_RESULT, reverse) +#define TEST_INPUT(input, result) \ + test_prio_queue(input, ARRAY_SIZE(input), result, ARRAY_SIZE(result)) int cmd_main(int argc, const char **argv) { - TEST(test_basic(), "prio-queue works for basic input"); - TEST(test_mixed(), "prio-queue works for mixed put & get commands"); - TEST(test_empty(), "prio-queue works when queue is empty"); - TEST(test_stack(), "prio-queue works when used as a LIFO stack"); - TEST(test_reverse(), "prio-queue works when LIFO stack is reversed"); + 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 })), + "prio-queue works for basic input"); + TEST(TEST_INPUT(((int []){ 6, 2, 4, GET, 5, 3, GET, GET, 1, DUMP }), + ((int []){ 2, 3, 4, 1, 5, 6 })), + "prio-queue works for mixed put & get commands"); + TEST(TEST_INPUT(((int []){ 1, 2, GET, GET, GET, 1, 2, GET, GET, GET }), + ((int []){ 1, 2, MISSING, 1, 2, MISSING })), + "prio-queue works when queue is empty"); + TEST(TEST_INPUT(((int []){ STACK, 8, 1, 5, 4, 6, 2, 3, DUMP }), + ((int []){ 3, 2, 6, 4, 5, 1, 8 })), + "prio-queue works when used as a LIFO stack"); + TEST(TEST_INPUT(((int []){ STACK, 1, 2, 3, 4, 5, 6, REVERSE, DUMP }), + ((int []){ 1, 2, 3, 4, 5, 6 })), + "prio-queue works when LIFO stack is reversed"); return test_done(); } diff --git a/tempfile.c b/tempfile.c index ecdebf1afb..ed88cf8431 100644 --- a/tempfile.c +++ b/tempfile.c @@ -50,15 +50,17 @@ static VOLATILE_LIST_HEAD(tempfile_list); -static void remove_template_directory(struct tempfile *tempfile, +static int remove_template_directory(struct tempfile *tempfile, int in_signal_handler) { if (tempfile->directory) { if (in_signal_handler) - rmdir(tempfile->directory); + return rmdir(tempfile->directory); else - rmdir_or_warn(tempfile->directory); + return rmdir_or_warn(tempfile->directory); } + + return 0; } static void remove_tempfiles(int in_signal_handler) @@ -353,16 +355,19 @@ int rename_tempfile(struct tempfile **tempfile_p, const char *path) return 0; } -void delete_tempfile(struct tempfile **tempfile_p) +int delete_tempfile(struct tempfile **tempfile_p) { struct tempfile *tempfile = *tempfile_p; + int err = 0; if (!is_tempfile_active(tempfile)) - return; + return 0; - close_tempfile_gently(tempfile); - unlink_or_warn(tempfile->filename.buf); - remove_template_directory(tempfile, 0); + err |= close_tempfile_gently(tempfile); + err |= unlink_or_warn(tempfile->filename.buf); + err |= remove_template_directory(tempfile, 0); deactivate_tempfile(tempfile); *tempfile_p = NULL; + + return err ? -1 : 0; } diff --git a/tempfile.h b/tempfile.h index d0413af733..2d2ae5b657 100644 --- a/tempfile.h +++ b/tempfile.h @@ -269,7 +269,7 @@ int reopen_tempfile(struct tempfile *tempfile); * `delete_tempfile()` for a `tempfile` object that has already been * deleted or renamed. */ -void delete_tempfile(struct tempfile **tempfile_p); +int delete_tempfile(struct tempfile **tempfile_p); /* * Close the file descriptor and/or file pointer if they are still @@ -433,6 +433,9 @@ void trace2_cmd_name_fl(const char *file, int line, const char *name) for_each_wanted_builtin (j, tgt_j) if (tgt_j->pfn_command_name_fl) tgt_j->pfn_command_name_fl(file, line, name, hierarchy); + + trace2_cmd_list_config(); + trace2_cmd_list_env_vars(); } void trace2_cmd_mode_fl(const char *file, int line, const char *mode) @@ -464,17 +467,29 @@ void trace2_cmd_alias_fl(const char *file, int line, const char *alias, void trace2_cmd_list_config_fl(const char *file, int line) { + static int emitted = 0; + if (!trace2_enabled) return; + if (emitted) + return; + emitted = 1; + tr2_cfg_list_config_fl(file, line); } void trace2_cmd_list_env_vars_fl(const char *file, int line) { + static int emitted = 0; + if (!trace2_enabled) return; + if (emitted) + return; + emitted = 1; + tr2_list_env_vars_fl(file, line); } @@ -5,7 +5,6 @@ #include "string-list.h" #include "run-command.h" #include "commit.h" -#include "tempfile.h" #include "trailer.h" #include "list.h" /* @@ -145,37 +144,6 @@ static char last_non_space_char(const char *s) return '\0'; } -static void print_tok_val(FILE *outfile, const char *tok, const char *val) -{ - char c; - - if (!tok) { - fprintf(outfile, "%s\n", val); - return; - } - - c = last_non_space_char(tok); - if (!c) - return; - if (strchr(separators, c)) - fprintf(outfile, "%s%s\n", tok, val); - else - fprintf(outfile, "%s%c %s\n", tok, separators[0], val); -} - -static void print_all(FILE *outfile, struct list_head *head, - const struct process_trailer_options *opts) -{ - struct list_head *pos; - struct trailer_item *item; - list_for_each(pos, head) { - item = list_entry(pos, struct trailer_item, list); - if ((!opts->trim_empty || strlen(item->value) > 0) && - (!opts->only_trailers || item->token)) - print_tok_val(outfile, item->token, item->value); - } -} - static struct trailer_item *trailer_from_arg(struct arg_item *arg_tok) { struct trailer_item *new_item = xcalloc(1, sizeof(*new_item)); @@ -366,8 +334,8 @@ static int find_same_and_apply_arg(struct list_head *head, return 0; } -static void process_trailers_lists(struct list_head *head, - struct list_head *arg_head) +void process_trailers_lists(struct list_head *head, + struct list_head *arg_head) { struct list_head *pos, *p; struct arg_item *arg_tok; @@ -589,7 +557,7 @@ static int git_trailer_config(const char *conf_key, const char *value, return 0; } -static void ensure_configured(void) +void trailer_config_init(void) { if (configured) return; @@ -719,7 +687,7 @@ static void add_arg_item(struct list_head *arg_head, char *tok, char *val, list_add_tail(&new_item->list, arg_head); } -static void parse_trailers_from_config(struct list_head *config_head) +void parse_trailers_from_config(struct list_head *config_head) { struct arg_item *item; struct list_head *pos; @@ -735,8 +703,8 @@ static void parse_trailers_from_config(struct list_head *config_head) } } -static void parse_trailers_from_command_line_args(struct list_head *arg_head, - struct list_head *new_trailer_head) +void parse_trailers_from_command_line_args(struct list_head *arg_head, + struct list_head *new_trailer_head) { struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; @@ -775,17 +743,6 @@ static void parse_trailers_from_command_line_args(struct list_head *arg_head, free(cl_separators); } -static void read_input_file(struct strbuf *sb, const char *file) -{ - if (file) { - if (strbuf_read_file(sb, file, 0) < 0) - die_errno(_("could not read input file '%s'"), file); - } else { - if (strbuf_read(sb, fileno(stdin), 0) < 0) - die_errno(_("could not read from stdin")); - } -} - static const char *next_line(const char *str) { const char *nl = strchrnul(str, '\n'); @@ -882,7 +839,7 @@ static size_t find_trailer_block_start(const char *buf, size_t len) /* The first paragraph is the title and cannot be trailers */ for (s = buf; s < buf + len; s = next_line(s)) { - if (s[0] == comment_line_char) + if (starts_with_mem(s, buf + len - s, comment_line_str)) continue; if (is_blank_line(s)) break; @@ -902,7 +859,7 @@ static size_t find_trailer_block_start(const char *buf, size_t len) const char **p; ssize_t separator_pos; - if (bol[0] == comment_line_char) { + if (starts_with_mem(bol, buf + len - bol, comment_line_str)) { non_trailer_lines += possible_continuation_lines; possible_continuation_lines = 0; continue; @@ -999,21 +956,21 @@ static void unfold_value(struct strbuf *val) * Parse trailers in "str", populating the trailer info and "head" * linked list structure. */ -static void parse_trailers(struct trailer_info *info, - const char *str, - struct list_head *head, - const struct process_trailer_options *opts) +void parse_trailers(const struct process_trailer_options *opts, + struct trailer_info *info, + const char *str, + struct list_head *head) { struct strbuf tok = STRBUF_INIT; struct strbuf val = STRBUF_INIT; size_t i; - trailer_info_get(info, str, opts); + trailer_info_get(opts, str, info); for (i = 0; i < info->trailer_nr; i++) { int separator_pos; char *trailer = info->trailers[i]; - if (trailer[0] == comment_line_char) + if (starts_with(trailer, comment_line_str)) continue; separator_pos = find_separator(trailer, separators); if (separator_pos >= 1) { @@ -1034,99 +991,18 @@ static void parse_trailers(struct trailer_info *info, } } -static void free_all(struct list_head *head) +void free_trailers(struct list_head *trailers) { struct list_head *pos, *p; - list_for_each_safe(pos, p, head) { + list_for_each_safe(pos, p, trailers) { list_del(pos); free_trailer_item(list_entry(pos, struct trailer_item, list)); } } -static struct tempfile *trailers_tempfile; - -static FILE *create_in_place_tempfile(const char *file) -{ - struct stat st; - struct strbuf filename_template = STRBUF_INIT; - const char *tail; - FILE *outfile; - - if (stat(file, &st)) - die_errno(_("could not stat %s"), file); - if (!S_ISREG(st.st_mode)) - die(_("file %s is not a regular file"), file); - if (!(st.st_mode & S_IWUSR)) - die(_("file %s is not writable by user"), file); - - /* Create temporary file in the same directory as the original */ - tail = strrchr(file, '/'); - if (tail) - strbuf_add(&filename_template, file, tail - file + 1); - strbuf_addstr(&filename_template, "git-interpret-trailers-XXXXXX"); - - trailers_tempfile = xmks_tempfile_m(filename_template.buf, st.st_mode); - strbuf_release(&filename_template); - outfile = fdopen_tempfile(trailers_tempfile, "w"); - if (!outfile) - die_errno(_("could not open temporary file")); - - return outfile; -} - -void process_trailers(const char *file, - const struct process_trailer_options *opts, - struct list_head *new_trailer_head) -{ - LIST_HEAD(head); - struct strbuf sb = STRBUF_INIT; - struct trailer_info info; - FILE *outfile = stdout; - - ensure_configured(); - - read_input_file(&sb, file); - - if (opts->in_place) - outfile = create_in_place_tempfile(file); - - parse_trailers(&info, sb.buf, &head, opts); - - /* Print the lines before the trailers */ - if (!opts->only_trailers) - fwrite(sb.buf, 1, info.trailer_block_start, outfile); - - if (!opts->only_trailers && !info.blank_line_before_trailer) - fprintf(outfile, "\n"); - - - if (!opts->only_input) { - LIST_HEAD(config_head); - LIST_HEAD(arg_head); - parse_trailers_from_config(&config_head); - parse_trailers_from_command_line_args(&arg_head, new_trailer_head); - list_splice(&config_head, &arg_head); - process_trailers_lists(&head, &arg_head); - } - - print_all(outfile, &head, opts); - - free_all(&head); - trailer_info_release(&info); - - /* Print the lines after the trailers as is */ - if (!opts->only_trailers) - fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile); - - if (opts->in_place) - if (rename_tempfile(&trailers_tempfile, file)) - die_errno(_("could not rename temporary file to %s"), file); - - strbuf_release(&sb); -} - -void trailer_info_get(struct trailer_info *info, const char *str, - const struct process_trailer_options *opts) +void trailer_info_get(const struct process_trailer_options *opts, + const char *str, + struct trailer_info *info) { size_t end_of_log_message = 0, trailer_block_start = 0; struct strbuf **trailer_lines, **ptr; @@ -1134,7 +1010,7 @@ void trailer_info_get(struct trailer_info *info, const char *str, size_t nr = 0, alloc = 0; char **last = NULL; - ensure_configured(); + trailer_config_init(); end_of_log_message = find_end_of_log_message(str, opts->no_divider); trailer_block_start = find_trailer_block_start(str, end_of_log_message); @@ -1176,36 +1052,32 @@ void trailer_info_release(struct trailer_info *info) free(info->trailers); } -static void format_trailer_info(struct strbuf *out, - const struct trailer_info *info, - const char *msg, - const struct process_trailer_options *opts) +void format_trailers(const struct process_trailer_options *opts, + struct list_head *trailers, + struct strbuf *out) { size_t origlen = out->len; - size_t i; - - /* 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); - return; - } - - for (i = 0; i < info->trailer_nr; i++) { - char *trailer = info->trailers[i]; - ssize_t separator_pos = find_separator(trailer, separators); + struct list_head *pos; + struct trailer_item *item; - if (separator_pos >= 1) { + 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_addstr(&tok, item->token); + strbuf_addstr(&val, item->value); + + /* + * Skip key/value pairs where the value was empty. This + * can happen from trailers specified without a + * separator, like `--trailer "Reviewed-by"` (no + * corresponding value). + */ + if (opts->trim_empty && !strlen(item->value)) + continue; - parse_trailer(&tok, &val, NULL, trailer, separator_pos); if (!opts->filter || opts->filter(&tok, opts->filter_data)) { - if (opts->unfold) - unfold_value(&val); - if (opts->separator && out->len != origlen) strbuf_addbuf(out, opts->separator); if (!opts->value_only) @@ -1213,8 +1085,11 @@ static void format_trailer_info(struct strbuf *out, if (!opts->key_only && !opts->value_only) { if (opts->key_value_separator) strbuf_addbuf(out, opts->key_value_separator); - else - strbuf_addstr(out, ": "); + else { + char c = last_non_space_char(tok.buf); + if (c && !strchr(separators, c)) + strbuf_addf(out, "%c ", separators[0]); + } } if (!opts->key_only) strbuf_addbuf(out, &val); @@ -1228,22 +1103,34 @@ static void format_trailer_info(struct strbuf *out, if (opts->separator && out->len != origlen) { strbuf_addbuf(out, opts->separator); } - strbuf_addstr(out, trailer); - if (opts->separator) { + strbuf_addstr(out, item->value); + if (opts->separator) strbuf_rtrim(out); - } + else + strbuf_addch(out, '\n'); } } - } -void format_trailers_from_commit(struct strbuf *out, const char *msg, - const struct process_trailer_options *opts) +void format_trailers_from_commit(const struct process_trailer_options *opts, + const char *msg, + struct strbuf *out) { + LIST_HEAD(trailer_objects); struct trailer_info info; - trailer_info_get(&info, msg, opts); - format_trailer_info(out, &info, msg, opts); + parse_trailers(opts, &info, 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); + } else + format_trailers(opts, &trailer_objects, out); + + free_trailers(&trailer_objects); trailer_info_release(&info); } @@ -1253,7 +1140,7 @@ 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; - trailer_info_get(&iter->internal.info, msg, &opts); + trailer_info_get(&opts, msg, &iter->internal.info); iter->internal.cur = 0; } @@ -1270,6 +1157,7 @@ int trailer_iterator_advance(struct trailer_iterator *iter) strbuf_reset(&iter->val); parse_trailer(&iter->key, &iter->val, NULL, trailer, separator_pos); + /* Always unfold values during iteration. */ unfold_value(&iter->val); return 1; } @@ -81,28 +81,38 @@ struct process_trailer_options { #define PROCESS_TRAILER_OPTIONS_INIT {0} -void process_trailers(const char *file, - const struct process_trailer_options *opts, - struct list_head *new_trailer_head); +void parse_trailers_from_config(struct list_head *config_head); -void trailer_info_get(struct trailer_info *info, const char *str, - const struct process_trailer_options *opts); +void parse_trailers_from_command_line_args(struct list_head *arg_head, + struct list_head *new_trailer_head); + +void process_trailers_lists(struct list_head *head, + struct list_head *arg_head); + +void parse_trailers(const struct process_trailer_options *, + struct trailer_info *, + const char *str, + struct list_head *head); + +void trailer_info_get(const struct process_trailer_options *, + const char *str, + struct trailer_info *); void trailer_info_release(struct trailer_info *info); +void trailer_config_init(void); +void format_trailers(const struct process_trailer_options *, + struct list_head *trailers, + struct strbuf *out); +void free_trailers(struct list_head *); + /* - * Format the trailers from the commit msg "msg" into the strbuf "out". - * Note two caveats about "opts": - * - * - this is primarily a helper for pretty.c, and not - * all of the flags are supported. - * - * - this differs from process_trailers slightly in that we always format - * only the trailer block itself, even if the "only_trailers" option is not - * set. + * Convenience function to format the trailers from the commit msg "msg" into + * the strbuf "out". Reuses format_trailers() internally. */ -void format_trailers_from_commit(struct strbuf *out, const char *msg, - const struct process_trailer_options *opts); +void format_trailers_from_commit(const struct process_trailer_options *, + const char *msg, + struct strbuf *out); /* * An interface for iterating over the trailers found in a particular commit diff --git a/transport-helper.c b/transport-helper.c index dd6002b393..8d284b24d5 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -1078,7 +1078,7 @@ static int push_refs_with_export(struct transport *transport, set_common_push_options(transport, data->name, flags); if (flags & TRANSPORT_PUSH_FORCE) { if (set_helper_option(transport, "force", "true") != 0) - warning(_("helper %s does not support 'force'"), data->name); + warning(_("helper %s does not support '--force'"), data->name); } helper = get_helper(transport); @@ -1210,16 +1210,13 @@ static struct ref *get_refs_list_using_list(struct transport *transport, data->get_refs_list_called = 1; helper = get_helper(transport); - if (data->object_format) { - write_str_in_full(helper->in, "option object-format\n"); - if (recvline(data, &buf) || strcmp(buf.buf, "ok")) - exit(128); - } + if (data->object_format) + set_helper_option(transport, "object-format", "true"); if (data->push && for_push) - write_str_in_full(helper->in, "list for-push\n"); + write_constant(helper->in, "list for-push\n"); else - write_str_in_full(helper->in, "list\n"); + write_constant(helper->in, "list\n"); while (1) { char *eov, *eon; diff --git a/tree-walk.c b/tree-walk.c index b517792ba2..6565d9ad99 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -11,35 +11,19 @@ #include "json-writer.h" #include "environment.h" -static const char *get_mode(const char *str, unsigned int *modep) -{ - unsigned char c; - unsigned int mode = 0; - - if (*str == ' ') - return NULL; - - while ((c = *str++) != ' ') { - if (c < '0' || c > '7') - return NULL; - mode = (mode << 3) + (c - '0'); - } - *modep = mode; - return str; -} - static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned long size, struct strbuf *err) { const char *path; - unsigned int mode, len; - const unsigned hashsz = the_hash_algo->rawsz; + unsigned int len; + uint16_t mode; + const unsigned hashsz = desc->algo->rawsz; if (size < hashsz + 3 || buf[size - (hashsz + 1)]) { strbuf_addstr(err, _("too-short tree object")); return -1; } - path = get_mode(buf, &mode); + path = parse_mode(buf, &mode); if (!path) { strbuf_addstr(err, _("malformed mode in tree entry")); return -1; @@ -54,15 +38,19 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l desc->entry.path = path; desc->entry.mode = (desc->flags & TREE_DESC_RAW_MODES) ? mode : canon_mode(mode); desc->entry.pathlen = len - 1; - oidread(&desc->entry.oid, (const unsigned char *)path + len); + oidread_algop(&desc->entry.oid, (const unsigned char *)path + len, + desc->algo); return 0; } -static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, - unsigned long size, struct strbuf *err, +static int init_tree_desc_internal(struct tree_desc *desc, + const struct object_id *oid, + const void *buffer, unsigned long size, + struct strbuf *err, enum tree_desc_flags flags) { + desc->algo = (oid && oid->algo) ? &hash_algos[oid->algo] : the_hash_algo; desc->buffer = buffer; desc->size = size; desc->flags = flags; @@ -71,19 +59,21 @@ static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, return 0; } -void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size) +void init_tree_desc(struct tree_desc *desc, const struct object_id *tree_oid, + const void *buffer, unsigned long size) { struct strbuf err = STRBUF_INIT; - if (init_tree_desc_internal(desc, buffer, size, &err, 0)) + if (init_tree_desc_internal(desc, tree_oid, buffer, size, &err, 0)) die("%s", err.buf); strbuf_release(&err); } -int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size, +int init_tree_desc_gently(struct tree_desc *desc, const struct object_id *oid, + const void *buffer, unsigned long size, enum tree_desc_flags flags) { struct strbuf err = STRBUF_INIT; - int result = init_tree_desc_internal(desc, buffer, size, &err, flags); + int result = init_tree_desc_internal(desc, oid, buffer, size, &err, flags); if (result) error("%s", err.buf); strbuf_release(&err); @@ -100,9 +90,9 @@ void *fill_tree_descriptor(struct repository *r, if (oid) { buf = read_object_with_reference(r, oid, OBJ_TREE, &size, NULL); if (!buf) - die("unable to read tree %s", oid_to_hex(oid)); + die(_("unable to read tree (%s)"), oid_to_hex(oid)); } - init_tree_desc(desc, buf, size); + init_tree_desc(desc, oid, buf, size); return buf; } @@ -119,7 +109,7 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a) static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err) { const void *buf = desc->buffer; - const unsigned char *end = (const unsigned char *)desc->entry.path + desc->entry.pathlen + 1 + the_hash_algo->rawsz; + const unsigned char *end = (const unsigned char *)desc->entry.path + desc->entry.pathlen + 1 + desc->algo->rawsz; unsigned long size = desc->size; unsigned long len = end - (const unsigned char *)buf; @@ -633,7 +623,7 @@ int get_tree_entry(struct repository *r, retval = -1; } else { struct tree_desc t; - init_tree_desc(&t, tree, size); + init_tree_desc(&t, tree_oid, tree, size); retval = find_tree_entry(r, &t, name, oid, mode); } free(tree); @@ -676,7 +666,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r, struct tree_desc t; int follows_remaining = GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS; - init_tree_desc(&t, NULL, 0UL); + init_tree_desc(&t, NULL, NULL, 0UL); strbuf_addstr(&namebuf, name); oidcpy(¤t_tree_oid, tree_oid); @@ -712,7 +702,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r, goto done; /* descend */ - init_tree_desc(&t, tree, size); + init_tree_desc(&t, ¤t_tree_oid, tree, size); } /* Handle symlinks to e.g. a//b by removing leading slashes */ @@ -746,7 +736,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r, free(parent->tree); parents_nr--; parent = &parents[parents_nr - 1]; - init_tree_desc(&t, parent->tree, parent->size); + init_tree_desc(&t, &parent->oid, parent->tree, parent->size); strbuf_remove(&namebuf, 0, remainder ? 3 : 2); continue; } @@ -826,7 +816,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r, contents_start = contents; parent = &parents[parents_nr - 1]; - init_tree_desc(&t, parent->tree, parent->size); + init_tree_desc(&t, &parent->oid, parent->tree, parent->size); strbuf_splice(&namebuf, 0, len, contents_start, link_len); if (remainder) diff --git a/tree-walk.h b/tree-walk.h index a6bfa3da3a..0b1067fbc5 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -24,6 +24,7 @@ struct name_entry { * A semi-opaque data structure used to maintain the current state of the walk. */ struct tree_desc { + const struct git_hash_algo *algo; /* * pointer into the memory representation of the tree. It always * points at the current entry being visited. @@ -83,9 +84,11 @@ int update_tree_entry_gently(struct tree_desc *); * size parameters are assumed to be the same as the buffer and size * members of `struct tree`. */ -void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size); +void init_tree_desc(struct tree_desc *desc, const struct object_id *tree_oid, + const void *buf, unsigned long size); -int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size, +int init_tree_desc_gently(struct tree_desc *desc, const struct object_id *oid, + const void *buf, unsigned long size, enum tree_desc_flags flags); /* @@ -29,7 +29,7 @@ int read_tree_at(struct repository *r, if (parse_tree(tree)) return -1; - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (retval != all_entries_interesting) { diff --git a/upload-pack.c b/upload-pack.c index 2537affa90..902144b9d3 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -28,6 +28,7 @@ #include "shallow.h" #include "write-or-die.h" #include "json-writer.h" +#include "strmap.h" /* Remember to update object flag allocation in object.h */ #define THEY_HAVE (1u << 11) @@ -61,12 +62,11 @@ struct upload_pack_data { struct string_list symref; /* v0 only */ struct object_array want_obj; struct object_array have_obj; - struct oid_array haves; /* v2 only */ - struct string_list wanted_refs; /* v2 only */ + struct strmap wanted_refs; /* v2 only */ struct strvec hidden_refs; struct object_array shallows; - struct string_list deepen_not; + struct oidset deepen_not; struct object_array extra_edge_obj; int depth; timestamp_t deepen_since; @@ -113,6 +113,8 @@ struct upload_pack_data { unsigned done : 1; /* v2 only */ unsigned allow_ref_in_want : 1; /* v2 only */ unsigned allow_sideband_all : 1; /* v2 only */ + unsigned seen_haves : 1; /* v2 only */ + unsigned allow_packfile_uris : 1; /* v2 only */ unsigned advertise_sid : 1; unsigned sent_capabilities : 1; }; @@ -120,13 +122,12 @@ struct upload_pack_data { static void upload_pack_data_init(struct upload_pack_data *data) { struct string_list symref = STRING_LIST_INIT_DUP; - struct string_list wanted_refs = STRING_LIST_INIT_DUP; + struct strmap wanted_refs = STRMAP_INIT; struct strvec hidden_refs = STRVEC_INIT; struct object_array want_obj = OBJECT_ARRAY_INIT; struct object_array have_obj = OBJECT_ARRAY_INIT; - struct oid_array haves = OID_ARRAY_INIT; struct object_array shallows = OBJECT_ARRAY_INIT; - struct string_list deepen_not = STRING_LIST_INIT_DUP; + struct oidset deepen_not = OID_ARRAY_INIT; struct string_list uri_protocols = STRING_LIST_INIT_DUP; struct object_array extra_edge_obj = OBJECT_ARRAY_INIT; struct string_list allowed_filters = STRING_LIST_INIT_DUP; @@ -137,7 +138,6 @@ static void upload_pack_data_init(struct upload_pack_data *data) data->hidden_refs = hidden_refs; data->want_obj = want_obj; data->have_obj = have_obj; - data->haves = haves; data->shallows = shallows; data->deepen_not = deepen_not; data->uri_protocols = uri_protocols; @@ -155,13 +155,12 @@ static void upload_pack_data_init(struct upload_pack_data *data) static void upload_pack_data_clear(struct upload_pack_data *data) { string_list_clear(&data->symref, 1); - string_list_clear(&data->wanted_refs, 1); + strmap_clear(&data->wanted_refs, 1); strvec_clear(&data->hidden_refs); object_array_clear(&data->want_obj); object_array_clear(&data->have_obj); - oid_array_clear(&data->haves); object_array_clear(&data->shallows); - string_list_clear(&data->deepen_not, 0); + oidset_clear(&data->deepen_not); object_array_clear(&data->extra_edge_obj); list_objects_filter_release(&data->filter_options); string_list_clear(&data->allowed_filters, 0); @@ -463,7 +462,7 @@ static void create_pack_file(struct upload_pack_data *pack_data, fail: free(output_state); - send_client_data(3, abort_msg, sizeof(abort_msg), + send_client_data(3, abort_msg, strlen(abort_msg), pack_data->use_sideband); die("git upload-pack: %s", abort_msg); } @@ -471,7 +470,9 @@ static void create_pack_file(struct upload_pack_data *pack_data, static int do_got_oid(struct upload_pack_data *data, const struct object_id *oid) { int we_knew_they_have = 0; - struct object *o = parse_object(the_repository, oid); + struct object *o = parse_object_with_flags(the_repository, oid, + PARSE_OBJECT_SKIP_HASH_CHECK | + PARSE_OBJECT_DISCARD_TREE); if (!o) die("oops (%s)", oid_to_hex(oid)); @@ -528,8 +529,6 @@ static int get_common_commits(struct upload_pack_data *data, int got_other = 0; int sent_ready = 0; - save_commit_buffer = 0; - for (;;) { const char *arg; @@ -926,12 +925,13 @@ static int send_shallow_list(struct upload_pack_data *data) strvec_push(&av, "rev-list"); if (data->deepen_since) strvec_pushf(&av, "--max-age=%"PRItime, data->deepen_since); - if (data->deepen_not.nr) { + if (oidset_size(&data->deepen_not)) { + const struct object_id *oid; + struct oidset_iter iter; strvec_push(&av, "--not"); - for (i = 0; i < data->deepen_not.nr; i++) { - struct string_list_item *s = data->deepen_not.items + i; - strvec_push(&av, s->string); - } + oidset_iter_init(&data->deepen_not, &iter); + while ((oid = oidset_iter_next(&iter))) + strvec_push(&av, oid_to_hex(oid)); strvec_push(&av, "--not"); } for (i = 0; i < data->want_obj.nr; i++) { @@ -1007,7 +1007,7 @@ static int process_deepen_since(const char *line, timestamp_t *deepen_since, int return 0; } -static int process_deepen_not(const char *line, struct string_list *deepen_not, int *deepen_rev_list) +static int process_deepen_not(const char *line, struct oidset *deepen_not, int *deepen_rev_list) { const char *arg; if (skip_prefix(line, "deepen-not ", &arg)) { @@ -1015,7 +1015,7 @@ static int process_deepen_not(const char *line, struct string_list *deepen_not, struct object_id oid; if (expand_ref(the_repository, arg, strlen(arg), &oid, &ref) != 1) die("git upload-pack: ambiguous deepen-not: %s", line); - string_list_append(deepen_not, ref); + oidset_insert(deepen_not, &oid); free(ref); *deepen_rev_list = 1; return 1; @@ -1151,7 +1151,9 @@ static void receive_needs(struct upload_pack_data *data, free(client_sid); } - o = parse_object(the_repository, &oid_buf); + o = parse_object_with_flags(the_repository, &oid_buf, + PARSE_OBJECT_SKIP_HASH_CHECK | + PARSE_OBJECT_DISCARD_TREE); if (!o) { packet_writer_error(&data->writer, "upload-pack: not our ref %s", @@ -1362,6 +1364,9 @@ static int upload_pack_config(const char *var, const char *value, data->allow_ref_in_want = git_config_bool(var, value); } else if (!strcmp("uploadpack.allowsidebandall", var)) { data->allow_sideband_all = git_config_bool(var, value); + } else if (!strcmp("uploadpack.blobpackfileuri", var)) { + if (value) + data->allow_packfile_uris = 1; } else if (!strcmp("core.precomposeunicode", var)) { precomposed_unicode = git_config_bool(var, value); } else if (!strcmp("transfer.advertisesid", var)) { @@ -1385,10 +1390,13 @@ static int upload_pack_protected_config(const char *var, const char *value, return 0; } -static void get_upload_pack_config(struct upload_pack_data *data) +static void get_upload_pack_config(struct repository *r, + struct upload_pack_data *data) { - git_config(upload_pack_config, data); + repo_config(r, upload_pack_config, data); git_protected_config(upload_pack_protected_config, data); + + data->allow_sideband_all |= git_env_bool("GIT_TEST_SIDEBAND_ALL", 0); } void upload_pack(const int advertise_refs, const int stateless_rpc, @@ -1398,7 +1406,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc, struct upload_pack_data data; upload_pack_data_init(&data); - get_upload_pack_config(&data); + get_upload_pack_config(the_repository, &data); data.stateless_rpc = stateless_rpc; data.timeout = timeout; @@ -1468,7 +1476,8 @@ static int parse_want(struct packet_writer *writer, const char *line, "expected to get oid, not '%s'", line); o = parse_object_with_flags(the_repository, &oid, - PARSE_OBJECT_SKIP_HASH_CHECK); + PARSE_OBJECT_SKIP_HASH_CHECK | + PARSE_OBJECT_DISCARD_TREE); if (!o) { packet_writer_error(writer, @@ -1490,14 +1499,13 @@ static int parse_want(struct packet_writer *writer, const char *line, } static int parse_want_ref(struct packet_writer *writer, const char *line, - struct string_list *wanted_refs, + struct strmap *wanted_refs, struct strvec *hidden_refs, struct object_array *want_obj) { const char *refname_nons; if (skip_prefix(line, "want-ref ", &refname_nons)) { struct object_id oid; - struct string_list_item *item; struct object *o = NULL; struct strbuf refname = STRBUF_INIT; @@ -1509,8 +1517,11 @@ static int parse_want_ref(struct packet_writer *writer, const char *line, } strbuf_release(&refname); - item = string_list_append(wanted_refs, refname_nons); - item->util = oiddup(&oid); + if (strmap_put(wanted_refs, refname_nons, oiddup(&oid))) { + packet_writer_error(writer, "duplicate want-ref %s", + refname_nons); + die("duplicate want-ref %s", refname_nons); + } if (!starts_with(refname_nons, "refs/tags/")) { struct commit *commit = lookup_commit_in_graph(the_repository, &oid); @@ -1532,15 +1543,14 @@ static int parse_want_ref(struct packet_writer *writer, const char *line, return 0; } -static int parse_have(const char *line, struct oid_array *haves) +static int parse_have(const char *line, struct upload_pack_data *data) { const char *arg; if (skip_prefix(line, "have ", &arg)) { struct object_id oid; - if (get_oid_hex(arg, &oid)) - die("git upload-pack: expected SHA1 object, got '%s'", arg); - oid_array_append(haves, &oid); + got_oid(data, arg, &oid); + data->seen_haves = 1; return 1; } @@ -1552,13 +1562,13 @@ static void trace2_fetch_info(struct upload_pack_data *data) struct json_writer jw = JSON_WRITER_INIT; jw_object_begin(&jw, 0); - jw_object_intmax(&jw, "haves", data->haves.nr); + jw_object_intmax(&jw, "haves", data->have_obj.nr); jw_object_intmax(&jw, "wants", data->want_obj.nr); - jw_object_intmax(&jw, "want-refs", data->wanted_refs.nr); + jw_object_intmax(&jw, "want-refs", strmap_get_size(&data->wanted_refs)); jw_object_intmax(&jw, "depth", data->depth); jw_object_intmax(&jw, "shallows", data->shallows.nr); jw_object_bool(&jw, "deepen-since", data->deepen_since); - jw_object_intmax(&jw, "deepen-not", data->deepen_not.nr); + jw_object_intmax(&jw, "deepen-not", oidset_size(&data->deepen_not)); jw_object_bool(&jw, "deepen-relative", data->deepen_relative); if (data->filter_options.choice) jw_object_string(&jw, "filter", list_object_filter_config_name(data->filter_options.choice)); @@ -1586,7 +1596,7 @@ static void process_args(struct packet_reader *request, &data->hidden_refs, &data->want_obj)) continue; /* process have line */ - if (parse_have(arg, &data->haves)) + if (parse_have(arg, data)) continue; /* process args like thin-pack */ @@ -1638,14 +1648,17 @@ static void process_args(struct packet_reader *request, continue; } - if ((git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) || - data->allow_sideband_all) && + if (data->allow_sideband_all && !strcmp(arg, "sideband-all")) { data->writer.use_sideband = 1; continue; } - if (skip_prefix(arg, "packfile-uris ", &p)) { + if (data->allow_packfile_uris && + skip_prefix(arg, "packfile-uris ", &p)) { + if (data->uri_protocols.nr) + send_err_and_die(data, + "multiple packfile-uris lines forbidden"); string_list_split(&data->uri_protocols, p, ',', -1); continue; } @@ -1664,27 +1677,7 @@ static void process_args(struct packet_reader *request, trace2_fetch_info(data); } -static int process_haves(struct upload_pack_data *data, struct oid_array *common) -{ - int i; - - /* Process haves */ - for (i = 0; i < data->haves.nr; i++) { - const struct object_id *oid = &data->haves.oid[i]; - - if (!repo_has_object_file_with_flags(the_repository, oid, - OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT)) - continue; - - oid_array_append(common, oid); - - do_got_oid(data, oid); - } - - return 0; -} - -static int send_acks(struct upload_pack_data *data, struct oid_array *acks) +static int send_acks(struct upload_pack_data *data, struct object_array *acks) { int i; @@ -1696,7 +1689,7 @@ static int send_acks(struct upload_pack_data *data, struct oid_array *acks) for (i = 0; i < acks->nr; i++) { packet_writer_write(&data->writer, "ACK %s\n", - oid_to_hex(&acks->oid[i])); + oid_to_hex(&acks->objects[i].item->oid)); } if (!data->wait_for_done && ok_to_give_up(data)) { @@ -1710,13 +1703,11 @@ static int send_acks(struct upload_pack_data *data, struct oid_array *acks) static int process_haves_and_send_acks(struct upload_pack_data *data) { - struct oid_array common = OID_ARRAY_INIT; int ret = 0; - process_haves(data, &common); if (data->done) { ret = 1; - } else if (send_acks(data, &common)) { + } else if (send_acks(data, &data->have_obj)) { packet_writer_delim(&data->writer); ret = 1; } else { @@ -1725,24 +1716,23 @@ static int process_haves_and_send_acks(struct upload_pack_data *data) ret = 0; } - oid_array_clear(&data->haves); - oid_array_clear(&common); return ret; } static void send_wanted_ref_info(struct upload_pack_data *data) { - const struct string_list_item *item; + struct hashmap_iter iter; + const struct strmap_entry *e; - if (!data->wanted_refs.nr) + if (strmap_empty(&data->wanted_refs)) return; packet_writer_write(&data->writer, "wanted-refs\n"); - for_each_string_list_item(item, &data->wanted_refs) { + strmap_for_each_entry(&data->wanted_refs, &iter, e) { packet_writer_write(&data->writer, "%s %s\n", - oid_to_hex(item->util), - item->string); + oid_to_hex(e->value), + e->key); } packet_writer_delim(&data->writer); @@ -1771,7 +1761,7 @@ enum fetch_state { FETCH_DONE, }; -int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) +int upload_pack_v2(struct repository *r, struct packet_reader *request) { enum fetch_state state = FETCH_PROCESS_ARGS; struct upload_pack_data data; @@ -1780,7 +1770,7 @@ int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) upload_pack_data_init(&data); data.use_sideband = LARGE_PACKET_MAX; - get_upload_pack_config(&data); + get_upload_pack_config(r, &data); while (state != FETCH_DONE) { switch (state) { @@ -1796,7 +1786,7 @@ int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) * they didn't want anything. */ state = FETCH_DONE; - } else if (data.haves.nr) { + } else if (data.seen_haves) { /* * Request had 'have' lines, so lets ACK them. */ @@ -1839,41 +1829,28 @@ int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request) int upload_pack_advertise(struct repository *r, struct strbuf *value) { - if (value) { - int allow_filter_value; - int allow_ref_in_want; - int allow_sideband_all_value; - char *str = NULL; + struct upload_pack_data data; + upload_pack_data_init(&data); + get_upload_pack_config(r, &data); + + if (value) { strbuf_addstr(value, "shallow wait-for-done"); - if (!repo_config_get_bool(r, - "uploadpack.allowfilter", - &allow_filter_value) && - allow_filter_value) + if (data.allow_filter) strbuf_addstr(value, " filter"); - if (!repo_config_get_bool(r, - "uploadpack.allowrefinwant", - &allow_ref_in_want) && - allow_ref_in_want) + if (data.allow_ref_in_want) strbuf_addstr(value, " ref-in-want"); - if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) || - (!repo_config_get_bool(r, - "uploadpack.allowsidebandall", - &allow_sideband_all_value) && - allow_sideband_all_value)) + if (data.allow_sideband_all) strbuf_addstr(value, " sideband-all"); - if (!repo_config_get_string(r, - "uploadpack.blobpackfileuri", - &str) && - str) { + if (data.allow_packfile_uris) strbuf_addstr(value, " packfile-uris"); - free(str); - } } + upload_pack_data_clear(&data); + return 1; } @@ -19,8 +19,11 @@ static void vreportf(const char *prefix, const char *err, va_list params) } memcpy(msg, prefix, prefix_len); p = msg + prefix_len; - if (vsnprintf(p, pend - p, err, params) < 0) + if (vsnprintf(p, pend - p, err, params) < 0) { + fprintf(stderr, _("error: unable to format message: %s\n"), + err); *p = '\0'; /* vsnprintf() failed, clip at prefix */ + } for (; p != pend - 1 && *p; p++) { if (iscntrl(*p) && *p != '\t' && *p != '\n') diff --git a/userdiff.c b/userdiff.c index e399543823..82bc76b910 100644 --- a/userdiff.c +++ b/userdiff.c @@ -3,6 +3,7 @@ #include "userdiff.h" #include "attr.h" #include "strbuf.h" +#include "environment.h" static struct userdiff_driver *drivers; static int ndrivers; @@ -89,12 +90,48 @@ PATTERNS("cpp", "|\\.[0-9][0-9]*([Ee][-+]?[0-9]+)?[fFlL]?" "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->\\*?|\\.\\*|<=>"), PATTERNS("csharp", - /* Keywords */ - "!^[ \t]*(do|while|for|if|else|instanceof|new|return|switch|case|throw|catch|using)\n" - /* Methods and constructors */ - "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe|async)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[<>@._[:alnum:]]+[ \t]*\\(.*\\))[ \t]*$\n" - /* Properties */ - "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[@._[:alnum:]]+)[ \t]*$\n" + /* + * Jump over reserved keywords which are illegal method names, but which + * can be followed by parentheses without special characters in between, + * making them look like methods. + */ + "!(^|[ \t]+)" /* Start of line or whitespace. */ + "(do|while|for|foreach|if|else|new|default|return|switch|case|throw" + "|catch|using|lock|fixed)" + "([ \t(]+|$)\n" /* Whitespace, "(", or end of line. */ + /* + * Methods/constructors: + * The strategy is to identify a minimum of two groups (any combination + * of keywords/type/name) before the opening parenthesis, and without + * final unexpected characters, normally only used in ordinary statements. + */ + "^[ \t]*" /* Remove leading whitespace. */ + "(" /* Start chunk header capture. */ + "(" /* First group. */ + "[][[:alnum:]@_.]" /* Name. */ + "(<[][[:alnum:]@_, \t<>]+>)?" /* Optional generic parameters. */ + ")+" + "([ \t]+" /* Subsequent groups, prepended with space. */ + "([][[:alnum:]@_.](<[][[:alnum:]@_, \t<>]+>)?)+" + ")+" + "[ \t]*" /* Optional space before parameters start. */ + "\\(" /* Start of method parameters. */ + "[^;]*" /* Allow complex parameters, but exclude statements (;). */ + ")$\n" /* Close chunk header capture. */ + /* + * Properties: + * As with methods, expect a minimum of two groups. But, more trivial than + * methods, the vast majority of properties long enough to be worth + * showing a chunk header for don't include "=:;,()" on the line they are + * defined, since they don't have a parameter list. + */ + "^[ \t]*(" + "([][[:alnum:]@_.](<[][[:alnum:]@_, \t<>]+>)?)+" + "([ \t]+" + "([][[:alnum:]@_.](<[][[:alnum:]@_, \t<>]+>)?)+" + ")+" /* Up to here, same as methods regex. */ + "[^;=:,()]*" /* Compared to methods, no parameter list allowed. */ + ")$\n" /* Type definitions */ "^[ \t]*(((static|public|internal|private|protected|new|unsafe|sealed|abstract|partial)[ \t]+)*(class|enum|interface|struct|record)[ \t]+.*)$\n" /* Namespace */ @@ -323,8 +360,7 @@ static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver, { struct find_by_namelen_data *cb_data = priv; - if (!strncmp(driver->name, cb_data->name, cb_data->len) && - !driver->name[cb_data->len]) { + if (!xstrncmpz(driver->name, cb_data->name, cb_data->len)) { cb_data->driver = driver; return 1; /* tell the caller to stop iterating */ } @@ -460,7 +496,8 @@ struct userdiff_driver *userdiff_get_textconv(struct repository *r, if (!driver->textconv) return NULL; - if (driver->textconv_want_cache && !driver->textconv_cache) { + if (driver->textconv_want_cache && !driver->textconv_cache && + have_git_dir()) { struct notes_cache *c = xmalloc(sizeof(*c)); struct strbuf name = STRBUF_INIT; @@ -45,7 +45,7 @@ static int process_tree(struct walker *walker, struct tree *tree) if (parse_tree(tree)) return -1; - init_tree_desc(&desc, tree->buffer, tree->size); + init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { struct object *obj = NULL; diff --git a/worktree.c b/worktree.c index b02a05a74a..cf5eea8c93 100644 --- a/worktree.c +++ b/worktree.c @@ -807,9 +807,9 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, static int move_config_setting(const char *key, const char *value, const char *from_file, const char *to_file) { - if (git_config_set_in_file_gently(to_file, key, value)) + if (git_config_set_in_file_gently(to_file, key, NULL, value)) return error(_("unable to set %s in '%s'"), key, to_file); - if (git_config_set_in_file_gently(from_file, key, NULL)) + if (git_config_set_in_file_gently(from_file, key, NULL, NULL)) return error(_("unable to unset %s in '%s'"), key, from_file); return 0; } @@ -670,7 +670,7 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...) va_end(ap); if (len < 0) - BUG("your snprintf is broken"); + die(_("unable to format message: %s"), fmt); if (len >= max) BUG("attempt to snprintf into too-small buffer"); return len; diff --git a/wt-status.c b/wt-status.c index b5a29083df..bdfc23e2ae 100644 --- a/wt-status.c +++ b/wt-status.c @@ -70,7 +70,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color, strbuf_vaddf(&sb, fmt, ap); if (!sb.len) { if (s->display_comment_prefix) { - strbuf_addch(&sb, comment_line_char); + strbuf_addstr(&sb, comment_line_str); if (!trail) strbuf_addch(&sb, ' '); } @@ -85,7 +85,7 @@ static void status_vprintf(struct wt_status *s, int at_bol, const char *color, strbuf_reset(&linebuf); if (at_bol && s->display_comment_prefix) { - strbuf_addch(&linebuf, comment_line_char); + strbuf_addstr(&linebuf, comment_line_str); if (*line != '\n' && *line != '\t') strbuf_addch(&linebuf, ' '); } @@ -1028,7 +1028,7 @@ static void wt_longstatus_print_submodule_summary(struct wt_status *s, int uncom if (s->display_comment_prefix) { size_t len; summary_content = strbuf_detach(&summary, &len); - strbuf_add_commented_lines(&summary, summary_content, len, comment_line_char); + strbuf_add_commented_lines(&summary, summary_content, len, comment_line_str); free(summary_content); } @@ -1090,11 +1090,14 @@ size_t wt_status_locate_end(const char *s, size_t len) const char *p; struct strbuf pattern = STRBUF_INIT; - strbuf_addf(&pattern, "\n%c %s", comment_line_char, cut_line); + strbuf_addf(&pattern, "\n%s %s", comment_line_str, cut_line); if (starts_with(s, pattern.buf + 1)) len = 0; - else if ((p = strstr(s, pattern.buf))) - len = p - s + 1; + else if ((p = strstr(s, pattern.buf))) { + size_t newlen = p - s + 1; + if (newlen < len) + len = newlen; + } strbuf_release(&pattern); return len; } @@ -1103,16 +1106,19 @@ void wt_status_append_cut_line(struct strbuf *buf) { const char *explanation = _("Do not modify or remove the line above.\nEverything below it will be ignored."); - strbuf_commented_addf(buf, comment_line_char, "%s", cut_line); - strbuf_add_commented_lines(buf, explanation, strlen(explanation), comment_line_char); + strbuf_commented_addf(buf, comment_line_str, "%s", cut_line); + strbuf_add_commented_lines(buf, explanation, strlen(explanation), comment_line_str); } -void wt_status_add_cut_line(FILE *fp) +void wt_status_add_cut_line(struct wt_status *s) { struct strbuf buf = STRBUF_INIT; + if (s->added_cut_line) + return; + s->added_cut_line = 1; wt_status_append_cut_line(&buf); - fputs(buf.buf, fp); + fputs(buf.buf, s->fp); strbuf_release(&buf); } @@ -1143,11 +1149,12 @@ static void wt_longstatus_print_verbose(struct wt_status *s) * file (and even the "auto" setting won't work, since it * will have checked isatty on stdout). But we then do want * to insert the scissor line here to reliably remove the - * diff before committing. + * diff before committing, if we didn't already include one + * before. */ if (s->fp != stdout) { rev.diffopt.use_color = 0; - wt_status_add_cut_line(s->fp); + wt_status_add_cut_line(s); } if (s->verbose > 1 && s->committable) { /* print_updated() printed a header, so do we */ @@ -1176,8 +1183,6 @@ static void wt_longstatus_print_tracking(struct wt_status *s) struct strbuf sb = STRBUF_INIT; const char *cp, *ep, *branch_name; struct branch *branch; - char comment_line_string[3]; - int i; uint64_t t_begin = 0; assert(s->branch && !s->is_initial); @@ -1202,20 +1207,15 @@ static void wt_longstatus_print_tracking(struct wt_status *s) } } - i = 0; - if (s->display_comment_prefix) { - comment_line_string[i++] = comment_line_char; - comment_line_string[i++] = ' '; - } - comment_line_string[i] = '\0'; - for (cp = sb.buf; (ep = strchr(cp, '\n')) != NULL; cp = ep + 1) color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), - "%s%.*s", comment_line_string, + "%s%s%.*s", + s->display_comment_prefix ? comment_line_str : "", + s->display_comment_prefix ? " " : "", (int)(ep - cp), cp); if (s->display_comment_prefix) - color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "%c", - comment_line_char); + color_fprintf_ln(s->fp, color(WT_STATUS_HEADER, s), "%s", + comment_line_str); else fputs("\n", s->fp); strbuf_release(&sb); @@ -1382,7 +1382,7 @@ static int read_rebase_todolist(const char *fname, struct string_list *lines) git_path("%s", fname)); } while (!strbuf_getline_lf(&line, f)) { - if (line.len && line.buf[0] == comment_line_char) + if (starts_with(line.buf, comment_line_str)) continue; strbuf_trim(&line); if (!line.len) diff --git a/wt-status.h b/wt-status.h index 819dcad723..4e377ce62b 100644 --- a/wt-status.h +++ b/wt-status.h @@ -23,7 +23,8 @@ enum color_wt_status { }; enum untracked_status_type { - SHOW_NO_UNTRACKED_FILES, + SHOW_UNTRACKED_FILES_ERROR = -1, + SHOW_NO_UNTRACKED_FILES = 0, SHOW_NORMAL_UNTRACKED_FILES, SHOW_ALL_UNTRACKED_FILES }; @@ -130,6 +131,7 @@ struct wt_status { int rename_score; int rename_limit; enum wt_status_format status_format; + unsigned char added_cut_line; /* boolean */ struct wt_status_state state; struct object_id oid_commit; /* when not Initial */ @@ -147,7 +149,7 @@ struct wt_status { size_t wt_status_locate_end(const char *s, size_t len); void wt_status_append_cut_line(struct strbuf *buf); -void wt_status_add_cut_line(FILE *fp); +void wt_status_add_cut_line(struct wt_status *s); void wt_status_prepare(struct repository *r, struct wt_status *s); void wt_status_print(struct wt_status *s); void wt_status_collect(struct wt_status *s); diff --git a/xdiff-interface.c b/xdiff-interface.c index 3162f51743..16ed8ac492 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -305,6 +305,22 @@ int xdiff_compare_lines(const char *l1, long s1, return xdl_recmatch(l1, s1, l2, s2, flags); } +int parse_conflict_style_name(const char *value) +{ + if (!strcmp(value, "diff3")) + return XDL_MERGE_DIFF3; + else if (!strcmp(value, "zdiff3")) + return XDL_MERGE_ZEALOUS_DIFF3; + else if (!strcmp(value, "merge")) + return 0; + /* + * Please update _git_checkout() in git-completion.bash when + * you add new merge config + */ + else + return -1; +} + int git_xmerge_style = -1; int git_xmerge_config(const char *var, const char *value, @@ -313,17 +329,8 @@ int git_xmerge_config(const char *var, const char *value, if (!strcmp(var, "merge.conflictstyle")) { if (!value) return config_error_nonbool(var); - if (!strcmp(value, "diff3")) - git_xmerge_style = XDL_MERGE_DIFF3; - else if (!strcmp(value, "zdiff3")) - git_xmerge_style = XDL_MERGE_ZEALOUS_DIFF3; - else if (!strcmp(value, "merge")) - git_xmerge_style = 0; - /* - * Please update _git_checkout() in - * git-completion.bash when you add new merge config - */ - else + git_xmerge_style = parse_conflict_style_name(value); + if (git_xmerge_style == -1) return error(_("unknown style '%s' given for '%s'"), value, var); return 0; diff --git a/xdiff-interface.h b/xdiff-interface.h index e6f80df046..38537169b7 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -51,6 +51,7 @@ int buffer_is_binary(const char *ptr, unsigned long size); void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags); void xdiff_clear_find_func(xdemitconf_t *xecfg); struct config_context; +int parse_conflict_style_name(const char *value); int git_xmerge_config(const char *var, const char *value, const struct config_context *ctx, void *cb); extern int git_xmerge_style; |