diff options
760 files changed, 57580 insertions, 25856 deletions
diff --git a/.gitattributes b/.gitattributes index c6a0b35116..32583149c2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,6 +13,7 @@ CODE_OF_CONDUCT.md -whitespace /mergetools/* text eol=lf /t/oid-info/* text eol=lf /Documentation/git-merge.adoc conflict-marker-size=32 +/Documentation/git-merge-file.adoc conflict-marker-size=32 /Documentation/gitk.adoc conflict-marker-size=32 /Documentation/user-manual.adoc conflict-marker-size=32 /t/t????-*.sh conflict-marker-size=32 diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 124301dbbe..01a0437b2f 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -147,9 +147,13 @@ jobs: key: cov-build-${{ env.COVERITY_LANGUAGE }}-${{ env.COVERITY_PLATFORM }}-${{ steps.lookup.outputs.hash }} - name: build with cov-build run: | - export PATH="$RUNNER_TEMP/cov-analysis/bin:$PATH" && + export PATH="$PATH:$RUNNER_TEMP/cov-analysis/bin" && cov-configure --gcc && - cov-build --dir cov-int make + if ! cov-build --dir cov-int make + then + cat cov-int/build-log.txt + exit 1 + fi - name: package the build run: tar -czvf cov-int.tgz cov-int - name: submit the build to Coverity Scan diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1c8260ecb6..7dbf9f7f12 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -265,7 +265,7 @@ jobs: run: pip install meson ninja - name: Setup shell: pwsh - run: meson setup build -Dperl=disabled -Dcredential_helpers=wincred + run: meson setup build --vsenv -Dbuildtype=release -Dperl=disabled -Dcredential_helpers=wincred - name: Compile shell: pwsh run: meson compile -C build @@ -349,6 +349,7 @@ jobs: if: needs.ci-config.outputs.enabled == 'yes' env: CC: clang + CI_JOB_IMAGE: ubuntu-latest runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -407,12 +408,27 @@ jobs: jobname: ${{matrix.vector.jobname}} CC: ${{matrix.vector.cc}} CI_JOB_IMAGE: ${{matrix.vector.image}} + CUSTOM_PATH: /custom runs-on: ubuntu-latest container: ${{matrix.vector.image}} steps: - name: prepare libc6 for actions if: matrix.vector.jobname == 'linux32' run: apt -q update && apt -q -y install libc6-amd64 lib64stdc++6 + - name: install git in container + run: | + if command -v git + then + : # nothing to do + elif command -v apk + then + apk add --update git + elif command -v dnf + then + dnf -yq update && dnf -yq install git + else + apt-get -q update && apt-get -q -y install git + fi - uses: actions/checkout@v4 - run: ci/install-dependencies.sh - run: useradd builder --create-home @@ -432,6 +448,7 @@ jobs: if: needs.ci-config.outputs.enabled == 'yes' env: jobname: StaticAnalysis + CI_JOB_IMAGE: ubuntu-22.04 runs-on: ubuntu-22.04 concurrency: group: static-analysis-${{ github.ref }} @@ -446,6 +463,7 @@ jobs: if: needs.ci-config.outputs.enabled == 'yes' env: jobname: sparse + CI_JOB_IMAGE: ubuntu-22.04 runs-on: ubuntu-22.04 concurrency: group: sparse-${{ github.ref }} @@ -464,6 +482,7 @@ jobs: cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} env: jobname: Documentation + CI_JOB_IMAGE: ubuntu-latest runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 08a66ca508..04c444404e 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ /git-diff /git-diff-files /git-diff-index +/git-diff-pairs /git-diff-tree /git-difftool /git-difftool--helper diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2805cdeecb..bb6d5b976c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -164,7 +164,7 @@ build:msvc-meson: extends: .msvc-meson stage: build script: - - meson setup build -Dperl=disabled -Dbackend_max_links=1 -Dcredential_helpers=wincred + - meson setup build --vsenv -Dperl=disabled -Dbackend_max_links=1 -Dcredential_helpers=wincred - meson compile -C build artifacts: paths: @@ -173,7 +173,6 @@ build:msvc-meson: test:msvc-meson: extends: .msvc-meson stage: test - when: manual timeout: 6h needs: - job: "build:msvc-meson" diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc index ac9a84c17b..c6bd94986c 100644 --- a/Documentation/BreakingChanges.adoc +++ b/Documentation/BreakingChanges.adoc @@ -178,6 +178,11 @@ references. + These features will be removed. +* Support for "--stdin" option in the "name-rev" command was + deprecated (and hidden from the documentation) in the Git 2.40 + timeframe, in preference to its synonym "--annotate-stdin". Git 3.0 + removes the support for "--stdin" altogether. + * The git-whatchanged(1) command has outlived its usefulness more than 10 years ago, and takes more keystrokes to type than its rough equivalent `git log --raw`. We have nominated the command for diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines index a0e7041c54..6350949f2e 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -315,6 +315,9 @@ For C programs: encouraged to have a blank line between the end of the declarations and the first statement in the block. + - Do not explicitly initialize global variables to 0 or NULL; + instead, let BSS take care of the zero initialization. + - NULL pointers shall be written as NULL, not as 0. - When declaring pointers, the star sides with the variable @@ -861,6 +864,9 @@ Markup: _<git-dir>_ _<key-id>_ +Characters are also surrounded by underscores: + _LF_, _CR_, _CR_/_LF_, _NUL_, _EOF_ + Git's Asciidoc processor has been tailored to treat backticked text as complex synopsis. When literal and placeholders are mixed, you can use the backtick notation which will take care of correctly typesetting @@ -874,6 +880,17 @@ Markup: As a side effect, backquoted placeholders are correctly typeset, but this style is not recommended. + When documenting multiple related `git config` variables, place them on + a separate line instead of separating them by commas. For example, do + not write this: + `core.var1`, `core.var2`:: + Description common to `core.var1` and `core.var2`. + +Instead write this: + `core.var1`:: + `core.var2`:: + Description common to `core.var1` and `core.var2`. + Synopsis Syntax The synopsis (a paragraph with [synopsis] attribute) is automatically diff --git a/Documentation/Makefile b/Documentation/Makefile index 671267a8ac..df2ce187eb 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -109,6 +109,7 @@ SP_ARTICLES += howto/coordinate-embargoed-releases API_DOCS = $(patsubst %.adoc,%,$(filter-out technical/api-index-skel.adoc technical/api-index.adoc, $(wildcard technical/api-*.adoc))) SP_ARTICLES += $(API_DOCS) +TECH_DOCS += BreakingChanges TECH_DOCS += DecisionMaking TECH_DOCS += ReviewingGuidelines TECH_DOCS += MyFirstContribution @@ -316,8 +317,8 @@ cmds_txt = cmds-ancillaryinterrogators.adoc \ $(cmds_txt): cmd-list.made -cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT) - $(QUIET_GEN)$(PERL_PATH) ./cmd-list.perl .. . $(cmds_txt) && \ +cmd-list.made: cmd-list.sh ../command-list.txt $(MAN1_TXT) + $(QUIET_GEN)$(SHELL_PATH) ./cmd-list.sh .. . $(cmds_txt) && \ date >$@ mergetools-%.adoc: generate-mergetool-list.sh ../git-mergetool--lib.sh $(wildcard ../mergetools/*) @@ -397,9 +398,9 @@ user-manual.html: user-manual.xml $(XSLT) git.info: user-manual.texi $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi -user-manual.texi: user-manual.xml +user-manual.texi: user-manual.xml fix-texi.sh $(QUIET_DB2TEXI)$(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@+ && \ - $(PERL_PATH) fix-texi.perl <$@+ >$@ && \ + $(SHELL_PATH) fix-texi.sh <$@+ >$@ && \ $(RM) $@+ user-manual.pdf: user-manual.xml @@ -509,7 +510,12 @@ lint-docs-meson: awk "/^manpages = {$$/ {flag=1 ; next } /^}$$/ { flag=0 } flag { gsub(/^ \047/, \"\"); gsub(/\047 : [157],\$$/, \"\"); print }" meson.build | \ grep -v -e '#' -e '^$$' | \ sort >tmp-meson-diff/meson.adoc && \ - ls git*.adoc scalar.adoc | grep -v -e git-bisect-lk2009.adoc -e git-tools.adoc >tmp-meson-diff/actual.adoc && \ + ls git*.adoc scalar.adoc | \ + grep -v -e git-bisect-lk2009.adoc \ + -e git-pack-redundant.adoc \ + -e git-tools.adoc \ + -e git-whatchanged.adoc \ + >tmp-meson-diff/actual.adoc && \ if ! cmp tmp-meson-diff/meson.adoc tmp-meson-diff/actual.adoc; then \ echo "Meson man pages differ from actual man pages:"; \ diff -u tmp-meson-diff/meson.adoc tmp-meson-diff/actual.adoc; \ diff --git a/Documentation/MyFirstContribution.adoc b/Documentation/MyFirstContribution.adoc index afcf4b46c1..aca7212cfe 100644 --- a/Documentation/MyFirstContribution.adoc +++ b/Documentation/MyFirstContribution.adoc @@ -40,14 +40,6 @@ the list by sending an email to <git+subscribe@vger.kernel.org> The https://lore.kernel.org/git[archive] of this mailing list is available to view in a browser. -==== https://groups.google.com/forum/#!forum/git-mentoring[git-mentoring@googlegroups.com] - -This mailing list is targeted to new contributors and was created as a place to -post questions and receive answers outside of the public eye of the main list. -Veteran contributors who are especially interested in helping mentor newcomers -are present on the list. In order to avoid search indexers, group membership is -required to view messages; anyone can join and no approval is required. - ==== https://web.libera.chat/#git-devel[#git-devel] on Libera Chat This IRC channel is for conversations between Git contributors. If someone is @@ -150,15 +142,31 @@ command in `builtin/psuh.c`. Create that file, and within it, write the entry point for your command in a function matching the style and signature: ---- -int cmd_psuh(int argc, const char **argv, const char *prefix) +int cmd_psuh(int argc UNUSED, const char **argv UNUSED, + const char *prefix UNUSED, struct repository *repo UNUSED) ---- +A few things to note: + +* A subcommand implementation takes its command line arguments + in `int argc` + `const char **argv`, like `main()` would. + +* It also takes two extra parameters, `prefix` and `repo`. What + they mean will not be discussed until much later. + +* Because this first example will not use any of the parameters, + your compiler will give warnings on unused parameters. As the + list of these four parameters is mandated by the API to add + new built-in commands, you cannot omit them. Instead, you add + `UNUSED` to each of them to tell the compiler that you *know* + you are not (yet) using it. + We'll also need to add the declaration of psuh; open up `builtin.h`, find the declaration for `cmd_pull`, and add a new line for `psuh` immediately before it, in order to keep the declarations alphabetically sorted: ---- -int cmd_psuh(int argc, const char **argv, const char *prefix); +int cmd_psuh(int argc, const char **argv, const char *prefix, struct repository *repo); ---- Be sure to `#include "builtin.h"` in your `psuh.c`. You'll also need to @@ -174,7 +182,8 @@ Throughout the tutorial, we will mark strings for translation as necessary; you should also do so when writing your user-facing commands in the future. ---- -int cmd_psuh(int argc, const char **argv, const char *prefix) +int cmd_psuh(int argc UNUSED, const char **argv UNUSED, + const char *prefix UNUSED, struct repository *repo UNUSED) { printf(_("Pony saying hello goes here.\n")); return 0; @@ -287,8 +296,9 @@ on the reference implementation linked at the top of this document. It's probably useful to do at least something besides printing out a string. Let's start by having a look at everything we get. -Modify your `cmd_psuh` implementation to dump the args you're passed, keeping -existing `printf()` calls in place: +Modify your `cmd_psuh` implementation to dump the args you're passed, +keeping existing `printf()` calls in place; because the args are now +used, remove the `UNUSED` macro from them: ---- int i; @@ -312,7 +322,8 @@ on the command line, including the name of our command. (If `prefix` is empty for you, try `cd Documentation/ && ../bin-wrappers/git psuh`). That's not so helpful. So what other context can we get? -Add a line to `#include "config.h"`. Then, add the following bits to the +Add a line to `#include "config.h"` and `#include "repository.h"`. +Then, add the following bits to the function body: function body: ---- @@ -320,18 +331,18 @@ function body: ... - git_config(git_default_config, NULL); - if (git_config_get_string_tmp("user.name", &cfg_name) > 0) + repo_config(repo, git_default_config, NULL); + if (repo_config_get_string_tmp(repo, "user.name", &cfg_name)) printf(_("No name is found in config\n")); else printf(_("Your name: %s\n"), cfg_name); ---- -`git_config()` will grab the configuration from config files known to Git and -apply standard precedence rules. `git_config_get_string_tmp()` will look up +`repo_config()` will grab the configuration from config files known to Git and +apply standard precedence rules. `repo_config_get_string_tmp()` will look up a specific key ("user.name") and give you the value. There are a number of single-key lookup functions like this one; you can see them all (and more info -about how to use `git_config()`) in `Documentation/technical/api-config.adoc`. +about how to use `repo_config()`) in `Documentation/technical/api-config.adoc`. You should see that the name printed matches the one you see when you run: @@ -364,9 +375,10 @@ status_init_config(&s, git_status_config); ---- But as we drill down, we can find that `status_init_config()` wraps a call -to `git_config()`. Let's modify the code we wrote in the previous commit. +to `repo_config()`. Let's modify the code we wrote in the previous commit. Be sure to include the header to allow you to use `struct wt_status`: + ---- #include "wt-status.h" ---- @@ -379,8 +391,8 @@ prepare it, and print its contents: ... - wt_status_prepare(the_repository, &status); - git_config(git_default_config, &status); + wt_status_prepare(repo, &status); + repo_config(repo, git_default_config, &status); ... diff --git a/Documentation/MyFirstObjectWalk.adoc b/Documentation/MyFirstObjectWalk.adoc index 102a465a48..413a9fdb05 100644 --- a/Documentation/MyFirstObjectWalk.adoc +++ b/Documentation/MyFirstObjectWalk.adoc @@ -43,7 +43,7 @@ Open up a new file `builtin/walken.c` and set up the command handler: #include "builtin.h" #include "trace.h" -int cmd_walken(int argc, const char **argv, const char *prefix) +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) { trace_printf(_("cmd_walken incoming...\n")); return 0; @@ -86,7 +86,7 @@ int cmd_walken(int argc, const char **argv, const char *prefix) Also add the relevant line in `builtin.h` near `cmd_version()`: ---- -int cmd_walken(int argc, const char **argv, const char *prefix); +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo); ---- Include the command in `git.c` in `commands[]` near the entry for `version`, @@ -96,10 +96,23 @@ maintaining alphabetical ordering: { "walken", cmd_walken, RUN_SETUP }, ---- -Add it to the `Makefile` near the line for `builtin/worktree.o`: +Add an entry for the new command in the both the Make and Meson build system, +before the entry for `worktree`: +- In the `Makefile`: ---- +... BUILTIN_OBJS += builtin/walken.o +... +---- + +- In the `meson.build` file: +---- +builtin_sources = [ + ... + 'builtin/walken.c', + ... +] ---- Build and test out your command, without forgetting to ensure the `DEVELOPER` @@ -193,7 +206,7 @@ initialization functions. Next, we should have a look at any relevant configuration settings (i.e., settings readable and settable from `git config`). This is done by providing a -callback to `git_config()`; within that callback, you can also invoke methods +callback to `repo_config()`; within that callback, you can also invoke methods from other components you may need that need to intercept these options. Your callback will be invoked once per each configuration value which Git knows about (global, local, worktree, etc.). @@ -221,14 +234,14 @@ static int git_walken_config(const char *var, const char *value, } ---- -Make sure to invoke `git_config()` with it in your `cmd_walken()`: +Make sure to invoke `repo_config()` with it in your `cmd_walken()`: ---- -int cmd_walken(int argc, const char **argv, const char *prefix) +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) { ... - git_config(git_walken_config, NULL); + repo_config(repo, git_walken_config, NULL); ... } @@ -250,14 +263,14 @@ We'll also need to include the `revision.h` header: ... -int cmd_walken(int argc, const char **argv, const char *prefix) +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) { /* This can go wherever you like in your declarations.*/ struct rev_info rev; ... - /* This should go after the git_config() call. */ - repo_init_revisions(the_repository, &rev, prefix); + /* This should go after the repo_config() call. */ + repo_init_revisions(repo, &rev, prefix); ... } @@ -287,6 +300,7 @@ static void final_rev_info_setup(struct rev_info *rev) ==== Instead of using the shorthand `add_head_to_pending()`, you could do something like this: + ---- struct setup_revision_opt opt; @@ -295,6 +309,7 @@ something like this: opt.revarg_opt = REVARG_COMMITTISH; setup_revisions(argc, argv, rev, &opt); ---- + Using a `setup_revision_opt` gives you finer control over your walk's starting point. ==== @@ -303,7 +318,7 @@ Then let's invoke `final_rev_info_setup()` after the call to `repo_init_revisions()`: ---- -int cmd_walken(int argc, const char **argv, const char *prefix) +int cmd_walken(int argc, const char **argv, const char *prefix, struct repository *repo) { ... diff --git a/Documentation/RelNotes/2.50.0.adoc b/Documentation/RelNotes/2.50.0.adoc new file mode 100644 index 0000000000..e85747335b --- /dev/null +++ b/Documentation/RelNotes/2.50.0.adoc @@ -0,0 +1,441 @@ +Git v2.50 Release Notes +======================= + +UI, Workflows & Features +------------------------ + + * A post-processing filter for "diff --raw" output has been + introduced. + + * "git repack" learned "--combine-cruft-below-size" option that + controls how cruft-packs are combined. + + * TCP keepalive behaviour on http transports can now be configured by + calling cURL library. + + * Incrementally updating multi-pack index files. + + * "git reflog" learns "drop" subcommand, that discards the entire + reflog data for a ref. + + * A new userdiff driver for ".ini" format configuration files has + been added. + + * The job to coalesce loose objects into packfiles in "git + maintenance" now has configurable batch size. + + * "git clone" still gave the message about the default branch name; + this message has been turned into an advice message that can be + turned off. + + * "git rev-list" learns machine-parsable output format that delimits + each field with NUL. + + * "git maintenance" learns a new task to expire reflog entries. + + * Auth-related (and unrelated) error handling in send-email has been + made more robust. + + * Updating multiple references have only been possible in an all-or-nothing + fashion with transactions, but it can be more efficient to batch + multiple updates even when some of them are allowed to fail in a + best-effort manner. A new "best effort batches of updates" mode + has been introduced. + + * "git help --build-options" reports SHA-1 and SHA-256 backends used + in the build. + + * "git cat-file --batch" and friends learned to allow "--filter=" to + omit certain objects, just like the transport layer does. + + * "git blame --porcelain" mode now talks about unblamable lines and + lines that are blamed to an ignored commit. + + * The build procedure installs bash (but not zsh) completion script. + + * send-email has been updated to work better with Outlook's SMTP server. + + * "git diff --minimal" used to give non-minimal output when its + optimization kicked in, which has been disabled. + + * "git index-pack --fix-thin" used to abort to prevent a cycle in + delta chains from forming in a corner case even when there is no + such cycle. + + * Make repository clean-up tasks that "gc" can do available to "git + maintenance" front-end. + + * Bundle-URI feature did not use refs recorded in the bundle other + than normal branches as anchoring points to optimize the follow-up + fetch during "git clone"; now it is told to utilize all. + + * The `send-email` documentation has been updated with OAuth2.0 + related examples. + + * Two of the "scalar" subcommands that add a repository that hasn't + been under "scalar"'s control are taught an option not to enable the + scheduled maintenance on it. + + * The userdiff pattern for shell scripts has been updated to cope + with more bash-isms. + + * "git merge-tree" learned an option to see if it resolves cleanly + without actually creating a result. + + * The commit title in the "rebase -i" todo file are now prefixed with + '#', just like a merge commit being replayed. + + * "git receive-pack" optionally learns not to care about connectivity + check, which can be useful when the repository arranges to ensure + connectivity by some other means. + + * "git notes --help" documentation updates. + + +Performance, Internal Implementation, Development Support etc. +-------------------------------------------------------------- + + * A handful of built-in command implementations have been rewritten + to use the repository instance supplied by git.c:run_builtin(), its + caller. + + * "git fsck" becomes more careful when checking the refs. + + * "git fast-export | git fast-import" learns to deal with commit and + tag objects with embedded signatures a bit better. This is highly + experimental and the format of the data stream may change in the + future without compatibility guarantees. + + * The code paths to check whether a refname X is available (by seeing + if another ref X/Y exists, etc.) have been optimized. + + * First step of deprecating and removing merge-recursive. + + * In protocol v2 where the refs advertisement is constrained, we try + to tell the server side not to limit the advertisement when there + is no specific need to, which has been the source of confusion and + recent bugs. Revamp the logic to simplify. + + * Update meson based build procedure for breaking changes support. + + * Enable -Wunreachable-code for developer builds. + + * Ensure what we write in assert() does not have side effects, + and introduce ASSERT() macro to mark those that cannot be + mechanically checked for lack of side effects. + + * Give more meaningful error return values from block writer layer of + the reftable ref-API backend. + + * Make the code in reftable library less reliant on the service + routines it used to borrow from Git proper, to make it easier to + use by external users of the library. + + * CI update. + + * The object layer has been updated to take an explicit repository + instance as a parameter in more code paths. + + * Some warnings from "-Wsign-compare" for builtin/rm.c have been + squelched. + + * A few traditional unit tests have been rewritten to use the clar + framework. + + * Some warnings from "-Wsign-compare" for pathspec.c have been + squelched. + + * "make test" used to have a hard dependency on (basic) Perl; tests + have been rewritten help environment with NO_PERL test the build as + much as possible. + + * Remove remnants of the recursive merge strategy backend, which was + superseded by the ort merge strategy. + + * Optimize the code to dedup references recorded in a bundle file. + + * Update parse-options API to catch mistakes to pass address of an + integral variable of a wrong type/size. + + * Since a call to repo_config() can be called with repo set to NULL + these days, a command that is marked as RUN_SETUP in the builtin + command table does not have to check repo with NULL before making + the call. + + * Overhaul of the reftable API. + + * Reduce requirement for Perl in our documentation build and a few + scripts. + + * The build procedure based on Meson learned to drive the + benchmarking tests. + + * Code clean-up for meson-based build infrastructure. + + * Add an equivalent to "make hdr-check" target to meson based builds. + + * Further code clean-up in the object-store layer. + + * Build performance fix. + + * Teach "git send-email" to also consult `hostname -f` for mail + domain to compute the identity given to SMTP servers. + + * The dependency on the_repository variable has been reduced from the + code paths in "git replay". + + * Support to create a loose object file with unknown object type has + been dropped. + + * The code path to access the "packed-refs" file while "fsck" is + taught to mmap the file, instead of reading the whole file into + memory. + + * Assorted fixes for issues found with CodeQL. + + * Remove the leftover hints to the test framework to mark tests that + do not pass the leak checker tests, as they should no longer be + needed. + + * When a stale .midx file refers to .pack files that no longer exist, + we ended up checking for these non-existent files repeatedly, which + has been optimized by memoizing the non-existence. + + * Build settings have been improved for BSD based systems. + + * Newer version of libcURL detected curl_easy_setopt() calls we made + with platform-natural "int" when we should have used "long", which + all have been corrected. + + * Tests that compare $HOME and $(pwd), which should be the same + directory unless the tests chdir's around, would fail when the user + enters the test directory via symbolic links, which has been + corrected. + + +Fixes since v2.49 +----------------- + + * The refname exclusion logic in the packed-ref backend has been + broken for some time, which confused upload-pack to advertise + different set of refs. This has been corrected. + (merge 10e8a9352b tb/refs-exclude-fixes later to maint). + + * The merge-recursive and merge-ort machinery crashed in corner cases + when certain renames are involved. + (merge 3adba40858 en/merge-process-renames-crash-fix later to maint). + + * Certain "cruft" objects would have never been refreshed when there + are multiple cruft packs in the repository, which has been + corrected. + (merge 08f612ba70 tb/multi-cruft-pack-refresh-fix later to maint). + + * The xdiff code on 32-bit platform misbehaved when an insanely large + context size is given, which has been corrected. + (merge d39e28e68c rs/xdiff-context-length-fix later to maint). + + * GitHub Actions CI switched on a CI/CD variable that does not exist + when choosing what packages to install etc., which has been + corrected. + (merge ee89f7c79d kn/ci-meson-check-build-docs-fix later to maint). + + * Using "git name-rev --stdin" as an example, improve the framework to + prepare tests to pretend to be in the future where the breaking + changes have already happened. + (merge de3dec1187 jc/name-rev-stdin later to maint). + + * An earlier code refactoring of the hash machinery missed a few + required calls to init_fn. + (merge d39f04b638 jh/hash-init-fixes later to maint). + + * A documentation page was left out from formatting and installation, + which has been corrected. + (merge ae85116f18 pw/build-breaking-changes-doc later to maint). + + * The bash command line completion script (in contrib/) has been + updated to cope with remote repository nicknames with slashes in + them. + (merge 778d2f1760 dm/completion-remote-names-fix later to maint). + + * "Dubious ownership" checks on Windows has been tightened up. + (merge 5bb88e89ef js/mingw-admins-are-special later to maint). + + * Layout configuration in vimdiff backend didn't work as advertised, + which has been corrected. + (merge 93bab2d04b fr/vimdiff-layout-fixes later to maint). + + * Fix our use of zlib corner cases. + (merge 1cb2f293f5 jk/zlib-inflate-fixes later to maint). + + * Fix lockfile contention in reftable code on Windows. + (merge 0a3dceabf1 ps/mingw-creat-excl-fix later to maint). + + * "git-merge-file" documentation source, which has lines that look + like conflict markers, lacked custom conflict marker size defined, + which has been corrected.. + (merge d3b5832381 pw/custom-conflict-marker-size-for-merge-related-docs later to maint). + + * Squelch false-positive from sparse. + (merge da87b58014 dd/sparse-glibc-workaround later to maint). + + * Adjust to the deprecation of use of Ubuntu 20.04 GitHub Actions CI. + (merge 832d9f6d0b js/ci-github-update-ubuntu later to maint). + + * Work around CI breakage due to fedora base image getting updated. + (merge 8a471a663b js/ci-fedora-gawk later to maint). + + * A ref transaction corner case fix. + (merge b9fadeead7 jt/ref-transaction-abort-fix later to maint). + + * Random build fixes. + (merge 85e1d6819f ps/misc-build-fixes later to maint). + + * "git fetch [<remote>]" with only the configured fetch refspec + should be the only thing to update refs/remotes/<remote>/HEAD, + but the code was overly eager to do so in other cases. + + * Incorrect sorting of refs with bytes with high-bit set on platforms + with signed char led to a BUG, which has been corrected. + + * "make perf" fixes. + (merge 1665f12fa0 pb/perf-test-fixes later to maint). + + * Doc mark-up updates. + (merge 5a5565ec44 ja/doc-reset-mv-rm-markup-updates later to maint). + + * Work around false positive from CodeQL checker. + (merge 0f558141ed js/range-check-codeql-workaround later to maint). + + * "git log --{left,right}-only A...B", when A and B does not share + any common ancestor, now behaves as expected. + (merge e7ef4be7c2 mh/left-right-limited later to maint). + + * Document the convention to disable hooks altogether by setting the + hooksPath configuration variable to /dev/null. + (merge 1b2eee94f1 ds/doc-disable-hooks later to maint). + + * Make sure outage of third-party sites that supply P4, Git-LFS, and + JGit we use for testing would not prevent our CI jobs from running + at all. + + * Various build tweaks, including CSPRNG selection on some platforms. + (merge cdda67de03 rj/build-tweaks later to maint). + + * Developer support fix.. + (merge 32b74b9809 js/git-perf-env-override later to maint). + + * Fix for scheduled maintenance tasks on platforms using launchctl. + (merge eb2d7beb0e jh/gc-launchctl-schedule-fix later to maint). + + * Update to arm64 Windows port (part of which had been reverted as it + broke builds for existing platforms, which may need to be redone in + future releases). + + * hashmap API clean-up to ensure hashmap_clear() leaves a cleared map + in a reusable state. + (merge 9481877de3 en/hashmap-clear-fix later to maint). + + * "git mv a a/b dst" would ask to move the directory 'a' itself, as + well as its contents, in a single destination directory, which is + a contradicting request that is impossible to satisfy. This case is + now detected and the command errors out. + (merge 974f0d4664 ps/mv-contradiction-fix later to maint). + + * Further refinement on CI messages when an optional external + software is unavailable (e.g. due to third-party service outage). + (merge 956acbefbd jc/ci-skip-unavailable-external-software later to maint). + + * Test result aggregation did not work in Meson based CI jobs. + (merge bd38ed5be1 ps/ci-test-aggreg-fix-for-meson later to maint). + + * Code clean-up around stale CI elements and building with Visual Studio. + (merge a7b060f67f js/ci-buildsystems-cleanup later to maint). + + * "git add 'f?o'" did not add 'foo' if 'f?o', an unusual pathname, + also existed on the working tree, which has been corrected. + (merge ec727e189c kj/glob-path-with-special-char later to maint). + + * The fallback implementation of open_nofollow() depended on + open("symlink", O_NOFOLLOW) to set errno to ELOOP, but a few BSD + derived systems use different errno, which has been worked around. + (merge f47bcc3413 cf/wrapper-bsd-eloop later to maint). + + * Use-after-free fix in the sequencer. + (merge 5dbaec628d pw/sequencer-reflog-use-after-free later to maint). + + * win+Meson CI pipeline, unlike other pipelines for Windows, + used to build artifacts in developer mode, which has been changed to + build them in release mode for consistency. + (merge 184abdcf05 js/ci-build-win-in-release-mode later to maint). + + * CI settings at GitLab has been updated to run MSVC based Meson job + automatically (as opposed to be done only upon manual request). + (merge 6389579b2f ps/ci-gitlab-enable-msvc-meson-job later to maint). + + * "git apply" and "git add -i/-p" code paths no longer unnecessarily + expand sparse-index while working. + (merge ecf9ba20e3 ds/sparse-apply-add-p later to maint). + + * Avoid adding directory path to a sparse-index tree entries to the + name-hash, since they would bloat the hashtable without anybody + querying for them. This was done already for a single threaded + part of the code, but now the multi-threaded code also does the + same. + (merge 2e60aabc75 am/sparse-index-name-hash-fix later to maint). + + * Recent versions of Perl started warning against "! A =~ /pattern/" + which does not negate the result of the matching. As it turns out + that the problematic function is not even called, it was removed. + (merge 67cae845d2 op/cvsserver-perl-warning later to maint). + + * "git apply --index/--cached" when applying a deletion patch in + reverse failed to give the mode bits of the path "removed" by the + patch to the file it creates, which has been corrected. + + * "git verify-refs" errored out in a repository in which + linked worktrees were prepared with Git 2.43 or lower. + (merge d5b3c38b8a sj/ref-contents-check-fix later to maint). + + * Update total_ram() function on BSD variants. + + * Update online_cpus() function on BSD variants. + + * Revert a botched bswap.h change that broke ntohll() functions on + big-endian systems with __builtin_bswap32/64(). + + * Fixes for GitHub Actions Coverity job. + (merge 3cc4fc1ebd js/github-ci-win-coverity-fix later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge 227c4f33a0 ja/doc-block-delimiter-markup-fix later to maint). + (merge 2bfd3b3685 ab/decorate-code-cleanup later to maint). + (merge 5337daddc7 am/dir-dedup-decl-of-repository later to maint). + (merge 554051d691 en/diff-rename-follow-fix later to maint). + (merge a18c18b470 en/random-cleanups later to maint). + (merge 5af21c9acb hj/doc-rev-list-ancestry-fix later to maint). + (merge 26d76ca284 aj/doc-restore-p-update later to maint). + (merge 2c0dcb9754 cc/lop-remote later to maint). + (merge 7b399322a2 ja/doc-branch-markup later to maint). + (merge ee434e1807 pw/doc-pack-refs-markup-fix later to maint). + (merge c000918eb7 tb/bitamp-typofix later to maint). + (merge fa8cd29676 js/imap-send-peer-cert-verify later to maint). + (merge 98b423bc1c rs/clear-commit-marks-simplify later to maint). + (merge 133d065dd6 ta/bulk-checkin-signed-compare-false-warning-fix later to maint). + (merge d2827dc31e es/meson-build-skip-coccinelle later to maint). + (merge ee8edb7156 dk/vimdiff-doc-fix later to maint). + (merge 107d889303 md/t1403-path-is-file later to maint). + (merge abd4192b07 js/comma-semicolon-confusion later to maint). + (merge 27b7264206 ab/environment-clean-header later to maint). + (merge ff4a749354 as/typofix-in-env-h-header later to maint). + (merge 86eef3541e az/tighten-string-array-constness later to maint). + (merge 25292c301d lo/remove-log-reencode-from-rev-info later to maint). + (merge 1aa50636fd jk/p5332-testfix later to maint). + (merge 42cf4ac552 ps/ci-resurrect-p4-on-github later to maint). + (merge 104add8368 js/diff-codeql-false-positive-workaround later to maint). + (merge f62977b93c en/get-tree-entry-doc later to maint). + (merge e5dd0a05ed ly/am-split-stgit-leakfix later to maint). + (merge bac220e154 rc/t1001-test-path-is-file later to maint). + (merge 91db6c735d ly/reftable-writer-leakfix later to maint). + (merge 20e4e9ad0b jc/doc-synopsis-option-markup later to maint). + (merge cddcee7f64 es/meson-configure-build-options-fix later to maint). + (merge cea9f55f00 wk/sparse-checkout-doc-fix later to maint). diff --git a/Documentation/RelNotes/2.51.0.adoc b/Documentation/RelNotes/2.51.0.adoc new file mode 100644 index 0000000000..89645da210 --- /dev/null +++ b/Documentation/RelNotes/2.51.0.adoc @@ -0,0 +1,84 @@ +Git v2.51 Release Notes +======================= + +UI, Workflows & Features +------------------------ + + * Userdiff patterns for the R language have been added. + + * Documentation for "git send-email" has been updated with a bit more + credential helper and OAuth information. + + * "git cat-file --batch" learns to understand %(objectmode) atom to + allow the caller to tell missing objects (due to repository + corruption) and submodules (whose commit objects are OK to be + missing) apart. + + * "git diff --no-index dirA dirB" can limit the comparison with + pathspec at the end of the command line, just like normal "git + diff". + + * "git subtree" (in contrib/) learned to grok GPG signing its commits. + + +Performance, Internal Implementation, Development Support etc. +-------------------------------------------------------------- + + * "git pack-objects" learned to find delta bases from blobs at the + same path, using the --path-walk API. + + * CodingGuidelines update. + + * Add settings for Solaris 10 & 11. + + * Meson-based build/test framework now understands TAP output + generated by our tests. + + * "Do not explicitly initialize to zero" rule has been clarified in + the CodingGuidelines document. + + +Fixes since v2.50 +----------------- + + * A memory-leak in an error code path has been plugged. + (merge 7082da85cb ly/commit-graph-graph-write-leakfix later to maint). + + * A memory-leak in an error code path has been plugged. + (merge aedebdb6b9 ly/fetch-pack-leakfix later to maint). + + * Some leftover references to documentation source files that no + longer exist, due to recent ".txt" -> ".adoc" renaming, have been + corrected. + (merge 3717a5775a jw/doc-txt-to-adoc-refs later to maint). + + * "git stash -p <pathspec>" improvements. + (merge 468817bab2 pw/stash-p-pathspec-fixes later to maint). + + * "git send-email" incremented its internal message counter when a + message was edited, which made logic that treats the first message + specially misbehave, which has been corrected. + (merge 2cc27b3501 ag/send-email-edit-threading-fix later to maint). + + * "git stash" recorded a wrong branch name when submodules are + present in the current checkout, which has been corrected. + (merge ffb36c64f2 kj/stash-onbranch-submodule-fix later to maint). + + * When asking to apply mailmap to both author and committer field + while showing a commit object, the field that appears later was not + correctly parsed and replaced, which has been corrected. + (merge abf94a283f sa/multi-mailmap-fix later to maint). + + * Other code cleanup, docfix, build fix, etc. + (merge b257adb571 lo/my-first-ow-doc-update later to maint). + (merge 8b34b6a220 ly/sequencer-update-squash-is-fixup-only later to maint). + (merge 5dceb8bd05 ly/do-not-localize-bug-messages later to maint). + (merge 61372dd613 ly/commit-buffer-reencode-leakfix later to maint). + (merge 81cd1eef7d ly/pack-bitmap-root-leakfix later to maint). + (merge bfc9f9cc64 ly/submodule-update-failure-leakfix later to maint). + (merge 65dff89c6b ma/doc-diff-cc-headers later to maint). + (merge efb61591ee jm/bundle-uri-debug-output-to-fp later to maint). + (merge a3d278bb64 ly/prepare-show-merge-leakfix later to maint). + (merge 1fde1c5daf ac/preload-index-wo-the-repository later to maint). + (merge 855cfc65ae rm/t2400-modernize later to maint). + (merge 2939494284 ly/run-builtin-use-passed-in-repo later to maint). diff --git a/Documentation/ToolsForGit.adoc b/Documentation/ToolsForGit.adoc index ae7690b45d..a842c13327 100644 --- a/Documentation/ToolsForGit.adoc +++ b/Documentation/ToolsForGit.adoc @@ -34,6 +34,7 @@ This is adapted from Linux's suggestion in its CodingStyle document: - To follow the rules in CodingGuidelines, it's useful to put the following in GIT_CHECKOUT/.dir-locals.el, assuming you use cperl-mode: + ---- ;; note the first part is useful for C editing, too ((nil . ((indent-tabs-mode . t) diff --git a/Documentation/asciidoc.conf.in b/Documentation/asciidoc.conf.in index f2aef6cb79..9d9139306e 100644 --- a/Documentation/asciidoc.conf.in +++ b/Documentation/asciidoc.conf.in @@ -43,7 +43,7 @@ ifdef::doctype-book[] endif::doctype-book[] [literal-inlinemacro] -{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'<emphasis>\1</emphasis>', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<literal>\2</literal>', re.sub(r'(\.\.\.?)([^\]$.])', r'<literal>\1</literal>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} +{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'<emphasis>\1</emphasis>', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@\\\*\/_^\$]+\.?)+|,)',r'\1<literal>\2</literal>', re.sub(r'(\.\.\.?)([^\]$.])', r'<literal>\1</literal>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} endif::backend-docbook[] @@ -75,18 +75,18 @@ git-relative-html-prefix= <a href="{git-relative-html-prefix}{target}.html">{target}{0?({0})}</a> [literal-inlinemacro] -{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'<em>\1</em>', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\/_^\$]+\.?)+)',r'\1<code>\2</code>', re.sub(r'(\.\.\.?)([^\]$.])', r'<code>\1</code>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} +{eval:re.sub(r'(<[-a-zA-Z0-9.]+>)', r'<em>\1</em>', re.sub(r'([\[\s|()>]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,\\\*\/_^\$]+\.?)+)',r'\1<code>\2</code>', re.sub(r'(\.\.\.?)([^\]$.])', r'<code>\1</code>\2', macros.passthroughs[int(attrs['passtext'][1:-1])] if attrs['passtext'][1:-1].isnumeric() else attrs['passtext'][1:-1])))} endif::backend-xhtml11[] ifdef::backend-docbook[] ifdef::doctype-manpage[] [paradef-default] -synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!<phrase>\\0</phrase>!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1<literal>\\2</literal>!g;s!<[-a-zA-Z0-9.]\\+>!<emphasis>\\0</emphasis>!g'" +synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!<phrase>\\0</phrase>!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.\\\\\\*]\\+\\|…\\)!\\1<literal>\\2</literal>!g;s!<[-a-zA-Z0-9.]\\+>!<emphasis>\\0</emphasis>!g'" endif::doctype-manpage[] endif::backend-docbook[] ifdef::backend-xhtml11[] [paradef-default] -synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!<span>\\0</span>!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.]\\+\\|…\\)!\\1<code>\\2</code>!g;s!<[-a-zA-Z0-9.]\\+>!<em>\\0</em>!g'" +synopsis-style=template="verseparagraph",filter="sed 's!…\\(\\]\\|$\\)!<span>\\0</span>!g;s!\\([\\[ |()]\\|^\\|\\]\\|>\\)\\([-=a-zA-Z0-9:+@,\\/_^\\$.\\\\\\*]\\+\\|…\\)!\\1<code>\\2</code>!g;s!<[-a-zA-Z0-9.]\\+>!<em>\\0</em>!g'" endif::backend-xhtml11[] diff --git a/Documentation/asciidoctor-extensions.rb.in b/Documentation/asciidoctor-extensions.rb.in index 2494f17a51..8b7b161349 100644 --- a/Documentation/asciidoctor-extensions.rb.in +++ b/Documentation/asciidoctor-extensions.rb.in @@ -49,8 +49,8 @@ module Git def process parent, reader, attrs outlines = reader.lines.map do |l| - l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2') - .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$]+)}, '\1{empty}`\2`{empty}') + l.gsub(/(\.\.\.?)([^\]$\. ])/, '{empty}`\1`{empty}\2') + .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$\\\*]+)}, '\1{empty}`\2`{empty}') .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__') .gsub(']', ']{empty}') end @@ -71,8 +71,9 @@ module Git # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math %(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>) elsif type == :monospaced - node.text.gsub(/(\.\.\.?)([^\]$.])/, '<literal>\1</literal>\2') - .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<literal>\2</literal>') + node.text.gsub(/(\.\.\.?)([^\]$\.])/, '<literal>\1</literal>\2') + .gsub(/^\.\.\.?$/, '<literal>\0</literal>') + .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@/_^\$\\\*]+\.{0,2})+|,)}, '\1<literal>\2</literal>') .gsub(/(<[-a-zA-Z0-9.]+>)/, '<emphasis>\1</emphasis>') else open, close, supports_phrase = QUOTE_TAGS[type] @@ -100,7 +101,8 @@ module Git def convert_inline_quoted node if node.type == :monospaced node.text.gsub(/(\.\.\.?)([^\]$.])/, '<code>\1</code>\2') - .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<code>\2</code>') + .gsub(/^\.\.\.?$/, '<code>\0</code>') + .gsub(%r{([\[\s|()>.]|^|\]|>)(\.?([-a-zA-Z0-9:+=~@,/_^\$\\\*]+\.{0,2})+)}, '\1<code>\2</code>') .gsub(/(<[-a-zA-Z0-9.]+>)/, '<em>\1</em>') else diff --git a/Documentation/blame-options.adoc b/Documentation/blame-options.adoc index aa77406d4e..19ea187238 100644 --- a/Documentation/blame-options.adoc +++ b/Documentation/blame-options.adoc @@ -125,7 +125,8 @@ take effect. another commit will be marked with a `?` in the blame output. If the `blame.markUnblamableLines` config option is set, then those lines touched by an ignored commit that we could not attribute to another revision are - marked with a '*'. + marked with a '*'. In the porcelain modes, we print 'ignored' and + 'unblamable' on a newline respectively. --ignore-revs-file <file>:: Ignore revisions listed in `file`, which must be in the same format as an diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl deleted file mode 100755 index 0a0c1b3f61..0000000000 --- a/Documentation/cmd-list.perl +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/perl -w - -use File::Compare qw(compare); - -sub format_one { - my ($source_dir, $out, $nameattr) = @_; - my ($name, $attr) = @$nameattr; - my ($path) = "$source_dir/Documentation/$name.adoc"; - my ($state, $description); - my $mansection; - $state = 0; - open I, '<', "$path" or die "No such file $path.adoc"; - while (<I>) { - if (/^(?:git|scalar)[a-z0-9-]*\(([0-9])\)$/) { - $mansection = $1; - next; - } - if (/^NAME$/) { - $state = 1; - next; - } - if ($state == 1 && /^----$/) { - $state = 2; - next; - } - next if ($state != 2); - chomp; - $description = $_; - last; - } - close I; - if (!defined $description) { - die "No description found in $path.adoc"; - } - if (my ($verify_name, $text) = ($description =~ /^($name) - (.*)/)) { - print $out "linkgit:$name\[$mansection\]::\n\t"; - if ($attr =~ / deprecated /) { - print $out "(deprecated) "; - } - print $out "$text.\n\n"; - } - else { - die "Description does not match $name: $description"; - } -} - -my ($source_dir, $build_dir, @categories) = @ARGV; - -open IN, "<$source_dir/command-list.txt"; -while (<IN>) { - last if /^### command list/; -} - -my %cmds = (); -for (sort <IN>) { - next if /^#/; - - chomp; - my ($name, $cat, $attr) = /^(\S+)\s+(.*?)(?:\s+(.*))?$/; - $attr = '' unless defined $attr; - push @{$cmds{$cat}}, [$name, " $attr "]; -} -close IN; - -for my $out (@categories) { - my ($cat) = $out =~ /^cmds-(.*)\.adoc$/; - my ($path) = "$build_dir/$out"; - open O, '>', "$path+" or die "Cannot open output file $out+"; - for (@{$cmds{$cat}}) { - format_one($source_dir, \*O, $_); - } - close O; - - if (-f "$path" && compare("$path", "$path+") == 0) { - unlink "$path+"; - } - else { - rename "$path+", "$path"; - } -} diff --git a/Documentation/cmd-list.sh b/Documentation/cmd-list.sh new file mode 100755 index 0000000000..077def3b72 --- /dev/null +++ b/Documentation/cmd-list.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +set -e + +format_one () { + source_dir="$1" + command="$2" + attributes="$3" + + path="$source_dir/Documentation/$command.adoc" + if ! test -f "$path" + then + echo >&2 "No such file $path" + exit 1 + fi + + state=0 + while read line + do + case "$state" in + 0) + case "$line" in + git*\(*\)|scalar*\(*\)) + mansection="${line##*\(}" + mansection="${mansection%\)}" + ;; + NAME) + state=1;; + esac + ;; + 1) + if test "$line" = "----" + then + state=2 + fi + ;; + 2) + description="$line" + break + ;; + esac + done <"$path" + + if test -z "$mansection" + then + echo "No man section found in $path" >&2 + exit 1 + fi + + if test -z "$description" + then + echo >&2 "No description found in $path" + exit 1 + fi + + case "$description" in + "$command - "*) + text="${description#$command - }" + + printf "linkgit:%s[%s]::\n\t" "$command" "$mansection" + case "$attributes" in + *" deprecated "*) + printf "(deprecated) " + ;; + esac + printf "$text.\n\n" + ;; + *) + echo >&2 "Description does not match $command: $description" + exit 1 + ;; + esac +} + +source_dir="$1" +build_dir="$2" +shift 2 + +for out +do + category="${out#cmds-}" + category="${category%.adoc}" + path="$build_dir/$out" + + while read command command_category attributes + do + case "$command" in + "#"*) + continue;; + esac + + case "$command_category" in + "$category") + format_one "$source_dir" "$command" " $attributes ";; + esac + done <"$source_dir/command-list.txt" >"$build_dir/$out+" + + if cmp "$build_dir/$out+" "$build_dir/$out" >/dev/null 2>&1 + then + rm "$build_dir/$out+" + else + mv "$build_dir/$out+" "$build_dir/$out" + fi +done diff --git a/Documentation/config/branch.adoc b/Documentation/config/branch.adoc index 432b9cd2c0..e35ea7ac64 100644 --- a/Documentation/config/branch.adoc +++ b/Documentation/config/branch.adoc @@ -1,41 +1,42 @@ -branch.autoSetupMerge:: - Tells 'git branch', 'git switch' and 'git checkout' to set up new branches +`branch.autoSetupMerge`:: + Tells `git branch`, `git switch` and `git checkout` to set up new branches so that linkgit:git-pull[1] will appropriately merge from the starting point branch. Note that even if this option is not set, this behavior can be chosen per-branch using the `--track` - and `--no-track` options. The valid settings are: `false` -- no - automatic setup is done; `true` -- automatic setup is done when the - starting point is a remote-tracking branch; `always` -- - automatic setup is done when the starting point is either a - local branch or remote-tracking branch; `inherit` -- if the starting point - has a tracking configuration, it is copied to the new - branch; `simple` -- automatic setup is done only when the starting point + and `--no-track` options. This option defaults to `true`. The valid settings + are: +`false`;; no automatic setup is done +`true`;; automatic setup is done when the starting point is a remote-tracking branch +`always`;; automatic setup is done when the starting point is either a + local branch or remote-tracking branch +`inherit`;; if the starting point has a tracking configuration, it is copied to the new + branch +`simple`;; automatic setup is done only when the starting point is a remote-tracking branch and the new branch has the same name as the - remote branch. This option defaults to true. + remote branch. -branch.autoSetupRebase:: - When a new branch is created with 'git branch', 'git switch' or 'git checkout' +`branch.autoSetupRebase`:: + When a new branch is created with `git branch`, `git switch` or `git checkout` that tracks another branch, this variable tells Git to set - up pull to rebase instead of merge (see "branch.<name>.rebase"). - When `never`, rebase is never automatically set to true. - When `local`, rebase is set to true for tracked branches of - other local branches. - When `remote`, rebase is set to true for tracked branches of - remote-tracking branches. - When `always`, rebase will be set to true for all tracking - branches. - See "branch.autoSetupMerge" for details on how to set up a - branch to track another branch. - This option defaults to never. + up pull to rebase instead of merge (see `branch.<name>.rebase`). + The valid settings are: +`never`;; rebase is never automatically set to true. +`local`;; rebase is set to true for tracked branches of other local branches. +`remote`;; rebase is set to true for tracked branches of remote-tracking branches. +`always`;; rebase will be set to true for all tracking branches. -branch.sort:: ++ +See `branch.autoSetupMerge` for details on how to set up a branch to track another branch. +This option defaults to `never`. + +`branch.sort`:: This variable controls the sort ordering of branches when displayed by - linkgit:git-branch[1]. Without the "--sort=<value>" option provided, the + linkgit:git-branch[1]. Without the `--sort=<value>` option provided, the value of this variable will be used as the default. See linkgit:git-for-each-ref[1] field names for valid values. -branch.<name>.remote:: - When on branch <name>, it tells 'git fetch' and 'git push' +`branch.<name>.remote`:: + When on branch _<name>_, it tells `git fetch` and `git push` which remote to fetch from or push to. The remote to push to may be overridden with `remote.pushDefault` (for all branches). The remote to push to, for the current branch, may be further @@ -46,58 +47,58 @@ branch.<name>.remote:: Additionally, `.` (a period) is the current local repository (a dot-repository), see `branch.<name>.merge`'s final note below. -branch.<name>.pushRemote:: - When on branch <name>, it overrides `branch.<name>.remote` for +`branch.<name>.pushRemote`:: + When on branch _<name>_, it overrides `branch.<name>.remote` for pushing. It also overrides `remote.pushDefault` for pushing - from branch <name>. When you pull from one place (e.g. your + from branch _<name>_. When you pull from one place (e.g. your upstream) and push to another place (e.g. your own publishing repository), you would want to set `remote.pushDefault` to specify the remote to push to for all branches, and use this option to override it for a specific branch. -branch.<name>.merge:: - Defines, together with branch.<name>.remote, the upstream branch - for the given branch. It tells 'git fetch'/'git pull'/'git rebase' which - branch to merge and can also affect 'git push' (see push.default). - When in branch <name>, it tells 'git fetch' the default - refspec to be marked for merging in FETCH_HEAD. The value is +`branch.<name>.merge`:: + Defines, together with `branch.<name>.remote`, the upstream branch + for the given branch. It tells `git fetch`/`git pull`/`git rebase` which + branch to merge and can also affect `git push` (see `push.default`). + When in branch _<name>_, it tells `git fetch` the default + refspec to be marked for merging in `FETCH_HEAD`. The value is handled like the remote part of a refspec, and must match a ref which is fetched from the remote given by - "branch.<name>.remote". - The merge information is used by 'git pull' (which first calls - 'git fetch') to lookup the default branch for merging. Without - this option, 'git pull' defaults to merge the first refspec fetched. + `branch.<name>.remote`. + The merge information is used by `git pull` (which first calls + `git fetch`) to lookup the default branch for merging. Without + this option, `git pull` defaults to merge the first refspec fetched. Specify multiple values to get an octopus merge. - If you wish to setup 'git pull' so that it merges into <name> from + If you wish to setup `git pull` so that it merges into <name> from another branch in the local repository, you can point branch.<name>.merge to the desired branch, and use the relative path - setting `.` (a period) for branch.<name>.remote. + setting `.` (a period) for `branch.<name>.remote`. -branch.<name>.mergeOptions:: - Sets default options for merging into branch <name>. The syntax and +`branch.<name>.mergeOptions`:: + Sets default options for merging into branch _<name>_. The syntax and supported options are the same as those of linkgit:git-merge[1], but option values containing whitespace characters are currently not supported. -branch.<name>.rebase:: - When true, rebase the branch <name> on top of the fetched branch, +`branch.<name>.rebase`:: + When true, rebase the branch _<name>_ on top of the fetched branch, instead of merging the default branch from the default remote when - "git pull" is run. See "pull.rebase" for doing this in a non + `git pull` is run. See `pull.rebase` for doing this in a non branch-specific manner. + -When `merges` (or just 'm'), pass the `--rebase-merges` option to 'git rebase' +When `merges` (or just `m`), pass the `--rebase-merges` option to `git rebase` so that the local merge commits are included in the rebase (see linkgit:git-rebase[1] for details). + -When the value is `interactive` (or just 'i'), the rebase is run in interactive +When the value is `interactive` (or just `i`), the rebase is run in interactive mode. + *NOTE*: this is a possibly dangerous operation; do *not* use it unless you understand the implications (see linkgit:git-rebase[1] for details). -branch.<name>.description:: +`branch.<name>.description`:: Branch description, can be edited with `git branch --edit-description`. Branch description is - automatically added to the format-patch cover letter or - request-pull summary. + automatically added to the `format-patch` cover letter or + `request-pull` summary. diff --git a/Documentation/config/checkout.adoc b/Documentation/config/checkout.adoc index a323022993..e35d212969 100644 --- a/Documentation/config/checkout.adoc +++ b/Documentation/config/checkout.adoc @@ -1,9 +1,9 @@ -checkout.defaultRemote:: +`checkout.defaultRemote`:: When you run `git checkout <something>` or `git switch <something>` and only have one remote, it may implicitly fall back on checking out and tracking e.g. `origin/<something>`. This stops working as soon - as you have more than one remote with a `<something>` + as you have more than one remote with a _<something>_ reference. This setting allows for setting the name of a preferred remote that should always win when it comes to disambiguation. The typical use-case is to set this to @@ -12,17 +12,17 @@ checkout.defaultRemote:: Currently this is used by linkgit:git-switch[1] and linkgit:git-checkout[1] when `git checkout <something>` or `git switch <something>` -will checkout the `<something>` branch on another remote, +will checkout the _<something>_ branch on another remote, and by linkgit:git-worktree[1] when `git worktree add` refers to a remote branch. This setting might be used for other checkout-like commands or functionality in the future. -checkout.guess:: +`checkout.guess`:: Provides the default value for the `--guess` or `--no-guess` option in `git checkout` and `git switch`. See linkgit:git-switch[1] and linkgit:git-checkout[1]. -checkout.workers:: +`checkout.workers`:: The number of parallel workers to use when updating the working tree. The default is one, i.e. sequential execution. If set to a value less than one, Git will use as many workers as the number of logical cores @@ -30,13 +30,13 @@ checkout.workers:: all commands that perform checkout. E.g. checkout, clone, reset, sparse-checkout, etc. + -Note: Parallel checkout usually delivers better performance for repositories +NOTE: Parallel checkout usually delivers better performance for repositories located on SSDs or over NFS. For repositories on spinning disks and/or machines with a small number of cores, the default sequential checkout often performs better. The size and compression level of a repository might also influence how well the parallel version performs. -checkout.thresholdForParallelism:: +`checkout.thresholdForParallelism`:: When running parallel checkout with a small number of files, the cost of subprocess spawning and inter-process communication might outweigh the parallelization gains. This setting allows you to define the minimum diff --git a/Documentation/config/commit.adoc b/Documentation/config/commit.adoc index d3f4624fd2..208ae76c81 100644 --- a/Documentation/config/commit.adoc +++ b/Documentation/config/commit.adoc @@ -8,10 +8,11 @@ endif::git-commit[] This setting overrides the default of the `--cleanup` option in `git commit`. {see-git-commit} Changing the default can be useful when you always want to keep lines that begin - with the comment character `#` in your log message, in which case you + with the comment character (`core.commentChar`, default `#`) + in your log message, in which case you would do `git config commit.cleanup whitespace` (note that you will - have to remove the help lines that begin with `#` in the commit log - template yourself, if you do this). + have to remove the help lines that begin with the comment character + in the commit log template yourself, if you do this). `commit.gpgSign`:: A boolean to specify whether all commits should be GPG signed. diff --git a/Documentation/config/core.adoc b/Documentation/config/core.adoc index 8f6d8e7754..9fde1ab63a 100644 --- a/Documentation/config/core.adoc +++ b/Documentation/config/core.adoc @@ -512,6 +512,11 @@ centrally configure your Git hooks instead of configuring them on a per-repository basis, or as a more flexible and centralized alternative to having an `init.templateDir` where you've changed default hooks. ++ +You can also disable all hooks entirely by setting `core.hooksPath` +to `/dev/null`. This is usually only advisable for expert users and +on a per-command basis using configuration parameters of the form +`git -c core.hooksPath=/dev/null ...`. core.editor:: Commands such as `commit` and `tag` that let you edit diff --git a/Documentation/config/feature.adoc b/Documentation/config/feature.adoc index f061b64b74..cb49ff2604 100644 --- a/Documentation/config/feature.adoc +++ b/Documentation/config/feature.adoc @@ -20,6 +20,10 @@ walking fewer objects. + * `pack.allowPackReuse=multi` may improve the time it takes to create a pack by reusing objects from multiple packs instead of just one. ++ +* `pack.usePathWalk` may speed up packfile creation and make the packfiles be +significantly smaller in the presence of certain filename collisions with Git's +default name-hash. feature.manyFiles:: Enable config options that optimize for repos with many files in the diff --git a/Documentation/config/fmt-merge-msg.adoc b/Documentation/config/fmt-merge-msg.adoc index 3fbf40e24f..696ba0531a 100644 --- a/Documentation/config/fmt-merge-msg.adoc +++ b/Documentation/config/fmt-merge-msg.adoc @@ -1,19 +1,19 @@ -merge.branchdesc:: +`merge.branchdesc`:: In addition to branch names, populate the log message with the branch description text associated with them. Defaults to false. -merge.log:: +`merge.log`:: In addition to branch names, populate the log message with at most the specified number of one-line descriptions from the actual commits that are being merged. Defaults to false, and true is a synonym for 20. -merge.suppressDest:: +`merge.suppressDest`:: By adding a glob that matches the names of integration branches to this multi-valued configuration variable, the default merge message computed for merges into these - integration branches will omit "into <branch name>" from + integration branches will omit "into _<branch-name>_" from its title. + An element with an empty value can be used to clear the list diff --git a/Documentation/config/gitcvs.adoc b/Documentation/config/gitcvs.adoc index 02da427fd9..31d7be3992 100644 --- a/Documentation/config/gitcvs.adoc +++ b/Documentation/config/gitcvs.adoc @@ -47,7 +47,8 @@ gitcvs.dbDriver:: May not contain double colons (`:`). Default: 'SQLite'. See linkgit:git-cvsserver[1]. -gitcvs.dbUser, gitcvs.dbPass:: +gitcvs.dbUser:: +gitcvs.dbPass:: Database user and password. Only useful if setting `gitcvs.dbDriver`, since SQLite has no concept of database users and/or passwords. 'gitcvs.dbUser' supports variable substitution (see diff --git a/Documentation/config/http.adoc b/Documentation/config/http.adoc index 22a8803dea..9da5c298cc 100644 --- a/Documentation/config/http.adoc +++ b/Documentation/config/http.adoc @@ -289,13 +289,32 @@ for most push problems, but can increase memory consumption significantly since the entire buffer is allocated even for small pushes. -http.lowSpeedLimit, http.lowSpeedTime:: +http.lowSpeedLimit:: +http.lowSpeedTime:: If the HTTP transfer speed, in bytes per second, is less than 'http.lowSpeedLimit' for longer than 'http.lowSpeedTime' seconds, the transfer is aborted. Can be overridden by the `GIT_HTTP_LOW_SPEED_LIMIT` and `GIT_HTTP_LOW_SPEED_TIME` environment variables. +http.keepAliveIdle:: + Specifies how long in seconds to wait on an idle connection + before sending TCP keepalive probes (if supported by the OS). If + unset, curl's default value is used. Can be overridden by the + `GIT_HTTP_KEEPALIVE_IDLE` environment variable. + +http.keepAliveInterval:: + Specifies how long in seconds to wait between TCP keepalive + probes (if supported by the OS). If unset, curl's default value + is used. Can be overridden by the `GIT_HTTP_KEEPALIVE_INTERVAL` + environment variable. + +http.keepAliveCount:: + Specifies how many TCP keepalive probes to send before giving up + and terminating the connection (if supported by the OS). If + unset, curl's default value is used. Can be overridden by the + `GIT_HTTP_KEEPALIVE_COUNT` environment variable. + http.noEPSV:: A boolean which disables using of EPSV ftp command by curl. This can be helpful with some "poor" ftp servers which don't diff --git a/Documentation/config/maintenance.adoc b/Documentation/config/maintenance.adoc index 72a9d6cf81..2f71934218 100644 --- a/Documentation/config/maintenance.adoc +++ b/Documentation/config/maintenance.adoc @@ -61,6 +61,11 @@ maintenance.loose-objects.auto:: loose objects is at least the value of `maintenance.loose-objects.auto`. The default value is 100. +maintenance.loose-objects.batchSize:: + This integer config option controls the maximum number of loose objects + written into a packfile during the `loose-objects` task. The default is + fifty thousand. Use value `0` to indicate no limit. + maintenance.incremental-repack.auto:: This integer config option controls how often the `incremental-repack` task should be run as part of `git maintenance run --auto`. If zero, @@ -69,3 +74,29 @@ maintenance.incremental-repack.auto:: Otherwise, a positive value implies the command should run when the number of pack-files not in the multi-pack-index is at least the value of `maintenance.incremental-repack.auto`. The default value is 10. + +maintenance.reflog-expire.auto:: + This integer config option controls how often the `reflog-expire` task + should be run as part of `git maintenance run --auto`. If zero, then + the `reflog-expire` task will not run with the `--auto` option. A + negative value will force the task to run every time. Otherwise, a + positive value implies the command should run when the number of + expired reflog entries in the "HEAD" reflog is at least the value of + `maintenance.loose-objects.auto`. The default value is 100. + +maintenance.rerere-gc.auto:: + This integer config option controls how often the `rerere-gc` task + should be run as part of `git maintenance run --auto`. If zero, then + the `rerere-gc` task will not run with the `--auto` option. A negative + value will force the task to run every time. Otherwise, any positive + value implies the command will run when the "rr-cache" directory exists + and has at least one entry, regardless of whether it is stale or not. + This heuristic may be refined in the future. The default value is 1. + +maintenance.worktree-prune.auto:: + This integer config option controls how often the `worktree-prune` task + should be run as part of `git maintenance run --auto`. If zero, then + the `worktree-prune` task will not run with the `--auto` option. A + negative value will force the task to run every time. Otherwise, a + positive value implies the command should run when the number of + prunable worktrees exceeds the value. The default value is 1. diff --git a/Documentation/config/merge.adoc b/Documentation/config/merge.adoc index d2d0f21a71..86359f6dd2 100644 --- a/Documentation/config/merge.adoc +++ b/Documentation/config/merge.adoc @@ -1,9 +1,9 @@ -merge.conflictStyle:: +`merge.conflictStyle`:: Specify the style in which conflicted hunks are written out to working tree files upon merge. The default is "merge", which - shows a `<<<<<<<` conflict marker, changes made by one side, + shows a +<<<<<<<+ conflict marker, changes made by one side, a `=======` marker, changes made by the other side, and then - a `>>>>>>>` marker. An alternate style, "diff3", adds a `|||||||` + a +>>>>>>>+ marker. An alternate style, "diff3", adds a +|||||||+ marker and the original text before the `=======` marker. The "merge" style tends to produce smaller conflict regions than diff3, both because of the exclusion of the original text, and because @@ -13,17 +13,17 @@ merge.conflictStyle:: the conflict region when those matching lines appear near either the beginning or end of a conflict region. -merge.defaultToUpstream:: +`merge.defaultToUpstream`:: If merge is called without any commit argument, merge the upstream branches configured for the current branch by using their last observed values stored in their remote-tracking branches. The values of the `branch.<current branch>.merge` that name the - branches at the remote named by `branch.<current branch>.remote` + branches at the remote named by `branch.<current-branch>.remote` are consulted, and then they are mapped via `remote.<remote>.fetch` to their corresponding remote-tracking branches, and the tips of these tracking branches are merged. Defaults to true. -merge.ff:: +`merge.ff`:: By default, Git does not create an extra merge commit when merging a commit that is a descendant of the current commit. Instead, the tip of the current branch is fast-forwarded. When set to `false`, @@ -33,42 +33,46 @@ merge.ff:: allowed (equivalent to giving the `--ff-only` option from the command line). -merge.verifySignatures:: - If true, this is equivalent to the --verify-signatures command +`merge.verifySignatures`:: + If true, this is equivalent to the `--verify-signatures` command line option. See linkgit:git-merge[1] for details. include::fmt-merge-msg.adoc[] -merge.renameLimit:: +`merge.renameLimit`:: The number of files to consider in the exhaustive portion of rename detection during a merge. If not specified, defaults - to the value of diff.renameLimit. If neither - merge.renameLimit nor diff.renameLimit are specified, + to the value of `diff.renameLimit`. If neither + `merge.renameLimit` nor `diff.renameLimit` are specified, currently defaults to 7000. This setting has no effect if rename detection is turned off. -merge.renames:: - Whether Git detects renames. If set to "false", rename detection - is disabled. If set to "true", basic rename detection is enabled. +`merge.renames`:: + Whether Git detects renames. If set to `false`, rename detection + is disabled. If set to `true`, basic rename detection is enabled. Defaults to the value of diff.renames. -merge.directoryRenames:: +`merge.directoryRenames`:: Whether Git detects directory renames, affecting what happens at merge time to new files added to a directory on one side of history when that directory was renamed on the other side of - history. If merge.directoryRenames is set to "false", directory - rename detection is disabled, meaning that such new files will be - left behind in the old directory. If set to "true", directory - rename detection is enabled, meaning that such new files will be - moved into the new directory. If set to "conflict", a conflict - will be reported for such paths. If merge.renames is false, - merge.directoryRenames is ignored and treated as false. Defaults - to "conflict". - -merge.renormalize:: + history. Possible values are: ++ +-- +`false`;; Directory rename detection is disabled, meaning that such new files will be + left behind in the old directory. +`true`;; Directory rename detection is enabled, meaning that such new files will be + moved into the new directory. +`conflict`;; A conflict will be reported for such paths. +-- ++ +If `merge.renames` is `false`, `merge.directoryRenames` is ignored and treated +as `false`. Defaults to `conflict`. + +`merge.renormalize`:: Tell Git that canonical representation of files in the repository has changed over time (e.g. earlier commits record - text files with CRLF line endings, but recent ones use LF line + text files with _CRLF_ line endings, but recent ones use _LF_ line endings). In such a repository, for each file where a three-way content merge is needed, Git can convert the data recorded in commits to a canonical form before performing a @@ -76,35 +80,35 @@ merge.renormalize:: see section "Merging branches with differing checkin/checkout attributes" in linkgit:gitattributes[5]. -merge.stat:: - Whether to print the diffstat between ORIG_HEAD and the merge result +`merge.stat`:: + Whether to print the diffstat between `ORIG_HEAD` and the merge result at the end of the merge. True by default. -merge.autoStash:: - When set to true, automatically create a temporary stash entry +`merge.autoStash`:: + When set to `true`, automatically create a temporary stash entry before the operation begins, and apply it after the operation ends. This means that you can run merge on a dirty worktree. However, use with care: the final stash application after a successful merge might result in non-trivial conflicts. This option can be overridden by the `--no-autostash` and `--autostash` options of linkgit:git-merge[1]. - Defaults to false. + Defaults to `false`. -merge.tool:: +`merge.tool`:: Controls which merge tool is used by linkgit:git-mergetool[1]. The list below shows the valid built-in values. Any other value is treated as a custom merge tool and requires - that a corresponding mergetool.<tool>.cmd variable is defined. + that a corresponding `mergetool.<tool>.cmd` variable is defined. -merge.guitool:: +`merge.guitool`:: Controls which merge tool is used by linkgit:git-mergetool[1] when the - -g/--gui flag is specified. The list below shows the valid built-in values. + `-g`/`--gui` flag is specified. The list below shows the valid built-in values. Any other value is treated as a custom merge tool and requires that a - corresponding mergetool.<guitool>.cmd variable is defined. + corresponding `mergetool.<guitool>.cmd` variable is defined. include::{build_dir}/mergetools-merge.adoc[] -merge.verbosity:: +`merge.verbosity`:: Controls the amount of output shown by the recursive merge strategy. Level 0 outputs nothing except a final error message if conflicts were detected. Level 1 outputs only @@ -112,15 +116,15 @@ merge.verbosity:: above outputs debugging information. The default is level 2. Can be overridden by the `GIT_MERGE_VERBOSITY` environment variable. -merge.<driver>.name:: +`merge.<driver>.name`:: Defines a human-readable name for a custom low-level merge driver. See linkgit:gitattributes[5] for details. -merge.<driver>.driver:: +`merge.<driver>.driver`:: Defines the command that implements a custom low-level merge driver. See linkgit:gitattributes[5] for details. -merge.<driver>.recursive:: +`merge.<driver>.recursive`:: Names a low-level merge driver to be used when performing an internal merge between common ancestors. See linkgit:gitattributes[5] for details. diff --git a/Documentation/config/mergetool.adoc b/Documentation/config/mergetool.adoc index 00bf665aa0..6be506145c 100644 --- a/Documentation/config/mergetool.adoc +++ b/Documentation/config/mergetool.adoc @@ -1,24 +1,24 @@ -mergetool.<tool>.path:: +`mergetool.<tool>.path`:: Override the path for the given tool. This is useful in case - your tool is not in the PATH. + your tool is not in the `$PATH`. -mergetool.<tool>.cmd:: +`mergetool.<tool>.cmd`:: Specify the command to invoke the specified merge tool. The specified command is evaluated in shell with the following - variables available: 'BASE' is the name of a temporary file + variables available: `BASE` is the name of a temporary file containing the common base of the files to be merged, if available; - 'LOCAL' is the name of a temporary file containing the contents of - the file on the current branch; 'REMOTE' is the name of a temporary + `LOCAL` is the name of a temporary file containing the contents of + the file on the current branch; `REMOTE` is the name of a temporary file containing the contents of the file from the branch being - merged; 'MERGED' contains the name of the file to which the merge + merged; `MERGED` contains the name of the file to which the merge tool should write the results of a successful merge. -mergetool.<tool>.hideResolved:: +`mergetool.<tool>.hideResolved`:: Allows the user to override the global `mergetool.hideResolved` value for a specific tool. See `mergetool.hideResolved` for the full description. -mergetool.<tool>.trustExitCode:: +`mergetool.<tool>.trustExitCode`:: For a custom merge command, specify whether the exit code of the merge command can be used to determine whether the merge was successful. If this is not set to true then the merge target file @@ -26,7 +26,7 @@ mergetool.<tool>.trustExitCode:: if the file has been updated; otherwise, the user is prompted to indicate the success of the merge. -mergetool.meld.hasOutput:: +`mergetool.meld.hasOutput`:: Older versions of `meld` do not support the `--output` option. Git will attempt to detect whether `meld` supports `--output` by inspecting the output of `meld --help`. Configuring @@ -35,7 +35,7 @@ mergetool.meld.hasOutput:: to `true` tells Git to unconditionally use the `--output` option, and `false` avoids using `--output`. -mergetool.meld.useAutoMerge:: +`mergetool.meld.useAutoMerge`:: When the `--auto-merge` is given, meld will merge all non-conflicting parts automatically, highlight the conflicting parts, and wait for user decision. Setting `mergetool.meld.useAutoMerge` to `true` tells @@ -45,15 +45,15 @@ mergetool.meld.useAutoMerge:: value of `false` avoids using `--auto-merge` altogether, and is the default value. -mergetool.<vimdiff variant>.layout:: - Configure the split window layout for vimdiff's `<variant>`, which is any of `vimdiff`, +`mergetool.<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 + 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 + 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` + will be used. To configure the layout, see the 'BACKEND SPECIFIC HINTS' ifdef::git-mergetool[] section. endif::[] @@ -61,39 +61,39 @@ ifndef::git-mergetool[] section in linkgit:git-mergetool[1]. endif::[] -mergetool.hideResolved:: +`mergetool.hideResolved`:: During a merge, Git will automatically resolve as many conflicts as - possible and write the 'MERGED' file containing conflict markers around - any conflicts that it cannot resolve; 'LOCAL' and 'REMOTE' normally - represent the versions of the file from before Git's conflict - resolution. This flag causes 'LOCAL' and 'REMOTE' to be overwritten so + possible and write the `$MERGED` file containing conflict markers around + any conflicts that it cannot resolve; `$LOCAL` and `$REMOTE` normally + are the versions of the file from before Git`s conflict + resolution. This flag causes `$LOCAL` and `$REMOTE` to be overwritten so that only the unresolved conflicts are presented to the merge tool. Can be configured per-tool via the `mergetool.<tool>.hideResolved` configuration variable. Defaults to `false`. -mergetool.keepBackup:: +`mergetool.keepBackup`:: After performing a merge, the original file with conflict markers can be saved as a file with a `.orig` extension. If this variable is set to `false` then this file is not preserved. Defaults to `true` (i.e. keep the backup files). -mergetool.keepTemporaries:: +`mergetool.keepTemporaries`:: When invoking a custom merge tool, Git uses a set of temporary files to pass to the tool. If the tool returns an error and this variable is set to `true`, then these temporary files will be preserved; otherwise, they will be removed after the tool has exited. Defaults to `false`. -mergetool.writeToTemp:: - Git writes temporary 'BASE', 'LOCAL', and 'REMOTE' versions of +`mergetool.writeToTemp`:: + Git writes temporary `BASE`, `LOCAL`, and `REMOTE` versions of conflicting files in the worktree by default. Git will attempt to use a temporary directory for these files when set `true`. Defaults to `false`. -mergetool.prompt:: +`mergetool.prompt`:: Prompt before each invocation of the merge resolution program. -mergetool.guiDefault:: +`mergetool.guiDefault`:: Set `true` to use the `merge.guitool` by default (equivalent to specifying the `--gui` argument), or `auto` to select `merge.guitool` or `merge.tool` depending on the presence of a `DISPLAY` environment diff --git a/Documentation/config/pack.adoc b/Documentation/config/pack.adoc index da527377fa..75402d5579 100644 --- a/Documentation/config/pack.adoc +++ b/Documentation/config/pack.adoc @@ -155,6 +155,10 @@ pack.useSparse:: commits contain certain types of direct renames. Default is `true`. +pack.usePathWalk:: + Enable the `--path-walk` option by default for `git pack-objects` + processes. See linkgit:git-pack-objects[1] for full details. + pack.preferBitmapTips:: When selecting which commits will receive bitmaps, prefer a commit at the tip of any reference that is a suffix of any value diff --git a/Documentation/config/promisor.adoc b/Documentation/config/promisor.adoc index 9192acfd24..2638b01f83 100644 --- a/Documentation/config/promisor.adoc +++ b/Documentation/config/promisor.adoc @@ -26,5 +26,5 @@ promisor.acceptFromServer:: server will be accepted. By accepting a promisor remote, the client agrees that the server might omit objects that are lazily fetchable from this promisor remote from its responses - to "fetch" and "clone" requests from the client. See - linkgit:gitprotocol-v2[5]. + to "fetch" and "clone" requests from the client. Name and URL + comparisons are case sensitive. See linkgit:gitprotocol-v2[5]. diff --git a/Documentation/config/remote.adoc b/Documentation/config/remote.adoc index 25fe219d10..91e46f66f5 100644 --- a/Documentation/config/remote.adoc +++ b/Documentation/config/remote.adoc @@ -108,7 +108,8 @@ the values inherited from a lower priority configuration files (e.g. `$HOME/.gitconfig`). remote.<name>.followRemoteHEAD:: - How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`. + How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD` + when fetching using the configured refspecs of a remote. The default value is "create", which will create `remotes/<name>/HEAD` if it exists on the remote, but not locally; this will not touch an already existing local reference. Setting it to "warn" will print diff --git a/Documentation/config/sendemail.adoc b/Documentation/config/sendemail.adoc index 5ffcfc9f2a..54f1248e64 100644 --- a/Documentation/config/sendemail.adoc +++ b/Documentation/config/sendemail.adoc @@ -1,32 +1,32 @@ sendemail.identity:: A configuration identity. When given, causes values in the - 'sendemail.<identity>' subsection to take precedence over - values in the 'sendemail' section. The default identity is + `sendemail.<identity>` subsection to take precedence over + values in the `sendemail` section. The default identity is the value of `sendemail.identity`. sendemail.smtpEncryption:: See linkgit:git-send-email[1] for description. Note that this - setting is not subject to the 'identity' mechanism. + setting is not subject to the `identity` mechanism. sendemail.smtpSSLCertPath:: Path to ca-certificates (either a directory or a single file). Set it to an empty string to disable certificate verification. sendemail.<identity>.*:: - Identity-specific versions of the 'sendemail.*' parameters + Identity-specific versions of the `sendemail.*` parameters found below, taking precedence over those when this identity is selected, through either the command-line or `sendemail.identity`. sendemail.multiEdit:: - If true (default), a single editor instance will be spawned to edit + If `true` (default), a single editor instance will be spawned to edit files you have to edit (patches when `--annotate` is used, and the - summary when `--compose` is used). If false, files will be edited one + summary when `--compose` is used). If `false`, files will be edited one after the other, spawning a new editor each time. sendemail.confirm:: Sets the default for whether to confirm before sending. Must be - one of 'always', 'never', 'cc', 'compose', or 'auto'. See `--confirm` + one of `always`, `never`, `cc`, `compose`, or `auto`. See `--confirm` in the linkgit:git-send-email[1] documentation for the meaning of these values. @@ -51,7 +51,7 @@ sendemail.aliasesFile:: sendemail.aliasFileType:: Format of the file(s) specified in sendemail.aliasesFile. Must be - one of 'mutt', 'mailrc', 'pine', 'elm', 'gnus', or 'sendmail'. + one of `mutt`, `mailrc`, `pine`, `elm`, `gnus`, or `sendmail`. + What an alias file in each format looks like can be found in the documentation of the email program of the same name. The @@ -101,7 +101,7 @@ sendemail.signedOffCc (deprecated):: sendemail.smtpBatchSize:: Number of messages to be sent per connection, after that a relogin - will happen. If the value is 0 or undefined, send all messages in + will happen. If the value is `0` or undefined, send all messages in one connection. See also the `--batch-size` option of linkgit:git-send-email[1]. @@ -111,5 +111,5 @@ sendemail.smtpReloginDelay:: sendemail.forbidSendmailVariables:: To avoid common misconfiguration mistakes, linkgit:git-send-email[1] - will abort with a warning if any configuration options for "sendmail" + will abort with a warning if any configuration options for `sendmail` exist. Set this variable to bypass the check. diff --git a/Documentation/diff-generate-patch.adoc b/Documentation/diff-generate-patch.adoc index e5c813c96f..7b6cdd1980 100644 --- a/Documentation/diff-generate-patch.adoc +++ b/Documentation/diff-generate-patch.adoc @@ -138,7 +138,7 @@ or like this (when the `--cc` option is used): + [synopsis] index <hash>,<hash>..<hash> -mode <mode>,<mode>`..`<mode> +mode <mode>,<mode>..<mode> new file mode <mode> deleted file mode <mode>,<mode> + diff --git a/Documentation/fix-texi.perl b/Documentation/fix-texi.perl deleted file mode 100755 index ff7d78f620..0000000000 --- a/Documentation/fix-texi.perl +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/perl -w - -while (<>) { - if (/^\@setfilename/) { - $_ = "\@setfilename git.info\n"; - } elsif (/^\@direntry/) { - print '@dircategory Development -@direntry -* Git: (git). A fast distributed revision control system -@end direntry -'; } - unless (/^\@direntry/../^\@end direntry/) { - print; - } -} diff --git a/Documentation/fix-texi.sh b/Documentation/fix-texi.sh new file mode 100755 index 0000000000..bc300f7b0f --- /dev/null +++ b/Documentation/fix-texi.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +awk ' + /^@setfilename/{ + print "@setfilename git.info" + next + } + /^@direntry/{ + direntry=1 + print "@dircategory Development" + print "@direntry" + print "* Git: (git). A fast distributed revision control system" + print "@end direntry" + next + } + /^@end direntry/{ + direntry=0 + next + } + !direntry +' diff --git a/Documentation/fsck-msgids.adoc b/Documentation/fsck-msgids.adoc index b14bc44ca4..0ba4f9a27e 100644 --- a/Documentation/fsck-msgids.adoc +++ b/Documentation/fsck-msgids.adoc @@ -16,6 +16,13 @@ `badObjectSha1`:: (ERROR) An object has a bad sha1. +`badPackedRefEntry`:: + (ERROR) The "packed-refs" file contains an invalid entry. + +`badPackedRefHeader`:: + (ERROR) The "packed-refs" file contains an invalid + header. + `badParentSha1`:: (ERROR) A commit object has a bad parent sha1. @@ -52,6 +59,12 @@ `emptyName`:: (WARN) A path contains an empty name. +`emptyPackedRefsFile`:: + (INFO) "packed-refs" file is empty. Report to the + git@vger.kernel.org mailing list if you see this error. As only + very early versions of Git would create such an empty + "packed_refs" file, we might tighten this rule in the future. + `extraHeaderEntry`:: (IGNORE) Extra headers found after `tagger`. @@ -176,6 +189,13 @@ `nullSha1`:: (WARN) Tree contains entries pointing to a null sha1. +`packedRefEntryNotTerminated`:: + (ERROR) The "packed-refs" file contains an entry that is + not terminated by a newline. + +`packedRefUnsorted`:: + (ERROR) The "packed-refs" file is not sorted. + `refMissingNewline`:: (INFO) A loose ref that does not end with newline(LF). As valid implementations of Git never created such a loose ref diff --git a/Documentation/git-bisect.adoc b/Documentation/git-bisect.adoc index 82f944dc03..58dbb74a15 100644 --- a/Documentation/git-bisect.adoc +++ b/Documentation/git-bisect.adoc @@ -495,6 +495,7 @@ $ git bisect old HEAD~10 # the tenth commit from now is marked as old ------------ + or: ++ ------------ $ git bisect start --term-old broken --term-new fixed $ git bisect fixed diff --git a/Documentation/git-blame.adoc b/Documentation/git-blame.adoc index f75ed44790..e438d28625 100644 --- a/Documentation/git-blame.adoc +++ b/Documentation/git-blame.adoc @@ -135,10 +135,11 @@ header elements later. The porcelain format generally suppresses commit information that has already been seen. For example, two lines that are blamed to the same commit will both be shown, but the details for that commit will be shown -only once. This is more efficient, but may require more state be kept by -the reader. The `--line-porcelain` option can be used to output full -commit information for each line, allowing simpler (but less efficient) -usage like: +only once. Information which is specific to individual lines will not be +grouped together, like revs to be marked 'ignored' or 'unblamable'. This +is more efficient, but may require more state be kept by the reader. The +`--line-porcelain` option can be used to output full commit information +for each line, allowing simpler (but less efficient) usage like: # count the number of lines attributed to each author git blame --line-porcelain file | diff --git a/Documentation/git-branch.adoc b/Documentation/git-branch.adoc index 7a073a36d6..c0afddc424 100644 --- a/Documentation/git-branch.adoc +++ b/Documentation/git-branch.adoc @@ -7,23 +7,23 @@ git-branch - List, create, or delete branches SYNOPSIS -------- -[verse] -'git branch' [--color[=<when>] | --no-color] [--show-current] - [-v [--abbrev=<n> | --no-abbrev]] - [--column[=<options>] | --no-column] [--sort=<key>] - [--merged [<commit>]] [--no-merged [<commit>]] - [--contains [<commit>]] [--no-contains [<commit>]] - [--points-at <object>] [--format=<format>] - [(-r | --remotes) | (-a | --all)] - [--list] [<pattern>...] -'git branch' [--track[=(direct|inherit)] | --no-track] [-f] - [--recurse-submodules] <branchname> [<start-point>] -'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>] -'git branch' --unset-upstream [<branchname>] -'git branch' (-m | -M) [<oldbranch>] <newbranch> -'git branch' (-c | -C) [<oldbranch>] <newbranch> -'git branch' (-d | -D) [-r] <branchname>... -'git branch' --edit-description [<branchname>] +[synopsis] +git branch [--color[=<when>] | --no-color] [--show-current] + [-v [--abbrev=<n> | --no-abbrev]] + [--column[=<options>] | --no-column] [--sort=<key>] + [--merged [<commit>]] [--no-merged [<commit>]] + [--contains [<commit>]] [--no-contains [<commit>]] + [--points-at <object>] [--format=<format>] + [(-r|--remotes) | (-a|--all)] + [--list] [<pattern>...] +git branch [--track[=(direct|inherit)] | --no-track] [-f] + [--recurse-submodules] <branch-name> [<start-point>] +git branch (--set-upstream-to=<upstream>|-u <upstream>) [<branch-name>] +git branch --unset-upstream [<branch-name>] +git branch (-m|-M) [<old-branch>] <new-branch> +git branch (-c|-C) [<old-branch>] <new-branch> +git branch (-d|-D) [-r] <branch-name>... +git branch --edit-description [<branch-name>] DESCRIPTION ----------- @@ -49,173 +49,184 @@ With `--contains`, shows only the branches that contain the named commit named commit), `--no-contains` inverts it. With `--merged`, only branches merged into the named commit (i.e. the branches whose tip commits are reachable from the named commit) will be listed. With `--no-merged` only -branches not merged into the named commit will be listed. If the <commit> +branches not merged into the named commit will be listed. If the _<commit>_ argument is missing it defaults to `HEAD` (i.e. the tip of the current branch). -The command's second form creates a new branch head named <branchname> -which points to the current `HEAD`, or <start-point> if given. As a -special case, for <start-point>, you may use `"A...B"` as a shortcut for -the merge base of `A` and `B` if there is exactly one merge base. You -can leave out at most one of `A` and `B`, in which case it defaults to -`HEAD`. +The command's second form creates a new branch head named _<branch-name>_ +which points to the current `HEAD`, or _<start-point>_ if given. As a +special case, for _<start-point>_, you may use `<rev-A>...<rev-B>` as a +shortcut for the merge base of _<rev-A>_ and _<rev-B>_ if there is exactly +one merge base. You can leave out at most one of _<rev-A>_ and _<rev-B>_, +in which case it defaults to `HEAD`. Note that this will create the new branch, but it will not switch the -working tree to it; use "git switch <newbranch>" to switch to the +working tree to it; use `git switch <new-branch>` to switch to the new branch. When a local branch is started off a remote-tracking branch, Git sets up the branch (specifically the `branch.<name>.remote` and `branch.<name>.merge` -configuration entries) so that 'git pull' will appropriately merge from +configuration entries) so that `git pull` will appropriately merge from the remote-tracking branch. This behavior may be changed via the global `branch.autoSetupMerge` configuration flag. That setting can be overridden by using the `--track` and `--no-track` options, and changed later using `git branch --set-upstream-to`. -With a `-m` or `-M` option, <oldbranch> will be renamed to <newbranch>. -If <oldbranch> had a corresponding reflog, it is renamed to match -<newbranch>, and a reflog entry is created to remember the branch -renaming. If <newbranch> exists, -M must be used to force the rename +With a `-m` or `-M` option, _<old-branch>_ will be renamed to _<new-branch>_. +If _<old-branch>_ had a corresponding reflog, it is renamed to match +_<new-branch>_, and a reflog entry is created to remember the branch +renaming. If _<new-branch>_ exists, `-M` must be used to force the rename to happen. The `-c` and `-C` options have the exact same semantics as `-m` and `-M`, except instead of the branch being renamed, it will be copied to a new name, along with its config and reflog. -With a `-d` or `-D` option, `<branchname>` will be deleted. You may +With a `-d` or `-D` option, _<branch-name>_ will be deleted. You may specify more than one branch for deletion. If the branch currently has a reflog then the reflog will also be deleted. Use `-r` together with `-d` to delete remote-tracking branches. Note, that it only makes sense to delete remote-tracking branches if they no longer exist -in the remote repository or if 'git fetch' was configured not to fetch -them again. See also the 'prune' subcommand of linkgit:git-remote[1] for a +in the remote repository or if `git fetch` was configured not to fetch +them again. See also the `prune` subcommand of linkgit:git-remote[1] for a way to clean up all obsolete remote-tracking branches. OPTIONS ------- --d:: ---delete:: +`-d`:: +`--delete`:: Delete a branch. The branch must be fully merged in its upstream branch, or in `HEAD` if no upstream was set with `--track` or `--set-upstream-to`. --D:: +`-D`:: Shortcut for `--delete --force`. ---create-reflog:: +`--create-reflog`:: Create the branch's reflog. This activates recording of all changes made to the branch ref, enabling use of date - based sha1 expressions such as "<branchname>@\{yesterday}". + based sha1 expressions such as `<branch-name>@{yesterday}`. Note that in non-bare repositories, reflogs are usually enabled by default by the `core.logAllRefUpdates` config option. The negated form `--no-create-reflog` only overrides an earlier `--create-reflog`, but currently does not negate the setting of `core.logAllRefUpdates`. --f:: ---force:: - Reset <branchname> to <start-point>, even if <branchname> exists - already. Without `-f`, 'git branch' refuses to change an existing branch. +`-f`:: +`--force`:: + Reset _<branch-name>_ to _<start-point>_, even if _<branch-name>_ exists + already. Without `-f`, `git branch` refuses to change an existing branch. In combination with `-d` (or `--delete`), allow deleting the branch irrespective of its merged status, or whether it even points to a valid commit. In combination with `-m` (or `--move`), allow renaming the branch even if the new branch name already exists, the same applies for `-c` (or `--copy`). + -Note that 'git branch -f <branchname> [<start-point>]', even with '-f', -refuses to change an existing branch `<branchname>` that is checked out +Note that `git branch -f <branch-name> [<start-point>]`, even with `-f`, +refuses to change an existing branch _<branch-name>_ that is checked out in another worktree linked to the same repository. --m:: ---move:: +`-m`:: +`--move`:: Move/rename a branch, together with its config and reflog. --M:: +`-M`:: Shortcut for `--move --force`. --c:: ---copy:: +`-c`:: +`--copy`:: Copy a branch, together with its config and reflog. --C:: +`-C`:: Shortcut for `--copy --force`. ---color[=<when>]:: +`--color[=<when>]`:: Color branches to highlight current, local, and remote-tracking branches. - The value must be always (the default), never, or auto. + The value must be `always` (the default), `never`, or `auto`. ---no-color:: +`--no-color`:: Turn off branch colors, even when the configuration file gives the default to color output. Same as `--color=never`. --i:: ---ignore-case:: +`-i`:: +`--ignore-case`:: Sorting and filtering branches are case insensitive. ---omit-empty:: +`--omit-empty`:: Do not print a newline after formatted refs where the format expands to the empty string. ---column[=<options>]:: ---no-column:: +`--column[=<options>]`:: +`--no-column`:: Display branch listing in columns. See configuration variable `column.branch` for option syntax. `--column` and `--no-column` - without options are equivalent to 'always' and 'never' respectively. + without options are equivalent to `always` and `never` respectively. + This option is only applicable in non-verbose mode. --r:: ---remotes:: - List or delete (if used with -d) the remote-tracking branches. +`--sort=<key>`:: + Sort based on _<key>_. Prefix `-` to sort in descending + order of the value. You may use the `--sort=<key>` option + multiple times, in which case the last key becomes the primary + key. The keys supported are the same as those in linkgit:git-for-each-ref[1]. + Sort order defaults to the value configured for the + `branch.sort` variable if it exists, or to sorting based on the + full refname (including `refs/...` prefix). This lists + detached `HEAD` (if present) first, then local branches and + finally remote-tracking branches. See linkgit:git-config[1]. + +`-r`:: +`--remotes`:: + List or delete (if used with `-d`) the remote-tracking branches. Combine with `--list` to match the optional pattern(s). --a:: ---all:: +`-a`:: +`--all`:: List both remote-tracking branches and local branches. Combine with `--list` to match optional pattern(s). --l:: ---list:: +`-l`:: +`--list`:: List branches. With optional `<pattern>...`, e.g. `git branch --list 'maint-*'`, list only the branches that match the pattern(s). ---show-current:: - Print the name of the current branch. In detached HEAD state, +`--show-current`:: + Print the name of the current branch. In detached `HEAD` state, nothing is printed. --v:: --vv:: ---verbose:: +`-v`:: +`-vv`:: +`--verbose`:: When in list mode, show sha1 and commit subject line for each head, along with relationship to upstream branch (if any). If given twice, print the path of the linked worktree (if any) and the name of the upstream branch, as well (see also `git remote show <remote>`). Note that the - current worktree's HEAD will not have its path printed (it will always + current worktree's `HEAD` will not have its path printed (it will always be your current directory). --q:: ---quiet:: +`-q`:: +`--quiet`:: Be more quiet when creating or deleting a branch, suppressing non-error messages. ---abbrev=<n>:: +`--abbrev=<n>`:: In the verbose listing that show the commit object name, - show the shortest prefix that is at least '<n>' hexdigits + show the shortest prefix that is at least _<n>_ hexdigits long that uniquely refers the object. The default value is 7 and can be overridden by the `core.abbrev` config option. ---no-abbrev:: +`--no-abbrev`:: Display the full sha1s in the output listing rather than abbreviating them. --t:: ---track[=(direct|inherit)]:: +`-t`:: +`--track[=(direct|inherit)]`:: When creating a new branch, set up `branch.<name>.remote` and `branch.<name>.merge` configuration entries to set "upstream" tracking configuration for the new branch. This @@ -229,7 +240,7 @@ The exact upstream branch is chosen depending on the optional argument: itself as the upstream; `--track=inherit` means to copy the upstream configuration of the start-point branch. + -The branch.autoSetupMerge configuration variable specifies how `git switch`, +The `branch.autoSetupMerge` configuration variable specifies how `git switch`, `git checkout` and `git branch` should behave when neither `--track` nor `--no-track` are specified: + @@ -238,106 +249,94 @@ were given whenever the start-point is a remote-tracking branch. `false` behaves as if `--no-track` were given. `always` behaves as though `--track=direct` were given. `inherit` behaves as though `--track=inherit` were given. `simple` behaves as though `--track=direct` were given only when -the start-point is a remote-tracking branch and the new branch has the same +the _<start-point>_ is a remote-tracking branch and the new branch has the same name as the remote branch. + See linkgit:git-pull[1] and linkgit:git-config[1] for additional discussion on how the `branch.<name>.remote` and `branch.<name>.merge` options are used. ---no-track:: +`--no-track`:: Do not set up "upstream" configuration, even if the - branch.autoSetupMerge configuration variable is set. + `branch.autoSetupMerge` configuration variable is set. ---recurse-submodules:: - THIS OPTION IS EXPERIMENTAL! Causes the current command to +`--recurse-submodules`:: + THIS OPTION IS EXPERIMENTAL! Cause the current command to recurse into submodules if `submodule.propagateBranches` is enabled. See `submodule.propagateBranches` in linkgit:git-config[1]. Currently, only branch creation is supported. + -When used in branch creation, a new branch <branchname> will be created +When used in branch creation, a new branch _<branch-name>_ will be created in the superproject and all of the submodules in the superproject's -<start-point>. In submodules, the branch will point to the submodule -commit in the superproject's <start-point> but the branch's tracking +_<start-point>_. In submodules, the branch will point to the submodule +commit in the superproject's _<start-point>_ but the branch's tracking information will be set up based on the submodule's branches and remotes e.g. `git branch --recurse-submodules topic origin/main` will create the submodule branch "topic" that points to the submodule commit in the superproject's "origin/main", but tracks the submodule's "origin/main". ---set-upstream:: +`--set-upstream`:: As this option had confusing syntax, it is no longer supported. Please use `--track` or `--set-upstream-to` instead. --u <upstream>:: ---set-upstream-to=<upstream>:: - Set up <branchname>'s tracking information so <upstream> is - considered <branchname>'s upstream branch. If no <branchname> +`-u <upstream>`:: +`--set-upstream-to=<upstream>`:: + Set up _<branch-name>_'s tracking information so _<upstream>_ is + considered _<branch-name>_'s upstream branch. If no _<branch-name>_ is specified, then it defaults to the current branch. ---unset-upstream:: - Remove the upstream information for <branchname>. If no branch +`--unset-upstream`:: + Remove the upstream information for _<branch-name>_. If no branch is specified it defaults to the current branch. ---edit-description:: +`--edit-description`:: Open an editor and edit the text to explain what the branch is for, to be used by various other commands (e.g. `format-patch`, `request-pull`, and `merge` (if enabled)). Multi-line explanations may be used. ---contains [<commit>]:: - Only list branches which contain the specified commit (HEAD +`--contains [<commit>]`:: + Only list branches which contain _<commit>_ (`HEAD` if not specified). Implies `--list`. ---no-contains [<commit>]:: - Only list branches which don't contain the specified commit - (HEAD if not specified). Implies `--list`. +`--no-contains [<commit>]`:: + Only list branches which don't contain _<commit>_ + (`HEAD` if not specified). Implies `--list`. ---merged [<commit>]:: - Only list branches whose tips are reachable from the - specified commit (HEAD if not specified). Implies `--list`. +`--merged [<commit>]`:: + Only list branches whose tips are reachable from + _<commit>_ (`HEAD` if not specified). Implies `--list`. ---no-merged [<commit>]:: - Only list branches whose tips are not reachable from the - specified commit (HEAD if not specified). Implies `--list`. +`--no-merged [<commit>]`:: + Only list branches whose tips are not reachable from + _<commit>_ (`HEAD` if not specified). Implies `--list`. -<branchname>:: +`--points-at <object>`:: + Only list branches of _<object>_. + +`--format <format>`:: + A string that interpolates `%(fieldname)` from a branch ref being shown + and the object it points at. _<format>_ is the same as + that of linkgit:git-for-each-ref[1]. + +_<branch-name>_:: The name of the branch to create or delete. The new branch name must pass all checks defined by linkgit:git-check-ref-format[1]. Some of these checks may restrict the characters allowed in a branch name. -<start-point>:: +_<start-point>_:: The new branch head will point to this commit. It may be given as a branch name, a commit-id, or a tag. If this - option is omitted, the current HEAD will be used instead. + option is omitted, the current `HEAD` will be used instead. -<oldbranch>:: +_<old-branch>_:: The name of an existing branch. If this option is omitted, the name of the current branch will be used instead. -<newbranch>:: +_<new-branch>_:: The new name for an existing branch. The same restrictions as for - <branchname> apply. - ---sort=<key>:: - Sort based on the key given. Prefix `-` to sort in descending - order of the value. You may use the --sort=<key> option - multiple times, in which case the last key becomes the primary - key. The keys supported are the same as those in `git - for-each-ref`. Sort order defaults to the value configured for the - `branch.sort` variable if it exists, or to sorting based on the - full refname (including `refs/...` prefix). This lists - detached HEAD (if present) first, then local branches and - finally remote-tracking branches. See linkgit:git-config[1]. - - ---points-at <object>:: - Only list branches of the given object. - ---format <format>:: - A string that interpolates `%(fieldname)` from a branch ref being shown - and the object it points at. The format is the same as - that of linkgit:git-for-each-ref[1]. + _<branch-name>_ apply. CONFIGURATION ------------- @@ -374,7 +373,7 @@ $ git branch -D test <2> ------------ + <1> Delete the remote-tracking branches "todo", "html" and "man". The next - 'fetch' or 'pull' will create them again unless you configure them not to. + `git fetch` or `git pull` will create them again unless you configure them not to. See linkgit:git-fetch[1]. <2> Delete the "test" branch even if the "master" branch (or whichever branch is currently checked out) does not have all commits from the test branch. @@ -386,8 +385,8 @@ $ git branch -r -l '<remote>/<pattern>' <1> $ git for-each-ref 'refs/remotes/<remote>/<pattern>' <2> ------------ + -<1> Using `-a` would conflate <remote> with any local branches you happen to - have been prefixed with the same <remote> pattern. +<1> Using `-a` would conflate _<remote>_ with any local branches you happen to + have been prefixed with the same _<remote>_ pattern. <2> `for-each-ref` can take a wide range of options. See linkgit:git-for-each-ref[1] Patterns will normally need quoting. @@ -396,24 +395,24 @@ NOTES ----- If you are creating a branch that you want to switch to immediately, -it is easier to use the "git switch" command with its `-c` option to +it is easier to use the `git switch` command with its `-c` option to do the same thing with a single command. The options `--contains`, `--no-contains`, `--merged` and `--no-merged` serve four related but different purposes: - `--contains <commit>` is used to find all branches which will need - special attention if <commit> were to be rebased or amended, since those - branches contain the specified <commit>. + special attention if _<commit>_ were to be rebased or amended, since those + branches contain the specified _<commit>_. - `--no-contains <commit>` is the inverse of that, i.e. branches that don't - contain the specified <commit>. + contain the specified _<commit>_. - `--merged` is used to find all branches which can be safely deleted, - since those branches are fully contained by HEAD. + since those branches are fully contained by `HEAD`. - `--no-merged` is used to find branches which are candidates for merging - into HEAD, since those branches are not fully contained by HEAD. + into `HEAD`, since those branches are not fully contained by `HEAD`. include::ref-reachability-filters.adoc[] @@ -422,8 +421,8 @@ SEE ALSO linkgit:git-check-ref-format[1], linkgit:git-fetch[1], linkgit:git-remote[1], -link:user-manual.html#what-is-a-branch[``Understanding history: What is -a branch?''] in the Git User's Manual. +link:user-manual.html#what-is-a-branch["Understanding history: What is +a branch?"] in the Git User's Manual. GIT --- diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc index d5890ae368..180d1ad363 100644 --- a/Documentation/git-cat-file.adoc +++ b/Documentation/git-cat-file.adoc @@ -9,8 +9,7 @@ SYNOPSIS -------- [verse] 'git cat-file' <type> <object> -'git cat-file' (-e | -p) <object> -'git cat-file' (-t | -s) [--allow-unknown-type] <object> +'git cat-file' (-e | -p | -t | -s) <object> 'git cat-file' (--textconv | --filters) [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>] 'git cat-file' (--batch | --batch-check | --batch-command) [--batch-all-objects] @@ -81,6 +80,25 @@ OPTIONS end-of-line conversion, etc). In this case, `<object>` has to be of the form `<tree-ish>:<path>`, or `:<path>`. +--filter=<filter-spec>:: +--no-filter:: + Omit objects from the list of printed objects. This can only be used in + combination with one of the batched modes. Excluded objects that have + been explicitly requested via any of the batch modes that read objects + via standard input (`--batch`, `--batch-check`) will be reported as + "filtered". Excluded objects in `--batch-all-objects` mode will not be + printed at all. The '<filter-spec>' may be one of the following: ++ +The form '--filter=blob:none' omits all blobs. ++ +The form '--filter=blob:limit=<n>[kmg]' omits blobs of size at least n +bytes or units. n may be zero. The suffixes k, m, and g can be used to name +units in KiB, MiB, or GiB. For example, 'blob:limit=1k' is the same as +'blob:limit=1024'. ++ +The form '--filter=object:type=(tag|commit|tree|blob)' omits all objects which +are not of the requested type. + --path=<path>:: For use with `--textconv` or `--filters`, to allow specifying an object name and a path separately, e.g. when it is difficult to figure out @@ -183,9 +201,6 @@ flush:: only once, even if it is stored multiple times in the repository. ---allow-unknown-type:: - Allow `-s` or `-t` to query broken/corrupt objects of unknown type. - --follow-symlinks:: With `--batch` or `--batch-check`, follow symlinks inside the repository when requesting objects with extended SHA-1 @@ -292,6 +307,11 @@ newline. The available atoms are: `objecttype`:: The type of the object (the same as `cat-file -t` reports). +`objectmode`:: + If the specified object has mode information (such as a tree or + index entry), the mode expressed as an octal integer. Otherwise, + empty string. + `objectsize`:: The size, in bytes, of the object (the same as `cat-file -s` reports). @@ -322,10 +342,10 @@ of `%(objectsize)` bytes), followed by a newline. For example, `--batch` without a custom format would produce: ------------- +----------- <oid> SP <type> SP <size> LF <contents> LF ------------- +----------- Whereas `--batch-check='%(objectname) %(objecttype)'` would produce: @@ -340,12 +360,27 @@ the repository, then `cat-file` will ignore any custom format and print: <object> SP missing LF ------------ +If a name is specified on stdin that is filtered out via `--filter=`, +then `cat-file` will ignore any custom format and print: + +------------ +<object> SP excluded LF +------------ + If a name is specified that might refer to more than one object (an ambiguous short sha), then `cat-file` will ignore any custom format and print: ------------ <object> SP ambiguous LF ------------ +If a name is specified that refers to a submodule entry in a tree and the +target object does not exist in the repository, then `cat-file` will ignore +any custom format and print (with the object ID of the submodule): + +------------ +<oid> SP submodule LF +------------ + If `--follow-symlinks` is used, and a symlink in the repository points outside the repository, then `cat-file` will ignore any custom format and print: diff --git a/Documentation/git-check-attr.adoc b/Documentation/git-check-attr.adoc index cb5a6c8f33..503b644657 100644 --- a/Documentation/git-check-attr.adoc +++ b/Documentation/git-check-attr.adoc @@ -76,6 +76,7 @@ EXAMPLES -------- In the examples, the following '.gitattributes' file is used: + --------------- *.java diff=java -crlf myAttr NoMyAttr.java !myAttr @@ -83,12 +84,14 @@ README caveat=unspecified --------------- * Listing a single attribute: ++ --------------- $ git check-attr diff org/example/MyClass.java org/example/MyClass.java: diff: java --------------- * Listing multiple attributes for a file: ++ --------------- $ git check-attr crlf diff myAttr -- org/example/MyClass.java org/example/MyClass.java: crlf: unset @@ -97,6 +100,7 @@ org/example/MyClass.java: myAttr: set --------------- * Listing all attributes for a file: ++ --------------- $ git check-attr --all -- org/example/MyClass.java org/example/MyClass.java: diff: java @@ -104,6 +108,7 @@ org/example/MyClass.java: myAttr: set --------------- * Listing an attribute for multiple files: ++ --------------- $ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java org/example/MyClass.java: myAttr: set @@ -111,6 +116,7 @@ org/example/NoMyAttr.java: myAttr: unspecified --------------- * Not all values are equally unambiguous: ++ --------------- $ git check-attr caveat README README: caveat: unspecified diff --git a/Documentation/git-checkout.adoc b/Documentation/git-checkout.adoc index a66c53a5cd..ee83b6d9ba 100644 --- a/Documentation/git-checkout.adoc +++ b/Documentation/git-checkout.adoc @@ -7,54 +7,54 @@ git-checkout - Switch branches or restore working tree files SYNOPSIS -------- -[verse] -'git checkout' [-q] [-f] [-m] [<branch>] -'git checkout' [-q] [-f] [-m] --detach [<branch>] -'git checkout' [-q] [-f] [-m] [--detach] <commit> -'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>] -'git checkout' [-f] <tree-ish> [--] <pathspec>... -'git checkout' [-f] <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul] -'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>... -'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul] -'git checkout' (-p|--patch) [<tree-ish>] [--] [<pathspec>...] +[synopsis] +git checkout [-q] [-f] [-m] [<branch>] +git checkout [-q] [-f] [-m] --detach [<branch>] +git checkout [-q] [-f] [-m] [--detach] <commit> +git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new-branch>] [<start-point>] +git checkout [-f] <tree-ish> [--] <pathspec>... +git checkout [-f] <tree-ish> --pathspec-from-file=<file> [--pathspec-file-nul] +git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [--] <pathspec>... +git checkout [-f|--ours|--theirs|-m|--conflict=<style>] --pathspec-from-file=<file> [--pathspec-file-nul] +git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...] DESCRIPTION ----------- Updates files in the working tree to match the version in the index -or the specified tree. If no pathspec was given, 'git checkout' will +or the specified tree. If no pathspec was given, `git checkout` will also update `HEAD` to set the specified branch as the current branch. -'git checkout' [<branch>]:: - To prepare for working on `<branch>`, switch to it by updating +`git checkout [<branch>]`:: + To prepare for working on _<branch>_, switch to it by updating the index and the files in the working tree, and by pointing `HEAD` at the branch. Local modifications to the files in the working tree are kept, so that they can be committed to the - `<branch>`. + _<branch>_. + -If `<branch>` is not found but there does exist a tracking branch in -exactly one remote (call it `<remote>`) with a matching name and +If _<branch>_ is not found but there does exist a tracking branch in +exactly one remote (call it _<remote>_) with a matching name and `--no-guess` is not specified, treat as equivalent to + ------------ $ git checkout -b <branch> --track <remote>/<branch> ------------ + -You could omit `<branch>`, in which case the command degenerates to +You could omit _<branch>_, in which case the command degenerates to "check out the current branch", which is a glorified no-op with rather expensive side-effects to show only the tracking information, if it exists, for the current branch. -'git checkout' -b|-B <new-branch> [<start-point>]:: +`git checkout (-b|-B) <new-branch> [<start-point>]`:: Specifying `-b` causes a new branch to be created as if linkgit:git-branch[1] were called and then checked out. In this case you can use the `--track` or `--no-track` options, - which will be passed to 'git branch'. As a convenience, + which will be passed to `git branch`. As a convenience, `--track` without `-b` implies branch creation; see the description of `--track` below. + -If `-B` is given, `<new-branch>` is created if it doesn't exist; otherwise, it +If `-B` is given, _<new-branch>_ is created if it doesn't exist; otherwise, it is reset. This is the transactional equivalent of + ------------ @@ -67,30 +67,30 @@ successful (e.g., when the branch is in use in another worktree, not just the current branch stays the same, but the branch is not reset to the start-point, either). -'git checkout' --detach [<branch>]:: -'git checkout' [--detach] <commit>:: +`git checkout --detach [<branch>]`:: +`git checkout [--detach] <commit>`:: - Prepare to work on top of `<commit>`, by detaching `HEAD` at it + Prepare to work on top of _<commit>_, by detaching `HEAD` at it (see "DETACHED HEAD" section), and updating the index and the files in the working tree. Local modifications to the files in the working tree are kept, so that the resulting working tree will be the state recorded in the commit plus the local modifications. + -When the `<commit>` argument is a branch name, the `--detach` option can +When the _<commit>_ argument is a branch name, the `--detach` option can be used to detach `HEAD` at the tip of the branch (`git checkout <branch>` would check out that branch without detaching `HEAD`). + -Omitting `<branch>` detaches `HEAD` at the tip of the current branch. +Omitting _<branch>_ detaches `HEAD` at the tip of the current branch. -'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...:: -'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]:: +`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <pathspec>...`:: +`git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] --pathspec-from-file=<file> [--pathspec-file-nul]`:: Overwrite the contents of the files that match the pathspec. - When the `<tree-ish>` (most often a commit) is not given, + When the _<tree-ish>_ (most often a commit) is not given, overwrite working tree with the contents in the index. - When the `<tree-ish>` is given, overwrite both the index and - the working tree with the contents at the `<tree-ish>`. + When the _<tree-ish>_ is given, overwrite both the index and + the working tree with the contents at the _<tree-ish>_. + The index may contain unmerged entries because of a previous failed merge. By default, if you try to check out such an entry from the index, the @@ -100,7 +100,7 @@ specific side of the merge can be checked out of the index by using `--ours` or `--theirs`. With `-m`, changes made to the working tree file can be discarded to re-create the original conflicted merge result. -'git checkout' (-p|--patch) [<tree-ish>] [--] [<pathspec>...]:: +`git checkout (-p|--patch) [<tree-ish>] [--] [<pathspec>...]`:: This is similar to the previous mode, but lets you use the interactive interface to show the "diff" output and choose which hunks to use in the result. See below for the description of @@ -108,19 +108,19 @@ file can be discarded to re-create the original conflicted merge result. OPTIONS ------- --q:: ---quiet:: +`-q`:: +`--quiet`:: Quiet, suppress feedback messages. ---progress:: ---no-progress:: +`--progress`:: +`--no-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 enables progress reporting even if not attached to a terminal, regardless of `--quiet`. --f:: ---force:: +`-f`:: +`--force`:: When switching branches, proceed even if the index or the working tree differs from `HEAD`, and even if there are untracked files in the way. This is used to throw away local changes and @@ -129,13 +129,13 @@ OPTIONS When checking out paths from the index, do not fail upon unmerged entries; instead, unmerged entries are ignored. ---ours:: ---theirs:: +`--ours`:: +`--theirs`:: When checking out paths from the index, check out stage #2 - ('ours') or #3 ('theirs') for unmerged paths. + (`ours`) or #3 (`theirs`) for unmerged paths. + -Note that during `git rebase` and `git pull --rebase`, 'ours' and -'theirs' may appear swapped; `--ours` gives the version from the +Note that during `git rebase` and `git pull --rebase`, `ours` and +`theirs` may appear swapped; `--ours` gives the version from the branch the changes are rebased onto, while `--theirs` gives the version from the branch that holds your work that is being rebased. + @@ -149,22 +149,22 @@ as `ours` (i.e. "our shared canonical history"), while what you did on your side branch as `theirs` (i.e. "one contributor's work on top of it"). --b <new-branch>:: - Create a new branch named `<new-branch>`, start it at - `<start-point>`, and check the resulting branch out; +`-b <new-branch>`:: + Create a new branch named _<new-branch>_, start it at + _<start-point>_, and check the resulting branch out; see linkgit:git-branch[1] for details. --B <new-branch>:: - Creates the branch `<new-branch>`, start it at `<start-point>`; - if it already exists, then reset it to `<start-point>`. And then +`-B <new-branch>`:: + Creates the branch _<new-branch>_, start it at _<start-point>_; + if it already exists, then reset it to _<start-point>_. And then check the resulting branch out. This is equivalent to running - "git branch" with "-f" followed by "git checkout" of that branch; + `git branch` with `-f` followed by `git checkout` of that branch; see linkgit:git-branch[1] for details. --t:: ---track[=(direct|inherit)]:: +`-t`:: +`--track[=(direct|inherit)]`:: When creating a new branch, set up "upstream" configuration. See - "--track" in linkgit:git-branch[1] for details. + `--track` in linkgit:git-branch[1] for details. + If no `-b` option is given, the name of the new branch will be derived from the remote-tracking branch, by looking at the local part of @@ -176,14 +176,14 @@ off of `origin/hack` (or `remotes/origin/hack`, or even guessing results in an empty name, the guessing is aborted. You can explicitly give a name with `-b` in such a case. ---no-track:: +`--no-track`:: Do not set up "upstream" configuration, even if the `branch.autoSetupMerge` configuration variable is true. ---guess:: ---no-guess:: - If `<branch>` is not found but there does exist a tracking - branch in exactly one remote (call it `<remote>`) with a +`--guess`:: +`--no-guess`:: + If _<branch>_ is not found but there does exist a tracking + branch in exactly one remote (call it _<remote>_) with a matching name, treat as equivalent to + ------------ @@ -192,10 +192,10 @@ $ git checkout -b <branch> --track <remote>/<branch> + If the branch exists in multiple remotes and one of them is named by the `checkout.defaultRemote` configuration variable, we'll use that -one for the purposes of disambiguation, even if the `<branch>` isn't +one for the purposes of disambiguation, even if the _<branch>_ isn't unique across all remotes. Set it to e.g. `checkout.defaultRemote=origin` to always checkout remote -branches from there if `<branch>` is ambiguous but exists on the +branches from there if _<branch>_ is ambiguous but exists on the 'origin' remote. See also `checkout.defaultRemote` in linkgit:git-config[1]. + @@ -204,28 +204,28 @@ linkgit:git-config[1]. The default behavior can be set via the `checkout.guess` configuration variable. --l:: +`-l`:: Create the new branch's reflog; see linkgit:git-branch[1] for details. --d:: ---detach:: +`-d`:: +`--detach`:: Rather than checking out a branch to work on it, check out a commit for inspection and discardable experiments. This is the default behavior of `git checkout <commit>` when - `<commit>` is not a branch name. See the "DETACHED HEAD" section + _<commit>_ is not a branch name. See the "DETACHED HEAD" section below for details. ---orphan <new-branch>:: - Create a new unborn branch, named `<new-branch>`, started from - `<start-point>` and switch to it. The first commit made on this +`--orphan <new-branch>`:: + Create a new unborn branch, named _<new-branch>_, started from + _<start-point>_ and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits. + The index and the working tree are adjusted as if you had previously run `git checkout <start-point>`. This allows you to start a new history -that records a set of paths similar to `<start-point>` by easily running +that records a set of paths similar to _<start-point>_ by easily running `git commit -a` to make the root commit. + This can be useful when you want to publish the tree from a commit @@ -235,20 +235,20 @@ whose full history contains proprietary or otherwise encumbered bits of code. + If you want to start a disconnected history that records a set of paths -that is totally different from the one of `<start-point>`, then you should +that is totally different from the one of _<start-point>_, then you should clear the index and the working tree right after creating the orphan branch by running `git rm -rf .` from the top level of the working tree. Afterwards you will be ready to prepare your new files, repopulating the working tree, by copying them from elsewhere, extracting a tarball, etc. ---ignore-skip-worktree-bits:: - In sparse checkout mode, `git checkout -- <paths>` would - update only entries matched by `<paths>` and sparse patterns +`--ignore-skip-worktree-bits`:: + In sparse checkout mode, `git checkout -- <path>...` would + update only entries matched by _<paths>_ and sparse patterns in `$GIT_DIR/info/sparse-checkout`. This option ignores - the sparse patterns and adds back any files in `<paths>`. + the sparse patterns and adds back any files in `<path>...`. --m:: ---merge:: +`-m`:: +`--merge`:: When switching branches, if you have local modifications to one or more files that are different between the current branch and the branch to @@ -269,40 +269,40 @@ used when checking out paths from a tree-ish. + When switching branches with `--merge`, staged changes may be lost. ---conflict=<style>:: +`--conflict=<style>`:: The same as `--merge` option above, but changes the way the conflicting hunks are presented, overriding the `merge.conflictStyle` configuration variable. Possible values are - "merge" (default), "diff3", and "zdiff3". + `merge` (default), `diff3`, and `zdiff3`. --p:: ---patch:: +`-p`:: +`--patch`:: Interactively select hunks in the difference between the - `<tree-ish>` (or the index, if unspecified) and the working + _<tree-ish>_ (or the index, if unspecified) and the working tree. The chosen hunks are then applied in reverse to the - working tree (and if a `<tree-ish>` was specified, the index). + working tree (and if a _<tree-ish>_ was specified, the index). + This means that you can use `git checkout -p` to selectively discard -edits from your current working tree. See the ``Interactive Mode'' +edits from your current working tree. See the "Interactive Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. + Note that this option uses the no overlay mode by default (see also `--overlay`), and currently doesn't support overlay mode. ---ignore-other-worktrees:: +`--ignore-other-worktrees`:: `git checkout` refuses when the wanted branch is already checked out or otherwise in use by another worktree. This option makes it check the branch out anyway. In other words, the branch can be in use by more than one worktree. ---overwrite-ignore:: ---no-overwrite-ignore:: +`--overwrite-ignore`:: +`--no-overwrite-ignore`:: Silently overwrite ignored files when switching branches. This is the default behavior. Use `--no-overwrite-ignore` to abort the operation when the new branch contains ignored files. ---recurse-submodules:: ---no-recurse-submodules:: +`--recurse-submodules`:: +`--no-recurse-submodules`:: Using `--recurse-submodules` will update the content of all active submodules according to the commit recorded in the superproject. If local modifications in a submodule would be overwritten the checkout @@ -311,25 +311,25 @@ Note that this option uses the no overlay mode by default (see also Just like linkgit:git-submodule[1], this will detach `HEAD` of the submodule. ---overlay:: ---no-overlay:: +`--overlay`:: +`--no-overlay`:: In the default overlay mode, `git checkout` never removes files from the index or the working tree. When specifying `--no-overlay`, files that appear in the index and - working tree, but not in `<tree-ish>` are removed, to make them - match `<tree-ish>` exactly. + working tree, but not in _<tree-ish>_ are removed, to make them + match _<tree-ish>_ exactly. ---pathspec-from-file=<file>:: - Pathspec is passed in `<file>` instead of commandline args. If - `<file>` is exactly `-` then standard input is used. Pathspec - elements are separated by LF or CR/LF. Pathspec elements can be +`--pathspec-from-file=<file>`:: + Pathspec is passed in _<file>_ instead of commandline args. If + _<file>_ is exactly `-` then standard input is used. Pathspec + elements are separated by _LF_ or _CR_/_LF_. Pathspec elements can be quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). See also `--pathspec-file-nul` and global `--literal-pathspecs`. ---pathspec-file-nul:: +`--pathspec-file-nul`:: Only meaningful with `--pathspec-from-file`. Pathspec elements are - separated with NUL character and all other characters are taken + separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). <branch>:: @@ -343,33 +343,33 @@ You can use the `@{-N}` syntax to refer to the N-th last branch/commit checked out using "git checkout" operation. You may also specify `-` which is synonymous to `@{-1}`. + -As a special case, you may use `A...B` as a shortcut for the -merge base of `A` and `B` if there is exactly one merge base. You can -leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. +As a special case, you may use `<rev-a>...<rev-b>` as a shortcut for the +merge base of _<rev-a>_ and _<rev-b>_ if there is exactly one merge base. You can +leave out at most one of _<rev-a>_ and _<rev-b>_, in which case it defaults to `HEAD`. -<new-branch>:: +_<new-branch>_:: Name for the new branch. -<start-point>:: +_<start-point>_:: The name of a commit at which to start the new branch; see linkgit:git-branch[1] for details. Defaults to `HEAD`. + -As a special case, you may use `"A...B"` as a shortcut for the -merge base of `A` and `B` if there is exactly one merge base. You can -leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. +As a special case, you may use `<rev-a>...<rev-b>` as a shortcut for the +merge base of _<rev-a>_ and _<rev-b>_ if there is exactly one merge base. You can +leave out at most one of _<rev-a>_ and _<rev-b>_, in which case it defaults to `HEAD`. -<tree-ish>:: +_<tree-ish>_:: Tree to checkout from (when paths are given). If not specified, the index will be used. + -As a special case, you may use `"A...B"` as a shortcut for the -merge base of `A` and `B` if there is exactly one merge base. You can -leave out at most one of `A` and `B`, in which case it defaults to `HEAD`. +As a special case, you may use `<rev-a>...<rev-b>` as a shortcut for the +merge base of _<rev-a>_ and _<rev-b>_ if there is exactly one merge base. You can +leave out at most one of _<rev-a>_ and _<rev-b>_, in which case it defaults to `HEAD`. -\--:: +`--`:: Do not interpret any more arguments as options. -<pathspec>...:: +`<pathspec>...`:: Limits the paths affected by the operation. + For more details, see the 'pathspec' entry in linkgit:gitglossary[7]. @@ -391,7 +391,7 @@ a---b---c branch 'master' (refers to commit 'c') ------------ When a commit is created in this state, the branch is updated to refer to -the new commit. Specifically, 'git commit' creates a new commit `d`, whose +the new commit. Specifically, `git commit` creates a new commit `d`, whose parent is commit `c`, and then updates branch `master` to refer to new commit `d`. `HEAD` still refers to branch `master` and so indirectly now refers to commit `d`: @@ -510,11 +510,11 @@ ARGUMENT DISAMBIGUATION ----------------------- When there is only one argument given and it is not `--` (e.g. `git -checkout abc`), and when the argument is both a valid `<tree-ish>` -(e.g. a branch `abc` exists) and a valid `<pathspec>` (e.g. a file +checkout abc`), and when the argument is both a valid _<tree-ish>_ +(e.g. a branch `abc` exists) and a valid _<pathspec>_ (e.g. a file or a directory whose name is "abc" exists), Git would usually ask you to disambiguate. Because checking out a branch is so common an -operation, however, `git checkout abc` takes "abc" as a `<tree-ish>` +operation, however, `git checkout abc` takes "abc" as a _<tree-ish>_ in such a situation. Use `git checkout -- <pathspec>` if you want to checkout these paths out of the index. diff --git a/Documentation/git-column.adoc b/Documentation/git-column.adoc index 85fb87c94a..8e0047214d 100644 --- a/Documentation/git-column.adoc +++ b/Documentation/git-column.adoc @@ -50,6 +50,7 @@ EXAMPLES -------- Format data by columns: + ------------ $ seq 1 24 | git column --mode=column --padding=5 1 4 7 10 13 16 19 22 @@ -58,6 +59,7 @@ $ seq 1 24 | git column --mode=column --padding=5 ------------ Format data by rows: + ------------ $ seq 1 21 | git column --mode=row --padding=5 1 2 3 4 5 6 7 @@ -66,6 +68,7 @@ $ seq 1 21 | git column --mode=row --padding=5 ------------ List some tags in a table with unequal column widths: + ------------ $ git tag --list 'v2.4.*' --column=row,dense v2.4.0 v2.4.0-rc0 v2.4.0-rc1 v2.4.0-rc2 v2.4.0-rc3 diff --git a/Documentation/git-cvsserver.adoc b/Documentation/git-cvsserver.adoc index 4c475efeab..fe822f571d 100644 --- a/Documentation/git-cvsserver.adoc +++ b/Documentation/git-cvsserver.adoc @@ -125,9 +125,11 @@ creation in your platform (e.g. mkpasswd in Linux, encrypt in OpenBSD or pwhash in NetBSD) and paste it in the right location. Then provide your password via the pserver method, for example: + ------ cvs -d:pserver:someuser:somepassword@server:/path/repo.git co <HEAD_name> ------ + No special setup is needed for SSH access, other than having Git tools in the PATH. If you have clients that do not accept the CVS_SERVER environment variable, you can rename 'git-cvsserver' to `cvs`. @@ -138,6 +140,7 @@ CVS_SERVER directly in CVSROOT like ------ cvs -d ":ext;CVS_SERVER=git cvsserver:user@server/path/repo.git" co <HEAD_name> ------ + This has the advantage that it will be saved in your 'CVS/Root' files and you don't need to worry about always setting the correct environment variable. SSH users restricted to 'git-shell' don't need to override the default @@ -168,6 +171,7 @@ All configuration variables can also be overridden for a specific method of access. Valid method names are "ext" (for SSH access) and "pserver". The following example configuration would disable pserver access while still allowing access over SSH. + ------ [gitcvs] enabled=0 diff --git a/Documentation/git-daemon.adoc b/Documentation/git-daemon.adoc index ede7b935d6..99389f0388 100644 --- a/Documentation/git-daemon.adoc +++ b/Documentation/git-daemon.adoc @@ -7,21 +7,21 @@ git-daemon - A really simple server for Git repositories SYNOPSIS -------- -[verse] -'git daemon' [--verbose] [--syslog] [--export-all] - [--timeout=<n>] [--init-timeout=<n>] [--max-connections=<n>] - [--strict-paths] [--base-path=<path>] [--base-path-relaxed] - [--user-path | --user-path=<path>] - [--interpolated-path=<pathtemplate>] - [--reuseaddr] [--detach] [--pid-file=<file>] - [--enable=<service>] [--disable=<service>] - [--allow-override=<service>] [--forbid-override=<service>] - [--access-hook=<path>] [--[no-]informative-errors] - [--inetd | - [--listen=<host-or-ipaddr>] [--port=<n>] - [--user=<user> [--group=<group>]]] - [--log-destination=(stderr|syslog|none)] - [<directory>...] +[synopsis] +git daemon [--verbose] [--syslog] [--export-all] + [--timeout=<n>] [--init-timeout=<n>] [--max-connections=<n>] + [--strict-paths] [--base-path=<path>] [--base-path-relaxed] + [--user-path | --user-path=<path>] + [--interpolated-path=<pathtemplate>] + [--reuseaddr] [--detach] [--pid-file=<file>] + [--enable=<service>] [--disable=<service>] + [--allow-override=<service>] [--forbid-override=<service>] + [--access-hook=<path>] [--[no-]informative-errors] + [--inetd | + [--listen=<host-or-ipaddr>] [--port=<n>] + [--user=<user> [--group=<group>]]] + [--log-destination=(stderr|syslog|none)] + [<directory>...] DESCRIPTION ----------- @@ -32,111 +32,111 @@ that service if it is enabled. It verifies that the directory has the magic file "git-daemon-export-ok", and it will refuse to export any Git directory that hasn't explicitly been marked for export this way (unless the `--export-all` parameter is specified). If you -pass some directory paths as 'git daemon' arguments, the offers are limited to +pass some directory paths as `git daemon` arguments, the offers are limited to repositories within those directories. By default, only `upload-pack` service is enabled, which serves -'git fetch-pack' and 'git ls-remote' clients, which are invoked -from 'git fetch', 'git pull', and 'git clone'. +`git fetch-pack` and `git ls-remote` clients, which are invoked +from `git fetch`, `git pull`, and `git clone`. This is ideally suited for read-only updates, i.e., pulling from Git repositories. -An `upload-archive` also exists to serve 'git archive'. +An `upload-archive` also exists to serve `git archive`. OPTIONS ------- ---strict-paths:: +`--strict-paths`:: Match paths exactly (i.e. don't allow "/foo/repo" when the real path is "/foo/repo.git" or "/foo/repo/.git") and don't do user-relative paths. - 'git daemon' will refuse to start when this option is enabled and no + `git daemon` will refuse to start when this option is enabled and no directory arguments are provided. ---base-path=<path>:: +`--base-path=<path>`:: Remap all the path requests as relative to the given path. - This is sort of "Git root" - if you run 'git daemon' with - '--base-path=/srv/git' on example.com, then if you later try to pull - 'git://example.com/hello.git', 'git daemon' will interpret the path - as `/srv/git/hello.git`. - ---base-path-relaxed:: - If --base-path is enabled and repo lookup fails, with this option - 'git daemon' will attempt to lookup without prefixing the base path. - This is useful for switching to --base-path usage, while still + This is sort of "Git root" - if you run `git daemon` with + `--base-path=/srv/git` on `example.com`, then if you later try + to pull from `git://example.com/hello.git`, `git daemon` will + interpret the path as `/srv/git/hello.git`. + +`--base-path-relaxed`:: + If `--base-path` is enabled and repo lookup fails, with this option + `git daemon` will attempt to lookup without prefixing the base path. + This is useful for switching to `--base-path` usage, while still allowing the old paths. ---interpolated-path=<pathtemplate>:: +`--interpolated-path=<pathtemplate>`:: To support virtual hosting, an interpolated path template can be used to dynamically construct alternate paths. The template - supports %H for the target hostname as supplied by the client but - converted to all lowercase, %CH for the canonical hostname, - %IP for the server's IP address, %P for the port number, - and %D for the absolute path of the named repository. + supports `%H` for the target hostname as supplied by the client but + converted to all lowercase, `%CH` for the canonical hostname, + `%IP` for the server's IP address, `%P` for the port number, + and `%D` for the absolute path of the named repository. After interpolation, the path is validated against the directory list. ---export-all:: +`--export-all`:: Allow pulling from all directories that look like Git repositories (have the 'objects' and 'refs' subdirectories), even if they - do not have the 'git-daemon-export-ok' file. + do not have the `git-daemon-export-ok` file. ---inetd:: - Have the server run as an inetd service. Implies --syslog (may be - overridden with `--log-destination=`). - Incompatible with --detach, --port, --listen, --user and --group - options. +`--inetd`:: + Have the server run as an inetd service. Implies `--syslog` (may + be overridden with `--log-destination=`). + Incompatible with `--detach`, `--port`, `--listen`, `--user` and + `--group` options. ---listen=<host-or-ipaddr>:: +`--listen=<host-or-ipaddr>`:: Listen on a specific IP address or hostname. IP addresses can be either an IPv4 address or an IPv6 address if supported. If IPv6 - is not supported, then --listen=<hostname> is also not supported and - --listen must be given an IPv4 address. + is not supported, then `--listen=<hostname>` is also not supported + and `--listen` must be given an IPv4 address. Can be given more than once. Incompatible with `--inetd` option. ---port=<n>:: +`--port=<n>`:: Listen on an alternative port. Incompatible with `--inetd` option. ---init-timeout=<n>:: +`--init-timeout=<n>`:: Timeout (in seconds) between the moment the connection is established and the client request is received (typically a rather low value, since that should be basically immediate). ---timeout=<n>:: +`--timeout=<n>`:: Timeout (in seconds) for specific client sub-requests. This includes the time it takes for the server to process the sub-request and the time spent waiting for the next client's request. ---max-connections=<n>:: +`--max-connections=<n>`:: Maximum number of concurrent clients, defaults to 32. Set it to zero for no limit. ---syslog:: +`--syslog`:: Short for `--log-destination=syslog`. ---log-destination=<destination>:: +`--log-destination=<destination>`:: Send log messages to the specified destination. - Note that this option does not imply --verbose, + Note that this option does not imply `--verbose`, thus by default only error conditions will be logged. - The <destination> must be one of: + The _<destination>_ must be one of: + -- -stderr:: +`stderr`:: Write to standard error. Note that if `--detach` is specified, the process disconnects from the real standard error, making this destination effectively equivalent to `none`. -syslog:: +`syslog`:: Write to syslog, using the `git-daemon` identifier. -none:: +`none`:: Disable all logging. -- + The default destination is `syslog` if `--inetd` or `--detach` is specified, otherwise `stderr`. ---user-path:: ---user-path=<path>:: +`--user-path`:: +`--user-path=<path>`:: Allow {tilde}user notation to be used in requests. When specified with no parameter, a request to git://host/{tilde}alice/foo is taken as a request to access @@ -145,23 +145,23 @@ otherwise `stderr`. taken as a request to access `<path>/foo` repository in the home directory of user `alice`. ---verbose:: +`--verbose`:: Log details about the incoming connections and requested files. ---reuseaddr:: - Use SO_REUSEADDR when binding the listening socket. +`--reuseaddr`:: + Use `SO_REUSEADDR` when binding the listening socket. This allows the server to restart without waiting for old connections to time out. ---detach:: - Detach from the shell. Implies --syslog. +`--detach`:: + Detach from the shell. Implies `--syslog`. ---pid-file=<file>:: - Save the process id in 'file'. Ignored when the daemon +`--pid-file=<file>`:: + Save the process id in _<file>_. Ignored when the daemon is run under `--inetd`. ---user=<user>:: ---group=<group>:: +`--user=<user>`:: +`--group=<group>`:: Change daemon's uid and gid before entering the service loop. When only `--user` is given without `--group`, the primary group ID for the user is used. The values of @@ -170,43 +170,44 @@ otherwise `stderr`. + Giving these options is an error when used with `--inetd`; use the facility of inet daemon to achieve the same before spawning -'git daemon' if needed. +`git daemon` if needed. + Like many programs that switch user id, the daemon does not reset -environment variables such as `$HOME` when it runs git programs, +environment variables such as `HOME` when it runs git programs, e.g. `upload-pack` and `receive-pack`. When using this option, you may also want to set and export `HOME` to point at the home -directory of `<user>` before starting the daemon, and make sure any -Git configuration files in that directory are readable by `<user>`. +directory of _<user>_ before starting the daemon, and make sure any +Git configuration files in that directory are readable by _<user>_. ---enable=<service>:: ---disable=<service>:: +`--enable=<service>`:: +`--disable=<service>`:: Enable/disable the service site-wide per default. Note that a service disabled site-wide can still be enabled per repository if it is marked overridable and the repository enables the service with a configuration item. ---allow-override=<service>:: ---forbid-override=<service>:: +`--allow-override=<service>`:: +`--forbid-override=<service>`:: Allow/forbid overriding the site-wide default with per repository configuration. By default, all the services may be overridden. ---[no-]informative-errors:: +`--informative-errors`:: +`--no-informative-errors`:: When informative errors are turned on, git-daemon will report more verbose errors to the client, differentiating conditions like "no such repository" from "repository not exported". This is more convenient for clients, but may leak information about the existence of unexported repositories. When informative errors are not enabled, all errors report "access denied" to the - client. The default is --no-informative-errors. + client. The default is `--no-informative-errors`. ---access-hook=<path>:: +`--access-hook=<path>`:: Every time a client connects, first run an external command specified by the <path> with service name (e.g. "upload-pack"), - path to the repository, hostname (%H), canonical hostname - (%CH), IP address (%IP), and TCP port (%P) as its command-line + path to the repository, hostname (`%H`), canonical hostname + (`%CH`), IP address (`%IP`), and TCP port (`%P`) as its command-line arguments. The external command can decide to decline the service by exiting with a non-zero status (or to allow it by exiting with a zero status). It can also look at the $REMOTE_ADDR @@ -217,7 +218,7 @@ The external command can optionally write a single line to its standard output to be sent to the requestor as an error message when it declines the service. -<directory>:: +_<directory>_:: The remaining arguments provide a list of directories. If any directories are specified, then the `git-daemon` process will serve a requested directory only if it is contained in one of @@ -229,24 +230,24 @@ SERVICES These services can be globally enabled/disabled using the command-line options of this command. If finer-grained -control is desired (e.g. to allow 'git archive' to be run +control is desired (e.g. to allow `git archive` to be run against only in a few selected repositories the daemon serves), the per-repository configuration file can be used to enable or disable them. upload-pack:: - This serves 'git fetch-pack' and 'git ls-remote' + This serves `git fetch-pack` and `git ls-remote` clients. It is enabled by default, but a repository can disable it by setting `daemon.uploadpack` configuration item to `false`. upload-archive:: - This serves 'git archive --remote'. It is disabled by + This serves `git archive --remote`. It is disabled by default, but a repository can enable it by setting `daemon.uploadarch` configuration item to `true`. receive-pack:: - This serves 'git send-pack' clients, allowing anonymous + This serves `git send-pack` clients, allowing anonymous push. It is disabled by default, as there is _no_ authentication in the protocol (in other words, anybody can push anything into the repository, including removal @@ -300,7 +301,7 @@ default repository could be made as well. 'git daemon' as regular daemon for virtual hosts:: - To set up 'git daemon' as a regular, non-inetd service that + To set up `git daemon` as a regular, non-inetd service that handles repositories for multiple virtual hosts based on their IP addresses, start the daemon like this: + @@ -317,7 +318,7 @@ Repositories can still be accessed by hostname though, assuming they correspond to these IP addresses. selectively enable/disable services per repository:: - To enable 'git archive --remote' and disable 'git fetch' against + To enable `git archive --remote` and disable `git fetch` against a repository, have the following in the configuration file in the repository (that is the file 'config' next to `HEAD`, 'refs' and 'objects'). @@ -331,8 +332,8 @@ selectively enable/disable services per repository:: ENVIRONMENT ----------- -'git daemon' will set REMOTE_ADDR to the IP address of the client -that connected to it, if the IP address is available. REMOTE_ADDR will +`git daemon` will set `REMOTE_ADDR` to the IP address of the client +that connected to it, if the IP address is available. `REMOTE_ADDR` will be available in the environment of hooks called when services are performed. diff --git a/Documentation/git-diff-pairs.adoc b/Documentation/git-diff-pairs.adoc new file mode 100644 index 0000000000..f99fcd1ead --- /dev/null +++ b/Documentation/git-diff-pairs.adoc @@ -0,0 +1,60 @@ +git-diff-pairs(1) +================= + +NAME +---- +git-diff-pairs - Compare the content and mode of provided blob pairs + +SYNOPSIS +-------- +[synopsis] +git diff-pairs -z [<diff-options>] + +DESCRIPTION +----------- +Show changes for file pairs provided on stdin. Input for this command must be +in the NUL-terminated raw output format as generated by commands such as `git +diff-tree -z -r --raw`. By default, the outputted diffs are computed and shown +in the patch format when stdin closes. + +A single NUL byte may be written to stdin between raw input lines to compute +file pair diffs up to that point instead of waiting for stdin to close. A NUL +byte is also written to the output to delimit between these batches of diffs. + +Usage of this command enables the traditional diff pipeline to be broken up +into separate stages where `diff-pairs` acts as the output phase. Other +commands, such as `diff-tree`, may serve as a frontend to compute the raw +diff format used as input. + +Instead of computing diffs via `git diff-tree -p -M` in one step, `diff-tree` +can compute the file pairs and rename information without the blob diffs. This +output can be fed to `diff-pairs` to generate the underlying blob diffs as done +in the following example: + +----------------------------- +git diff-tree -z -r -M $a $b | +git diff-pairs -z +----------------------------- + +Computing the tree diff upfront with rename information allows patch output +from `diff-pairs` to be progressively computed over the course of potentially +multiple invocations. + +Pathspecs are not currently supported by `diff-pairs`. Pathspec limiting should +be performed by the upstream command generating the raw diffs used as input. + +Tree objects are not currently supported as input and are rejected. + +Abbreviated object IDs in the `diff-pairs` input are not supported. Outputted +object IDs can be abbreviated using the `--abbrev` option. + +OPTIONS +------- + +include::diff-options.adoc[] + +include::diff-generate-patch.adoc[] + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/git-diff.adoc b/Documentation/git-diff.adoc index dec173a345..272331afba 100644 --- a/Documentation/git-diff.adoc +++ b/Documentation/git-diff.adoc @@ -14,7 +14,7 @@ git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...] git diff [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...] git diff [<options>] <commit>...<commit> [--] [<path>...] git diff [<options>] <blob> <blob> -git diff [<options>] --no-index [--] <path> <path> +git diff [<options>] --no-index [--] <path> <path> [<pathspec>...] DESCRIPTION ----------- @@ -31,14 +31,18 @@ files on disk. further add to the index but you still haven't. You can stage these changes by using linkgit:git-add[1]. -`git diff [<options>] --no-index [--] <path> <path>`:: +`git diff [<options>] --no-index [--] <path> <path> [<pathspec>...]`:: This form is to compare the given two paths on the filesystem. You can omit the `--no-index` option when running the command in a working tree controlled by Git and at least one of the paths points outside the working tree, or when running the command outside a working tree - controlled by Git. This form implies `--exit-code`. + controlled by Git. This form implies `--exit-code`. If both + paths point to directories, additional pathspecs may be + provided. These will limit the files included in the + difference. All such pathspecs must be relative as they + apply to both sides of the diff. `git diff [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]`:: diff --git a/Documentation/git-fast-export.adoc b/Documentation/git-fast-export.adoc index 752e4b9b01..43bbb4f63c 100644 --- a/Documentation/git-fast-export.adoc +++ b/Documentation/git-fast-export.adoc @@ -27,17 +27,31 @@ OPTIONS Insert 'progress' statements every <n> objects, to be shown by 'git fast-import' during import. ---signed-tags=(verbatim|warn|warn-strip|strip|abort):: +--signed-tags=(verbatim|warn-verbatim|warn-strip|strip|abort):: Specify how to handle signed tags. Since any transformation - after the export can change the tag names (which can also happen - when excluding revisions) the signatures will not match. + after the export (or during the export, such as excluding + revisions) can change the hashes being signed, the signatures + may become invalid. + When asking to 'abort' (which is the default), this program will die when encountering a signed tag. With 'strip', the tags will silently be made unsigned, with 'warn-strip' they will be made unsigned but a warning will be displayed, with 'verbatim', they will be silently -exported and with 'warn', they will be exported, but you will see a -warning. +exported and with 'warn-verbatim' (or 'warn', a deprecated synonym), +they will be exported, but you will see a warning. 'verbatim' and +'warn-verbatim' should only be used if you know that no transformation +affecting tags or any commit in their history will be performed by you +or by fast-export or fast-import, or if you do not care that the +resulting tag will have an invalid signature. + +--signed-commits=(verbatim|warn-verbatim|warn-strip|strip|abort):: + Specify how to handle signed commits. Behaves exactly as + '--signed-tags', but for commits. Default is 'strip', which + is the same as how earlier versions of this command without + this option behaved. ++ +NOTE: This is highly experimental and the format of the data stream may +change in the future without compatibility guarantees. --tag-of-filtered-object=(abort|drop|rewrite):: Specify how to handle tags whose tagged object is filtered out. diff --git a/Documentation/git-fast-import.adoc b/Documentation/git-fast-import.adoc index 58a2eaa51a..250d866652 100644 --- a/Documentation/git-fast-import.adoc +++ b/Documentation/git-fast-import.adoc @@ -431,13 +431,22 @@ and control the current import process. More detailed discussion Create or update a branch with a new commit, recording one logical change to the project. +//// +Yes, it's intentional that the 'gpgsig' line doesn't have a trailing +`LF`; the definition of `data` has a byte-count prefix, so it +doesn't need an `LF` to act as a terminator (and `data` also already +includes an optional trailing `LF?` just in case you want to include +one). +//// + .... 'commit' SP <ref> LF mark? original-oid? ('author' (SP <name>)? SP LT <email> GT SP <when> LF)? 'committer' (SP <name>)? SP LT <email> GT SP <when> LF - ('encoding' SP <encoding>)? + ('gpgsig' SP <alg> LF data)? + ('encoding' SP <encoding> LF)? data ('from' SP <commit-ish> LF)? ('merge' SP <commit-ish> LF)* @@ -505,6 +514,18 @@ that was selected by the --date-format=<fmt> command-line option. See ``Date Formats'' above for the set of supported formats, and their syntax. +`gpgsig` +^^^^^^^^ + +The optional `gpgsig` command is used to include a PGP/GPG signature +that signs the commit data. + +Here <alg> specifies which hashing algorithm is used for this +signature, either `sha1` or `sha256`. + +NOTE: This is highly experimental and the format of the data stream may +change in the future without compatibility guarantees. + `encoding` ^^^^^^^^^^ The optional `encoding` command indicates the encoding of the commit diff --git a/Documentation/git-for-each-ref.adoc b/Documentation/git-for-each-ref.adoc index ffb97e62c2..5ef89fc0fe 100644 --- a/Documentation/git-for-each-ref.adoc +++ b/Documentation/git-for-each-ref.adoc @@ -441,6 +441,7 @@ Ref: %(*refname) A simple example showing the use of shell eval on the output, demonstrating the use of --shell. List the prefixes of all heads: + ------------ #!/bin/sh @@ -455,6 +456,7 @@ done A bit more elaborate report on tags, demonstrating that the format may be an entire script: + ------------ #!/bin/sh diff --git a/Documentation/git-fsck.adoc b/Documentation/git-fsck.adoc index 8f32800a83..11203ba925 100644 --- a/Documentation/git-fsck.adoc +++ b/Documentation/git-fsck.adoc @@ -12,7 +12,7 @@ SYNOPSIS 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs] [--[no-]full] [--strict] [--verbose] [--lost-found] [--[no-]dangling] [--[no-]progress] [--connectivity-only] - [--[no-]name-objects] [<object>...] + [--[no-]name-objects] [--[no-]references] [<object>...] DESCRIPTION ----------- @@ -104,6 +104,11 @@ care about this output and want to speed it up further. progress status even if the standard error stream is not directed to a terminal. +--[no-]references:: + Control whether to check the references database consistency + via 'git refs verify'. See linkgit:git-refs[1] for details. + The default is to check the references database. + CONFIGURATION ------------- diff --git a/Documentation/git-maintenance.adoc b/Documentation/git-maintenance.adoc index 0450d74aff..540b5cf68b 100644 --- a/Documentation/git-maintenance.adoc +++ b/Documentation/git-maintenance.adoc @@ -126,13 +126,17 @@ loose-objects:: objects that already exist in a pack-file; concurrent Git processes will examine the pack-file for the object data instead of the loose object. Second, it creates a new pack-file (starting with "loose-") - containing a batch of loose objects. The batch size is limited to 50 - thousand objects to prevent the job from taking too long on a - repository with many loose objects. The `gc` task writes unreachable - objects as loose objects to be cleaned up by a later step only if - they are not re-added to a pack-file; for this reason it is not - advisable to enable both the `loose-objects` and `gc` tasks at the - same time. + containing a batch of loose objects. ++ +The batch size defaults to fifty thousand objects to prevent the job from +taking too long on a repository with many loose objects. Use the +`maintenance.loose-objects.batchSize` config option to adjust this size, +including a value of `0` to remove the limit. ++ +The `gc` task writes unreachable objects as loose objects to be cleaned up +by a later step only if they are not re-added to a pack-file; for this +reason it is not advisable to enable both the `loose-objects` and `gc` +tasks at the same time. incremental-repack:: The `incremental-repack` job repacks the object directory @@ -158,6 +162,18 @@ pack-refs:: need to iterate across many references. See linkgit:git-pack-refs[1] for more information. +reflog-expire:: + The `reflog-expire` task deletes any entries in the reflog older than the + expiry threshold. See linkgit:git-reflog[1] for more information. + +rerere-gc:: + The `rerere-gc` task invokes garbage collection for stale entries in + the rerere cache. See linkgit:git-rerere[1] for more information. + +worktree-prune:: + The `worktree-prune` task deletes stale or broken worktrees. See + linkgit:git-worktree[1] for more information. + OPTIONS ------- --auto:: diff --git a/Documentation/git-merge-tree.adoc b/Documentation/git-merge-tree.adoc index cf0578f9b5..f824eea61f 100644 --- a/Documentation/git-merge-tree.adoc +++ b/Documentation/git-merge-tree.adoc @@ -65,6 +65,12 @@ OPTIONS default is to include these messages if there are merge conflicts, and to omit them otherwise. +--quiet:: + Disable all output from the program. Useful when you are only + interested in the exit status. Allows merge-tree to exit + early when it finds a conflict, and allows it to avoid writing + most objects created by merges. + --allow-unrelated-histories:: merge-tree will by default error out if the two branches specified share no common history. This flag can be given to override that diff --git a/Documentation/git-merge.adoc b/Documentation/git-merge.adoc index 64281d6d44..12aa859d16 100644 --- a/Documentation/git-merge.adoc +++ b/Documentation/git-merge.adoc @@ -8,13 +8,13 @@ git-merge - Join two or more development histories together SYNOPSIS -------- -[verse] -'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] +[synopsis] +git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] [--no-verify] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] [--[no-]allow-unrelated-histories] [--[no-]rerere-autoupdate] [-m <msg>] [-F <file>] [--into-name <branch>] [<commit>...] -'git merge' (--continue | --abort | --quit) +git merge (--continue | --abort | --quit) DESCRIPTION ----------- @@ -57,7 +57,7 @@ merge started (and especially if those changes were further modified after the merge was started), `git merge --abort` will in some cases be unable to reconstruct the original (pre-merge) changes. Therefore: -*Warning*: Running `git merge` with non-trivial uncommitted changes is +WARNING: Running `git merge` with non-trivial uncommitted changes is discouraged: while possible, it may leave you in a state that is hard to back out of in the case of a conflict. @@ -67,7 +67,7 @@ OPTIONS include::merge-options.adoc[] --m <msg>:: +`-m <msg>`:: Set the commit message to be used for the merge commit (in case one is created). + @@ -78,13 +78,13 @@ The `git fmt-merge-msg` command can be used to give a good default for automated `git merge` invocations. The automated message can include the branch description. ---into-name <branch>:: +`--into-name <branch>`:: Prepare the default merge message as if merging to the branch - `<branch>`, instead of the name of the real branch to which + _<branch>_, instead of the name of the real branch to which the merge is made. --F <file>:: ---file=<file>:: +`-F <file>`:: +`--file=<file>`:: Read the commit message to be used for the merge commit (in case one is created). + @@ -93,12 +93,12 @@ will be appended to the specified message. include::rerere-options.adoc[] ---overwrite-ignore:: ---no-overwrite-ignore:: +`--overwrite-ignore`:: +`--no-overwrite-ignore`:: Silently overwrite ignored files from the merge result. This is the default behavior. Use `--no-overwrite-ignore` to abort. ---abort:: +`--abort`:: Abort the current conflict resolution process, and try to reconstruct the pre-merge state. If an autostash entry is present, apply it to the worktree. @@ -114,17 +114,17 @@ which case `git merge --abort` applies the stash entry to the worktree whereas `git reset --merge` will save the stashed changes in the stash list. ---quit:: +`--quit`:: Forget about the current merge in progress. Leave the index and the working tree as-is. If `MERGE_AUTOSTASH` is present, the stash entry will be saved to the stash list. ---continue:: +`--continue`:: After a `git merge` stops due to conflicts you can conclude the merge by running `git merge --continue` (see "HOW TO RESOLVE CONFLICTS" section below). -<commit>...:: +`<commit>...`:: Commits, usually other branch heads, to merge into our branch. Specifying more than one commit will create a merge with more than two parents (affectionately called an Octopus merge). @@ -152,7 +152,7 @@ To avoid recording unrelated changes in the merge commit, `git pull` and `git merge` will also abort if there are any changes registered in the index relative to the `HEAD` commit. (Special narrow exceptions to this rule may exist depending on which merge -strategy is in use, but generally, the index must match HEAD.) +strategy is in use, but generally, the index must match `HEAD`.) If all named commits are already ancestors of `HEAD`, `git merge` will exit early with the message "Already up to date." @@ -195,11 +195,11 @@ happens: stage 2 from `HEAD`, and stage 3 from `MERGE_HEAD` (you can inspect the stages with `git ls-files -u`). The working tree files contain the result of the merge operation; i.e. 3-way - merge results with familiar conflict markers `<<<` `===` `>>>`. + merge results with familiar conflict markers +<<<+ `===` +>>>+. 5. A ref named `AUTO_MERGE` is written, pointing to a tree corresponding to the current content of the working tree (including conflict markers for textual conflicts). Note that this ref is only - written when the 'ort' merge strategy is used (the default). + written when the `ort` merge strategy is used (the default). 6. No other changes are made. In particular, the local modifications you had before you started merge will stay the same and the index entries for them stay as they were, @@ -231,7 +231,6 @@ git merge v1.2.3^0 git merge --ff-only v1.2.3 ---- - HOW CONFLICTS ARE PRESENTED --------------------------- @@ -260,7 +259,7 @@ And here is another line that is cleanly resolved or unmodified. ------------ The area where a pair of conflicting changes happened is marked with markers -`<<<<<<<`, `=======`, and `>>>>>>>`. The part before the `=======` ++<<<<<<<+, `=======`, and +>>>>>>>+. The part before the `=======` is typically your side, and the part afterwards is typically their side. The default format does not show what the original said in the conflicting @@ -270,7 +269,7 @@ side wants to say it is hard and you'd prefer to go shopping, while the other side wants to claim it is easy. An alternative style can be used by setting the `merge.conflictStyle` -configuration variable to either "diff3" or "zdiff3". In "diff3" +configuration variable to either `diff3` or `zdiff3`. In `diff3` style, the above conflict may look like this: ------------ @@ -290,7 +289,7 @@ Git makes conflict resolution easy. And here is another line that is cleanly resolved or unmodified. ------------ -while in "zdiff3" style, it may look like this: +while in `zdiff3` style, it may look like this: ------------ Here are lines that are either unchanged from the common @@ -308,8 +307,8 @@ Git makes conflict resolution easy. And here is another line that is cleanly resolved or unmodified. ------------ -In addition to the `<<<<<<<`, `=======`, and `>>>>>>>` markers, it uses -another `|||||||` marker that is followed by the original text. You can +In addition to the +<<<<<<<+, `=======`, and +>>>>>>>+ markers, it uses +another +|||||||+ marker that is followed by the original text. You can tell that the original just stated a fact, and your side simply gave in to that statement and gave up, while the other side tried to have a more positive attitude. You can sometimes come up with a better resolution by @@ -390,8 +389,8 @@ include::merge-strategies.adoc[] CONFIGURATION ------------- -branch.<name>.mergeOptions:: - Sets default options for merging into branch <name>. The syntax and +`branch.<name>.mergeOptions`:: + Sets default options for merging into branch _<name>_. The syntax and supported options are the same as those of `git merge`, but option values containing whitespace characters are currently not supported. diff --git a/Documentation/git-mergetool.adoc b/Documentation/git-mergetool.adoc index 046c3258f0..77d0b50550 100644 --- a/Documentation/git-mergetool.adoc +++ b/Documentation/git-mergetool.adoc @@ -7,95 +7,95 @@ git-mergetool - Run merge conflict resolution tools to resolve merge conflicts SYNOPSIS -------- -[verse] -'git mergetool' [--tool=<tool>] [-y | --[no-]prompt] [<file>...] +[synopsis] +git mergetool [--tool=<tool>] [-y | --[no-]prompt] [<file>...] DESCRIPTION ----------- Use `git mergetool` to run one of several merge utilities to resolve -merge conflicts. It is typically run after 'git merge'. +merge conflicts. It is typically run after `git merge`. If one or more <file> parameters are given, the merge tool program will be run to resolve differences in each file (skipping those without conflicts). Specifying a directory will include all unresolved files in -that path. If no <file> names are specified, 'git mergetool' will run +that path. If no _<file>_ names are specified, `git mergetool` will run the merge tool program on every file with merge conflicts. OPTIONS ------- --t <tool>:: ---tool=<tool>:: - Use the merge resolution program specified by <tool>. - Valid values include emerge, gvimdiff, kdiff3, - meld, vimdiff, and tortoisemerge. Run `git mergetool --tool-help` - for the list of valid <tool> settings. +`-t <tool>`:: +`--tool=<tool>`:: + Use the merge resolution program specified by _<tool>_. + Valid values include `emerge`, `gvimdiff`, `kdiff3`, + `meld`, `vimdiff`, and `tortoisemerge`. Run `git mergetool --tool-help` + for the list of valid _<tool>_ settings. + -If a merge resolution program is not specified, 'git mergetool' +If a merge resolution program is not specified, `git mergetool` will use the configuration variable `merge.tool`. If the -configuration variable `merge.tool` is not set, 'git mergetool' +configuration variable `merge.tool` is not set, `git mergetool` will pick a suitable default. + You can explicitly provide a full path to the tool by setting the configuration variable `mergetool.<tool>.path`. For example, you can configure the absolute path to kdiff3 by setting -`mergetool.kdiff3.path`. Otherwise, 'git mergetool' assumes the -tool is available in PATH. +`mergetool.kdiff3.path`. Otherwise, `git mergetool` assumes the +tool is available in `$PATH`. + Instead of running one of the known merge tool programs, -'git mergetool' can be customized to run an alternative program +`git mergetool` can be customized to run an alternative program by specifying the command line to invoke in a configuration variable `mergetool.<tool>.cmd`. + -When 'git mergetool' is invoked with this tool (either through the +When `git mergetool` is invoked with this tool (either through the `-t` or `--tool` option or the `merge.tool` configuration -variable), the configured command line will be invoked with `$BASE` +variable), the configured command line will be invoked with `BASE` set to the name of a temporary file containing the common base for -the merge, if available; `$LOCAL` set to the name of a temporary +the merge, if available; `LOCAL` set to the name of a temporary file containing the contents of the file on the current branch; -`$REMOTE` set to the name of a temporary file containing the -contents of the file to be merged, and `$MERGED` set to the name +`REMOTE` set to the name of a temporary file containing the +contents of the file to be merged, and `MERGED` set to the name of the file to which the merge tool should write the result of the merge resolution. + If the custom merge tool correctly indicates the success of a merge resolution with its exit code, then the configuration variable `mergetool.<tool>.trustExitCode` can be set to `true`. -Otherwise, 'git mergetool' will prompt the user to indicate the +Otherwise, `git mergetool` will prompt the user to indicate the success of the resolution after the custom tool has exited. ---tool-help:: +`--tool-help`:: Print a list of merge tools that may be used with `--tool`. --y:: ---no-prompt:: +`-y`:: +`--no-prompt`:: Don't prompt before each invocation of the merge resolution program. This is the default if the merge resolution program is explicitly specified with the `--tool` option or with the `merge.tool` configuration variable. ---prompt:: +`--prompt`:: Prompt before each invocation of the merge resolution program to give the user a chance to skip the path. --g:: ---gui:: - When 'git-mergetool' is invoked with the `-g` or `--gui` option, +`-g`:: +`--gui`:: + When `git-mergetool` is invoked with the `-g` or `--gui` option, the default merge tool will be read from the configured `merge.guitool` variable instead of `merge.tool`. If `merge.guitool` is not set, we will fallback to the tool configured under `merge.tool`. This may be autoselected using the configuration variable `mergetool.guiDefault`. ---no-gui:: +`--no-gui`:: This overrides a previous `-g` or `--gui` setting or `mergetool.guiDefault` configuration and reads the default merge tool from the configured `merge.tool` variable. --O<orderfile>:: +`-O<orderfile>`:: Process files in the order specified in the - <orderfile>, which has one shell glob pattern per line. + _<orderfile>_, which has one shell glob pattern per line. This overrides the `diff.orderFile` configuration variable (see linkgit:git-config[1]). To cancel `diff.orderFile`, use `-O/dev/null`. diff --git a/Documentation/git-multi-pack-index.adoc b/Documentation/git-multi-pack-index.adoc index 631d5c7d15..b6cd0d7f85 100644 --- a/Documentation/git-multi-pack-index.adoc +++ b/Documentation/git-multi-pack-index.adoc @@ -38,10 +38,13 @@ write:: + -- --preferred-pack=<pack>:: - Optionally specify the tie-breaking pack used when - multiple packs contain the same object. `<pack>` must - contain at least one object. If not given, ties are - broken in favor of the pack with the lowest mtime. + When specified, break ties in favor of this pack when + there are additional copies of its objects in other + packs. Ties for objects not found in the preferred + pack are always resolved in favor of the copy in the + pack with the highest mtime. If unspecified, the pack + with the lowest mtime is used by default. The + preferred pack must have at least one object. --[no-]bitmap:: Control whether or not a multi-pack bitmap is written. diff --git a/Documentation/git-mv.adoc b/Documentation/git-mv.adoc index dc1bf61534..f707e998f7 100644 --- a/Documentation/git-mv.adoc +++ b/Documentation/git-mv.adoc @@ -8,19 +8,18 @@ git-mv - Move or rename a file, a directory, or a symlink SYNOPSIS -------- -[verse] -'git mv' [<options>] <source>... <destination> + +[synopsis] +git mv [-v] [-f] [-n] [-k] <source> <destination> +git mv [-v] [-f] [-n] [-k] <source>... <destination-directory> DESCRIPTION ----------- Move or rename a file, directory, or symlink. - git mv [-v] [-f] [-n] [-k] <source> <destination> - git mv [-v] [-f] [-n] [-k] <source> ... <destination-directory> - -In the first form, it renames <source>, which must exist and be either -a file, symlink or directory, to <destination>. -In the second form, the last argument has to be an existing +In the first form, it renames _<source>_, which must exist and be either +a file, symlink or directory, to _<destination>_. +In the second form, _<destination-directory>_ has to be an existing directory; the given sources will be moved into this directory. The index is updated after successful completion, but the change must still be @@ -28,20 +27,20 @@ committed. OPTIONS ------- --f:: ---force:: +`-f`:: +`--force`:: Force renaming or moving of a file even if the <destination> exists. --k:: +`-k`:: Skip move or rename actions which would lead to an error condition. An error happens when a source is neither existing nor controlled by Git, or when it would overwrite an existing file unless `-f` is given. --n:: ---dry-run:: +`-n`:: +`--dry-run`:: Do nothing; only show what would happen --v:: ---verbose:: +`-v`:: +`--verbose`:: Report the names of files as they are moved. SUBMODULES @@ -49,8 +48,8 @@ SUBMODULES Moving a submodule using a gitfile (which means they were cloned with a Git version 1.7.8 or newer) will update the gitfile and core.worktree setting to make the submodule work in the new location. -It also will attempt to update the submodule.<name>.path setting in -the linkgit:gitmodules[5] file and stage that file (unless -n is used). +It also will attempt to update the `submodule.<name>.path` setting in +the linkgit:gitmodules[5] file and stage that file (unless `-n` is used). BUGS ---- diff --git a/Documentation/git-notes.adoc b/Documentation/git-notes.adoc index bcfe3dacd3..46a232ca71 100644 --- a/Documentation/git-notes.adoc +++ b/Documentation/git-notes.adoc @@ -87,6 +87,9 @@ In `--stdin` mode, take lines in the format on standard input, and copy the notes from each _<from-object>_ to its corresponding _<to-object>_. (The optional _<rest>_ is ignored so that the command can read the input given to the `post-rewrite` hook.) ++ +`--stdin` cannot be combined with object names given on the command +line. `append`:: Append new message(s) given by `-m` or `-F` options to an @@ -124,6 +127,10 @@ When done, the user can either finalize the merge with giving zero or one object from the command line, this is equivalent to specifying an empty note message to the `edit` subcommand. ++ +In `--stdin` mode, also remove the object names given on standard +input. In other words, `--stdin` can be combined with object names from +the command line. `prune`:: Remove all notes for non-existing/unreachable objects. @@ -144,26 +151,18 @@ OPTIONS Use the given note message (instead of prompting). If multiple `-m` options are given, their values are concatenated as separate paragraphs. - Lines starting with `#` and empty lines other than a - single line between paragraphs will be stripped out. - If you wish to keep them verbatim, use `--no-stripspace`. `-F <file>`:: `--file=<file>`:: Take the note message from the given file. Use `-` to read the note message from the standard input. - Lines starting with `#` and empty lines other than a - single line between paragraphs will be stripped out. - If you wish to keep them verbatim, use `--no-stripspace`. `-C <object>`:: `--reuse-message=<object>`:: Take the given blob object (for example, another note) as the note message. (Use `git notes copy <object>` instead to - copy notes between objects.). By default, message will be - copied verbatim, but if you wish to strip out the lines - starting with `#` and empty lines other than a single line - between paragraphs, use with `--stripspace` option. + copy notes between objects.) Implies `--no-stripspace` since + the default behavior is to copy the message verbatim. `-c <object>`:: `--reedit-message=<object>`:: @@ -174,21 +173,34 @@ OPTIONS Allow an empty note object to be stored. The default behavior is to automatically remove empty notes. -`--[no-]separator`:: `--separator=<paragraph-break>`:: +`--separator`:: +`--no-separator`:: Specify a string used as a custom inter-paragraph separator (a newline is added at the end as needed). If `--no-separator`, no separators will be added between paragraphs. Defaults to a blank line. -`--[no-]stripspace`:: - Strip leading and trailing whitespace from the note message. - Also strip out empty lines other than a single line between - paragraphs. Lines starting with `#` will be stripped out - in non-editor cases like `-m`, `-F` and `-C`, but not in - editor case like `git notes edit`, `-c`, etc. - -`--ref <ref>`:: +`--stripspace`:: +`--no-stripspace`:: + Clean up whitespace. Specifically (see + linkgit:git-stripspace[1]): ++ +-- +- remove trailing whitespace from all lines +- collapse multiple consecutive empty lines into one empty line +- remove empty lines from the beginning and end of the input +- add a missing `\n` to the last line if necessary. +-- ++ +`--stripspace` is the default except for +`-C`/`--reuse-message`. However, keep in mind that this depends on the +order of similar options. For example, for `-C <object> -m<message>`, +`--stripspace` will be used because the default for `-m` overrides the +previous `-C`. This is a known limitation that may be fixed in the +future. + +`--ref=<ref>`:: Manipulate the notes tree in _<ref>_. This overrides `GIT_NOTES_REF` and the `core.notesRef` configuration. The ref specifies the full refname when it begins with `refs/notes/`; when it @@ -200,9 +212,7 @@ OPTIONS object that does not have notes attached to it. `--stdin`:: - Also read the object names to remove notes from the standard - input (there is no reason you cannot combine this with object - names from the command line). + Only valid for `remove` and `copy`. See the respective subcommands. `-n`:: `--dry-run`:: diff --git a/Documentation/git-p4.adoc b/Documentation/git-p4.adoc index de5ee6748e..f97b786bf9 100644 --- a/Documentation/git-p4.adoc +++ b/Documentation/git-p4.adoc @@ -80,6 +80,7 @@ This: To reproduce the entire p4 history in Git, use the '@all' modifier on the depot path: + ------------ $ git p4 clone //depot/path/project@all ------------ @@ -89,19 +90,23 @@ Sync ~~~~ As development continues in the p4 repository, those changes can be included in the Git repository using: + ------------ $ git p4 sync ------------ + This command finds new changes in p4 and imports them as Git commits. P4 repositories can be added to an existing Git repository using 'git p4 sync' too: + ------------ $ mkdir repo-git $ cd repo-git $ git init $ git p4 sync //path/in/your/perforce/depot ------------ + This imports the specified depot into 'refs/remotes/p4/master' in an existing Git repository. The `--branch` option can be used to specify a different branch to @@ -125,6 +130,7 @@ and merge them with local uncommitted changes. Often, the p4 repository is the ultimate location for all code, thus a rebase workflow makes sense. This command does 'git p4 sync' followed by 'git rebase' to move local commits on top of updated p4 changes. + ------------ $ git p4 rebase ------------ @@ -140,16 +146,19 @@ will be created and populated if it does not already exist. To submit all changes that are in the current Git branch but not in the 'p4/master' branch, use: + ------------ $ git p4 submit ------------ To specify a branch other than the current one, use: + ------------ $ git p4 submit topicbranch ------------ To specify a single commit or a range of commits, use: + ------------ $ git p4 submit --commit <sha1> $ git p4 submit --commit <sha1..sha1> @@ -510,20 +519,24 @@ when cloning or syncing to have 'git p4' automatically find subdirectories in p4, and to generate these as branches in Git. For example, if the P4 repository structure is: + ---- //depot/main/... //depot/branch1/... ---- And "p4 branch -o branch1" shows a View line that looks like: + ---- //depot/main/... //depot/branch1/... ---- Then this 'git p4 clone' command: + ---- git p4 clone --detect-branches //depot@all ---- + produces a separate branch in 'refs/remotes/p4/' for //depot/main, called 'master', and one for //depot/branch1 called 'depot/branch1'. @@ -536,6 +549,7 @@ simple p4 branch specification, where the "source" and "destination" are the path elements in the p4 repository. The example above relied on the presence of the p4 branch. Without p4 branches, the same result will occur with: + ---- git init depot cd depot diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc index 7f69ae4855..b1c5aa27da 100644 --- a/Documentation/git-pack-objects.adoc +++ b/Documentation/git-pack-objects.adoc @@ -10,13 +10,13 @@ SYNOPSIS -------- [verse] 'git pack-objects' [-q | --progress | --all-progress] [--all-progress-implied] - [--no-reuse-delta] [--delta-base-offset] [--non-empty] - [--local] [--incremental] [--window=<n>] [--depth=<n>] - [--revs [--unpacked | --all]] [--keep-pack=<pack-name>] - [--cruft] [--cruft-expiration=<time>] - [--stdout [--filter=<filter-spec>] | <base-name>] - [--shallow] [--keep-true-parents] [--[no-]sparse] - [--name-hash-version=<n>] < <object-list> + [--no-reuse-delta] [--delta-base-offset] [--non-empty] + [--local] [--incremental] [--window=<n>] [--depth=<n>] + [--revs [--unpacked | --all]] [--keep-pack=<pack-name>] + [--cruft] [--cruft-expiration=<time>] + [--stdout [--filter=<filter-spec>] | <base-name>] + [--shallow] [--keep-true-parents] [--[no-]sparse] + [--name-hash-version=<n>] [--path-walk] < <object-list> DESCRIPTION @@ -375,6 +375,17 @@ many different directories. At the moment, this version is not allowed when writing reachability bitmap files with `--write-bitmap-index` and it will be automatically changed to version `1`. +--path-walk:: + Perform compression by first organizing objects by path, then a + second pass that compresses across paths as normal. This has the + potential to improve delta compression especially in the presence + of filenames that cause collisions in Git's default name-hash + algorithm. ++ +Incompatible with `--delta-islands`, `--shallow`, or `--filter`. The +`--use-bitmap-index` option will be ignored in the presence of +`--path-walk.` + DELTA ISLANDS ------------- diff --git a/Documentation/git-pack-refs.adoc b/Documentation/git-pack-refs.adoc index 2dcabaf74c..652c549771 100644 --- a/Documentation/git-pack-refs.adoc +++ b/Documentation/git-pack-refs.adoc @@ -88,10 +88,10 @@ Do not pack refs matching the given `glob(7)` pattern. Repetitions of this optio accumulate exclusion patterns. Use `--no-exclude` to clear and reset the list of patterns. If a ref is already packed, including it with `--exclude` will not unpack it. - ++ When used with `--all`, pack only loose refs which do not match any of the provided `--exclude` patterns. - ++ When used with `--include`, refs provided to `--include`, minus refs that are provided to `--exclude` will be packed. diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index 153cb69a4f..956d3048f5 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -1107,10 +1107,12 @@ In that case, the fix is easy because 'git rebase' knows to skip changes that are already present in the new upstream (unless `--reapply-cherry-picks` is given). So if you say (assuming you're on 'topic') + ------------ $ git rebase subsystem ------------ you will end up with the fixed history + ------------ o---o---o---o---o---o---o---o master \ @@ -1145,6 +1147,7 @@ of the old 'subsystem', for example: You can then transplant the old `subsystem..topic` to the new tip by saying (for the reflog case, and assuming you are on 'topic' already): + ------------ $ git rebase --onto subsystem subsystem@{1} ------------ diff --git a/Documentation/git-receive-pack.adoc b/Documentation/git-receive-pack.adoc index 20aca92073..0956086d61 100644 --- a/Documentation/git-receive-pack.adoc +++ b/Documentation/git-receive-pack.adoc @@ -46,6 +46,18 @@ OPTIONS `$GIT_URL/info/refs?service=git-receive-pack` requests. See `--http-backend-info-refs` in linkgit:git-upload-pack[1]. +--skip-connectivity-check:: + Bypasses the connectivity checks that validate the existence of all + objects in the transitive closure of reachable objects. This option is + intended for server operators that want to implement their own object + connectivity validation outside of Git. This is useful in such cases + where the server-side knows additional information about how Git is + being used and thus can rely on certain guarantees to more efficiently + compute object connectivity that Git itself cannot make. Usage of this + option without a reliable external mechanism to ensure full reachable + object connectivity risks corrupting the repository and should not be + used in the general case. + PRE-RECEIVE HOOK ---------------- Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists diff --git a/Documentation/git-reflog.adoc b/Documentation/git-reflog.adoc index a929c52982..412f06b8fe 100644 --- a/Documentation/git-reflog.adoc +++ b/Documentation/git-reflog.adoc @@ -16,6 +16,7 @@ SYNOPSIS [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...] 'git reflog delete' [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <ref>@{<specifier>}... +'git reflog drop' [--all [--single-worktree] | <refs>...] 'git reflog exists' <ref> DESCRIPTION @@ -48,10 +49,14 @@ and not reachable from the current tip, are removed from the reflog. This is typically not used directly by end users -- instead, see linkgit:git-gc[1]. -The "delete" subcommand deletes single entries from the reflog. Its -argument must be an _exact_ entry (e.g. "`git reflog delete -master@{2}`"). This subcommand is also typically not used directly by -end users. +The "delete" subcommand deletes single entries from the reflog, but +not the reflog itself. Its argument must be an _exact_ entry (e.g. "`git +reflog delete master@{2}`"). This subcommand is also typically not used +directly by end users. + +The "drop" subcommand completely removes the reflog for the specified +references. This is in contrast to "expire" and "delete", both of which +can be used to delete reflog entries, but not the reflog itself. The "exists" subcommand checks whether a ref has a reflog. It exits with zero status if the reflog exists, and non-zero status if it does @@ -132,6 +137,16 @@ Options for `delete` `--dry-run`, and `--verbose`, with the same meanings as when they are used with `expire`. +Options for `drop` +~~~~~~~~~~~~~~~~~~ + +--all:: + Drop the reflogs of all references from all worktrees. + +--single-worktree:: + By default when `--all` is specified, reflogs from all working + trees are dropped. This option limits the processing to reflogs + from the current working tree only. GIT --- diff --git a/Documentation/git-repack.adoc b/Documentation/git-repack.adoc index 5852a5c973..d12c4985f6 100644 --- a/Documentation/git-repack.adoc +++ b/Documentation/git-repack.adoc @@ -11,7 +11,7 @@ SYNOPSIS [verse] 'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m] [--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>] - [--write-midx] [--name-hash-version=<n>] + [--write-midx] [--name-hash-version=<n>] [--path-walk] DESCRIPTION ----------- @@ -77,15 +77,18 @@ to the new separate pack will be written. Only useful with `--cruft -d`. --max-cruft-size=<n>:: - Repack cruft objects into packs as large as `<n>` bytes before - creating new packs. As long as there are enough cruft packs - smaller than `<n>`, repacking will cause a new cruft pack to - be created containing objects from any combined cruft packs, - along with any new unreachable objects. Cruft packs larger than - `<n>` will not be modified. When the new cruft pack is larger - than `<n>` bytes, it will be split into multiple packs, all of - which are guaranteed to be at most `<n>` bytes in size. Only - useful with `--cruft -d`. + Overrides `--max-pack-size` for cruft packs. Inherits the value of + `--max-pack-size` (if any) by default. See the documentation for + `--max-pack-size` for more details. + +--combine-cruft-below-size=<n>:: + When generating cruft packs without pruning, only repack + existing cruft packs whose size is strictly less than `<n>`, + where `<n>` represents a number of bytes, which can optionally + be suffixed with "k", "m", or "g". Cruft packs whose size is + greater than or equal to `<n>` are left as-is and not repacked. + Useful when you want to avoid repacking large cruft pack(s) in + repositories that have many and/or large unreachable objects. --expire-to=<dir>:: Write a cruft pack containing pruned objects (if any) to the @@ -255,6 +258,9 @@ linkgit:git-multi-pack-index[1]). Provide this argument to the underlying `git pack-objects` process. See linkgit:git-pack-objects[1] for full details. +--path-walk:: + Pass the `--path-walk` option to the underlying `git pack-objects` + process. See linkgit:git-pack-objects[1] for full details. CONFIGURATION ------------- diff --git a/Documentation/git-reset.adoc b/Documentation/git-reset.adoc index 79ad5643ee..53ab88c545 100644 --- a/Documentation/git-reset.adoc +++ b/Documentation/git-reset.adoc @@ -7,23 +7,23 @@ git-reset - Reset current HEAD to the specified state SYNOPSIS -------- -[verse] -'git reset' [-q] [<tree-ish>] [--] <pathspec>... -'git reset' [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>] -'git reset' (--patch | -p) [<tree-ish>] [--] [<pathspec>...] -'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>] +[synopsis] +git reset [-q] [<tree-ish>] [--] <pathspec>... +git reset [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>] +git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>...] +git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>] DESCRIPTION ----------- -In the first three forms, copy entries from `<tree-ish>` to the index. -In the last form, set the current branch head (`HEAD`) to `<commit>`, +In the first three forms, copy entries from _<tree-ish>_ to the index. +In the last form, set the current branch head (`HEAD`) to _<commit>_, optionally modifying index and working tree to match. -The `<tree-ish>`/`<commit>` defaults to `HEAD` in all forms. +The _<tree-ish>_/_<commit>_ defaults to `HEAD` in all forms. -'git reset' [-q] [<tree-ish>] [--] <pathspec>...:: -'git reset' [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]:: +`git reset [-q] [<tree-ish>] [--] <pathspec>...`:: +`git reset [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]`:: These forms reset the index entries for all paths that match the - `<pathspec>` to their state at `<tree-ish>`. (It does not affect + _<pathspec>_ to their state at _<tree-ish>_. (It does not affect the working tree or the current branch.) + This means that `git reset <pathspec>` is the opposite of `git add @@ -37,30 +37,30 @@ and specifying a commit with `--source`, you can copy the contents of a path out of a commit to the index and to the working tree in one go. -'git reset' (--patch | -p) [<tree-ish>] [--] [<pathspec>...]:: +`git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>...]`:: Interactively select hunks in the difference between the index - and `<tree-ish>` (defaults to `HEAD`). The chosen hunks are applied + and _<tree-ish>_ (defaults to `HEAD`). The chosen hunks are applied in reverse to the index. + This means that `git reset -p` is the opposite of `git add -p`, i.e. -you can use it to selectively reset hunks. See the ``Interactive Mode'' +you can use it to selectively reset hunks. See the "Interactive Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. -'git reset' [<mode>] [<commit>]:: - This form resets the current branch head to `<commit>` and - possibly updates the index (resetting it to the tree of `<commit>`) and - the working tree depending on `<mode>`. Before the operation, `ORIG_HEAD` - is set to the tip of the current branch. If `<mode>` is omitted, - defaults to `--mixed`. The `<mode>` must be one of the following: +`git reset [<mode>] [<commit>]`:: + This form resets the current branch head to _<commit>_ and + possibly updates the index (resetting it to the tree of _<commit>_) and + the working tree depending on _<mode>_. Before the operation, `ORIG_HEAD` + is set to the tip of the current branch. If _<mode>_ is omitted, + defaults to `--mixed`. The _<mode>_ must be one of the following: + -- ---soft:: +`--soft`:: Does not touch the index file or the working tree at all (but - resets the head to `<commit>`, just like all modes do). This leaves + resets the head to _<commit>_, just like all modes do). This leaves all your changed files "Changes to be committed", as `git status` would put it. ---mixed:: +`--mixed`:: Resets the index but not the working tree (i.e., the changed files are preserved but not marked for commit) and reports what has not been updated. This is the default action. @@ -68,33 +68,33 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode. If `-N` is specified, removed paths are marked as intent-to-add (see linkgit:git-add[1]). ---hard:: +`--hard`:: Resets the index and working tree. Any changes to tracked files in the - working tree since `<commit>` are discarded. Any untracked files or + working tree since _<commit>_ are discarded. Any untracked files or directories in the way of writing any tracked files are simply deleted. ---merge:: +`--merge`:: Resets the index and updates the files in the working tree that are - different between `<commit>` and `HEAD`, but keeps those which are + different between _<commit>_ and `HEAD`, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added). - If a file that is different between `<commit>` and the index has + If a file that is different between _<commit>_ and the index has unstaged changes, reset is aborted. + In other words, `--merge` does something like a `git read-tree -u -m <commit>`, but carries forward unmerged index entries. ---keep:: +`--keep`:: Resets index entries and updates files in the working tree that are - different between `<commit>` and `HEAD`. - If a file that is different between `<commit>` and `HEAD` has local + different between _<commit>_ and `HEAD`. + If a file that is different between _<commit>_ and `HEAD` has local changes, reset is aborted. ---[no-]recurse-submodules:: - When the working tree is updated, using --recurse-submodules will +`--[no-]recurse-submodules`:: + When the working tree is updated, using `--recurse-submodules` will also recursively reset the working tree of all active submodules according to the commit recorded in the superproject, also setting - the submodules' HEAD to be detached at that commit. + the submodules' `HEAD` to be detached at that commit. -- See "Reset, restore and revert" in linkgit:git[1] for the differences @@ -104,31 +104,31 @@ between the three commands. OPTIONS ------- --q:: ---quiet:: +`-q`:: +`--quiet`:: Be quiet, only report errors. ---refresh:: ---no-refresh:: +`--refresh`:: +`--no-refresh`:: Refresh the index after a mixed reset. Enabled by default. ---pathspec-from-file=<file>:: - Pathspec is passed in `<file>` instead of commandline args. If - `<file>` is exactly `-` then standard input is used. Pathspec - elements are separated by LF or CR/LF. Pathspec elements can be +`--pathspec-from-file=<file>`:: + Pathspec is passed in _<file>_ instead of commandline args. If + _<file>_ is exactly `-` then standard input is used. Pathspec + elements are separated by _LF_ or _CR_/_LF_. Pathspec elements can be quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). See also `--pathspec-file-nul` and global `--literal-pathspecs`. ---pathspec-file-nul:: +`--pathspec-file-nul`:: Only meaningful with `--pathspec-from-file`. Pathspec elements are - separated with NUL character and all other characters are taken + separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). -\--:: +`--`:: Do not interpret any more arguments as options. -<pathspec>...:: +`<pathspec>...`:: Limits the paths affected by the operation. + For more details, see the 'pathspec' entry in linkgit:gitglossary[7]. @@ -348,7 +348,7 @@ $ git commit ... <8> ------------ + <1> First, reset the history back one commit so that we remove the original - commit, but leave the working tree with all the changes. The -N ensures + commit, but leave the working tree with all the changes. The `-N` ensures that any new files added with `HEAD` are still marked so that `git add -p` will find them. <2> Next, we interactively select diff hunks to add using the `git add -p` @@ -458,7 +458,7 @@ working index HEAD target working index HEAD --keep B C C .... -`reset --merge` is meant to be used when resetting out of a conflicted +`git reset --merge` is meant to be used when resetting out of a conflicted merge. Any mergy operation guarantees that the working tree file that is involved in the merge does not have a local change with respect to the index before it starts, and that it writes the result out to the working tree. So if @@ -467,7 +467,7 @@ between the index and the working tree, then it means that we are not resetting out from a state that a mergy operation left after failing with a conflict. That is why we disallow `--merge` option in this case. -`reset --keep` is meant to be used when removing some of the last +`git reset --keep` is meant to be used when removing some of the last commits in the current branch while keeping changes in the working tree. If there could be conflicts between the changes in the commit we want to remove and the changes in the working tree we want to keep, diff --git a/Documentation/git-restore.adoc b/Documentation/git-restore.adoc index 751f01b441..877b7772e6 100644 --- a/Documentation/git-restore.adoc +++ b/Documentation/git-restore.adoc @@ -51,9 +51,6 @@ leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to restore source and the restore location. See the "Interactive Mode" section of linkgit:git-add[1] to learn how to operate the `--patch` mode. -+ -Note that `--patch` can accept no pathspec and will prompt to restore -all modified paths. `-W`:: `--worktree`:: diff --git a/Documentation/git-rm.adoc b/Documentation/git-rm.adoc index 363a26934f..b5ead86796 100644 --- a/Documentation/git-rm.adoc +++ b/Documentation/git-rm.adoc @@ -7,10 +7,10 @@ git-rm - Remove files from the working tree and from the index SYNOPSIS -------- -[verse] -'git rm' [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] - [--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]] - [--] [<pathspec>...] +[synopsis] +git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] + [--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]] + [--] [<pathspec>...] DESCRIPTION ----------- @@ -30,7 +30,7 @@ sparse-checkouts are in use (see linkgit:git-sparse-checkout[1]), OPTIONS ------- -<pathspec>...:: +`<pathspec>...`:: Files to remove. A leading directory name (e.g. `dir` to remove `dir/file1` and `dir/file2`) can be given to remove all files in the directory, and recursively all sub-directories, but this @@ -43,57 +43,57 @@ directories `d` and `d2`, there is a difference between using `git rm 'd*'` and `git rm 'd/*'`, as the former will also remove all of directory `d2`. + -For more details, see the 'pathspec' entry in linkgit:gitglossary[7]. +For more details, see the _<pathspec>_ entry in linkgit:gitglossary[7]. --f:: ---force:: +`-f`:: +`--force`:: Override the up-to-date check. --n:: ---dry-run:: +`-n`:: +`--dry-run`:: Don't actually remove any file(s). Instead, just show if they exist in the index and would otherwise be removed by the command. --r:: +`-r`:: Allow recursive removal when a leading directory name is given. -\--:: +`--`:: This option can be used to separate command-line options from the list of files, (useful when filenames might be mistaken for command-line options). ---cached:: +`--cached`:: Use this option to unstage and remove paths only from the index. Working tree files, whether modified or not, will be left alone. ---ignore-unmatch:: +`--ignore-unmatch`:: Exit with a zero status even if no files matched. ---sparse:: +`--sparse`:: Allow updating index entries outside of the sparse-checkout cone. Normally, `git rm` refuses to update index entries whose paths do not fit within the sparse-checkout cone. See linkgit:git-sparse-checkout[1] for more. --q:: ---quiet:: +`-q`:: +`--quiet`:: `git rm` normally outputs one line (in the form of an `rm` command) for each file removed. This option suppresses that output. ---pathspec-from-file=<file>:: - Pathspec is passed in `<file>` instead of commandline args. If - `<file>` is exactly `-` then standard input is used. Pathspec - elements are separated by LF or CR/LF. Pathspec elements can be +`--pathspec-from-file=<file>`:: + Pathspec is passed in _<file>_ instead of 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 global `--literal-pathspecs`. ---pathspec-file-nul:: +`--pathspec-file-nul`:: Only meaningful with `--pathspec-from-file`. Pathspec elements are - separated with NUL character and all other characters are taken + separated with _NUL_ character and all other characters are taken literally (including newlines and quotes). @@ -153,15 +153,15 @@ SUBMODULES ---------- Only submodules using a gitfile (which means they were cloned with a Git version 1.7.8 or newer) will be removed from the work -tree, as their repository lives inside the .git directory of the +tree, as their repository lives inside the `.git` directory of the superproject. If a submodule (or one of those nested inside it) -still uses a .git directory, `git rm` will move the submodules +still uses a `.git` directory, `git rm` moves the submodules git directory into the superprojects git directory to protect -the submodule's history. If it exists the submodule.<name> section +the submodule's history. If it exists the `submodule.<name>` section in the linkgit:gitmodules[5] file will also be removed and that file -will be staged (unless --cached or -n are used). +will be staged (unless `--cached` or `-n` are used). -A submodule is considered up to date when the HEAD is the same as +A submodule is considered up to date when the `HEAD` is the same as recorded in the index, no tracked files are modified and no untracked files that aren't ignored are present in the submodule's work tree. Ignored files are deemed expendable and won't stop a submodule's work diff --git a/Documentation/git-send-email.adoc b/Documentation/git-send-email.adoc index 7f223db42d..7bd09c254b 100644 --- a/Documentation/git-send-email.adoc +++ b/Documentation/git-send-email.adoc @@ -21,7 +21,7 @@ Takes the patches given on the command line and emails them out. Patches can be specified as files, directories (which will send all files in the directory), or directly as a revision list. In the last case, any format accepted by linkgit:git-format-patch[1] can -be passed to git send-email, as well as options understood by +be passed to `git send-email`, as well as options understood by linkgit:git-format-patch[1]. The header of the email is configurable via command-line options. If not @@ -35,11 +35,11 @@ There are two formats accepted for patch files: This is what linkgit:git-format-patch[1] generates. Most headers and MIME formatting are ignored. -2. The original format used by Greg Kroah-Hartman's 'send_lots_of_email.pl' +2. The original format used by Greg Kroah-Hartman's `send_lots_of_email.pl` script + -This format expects the first line of the file to contain the "Cc:" value -and the "Subject:" of the message as the second line. +This format expects the first line of the file to contain the `Cc:` value +and the `Subject:` of the message as the second line. OPTIONS @@ -54,13 +54,13 @@ Composing `sendemail.multiEdit`. --bcc=<address>,...:: - Specify a "Bcc:" value for each email. Default is the value of + Specify a `Bcc:` value for each email. Default is the value of `sendemail.bcc`. + This option may be specified multiple times. --cc=<address>,...:: - Specify a starting "Cc:" value for each email. + Specify a starting `Cc:` value for each email. Default is the value of `sendemail.cc`. + This option may be specified multiple times. @@ -69,14 +69,14 @@ This option may be specified multiple times. Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1]) to edit an introductory message for the patch series. + -When `--compose` is used, git send-email will use the From, To, Cc, Bcc, -Subject, Reply-To, and In-Reply-To headers specified in the message. If -the body of the message (what you type after the headers and a blank -line) only contains blank (or Git: prefixed) lines, the summary won't be +When `--compose` is used, `git send-email` will use the `From`, `To`, `Cc`, +`Bcc`, `Subject`, `Reply-To`, and `In-Reply-To` headers specified in the +message. If the body of the message (what you type after the headers and a +blank line) only contains blank (or `Git:` prefixed) lines, the summary won't be sent, but the headers mentioned above will be used unless they are removed. + -Missing From or In-Reply-To headers will be prompted for. +Missing `From` or `In-Reply-To` headers will be prompted for. + See the CONFIGURATION section for `sendemail.multiEdit`. @@ -85,13 +85,13 @@ See the CONFIGURATION section for `sendemail.multiEdit`. the value of the `sendemail.from` configuration option is used. If neither the command-line option nor `sendemail.from` are set, then the user will be prompted for the value. The default for the prompt will be - the value of GIT_AUTHOR_IDENT, or GIT_COMMITTER_IDENT if that is not - set, as returned by "git var -l". + the value of `GIT_AUTHOR_IDENT`, or `GIT_COMMITTER_IDENT` if that is not + set, as returned by `git var -l`. --reply-to=<address>:: Specify the address where replies from recipients should go to. Use this if replies to messages should go to another address than what - is specified with the --from parameter. + is specified with the `--from` parameter. --in-reply-to=<identifier>:: Make the first mail (or all the mails with `--no-thread`) appear as a @@ -112,19 +112,32 @@ illustration below where `[PATCH v2 0/3]` is in reply to `[PATCH 0/2]`: [PATCH v2 2/3] New tests [PATCH v2 3/3] Implementation + -Only necessary if --compose is also set. If --compose +Only necessary if `--compose` is also set. If `--compose` is not set, this will be prompted for. +--[no-]outlook-id-fix:: + Microsoft Outlook SMTP servers discard the Message-ID sent via email and + assign a new random Message-ID, thus breaking threads. ++ +With `--outlook-id-fix`, `git send-email` uses a mechanism specific to +Outlook servers to learn the Message-ID the server assigned to fix the +threading. Use it only when you know that the server reports the +rewritten Message-ID the same way as Outlook servers do. ++ +Without this option specified, the fix is done by default when talking +to 'smtp.office365.com' or 'smtp-mail.outlook.com'. Use +`--no-outlook-id-fix` to disable even when talking to these two servers. + --subject=<string>:: Specify the initial subject of the email thread. - Only necessary if --compose is also set. If --compose + Only necessary if `--compose` is also set. If `--compose` is not set, this will be prompted for. --to=<address>,...:: Specify the primary recipient of the emails generated. Generally, this will be the upstream maintainer of the project involved. Default is the value of the `sendemail.to` configuration value; if that is unspecified, - and --to-cmd is not specified, this will be prompted for. + and `--to-cmd` is not specified, this will be prompted for. + This option may be specified multiple times. @@ -132,30 +145,30 @@ This option may be specified multiple times. When encountering a non-ASCII message or subject that does not declare its encoding, add headers/quoting to indicate it is encoded in <encoding>. Default is the value of the - 'sendemail.assume8bitEncoding'; if that is unspecified, this + `sendemail.assume8bitEncoding`; if that is unspecified, this will be prompted for if any non-ASCII files are encountered. + 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. - 7bit will fail upon encountering a non-ASCII message. quoted-printable + `7bit` will fail upon encountering a non-ASCII message. `quoted-printable` can be useful when the repository contains files that contain carriage - returns, but makes the raw patch email file (as saved from a MUA) much - harder to inspect manually. base64 is even more fool proof, but also - even more opaque. auto will use 8bit when possible, and quoted-printable - otherwise. + returns, but makes the raw patch email file (as saved from an MUA) much + harder to inspect manually. `base64` is even more fool proof, but also + even more opaque. `auto` will use `8bit` when possible, and + `quoted-printable` otherwise. + Default is the value of the `sendemail.transferEncoding` configuration value; if that is unspecified, default to `auto`. --xmailer:: --no-xmailer:: - Add (or prevent adding) the "X-Mailer:" header. By default, + Add (or prevent adding) the `X-Mailer:` header. By default, the header is added, but it can be turned off by setting the `sendemail.xmailer` configuration variable to `false`. @@ -165,9 +178,9 @@ Sending --envelope-sender=<address>:: Specify the envelope sender used to send the emails. This is useful if your default address is not the address that is - subscribed to a list. In order to use the 'From' address, set the - value to "auto". If you use the sendmail binary, you must have - suitable privileges for the -f parameter. Default is the value of the + subscribed to a list. In order to use the `From` address, set the + value to `auto`. If you use the `sendmail` binary, you must have + suitable privileges for the `-f` parameter. Default is the value of the `sendemail.envelopeSender` configuration variable; if that is unspecified, choosing the envelope sender is left to your MTA. @@ -176,27 +189,27 @@ Sending 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 - --smtp-server is also unspecified, git-send-email will search - for `sendmail` in `/usr/sbin`, `/usr/lib` and $PATH. + `--smtp-server` is also unspecified, `git send-email` will search + for `sendmail` in `/usr/sbin`, `/usr/lib` and `$PATH`. --smtp-encryption=<encryption>:: Specify in what way encrypting begins for the SMTP connection. - Valid values are 'ssl' and 'tls'. Any other value reverts to plain + Valid values are `ssl` and `tls`. Any other value reverts to plain (unencrypted) SMTP, which defaults to port 25. Despite the names, both values will use the same newer version of TLS, - but for historic reasons have these names. 'ssl' refers to "implicit" + but for historic reasons have these names. `ssl` refers to "implicit" encryption (sometimes called SMTPS), that uses port 465 by default. - 'tls' refers to "explicit" encryption (often known as STARTTLS), + `tls` refers to "explicit" encryption (often known as STARTTLS), that uses port 25 by default. Other ports might be used by the SMTP server, which are not the default. Commonly found alternative port for - 'tls' and unencrypted is 587. You need to check your provider's + `tls` and unencrypted is 587. You need to check your provider's documentation or your server configuration to make sure for your own case. Default is the value of `sendemail.smtpEncryption`. --smtp-domain=<FQDN>:: Specifies the Fully Qualified Domain Name (FQDN) used in the HELO/EHLO command to the SMTP server. Some servers require the - FQDN to match your IP address. If not set, git send-email attempts + FQDN to match your IP address. If not set, `git send-email` attempts to determine your FQDN automatically. Default is the value of `sendemail.smtpDomain`. @@ -210,10 +223,10 @@ $ git send-email --smtp-auth="PLAIN LOGIN GSSAPI" ... + If at least one of the specified mechanisms matches the ones advertised by the SMTP server and if it is supported by the utilized SASL library, the mechanism -is used for authentication. If neither 'sendemail.smtpAuth' nor `--smtp-auth` +is used for authentication. If neither `sendemail.smtpAuth` nor `--smtp-auth` is specified, all mechanisms supported by the SASL library can be used. The -special value 'none' maybe specified to completely disable authentication -independently of `--smtp-user` +special value `none` maybe specified to completely disable authentication +independently of `--smtp-user`. --smtp-pass[=<password>]:: Password for SMTP-AUTH. The argument is optional: If no @@ -225,16 +238,16 @@ Furthermore, passwords need not be specified in configuration files or on the command line. If a username has been specified (with `--smtp-user` or a `sendemail.smtpUser`), but no password has been specified (with `--smtp-pass` or `sendemail.smtpPass`), then -a password is obtained using 'git-credential'. +a password is obtained using linkgit:git-credential[1]. --no-smtp-auth:: - Disable SMTP authentication. Short hand for `--smtp-auth=none` + Disable SMTP authentication. Short hand for `--smtp-auth=none`. --smtp-server=<host>:: If set, specifies the outgoing SMTP server to use (e.g. `smtp.example.com` or a raw IP address). If unspecified, and if `--sendmail-cmd` is also unspecified, the default is to search - for `sendmail` in `/usr/sbin`, `/usr/lib` and $PATH if such a + for `sendmail` in `/usr/sbin`, `/usr/lib` and `$PATH` if such a program is available, falling back to `localhost` otherwise. + For backward compatibility, this option can also specify a full pathname @@ -247,7 +260,7 @@ instead. Specifies a port different from the default port (SMTP servers typically listen to smtp port 25, but may also listen to submission port 587, or the common SSL smtp port 465); - symbolic port names (e.g. "submission" instead of 587) + symbolic port names (e.g. `submission` instead of 587) are also accepted. The port can also be set with the `sendemail.smtpServerPort` configuration variable. @@ -256,17 +269,17 @@ instead. Default value can be specified by the `sendemail.smtpServerOption` configuration option. + -The --smtp-server-option option must be repeated for each option you want +The `--smtp-server-option` option must be repeated for each option you want to pass to the server. Likewise, different lines in the configuration files must be used for each option. --smtp-ssl:: - Legacy alias for '--smtp-encryption ssl'. + Legacy alias for `--smtp-encryption ssl`. --smtp-ssl-cert-path:: Path to a store of trusted CA certificates for SMTP SSL/TLS certificate validation (either a directory that has been processed - by 'c_rehash', or a single file containing one or more PEM format + by `c_rehash`, or a single file containing one or more PEM format 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 @@ -285,18 +298,18 @@ must be used for each option. connection and authentication problems. --batch-size=<num>:: - Some email servers (e.g. smtp.163.com) limit the number emails to be + Some email servers (e.g. 'smtp.163.com') limit the number of emails to be sent per session (connection) and this will lead to a failure when sending many messages. With this option, send-email will disconnect after - sending $<num> messages and wait for a few seconds (see --relogin-delay) - and reconnect, to work around such a limit. You may want to - use some form of credential helper to avoid having to retype - your password every time this happens. Defaults to the + sending _<num>_ messages and wait for a few seconds + (see `--relogin-delay`) and reconnect, to work around such a limit. + You may want to use some form of credential helper to avoid having to + retype your password every time this happens. Defaults to the `sendemail.smtpBatchSize` configuration variable. --relogin-delay=<int>:: - Waiting $<int> seconds before reconnecting to SMTP server. Used together - with --batch-size option. Defaults to the `sendemail.smtpReloginDelay` + Waiting _<int>_ seconds before reconnecting to SMTP server. Used together + with `--batch-size` option. Defaults to the `sendemail.smtpReloginDelay` configuration variable. Automating @@ -305,7 +318,7 @@ Automating --no-to:: --no-cc:: --no-bcc:: - Clears any list of "To:", "Cc:", "Bcc:" addresses previously + Clears any list of `To:`, `Cc:`, `Bcc:` addresses previously set via config. --no-identity:: @@ -314,13 +327,13 @@ Automating --to-cmd=<command>:: Specify a command to execute once per patch file which - should generate patch file specific "To:" entries. + 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 - should generate patch file specific "Cc:" entries. + should generate patch file specific `Cc:` entries. Output of this command must be single email address per line. Default is the value of `sendemail.ccCmd` configuration value. @@ -328,7 +341,7 @@ Automating Specify a command that is executed once per outgoing message and output RFC 2822 style header lines to be inserted into them. When the `sendemail.headerCmd` configuration variable is - set, its value is always used. When --header-cmd is provided + set, its value is always used. When `--header-cmd` is provided at the command line, its value takes precedence over the `sendemail.headerCmd` configuration variable. @@ -337,7 +350,7 @@ Automating --[no-]chain-reply-to:: If this is set, each email will be sent as a reply to the previous - email sent. If disabled with "--no-chain-reply-to", all emails after + email sent. If disabled with `--no-chain-reply-to`, all emails after the first will be sent as replies to the first email sent. When using this, it is recommended that the first file given be an overview of the entire patch series. Disabled by default, but the `sendemail.chainReplyTo` @@ -345,79 +358,80 @@ Automating --identity=<identity>:: A configuration identity. When given, causes values in the - 'sendemail.<identity>' subsection to take precedence over - values in the 'sendemail' section. The default identity is + `sendemail.<identity>` subsection to take precedence over + values in the `sendemail` section. The default identity is the value of `sendemail.identity`. --[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 - value; if that is unspecified, default to --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 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 + 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' - configuration value; if that is unspecified, default to --no-cc-cover. + 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 + 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' - configuration value; if that is unspecified, default to --no-to-cover. + 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>:: Specify an additional category of recipients to suppress the auto-cc of: + -- -- 'author' will avoid including the patch author. -- 'self' will avoid including the sender. -- 'cc' will avoid including anyone mentioned in Cc lines in the patch header - except for self (use 'self' for that). -- 'bodycc' will avoid including anyone mentioned in Cc lines in the - patch body (commit message) except for self (use 'self' for that). -- 'sob' will avoid including anyone mentioned in the Signed-off-by trailers except - for self (use 'self' for that). -- 'misc-by' will avoid including anyone mentioned in Acked-by, +- `author` will avoid including the patch author. +- `self` will avoid including the sender. +- `cc` will avoid including anyone mentioned in Cc lines in the patch header + except for self (use `self` for that). +- `bodycc` will avoid including anyone mentioned in Cc lines in the + patch body (commit message) except for self (use `self` for that). +- `sob` will avoid including anyone mentioned in the Signed-off-by trailers except + for self (use `self` for that). +- `misc-by` will avoid including anyone mentioned in Acked-by, Reviewed-by, Tested-by and other "-by" lines in the patch body, - except Signed-off-by (use 'sob' for that). -- 'cccmd' will avoid running the --cc-cmd. -- 'body' is equivalent to 'sob' + 'bodycc' + 'misc-by'. -- 'all' will suppress all auto cc values. + except Signed-off-by (use `sob` for that). +- `cccmd` will avoid running the --cc-cmd. +- `body` is equivalent to `sob` + `bodycc` + `misc-by`. +- `all` will suppress all auto cc values. -- + 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. +that is unspecified, default to `self` if `--suppress-from` is +specified, as well as `body` if `--no-signed-off-cc` is specified. --[no-]suppress-from:: - If this is set, do not add the From: address to the cc: list. + If this is set, do not add the `From:` address to the `Cc:` list. Default is the value of `sendemail.suppressFrom` configuration - value; if that is unspecified, default to --no-suppress-from. + value; if that is unspecified, default to `--no-suppress-from`. --[no-]thread:: - If this is set, the In-Reply-To and References headers will be + If this is set, the `In-Reply-To` and `References` headers will be added to each email sent. Whether each mail refers to the - previous email (`deep` threading per 'git format-patch' + previous email (`deep` threading per `git format-patch` wording) or to the first email (`shallow` threading) is - governed by "--[no-]chain-reply-to". + governed by `--[no-]chain-reply-to`. + -If disabled with "--no-thread", those headers will not be added -(unless specified with --in-reply-to). Default is the value of the +If disabled with `--no-thread`, those headers will not be added +(unless specified with `--in-reply-to`). Default is the value of the `sendemail.thread` configuration value; if that is unspecified, -default to --thread. +default to `--thread`. + It is up to the user to ensure that no In-Reply-To header already -exists when 'git send-email' is asked to add it (especially note that -'git format-patch' can be configured to do the threading itself). +exists when `git send-email` is asked to add it (especially note that +`git format-patch` can be configured to do the threading itself). Failure to do so may not produce the expected result in the recipient's MUA. --[no-]mailmap:: Use the mailmap file (see linkgit:gitmailmap[5]) to map all addresses to their canonical real name and email address. Additional - mailmap data specific to git-send-email may be provided using the + mailmap data specific to `git send-email` may be provided using the `sendemail.mailmap.file` or `sendemail.mailmap.blob` configuration values. Defaults to `sendemail.mailmap`. @@ -428,17 +442,17 @@ Administering Confirm just before sending: + -- -- 'always' will always confirm before sending -- 'never' will never confirm before sending -- 'cc' will confirm before sending when send-email has automatically - added addresses from the patch to the Cc list -- 'compose' will confirm before sending the first message when using --compose. -- 'auto' is equivalent to 'cc' + 'compose' +- `always` will always confirm before sending. +- `never` will never confirm before sending. +- `cc` will confirm before sending when send-email has automatically + added addresses from the patch to the Cc list. +- `compose` will confirm before sending the first message when using --compose. +- `auto` is equivalent to `cc` + `compose`. -- + Default is the value of `sendemail.confirm` configuration value; if that -is unspecified, default to 'auto' unless any of the suppress options -have been specified, in which case default to 'compose'. +is unspecified, default to `auto` unless any of the suppress options +have been specified, in which case default to `compose`. --dry-run:: Do everything except actually send the emails. @@ -447,10 +461,10 @@ have been specified, in which case default to 'compose'. When an argument may be understood either as a reference or as a file name, choose to understand it as a format-patch argument (`--format-patch`) or as a file name (`--no-format-patch`). By default, when such a conflict - occurs, git send-email will fail. + occurs, `git send-email` will fail. --quiet:: - Make git-send-email less verbose. One line per email should be + Make `git send-email` less verbose. One line per email should be all that is output. --[no-]validate:: @@ -461,7 +475,7 @@ have been specified, in which case default to 'compose'. * Invoke the sendemail-validate hook if present (see linkgit:githooks[5]). * Warn of patches that contain lines longer than 998 characters unless a suitable transfer encoding - ('auto', 'base64', or 'quoted-printable') is used; + (`auto`, `base64`, or `quoted-printable`) is used; this is due to SMTP limits as described by https://www.ietf.org/rfc/rfc5322.txt. -- @@ -480,13 +494,13 @@ 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. --translate-aliases:: Instead of the normal operation, read from standard input and interpret each line as an email alias. Translate it according to the configured alias file(s). Output each translated name and email - address to standard output, one per line. See 'sendemail.aliasFile' + address to standard output, one per line. See `sendemail.aliasFile` for more information about aliases. CONFIGURATION @@ -496,12 +510,12 @@ include::includes/cmd-config-section-all.adoc[] include::config/sendemail.adoc[] -EXAMPLES --------- -Use gmail as the smtp server +EXAMPLES OF SMTP SERVERS +------------------------ +Use Gmail as the SMTP Server ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To use 'git send-email' to send your patches through the GMail SMTP server, -edit ~/.gitconfig to specify your account settings: +To use `git send-email` to send your patches through the Gmail SMTP server, +edit `~/.gitconfig` to specify your account settings: ---- [sendemail] @@ -511,10 +525,52 @@ edit ~/.gitconfig to specify your account settings: smtpServerPort = 587 ---- +Gmail does not allow using your regular password for `git send-email`. If you have multi-factor authentication set up on your Gmail account, you can -generate an app-specific password for use with 'git send-email'. Visit +generate an app-specific password for use with `git send-email`. Visit https://security.google.com/settings/security/apppasswords to create it. +Alternatively, instead of using an app-specific password, you can use +OAuth2.0 authentication with Gmail. OAuth2.0 is more secure than +app-specific passwords, and works regardless of whether you have multi-factor +authentication set up. `OAUTHBEARER` and `XOAUTH2` are common mechanisms used +for this type of authentication. Gmail supports both of them. As an example, +if you want to use `OAUTHBEARER`, edit your `~/.gitconfig` file and add +`smtpAuth = OAUTHBEARER` to your account settings: + +---- +[sendemail] + smtpEncryption = tls + smtpServer = smtp.gmail.com + smtpUser = yourname@gmail.com + smtpServerPort = 587 + smtpAuth = OAUTHBEARER +---- + +Another alternative is using a tool developed by Google known as +https://github.com/google/gmail-oauth2-tools/tree/master/go/sendgmail[sendgmail] +to send emails using `git send-email`. + +Use Microsoft Outlook as the SMTP Server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Unlike Gmail, Microsoft Outlook no longer supports app-specific passwords. +Therefore, OAuth2.0 authentication must be used for Outlook. Also, it only +supports `XOAUTH2` authentication mechanism. + +Edit `~/.gitconfig` to specify your account settings for Outlook and use its +SMTP server with `git send-email`: + +---- +[sendemail] + smtpEncryption = tls + smtpServer = smtp.office365.com + smtpUser = yourname@outlook.com + smtpServerPort = 587 + smtpAuth = XOAUTH2 +---- + +SENDING PATCHES +--------------- Once your commits are ready to be sent to the mailing list, run the following commands: @@ -523,15 +579,40 @@ following commands: $ git send-email outgoing/* The first time you run it, you will be prompted for your credentials. Enter the -app-specific or your regular password as appropriate. If you have credential -helper configured (see linkgit:git-credential[1]), the password will be saved in -the credential store so you won't have to type it the next time. +app-specific or your regular password as appropriate. + +If you have a credential helper configured (see linkgit:git-credential[1]), the +password will be saved in the credential store so you won't have to type it the +next time. + +If you are using OAuth2.0 authentication, you need to use an access token in +place of a password when prompted. Various OAuth2.0 token generators are +available online. Community maintained credential helpers are also available: + + - https://github.com/AdityaGarg8/git-credential-email[git-credential-gmail] + (cross platform, dedicated helper for authenticating Gmail accounts) + + - https://github.com/AdityaGarg8/git-credential-email[git-credential-outlook] + (cross platform, dedicated helper for authenticating Microsoft Outlook accounts) + + - https://github.com/AdityaGarg8/git-credential-email[git-credential-yahoo] + (cross platform, dedicated helper for authenticating Yahoo accounts) + +You can also see linkgit:gitcredentials[7] for more OAuth based authentication +helpers. Note: the following core Perl modules that may be installed with your distribution of Perl are required: -MIME::Base64, MIME::QuotedPrint, Net::Domain and Net::SMTP. + +https://metacpan.org/pod/MIME::Base64[MIME::Base64], +https://metacpan.org/pod/MIME::QuotedPrint[MIME::QuotedPrint], +https://metacpan.org/pod/Net::Domain[Net::Domain] and +https://metacpan.org/pod/Net::SMTP[Net::SMTP]. + These additional Perl modules are also required: -Authen::SASL and Mail::Address. + +https://metacpan.org/pod/Authen::SASL[Authen::SASL] and +https://metacpan.org/pod/Mail::Address[Mail::Address]. SEE ALSO diff --git a/Documentation/git-stripspace.adoc b/Documentation/git-stripspace.adoc index a293327581..37287f211f 100644 --- a/Documentation/git-stripspace.adoc +++ b/Documentation/git-stripspace.adoc @@ -37,7 +37,8 @@ OPTIONS ------- -s:: --strip-comments:: - Skip and remove all lines starting with a comment character (default '#'). + Skip and remove all lines starting with a comment character + (`core.commentChar`, default `#`). -c:: --comment-lines:: diff --git a/Documentation/git-switch.adoc b/Documentation/git-switch.adoc index f55315c51e..9f62abf9e2 100644 --- a/Documentation/git-switch.adoc +++ b/Documentation/git-switch.adoc @@ -7,11 +7,11 @@ git-switch - Switch branches SYNOPSIS -------- -[verse] -'git switch' [<options>] [--no-guess] <branch> -'git switch' [<options>] --detach [<start-point>] -'git switch' [<options>] (-c|-C) <new-branch> [<start-point>] -'git switch' [<options>] --orphan <new-branch> +[synopsis] +git switch [<options>] [--no-guess] <branch> +git switch [<options>] --detach [<start-point>] +git switch [<options>] (-c|-C) <new-branch> [<start-point>] +git switch [<options>] --orphan <new-branch> DESCRIPTION ----------- @@ -33,33 +33,33 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. OPTIONS ------- -<branch>:: +_<branch>_:: Branch to switch to. -<new-branch>:: +_<new-branch>_:: Name for the new branch. -<start-point>:: +_<start-point>_:: The starting point for the new branch. Specifying a - `<start-point>` allows you to create a branch based on some - other point in history than where HEAD currently points. (Or, + _<start-point>_ allows you to create a branch based on some + other point in history than where `HEAD` currently points. (Or, in the case of `--detach`, allows you to inspect and detach from some other point.) + -You can use the `@{-N}` syntax to refer to the N-th last -branch/commit switched to using "git switch" or "git checkout" +You can use the `@{-<N>}` syntax to refer to the _<N>_-th last +branch/commit switched to using `git switch` or `git checkout` operation. You may also specify `-` which is synonymous to `@{-1}`. This is often used to switch quickly between two branches, or to undo a branch switch by mistake. + -As a special case, you may use `A...B` as a shortcut for the merge -base of `A` and `B` if there is exactly one merge base. You can leave -out at most one of `A` and `B`, in which case it defaults to `HEAD`. - --c <new-branch>:: ---create <new-branch>:: - Create a new branch named `<new-branch>` starting at - `<start-point>` before switching to the branch. This is the +As a special case, you may use `<rev-a>...<rev-b>` as a shortcut for the merge +base of _<rev-a>_ and _<rev-b>_ if there is exactly one merge base. You can leave +out at most one of _<rev-a>_ and _<rev-b>_, in which case it defaults to `HEAD`. + +`-c <new-branch>`:: +`--create <new-branch>`:: + Create a new branch named _<new-branch>_ starting at + _<start-point>_ before switching to the branch. This is the transactional equivalent of + ------------ @@ -67,32 +67,32 @@ $ git branch <new-branch> $ git switch <new-branch> ------------ + -that is to say, the branch is not reset/created unless "git switch" is +that is to say, the branch is not reset/created unless `git switch` is successful (e.g., when the branch is in use in another worktree, not just the current branch stays the same, but the branch is not reset to the start-point, either). --C <new-branch>:: ---force-create <new-branch>:: - Similar to `--create` except that if `<new-branch>` already - exists, it will be reset to `<start-point>`. This is a +`-C <new-branch>`:: +`--force-create <new-branch>`:: + Similar to `--create` except that if _<new-branch>_ already + exists, it will be reset to _<start-point>_. This is a convenient shortcut for: + ------------ -$ git branch -f <new-branch> -$ git switch <new-branch> +$ git branch -f _<new-branch>_ +$ git switch _<new-branch>_ ------------ --d:: ---detach:: +`-d`:: +`--detach`:: Switch to a commit for inspection and discardable experiments. See the "DETACHED HEAD" section in linkgit:git-checkout[1] for details. ---guess:: ---no-guess:: - If `<branch>` is not found but there does exist a tracking - branch in exactly one remote (call it `<remote>`) with a +`--guess`:: +`--no-guess`:: + If _<branch>_ is not found but there does exist a tracking + branch in exactly one remote (call it _<remote>_) with a matching name, treat as equivalent to + ------------ @@ -101,9 +101,9 @@ $ git switch -c <branch> --track <remote>/<branch> + If the branch exists in multiple remotes and one of them is named by the `checkout.defaultRemote` configuration variable, we'll use that -one for the purposes of disambiguation, even if the `<branch>` isn't +one for the purposes of disambiguation, even if the _<branch>_ isn't unique across all remotes. Set it to e.g. `checkout.defaultRemote=origin` -to always checkout remote branches from there if `<branch>` is +to always checkout remote branches from there if _<branch>_ is ambiguous but exists on the 'origin' remote. See also `checkout.defaultRemote` in linkgit:git-config[1]. + @@ -112,19 +112,19 @@ ambiguous but exists on the 'origin' remote. See also The default behavior can be set via the `checkout.guess` configuration variable. --f:: ---force:: +`-f`:: +`--force`:: An alias for `--discard-changes`. ---discard-changes:: +`--discard-changes`:: Proceed even if the index or the working tree differs from `HEAD`. Both the index and working tree are restored to match the switching target. If `--recurse-submodules` is specified, submodule content is also restored to match the switching target. This is used to throw away local changes. --m:: ---merge:: +`-m`:: +`--merge`:: If you have local modifications to one or more files that are different between the current branch and the branch to which you are switching, the command refuses to switch branches in @@ -138,25 +138,25 @@ paths are left unmerged, and you need to resolve the conflicts and mark the resolved paths with `git add` (or `git rm` if the merge should result in deletion of the path). ---conflict=<style>:: +`--conflict=<style>`:: The same as `--merge` option above, but changes the way the conflicting hunks are presented, overriding the `merge.conflictStyle` configuration variable. Possible values are - "merge" (default), "diff3", and "zdiff3". + `merge` (default), `diff3`, and `zdiff3`. --q:: ---quiet:: +`-q`:: +`--quiet`:: Quiet, suppress feedback messages. ---progress:: ---no-progress:: +`--progress`:: +`--no-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 enables progress reporting even if not attached to a terminal, regardless of `--quiet`. --t:: ---track [direct|inherit]:: +`-t`:: +`--track[ (direct|inherit)]`:: When creating a new branch, set up "upstream" configuration. `-c` is implied. See `--track` in linkgit:git-branch[1] for details. @@ -171,22 +171,22 @@ given name has no slash, or the above guessing results in an empty name, the guessing is aborted. You can explicitly give a name with `-c` in such a case. ---no-track:: +`--no-track`:: Do not set up "upstream" configuration, even if the `branch.autoSetupMerge` configuration variable is true. ---orphan <new-branch>:: - Create a new unborn branch, named `<new-branch>`. All +`--orphan <new-branch>`:: + Create a new unborn branch, named _<new-branch>_. All tracked files are removed. ---ignore-other-worktrees:: +`--ignore-other-worktrees`:: `git switch` refuses when the wanted ref is already checked out by another worktree. This option makes it check the ref out anyway. In other words, the ref can be held by more than one worktree. ---recurse-submodules:: ---no-recurse-submodules:: +`--recurse-submodules`:: +`--no-recurse-submodules`:: Using `--recurse-submodules` will update the content of all active submodules according to the commit recorded in the superproject. If nothing (or `--no-recurse-submodules`) is @@ -239,7 +239,7 @@ $ git switch - ------------ You can grow a new branch from any commit. For example, switch to -"HEAD~3" and create branch "fixup": +"`HEAD~3`" and create branch "`fixup`": ------------ $ git switch -c fixup HEAD~3 @@ -251,8 +251,8 @@ name: ------------ $ git switch new-topic -Branch 'new-topic' set up to track remote branch 'new-topic' from 'origin' -Switched to a new branch 'new-topic' +Branch `new-topic` set up to track remote branch `new-topic` from `origin` +Switched to a new branch `new-topic` ------------ To check out commit `HEAD~3` for temporary inspection or experiment diff --git a/Documentation/git-update-ref.adoc b/Documentation/git-update-ref.adoc index 9e6935d38d..9310ce9768 100644 --- a/Documentation/git-update-ref.adoc +++ b/Documentation/git-update-ref.adoc @@ -7,8 +7,10 @@ git-update-ref - Update the object name stored in a ref safely SYNOPSIS -------- -[verse] -'git update-ref' [-m <reason>] [--no-deref] (-d <ref> [<old-oid>] | [--create-reflog] <ref> <new-oid> [<old-oid>] | --stdin [-z]) +[synopsis] +git update-ref [-m <reason>] [--no-deref] -d <ref> [<old-oid>] +git update-ref [-m <reason>] [--no-deref] [--create-reflog] <ref> <new-oid> [<old-oid>] +git update-ref [-m <reason>] [--no-deref] --stdin [-z] [--batch-updates] DESCRIPTION ----------- @@ -57,6 +59,14 @@ performs all modifications together. Specify commands of the form: With `--create-reflog`, update-ref will create a reflog for each ref even if one would not ordinarily be created. +With `--batch-updates`, update-ref executes the updates in a batch but allows +individual updates to fail due to invalid or incorrect user input, applying only +the successful updates. However, system-related errors—such as I/O failures or +memory issues—will result in a full failure of all batched updates. Any failed +updates will be reported in the following format: + + rejected SP (<old-oid> | <old-target>) SP (<new-oid> | <new-target>) SP <rejection-reason> LF + Quote fields containing whitespace as if they were strings in C source code; i.e., surrounded by double-quotes and with backslash escapes. Use 40 "0" characters or the empty string to specify a zero value. To diff --git a/Documentation/git-var.adoc b/Documentation/git-var.adoc index 0680568dfd..b606c2d649 100644 --- a/Documentation/git-var.adoc +++ b/Documentation/git-var.adoc @@ -8,8 +8,8 @@ git-var - Show a Git logical variable SYNOPSIS -------- -[verse] -'git var' (-l | <variable>) +[synopsis] +git var (-l | <variable>) DESCRIPTION ----------- @@ -18,7 +18,7 @@ no value. OPTIONS ------- --l:: +`-l`:: Display the logical variables. In addition, all the variables of the Git configuration file .git/config are listed as well. (However, the configuration variables listing functionality @@ -32,58 +32,56 @@ EXAMPLES VARIABLES --------- -GIT_AUTHOR_IDENT:: +`GIT_AUTHOR_IDENT`:: The author of a piece of code. -GIT_COMMITTER_IDENT:: +`GIT_COMMITTER_IDENT`:: The person who put a piece of code into Git. -GIT_EDITOR:: +`GIT_EDITOR`:: Text editor for use by Git commands. The value is meant to be interpreted by the shell when it is used. Examples: `~/bin/vi`, `$SOME_ENVIRONMENT_VARIABLE`, `"C:\Program Files\Vim\gvim.exe" - --nofork`. The order of preference is the `$GIT_EDITOR` - environment variable, then `core.editor` configuration, then - `$VISUAL`, then `$EDITOR`, and then the default chosen at compile + --nofork`. The order of preference is `$GIT_EDITOR`, then + `core.editor` configuration value, then `$VISUAL`, then + `$EDITOR`, and then the default chosen at compile time, which is usually 'vi'. ifdef::git-default-editor[] The build you are using chose '{git-default-editor}' as the default. endif::git-default-editor[] -GIT_SEQUENCE_EDITOR:: +`GIT_SEQUENCE_EDITOR`:: Text editor used to edit the 'todo' file while running `git rebase -i`. Like `GIT_EDITOR`, the value is meant to be interpreted by - the shell when it is used. The order of preference is the - `$GIT_SEQUENCE_EDITOR` environment variable, then - `sequence.editor` configuration, and then the value of `git var - GIT_EDITOR`. + the shell when it is used. The order of preference is + `$GIT_SEQUENCE_EDITOR`, then `sequence.editor` configuration value, + and then the value of `git var GIT_EDITOR`. -GIT_PAGER:: +`GIT_PAGER`:: Text viewer for use by Git commands (e.g., 'less'). The value is meant to be interpreted by the shell. The order of preference - is the `$GIT_PAGER` environment variable, then `core.pager` - configuration, then `$PAGER`, and then the default chosen at - compile time (usually 'less'). + is `$GIT_PAGER`, then the value of `core.pager` configuration, then + `$PAGER`, and then the default chosen at compile time (usually `less`). ifdef::git-default-pager[] The build you are using chose '{git-default-pager}' as the default. endif::git-default-pager[] -GIT_DEFAULT_BRANCH:: +`GIT_DEFAULT_BRANCH`:: The name of the first branch created in newly initialized repositories. -GIT_SHELL_PATH:: +`GIT_SHELL_PATH`:: The path of the binary providing the POSIX shell for commands which use the shell. -GIT_ATTR_SYSTEM:: +`GIT_ATTR_SYSTEM`:: The path to the system linkgit:gitattributes[5] file, if one is enabled. -GIT_ATTR_GLOBAL:: +`GIT_ATTR_GLOBAL`:: The path to the global (per-user) linkgit:gitattributes[5] file. -GIT_CONFIG_SYSTEM:: +`GIT_CONFIG_SYSTEM`:: The path to the system configuration file, if one is enabled. -GIT_CONFIG_GLOBAL:: +`GIT_CONFIG_GLOBAL`:: The path to the global (per-user) configuration files, if any. Most path values contain only one value. However, some can contain multiple diff --git a/Documentation/git-verify-commit.adoc b/Documentation/git-verify-commit.adoc index aee4c40eac..ff5b8b97ef 100644 --- a/Documentation/git-verify-commit.adoc +++ b/Documentation/git-verify-commit.adoc @@ -7,26 +7,24 @@ git-verify-commit - Check the GPG signature of commits SYNOPSIS -------- -[verse] -'git verify-commit' [-v | --verbose] [--raw] <commit>... +[synopsis] +git verify-commit [-v | --verbose] [--raw] <commit>... DESCRIPTION ----------- -Validates the GPG signature created by 'git commit -S'. +Validates the GPG signature created by `git commit -S` +on the commit objects given on the command line. OPTIONS ------- ---raw:: +`--raw`:: Print the raw gpg status output to standard error instead of the normal human-readable output. --v:: ---verbose:: +`-v`:: +`--verbose`:: Print the contents of the commit object before validating it. -<commit>...:: - SHA-1 identifiers of Git commit objects. - GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-verify-pack.adoc b/Documentation/git-verify-pack.adoc index d7e886918a..b0462d8db3 100644 --- a/Documentation/git-verify-pack.adoc +++ b/Documentation/git-verify-pack.adoc @@ -8,43 +8,39 @@ git-verify-pack - Validate packed Git archive files SYNOPSIS -------- -[verse] -'git verify-pack' [-v | --verbose] [-s | --stat-only] [--] <pack>.idx... +[synopsis] +git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx... DESCRIPTION ----------- -Reads given idx file for packed Git archive created with the -'git pack-objects' command and verifies the idx file and the -corresponding pack file. +Read each idx file for packed Git archive given on the command line, +and verify the idx file and the corresponding pack file. OPTIONS ------- -<pack>.idx ...:: - The idx files to verify. - --v:: ---verbose:: +`-v`:: +`--verbose`:: After verifying the pack, show the list of objects contained in the pack and a histogram of delta chain length. --s:: ---stat-only:: +`-s`:: +`--stat-only`:: Do not verify the pack contents; only show the histogram of delta chain length. With `--verbose`, the list of objects is also shown. -\--:: +`--`:: Do not interpret any more arguments as options. OUTPUT FORMAT ------------- -When specifying the -v option the format used is: +When specifying the `-v` option the format used is: - SHA-1 type size size-in-packfile offset-in-packfile + object-name type size size-in-packfile offset-in-packfile for objects that are not deltified in the pack, and - SHA-1 type size size-in-packfile offset-in-packfile depth base-SHA-1 + object-name type size size-in-packfile offset-in-packfile depth base-object-name for objects that are deltified. diff --git a/Documentation/git-verify-tag.adoc b/Documentation/git-verify-tag.adoc index 81d50ecc4c..b3721a86f4 100644 --- a/Documentation/git-verify-tag.adoc +++ b/Documentation/git-verify-tag.adoc @@ -7,26 +7,24 @@ git-verify-tag - Check the GPG signature of tags SYNOPSIS -------- -[verse] -'git verify-tag' [-v | --verbose] [--format=<format>] [--raw] <tag>... +[synopsis] +git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>... DESCRIPTION ----------- -Validates the gpg signature created by 'git tag'. +Validates the gpg signature created by `git tag` in the tag +objects listed on the command line. OPTIONS ------- ---raw:: +`--raw`:: Print the raw gpg status output to standard error instead of the normal human-readable output. --v:: ---verbose:: +`-v`:: +`--verbose`:: Print the contents of the tag object before validating it. -<tag>...:: - SHA-1 identifiers of Git tag objects. - GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-version.adoc b/Documentation/git-version.adoc index 80fa7754a6..9462043a14 100644 --- a/Documentation/git-version.adoc +++ b/Documentation/git-version.adoc @@ -22,6 +22,14 @@ OPTIONS --build-options:: Include additional information about how git was built for diagnostic purposes. ++ +The libraries used to implement the SHA-1 and SHA-256 algorithms are displayed +in the form `SHA-1: <option>` and `SHA-256: <option>`. Note that the SHA-1 +options `SHA1_APPLE`, `SHA1_OPENSSL`, and `SHA1_BLK` do not use a collision +detection algorithm and thus may be vulnerable to known SHA-1 collision +attacks. When a faster SHA-1 implementation without collision detection is used +for only non-cryptographic purposes, the algorithm is displayed in the form +`non-collision-detecting-SHA-1: <option>`. GIT --- diff --git a/Documentation/git-write-tree.adoc b/Documentation/git-write-tree.adoc index f22041a9dc..4c7100ea1e 100644 --- a/Documentation/git-write-tree.adoc +++ b/Documentation/git-write-tree.adoc @@ -8,8 +8,8 @@ git-write-tree - Create a tree object from the current index SYNOPSIS -------- -[verse] -'git write-tree' [--missing-ok] [--prefix=<prefix>/] +[synopsis] +git write-tree [--missing-ok] [--prefix=<prefix>/] DESCRIPTION ----------- @@ -18,23 +18,23 @@ tree object is printed to standard output. The index must be in a fully merged state. -Conceptually, 'git write-tree' sync()s the current index contents +Conceptually, `git write-tree` sync()s the current index contents into a set of tree files. In order to have that match what is actually in your directory right -now, you need to have done a 'git update-index' phase before you did the -'git write-tree'. +now, you need to have done a `git update-index` phase before you did the +`git write-tree`. OPTIONS ------- ---missing-ok:: - Normally 'git write-tree' ensures that the objects referenced by the +`--missing-ok`:: + Normally `git write-tree` ensures that the objects referenced by the directory exist in the object database. This option disables this check. ---prefix=<prefix>/:: +`--prefix=<prefix>/`:: Writes a tree object that represents a subdirectory - `<prefix>`. This can be used to write the tree object + _<prefix>_. This can be used to write the tree object for a subproject that is in the named subdirectory. GIT diff --git a/Documentation/gitattributes.adoc b/Documentation/gitattributes.adoc index a22d1ef1e1..f20041a323 100644 --- a/Documentation/gitattributes.adoc +++ b/Documentation/gitattributes.adoc @@ -531,13 +531,14 @@ must not send any response before it received the content and the final flush packet. Also note that the "value" of a "key=value" pair can contain the "=" character whereas the key would never contain that character. ------------------------- + +----------------------- packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> 0000 packet: git> CONTENT packet: git> 0000 ------------------------- +----------------------- The filter is expected to respond with a list of "key=value" pairs terminated with a flush packet. If the filter does not experience @@ -559,6 +560,7 @@ packet: git< 0000 # empty list, keep "status=success" unchanged! If the result content is empty then the filter is expected to respond with a "success" status and a flush packet to signal the empty content. + ------------------------ packet: git< status=success packet: git< 0000 @@ -568,14 +570,16 @@ packet: git< 0000 # empty list, keep "status=success" unchanged! In case the filter cannot or does not want to process the content, it is expected to respond with an "error" status. ------------------------- + +----------------------- packet: git< status=error packet: git< 0000 ------------------------- +----------------------- If the filter experiences an error during processing, then it can send the status "error" after the content was (partially or completely) sent. + ------------------------ packet: git< status=success packet: git< 0000 @@ -589,10 +593,11 @@ In case the filter cannot or does not want to process the content as well as any future content for the lifetime of the Git process, then it is expected to respond with an "abort" status at any point in the protocol. ------------------------- + +----------------------- packet: git< status=abort packet: git< 0000 ------------------------- +----------------------- Git neither stops nor restarts the filter process in case the "error"/"abort" status is set. However, Git sets its exit code @@ -613,7 +618,8 @@ flag "can-delay" after the filter command and pathname. This flag denotes that the filter can delay filtering the current blob (e.g. to compensate network latencies) by responding with no content but with the status "delayed" and a flush packet. ------------------------- + +----------------------- packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> can-delay=1 @@ -622,7 +628,7 @@ packet: git> CONTENT packet: git> 0000 packet: git< status=delayed packet: git< 0000 ------------------------- +----------------------- If the filter supports the "delay" capability then it must support the "list_available_blobs" command. If Git sends this command, then the @@ -647,10 +653,12 @@ packet: git< status=success packet: git< 0000 ------------------------ + After Git received the pathnames, it will request the corresponding blobs again. These requests contain a pathname and an empty content section. The filter is expected to respond with the smudged content in the usual way as explained above. + ------------------------ packet: git> command=smudge packet: git> pathname=path/testfile.dat diff --git a/Documentation/gitcli.adoc b/Documentation/gitcli.adoc index 04193ec907..1ea681b59d 100644 --- a/Documentation/gitcli.adoc +++ b/Documentation/gitcli.adoc @@ -209,13 +209,13 @@ $ git foo -o Arg However, this is *NOT* allowed for switches with an optional value, where the 'stuck' form must be used: + ---------------------------- $ git describe --abbrev HEAD # correct $ git describe --abbrev=10 HEAD # correct $ git describe --abbrev 10 HEAD # NOT WHAT YOU MEANT ---------------------------- - NOTES ON FREQUENTLY CONFUSED OPTIONS ------------------------------------ diff --git a/Documentation/gitprotocol-common.adoc b/Documentation/gitprotocol-common.adoc index cdc9d6e707..b4a5316ca4 100644 --- a/Documentation/gitprotocol-common.adoc +++ b/Documentation/gitprotocol-common.adoc @@ -21,11 +21,13 @@ ABNF Notation ABNF notation as described by RFC 5234 is used within the protocol documents, except the following replacement core rules are used: + ---- HEXDIG = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ---- We also define the following common rules: + ---- NUL = %x00 zero-id = 40*"0" diff --git a/Documentation/gitprotocol-v2.adoc b/Documentation/gitprotocol-v2.adoc index 5598c93e67..9a57005d77 100644 --- a/Documentation/gitprotocol-v2.adoc +++ b/Documentation/gitprotocol-v2.adoc @@ -54,7 +54,7 @@ In general a client can request to speak protocol v2 by sending `version=2` through the respective side-channel for the transport being used which inevitably sets `GIT_PROTOCOL`. More information can be found in linkgit:gitprotocol-pack[5] and linkgit:gitprotocol-http[5], as well as the -`GIT_PROTOCOL` definition in `git.txt`. In all cases the +`GIT_PROTOCOL` definition in linkgit:git[1]. In all cases the response from the server is the capability advertisement. Git Transport @@ -99,7 +99,7 @@ Uses the `--http-backend-info-refs` option to linkgit:git-upload-pack[1]. The server may need to be configured to pass this header's contents via -the `GIT_PROTOCOL` variable. See the discussion in `git-http-backend.txt`. +the `GIT_PROTOCOL` variable. See the discussion in linkgit:git-http-backend[1]. Capability Advertisement ------------------------ diff --git a/Documentation/gitweb.adoc b/Documentation/gitweb.adoc index 5e2b491ec2..4261f9e235 100644 --- a/Documentation/gitweb.adoc +++ b/Documentation/gitweb.adoc @@ -103,6 +103,7 @@ You can generate the projects list index file using the project_index action "Generating projects list using gitweb" section below. Example contents: + ----------------------------------------------------------------------- foo.git Joe+R+Hacker+<joe@example.com> foo/bar.git O+W+Ner+<owner@example.org> @@ -124,6 +125,7 @@ Generating projects list using gitweb We assume that GITWEB_CONFIG has its default Makefile value, namely 'gitweb_config.perl'. Put the following in 'gitweb_make_index.perl' file: + ---------------------------------------------------------------------------- read_config_file("gitweb_config.perl"); $projects_list = $projectroot; @@ -518,12 +520,14 @@ rules. If you use the rewrite rules from the example you *might* also need something like the following in your gitweb configuration file (`/etc/gitweb.conf` following example): + ---------------------------------------------------------------------------- @stylesheets = ("/some/absolute/path/gitweb.css"); $my_uri = "/"; $home_link = "/"; $per_request_config = 1; ---------------------------------------------------------------------------- + Nowadays though gitweb should create HTML base tag when needed (to set base URI for relative links), so it should work automatically. @@ -535,6 +539,7 @@ Apache virtual host and gitweb configuration files in the following way. The virtual host configuration (in Apache configuration file) should look like this: + -------------------------------------------------------------------------- <VirtualHost *:80> ServerName git.example.org @@ -575,9 +580,11 @@ like this: Here actual project root is passed to gitweb via `GITWEB_PROJECT_ROOT` environment variable from a web server, so you need to put the following line in gitweb configuration file (`/etc/gitweb.conf` in above example): + -------------------------------------------------------------------------- $projectroot = $ENV{'GITWEB_PROJECTROOT'} || "/pub/git"; -------------------------------------------------------------------------- + *Note* that this requires to be set for each request, so either `$per_request_config` must be false, or the above must be put in code referenced by `$per_request_config`; @@ -604,9 +611,11 @@ the third and the fourth. PATH_INFO usage ~~~~~~~~~~~~~~~ If you enable PATH_INFO usage in gitweb by putting + ---------------------------------------------------------------------------- $feature{'pathinfo'}{'default'} = [1]; ---------------------------------------------------------------------------- + in your gitweb configuration file, it is possible to set up your server so that it consumes and produces URLs in the form @@ -636,6 +645,7 @@ complementary static files (stylesheet, favicon, JavaScript): </Directory> </VirtualHost> ---------------------------------------------------------------------------- + The rewrite rule guarantees that existing static files will be properly served, whereas any other URL will be passed to gitweb as PATH_INFO parameter. @@ -647,6 +657,7 @@ for fetching" section). A possible workaround for the latter is the following: in your project root dir (e.g. `/pub/git`) have the projects named *without* a .git extension (e.g. `/pub/git/project` instead of `/pub/git/project.git`) and configure Apache as follows: + ---------------------------------------------------------------------------- <VirtualHost *:80> ServerAlias git.example.com diff --git a/Documentation/gitweb.conf.adoc b/Documentation/gitweb.conf.adoc index 85983587fc..1348e9b125 100644 --- a/Documentation/gitweb.conf.adoc +++ b/Documentation/gitweb.conf.adoc @@ -603,6 +603,7 @@ Many gitweb features can be enabled (or disabled) and configured using the Each `%feature` hash element is a hash reference and has the following structure: + ---------------------------------------------------------------------- "<feature-name>" => { "sub" => <feature-sub-(subroutine)>, @@ -613,6 +614,7 @@ structure: Some features cannot be overridden per project. For those features the structure of appropriate `%feature` hash element has a simpler form: + ---------------------------------------------------------------------- "<feature-name>" => { "override" => 0, diff --git a/Documentation/howto/recover-corrupted-object-harder.adoc b/Documentation/howto/recover-corrupted-object-harder.adoc index 5efb4fe81f..86a1ba75cf 100644 --- a/Documentation/howto/recover-corrupted-object-harder.adoc +++ b/Documentation/howto/recover-corrupted-object-harder.adoc @@ -125,7 +125,7 @@ static int try_zlib(unsigned char *buf, int len) { /* make this absurdly large so we don't have to loop */ static unsigned char out[1024*1024]; - z_stream z; + struct z_stream_s z; int ret; memset(&z, 0, sizeof(z)); @@ -278,7 +278,7 @@ int main(int argc, char **argv) static unsigned char buf[25 * 1024 * 1024]; static unsigned char out[25 * 1024 * 1024]; int len; - z_stream z; + struct z_stream_s z; int ret; len = read(0, buf, sizeof(buf)); diff --git a/Documentation/merge-options.adoc b/Documentation/merge-options.adoc index 0022185201..078f4f6157 100644 --- a/Documentation/merge-options.adoc +++ b/Documentation/merge-options.adoc @@ -1,23 +1,23 @@ ---commit:: ---no-commit:: +`--commit`:: +`--no-commit`:: Perform the merge and commit the result. This option can - be used to override --no-commit. + be used to override `--no-commit`. ifdef::git-pull[] Only useful when merging. endif::git-pull[] + -With --no-commit perform the merge and stop just before creating +With `--no-commit` perform the merge and stop just before creating a merge commit, to give the user a chance to inspect and further tweak the merge result before committing. + Note that fast-forward updates do not create a merge commit and -therefore there is no way to stop those merges with --no-commit. +therefore there is no way to stop those merges with `--no-commit`. Thus, if you want to ensure your branch is not changed or updated -by the merge command, use --no-ff with --no-commit. +by the merge command, use `--no-ff` with `--no-commit`. ---edit:: --e:: ---no-edit:: +`--edit`:: +`-e`:: +`--no-edit`:: Invoke an editor before committing successful mechanical merge to further edit the auto-generated merge message, so that the user can explain and justify the merge. The `--no-edit` option can be @@ -35,17 +35,17 @@ they run `git merge`. To make it easier to adjust such scripts to the updated behaviour, the environment variable `GIT_MERGE_AUTOEDIT` can be set to `no` at the beginning of them. ---cleanup=<mode>:: +`--cleanup=<mode>`:: This option determines how the merge message will be cleaned up before committing. See linkgit:git-commit[1] for more details. In addition, if - the '<mode>' is given a value of `scissors`, scissors will be appended + the _<mode>_ is given a value of `scissors`, scissors will be appended to `MERGE_MSG` before being passed on to the commit machinery in the case of a merge conflict. ifdef::git-merge[] ---ff:: ---no-ff:: ---ff-only:: +`--ff`:: +`--no-ff`:: +`--ff-only`:: Specifies how a merge is handled when the merged-in history is already a descendant of the current history. `--ff` is the default unless merging an annotated (and possibly signed) tag @@ -53,13 +53,13 @@ ifdef::git-merge[] hierarchy, in which case `--no-ff` is assumed. endif::git-merge[] ifdef::git-pull[] ---ff-only:: +`--ff-only`:: Only update to the new history if there is no divergent local history. This is the default when no method for reconciling divergent histories is provided (via the --rebase=* flags). ---ff:: ---no-ff:: +`--ff`:: +`--no-ff`:: When merging rather than rebasing, specifies how a merge is handled when the merged-in history is already a descendant of the current history. If merging is requested, `--ff` is the @@ -81,40 +81,40 @@ With `--ff-only`, resolve the merge as a fast-forward when possible. When not possible, refuse to merge and exit with a non-zero status. endif::git-merge[] --S[<keyid>]:: ---gpg-sign[=<keyid>]:: ---no-gpg-sign:: - GPG-sign the resulting merge commit. The `keyid` argument is +`-S[<key-id>]`:: +`--gpg-sign[=<key-id>]`:: +`--no-gpg-sign`:: + GPG-sign the resulting merge commit. The _<key-id>_ argument is optional and defaults to the committer identity; if specified, it must be stuck to the option without a space. `--no-gpg-sign` is useful to countermand both `commit.gpgSign` configuration variable, and earlier `--gpg-sign`. ---log[=<n>]:: ---no-log:: +`--log[=<n>]`:: +`--no-log`:: In addition to branch names, populate the log message with - one-line descriptions from at most <n> actual commits that are being + one-line descriptions from at most _<n>_ actual commits that are being merged. See also linkgit:git-fmt-merge-msg[1]. ifdef::git-pull[] Only useful when merging. endif::git-pull[] + -With --no-log do not list one-line descriptions from the +With `--no-log` do not list one-line descriptions from the actual commits being merged. include::signoff-option.adoc[] ---stat:: --n:: ---no-stat:: +`--stat`:: +`-n`:: +`--no-stat`:: Show a diffstat at the end of the merge. The diffstat is also controlled by the configuration option merge.stat. + -With -n or --no-stat do not show a diffstat at the end of the +With `-n` or `--no-stat` do not show a diffstat at the end of the merge. ---squash:: ---no-squash:: +`--squash`:: +`--no-squash`:: Produce the working tree and index state as if a real merge happened (except for the merge information), but do not actually make a commit, move the `HEAD`, or record `$GIT_DIR/MERGE_HEAD` @@ -123,16 +123,16 @@ merge. the current branch whose effect is the same as merging another branch (or more in case of an octopus). + -With --no-squash perform the merge and commit the result. This -option can be used to override --squash. +With `--no-squash` perform the merge and commit the result. This +option can be used to override `--squash`. + -With --squash, --commit is not allowed, and will fail. +With `--squash`, `--commit` is not allowed, and will fail. ifdef::git-pull[] + Only useful when merging. endif::git-pull[] ---[no-]verify:: +`--[no-]verify`:: By default, the pre-merge and commit-msg hooks are run. When `--no-verify` is given, these are bypassed. See also linkgit:githooks[5]. @@ -140,21 +140,21 @@ ifdef::git-pull[] Only useful when merging. endif::git-pull[] --s <strategy>:: ---strategy=<strategy>:: +`-s <strategy>`:: +`--strategy=<strategy>`:: Use the given merge strategy; can be supplied more than once to specify them in the order they should be tried. If there is no `-s` option, a built-in list of strategies is used instead (`ort` when merging a single head, `octopus` otherwise). --X <option>:: ---strategy-option=<option>:: +`-X <option>`:: +`--strategy-option=<option>`:: Pass merge strategy specific option through to the merge strategy. ---verify-signatures:: ---no-verify-signatures:: +`--verify-signatures`:: +`--no-verify-signatures`:: Verify that the tip commit of the side branch being merged is signed with a valid key, i.e. a key that has a valid uid: in the default trust model, this means the signing key has been signed by @@ -165,22 +165,22 @@ ifdef::git-pull[] Only useful when merging. endif::git-pull[] ---summary:: ---no-summary:: - Synonyms to --stat and --no-stat; these are deprecated and will be +`--summary`:: +`--no-summary`:: + Synonyms to `--stat` and `--no-stat`; these are deprecated and will be removed in the future. ifndef::git-pull[] --q:: ---quiet:: - Operate quietly. Implies --no-progress. +`-q`:: +`--quiet`:: + Operate quietly. Implies `--no-progress`. --v:: ---verbose:: +`-v`:: +`--verbose`:: Be verbose. ---progress:: ---no-progress:: +`--progress`:: +`--no-progress`:: Turn progress on/off explicitly. If neither is specified, progress is shown if standard error is connected to a terminal. Note that not all merge strategies may support progress @@ -188,8 +188,8 @@ ifndef::git-pull[] endif::git-pull[] ---autostash:: ---no-autostash:: +`--autostash`:: +`--no-autostash`:: Automatically create a temporary stash entry before the operation begins, record it in the ref `MERGE_AUTOSTASH` and apply it after the operation ends. This means @@ -197,13 +197,13 @@ endif::git-pull[] with care: the final stash application after a successful merge might result in non-trivial conflicts. ---allow-unrelated-histories:: +`--allow-unrelated-histories`:: By default, `git merge` command refuses to merge histories that do not share a common ancestor. This option can be used to override this safety when merging histories of two projects that started their lives independently. As that is a very rare occasion, no configuration variable to enable - this by default exists and will not be added. + this by default exists or will be added. ifdef::git-pull[] + Only useful when merging. diff --git a/Documentation/merge-strategies.adoc b/Documentation/merge-strategies.adoc index 93822ebc4e..2ba43f84e7 100644 --- a/Documentation/merge-strategies.adoc +++ b/Documentation/merge-strategies.adoc @@ -6,7 +6,7 @@ backend 'merge strategies' to be chosen with `-s` option. Some strategies can also take their own options, which can be passed by giving `-X<option>` arguments to `git merge` and/or `git pull`. -ort:: +`ort`:: This is the default merge strategy when pulling or merging one branch. This strategy can only resolve two heads using a 3-way merge algorithm. When there is more than one common @@ -29,26 +29,26 @@ descendant. Otherwise, Git will treat this case as a conflict, suggesting as a resolution a submodule commit that is descendant of the conflicting ones, if one exists. + -The 'ort' strategy can take the following options: +The `ort` strategy can take the following options: -ours;; +`ours`;; This option forces conflicting hunks to be auto-resolved cleanly by favoring 'our' version. Changes from the other tree that do not conflict with our side are reflected in the merge result. For a binary file, the entire contents are taken from our side. + -This should not be confused with the 'ours' merge strategy, which does not +This should not be confused with the `ours` merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring 'our' history contains all that happened in it. -theirs;; - This is the opposite of 'ours'; note that, unlike 'ours', there is - no 'theirs' merge strategy to confuse this merge option with. +`theirs`;; + This is the opposite of `ours`; note that, unlike `ours`, there is + no `theirs` merge strategy to confuse this merge option with. -ignore-space-change;; -ignore-all-space;; -ignore-space-at-eol;; -ignore-cr-at-eol;; +`ignore-space-change`;; +`ignore-all-space`;; +`ignore-space-at-eol`;; +`ignore-cr-at-eol`;; Treats lines with the indicated type of whitespace change as unchanged for the sake of a three-way merge. Whitespace changes mixed with other changes to a line are not ignored. @@ -61,7 +61,7 @@ ignore-cr-at-eol;; version includes a substantial change, 'their' version is used; * Otherwise, the merge proceeds in the usual way. -renormalize;; +`renormalize`;; This runs a virtual check-out and check-in of all three stages of any file which needs a three-way merge. This option is meant to be used when merging branches with different clean @@ -69,92 +69,81 @@ renormalize;; branches with differing checkin/checkout attributes" in linkgit:gitattributes[5] for details. -no-renormalize;; +`no-renormalize`;; Disables the `renormalize` option. This overrides the `merge.renormalize` configuration variable. -find-renames[=<n>];; +`find-renames[=<n>]`;; Turn on rename detection, optionally setting the similarity threshold. This is the default. This overrides the - 'merge.renames' configuration variable. + `merge.renames` configuration variable. See also linkgit:git-diff[1] `--find-renames`. -rename-threshold=<n>;; +`rename-threshold=<n>`;; Deprecated synonym for `find-renames=<n>`. -subtree[=<path>];; - This option is a more advanced form of 'subtree' strategy, where - the strategy makes a guess on how two trees must be shifted to - match with each other when merging. Instead, the specified path - is prefixed (or stripped from the beginning) to make the shape of - two trees to match. +`no-renames`;; + Turn off rename detection. This overrides the `merge.renames` + configuration variable. + See also linkgit:git-diff[1] `--no-renames`. -recursive:: - This can only resolve two heads using a 3-way merge - algorithm. When there is more than one common - ancestor that can be used for 3-way merge, it creates a - merged tree of the common ancestors and uses that as - the reference tree for the 3-way merge. This has been - reported to result in fewer merge conflicts without - causing mismerges by tests done on actual merge commits - taken from Linux 2.6 kernel development history. - Additionally this can detect and handle merges involving - renames. It does not make use of detected copies. This was - the default strategy for resolving two heads from Git v0.99.9k - until v2.33.0. -+ -For a path that is a submodule, the same caution as 'ort' applies to this -strategy. -+ -The 'recursive' strategy takes the same options as 'ort'. However, -there are three additional options that 'ort' ignores (not documented -above) that are potentially useful with the 'recursive' strategy: +`histogram`;; + Deprecated synonym for `diff-algorithm=histogram`. -patience;; +`patience`;; Deprecated synonym for `diff-algorithm=patience`. -diff-algorithm=[patience|minimal|histogram|myers];; +`diff-algorithm=(histogram|minimal|myers|patience)`;; Use a different diff algorithm while merging, which can help avoid mismerges that occur due to unimportant matching lines (such as braces from distinct functions). See also linkgit:git-diff[1] `--diff-algorithm`. Note that `ort` - specifically uses `diff-algorithm=histogram`, while `recursive` - defaults to the `diff.algorithm` config setting. + defaults to `diff-algorithm=histogram`, while regular diffs + currently default to the `diff.algorithm` config setting. -no-renames;; - Turn off rename detection. This overrides the `merge.renames` - configuration variable. - See also linkgit:git-diff[1] `--no-renames`. +`subtree[=<path>]`;; + This option is a more advanced form of 'subtree' strategy, where + the strategy makes a guess on how two trees must be shifted to + match with each other when merging. Instead, the specified path + is prefixed (or stripped from the beginning) to make the shape of + two trees to match. + +`recursive`:: + This is now a synonym for `ort`. It was an alternative + implementation until v2.49.0, but was redirected to mean `ort` + in v2.50.0. The previous recursive strategy was the default + strategy for resolving two heads from Git v0.99.9k until + v2.33.0. -resolve:: +`resolve`:: This can only resolve two heads (i.e. the current branch and another branch you pulled from) using a 3-way merge algorithm. It tries to carefully detect criss-cross merge ambiguities. It does not handle renames. -octopus:: +`octopus`:: This resolves cases with more than two heads, but refuses to do a complex merge that needs manual resolution. It is primarily meant to be used for bundling topic branch heads together. This is the default merge strategy when pulling or merging more than one branch. -ours:: +`ours`:: This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. It is meant to be used to supersede old development history of side - branches. Note that this is different from the -Xours option to - the 'recursive' merge strategy. + branches. Note that this is different from the `-Xours` option to + the `ort` merge strategy. -subtree:: +`subtree`:: This is a modified `ort` strategy. When merging trees A and B, if B corresponds to a subtree of A, B is first adjusted to match the tree structure of A, instead of reading the trees at the same level. This adjustment is also done to the common ancestor tree. -With the strategies that use 3-way merge (including the default, 'ort'), +With the strategies that use 3-way merge (including the default, `ort`), if a change is made on both branches, but later reverted on one of the branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the merge base diff --git a/Documentation/mergetools/vimdiff.adoc b/Documentation/mergetools/vimdiff.adoc index befa86d692..abfd426f74 100644 --- a/Documentation/mergetools/vimdiff.adoc +++ b/Documentation/mergetools/vimdiff.adoc @@ -86,7 +86,7 @@ command. + -- When `MERGED` is not present in the layout, you must "mark" one of the -buffers with an asterisk. That will become the buffer you need to edit and +buffers with an arobase (`@`). That will become the buffer you need to edit and save after resolving the conflicts. .... ------------------------------------------ @@ -183,13 +183,13 @@ 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: `vimdiff3`, `nvimdiff1`, etc...) to use a predefined layout. -In other words, using `--tool=[g,n,]vimdiffx` is the same as using -`--tool=[g,n,]vimdiff` and setting configuration variable -`mergetool.[g,n,]vimdiff.layout` to... +In other words, using `--tool=[g|n]vimdiff<x>` is the same as using +`--tool=[g|n]vimdiff` and setting configuration variable +`mergetool.[g|n]vimdiff.layout` to... - * `x=1`: `"@LOCAL, REMOTE"` - * `x=2`: `"LOCAL, MERGED, REMOTE"` - * `x=3`: `"MERGED"` + * `<x>=1`: `"@LOCAL, REMOTE"` + * `<x>=2`: `"LOCAL, MERGED, REMOTE"` + * `<x>=3`: `"MERGED"` -Example: using `--tool=gvimdiff2` will open `gvim` with three columns (LOCAL, -MERGED and REMOTE). +Example: using `--tool=gvimdiff2` will open `gvim` with three columns (`LOCAL`, +`MERGED` and `REMOTE`). diff --git a/Documentation/meson.build b/Documentation/meson.build index 594546d68b..2fe1a1369d 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -42,6 +42,7 @@ manpages = { 'git-diagnose.adoc' : 1, 'git-diff-files.adoc' : 1, 'git-diff-index.adoc' : 1, + 'git-diff-pairs.adoc' : 1, 'git-difftool.adoc' : 1, 'git-diff-tree.adoc' : 1, 'git-diff.adoc' : 1, @@ -96,7 +97,6 @@ manpages = { 'git-notes.adoc' : 1, 'git-p4.adoc' : 1, 'git-pack-objects.adoc' : 1, - 'git-pack-redundant.adoc' : 1, 'git-pack-refs.adoc' : 1, 'git-patch-id.adoc' : 1, 'git-prune-packed.adoc' : 1, @@ -158,7 +158,6 @@ manpages = { 'git-verify-tag.adoc' : 1, 'git-version.adoc' : 1, 'git-web--browse.adoc' : 1, - 'git-whatchanged.adoc' : 1, 'git-worktree.adoc' : 1, 'git-write-tree.adoc' : 1, 'git.adoc' : 1, @@ -205,11 +204,20 @@ manpages = { 'gitworkflows.adoc' : 7, } +manpages_breaking_changes = { + 'git-pack-redundant.adoc' : 1, + 'git-whatchanged.adoc' : 1, +} + +if not get_option('breaking_changes') + manpages += manpages_breaking_changes +endif + docs_backend = get_option('docs_backend') if docs_backend == 'auto' - if find_program('asciidoc', dirs: program_path, required: false).found() + if find_program('asciidoc', dirs: program_path, native: true, required: false).found() docs_backend = 'asciidoc' - elif find_program('asciidoctor', dirs: program_path, required: false).found() + elif find_program('asciidoctor', dirs: program_path, native: true, required: false).found() docs_backend = 'asciidoctor' else error('Neither asciidoc nor asciidoctor were found.') @@ -217,7 +225,7 @@ if docs_backend == 'auto' endif if docs_backend == 'asciidoc' - asciidoc = find_program('asciidoc', dirs: program_path) + asciidoc = find_program('asciidoc', dirs: program_path, native: true) asciidoc_html = 'xhtml11' asciidoc_docbook = 'docbook' xmlto_extra = [ ] @@ -242,11 +250,21 @@ if docs_backend == 'asciidoc' '--attribute=build_dir=' + meson.current_build_dir(), ] + pager_opt = get_option('default_pager') + if pager_opt != '' and pager_opt != 'less' + asciidoc_common_options += '-agit-default-pager=' + pager_opt + endif + + editor_opt = get_option('default_editor') + if editor_opt != '' and editor_opt != 'vi' + asciidoc_common_options += '-agit-default-editor=' + editor_opt + endif + documentation_deps = [ asciidoc_conf, ] elif docs_backend == 'asciidoctor' - asciidoctor = find_program('asciidoctor', dirs: program_path) + asciidoctor = find_program('asciidoctor', dirs: program_path, native: true) asciidoc_html = 'xhtml5' asciidoc_docbook = 'docbook5' xmlto_extra = [ @@ -279,6 +297,16 @@ elif docs_backend == 'asciidoctor' '--require', 'asciidoctor-extensions', ] + pager_opt = get_option('default_pager') + if pager_opt != '' and pager_opt != 'less' + asciidoc_common_options += '-agit-default-pager=' + pager_opt + endif + + editor_opt = get_option('default_editor') + if editor_opt != '' and editor_opt != 'vi' + asciidoc_common_options += '-agit-default-editor=' + editor_opt + endif + documentation_deps = [ asciidoctor_extensions, ] @@ -288,7 +316,7 @@ if get_option('breaking_changes') asciidoc_common_options += ['--attribute', 'with-breaking-changes'] endif -xmlto = find_program('xmlto', dirs: program_path) +xmlto = find_program('xmlto', dirs: program_path, native: true) cmd_lists = [ 'cmds-ancillaryinterrogators.adoc', @@ -307,12 +335,12 @@ cmd_lists = [ documentation_deps += custom_target( command: [ - perl, + shell, '@INPUT@', meson.project_source_root(), meson.current_build_dir(), ] + cmd_lists, - input: 'cmd-list.perl', + input: 'cmd-list.sh', output: cmd_lists ) @@ -409,7 +437,7 @@ if get_option('docs').contains('html') pointing_to: 'git.html', ) - xsltproc = find_program('xsltproc', dirs: program_path) + xsltproc = find_program('xsltproc', dirs: program_path, native: true) user_manual_xml = custom_target( command: asciidoc_common_options + [ @@ -440,6 +468,7 @@ if get_option('docs').contains('html') ) articles = [ + 'BreakingChanges.adoc', 'DecisionMaking.adoc', 'MyFirstContribution.adoc', 'MyFirstObjectWalk.adoc', @@ -479,7 +508,9 @@ endif # Sanity check that we are not missing any tests present in 't/'. This check # only runs once at configure time and is thus best-effort, only. Furthermore, # it only verifies man pages for the sake of simplicity. -configured_manpages = manpages.keys() + [ 'git-bisect-lk2009.adoc', 'git-tools.adoc' ] +configured_manpages = manpages.keys() +configured_manpages += manpages_breaking_changes.keys() +configured_manpages += [ 'git-bisect-lk2009.adoc', 'git-tools.adoc' ] actual_manpages = run_command(shell, '-c', 'ls git*.adoc scalar.adoc', check: true, env: script_environment, diff --git a/Documentation/rerere-options.adoc b/Documentation/rerere-options.adoc index c3321ddea2..b0b920144a 100644 --- a/Documentation/rerere-options.adoc +++ b/Documentation/rerere-options.adoc @@ -1,5 +1,5 @@ ---rerere-autoupdate:: ---no-rerere-autoupdate:: +`--rerere-autoupdate`:: +`--no-rerere-autoupdate`:: After the rerere mechanism reuses a recorded resolution on the current conflict to update the files in the working tree, allow it to also update the index with the result of diff --git a/Documentation/rev-list-options.adoc b/Documentation/rev-list-options.adoc index ee5c5c9489..ae8765644c 100644 --- a/Documentation/rev-list-options.adoc +++ b/Documentation/rev-list-options.adoc @@ -361,6 +361,30 @@ ifdef::git-rev-list[] --progress=<header>:: Show progress reports on stderr as objects are considered. The `<header>` text will be printed with each progress update. + +-z:: + Instead of being newline-delimited, each outputted object and its + accompanying metadata is delimited using NUL bytes. Output is printed + in the following form: ++ +----------------------------------------------------------------------- +<OID> NUL [<token>=<value> NUL]... +----------------------------------------------------------------------- ++ +Additional object metadata, such as object paths or boundary objects, is +printed using the `<token>=<value>` form. Token values are printed as-is +without any encoding/truncation. An OID entry never contains a '=' character +and thus is used to signal the start of a new object record. Examples: ++ +----------------------------------------------------------------------- +<OID> NUL +<OID> NUL path=<path> NUL +<OID> NUL boundary=yes NUL +<OID> NUL missing=yes NUL [<token>=<value> NUL]... +----------------------------------------------------------------------- ++ +This mode is only compatible with the `--objects`, `--boundary`, and +`--missing` output options. endif::git-rev-list[] History Simplification @@ -429,6 +453,7 @@ filtered for `foo`, they look different and equal, respectively.) In the following, we will always refer to the same example history to illustrate the differences between simplification settings. We assume that you are filtering for a file `foo` in this commit graph: + ----------------------------------------------------------------------- .-A---M---N---O---P---Q / / / / / / @@ -436,6 +461,7 @@ that you are filtering for a file `foo` in this commit graph: \ / / / / / `-------------' X ----------------------------------------------------------------------- + The horizontal line of history A---Q is taken to be the first parent of each merge. The commits are: @@ -640,7 +666,7 @@ commits affected by that topic, we may only want to view the subset of ----------------------------------------------------------------------- E \ - G---H---I---J + C---G---H---I---J \ L--M ----------------------------------------------------------------------- diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index 7e4259c674..4bd5b150e8 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -9,12 +9,12 @@ SYNOPSIS -------- [verse] scalar clone [--single-branch] [--branch <main-branch>] [--full-clone] - [--[no-]src] <url> [<enlistment>] + [--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>] scalar list -scalar register [<enlistment>] +scalar register [--[no-]maintenance] [<enlistment>] scalar unregister [<enlistment>] scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) [<enlistment>] -scalar reconfigure [ --all | <enlistment> ] +scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | <enlistment> ] scalar diagnose [<enlistment>] scalar delete <enlistment> @@ -97,6 +97,11 @@ cloning. If the HEAD at the remote did not point at any branch when A sparse-checkout is initialized by default. This behavior can be turned off via `--full-clone`. +--[no-]maintenance:: + By default, `scalar clone` configures the enlistment to use Git's + background maintenance feature. Use the `--no-maintenance` to skip + this configuration. + List ~~~~ @@ -117,6 +122,12 @@ Note: when this subcommand is called in a worktree that is called `src/`, its parent directory is considered to be the Scalar enlistment. If the worktree is _not_ called `src/`, it itself will be considered to be the Scalar enlistment. +--[no-]maintenance:: + By default, `scalar register` configures the enlistment to use Git's + background maintenance feature. Use the `--no-maintenance` to skip + this configuration. This does not disable any maintenance that may + already be enabled in other ways. + Unregister ~~~~~~~~~~ @@ -149,8 +160,18 @@ After a Scalar upgrade, or when the configuration of a Scalar enlistment was somehow corrupted or changed by mistake, this subcommand allows to reconfigure the enlistment. -With the `--all` option, all enlistments currently registered with Scalar -will be reconfigured. Use this option after each Scalar upgrade. +--all:: + When `--all` is specified, reconfigure all enlistments currently + registered with Scalar by the `scalar.repo` config key. Use this + option after each upgrade to get the latest features. + +--maintenance=(enable|disable|keep):: + By default, Scalar configures the enlistment to use Git's + background maintenance feature; this is the same as using the + `enable` value for this option. Use the `disable` value to + remove each considered enlistment from background maintenance. + Use `keep' to leave the background maintenance configuration + untouched for these repositories. Diagnose ~~~~~~~~ diff --git a/Documentation/technical/api-parse-options.adoc b/Documentation/technical/api-parse-options.adoc index 61fa6ee167..880eb94642 100644 --- a/Documentation/technical/api-parse-options.adoc +++ b/Documentation/technical/api-parse-options.adoc @@ -211,11 +211,13 @@ There are some macros to easily define options: Use of `--no-option` will clear the list of preceding values. `OPT_INTEGER(short, long, &int_var, description)`:: - Introduce an option with integer argument. - The integer is put into `int_var`. + Introduce an option with integer argument. The argument must be a + integer and may include a suffix of 'k', 'm' or 'g' to + scale the provided value by 1024, 1024^2 or 1024^3 respectively. + The scaled value is put into `int_var`. -`OPT_MAGNITUDE(short, long, &unsigned_long_var, description)`:: - Introduce an option with a size argument. The argument must be a +`OPT_UNSIGNED(short, long, &unsigned_long_var, description)`:: + Introduce an option with an unsigned integer argument. The argument must be a non-negative integer and may include a suffix of 'k', 'm' or 'g' to scale the provided value by 1024, 1024^2 or 1024^3 respectively. The scaled value is put into `unsigned_long_var`. diff --git a/Documentation/technical/api-path-walk.adoc b/Documentation/technical/api-path-walk.adoc index 3e089211fb..34c905eb9c 100644 --- a/Documentation/technical/api-path-walk.adoc +++ b/Documentation/technical/api-path-walk.adoc @@ -56,6 +56,14 @@ better off using the revision walk API instead. the revision walk so that the walk emits commits marked with the `UNINTERESTING` flag. +`edge_aggressive`:: + For performance reasons, usually only the boundary commits are + explored to find UNINTERESTING objects. However, in the case of + shallow clones it can be helpful to mark all trees and blobs + reachable from UNINTERESTING tip commits as UNINTERESTING. This + matches the behavior of `--objects-edge-aggressive` in the + revision API. + `pl`:: This pattern list pointer allows focusing the path-walk search to a set of patterns, only emitting paths that match the given @@ -69,4 +77,5 @@ Examples See example usages in: `t/helper/test-path-walk.c`, + `builtin/pack-objects.c`, `builtin/backfill.c` diff --git a/Documentation/technical/build-systems.adoc b/Documentation/technical/build-systems.adoc index d9dafb407c..3c5237b9fd 100644 --- a/Documentation/technical/build-systems.adoc +++ b/Documentation/technical/build-systems.adoc @@ -32,7 +32,10 @@ that generally have somebody running test pipelines against regularly: - OpenBSD The platforms which must be supported by the tool should be aligned with our -[platform support policy](platform-support.txt). +platform support policy (see platform-support.adoc). +// once we lose AsciiDoc compatibility, we can start writing the above as: +// xref:platform-support.adoc#platform-support-policy[platform support policy] +// or something like that, but until then.... === Auto-detection of supported features diff --git a/Documentation/technical/bundle-uri.adoc b/Documentation/technical/bundle-uri.adoc index 91d3a13e32..12283fa9ed 100644 --- a/Documentation/technical/bundle-uri.adoc +++ b/Documentation/technical/bundle-uri.adoc @@ -232,13 +232,13 @@ will interact with bundle URIs according to the following flow: are present in the client repository. If some are missing, then the client delays unbundling until other bundles have been unbundled, making those OIDs present. When all required OIDs are present, the - client unbundles that data using a refspec. The default refspec is - `+refs/heads/*:refs/bundles/*`, but this can be configured. These refs - are stored so that later `git fetch` negotiations can communicate each - bundled ref as a `have`, reducing the size of the fetch over the Git - protocol. To allow pruning refs from this ref namespace, Git may - introduce a numbered namespace (such as `refs/bundles/<i>/*`) such that - stale bundle refs can be deleted. + client unbundles that data using a refspec. The refspec used is + `+refs/*:refs/bundles/*`. These refs are stored so that later + `git fetch` negotiations can communicate each bundled ref as a `have`, + reducing the size of the fetch over the Git protocol. To allow pruning + refs from this ref namespace, Git may introduce a numbered namespace + (such as `refs/bundles/<i>/*`) such that stale bundle refs can be + deleted. 3. If the file is instead a bundle list, then the client inspects the `bundle.mode` to see if the list is of the `all` or `any` form. diff --git a/Documentation/technical/multi-pack-index.adoc b/Documentation/technical/multi-pack-index.adoc index cc063b30be..ffda70aa13 100644 --- a/Documentation/technical/multi-pack-index.adoc +++ b/Documentation/technical/multi-pack-index.adoc @@ -164,19 +164,81 @@ objects_nr($H2) + objects_nr($H1) + i (in the C implementation, this is often computed as `i + m->num_objects_in_base`). +=== Pseudo-pack order for incremental MIDXs + +The original implementation of multi-pack reachability bitmaps defined +the pseudo-pack order in linkgit:gitformat-pack[5] (see the section +titled "multi-pack-index reverse indexes") roughly as follows: + +____ +In short, a MIDX's pseudo-pack is the de-duplicated concatenation of +objects in packs stored by the MIDX, laid out in pack order, and the +packs arranged in MIDX order (with the preferred pack coming first). +____ + +In the incremental MIDX design, we extend this definition to include +objects from multiple layers of the MIDX chain. The pseudo-pack order +for incremental MIDXs is determined by concatenating the pseudo-pack +ordering for each layer of the MIDX chain in order. Formally two objects +`o1` and `o2` are compared as follows: + +1. If `o1` appears in an earlier layer of the MIDX chain than `o2`, then + `o1` sorts ahead of `o2`. + +2. Otherwise, if `o1` and `o2` appear in the same MIDX layer, and that + MIDX layer has no base, then if one of `pack(o1)` and `pack(o2)` is + preferred and the other is not, then the preferred one sorts ahead of + the non-preferred one. If there is a base layer (i.e. the MIDX layer + is not the first layer in the chain), then if `pack(o1)` appears + earlier in that MIDX layer's pack order, then `o1` sorts ahead of + `o2`. Likewise if `pack(o2)` appears earlier, then the opposite is + true. + +3. Otherwise, `o1` and `o2` appear in the same pack, and thus in the + same MIDX layer. Sort `o1` and `o2` by their offset within their + containing packfile. + +Note that the preferred pack is a property of the MIDX chain, not the +individual layers themselves. Fundamentally we could introduce a +per-layer preferred pack, but this is less relevant now that we can +perform multi-pack reuse across the set of packs in a MIDX. + +=== Reachability bitmaps and incremental MIDXs + +Each layer of an incremental MIDX chain may have its objects (and the +objects from any previous layer in the same MIDX chain) represented in +its own `*.bitmap` file. + +The structure of a `*.bitmap` file belonging to an incremental MIDX +chain is identical to that of a non-incremental MIDX bitmap, or a +classic single-pack bitmap. Since objects are added to the end of the +incremental MIDX's pseudo-pack order (see above), it is possible to +extend a bitmap when appending to the end of a MIDX chain. + +(Note: it is possible likewise to compress a contiguous sequence of MIDX +incremental layers, and their `*.bitmap` files into a single layer and +`*.bitmap`, but this is not yet implemented.) + +The object positions used are global within the pseudo-pack order, so +subsequent layers will have, for example, `m->num_objects_in_base` +number of `0` bits in each of their four type bitmaps. This follows from +the fact that we only write type bitmap entries for objects present in +the layer immediately corresponding to the bitmap). + +Note also that only the bitmap pertaining to the most recent layer in an +incremental MIDX chain is used to store reachability information about +the interesting and uninteresting objects in a reachability query. +Earlier bitmap layers are only used to look up commit and pseudo-merge +bitmaps from that layer, as well as the type-level bitmaps for objects +in that layer. + +To simplify the implementation, type-level bitmaps are iterated +simultaneously, and their results are OR'd together to avoid recursively +calling internal bitmap functions. + Future Work ----------- -- The multi-pack-index allows many packfiles, especially in a context - where repacking is expensive (such as a very large repo), or - unexpected maintenance time is unacceptable (such as a high-demand - build machine). However, the multi-pack-index needs to be rewritten - in full every time. We can extend the format to be incremental, so - writes are fast. By storing a small "tip" multi-pack-index that - points to large "base" MIDX files, we can keep writes fast while - still reducing the number of binary searches required for object - lookups. - - If the multi-pack-index is extended to store a "stable object order" (a function Order(hash) = integer that is constant for a given hash, even as the multi-pack-index is updated) then MIDX bitmaps could be diff --git a/Documentation/technical/sparse-checkout.adoc b/Documentation/technical/sparse-checkout.adoc index 67134bb768..0f750ef3e3 100644 --- a/Documentation/technical/sparse-checkout.adoc +++ b/Documentation/technical/sparse-checkout.adoc @@ -66,7 +66,7 @@ sparsity patterns: patterns from $GIT_DIR/info/sparse-checkout used to reasons: (1) users in cone mode specify directories rather than patterns (their directories are transformed into patterns, but users may think you are talking about non-cone mode if you use the - word "patterns"), and (b) the sparse specification might + word "patterns"), and (2) the sparse specification might transiently differ in the working tree or index from the sparsity patterns (see "Sparse specification vs. sparsity patterns"). @@ -356,8 +356,6 @@ understanding these differences can be beneficial. The behavior for these commands somewhat depends upon the merge strategy being used: * `ort` behaves as described above - * `recursive` tries to not vivify files unnecessarily, but does sometimes - vivify files without conflicts. * `octopus` and `resolve` will always vivify any file changed in the merge relative to the first parent, which is rather suboptimal. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 3abfe7d3d7..63463c8773 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,6 +1,6 @@ #!/bin/sh -DEF_VER=v2.49.0 +DEF_VER=v2.50.GIT LF=' ' @@ -82,7 +82,7 @@ read GIT_MAJOR_VERSION GIT_MINOR_VERSION GIT_MICRO_VERSION GIT_PATCH_LEVEL trail $(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ') EOF -REPLACED=$(printf "%s" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ +REPLACED=$(printf "%s\n" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ -e "s|@GIT_MAJOR_VERSION@|$GIT_MAJOR_VERSION|" \ -e "s|@GIT_MINOR_VERSION@|$GIT_MINOR_VERSION|" \ -e "s|@GIT_MICRO_VERSION@|$GIT_MICRO_VERSION|" \ @@ -340,9 +340,6 @@ include shared.mak # # Define HAVE_SYNC_FILE_RANGE if your platform has sync_file_range. # -# Define NEEDS_LIBRT if your platform requires linking with librt (glibc version -# before 2.17) for clock_gettime and CLOCK_MONOTONIC. -# # Define HAVE_BSD_SYSCTL if your platform has a BSD-compatible sysctl function. # # Define HAVE_GETDELIM if your system has the getdelim() function. @@ -618,6 +615,7 @@ prefix = $(HOME) bindir = $(prefix)/bin mandir = $(prefix)/share/man infodir = $(prefix)/share/info +bash_completion_dir = $(prefix)/share/bash-completion/completions gitexecdir = libexec/git-core mergetoolsdir = $(gitexecdir)/mergetools sharedir = $(prefix)/share @@ -821,6 +819,7 @@ TEST_BUILTINS_OBJS += test-mergesort.o TEST_BUILTINS_OBJS += test-mktemp.o TEST_BUILTINS_OBJS += test-name-hash.o TEST_BUILTINS_OBJS += test-online-cpus.o +TEST_BUILTINS_OBJS += test-pack-deltas.o TEST_BUILTINS_OBJS += test-pack-mtimes.o TEST_BUILTINS_OBJS += test-parse-options.o TEST_BUILTINS_OBJS += test-parse-pathspec-file.o @@ -860,6 +859,7 @@ TEST_BUILTINS_OBJS += test-wildmatch.o TEST_BUILTINS_OBJS += test-windows-named-pipe.o TEST_BUILTINS_OBJS += test-write-cache.o TEST_BUILTINS_OBJS += test-xml-encode.o +TEST_BUILTINS_OBJS += test-zlib.o # Do not add more tests here unless they have extra dependencies. Add # them in TEST_BUILTINS_OBJS above. @@ -955,7 +955,7 @@ FOUND_SOURCE_FILES := $(filter-out $(GENERATED_H),$(shell $(SOURCES_CMD))) FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES)) FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES)) -COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES),$(FOUND_C_SOURCES)) +COCCI_SOURCES = $(filter-out $(THIRD_PARTY_SOURCES) reftable/%,$(FOUND_C_SOURCES)) LIB_H = $(FOUND_H_SOURCES) @@ -994,7 +994,9 @@ LIB_OBJS += common-exit.o LIB_OBJS += common-init.o LIB_OBJS += compat/nonblock.o LIB_OBJS += compat/obstack.o +LIB_OBJS += compat/open.o LIB_OBJS += compat/terminal.o +LIB_OBJS += compiler-tricks/not-constant.o LIB_OBJS += config.o LIB_OBJS += connect.o LIB_OBJS += connected.o @@ -1041,6 +1043,7 @@ LIB_OBJS += gpg-interface.o LIB_OBJS += graph.o LIB_OBJS += grep.o LIB_OBJS += hash-lookup.o +LIB_OBJS += hash.o LIB_OBJS += hashmap.o LIB_OBJS += help.o LIB_OBJS += hex.o @@ -1068,7 +1071,6 @@ LIB_OBJS += merge-blobs.o LIB_OBJS += merge-ll.o LIB_OBJS += merge-ort.o LIB_OBJS += merge-ort-wrappers.o -LIB_OBJS += merge-recursive.o LIB_OBJS += merge.o LIB_OBJS += midx.o LIB_OBJS += midx-write.o @@ -1083,6 +1085,7 @@ LIB_OBJS += notes.o LIB_OBJS += object-file-convert.o LIB_OBJS += object-file.o LIB_OBJS += object-name.o +LIB_OBJS += object-store.o LIB_OBJS += object.o LIB_OBJS += oid-array.o LIB_OBJS += oidmap.o @@ -1242,6 +1245,7 @@ BUILTIN_OBJS += builtin/describe.o BUILTIN_OBJS += builtin/diagnose.o BUILTIN_OBJS += builtin/diff-files.o BUILTIN_OBJS += builtin/diff-index.o +BUILTIN_OBJS += builtin/diff-pairs.o BUILTIN_OBJS += builtin/diff-tree.o BUILTIN_OBJS += builtin/diff.o BUILTIN_OBJS += builtin/difftool.o @@ -1364,6 +1368,8 @@ CLAR_TEST_SUITES += u-reftable-tree CLAR_TEST_SUITES += u-strbuf CLAR_TEST_SUITES += u-strcmp-offset CLAR_TEST_SUITES += u-strvec +CLAR_TEST_SUITES += u-trailer +CLAR_TEST_SUITES += u-urlmatch-normalization CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X) CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES)) CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o @@ -1374,12 +1380,10 @@ UNIT_TEST_PROGRAMS += t-reftable-basics UNIT_TEST_PROGRAMS += t-reftable-block UNIT_TEST_PROGRAMS += t-reftable-merged UNIT_TEST_PROGRAMS += t-reftable-pq -UNIT_TEST_PROGRAMS += t-reftable-reader UNIT_TEST_PROGRAMS += t-reftable-readwrite UNIT_TEST_PROGRAMS += t-reftable-record UNIT_TEST_PROGRAMS += t-reftable-stack -UNIT_TEST_PROGRAMS += t-trailer -UNIT_TEST_PROGRAMS += t-urlmatch-normalization +UNIT_TEST_PROGRAMS += t-reftable-table UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS)) UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/lib-reftable.o @@ -1809,7 +1813,6 @@ ifdef FREAD_READS_DIRECTORIES endif ifdef OPEN_RETURNS_EINTR COMPAT_CFLAGS += -DOPEN_RETURNS_EINTR - COMPAT_OBJS += compat/open.o endif ifdef NO_SYMLINK_HEAD BASIC_CFLAGS += -DNO_SYMLINK_HEAD @@ -2171,18 +2174,14 @@ ifdef HAVE_SYNC_FILE_RANGE BASIC_CFLAGS += -DHAVE_SYNC_FILE_RANGE endif -ifdef NEEDS_LIBRT - EXTLIBS += -lrt +ifdef HAVE_SYSINFO + BASIC_CFLAGS += -DHAVE_SYSINFO endif ifdef HAVE_BSD_SYSCTL BASIC_CFLAGS += -DHAVE_BSD_SYSCTL endif -ifdef HAVE_BSD_KERN_PROC_SYSCTL - BASIC_CFLAGS += -DHAVE_BSD_KERN_PROC_SYSCTL -endif - ifdef HAVE_GETDELIM BASIC_CFLAGS += -DHAVE_GETDELIM endif @@ -2213,25 +2212,33 @@ ifneq ($(findstring openssl,$(CSPRNG_METHOD)),) EXTLIBS += -lcrypto -lssl endif -ifneq ($(PROCFS_EXECUTABLE_PATH),) - procfs_executable_path_SQ = $(subst ','\'',$(PROCFS_EXECUTABLE_PATH)) - BASIC_CFLAGS += '-DPROCFS_EXECUTABLE_PATH="$(procfs_executable_path_SQ)"' -endif - ifndef HAVE_PLATFORM_PROCINFO COMPAT_OBJS += compat/stub/procinfo.o endif -ifdef HAVE_NS_GET_EXECUTABLE_PATH - BASIC_CFLAGS += -DHAVE_NS_GET_EXECUTABLE_PATH -endif +ifdef RUNTIME_PREFIX -ifdef HAVE_ZOS_GET_EXECUTABLE_PATH - BASIC_CFLAGS += -DHAVE_ZOS_GET_EXECUTABLE_PATH -endif + ifdef HAVE_BSD_KERN_PROC_SYSCTL + BASIC_CFLAGS += -DHAVE_BSD_KERN_PROC_SYSCTL + endif + + ifneq ($(PROCFS_EXECUTABLE_PATH),) + pep_SQ = $(subst ','\'',$(PROCFS_EXECUTABLE_PATH)) + BASIC_CFLAGS += '-DPROCFS_EXECUTABLE_PATH="$(pep_SQ)"' + endif + + ifdef HAVE_NS_GET_EXECUTABLE_PATH + BASIC_CFLAGS += -DHAVE_NS_GET_EXECUTABLE_PATH + endif + + ifdef HAVE_ZOS_GET_EXECUTABLE_PATH + BASIC_CFLAGS += -DHAVE_ZOS_GET_EXECUTABLE_PATH + endif + + ifdef HAVE_WPGMPTR + BASIC_CFLAGS += -DHAVE_WPGMPTR + endif -ifdef HAVE_WPGMPTR - BASIC_CFLAGS += -DHAVE_WPGMPTR endif ifdef FILENO_IS_A_MACRO @@ -2261,6 +2268,10 @@ ifdef WITH_BREAKING_CHANGES BASIC_CFLAGS += -DWITH_BREAKING_CHANGES endif +ifdef CHECK_ASSERTION_SIDE_EFFECTS + BASIC_CFLAGS += -DCHECK_ASSERTION_SIDE_EFFECTS +endif + ifdef INCLUDE_LIBGIT_RS # Enable symbol hiding in contrib/libgit-sys/libgitpub.a without making # us rebuild the whole tree every time we run a Rust build. @@ -2319,6 +2330,7 @@ bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) mandir_SQ = $(subst ','\'',$(mandir)) mandir_relative_SQ = $(subst ','\'',$(mandir_relative)) infodir_relative_SQ = $(subst ','\'',$(infodir_relative)) +bash_completion_dir_SQ = $(subst ','\'',$(bash_completion_dir)) perllibdir_SQ = $(subst ','\'',$(perllibdir)) localedir_SQ = $(subst ','\'',$(localedir)) localedir_relative_SQ = $(subst ','\'',$(localedir_relative)) @@ -2729,10 +2741,10 @@ REFTABLE_OBJS += reftable/blocksource.o REFTABLE_OBJS += reftable/iter.o REFTABLE_OBJS += reftable/merged.o REFTABLE_OBJS += reftable/pq.o -REFTABLE_OBJS += reftable/reader.o REFTABLE_OBJS += reftable/record.o REFTABLE_OBJS += reftable/stack.o REFTABLE_OBJS += reftable/system.o +REFTABLE_OBJS += reftable/table.o REFTABLE_OBJS += reftable/tree.o REFTABLE_OBJS += reftable/writer.o @@ -2794,7 +2806,7 @@ endif compdb_dir = compile_commands ifeq ($(GENERATE_COMPILATION_DATABASE),yes) -missing_compdb_dir = $(compdb_dir) +missing_compdb_dir = $(filter-out $(wildcard $(compdb_dir)), $(compdb_dir)) $(missing_compdb_dir): @mkdir -p $@ @@ -3324,8 +3336,10 @@ HCC = $(HCO:hco=hcc) $(HCO): %.hco: %.hcc $(GENERATED_H) FORCE $(QUIET_HDR)$(CC) $(ALL_CFLAGS) -o /dev/null -c -xc $< -.PHONY: hdr-check $(HCO) +# TODO: deprecate 'hdr-check' in lieu of 'check-headers' in Git 2.51+ +.PHONY: hdr-check check-headers $(HCO) hdr-check: $(HCO) +check-headers: hdr-check .PHONY: style style: @@ -3563,6 +3577,10 @@ endif ifneq (,$X) $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_COMMANDS_TO_INSTALL) $(OTHER_PROGRAMS))), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';) endif +ifndef NO_BASH_COMPLETION + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bash_completion_dir_SQ)' && \ + $(INSTALL) -m 644 contrib/completion/git-completion.bash '$(DESTDIR_SQ)$(bash_completion_dir_SQ)/git' +endif bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \ execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \ @@ -1 +1 @@ -Documentation/RelNotes/2.49.0.adoc
\ No newline at end of file +Documentation/RelNotes/2.51.0.adoc
\ No newline at end of file @@ -51,6 +51,7 @@ static struct { [ADVICE_AM_WORK_DIR] = { "amWorkDir" }, [ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName" }, [ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge" }, + [ADVICE_DEFAULT_BRANCH_NAME] = { "defaultBranchName" }, [ADVICE_DETACHED_HEAD] = { "detachedHead" }, [ADVICE_DIVERGING] = { "diverging" }, [ADVICE_FETCH_SET_HEAD_WARN] = { "fetchRemoteHEADWarn" }, @@ -18,6 +18,7 @@ enum advice_type { ADVICE_AM_WORK_DIR, ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME, ADVICE_COMMIT_BEFORE_MERGE, + ADVICE_DEFAULT_BRANCH_NAME, ADVICE_DETACHED_HEAD, ADVICE_DIVERGING, ADVICE_FETCH_SET_HEAD_WARN, @@ -14,7 +14,7 @@ #include "abspath.h" #include "base85.h" #include "config.h" -#include "object-store-ll.h" +#include "object-store.h" #include "delta.h" #include "diff.h" #include "dir.h" @@ -2219,7 +2219,7 @@ static void reverse_patches(struct patch *p) struct fragment *frag = p->fragments; SWAP(p->new_name, p->old_name); - if (p->new_mode) + if (p->new_mode || p->is_delete) SWAP(p->new_mode, p->old_mode); SWAP(p->is_new, p->is_delete); SWAP(p->lines_added, p->lines_deleted); @@ -5123,8 +5123,8 @@ int apply_parse_options(int argc, const char **argv, /* Think twice before adding "--nul" synonym to this */ OPT_SET_INT('z', NULL, &state->line_termination, N_("paths are separated with NUL character"), '\0'), - OPT_INTEGER('C', NULL, &state->p_context, - N_("ensure at least <n> lines of context match")), + OPT_UNSIGNED('C', NULL, &state->p_context, + N_("ensure at least <n> lines of context match")), OPT_CALLBACK(0, "whitespace", state, N_("action"), N_("detect new or modified lines that have whitespace errors"), apply_option_parse_whitespace), diff --git a/archive-tar.c b/archive-tar.c index 0edf13fba7..282b48196f 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -11,7 +11,7 @@ #include "hex.h" #include "tar.h" #include "archive.h" -#include "object-store-ll.h" +#include "object-store.h" #include "strbuf.h" #include "streaming.h" #include "run-command.h" diff --git a/archive-zip.c b/archive-zip.c index 9f32730181..405da6f3d8 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -12,7 +12,7 @@ #include "hex.h" #include "streaming.h" #include "utf8.h" -#include "object-store-ll.h" +#include "object-store.h" #include "strbuf.h" #include "userdiff.h" #include "write-or-die.h" @@ -14,7 +14,7 @@ #include "pretty.h" #include "setup.h" #include "refs.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "tree.h" #include "tree-walk.h" @@ -216,7 +216,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base, /* Stream it? */ if (S_ISREG(mode) && !args->convert && oid_object_info(args->repo, oid, &size) == OBJ_BLOB && - size > big_file_threshold) + size > repo_settings_get_big_file_threshold(the_repository)) return write_entry(args, oid, path.buf, path.len, mode, NULL, size); buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size); @@ -312,7 +312,7 @@ int write_archive_entries(struct archiver_args *args, struct object_id fake_oid; int i; - oidcpy(&fake_oid, null_oid()); + oidcpy(&fake_oid, null_oid(the_hash_algo)); if (args->baselen > 0 && args->base[args->baselen - 1] == '/') { size_t len = args->baselen; @@ -650,20 +650,37 @@ static int parse_archive_args(int argc, const char **argv, OPT_STRING(0, "format", &format, N_("fmt"), N_("archive format")), OPT_STRING(0, "prefix", &base, N_("prefix"), N_("prepend prefix to each pathname in the archive")), - { OPTION_CALLBACK, 0, "add-file", args, N_("file"), - N_("add untracked file to archive"), 0, add_file_cb, - (intptr_t)&base }, - { OPTION_CALLBACK, 0, "add-virtual-file", args, - N_("path:content"), N_("add untracked file to archive"), 0, - add_file_cb, (intptr_t)&base }, + { + .type = OPTION_CALLBACK, + .long_name = "add-file", + .value = args, + .argh = N_("file"), + .help = N_("add untracked file to archive"), + .callback = add_file_cb, + .defval = (intptr_t) &base, + }, + { + .type = OPTION_CALLBACK, + .long_name = "add-virtual-file", + .value = args, + .argh = N_("path:content"), + .help = N_("add untracked file to archive"), + .callback = add_file_cb, + .defval = (intptr_t) &base, + }, OPT_STRING('o', "output", &output, N_("file"), N_("write the archive to this file")), OPT_BOOL(0, "worktree-attributes", &worktree_attributes, N_("read .gitattributes in working directory")), OPT__VERBOSE(&verbose, N_("report archived files on stderr")), - { OPTION_STRING, 0, "mtime", &mtime_option, N_("time"), - N_("set modification time of archive entries"), - PARSE_OPT_NONEG }, + { + .type = OPTION_STRING, + .long_name = "mtime", + .value = &mtime_option, + .argh = N_("time"), + .help = N_("set modification time of archive entries"), + .flags = PARSE_OPT_NONEG, + }, OPT_NUMBER_CALLBACK(&compression_level, N_("set compression level"), number_callback), OPT_GROUP(""), @@ -22,7 +22,7 @@ #include "read-cache-ll.h" #include "refs.h" #include "revision.h" -#include "object-store-ll.h" +#include "object-store.h" #include "setup.h" #include "thread-utils.h" #include "tree-walk.h" @@ -20,7 +20,7 @@ #include "commit-slab.h" #include "commit-reach.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "dir.h" @@ -3,7 +3,7 @@ #include "git-compat-util.h" #include "refs.h" -#include "object-store-ll.h" +#include "object-store.h" #include "cache-tree.h" #include "mergesort.h" #include "commit.h" @@ -255,7 +255,7 @@ static struct commit *fake_working_tree_commit(struct repository *r, switch (st.st_mode & S_IFMT) { case S_IFREG: if (opt->flags.allow_textconv && - textconv_object(r, read_from, mode, null_oid(), 0, &buf_ptr, &buf_len)) + textconv_object(r, read_from, mode, null_oid(the_hash_algo), 0, &buf_ptr, &buf_len)) strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1); else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size) die_errno("cannot open or read '%s'", read_from); @@ -277,7 +277,7 @@ static struct commit *fake_working_tree_commit(struct repository *r, convert_to_git(r->index, path, buf.buf, buf.len, &buf, 0); origin->file.ptr = buf.buf; origin->file.size = buf.len; - pretend_object_file(buf.buf, buf.len, OBJ_BLOB, &origin->blob_oid); + pretend_object_file(the_repository, buf.buf, buf.len, OBJ_BLOB, &origin->blob_oid); /* * Read the current index, replace the path entry with @@ -633,7 +633,7 @@ void create_branch(struct repository *r, 0, &err); if (!transaction || ref_transaction_update(transaction, ref.buf, - &oid, forcing ? NULL : null_oid(), + &oid, forcing ? NULL : null_oid(the_hash_algo), NULL, NULL, flags, msg, &err) || ref_transaction_commit(transaction, &err)) die("%s", err.buf); @@ -153,6 +153,7 @@ int cmd_diagnose(int argc, const char **argv, const char *prefix, struct reposit int cmd_diff_files(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff_index(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_diff_pairs(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_diff_tree(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_difftool(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_env__helper(int argc, const char **argv, const char *prefix, struct repository *repo); diff --git a/builtin/add.c b/builtin/add.c index 78dfb26577..7c292ffdc6 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -386,11 +386,14 @@ int cmd_add(int argc, char *ps_matched = NULL; struct lock_file lock_file = LOCK_INIT; - if (repo) - repo_config(repo, add_config, NULL); + repo_config(repo, add_config, NULL); argc = parse_options(argc, argv, prefix, builtin_add_options, builtin_add_usage, PARSE_OPT_KEEP_ARGV0); + + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; + if (patch_interactive) add_interactive = 1; if (add_interactive) { @@ -427,9 +430,6 @@ int cmd_add(int argc, add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize; require_pathspec = !(take_worktree_changes || (0 < addremove_explicit)); - prepare_repo_settings(repo); - repo->settings.command_requires_full_index = 0; - repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR); /* diff --git a/builtin/am.c b/builtin/am.c index 2921bb89ef..e32a3b4c97 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -31,7 +31,7 @@ #include "preload-index.h" #include "sequencer.h" #include "revision.h" -#include "merge-recursive.h" +#include "merge-ort-wrappers.h" #include "log-tree.h" #include "notes-utils.h" #include "rerere.h" @@ -850,8 +850,10 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths, series_dir = dirname(series_dir_buf); fp = fopen(*paths, "r"); - if (!fp) + if (!fp) { + free(series_dir_buf); return error_errno(_("could not open '%s' for reading"), *paths); + } while (!strbuf_getline_lf(&sb, fp)) { if (*sb.buf == '#') @@ -1638,12 +1640,13 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); o.branch2 = their_tree_name; + o.ancestor = "constructed fake ancestor"; o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE; if (state->quiet) o.verbosity = 0; - if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { + if (merge_ort_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { repo_rerere(the_repository, state->allow_rerere_autoupdate); free(their_tree_name); return error(_("Failed to merge in the changes.")); @@ -2399,11 +2402,16 @@ int cmd_am(int argc, OPT_CMDMODE(0, "quit", &resume_mode, N_("abort the patching operation but keep HEAD where it is"), RESUME_QUIT), - { OPTION_CALLBACK, 0, "show-current-patch", &resume_mode, - "(diff|raw)", - N_("show the patch being applied"), - PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, - parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW }, + { + .type = OPTION_CALLBACK, + .long_name = "show-current-patch", + .value = &resume_mode, + .argh = "(diff|raw)", + .help = N_("show the patch being applied"), + .flags = PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, + .callback = parse_opt_show_current_patch, + .defval = RESUME_SHOW_PATCH_RAW, + }, OPT_CMDMODE(0, "retry", &resume_mode, N_("try to apply current patch again"), RESUME_APPLY), @@ -2416,9 +2424,16 @@ int cmd_am(int argc, OPT_BOOL(0, "ignore-date", &state.ignore_date, N_("use current timestamp for author date")), OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate), - { OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, N_("key-id"), - N_("GPG-sign commits"), - PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, + { + .type = OPTION_STRING, + .short_name = 'S', + .long_name = "gpg-sign", + .value = &state.sign_commit, + .argh = N_("key-id"), + .help = N_("GPG-sign commits"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "", + }, OPT_CALLBACK_F(0, "empty", &state.empty_type, "(stop|drop|keep)", N_("how to handle empty patches"), PARSE_OPT_NONEG, am_option_parse_empty), diff --git a/builtin/apply.c b/builtin/apply.c index 84f1863d3a..a1e20c593d 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -12,7 +12,7 @@ static const char * const apply_usage[] = { int cmd_apply(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int force_apply = 0; int options = 0; @@ -35,6 +35,11 @@ int cmd_apply(int argc, &state, &force_apply, &options, apply_usage); + if (repo) { + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; + } + if (check_apply_state(&state, force_apply)) exit(128); diff --git a/builtin/backfill.c b/builtin/backfill.c index 33e1ea2f84..fa82ad2f6f 100644 --- a/builtin/backfill.c +++ b/builtin/backfill.c @@ -13,7 +13,7 @@ #include "tree.h" #include "tree-walk.h" #include "object.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oid-array.h" #include "oidset.h" #include "promisor-remote.h" @@ -123,8 +123,8 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit .sparse = 0, }; struct option options[] = { - OPT_INTEGER(0, "min-batch-size", &ctx.min_batch_size, - N_("Minimum number of objects to request at a time")), + OPT_UNSIGNED(0, "min-batch-size", &ctx.min_batch_size, + N_("Minimum number of objects to request at a time")), OPT_BOOL(0, "sparse", &ctx.sparse, N_("Restrict the missing objects to the current sparse-checkout")), OPT_END(), diff --git a/builtin/blame.c b/builtin/blame.c index c470654c7e..944952e30e 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -28,7 +28,7 @@ #include "line-log.h" #include "progress.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "pager.h" #include "blame.h" #include "refs.h" @@ -36,17 +36,17 @@ #include "tag.h" #include "write-or-die.h" -static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"); -static char annotate_usage[] = N_("git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>"); +static const char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"); +static const char annotate_usage[] = N_("git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>"); -static const char *blame_opt_usage[] = { +static const char *const blame_opt_usage[] = { blame_usage, "", N_("<rev-opts> are documented in git-rev-list(1)"), NULL }; -static const char *annotate_opt_usage[] = { +static const char *const annotate_opt_usage[] = { annotate_usage, "", N_("<rev-opts> are documented in git-rev-list(1)"), @@ -351,6 +351,19 @@ static void emit_porcelain_details(struct blame_origin *suspect, int repeat) write_filename_info(suspect); } +/* + * Information which needs to be printed per-line goes here. Any + * information which can be clubbed on a commit/file level, should + * be printed via 'emit_one_suspect_detail()'. + */ +static void emit_porcelain_per_line_details(struct blame_entry *ent) +{ + if (mark_unblamable_lines && ent->unblamable) + puts("unblamable"); + if (mark_ignored_lines && ent->ignored) + puts("ignored"); +} + static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent, int opt) { @@ -367,6 +380,7 @@ static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent, ent->lno + 1, ent->num_lines); emit_porcelain_details(suspect, repeat); + emit_porcelain_per_line_details(ent); cp = blame_nth_line(sb, ent->lno); for (cnt = 0; cnt < ent->num_lines; cnt++) { @@ -377,6 +391,7 @@ static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent, ent->lno + 1 + cnt); if (repeat) emit_porcelain_details(suspect, 1); + emit_porcelain_per_line_details(ent); } putchar('\t'); do { @@ -929,7 +944,7 @@ int cmd_blame(int argc, long anchor; long num_lines = 0; const char *str_usage = cmd_is_annotate ? annotate_usage : blame_usage; - const char **opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage; + const char *const *opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage; setup_default_color_by_age(); git_config(git_blame_config, &output_option); diff --git a/builtin/bugreport.c b/builtin/bugreport.c index 66d64bfd5a..f78c3f2aed 100644 --- a/builtin/bugreport.c +++ b/builtin/bugreport.c @@ -4,13 +4,13 @@ #include "editor.h" #include "gettext.h" #include "parse-options.h" +#include "path.h" #include "strbuf.h" #include "help.h" #include "compat/compiler.h" #include "hook.h" #include "hook-list.h" #include "diagnose.h" -#include "object-file.h" #include "setup.h" #include "version.h" @@ -141,7 +141,7 @@ int cmd_bugreport(int argc, } strbuf_addstr(&report_path, ".txt"); - switch (safe_create_leading_directories(report_path.buf)) { + switch (safe_create_leading_directories(the_repository, report_path.buf)) { case SCLD_OK: case SCLD_EXISTS: break; diff --git a/builtin/cat-file.c b/builtin/cat-file.c index b13561cf73..4b23fcecbd 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -15,14 +15,16 @@ #include "gettext.h" #include "hex.h" #include "ident.h" +#include "list-objects-filter-options.h" #include "parse-options.h" #include "userdiff.h" #include "streaming.h" #include "oid-array.h" #include "packfile.h" +#include "pack-bitmap.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "replace-object.h" #include "promisor-remote.h" #include "mailmap.h" @@ -35,6 +37,7 @@ enum batch_mode { }; struct batch_options { + struct list_objects_filter_options objects_filter; int enabled; int follow_symlinks; enum batch_mode batch_mode; @@ -97,8 +100,7 @@ static int stream_blob(const struct object_id *oid) return 0; } -static int cat_one_file(int opt, const char *exp_type, const char *obj_name, - int unknown_type) +static int cat_one_file(int opt, const char *exp_type, const char *obj_name) { int ret; struct object_id oid; @@ -107,7 +109,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, unsigned long size; struct object_context obj_context = {0}; 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 | @@ -118,9 +119,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, if (!path && opt_cw) get_oid_flags |= GET_OID_REQUIRE_PATH; - if (unknown_type) - flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE; - if (get_oid_with_context(the_repository, obj_name, get_oid_flags, &oid, &obj_context)) die("Not a valid object name %s", obj_name); @@ -133,16 +131,12 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, buf = NULL; switch (opt) { case 't': - oi.type_name = &sb; + oi.typep = &type; if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0) die("git cat-file: could not get object info"); - if (sb.len) { - printf("%s\n", sb.buf); - strbuf_release(&sb); - ret = 0; - goto cleanup; - } - break; + printf("%s\n", type_name(type)); + ret = 0; + goto cleanup; case 's': oi.sizep = &size; @@ -166,7 +160,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, goto cleanup; case 'e': - ret = !repo_has_object_file(the_repository, &oid); + ret = !has_object(the_repository, &oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR); goto cleanup; case 'w': @@ -280,6 +275,7 @@ struct expand_data { struct object_id oid; enum object_type type; unsigned long size; + unsigned short mode; off_t disk_size; const char *rest; struct object_id delta_base_oid; @@ -311,6 +307,7 @@ struct expand_data { */ unsigned skip_object_info : 1; }; +#define EXPAND_DATA_INIT { .mode = S_IFINVALID } static int is_atom(const char *atom, const char *s, int slen) { @@ -350,6 +347,9 @@ static int expand_atom(struct strbuf *sb, const char *atom, int len, else strbuf_addstr(sb, oid_to_hex(&data->delta_base_oid)); + } else if (is_atom("objectmode", atom, len)) { + if (!data->mark_query && !(S_IFINVALID == data->mode)) + strbuf_addf(sb, "%06o", data->mode); } else return 0; return 1; @@ -455,6 +455,16 @@ static void print_default_format(struct strbuf *scratch, struct expand_data *dat (uintmax_t)data->size, opt->output_delim); } +static void report_object_status(struct batch_options *opt, + const char *obj_name, + const struct object_id *oid, + const char *status) +{ + printf("%s %s%c", obj_name ? obj_name : oid_to_hex(oid), + status, opt->output_delim); + fflush(stdout); +} + /* * If "pack" is non-NULL, then "offset" is the byte offset within the pack from * which the object may be accessed (though note that we may also rely on @@ -470,8 +480,13 @@ static void batch_object_write(const char *obj_name, if (!data->skip_object_info) { int ret; - if (use_mailmap) + if (use_mailmap || + opt->objects_filter.choice == LOFC_BLOB_NONE || + opt->objects_filter.choice == LOFC_BLOB_LIMIT || + opt->objects_filter.choice == LOFC_OBJECT_TYPE) data->info.typep = &data->type; + if (opt->objects_filter.choice == LOFC_BLOB_LIMIT) + data->info.sizep = &data->size; if (pack) ret = packed_object_info(the_repository, pack, offset, @@ -481,12 +496,45 @@ static void batch_object_write(const char *obj_name, &data->oid, &data->info, OBJECT_INFO_LOOKUP_REPLACE); if (ret < 0) { - printf("%s missing%c", - obj_name ? obj_name : oid_to_hex(&data->oid), opt->output_delim); - fflush(stdout); + if (data->mode == S_IFGITLINK) + report_object_status(opt, oid_to_hex(&data->oid), &data->oid, "submodule"); + else + report_object_status(opt, obj_name, &data->oid, "missing"); return; } + switch (opt->objects_filter.choice) { + case LOFC_DISABLED: + break; + case LOFC_BLOB_NONE: + if (data->type == OBJ_BLOB) { + if (!opt->all_objects) + report_object_status(opt, obj_name, + &data->oid, "excluded"); + return; + } + break; + case LOFC_BLOB_LIMIT: + if (data->type == OBJ_BLOB && + data->size >= opt->objects_filter.blob_limit_value) { + if (!opt->all_objects) + report_object_status(opt, obj_name, + &data->oid, "excluded"); + return; + } + break; + case LOFC_OBJECT_TYPE: + if (data->type != opt->objects_filter.object_type) { + if (!opt->all_objects) + report_object_status(opt, obj_name, + &data->oid, "excluded"); + return; + } + break; + default: + BUG("unsupported objects filter"); + } + if (use_mailmap && (data->type == OBJ_COMMIT || data->type == OBJ_TAG)) { size_t s = data->size; char *buf = NULL; @@ -535,10 +583,10 @@ static void batch_one_object(const char *obj_name, if (result != FOUND) { switch (result) { case MISSING_OBJECT: - printf("%s missing%c", obj_name, opt->output_delim); + report_object_status(opt, obj_name, &data->oid, "missing"); break; case SHORT_NAME_AMBIGUOUS: - printf("%s ambiguous%c", obj_name, opt->output_delim); + report_object_status(opt, obj_name, &data->oid, "ambiguous"); break; case DANGLING_SYMLINK: printf("dangling %"PRIuMAX"%c%s%c", @@ -573,6 +621,7 @@ static void batch_one_object(const char *obj_name, goto out; } + data->mode = ctx.mode; batch_object_write(obj_name, scratch, opt, data, NULL, 0); out: @@ -595,25 +644,18 @@ static int batch_object_cb(const struct object_id *oid, void *vdata) return 0; } -static int collect_loose_object(const struct object_id *oid, - const char *path UNUSED, - void *data) -{ - oid_array_append(data, oid); - return 0; -} - -static int collect_packed_object(const struct object_id *oid, - struct packed_git *pack UNUSED, - uint32_t pos UNUSED, - void *data) +static int collect_object(const struct object_id *oid, + struct packed_git *pack UNUSED, + off_t offset UNUSED, + void *data) { oid_array_append(data, oid); return 0; } static int batch_unordered_object(const struct object_id *oid, - struct packed_git *pack, off_t offset, + struct packed_git *pack, + off_t offset, void *vdata) { struct object_cb_data *data = vdata; @@ -627,23 +669,6 @@ static int batch_unordered_object(const struct object_id *oid, return 0; } -static int batch_unordered_loose(const struct object_id *oid, - const char *path UNUSED, - void *data) -{ - return batch_unordered_object(oid, NULL, 0, data); -} - -static int batch_unordered_packed(const struct object_id *oid, - struct packed_git *pack, - uint32_t pos, - void *data) -{ - return batch_unordered_object(oid, pack, - nth_packed_object_offset(pack, pos), - data); -} - typedef void (*parse_cmd_fn_t)(struct batch_options *, const char *, struct strbuf *, struct expand_data *); @@ -776,11 +801,81 @@ static void batch_objects_command(struct batch_options *opt, #define DEFAULT_FORMAT "%(objectname) %(objecttype) %(objectsize)" +typedef int (*for_each_object_fn)(const struct object_id *oid, struct packed_git *pack, + off_t offset, void *data); + +struct for_each_object_payload { + for_each_object_fn callback; + void *payload; +}; + +static int batch_one_object_loose(const struct object_id *oid, + const char *path UNUSED, + void *_payload) +{ + struct for_each_object_payload *payload = _payload; + return payload->callback(oid, NULL, 0, payload->payload); +} + +static int batch_one_object_packed(const struct object_id *oid, + struct packed_git *pack, + uint32_t pos, + void *_payload) +{ + struct for_each_object_payload *payload = _payload; + return payload->callback(oid, pack, nth_packed_object_offset(pack, pos), + payload->payload); +} + +static int batch_one_object_bitmapped(const struct object_id *oid, + enum object_type type UNUSED, + int flags UNUSED, + uint32_t hash UNUSED, + struct packed_git *pack, + off_t offset, + void *_payload) +{ + struct for_each_object_payload *payload = _payload; + return payload->callback(oid, pack, offset, payload->payload); +} + +static void batch_each_object(struct batch_options *opt, + for_each_object_fn callback, + unsigned flags, + void *_payload) +{ + struct for_each_object_payload payload = { + .callback = callback, + .payload = _payload, + }; + struct bitmap_index *bitmap = prepare_bitmap_git(the_repository); + + for_each_loose_object(batch_one_object_loose, &payload, 0); + + if (bitmap && !for_each_bitmapped_object(bitmap, &opt->objects_filter, + batch_one_object_bitmapped, &payload)) { + struct packed_git *pack; + + for (pack = get_all_packs(the_repository); pack; pack = pack->next) { + if (bitmap_index_contains_pack(bitmap, pack) || + open_pack_index(pack)) + continue; + for_each_object_in_pack(pack, batch_one_object_packed, + &payload, flags); + } + } else { + for_each_packed_object(the_repository, batch_one_object_packed, + &payload, flags); + } + + free_bitmap_index(bitmap); +} + static int batch_objects(struct batch_options *opt) { struct strbuf input = STRBUF_INIT; struct strbuf output = STRBUF_INIT; - struct expand_data data; + struct expand_data data = EXPAND_DATA_INIT; int save_warning; int retval = 0; @@ -789,7 +884,6 @@ static int batch_objects(struct batch_options *opt) * object_info to be handed to oid_object_info_extended for each * object. */ - memset(&data, 0, sizeof(data)); data.mark_query = 1; expand_format(&output, opt->format ? opt->format : DEFAULT_FORMAT, @@ -812,7 +906,8 @@ static int batch_objects(struct batch_options *opt) struct object_cb_data cb; struct object_info empty = OBJECT_INFO_INIT; - if (!memcmp(&data.info, &empty, sizeof(empty))) + if (!memcmp(&data.info, &empty, sizeof(empty)) && + opt->objects_filter.choice == LOFC_DISABLED) data.skip_object_info = 1; if (repo_has_promisor_remote(the_repository)) @@ -829,18 +924,14 @@ static int batch_objects(struct batch_options *opt) cb.seen = &seen; - for_each_loose_object(batch_unordered_loose, &cb, 0); - for_each_packed_object(the_repository, batch_unordered_packed, - &cb, FOR_EACH_OBJECT_PACK_ORDER); + batch_each_object(opt, batch_unordered_object, + FOR_EACH_OBJECT_PACK_ORDER, &cb); oidset_clear(&seen); } else { struct oid_array sa = OID_ARRAY_INIT; - for_each_loose_object(collect_loose_object, &sa, 0); - for_each_packed_object(the_repository, collect_packed_object, - &sa, 0); - + batch_each_object(opt, collect_object, 0, &sa); oid_array_for_each_unique(&sa, batch_object_cb, &cb); oid_array_clear(&sa); @@ -936,15 +1027,17 @@ int cmd_cat_file(int argc, int opt_cw = 0; int opt_epts = 0; const char *exp_type = NULL, *obj_name = NULL; - struct batch_options batch = {0}; + struct batch_options batch = { + .objects_filter = LIST_OBJECTS_FILTER_INIT, + }; int unknown_type = 0; int input_nul_terminated = 0; int nul_terminated = 0; + int ret; - const char * const usage[] = { + const char * const builtin_catfile_usage[] = { N_("git cat-file <type> <object>"), - N_("git cat-file (-e | -p) <object>"), - N_("git cat-file (-t | -s) [--allow-unknown-type] <object>"), + N_("git cat-file (-e | -p | -t | -s) <object>"), N_("git cat-file (--textconv | --filters)\n" " [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"), N_("git cat-file (--batch | --batch-check | --batch-command) [--batch-all-objects]\n" @@ -962,8 +1055,8 @@ int cmd_cat_file(int argc, OPT_GROUP(N_("Emit [broken] object attributes")), OPT_CMDMODE('t', NULL, &opt, N_("show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"), 't'), OPT_CMDMODE('s', NULL, &opt, N_("show object size"), 's'), - OPT_BOOL(0, "allow-unknown-type", &unknown_type, - N_("allow -s and -t to work with broken/corrupt objects")), + OPT_HIDDEN_BOOL(0, "allow-unknown-type", &unknown_type, + N_("historical option -- no-op")), OPT_BOOL(0, "use-mailmap", &use_mailmap, N_("use mail map file")), OPT_ALIAS(0, "mailmap", "use-mailmap"), /* Batch mode */ @@ -1000,6 +1093,7 @@ int cmd_cat_file(int argc, N_("run filters on object's content"), 'w'), OPT_STRING(0, "path", &force_path, N_("blob|tree"), N_("use a <path> for (--textconv | --filters); Not with 'batch'")), + OPT_PARSE_LIST_OBJECTS_FILTER(&batch.objects_filter), OPT_END() }; @@ -1007,13 +1101,27 @@ int cmd_cat_file(int argc, batch.buffer_output = -1; - argc = parse_options(argc, argv, prefix, options, usage, 0); + argc = parse_options(argc, argv, prefix, options, builtin_catfile_usage, 0); opt_cw = (opt == 'c' || opt == 'w'); opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); if (use_mailmap) read_mailmap(&mailmap); + switch (batch.objects_filter.choice) { + case LOFC_DISABLED: + break; + case LOFC_BLOB_NONE: + case LOFC_BLOB_LIMIT: + case LOFC_OBJECT_TYPE: + if (!batch.enabled) + usage(_("objects filter only supported in batch mode")); + break; + default: + usagef(_("objects filter not supported: '%s'"), + list_object_filter_config_name(batch.objects_filter.choice)); + } + /* --batch-all-objects? */ if (opt == 'b') batch.all_objects = 1; @@ -1021,7 +1129,7 @@ int cmd_cat_file(int argc, /* Option compatibility */ if (force_path && !opt_cw) usage_msg_optf(_("'%s=<%s>' needs '%s' or '%s'"), - usage, options, + builtin_catfile_usage, options, "--path", _("path|tree-ish"), "--filters", "--textconv"); @@ -1029,20 +1137,20 @@ int cmd_cat_file(int argc, if (batch.enabled) ; else if (batch.follow_symlinks) - usage_msg_optf(_("'%s' requires a batch mode"), usage, options, - "--follow-symlinks"); + usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage, + options, "--follow-symlinks"); else if (batch.buffer_output >= 0) - usage_msg_optf(_("'%s' requires a batch mode"), usage, options, - "--buffer"); + usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage, + options, "--buffer"); else if (batch.all_objects) - usage_msg_optf(_("'%s' requires a batch mode"), usage, options, - "--batch-all-objects"); + usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage, + options, "--batch-all-objects"); else if (input_nul_terminated) - usage_msg_optf(_("'%s' requires a batch mode"), usage, options, - "-z"); + usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage, + options, "-z"); else if (nul_terminated) - usage_msg_optf(_("'%s' requires a batch mode"), usage, options, - "-Z"); + usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage, + options, "-Z"); batch.input_delim = batch.output_delim = '\n'; if (input_nul_terminated) @@ -1063,39 +1171,45 @@ int cmd_cat_file(int argc, batch.transform_mode = opt; else if (opt && opt != 'b') usage_msg_optf(_("'-%c' is incompatible with batch mode"), - usage, options, opt); + builtin_catfile_usage, options, opt); else if (argc) - usage_msg_opt(_("batch modes take no arguments"), usage, - options); + usage_msg_opt(_("batch modes take no arguments"), + builtin_catfile_usage, options); - return batch_objects(&batch); + ret = batch_objects(&batch); + goto out; } if (opt) { if (!argc && opt == 'c') usage_msg_optf(_("<rev> required with '%s'"), - usage, options, "--textconv"); + builtin_catfile_usage, options, + "--textconv"); else if (!argc && opt == 'w') usage_msg_optf(_("<rev> required with '%s'"), - usage, options, "--filters"); + builtin_catfile_usage, options, + "--filters"); else if (!argc && opt_epts) usage_msg_optf(_("<object> required with '-%c'"), - usage, options, opt); + builtin_catfile_usage, options, opt); else if (argc == 1) obj_name = argv[0]; else - usage_msg_opt(_("too many arguments"), usage, options); + usage_msg_opt(_("too many arguments"), builtin_catfile_usage, + options); } else if (!argc) { - usage_with_options(usage, options); + usage_with_options(builtin_catfile_usage, options); } else if (argc != 2) { usage_msg_optf(_("only two arguments allowed in <type> <object> mode, not %d"), - usage, options, argc); + builtin_catfile_usage, options, argc); } else if (argc) { exp_type = argv[0]; obj_name = argv[1]; } - if (unknown_type && opt != 't' && opt != 's') - die("git cat-file --allow-unknown-type: use with -s or -t"); - return cat_one_file(opt, exp_type, obj_name, unknown_type); + ret = cat_one_file(opt, exp_type, obj_name); + +out: + list_objects_filter_release(&batch.objects_filter); + return ret; } diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index e30086c7d4..7f74bc702f 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -5,7 +5,6 @@ * */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -68,10 +67,10 @@ static void write_tempfile_record(const char *name, const char *prefix) } } -static int checkout_file(const char *name, const char *prefix) +static int checkout_file(struct index_state *index, const char *name, const char *prefix) { int namelen = strlen(name); - int pos = index_name_pos(the_repository->index, name, namelen); + int pos = index_name_pos(index, name, namelen); int has_same_name = 0; int is_file = 0; int is_skipped = 1; @@ -81,8 +80,8 @@ static int checkout_file(const char *name, const char *prefix) if (pos < 0) pos = -pos - 1; - while (pos <the_repository->index->cache_nr) { - struct cache_entry *ce =the_repository->index->cache[pos]; + while (pos < index->cache_nr) { + struct cache_entry *ce = index->cache[pos]; if (ce_namelen(ce) != namelen || memcmp(ce->name, name, namelen)) break; @@ -137,13 +136,13 @@ static int checkout_file(const char *name, const char *prefix) return -1; } -static int checkout_all(const char *prefix, int prefix_length) +static int checkout_all(struct index_state *index, const char *prefix, int prefix_length) { int i, errs = 0; struct cache_entry *last_ce = NULL; - for (i = 0; i < the_repository->index->cache_nr ; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < index->cache_nr ; i++) { + struct cache_entry *ce = index->cache[i]; if (S_ISSPARSEDIR(ce->ce_mode)) { if (!ce_skip_worktree(ce)) @@ -156,8 +155,8 @@ static int checkout_all(const char *prefix, int prefix_length) * first entry inside the expanded sparse directory). */ if (ignore_skip_worktree) { - ensure_full_index(the_repository->index); - ce = the_repository->index->cache[i]; + ensure_full_index(index); + ce = index->cache[i]; } } @@ -213,7 +212,7 @@ static int option_parse_stage(const struct option *opt, int cmd_checkout_index(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i; struct lock_file lock_file = LOCK_INIT; @@ -253,19 +252,19 @@ int cmd_checkout_index(int argc, show_usage_with_options_if_asked(argc, argv, builtin_checkout_index_usage, builtin_checkout_index_options); - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); prefix_length = prefix ? strlen(prefix) : 0; - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; - if (repo_read_index(the_repository) < 0) { + if (repo_read_index(repo) < 0) { die("invalid cache"); } argc = parse_options(argc, argv, prefix, builtin_checkout_index_options, builtin_checkout_index_usage, 0); - state.istate = the_repository->index; + state.istate = repo->index; state.force = force; state.quiet = quiet; state.not_new = not_new; @@ -285,8 +284,8 @@ int cmd_checkout_index(int argc, */ if (index_opt && !state.base_dir_len && !to_tempfile) { state.refresh_cache = 1; - state.istate = the_repository->index; - repo_hold_locked_index(the_repository, &lock_file, + state.istate = repo->index; + repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR); } @@ -304,7 +303,7 @@ int cmd_checkout_index(int argc, if (read_from_stdin) die("git checkout-index: don't mix '--stdin' and explicit filenames"); p = prefix_path(prefix, prefix_length, arg); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } @@ -326,7 +325,7 @@ int cmd_checkout_index(int argc, strbuf_swap(&buf, &unquoted); } p = prefix_path(prefix, prefix_length, buf.buf); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } strbuf_release(&unquoted); @@ -334,7 +333,7 @@ int cmd_checkout_index(int argc, } if (all) - err |= checkout_all(prefix, prefix_length); + err |= checkout_all(repo->index, prefix, prefix_length); if (pc_workers > 1) err |= run_parallel_checkout(&state, pc_workers, pc_threshold, @@ -344,7 +343,7 @@ int cmd_checkout_index(int argc, return 1; if (is_lock_file_locked(&lock_file) && - write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) + write_locked_index(repo->index, &lock_file, COMMIT_LOCK)) die("Unable to write new index file"); return 0; } diff --git a/builtin/checkout.c b/builtin/checkout.c index 01ea9ff8b2..d185982f3a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -17,9 +17,10 @@ #include "merge-ll.h" #include "lockfile.h" #include "mem-pool.h" -#include "merge-recursive.h" +#include "merge-ort-wrappers.h" +#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "parse-options.h" #include "path.h" #include "preload-index.h" @@ -130,8 +131,8 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm int changed) { return run_hooks_l(the_repository, "post-checkout", - oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()), - oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()), + oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)), + oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)), changed ? "1" : "0", NULL); /* "new_commit" can be NULL when checking out from the index before a commit exists. */ @@ -710,7 +711,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o, opts.src_index = the_repository->index; opts.dst_index = the_repository->index; init_checkout_metadata(&opts.meta, info->refname, - info->commit ? &info->commit->object.oid : null_oid(), + info->commit ? &info->commit->object.oid : null_oid(the_hash_algo), NULL); if (parse_tree(tree) < 0) return 128; @@ -907,10 +908,10 @@ 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, - old_tree); + ret = merge_ort_nonrecursive(&o, + new_tree, + work, + old_tree); if (ret < 0) exit(128); ret = reset_tree(new_tree, diff --git a/builtin/clone.c b/builtin/clone.c index f14229abf4..91b9cd0d16 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -25,7 +25,7 @@ #include "refs.h" #include "refspec.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "tree.h" #include "tree-walk.h" #include "unpack-trees.h" @@ -342,6 +342,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, strbuf_setlen(src, src_len); die(_("failed to iterate over '%s'"), src->buf); } + + dir_iterator_free(iter); } static void clone_local(const char *src_repo, const char *dest_repo) @@ -450,7 +452,9 @@ static struct ref *wanted_peer_refs(struct clone_opts *opts, if (head) tail_link_ref(head, &tail); if (option_single_branch) - refs = to_free = guess_remote_head(head, refs, 0); + refs = to_free = + guess_remote_head(head, refs, + REMOTE_GUESS_HEAD_QUIET); } else if (option_single_branch) { local_refs = NULL; tail = &local_refs; @@ -500,9 +504,7 @@ static void write_followtags(const struct ref *refs, const char *msg) continue; if (ends_with(ref->name, "^{}")) continue; - if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid, - OBJECT_INFO_QUICK | - OBJECT_INFO_SKIP_FETCH_OBJECT)) + if (!has_object(the_repository, &ref->old_oid, 0)) continue; refs_update_ref(get_main_ref_store(the_repository), msg, ref->name, &ref->old_oid, NULL, 0, @@ -690,7 +692,7 @@ static int checkout(int submodule_progress, int filter_submodules, if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); - err |= run_hooks_l(the_repository, "post-checkout", oid_to_hex(null_oid()), + err |= run_hooks_l(the_repository, "post-checkout", oid_to_hex(null_oid(the_hash_algo)), oid_to_hex(&oid), "1", NULL); if (!err && (option_recurse_submodules.nr > 0)) { @@ -928,9 +930,16 @@ int cmd_clone(int argc, N_("don't use local hardlinks, always copy")), OPT_BOOL('s', "shared", &option_shared, N_("setup as shared repository")), - { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules, - N_("pathspec"), N_("initialize submodules in the clone"), - PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." }, + { + .type = OPTION_CALLBACK, + .long_name = "recurse-submodules", + .value = &option_recurse_submodules, + .argh = N_("pathspec"), + .help = N_("initialize submodules in the clone"), + .flags = PARSE_OPT_OPTARG, + .callback = recurse_submodules_cb, + .defval = (intptr_t)".", + }, OPT_ALIAS(0, "recursive", "recurse-submodules"), OPT_INTEGER('j', "jobs", &max_jobs, N_("number of submodules cloned in parallel")), @@ -1088,7 +1097,7 @@ int cmd_clone(int argc, sigchain_push_common(remove_junk_on_signal); if (!option_bare) { - if (safe_create_leading_directories_const(work_tree) < 0) + if (safe_create_leading_directories_const(the_repository, work_tree) < 0) die_errno(_("could not create leading directories of '%s'"), work_tree); if (dest_exists) @@ -1109,7 +1118,7 @@ int cmd_clone(int argc, junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL; junk_git_dir = git_dir; } - if (safe_create_leading_directories_const(git_dir) < 0) + if (safe_create_leading_directories_const(the_repository, git_dir) < 0) die(_("could not create leading directories of '%s'"), git_dir); if (0 <= option_verbosity) { @@ -1523,7 +1532,8 @@ int cmd_clone(int argc, } remote_head = find_ref_by_name(refs, "HEAD"); - remote_head_points_at = guess_remote_head(remote_head, mapped_refs, 0); + remote_head_points_at = guess_remote_head(remote_head, mapped_refs, + REMOTE_GUESS_HEAD_QUIET); if (option_branch) { our_head_points_at = find_remote_branch(mapped_refs, option_branch); diff --git a/builtin/column.c b/builtin/column.c index 50314cc255..ce6443d5fa 100644 --- a/builtin/column.c +++ b/builtin/column.c @@ -31,7 +31,7 @@ int cmd_column(int argc, struct option options[] = { OPT_STRING(0, "command", &real_command, N_("name"), N_("lookup config vars")), OPT_COLUMN(0, "mode", &colopts, N_("layout to use")), - OPT_INTEGER(0, "raw-mode", &colopts, N_("layout to use")), + OPT_UNSIGNED(0, "raw-mode", &colopts, N_("layout to use")), OPT_INTEGER(0, "width", &copts.width, N_("maximum width")), OPT_STRING(0, "indent", &copts.indent, N_("string"), N_("padding space on left border")), OPT_STRING(0, "nl", &copts.nl, N_("string"), N_("padding space on right border")), diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 8ca75262c5..ee48980248 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -6,7 +6,7 @@ #include "hex.h" #include "parse-options.h" #include "commit-graph.h" -#include "object-store-ll.h" +#include "object-store.h" #include "progress.h" #include "replace-object.h" #include "strbuf.h" @@ -22,12 +22,12 @@ " [--changed-paths] [--[no-]max-new-filters <n>] [--[no-]progress]\n" \ " <split-options>") -static const char * builtin_commit_graph_verify_usage[] = { +static const char * const builtin_commit_graph_verify_usage[] = { BUILTIN_COMMIT_GRAPH_VERIFY_USAGE, NULL }; -static const char * builtin_commit_graph_write_usage[] = { +static const char * const builtin_commit_graph_write_usage[] = { BUILTIN_COMMIT_GRAPH_WRITE_USAGE, NULL }; @@ -311,6 +311,7 @@ static int graph_write(int argc, const char **argv, const char *prefix, while (strbuf_getline(&buf, stdin) != EOF) { if (read_one_commit(&commits, progress, buf.buf)) { result = 1; + stop_progress(&progress); goto cleanup; } } diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 38457600a4..ad6b2c9320 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -9,7 +9,7 @@ #include "gettext.h" #include "hex.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "parse-options.h" @@ -111,8 +111,16 @@ int cmd_commit_tree(int argc, OPT_CALLBACK_F('F', NULL, &buffer, N_("file"), N_("read commit log message from file"), PARSE_OPT_NONEG, parse_file_arg_callback), - { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"), - N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, + { + .type = OPTION_STRING, + .short_name = 'S', + .long_name = "gpg-sign", + .value = &sign_commit, + .argh = N_("key-id"), + .help = N_("GPG sign commit"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "", + }, OPT_END() }; int ret; diff --git a/builtin/commit.c b/builtin/commit.c index 2f45968222..fba0dded64 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1022,7 +1022,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, for (i = 0; i < the_repository->index->cache_nr; i++) if (ce_intent_to_add(the_repository->index->cache[i])) ita_nr++; - committable = the_repository->index->cache_nr - ita_nr > 0; + committable = the_repository->index->cache_nr > ita_nr; } else { /* * Unless the user did explicitly request a submodule @@ -1542,17 +1542,34 @@ struct repository *repo UNUSED) STATUS_FORMAT_LONG), OPT_BOOL('z', "null", &s.null_termination, N_("terminate entries with NUL")), - { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, - N_("mode"), - N_("show untracked files, optional modes: all, normal, no. (Default: all)"), - PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, - { OPTION_STRING, 0, "ignored", &ignored_arg, - N_("mode"), - N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"), - PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, - { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"), - N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"), - PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, + { + .type = OPTION_STRING, + .short_name = 'u', + .long_name = "untracked-files", + .value = &untracked_files_arg, + .argh = N_("mode"), + .help = N_("show untracked files, optional modes: all, normal, no. (Default: all)"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t)"all", + }, + { + .type = OPTION_STRING, + .long_name = "ignored", + .value = &ignored_arg, + .argh = N_("mode"), + .help = N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t)"traditional", + }, + { + .type = OPTION_STRING, + .long_name = "ignore-submodules", + .value = &ignore_submodule_arg, + .argh = N_("when"), + .help = N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t)"all", + }, OPT_COLUMN(0, "column", &s.colopts, N_("list untracked files in columns")), OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")), OPT_CALLBACK_F('M', "find-renames", &rename_score_arg, @@ -1688,8 +1705,16 @@ int cmd_commit(int argc, OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")), OPT_CLEANUP(&cleanup_arg), OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")), - { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"), - N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, + { + .type = OPTION_STRING, + .short_name = 'S', + .long_name = "gpg-sign", + .value = &sign_commit, + .argh = N_("key-id"), + .help = N_("GPG sign commit"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "", + }, /* end commit message options */ OPT_GROUP(N_("Commit contents options")), @@ -1714,7 +1739,16 @@ int cmd_commit(int argc, N_("terminate entries with NUL")), OPT_BOOL(0, "amend", &amend, N_("amend previous commit")), OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")), - { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, + { + .type = OPTION_STRING, + .short_name = 'u', + .long_name = "untracked-files", + .value = &untracked_files_arg, + .argh = N_("mode"), + .help = N_("show untracked files, optional modes: all, normal, no. (Default: all)"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t)"all", + }, OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), /* end commit contents options */ diff --git a/builtin/config.c b/builtin/config.c index 53a90094e3..f70d635477 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -131,9 +131,16 @@ struct config_display_options { #define TYPE_COLOR 6 #define TYPE_BOOL_OR_STR 7 -#define OPT_CALLBACK_VALUE(s, l, v, h, i) \ - { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \ - PARSE_OPT_NONEG, option_parse_type, (i) } +#define OPT_CALLBACK_VALUE(s, l, v, h, i) { \ + .type = OPTION_CALLBACK, \ + .short_name = (s), \ + .long_name = (l), \ + .value = (v), \ + .help = (h), \ + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, \ + .callback = option_parse_type, \ + .defval = (i), \ +} static int option_parse_type(const struct option *opt, const char *arg, int unset) diff --git a/builtin/count-objects.c b/builtin/count-objects.c index 1e89148ed7..a88c0c9c09 100644 --- a/builtin/count-objects.c +++ b/builtin/count-objects.c @@ -12,7 +12,7 @@ #include "parse-options.h" #include "quote.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-file.h" static unsigned long garbage; static off_t size_garbage; diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c index e707618e74..5065ff4660 100644 --- a/builtin/credential-cache--daemon.c +++ b/builtin/credential-cache--daemon.c @@ -2,8 +2,8 @@ #include "builtin.h" #include "abspath.h" #include "gettext.h" -#include "object-file.h" #include "parse-options.h" +#include "path.h" #ifndef NO_UNIX_SOCKETS @@ -271,7 +271,7 @@ static void init_socket_directory(const char *path) * condition in which somebody can chdir to it, sleep, then try to open * our protected socket. */ - if (safe_create_leading_directories_const(dir) < 0) + if (safe_create_leading_directories_const(the_repository, dir) < 0) die_errno("unable to create directories for '%s'", dir); if (mkdir(dir, 0700) < 0) die_errno("unable to mkdir '%s'", dir); diff --git a/builtin/describe.c b/builtin/describe.c index e2e73f3d75..2d50883b72 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -19,7 +19,7 @@ #include "setup.h" #include "strvec.h" #include "run-command.h" -#include "object-store-ll.h" +#include "object-store.h" #include "list-objects.h" #include "commit-slab.h" #include "wildmatch.h" @@ -518,7 +518,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst) { struct rev_info revs; struct strvec args = STRVEC_INIT; - struct process_commit_data pcd = { *null_oid(), oid, dst, &revs}; + struct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs}; strvec_pushl(&args, "internal: The first arg is not parsed", "--objects", "--in-commit-order", "--reverse", "HEAD", @@ -601,12 +601,24 @@ int cmd_describe(int argc, N_("do not consider tags matching <pattern>")), OPT_BOOL(0, "always", &always, N_("show abbreviated commit object as fallback")), - {OPTION_STRING, 0, "dirty", &dirty, N_("mark"), - N_("append <mark> on dirty working tree (default: \"-dirty\")"), - PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"}, - {OPTION_STRING, 0, "broken", &broken, N_("mark"), - N_("append <mark> on broken working tree (default: \"-broken\")"), - PARSE_OPT_OPTARG, NULL, (intptr_t) "-broken"}, + { + .type = OPTION_STRING, + .long_name = "dirty", + .value = &dirty, + .argh = N_("mark"), + .help = N_("append <mark> on dirty working tree (default: \"-dirty\")"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "-dirty", + }, + { + .type = OPTION_STRING, + .long_name = "broken", + .value = &broken, + .argh = N_("mark"), + .help = N_("append <mark> on broken working tree (default: \"-broken\")"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "-broken", + }, OPT_END(), }; diff --git a/builtin/diagnose.c b/builtin/diagnose.c index 33c39bd598..ec86d66389 100644 --- a/builtin/diagnose.c +++ b/builtin/diagnose.c @@ -3,8 +3,8 @@ #include "builtin.h" #include "abspath.h" #include "gettext.h" -#include "object-file.h" #include "parse-options.h" +#include "path.h" #include "diagnose.h" static const char * const diagnose_usage[] = { @@ -50,7 +50,7 @@ int cmd_diagnose(int argc, strbuf_addftime(&zip_path, option_suffix, localtime_r(&now, &tm), 0, 0); strbuf_addstr(&zip_path, ".zip"); - switch (safe_create_leading_directories(zip_path.buf)) { + switch (safe_create_leading_directories(the_repository, zip_path.buf)) { case SCLD_OK: case SCLD_EXISTS: break; diff --git a/builtin/diff-pairs.c b/builtin/diff-pairs.c new file mode 100644 index 0000000000..71c045331a --- /dev/null +++ b/builtin/diff-pairs.c @@ -0,0 +1,207 @@ +#include "builtin.h" +#include "config.h" +#include "diff.h" +#include "diffcore.h" +#include "gettext.h" +#include "hash.h" +#include "hex.h" +#include "object.h" +#include "parse-options.h" +#include "revision.h" +#include "strbuf.h" + +static unsigned parse_mode_or_die(const char *mode, const char **end) +{ + uint16_t ret; + + *end = parse_mode(mode, &ret); + if (!*end) + die(_("unable to parse mode: %s"), mode); + return ret; +} + +static void parse_oid_or_die(const char *hex, struct object_id *oid, + const char **end, const struct git_hash_algo *algop) +{ + if (parse_oid_hex_algop(hex, oid, end, algop) || *(*end)++ != ' ') + die(_("unable to parse object id: %s"), hex); +} + +int cmd_diff_pairs(int argc, const char **argv, const char *prefix, + struct repository *repo) +{ + struct strbuf path_dst = STRBUF_INIT; + struct strbuf path = STRBUF_INIT; + struct strbuf meta = STRBUF_INIT; + struct option *parseopts; + struct rev_info revs; + int line_term = '\0'; + int ret; + + const char * const builtin_diff_pairs_usage[] = { + N_("git diff-pairs -z [<diff-options>]"), + NULL + }; + struct option builtin_diff_pairs_options[] = { + OPT_END() + }; + + repo_init_revisions(repo, &revs, prefix); + + /* + * Diff options are usually parsed implicitly as part of + * setup_revisions(). Explicitly handle parsing to ensure options are + * printed in the usage message. + */ + parseopts = add_diff_options(builtin_diff_pairs_options, &revs.diffopt); + show_usage_with_options_if_asked(argc, argv, builtin_diff_pairs_usage, parseopts); + + repo_config(repo, git_diff_basic_config, NULL); + revs.diffopt.no_free = 1; + revs.disable_stdin = 1; + revs.abbrev = 0; + revs.diff = 1; + + argc = parse_options(argc, argv, prefix, parseopts, builtin_diff_pairs_usage, + PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_DASHDASH); + + if (setup_revisions(argc, argv, &revs, NULL) > 1) + usagef(_("unrecognized argument: %s"), argv[0]); + + /* + * With the -z option, both command input and raw output are + * NUL-delimited (this mode does not affect patch output). At present + * only NUL-delimited raw diff formatted input is supported. + */ + if (revs.diffopt.line_termination) + usage(_("working without -z is not supported")); + + if (revs.prune_data.nr) + usage(_("pathspec arguments not supported")); + + if (revs.pending.nr || revs.max_count != -1 || + revs.min_age != (timestamp_t)-1 || + revs.max_age != (timestamp_t)-1) + usage(_("revision arguments not allowed")); + + if (!revs.diffopt.output_format) + revs.diffopt.output_format = DIFF_FORMAT_PATCH; + + /* + * If rename detection is not requested, use rename information from the + * raw diff formatted input. Setting skip_resolving_statuses ensures + * diffcore_std() does not mess with rename information already present + * in queued filepairs. + */ + if (!revs.diffopt.detect_rename) + revs.diffopt.skip_resolving_statuses = 1; + + while (1) { + struct object_id oid_a, oid_b; + struct diff_filepair *pair; + unsigned mode_a, mode_b; + const char *p; + char status; + + if (strbuf_getwholeline(&meta, stdin, line_term) == EOF) + break; + + p = meta.buf; + if (!*p) { + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + /* + * When the diff queue is explicitly flushed, append a + * NUL byte to separate batches of diffs. + */ + fputc('\0', revs.diffopt.file); + fflush(revs.diffopt.file); + continue; + } + + if (*p != ':') + die(_("invalid raw diff input")); + p++; + + mode_a = parse_mode_or_die(p, &p); + mode_b = parse_mode_or_die(p, &p); + + if (S_ISDIR(mode_a) || S_ISDIR(mode_b)) + die(_("tree objects not supported")); + + parse_oid_or_die(p, &oid_a, &p, repo->hash_algo); + parse_oid_or_die(p, &oid_b, &p, repo->hash_algo); + + status = *p++; + + if (strbuf_getwholeline(&path, stdin, line_term) == EOF) + die(_("got EOF while reading path")); + + switch (status) { + case DIFF_STATUS_ADDED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '+', mode_b, + &oid_b, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_DELETED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '-', mode_a, + &oid_a, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_TYPE_CHANGED: + case DIFF_STATUS_MODIFIED: + pair = diff_queue_change(&diff_queued_diff, &revs.diffopt, + mode_a, mode_b, &oid_a, &oid_b, + 1, 1, path.buf, 0, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_RENAMED: + case DIFF_STATUS_COPIED: { + struct diff_filespec *a, *b; + unsigned int score; + + if (strbuf_getwholeline(&path_dst, stdin, line_term) == EOF) + die(_("got EOF while reading destination path")); + + a = alloc_filespec(path.buf); + b = alloc_filespec(path_dst.buf); + fill_filespec(a, &oid_a, 1, mode_a); + fill_filespec(b, &oid_b, 1, mode_b); + + pair = diff_queue(&diff_queued_diff, a, b); + + if (strtoul_ui(p, 10, &score)) + die(_("unable to parse rename/copy score: %s"), p); + + pair->score = score * MAX_SCORE / 100; + pair->status = status; + pair->renamed_pair = 1; + } + break; + + default: + die(_("unknown diff status: %c"), status); + } + } + + revs.diffopt.no_free = 0; + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + ret = diff_result_code(&revs); + + strbuf_release(&path_dst); + strbuf_release(&path); + strbuf_release(&meta); + release_revisions(&revs); + FREE_AND_NULL(parseopts); + + return ret; +} diff --git a/builtin/diff.c b/builtin/diff.c index a4fffee42c..c6231edce4 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -35,7 +35,7 @@ static const char builtin_diff_usage[] = " or: git diff [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...]\n" " or: git diff [<options>] <commit>...<commit> [--] [<path>...]\n" " or: git diff [<options>] <blob> <blob>\n" -" or: git diff [<options>] --no-index [--] <path> <path>" +" or: git diff [<options>] --no-index [--] <path> <path> [<pathspec>...]" "\n" COMMON_DIFF_OPTIONS_HELP; @@ -104,7 +104,7 @@ static void builtin_diff_b_f(struct rev_info *revs, stuff_change(&revs->diffopt, blob[0]->mode, canon_mode(st.st_mode), - &blob[0]->item->oid, null_oid(), + &blob[0]->item->oid, null_oid(the_hash_algo), 1, 0, blob[0]->path ? blob[0]->path : path, path); @@ -498,7 +498,8 @@ int cmd_diff(int argc, /* If this is a no-index diff, just run it and exit there. */ if (no_index) - exit(diff_no_index(&rev, no_index == DIFF_NO_INDEX_IMPLICIT, + exit(diff_no_index(&rev, the_repository->hash_algo, + no_index == DIFF_NO_INDEX_IMPLICIT, argc, argv)); diff --git a/builtin/difftool.c b/builtin/difftool.c index 41cd00066c..a3b64ce694 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -22,6 +22,7 @@ #include "gettext.h" #include "hex.h" #include "parse-options.h" +#include "path.h" #include "read-cache-ll.h" #include "repository.h" #include "sparse-index.h" @@ -29,7 +30,7 @@ #include "strbuf.h" #include "lockfile.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "dir.h" #include "entry.h" #include "setup.h" @@ -271,9 +272,9 @@ static void changed_files(struct repository *repo, strbuf_release(&buf); } -static int ensure_leading_directories(char *path) +static int ensure_leading_directories(struct repository *repo, char *path) { - switch (safe_create_leading_directories(path)) { + switch (safe_create_leading_directories(repo, path)) { case SCLD_OK: case SCLD_EXISTS: return 0; @@ -341,11 +342,12 @@ static int checkout_path(unsigned mode, struct object_id *oid, return ret; } -static void write_file_in_directory(struct strbuf *dir, size_t dir_len, - const char *path, const char *content) +static void write_file_in_directory(struct repository *repo, + struct strbuf *dir, size_t dir_len, + const char *path, const char *content) { add_path(dir, dir_len, path); - ensure_leading_directories(dir->buf); + ensure_leading_directories(repo, dir->buf); unlink(dir->buf); write_file(dir->buf, "%s", content); } @@ -356,14 +358,15 @@ static void write_file_in_directory(struct strbuf *dir, size_t dir_len, * as text files, resulting in behavior that is analogous to what "git diff" * displays for symlink and submodule diffs. */ -static void write_standin_files(struct pair_entry *entry, - struct strbuf *ldir, size_t ldir_len, - struct strbuf *rdir, size_t rdir_len) +static void write_standin_files(struct repository *repo, + struct pair_entry *entry, + struct strbuf *ldir, size_t ldir_len, + struct strbuf *rdir, size_t rdir_len) { if (*entry->left) - write_file_in_directory(ldir, ldir_len, entry->path, entry->left); + write_file_in_directory(repo, ldir, ldir_len, entry->path, entry->left); if (*entry->right) - write_file_in_directory(rdir, rdir_len, entry->path, entry->right); + write_file_in_directory(repo, rdir, rdir_len, entry->path, entry->right); } static int run_dir_diff(struct repository *repo, @@ -533,7 +536,7 @@ static int run_dir_diff(struct repository *repo, ADD_CACHE_JUST_APPEND); add_path(&rdir, rdir_len, dst_path); - if (ensure_leading_directories(rdir.buf)) { + if (ensure_leading_directories(repo, rdir.buf)) { ret = error("could not create " "directory for '%s'", dst_path); @@ -576,7 +579,7 @@ static int run_dir_diff(struct repository *repo, */ hashmap_for_each_entry(&submodules, &iter, entry, entry /* member name */) { - write_standin_files(entry, &ldir, ldir_len, &rdir, rdir_len); + write_standin_files(repo, entry, &ldir, ldir_len, &rdir, rdir_len); } /* @@ -587,7 +590,7 @@ static int run_dir_diff(struct repository *repo, hashmap_for_each_entry(&symlinks2, &iter, entry, entry /* member name */) { - write_standin_files(entry, &ldir, ldir_len, &rdir, rdir_len); + write_standin_files(repo, entry, &ldir, ldir_len, &rdir, rdir_len); } strbuf_setlen(&ldir, ldir_len); @@ -750,8 +753,7 @@ int cmd_difftool(int argc, }; struct child_process child = CHILD_PROCESS_INIT; - if (repo) - repo_config(repo, difftool_config, &dt_options); + repo_config(repo, difftool_config, &dt_options); dt_options.symlinks = dt_options.has_symlinks; argc = parse_options(argc, argv, prefix, builtin_difftool_options, diff --git a/builtin/fast-export.c b/builtin/fast-export.c index a5c82eef1d..fcf6b00d5f 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -14,7 +14,7 @@ #include "refs.h" #include "refspec.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "object.h" #include "tag.h" @@ -30,13 +30,16 @@ #include "remote.h" #include "blob.h" -static const char *fast_export_usage[] = { +static const char *const fast_export_usage[] = { N_("git fast-export [<rev-list-opts>]"), NULL }; +enum sign_mode { SIGN_ABORT, SIGN_VERBATIM, SIGN_STRIP, SIGN_WARN_VERBATIM, SIGN_WARN_STRIP }; + static int progress; -static enum signed_tag_mode { SIGNED_TAG_ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = SIGNED_TAG_ABORT; +static enum sign_mode signed_tag_mode = SIGN_ABORT; +static enum sign_mode signed_commit_mode = SIGN_STRIP; static enum tag_of_filtered_mode { TAG_FILTERING_ABORT, DROP, REWRITE } tag_of_filtered_mode = TAG_FILTERING_ABORT; static enum reencode_mode { REENCODE_ABORT, REENCODE_YES, REENCODE_NO } reencode_mode = REENCODE_ABORT; static int fake_missing_tagger; @@ -53,23 +56,24 @@ static int anonymize; static struct hashmap anonymized_seeds; static struct revision_sources revision_sources; -static int parse_opt_signed_tag_mode(const struct option *opt, +static int parse_opt_sign_mode(const struct option *opt, const char *arg, int unset) { - enum signed_tag_mode *val = opt->value; - - if (unset || !strcmp(arg, "abort")) - *val = SIGNED_TAG_ABORT; + enum sign_mode *val = opt->value; + if (unset) + return 0; + else if (!strcmp(arg, "abort")) + *val = SIGN_ABORT; else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore")) - *val = VERBATIM; - else if (!strcmp(arg, "warn")) - *val = WARN; + *val = SIGN_VERBATIM; + else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn")) + *val = SIGN_WARN_VERBATIM; else if (!strcmp(arg, "warn-strip")) - *val = WARN_STRIP; + *val = SIGN_WARN_STRIP; else if (!strcmp(arg, "strip")) - *val = STRIP; + *val = SIGN_STRIP; else - return error("Unknown signed-tags mode: %s", arg); + return error("Unknown %s mode: %s", opt->long_name, arg); return 0; } @@ -510,21 +514,6 @@ static void show_filemodify(struct diff_queue_struct *q, } } -static const char *find_encoding(const char *begin, const char *end) -{ - const char *needle = "\nencoding "; - char *bol, *eol; - - bol = memmem(begin, end ? end - begin : strlen(begin), - needle, strlen(needle)); - if (!bol) - return NULL; - bol += strlen(needle); - eol = strchrnul(bol, '\n'); - *eol = '\0'; - return bol; -} - static char *anonymize_ref_component(void) { static int counter; @@ -626,13 +615,53 @@ static void anonymize_ident_line(const char **beg, const char **end) *end = out->buf + out->len; } +/* + * find_commit_multiline_header is similar to find_commit_header, + * except that it handles multi-line headers, rather than simply + * returning the first line of the header. + * + * The returned string has had the ' ' line continuation markers + * removed, and points to allocated memory that must be free()d (not + * to memory within 'msg'). + * + * If the header is found, then *end is set to point at the '\n' in + * msg that immediately follows the header value. + */ +static const char *find_commit_multiline_header(const char *msg, + const char *key, + const char **end) +{ + struct strbuf val = STRBUF_INIT; + const char *bol, *eol; + size_t len; + + bol = find_commit_header(msg, key, &len); + if (!bol) + return NULL; + eol = bol + len; + strbuf_add(&val, bol, len); + + while (eol[0] == '\n' && eol[1] == ' ') { + bol = eol + 2; + eol = strchrnul(bol, '\n'); + strbuf_addch(&val, '\n'); + strbuf_add(&val, bol, eol - bol); + } + + *end = eol; + return strbuf_detach(&val, NULL); +} + static void handle_commit(struct commit *commit, struct rev_info *rev, struct string_list *paths_of_changed_objects) { int saved_output_format = rev->diffopt.output_format; - const char *commit_buffer; + const char *commit_buffer, *commit_buffer_cursor; const char *author, *author_end, *committer, *committer_end; - const char *encoding, *message; + const char *encoding = NULL; + size_t encoding_len; + const char *signature_alg = NULL, *signature = NULL; + const char *message; char *reencoded = NULL; struct commit_list *p; const char *refname; @@ -641,21 +670,43 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, rev->diffopt.output_format = DIFF_FORMAT_CALLBACK; parse_commit_or_die(commit); - commit_buffer = repo_get_commit_buffer(the_repository, commit, NULL); - author = strstr(commit_buffer, "\nauthor "); + commit_buffer_cursor = commit_buffer = repo_get_commit_buffer(the_repository, commit, NULL); + + author = strstr(commit_buffer_cursor, "\nauthor "); if (!author) die("could not find author in commit %s", oid_to_hex(&commit->object.oid)); author++; - author_end = strchrnul(author, '\n'); - committer = strstr(author_end, "\ncommitter "); + commit_buffer_cursor = author_end = strchrnul(author, '\n'); + + committer = strstr(commit_buffer_cursor, "\ncommitter "); if (!committer) die("could not find committer in commit %s", oid_to_hex(&commit->object.oid)); committer++; - committer_end = strchrnul(committer, '\n'); - message = strstr(committer_end, "\n\n"); - encoding = find_encoding(committer_end, message); + commit_buffer_cursor = committer_end = strchrnul(committer, '\n'); + + /* + * find_commit_header() and find_commit_multiline_header() get + * a `+ 1` because commit_buffer_cursor points at the trailing + * "\n" at the end of the previous line, but they want a + * pointer to the beginning of the next line. + */ + + if (*commit_buffer_cursor == '\n') { + encoding = find_commit_header(commit_buffer_cursor + 1, "encoding", &encoding_len); + if (encoding) + commit_buffer_cursor = encoding + encoding_len; + } + + if (*commit_buffer_cursor == '\n') { + if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig", &commit_buffer_cursor))) + signature_alg = "sha1"; + else if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig-sha256", &commit_buffer_cursor))) + signature_alg = "sha256"; + } + + message = strstr(commit_buffer_cursor, "\n\n"); if (message) message += 2; @@ -694,16 +745,20 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, if (anonymize) { reencoded = anonymize_commit_message(); } else if (encoding) { - switch(reencode_mode) { + char *buf; + switch (reencode_mode) { case REENCODE_YES: - reencoded = reencode_string(message, "UTF-8", encoding); + buf = xstrfmt("%.*s", (int)encoding_len, encoding); + reencoded = reencode_string(message, "UTF-8", buf); + free(buf); break; case REENCODE_NO: break; case REENCODE_ABORT: - die("Encountered commit-specific encoding %s in commit " + die("Encountered commit-specific encoding %.*s in commit " "%s; use --reencode=[yes|no] to handle it", - encoding, oid_to_hex(&commit->object.oid)); + (int)encoding_len, encoding, + oid_to_hex(&commit->object.oid)); } } if (!commit->parents) @@ -714,8 +769,33 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, printf("%.*s\n%.*s\n", (int)(author_end - author), author, (int)(committer_end - committer), committer); + if (signature) { + switch (signed_commit_mode) { + case SIGN_ABORT: + die("encountered signed commit %s; use " + "--signed-commits=<mode> to handle it", + oid_to_hex(&commit->object.oid)); + case SIGN_WARN_VERBATIM: + warning("exporting signed commit %s", + oid_to_hex(&commit->object.oid)); + /* fallthru */ + case SIGN_VERBATIM: + printf("gpgsig %s\ndata %u\n%s", + signature_alg, + (unsigned)strlen(signature), + signature); + break; + case SIGN_WARN_STRIP: + warning("stripping signature from commit %s", + oid_to_hex(&commit->object.oid)); + /* fallthru */ + case SIGN_STRIP: + break; + } + free((char *)signature); + } if (!reencoded && encoding) - printf("encoding %s\n", encoding); + printf("encoding %.*s\n", (int)encoding_len, encoding); printf("data %u\n%s", (unsigned)(reencoded ? strlen(reencoded) : message @@ -828,22 +908,22 @@ static void handle_tag(const char *name, struct tag *tag) const char *signature = strstr(message, "\n-----BEGIN PGP SIGNATURE-----\n"); if (signature) - switch(signed_tag_mode) { - case SIGNED_TAG_ABORT: + switch (signed_tag_mode) { + case SIGN_ABORT: die("encountered signed tag %s; use " "--signed-tags=<mode> to handle it", oid_to_hex(&tag->object.oid)); - case WARN: + case SIGN_WARN_VERBATIM: warning("exporting signed tag %s", oid_to_hex(&tag->object.oid)); /* fallthru */ - case VERBATIM: + case SIGN_VERBATIM: break; - case WARN_STRIP: + case SIGN_WARN_STRIP: warning("stripping signature from tag %s", oid_to_hex(&tag->object.oid)); /* fallthru */ - case STRIP: + case SIGN_STRIP: message_size = signature + 1 - message; break; } @@ -853,7 +933,7 @@ static void handle_tag(const char *name, struct tag *tag) tagged = tag->tagged; tagged_mark = get_object_mark(tagged); if (!tagged_mark) { - switch(tag_of_filtered_mode) { + switch (tag_of_filtered_mode) { case TAG_FILTERING_ABORT: die("tag %s tags unexported object; use " "--tag-of-filtered-object=<mode> to handle it", @@ -869,7 +949,7 @@ static void handle_tag(const char *name, struct tag *tag) p = rewrite_commit((struct commit *)tagged); if (!p) { printf("reset %s\nfrom %s\n\n", - name, oid_to_hex(null_oid())); + name, oid_to_hex(null_oid(the_hash_algo))); free(buf); return; } @@ -883,7 +963,7 @@ static void handle_tag(const char *name, struct tag *tag) if (tagged->type == OBJ_TAG) { printf("reset %s\nfrom %s\n\n", - name, oid_to_hex(null_oid())); + name, oid_to_hex(null_oid(the_hash_algo))); } skip_prefix(name, "refs/tags/", &name); printf("tag %s\n", name); @@ -965,7 +1045,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) continue; } - switch(commit->object.type) { + switch (commit->object.type) { case OBJ_COMMIT: break; case OBJ_BLOB: @@ -1023,7 +1103,7 @@ static void handle_tags_and_duplicates(struct string_list *extras) * it. */ printf("reset %s\nfrom %s\n\n", - name, oid_to_hex(null_oid())); + name, oid_to_hex(null_oid(the_hash_algo))); continue; } @@ -1042,7 +1122,7 @@ static void handle_tags_and_duplicates(struct string_list *extras) if (!reference_excluded_commits) { /* delete the ref */ printf("reset %s\nfrom %s\n\n", - name, oid_to_hex(null_oid())); + name, oid_to_hex(null_oid(the_hash_algo))); continue; } /* set ref to commit using oid, not mark */ @@ -1153,7 +1233,7 @@ static void handle_deletes(void) continue; printf("reset %s\nfrom %s\n\n", - refspec->dst, oid_to_hex(null_oid())); + refspec->dst, oid_to_hex(null_oid(the_hash_algo))); } } @@ -1202,7 +1282,10 @@ int cmd_fast_export(int argc, N_("show progress after <n> objects")), OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, N_("mode"), N_("select handling of signed tags"), - parse_opt_signed_tag_mode), + parse_opt_sign_mode), + OPT_CALLBACK(0, "signed-commits", &signed_commit_mode, N_("mode"), + N_("select handling of signed commits"), + parse_opt_sign_mode), OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, N_("mode"), N_("select handling of tags that tag filtered objects"), parse_opt_tag_of_filtered_mode), diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 397a6f46ad..b2839c5f43 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -24,7 +24,7 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "mem-pool.h" #include "commit-reach.h" #include "khash.h" @@ -770,7 +770,7 @@ static void start_packfile(void) p->pack_fd = pack_fd; p->do_not_close = 1; p->repo = the_repository; - pack_file = hashfd(pack_fd, p->pack_name); + pack_file = hashfd(the_repository->hash_algo, pack_fd, p->pack_name); pack_data = p; pack_size = write_pack_header(pack_file, 0); @@ -798,7 +798,7 @@ static const char *create_index(void) if (c != last) die("internal consistency error creating the index"); - tmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count, + tmpfile = write_idx_file(the_repository, NULL, idx, object_count, &pack_idx_opts, pack_data->hash); free(idx); return tmpfile; @@ -811,7 +811,8 @@ static char *keep_pack(const char *curr_index_name) int keep_fd; odb_pack_name(pack_data->repo, &name, pack_data->hash, "keep"); - keep_fd = odb_pack_keep(name.buf); + keep_fd = safe_create_file_with_leading_directories(pack_data->repo, + name.buf); if (keep_fd < 0) die_errno("cannot create keep file"); write_or_die(keep_fd, keep_msg, strlen(keep_msg)); @@ -1720,7 +1721,7 @@ static void dump_marks(void) if (!export_marks_file || (import_marks_file && !import_marks_file_done)) return; - if (safe_create_leading_directories_const(export_marks_file)) { + if (safe_create_leading_directories_const(the_repository, export_marks_file)) { failure |= error_errno("unable to create leading directories of %s", export_marks_file); return; @@ -2021,7 +2022,7 @@ static void parse_and_store_blob( static struct strbuf buf = STRBUF_INIT; uintmax_t len; - if (parse_data(&buf, big_file_threshold, &len)) + if (parse_data(&buf, repo_settings_get_big_file_threshold(the_repository), &len)) store_object(OBJ_BLOB, &buf, last, oidout, mark); else { if (last) { @@ -2719,10 +2720,13 @@ static struct hash_list *parse_merge(unsigned int *count) static void parse_new_commit(const char *arg) { + static struct strbuf sig = STRBUF_INIT; static struct strbuf msg = STRBUF_INIT; + struct string_list siglines = STRING_LIST_INIT_NODUP; struct branch *b; char *author = NULL; char *committer = NULL; + char *sig_alg = NULL; char *encoding = NULL; struct hash_list *merge_list = NULL; unsigned int merge_count; @@ -2746,6 +2750,13 @@ static void parse_new_commit(const char *arg) } if (!committer) die("Expected committer but didn't get one"); + if (skip_prefix(command_buf.buf, "gpgsig ", &v)) { + sig_alg = xstrdup(v); + read_next_command(); + parse_data(&sig, 0, NULL); + read_next_command(); + } else + strbuf_setlen(&sig, 0); if (skip_prefix(command_buf.buf, "encoding ", &v)) { encoding = xstrdup(v); read_next_command(); @@ -2819,10 +2830,23 @@ static void parse_new_commit(const char *arg) strbuf_addf(&new_data, "encoding %s\n", encoding); + if (sig_alg) { + if (!strcmp(sig_alg, "sha1")) + strbuf_addstr(&new_data, "gpgsig "); + else if (!strcmp(sig_alg, "sha256")) + strbuf_addstr(&new_data, "gpgsig-sha256 "); + else + die("Expected gpgsig algorithm sha1 or sha256, got %s", sig_alg); + string_list_split_in_place(&siglines, sig.buf, "\n", -1); + strbuf_add_separated_string_list(&new_data, "\n ", &siglines); + strbuf_addch(&new_data, '\n'); + } strbuf_addch(&new_data, '\n'); strbuf_addbuf(&new_data, &msg); + string_list_clear(&siglines, 1); free(author); free(committer); + free(sig_alg); free(encoding); if (!store_object(OBJ_COMMIT, &new_data, NULL, &b->oid, next_mark)) @@ -3402,7 +3426,7 @@ static int parse_one_option(const char *option) unsigned long v; if (!git_parse_ulong(option, &v)) return 0; - big_file_threshold = v; + repo_settings_set_big_file_threshold(the_repository, v); } else if (skip_prefix(option, "depth=", &option)) { option_depth(option); } else if (skip_prefix(option, "active-branches=", &option)) { diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index d07eec9e55..d9e42bad58 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -274,8 +274,10 @@ int cmd_fetch_pack(int argc, } close(fd[0]); close(fd[1]); - if (finish_connect(conn)) - return 1; + if (finish_connect(conn)) { + ret = 1; + goto cleanup; + } ret = !fetched_refs; @@ -291,6 +293,7 @@ int cmd_fetch_pack(int argc, printf("%s %s\n", oid_to_hex(&ref->old_oid), ref->name); +cleanup: for (size_t i = 0; i < nr_sought; i++) free_one_ref(sought_to_free[i]); free(sought_to_free); diff --git a/builtin/fetch.c b/builtin/fetch.c index 95fd0018b9..40a0e8d244 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -14,7 +14,7 @@ #include "refs.h" #include "refspec.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oidset.h" #include "oid-array.h" #include "commit.h" @@ -337,7 +337,6 @@ static void find_non_local_tags(const struct ref *refs, struct string_list_item *remote_ref_item; const struct ref *ref; struct refname_hash_entry *item = NULL; - const int quick_flags = OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT; refname_hash_init(&existing_refs); refname_hash_init(&remote_refs); @@ -367,9 +366,9 @@ static void find_non_local_tags(const struct ref *refs, */ if (ends_with(ref->name, "^{}")) { if (item && - !repo_has_object_file_with_flags(the_repository, &ref->old_oid, quick_flags) && + !has_object(the_repository, &ref->old_oid, 0) && !oidset_contains(&fetch_oids, &ref->old_oid) && - !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) && + !has_object(the_repository, &item->oid, 0) && !oidset_contains(&fetch_oids, &item->oid)) clear_item(item); item = NULL; @@ -383,7 +382,7 @@ static void find_non_local_tags(const struct ref *refs, * fetch. */ if (item && - !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) && + !has_object(the_repository, &item->oid, 0) && !oidset_contains(&fetch_oids, &item->oid)) clear_item(item); @@ -404,7 +403,7 @@ static void find_non_local_tags(const struct ref *refs, * checked to see if it needs fetching. */ if (item && - !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) && + !has_object(the_repository, &item->oid, 0) && !oidset_contains(&fetch_oids, &item->oid)) clear_item(item); @@ -586,7 +585,7 @@ static struct ref *get_ref_map(struct remote *remote, struct refspec_item tag_refspec; /* also fetch all tags */ - refspec_item_init(&tag_refspec, TAG_REFSPEC, 0); + refspec_item_init_push(&tag_refspec, TAG_REFSPEC); get_fetch_map(remote_refs, &tag_refspec, &tail, 0); refspec_item_clear(&tag_refspec); } else if (tags == TAGS_DEFAULT && *autotags) { @@ -687,7 +686,7 @@ static int s_update_ref(const char *action, switch (ref_transaction_commit(our_transaction, &err)) { case 0: break; - case TRANSACTION_NAME_CONFLICT: + case REF_TRANSACTION_ERROR_NAME_CONFLICT: ret = STORE_REF_ERROR_DF_CONFLICT; goto out; default: @@ -911,7 +910,8 @@ static int update_local_ref(struct ref *ref, struct commit *current = NULL, *updated; int fast_forward = 0; - if (!repo_has_object_file(the_repository, &ref->new_oid)) + if (!has_object(the_repository, &ref->new_oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) die(_("object %s not found"), oid_to_hex(&ref->new_oid)); if (oideq(&ref->old_oid, &ref->new_oid)) { @@ -1330,8 +1330,7 @@ static int check_exist_and_connected(struct ref *ref_map) * we need all direct targets to exist. */ for (r = rm; r; r = r->next) { - if (!repo_has_object_file_with_flags(the_repository, &r->old_oid, - OBJECT_INFO_SKIP_FETCH_OBJECT)) + if (!has_object(the_repository, &r->old_oid, HAS_OBJECT_RECHECK_PACKED)) return -1; } @@ -1638,14 +1637,11 @@ static int set_head(const struct ref *remote_refs, struct remote *remote) get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0); matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"), - fetch_map, 1); + fetch_map, REMOTE_GUESS_HEAD_ALL); for (ref = matches; ref; ref = ref->next) { string_list_append(&heads, strip_refshead(ref->name)); } - if (follow_remote_head == FOLLOW_REMOTE_NEVER) - goto cleanup; - if (!heads.nr) result = 1; else if (heads.nr > 1) @@ -1691,21 +1687,6 @@ cleanup: return result; } -static int uses_remote_tracking(struct transport *transport, struct refspec *rs) -{ - if (!remote_is_configured(transport->remote, 0)) - return 0; - - if (!rs->nr) - rs = &transport->remote->fetch; - - for (int i = 0; i < rs->nr; i++) - if (rs->items[i].dst) - return 1; - - return 0; -} - static int do_fetch(struct transport *transport, struct refspec *rs, const struct fetch_config *config) @@ -1718,9 +1699,9 @@ static int do_fetch(struct transport *transport, const struct ref *remote_refs; struct transport_ls_refs_options transport_ls_refs_options = TRANSPORT_LS_REFS_OPTIONS_INIT; - int must_list_refs = 1; struct fetch_head fetch_head = { 0 }; struct strbuf err = STRBUF_INIT; + int do_set_head = 0; if (tags == TAGS_DEFAULT) { if (transport->remote->fetch_tags == 2) @@ -1737,28 +1718,17 @@ static int do_fetch(struct transport *transport, } if (rs->nr) { - int i; - refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes); - - /* - * We can avoid listing refs if all of them are exact - * OIDs - */ - must_list_refs = 0; - for (i = 0; i < rs->nr; i++) { - if (!rs->items[i].exact_sha1) { - must_list_refs = 1; - break; - } - } } else { struct branch *branch = branch_get(NULL); - if (transport->remote->fetch.nr) + if (transport->remote->fetch.nr) { refspec_ref_prefixes(&transport->remote->fetch, &transport_ls_refs_options.ref_prefixes); - if (branch_has_merge_config(branch) && + if (transport->remote->follow_remote_head != FOLLOW_REMOTE_NEVER) + do_set_head = 1; + } + if (branch && branch_has_merge_config(branch) && !strcmp(branch->remote_name, transport->remote->name)) { int i; for (i = 0; i < branch->merge_nr; i++) { @@ -1766,23 +1736,29 @@ static int do_fetch(struct transport *transport, branch->merge[i]->src); } } - } - if (tags == TAGS_SET || tags == TAGS_DEFAULT) { - must_list_refs = 1; - if (transport_ls_refs_options.ref_prefixes.nr) - strvec_push(&transport_ls_refs_options.ref_prefixes, - "refs/tags/"); - } - - if (uses_remote_tracking(transport, rs)) { - must_list_refs = 1; - if (transport_ls_refs_options.ref_prefixes.nr) + /* + * If there are no refs specified to fetch, then we just + * fetch HEAD; mention that to narrow the advertisement. + */ + if (!transport_ls_refs_options.ref_prefixes.nr) strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); } - if (must_list_refs) { + if (tags == TAGS_SET || tags == TAGS_DEFAULT) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "refs/tags/"); + + if (do_set_head) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "HEAD"); + + /* + * Only initiate ref listing if we have at least one ref we want to + * know about. + */ + if (transport_ls_refs_options.ref_prefixes.nr) { trace2_region_enter("fetch", "remote_refs", the_repository); remote_refs = transport_get_remote_refs(transport, &transport_ls_refs_options); @@ -1867,8 +1843,15 @@ static int do_fetch(struct transport *transport, goto cleanup; retcode = ref_transaction_commit(transaction, &err); - if (retcode) + if (retcode) { + /* + * Explicitly handle transaction cleanup to avoid + * aborting an already closed transaction. + */ + ref_transaction_free(transaction); + transaction = NULL; goto cleanup; + } } commit_fetch_head(&fetch_head); @@ -1926,12 +1909,13 @@ static int do_fetch(struct transport *transport, "you need to specify exactly one branch with the --set-upstream option")); } } - if (set_head(remote_refs, transport->remote)) - ; + if (do_set_head) { /* - * Way too many cases where this can go wrong - * so let's just fail silently for now. + * Way too many cases where this can go wrong so let's just + * ignore errors and fail silently for now. */ + set_head(remote_refs, transport->remote); + } cleanup: if (retcode) { @@ -2367,8 +2351,14 @@ int cmd_fetch(int argc, OPT_SET_INT_F(0, "refetch", &refetch, N_("re-fetch without negotiating common commits"), 1, PARSE_OPT_NONEG), - { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"), - N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN }, + { + .type = OPTION_STRING, + .long_name = "submodule-prefix", + .value = &submodule_prefix, + .argh = N_("dir"), + .help = N_("prepend this to submodule path output"), + .flags = PARSE_OPT_HIDDEN, + }, OPT_CALLBACK_F(0, "recurse-submodules-default", &recurse_submodules_default, N_("on-demand"), N_("default for recursive fetching of submodules " @@ -2570,6 +2560,7 @@ int cmd_fetch(int argc, if (server_options.nr) gtransport->server_options = &server_options; result = transport_fetch_refs(gtransport, NULL); + gtransport->smart_options->acked_commits = NULL; oidset_iter_init(&acked_commits, &iter); while ((oid = oidset_iter_next(&iter))) diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 189cd1096a..3b6aac2cf7 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -20,13 +20,26 @@ int cmd_fmt_merge_msg(int argc, char *into_name = NULL; int shortlog_len = -1; struct option options[] = { - { OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"), - N_("populate log with at most <n> entries from shortlog"), - PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN }, - { OPTION_INTEGER, 0, "summary", &shortlog_len, N_("n"), - N_("alias for --log (deprecated)"), - PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL, - DEFAULT_MERGE_LOG_LEN }, + { + .type = OPTION_INTEGER, + .long_name = "log", + .value = &shortlog_len, + .precision = sizeof(shortlog_len), + .argh = N_("n"), + .help = N_("populate log with at most <n> entries from shortlog"), + .flags = PARSE_OPT_OPTARG, + .defval = DEFAULT_MERGE_LOG_LEN, + }, + { + .type = OPTION_INTEGER, + .long_name = "summary", + .value = &shortlog_len, + .precision = sizeof(shortlog_len), + .argh = N_("n"), + .help = N_("alias for --log (deprecated)"), + .flags = PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, + .defval = DEFAULT_MERGE_LOG_LEN, + }, OPT_STRING('m', "message", &message, N_("text"), N_("use <text> as start of message")), OPT_STRING(0, "into-name", &into_name, N_("name"), diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 8085ebd8fe..3d2207ec77 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" @@ -20,7 +19,7 @@ static char const * const for_each_ref_usage[] = { int cmd_for_each_ref(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; @@ -63,7 +62,7 @@ int cmd_for_each_ref(int argc, format.format = "%(objectname) %(objecttype)\t%(refname)"; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); /* Set default (refname) sorting */ string_list_append(&sorting_options, "refname"); diff --git a/builtin/fsck.c b/builtin/fsck.c index eea1d43647..e7d96a9c8e 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -17,7 +17,7 @@ #include "packfile.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "read-cache-ll.h" #include "replace-object.h" @@ -50,6 +50,7 @@ static int verbose; static int show_progress = -1; static int show_dangling = 1; static int name_objects; +static int check_references = 1; #define ERROR_OBJECT 01 #define ERROR_REACHABLE 02 #define ERROR_PACK 04 @@ -331,7 +332,7 @@ static void check_unreachable_object(struct object *obj) describe_object(&obj->oid)); FILE *f; - if (safe_create_leading_directories_const(filename)) { + if (safe_create_leading_directories_const(the_repository, filename)) { error(_("could not create lost-found")); free(filename); return; @@ -399,12 +400,12 @@ static void check_connectivity(void) } /* Look up all the requirements, warn about missing objects.. */ - max = get_max_object_index(); + max = get_max_object_index(the_repository); if (verbose) fprintf_ln(stderr, _("Checking connectivity (%d objects)"), max); for (i = 0; i < max; i++) { - struct object *obj = get_indexed_object(i); + struct object *obj = get_indexed_object(the_repository, i); if (obj) check_object(obj); @@ -613,23 +614,20 @@ static void get_default_heads(void) struct for_each_loose_cb { struct progress *progress; - struct strbuf obj_type; }; -static int fsck_loose(const struct object_id *oid, const char *path, void *data) +static int fsck_loose(const struct object_id *oid, const char *path, + void *data UNUSED) { - struct for_each_loose_cb *cb_data = data; struct object *obj; enum object_type type = OBJ_NONE; unsigned long size; void *contents = NULL; int eaten; struct object_info oi = OBJECT_INFO_INIT; - struct object_id real_oid = *null_oid(); + struct object_id real_oid = *null_oid(the_hash_algo); int err = 0; - strbuf_reset(&cb_data->obj_type); - oi.type_name = &cb_data->obj_type; oi.sizep = &size; oi.typep = &type; @@ -641,10 +639,6 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data) err = error(_("%s: object corrupt or missing: %s"), oid_to_hex(oid), path); } - if (type != OBJ_NONE && type < 0) - err = error(_("%s: object is of unknown type '%s': %s"), - oid_to_hex(&real_oid), cb_data->obj_type.buf, - path); if (err < 0) { errors_found |= ERROR_OBJECT; free(contents); @@ -696,7 +690,6 @@ static void fsck_object_dir(const char *path) { struct progress *progress = NULL; struct for_each_loose_cb cb_data = { - .obj_type = STRBUF_INIT, .progress = progress, }; @@ -711,7 +704,6 @@ static void fsck_object_dir(const char *path) &cb_data); display_progress(progress, 256); stop_progress(&progress); - strbuf_release(&cb_data.obj_type); } static int fsck_head_link(const char *head_ref_name, @@ -905,11 +897,37 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress) return res; } +static void fsck_refs(struct repository *r) +{ + struct child_process refs_verify = CHILD_PROCESS_INIT; + struct progress *progress = NULL; + + if (show_progress) + progress = start_progress(r, _("Checking ref database"), 1); + + if (verbose) + fprintf_ln(stderr, _("Checking ref database")); + + child_process_init(&refs_verify); + refs_verify.git_cmd = 1; + strvec_pushl(&refs_verify.args, "refs", "verify", NULL); + if (verbose) + strvec_push(&refs_verify.args, "--verbose"); + if (check_strict) + strvec_push(&refs_verify.args, "--strict"); + + if (run_command(&refs_verify)) + errors_found |= ERROR_REFS; + + display_progress(progress, 1); + stop_progress(&progress); +} + static char const * const fsck_usage[] = { N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" - " [--[no-]name-objects] [<object>...]"), + " [--[no-]name-objects] [--[no-]references] [<object>...]"), NULL }; @@ -928,6 +946,7 @@ static struct option fsck_opts[] = { N_("write dangling objects in .git/lost-found")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")), OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")), + OPT_BOOL(0, "references", &check_references, N_("check reference database consistency")), OPT_END(), }; @@ -970,6 +989,9 @@ int cmd_fsck(int argc, git_config(git_fsck_config, &fsck_obj_options); prepare_repo_settings(the_repository); + if (check_references) + fsck_refs(the_repository); + if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_packed_object(the_repository, diff --git a/builtin/gc.c b/builtin/gc.c index 99431fd467..7dc94f243d 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -16,6 +16,7 @@ #include "builtin.h" #include "abspath.h" #include "date.h" +#include "dir.h" #include "environment.h" #include "hex.h" #include "config.h" @@ -29,10 +30,11 @@ #include "commit-graph.h" #include "packfile.h" #include "object-file.h" -#include "object-store-ll.h" #include "pack.h" #include "pack-objects.h" #include "path.h" +#include "reflog.h" +#include "rerere.h" #include "blob.h" #include "tree.h" #include "promisor-remote.h" @@ -43,6 +45,7 @@ #include "hook.h" #include "setup.h" #include "trace2.h" +#include "worktree.h" #define FAILED_RUN "failed to run %s" @@ -52,16 +55,9 @@ static const char * const builtin_gc_usage[] = { }; static timestamp_t gc_log_expire_time; - -static struct strvec reflog = STRVEC_INIT; static struct strvec repack = STRVEC_INIT; -static struct strvec prune = STRVEC_INIT; -static struct strvec prune_worktrees = STRVEC_INIT; -static struct strvec rerere = STRVEC_INIT; - static struct tempfile *pidfile; static struct lock_file log_lock; - static struct string_list pack_garbage = STRING_LIST_INIT_DUP; static void clean_pack_garbage(void) @@ -288,6 +284,146 @@ static int maintenance_task_pack_refs(struct maintenance_run_opts *opts, return run_command(&cmd); } +struct count_reflog_entries_data { + struct expire_reflog_policy_cb policy; + size_t count; + size_t limit; +}; + +static int count_reflog_entries(struct object_id *old_oid, struct object_id *new_oid, + const char *committer, timestamp_t timestamp, + int tz, const char *msg, void *cb_data) +{ + struct count_reflog_entries_data *data = cb_data; + if (should_expire_reflog_ent(old_oid, new_oid, committer, timestamp, tz, msg, &data->policy)) + data->count++; + return data->count >= data->limit; +} + +static int reflog_expire_condition(struct gc_config *cfg UNUSED) +{ + timestamp_t now = time(NULL); + struct count_reflog_entries_data data = { + .policy = { + .opts = REFLOG_EXPIRE_OPTIONS_INIT(now), + }, + }; + int limit = 100; + + git_config_get_int("maintenance.reflog-expire.auto", &limit); + if (!limit) + return 0; + if (limit < 0) + return 1; + data.limit = limit; + + repo_config(the_repository, reflog_expire_config, &data.policy.opts); + + reflog_expire_options_set_refname(&data.policy.opts, "HEAD"); + refs_for_each_reflog_ent(get_main_ref_store(the_repository), "HEAD", + count_reflog_entries, &data); + + reflog_expiry_cleanup(&data.policy); + return data.count >= data.limit; +} + +static int maintenance_task_reflog_expire(struct maintenance_run_opts *opts UNUSED, + struct gc_config *cfg UNUSED) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + cmd.git_cmd = 1; + strvec_pushl(&cmd.args, "reflog", "expire", "--all", NULL); + return run_command(&cmd); +} + +static int maintenance_task_worktree_prune(struct maintenance_run_opts *opts UNUSED, + struct gc_config *cfg) +{ + struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT; + + prune_worktrees_cmd.git_cmd = 1; + strvec_pushl(&prune_worktrees_cmd.args, "worktree", "prune", "--expire", NULL); + strvec_push(&prune_worktrees_cmd.args, cfg->prune_worktrees_expire); + + return run_command(&prune_worktrees_cmd); +} + +static int worktree_prune_condition(struct gc_config *cfg) +{ + struct strbuf buf = STRBUF_INIT; + int should_prune = 0, limit = 1; + timestamp_t expiry_date; + struct dirent *d; + DIR *dir = NULL; + + git_config_get_int("maintenance.worktree-prune.auto", &limit); + if (limit <= 0) { + should_prune = limit < 0; + goto out; + } + + if (parse_expiry_date(cfg->prune_worktrees_expire, &expiry_date)) + goto out; + + dir = opendir(repo_git_path_replace(the_repository, &buf, "worktrees")); + if (!dir) + goto out; + + while (limit && (d = readdir_skip_dot_and_dotdot(dir))) { + char *wtpath; + strbuf_reset(&buf); + if (should_prune_worktree(d->d_name, &buf, &wtpath, expiry_date)) + limit--; + free(wtpath); + } + + should_prune = !limit; + +out: + if (dir) + closedir(dir); + strbuf_release(&buf); + return should_prune; +} + +static int maintenance_task_rerere_gc(struct maintenance_run_opts *opts UNUSED, + struct gc_config *cfg UNUSED) +{ + struct child_process rerere_cmd = CHILD_PROCESS_INIT; + rerere_cmd.git_cmd = 1; + strvec_pushl(&rerere_cmd.args, "rerere", "gc", NULL); + return run_command(&rerere_cmd); +} + +static int rerere_gc_condition(struct gc_config *cfg UNUSED) +{ + struct strbuf path = STRBUF_INIT; + int should_gc = 0, limit = 1; + DIR *dir = NULL; + + git_config_get_int("maintenance.rerere-gc.auto", &limit); + if (limit <= 0) { + should_gc = limit < 0; + goto out; + } + + /* + * We skip garbage collection in case we either have no "rr-cache" + * directory or when it doesn't contain at least one entry. + */ + repo_git_path_replace(the_repository, &path, "rr-cache"); + dir = opendir(path.buf); + if (!dir) + goto out; + should_gc = !!readdir_skip_dot_and_dotdot(dir); + +out: + strbuf_release(&path); + if (dir) + closedir(dir); + return should_gc; +} + static int too_many_loose_objects(struct gc_config *cfg) { /* @@ -373,9 +509,14 @@ static uint64_t total_ram(void) #if defined(HAVE_SYSINFO) struct sysinfo si; - if (!sysinfo(&si)) - return si.totalram; -#elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM)) + if (!sysinfo(&si)) { + uint64_t total = si.totalram; + + if (si.mem_unit > 1) + total *= (uint64_t)si.mem_unit; + return total; + } +#elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM) || defined(HW_PHYSMEM64)) int64_t physical_memory; int mib[2]; size_t length; @@ -383,6 +524,8 @@ static uint64_t total_ram(void) mib[0] = CTL_HW; # if defined(HW_MEMSIZE) mib[1] = HW_MEMSIZE; +# elif defined(HW_PHYSMEM64) + mib[1] = HW_PHYSMEM64; # else mib[1] = HW_PHYSMEM; # endif @@ -667,21 +810,14 @@ static void gc_before_repack(struct maintenance_run_opts *opts, if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg)) die(FAILED_RUN, "pack-refs"); - - if (cfg->prune_reflogs) { - struct child_process cmd = CHILD_PROCESS_INIT; - - cmd.git_cmd = 1; - strvec_pushv(&cmd.args, reflog.v); - if (run_command(&cmd)) - die(FAILED_RUN, reflog.v[0]); - } + if (cfg->prune_reflogs && maintenance_task_reflog_expire(opts, cfg)) + die(FAILED_RUN, "reflog"); } int cmd_gc(int argc, -const char **argv, -const char *prefix, -struct repository *repo UNUSED) + const char **argv, + const char *prefix, + struct repository *repo UNUSED) { int aggressive = 0; int quiet = 0; @@ -691,7 +827,6 @@ struct repository *repo UNUSED) int daemonized = 0; int keep_largest_pack = -1; timestamp_t dummy; - struct child_process rerere_cmd = CHILD_PROCESS_INIT; struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT; struct gc_config cfg = GC_CONFIG_INIT; const char *prune_expire_sentinel = "sentinel"; @@ -699,12 +834,18 @@ struct repository *repo UNUSED) int ret; struct option builtin_gc_options[] = { OPT__QUIET(&quiet, N_("suppress progress reporting")), - { OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"), - N_("prune unreferenced objects"), - PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire_arg }, + { + .type = OPTION_STRING, + .long_name = "prune", + .value = &prune_expire_arg, + .argh = N_("date"), + .help = N_("prune unreferenced objects"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t)prune_expire_arg, + }, OPT_BOOL(0, "cruft", &cfg.cruft_packs, N_("pack unreferenced objects separately")), - OPT_MAGNITUDE(0, "max-cruft-size", &cfg.max_cruft_size, - N_("with --cruft, limit the size of new cruft packs")), + OPT_UNSIGNED(0, "max-cruft-size", &cfg.max_cruft_size, + N_("with --cruft, limit the size of new cruft packs")), OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")), OPT_BOOL_F(0, "auto", &opts.auto_flag, N_("enable auto-gc mode"), PARSE_OPT_NOCOMPLETE), @@ -723,11 +864,7 @@ struct repository *repo UNUSED) show_usage_with_options_if_asked(argc, argv, builtin_gc_usage, builtin_gc_options); - strvec_pushl(&reflog, "reflog", "expire", "--all", NULL); strvec_pushl(&repack, "repack", "-d", "-l", NULL); - strvec_pushl(&prune, "prune", "--expire", NULL); - strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL); - strvec_pushl(&rerere, "rerere", "gc", NULL); gc_config(&cfg); @@ -853,34 +990,27 @@ struct repository *repo UNUSED) if (cfg.prune_expire) { struct child_process prune_cmd = CHILD_PROCESS_INIT; + strvec_pushl(&prune_cmd.args, "prune", "--expire", NULL); /* run `git prune` even if using cruft packs */ - strvec_push(&prune, cfg.prune_expire); + strvec_push(&prune_cmd.args, cfg.prune_expire); if (quiet) - strvec_push(&prune, "--no-progress"); + strvec_push(&prune_cmd.args, "--no-progress"); if (repo_has_promisor_remote(the_repository)) - strvec_push(&prune, + strvec_push(&prune_cmd.args, "--exclude-promisor-objects"); prune_cmd.git_cmd = 1; - strvec_pushv(&prune_cmd.args, prune.v); + if (run_command(&prune_cmd)) - die(FAILED_RUN, prune.v[0]); + die(FAILED_RUN, prune_cmd.args.v[0]); } } - if (cfg.prune_worktrees_expire) { - struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT; + if (cfg.prune_worktrees_expire && + maintenance_task_worktree_prune(&opts, &cfg)) + die(FAILED_RUN, "worktree"); - strvec_push(&prune_worktrees, cfg.prune_worktrees_expire); - prune_worktrees_cmd.git_cmd = 1; - strvec_pushv(&prune_worktrees_cmd.args, prune_worktrees.v); - if (run_command(&prune_worktrees_cmd)) - die(FAILED_RUN, prune_worktrees.v[0]); - } - - rerere_cmd.git_cmd = 1; - strvec_pushv(&rerere_cmd.args, rerere.v); - if (run_command(&rerere_cmd)) - die(FAILED_RUN, rerere.v[0]); + if (maintenance_task_rerere_gc(&opts, &cfg)) + die(FAILED_RUN, "rerere"); report_garbage = report_pack_garbage; reprepare_packed_git(the_repository); @@ -1029,6 +1159,8 @@ static int run_write_commit_graph(struct maintenance_run_opts *opts) if (opts->quiet) strvec_push(&child.args, "--no-progress"); + else + strvec_push(&child.args, "--progress"); return !!run_command(&child); } @@ -1161,6 +1293,7 @@ static int write_loose_object_to_stdin(const struct object_id *oid, fprintf(d->in, "%s\n", oid_to_hex(oid)); + /* If batch_size is INT_MAX, then this will return 0 always. */ return ++(d->count) > d->batch_size; } @@ -1185,6 +1318,8 @@ static int pack_loose(struct maintenance_run_opts *opts) strvec_push(&pack_proc.args, "pack-objects"); if (opts->quiet) strvec_push(&pack_proc.args, "--quiet"); + else + strvec_push(&pack_proc.args, "--no-quiet"); strvec_pushf(&pack_proc.args, "%s/pack/loose", r->objects->odb->path); pack_proc.in = -1; @@ -1204,6 +1339,15 @@ static int pack_loose(struct maintenance_run_opts *opts) data.count = 0; data.batch_size = 50000; + repo_config_get_int(r, "maintenance.loose-objects.batchSize", + &data.batch_size); + + /* If configured as 0, then remove limit. */ + if (!data.batch_size) + data.batch_size = INT_MAX; + else if (data.batch_size > 0) + data.batch_size--; /* Decrease for equality on limit. */ + for_each_loose_file_in_objdir(r->objects->odb->path, write_loose_object_to_stdin, NULL, @@ -1263,6 +1407,8 @@ static int multi_pack_index_write(struct maintenance_run_opts *opts) if (opts->quiet) strvec_push(&child.args, "--no-progress"); + else + strvec_push(&child.args, "--progress"); if (run_command(&child)) return error(_("failed to write multi-pack-index")); @@ -1279,6 +1425,8 @@ static int multi_pack_index_expire(struct maintenance_run_opts *opts) if (opts->quiet) strvec_push(&child.args, "--no-progress"); + else + strvec_push(&child.args, "--progress"); if (run_command(&child)) return error(_("'git multi-pack-index expire' failed")); @@ -1335,6 +1483,8 @@ static int multi_pack_index_repack(struct maintenance_run_opts *opts) if (opts->quiet) strvec_push(&child.args, "--no-progress"); + else + strvec_push(&child.args, "--progress"); strvec_pushf(&child.args, "--batch-size=%"PRIuMAX, (uintmax_t)get_auto_pack_size()); @@ -1392,6 +1542,9 @@ enum maintenance_task_label { TASK_GC, TASK_COMMIT_GRAPH, TASK_PACK_REFS, + TASK_REFLOG_EXPIRE, + TASK_WORKTREE_PRUNE, + TASK_RERERE_GC, /* Leave as final value */ TASK__COUNT @@ -1428,6 +1581,21 @@ static struct maintenance_task tasks[] = { maintenance_task_pack_refs, pack_refs_condition, }, + [TASK_REFLOG_EXPIRE] = { + "reflog-expire", + maintenance_task_reflog_expire, + reflog_expire_condition, + }, + [TASK_WORKTREE_PRUNE] = { + "worktree-prune", + maintenance_task_worktree_prune, + worktree_prune_condition, + }, + [TASK_RERERE_GC] = { + "rerere-gc", + maintenance_task_rerere_gc, + rerere_gc_condition, + }, }; static int compare_tasks_by_selection(const void *a_, const void *b_) @@ -2075,7 +2243,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit case SCHEDULE_DAILY: repeat = "<dict>\n" - "<key>Day</key><integer>%d</integer>\n" + "<key>Weekday</key><integer>%d</integer>\n" "<key>Hour</key><integer>0</integer>\n" "<key>Minute</key><integer>%d</integer>\n" "</dict>\n"; @@ -2086,7 +2254,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit case SCHEDULE_WEEKLY: strbuf_addf(&plist, "<dict>\n" - "<key>Day</key><integer>0</integer>\n" + "<key>Weekday</key><integer>0</integer>\n" "<key>Hour</key><integer>0</integer>\n" "<key>Minute</key><integer>%d</integer>\n" "</dict>\n", @@ -2099,7 +2267,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit } strbuf_addstr(&plist, "</array>\n</dict>\n</plist>\n"); - if (safe_create_leading_directories(filename)) + if (safe_create_leading_directories(the_repository, filename)) die(_("failed to create directories for '%s'"), filename); if ((long)lock_file_timeout_ms < 0 && @@ -2565,7 +2733,7 @@ static int systemd_timer_write_timer_file(enum schedule_priority schedule, filename = xdg_config_home_systemd(local_timer_name); - if (safe_create_leading_directories(filename)) { + if (safe_create_leading_directories(the_repository, filename)) { error(_("failed to create directories for '%s'"), filename); goto error; } @@ -2638,7 +2806,7 @@ static int systemd_timer_write_service_template(const char *exec_path) char *local_service_name = xstrfmt(SYSTEMD_UNIT_FORMAT, "", "service"); filename = xdg_config_home_systemd(local_service_name); - if (safe_create_leading_directories(filename)) { + if (safe_create_leading_directories(the_repository, filename)) { error(_("failed to create directories for '%s'"), filename); goto error; } diff --git a/builtin/grep.c b/builtin/grep.c index d1427290f7..3ce574a605 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -26,7 +26,7 @@ #include "submodule-config.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "packfile.h" #include "pager.h" #include "path.h" @@ -453,7 +453,7 @@ static int grep_submodule(struct grep_opt *opt, return 0; subrepo = xmalloc(sizeof(*subrepo)); - if (repo_submodule_init(subrepo, superproject, path, null_oid())) { + if (repo_submodule_init(subrepo, superproject, path, null_oid(opt->repo->hash_algo))) { free(subrepo); return 0; } @@ -983,9 +983,9 @@ int cmd_grep(int argc, OPT_CALLBACK('C', "context", &opt, N_("n"), N_("show <n> context lines before and after matches"), context_callback), - OPT_INTEGER('B', "before-context", &opt.pre_context, + OPT_UNSIGNED('B', "before-context", &opt.pre_context, N_("show <n> context lines before matches")), - OPT_INTEGER('A', "after-context", &opt.post_context, + OPT_UNSIGNED('A', "after-context", &opt.post_context, N_("show <n> context lines after matches")), OPT_INTEGER(0, "threads", &num_threads, N_("use <n> worker threads")), @@ -1017,10 +1017,16 @@ int cmd_grep(int argc, OPT_BOOL(0, "all-match", &opt.all_match, N_("show only matches from files that match all patterns")), OPT_GROUP(""), - { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager, - N_("pager"), N_("show matching files in the pager"), - PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE, - NULL, (intptr_t)default_pager }, + { + .type = OPTION_STRING, + .short_name = 'O', + .long_name = "open-files-in-pager", + .value = &show_in_pager, + .argh = N_("pager"), + .help = N_("show matching files in the pager"), + .flags = PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE, + .defval = (intptr_t)default_pager, + }, OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored, N_("allow calling of grep(1) (ignored by this build)"), PARSE_OPT_NOCOMPLETE), @@ -1144,7 +1150,7 @@ int cmd_grep(int argc, break; } - object = parse_object_or_die(&oid, arg); + object = parse_object_or_die(the_repository, &oid, arg); if (!seen_dashdash) verify_non_filename(prefix, arg); add_object_array_with_path(object, arg, &list, oc.mode, oc.path); diff --git a/builtin/hash-object.c b/builtin/hash-object.c index a25f0403f4..6a99ec250d 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -11,7 +11,7 @@ #include "gettext.h" #include "hex.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "blob.h" #include "quote.h" #include "parse-options.h" @@ -19,38 +19,15 @@ #include "strbuf.h" #include "write-or-die.h" -/* - * This is to create corrupt objects for debugging and as such it - * needs to bypass the data conversion performed by, and the type - * limitation imposed by, index_fd() and its callees. - */ -static int hash_literally(struct object_id *oid, int fd, const char *type, unsigned flags) -{ - struct strbuf buf = STRBUF_INIT; - int ret; - - if (strbuf_read(&buf, fd, 4096) < 0) - ret = -1; - else - ret = write_object_file_literally(buf.buf, buf.len, type, oid, - flags); - close(fd); - strbuf_release(&buf); - return ret; -} - -static void hash_fd(int fd, const char *type, const char *path, unsigned flags, - int literally) +static void hash_fd(int fd, const char *type, const char *path, unsigned flags) { struct stat st; struct object_id oid; if (fstat(fd, &st) < 0 || - (literally - ? hash_literally(&oid, fd, type, flags) - : index_fd(the_repository->index, &oid, fd, &st, - type_from_string(type), path, flags))) - die((flags & HASH_WRITE_OBJECT) + index_fd(the_repository->index, &oid, fd, &st, + type_from_string(type), path, flags)) + die((flags & INDEX_WRITE_OBJECT) ? "Unable to add %s to database" : "Unable to hash %s", path); printf("%s\n", oid_to_hex(&oid)); @@ -58,15 +35,14 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags, } static void hash_object(const char *path, const char *type, const char *vpath, - unsigned flags, int literally) + unsigned flags) { int fd; fd = xopen(path, O_RDONLY); - hash_fd(fd, type, vpath, flags, literally); + hash_fd(fd, type, vpath, flags); } -static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, - int literally) +static void hash_stdin_paths(const char *type, int no_filters, unsigned flags) { struct strbuf buf = STRBUF_INIT; struct strbuf unquoted = STRBUF_INIT; @@ -78,8 +54,7 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, die("line is badly quoted"); strbuf_swap(&buf, &unquoted); } - hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags, - literally); + hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags); } strbuf_release(&buf); strbuf_release(&unquoted); @@ -100,19 +75,20 @@ int cmd_hash_object(int argc, int hashstdin = 0; int stdin_paths = 0; int no_filters = 0; - int literally = 0; int nongit = 0; - unsigned flags = HASH_FORMAT_CHECK; + unsigned flags = INDEX_FORMAT_CHECK; const char *vpath = NULL; char *vpath_free = NULL; const struct option hash_object_options[] = { OPT_STRING('t', NULL, &type, N_("type"), N_("object type")), OPT_BIT('w', NULL, &flags, N_("write the object into the object database"), - HASH_WRITE_OBJECT), + INDEX_WRITE_OBJECT), OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")), OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")), OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")), - OPT_BOOL( 0, "literally", &literally, N_("just hash any random garbage to create corrupt objects for debugging Git")), + OPT_NEGBIT( 0, "literally", &flags, + N_("just hash any random garbage to create corrupt objects for debugging Git"), + INDEX_FORMAT_CHECK), OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")), OPT_END() }; @@ -122,7 +98,7 @@ int cmd_hash_object(int argc, argc = parse_options(argc, argv, prefix, hash_object_options, hash_object_usage, 0); - if (flags & HASH_WRITE_OBJECT) + if (flags & INDEX_WRITE_OBJECT) prefix = setup_git_directory(); else prefix = setup_git_directory_gently(&nongit); @@ -158,7 +134,7 @@ int cmd_hash_object(int argc, } if (hashstdin) - hash_fd(0, type, vpath, flags, literally); + hash_fd(0, type, vpath, flags); for (i = 0 ; i < argc; i++) { const char *arg = argv[i]; @@ -167,12 +143,12 @@ int cmd_hash_object(int argc, if (prefix) arg = to_free = prefix_filename(prefix, arg); hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg, - flags, literally); + flags); free(to_free); } if (stdin_paths) - hash_stdin_paths(type, no_filters, flags, literally); + hash_stdin_paths(type, no_filters, flags); free(vpath_free); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 52cc97d52c..bb7925bd29 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -21,7 +21,7 @@ #include "packfile.h" #include "pack-revindex.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oid-array.h" #include "oidset.h" #include "path.h" @@ -279,14 +279,14 @@ static unsigned check_objects(void) { unsigned i, max, foreign_nr = 0; - max = get_max_object_index(); + max = get_max_object_index(the_repository); if (verbose) progress = start_delayed_progress(the_repository, _("Checking objects"), max); for (i = 0; i < max; i++) { - foreign_nr += check_object(get_indexed_object(i)); + foreign_nr += check_object(get_indexed_object(the_repository, i)); display_progress(progress, i + 1); } @@ -485,7 +485,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size, git_hash_update(&c, hdr, hdrlen); } else oid = NULL; - if (type == OBJ_BLOB && size > big_file_threshold) + if (type == OBJ_BLOB && + size > repo_settings_get_big_file_threshold(the_repository)) buf = fixed_buf; else buf = xmallocz(size); @@ -799,7 +800,8 @@ static int check_collison(struct object_entry *entry) enum object_type type; unsigned long size; - if (entry->size <= big_file_threshold || entry->type != OBJ_BLOB) + if (entry->size <= repo_settings_get_big_file_threshold(the_repository) || + entry->type != OBJ_BLOB) return -1; memset(&data, 0, sizeof(data)); @@ -890,9 +892,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, if (startup_info->have_repository) { read_lock(); - collision_test_needed = - repo_has_object_file_with_flags(the_repository, oid, - OBJECT_INFO_QUICK); + collision_test_needed = has_object(the_repository, oid, + HAS_OBJECT_FETCH_PROMISOR); read_unlock(); } @@ -1107,8 +1108,8 @@ static void *threaded_second_pass(void *data) set_thread_data(data); for (;;) { struct base_data *parent = NULL; - struct object_entry *child_obj; - struct base_data *child; + struct object_entry *child_obj = NULL; + struct base_data *child = NULL; counter_lock(); display_progress(progress, nr_resolved_deltas); @@ -1135,15 +1136,18 @@ static void *threaded_second_pass(void *data) parent = list_first_entry(&work_head, struct base_data, list); - if (parent->ref_first <= parent->ref_last) { + while (parent->ref_first <= parent->ref_last) { int offset = ref_deltas[parent->ref_first++].obj_no; child_obj = objects + offset; - if (child_obj->real_type != OBJ_REF_DELTA) - die("REF_DELTA at offset %"PRIuMAX" already resolved (duplicate base %s?)", - (uintmax_t) child_obj->idx.offset, - oid_to_hex(&parent->obj->idx.oid)); + if (child_obj->real_type != OBJ_REF_DELTA) { + child_obj = NULL; + continue; + } child_obj->real_type = parent->obj->real_type; - } else { + break; + } + + if (!child_obj && parent->ofs_first <= parent->ofs_last) { child_obj = objects + ofs_deltas[parent->ofs_first++].obj_no; assert(child_obj->real_type == OBJ_OFS_DELTA); @@ -1176,29 +1180,32 @@ static void *threaded_second_pass(void *data) } work_unlock(); - if (parent) { - child = resolve_delta(child_obj, parent); - if (!child->children_remaining) - FREE_AND_NULL(child->data); - } else { - child = make_base(child_obj, NULL); - if (child->children_remaining) { - /* - * Since this child has its own delta children, - * we will need this data in the future. - * Inflate now so that future iterations will - * have access to this object's data while - * outside the work mutex. - */ - child->data = get_data_from_pack(child_obj); - child->size = child_obj->size; + if (child_obj) { + if (parent) { + child = resolve_delta(child_obj, parent); + if (!child->children_remaining) + FREE_AND_NULL(child->data); + } else{ + child = make_base(child_obj, NULL); + if (child->children_remaining) { + /* + * Since this child has its own delta children, + * we will need this data in the future. + * Inflate now so that future iterations will + * have access to this object's data while + * outside the work mutex. + */ + child->data = get_data_from_pack(child_obj); + child->size = child_obj->size; + } } } work_lock(); if (parent) parent->retain_data--; - if (child->data) { + + if (child && child->data) { /* * This child has its own children, so add it to * work_head. @@ -1207,7 +1214,7 @@ static void *threaded_second_pass(void *data) base_cache_used += child->size; prune_base_data(NULL); free_base_data(child); - } else { + } else if (child) { /* * This child does not have its own children. It may be * the last descendant of its ancestors; free those @@ -1286,6 +1293,7 @@ static void parse_pack_objects(unsigned char *hash) /* Check pack integrity */ flush(); + the_hash_algo->init_fn(&tmp_ctx); git_hash_clone(&tmp_ctx, &input_ctx); git_hash_final(hash, &tmp_ctx); if (!hasheq(fill(the_hash_algo->rawsz), hash, the_repository->hash_algo)) @@ -1381,7 +1389,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha REALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1); memset(objects + nr_objects + 1, 0, nr_unresolved * sizeof(*objects)); - f = hashfd(output_fd, curr_pack); + f = hashfd(the_repository->hash_algo, output_fd, curr_pack); fix_unresolved_deltas(f); strbuf_addf(&msg, Q_("completed with %d local object", "completed with %d local objects", @@ -1562,7 +1570,7 @@ static void write_special_file(const char *suffix, const char *msg, else filename = odb_pack_name(the_repository, &name_buf, hash, suffix); - fd = odb_pack_keep(filename); + fd = safe_create_file_with_leading_directories(the_repository, filename); if (fd < 0) { if (errno != EEXIST) die_errno(_("cannot write %s file '%s'"), @@ -2088,10 +2096,10 @@ int cmd_index_pack(int argc, ALLOC_ARRAY(idx_objects, nr_objects); for (i = 0; i < nr_objects; i++) idx_objects[i] = &objects[i].idx; - curr_index = write_idx_file(the_hash_algo, index_name, idx_objects, + curr_index = write_idx_file(the_repository, index_name, idx_objects, nr_objects, &opts, pack_hash); if (rev_index) - curr_rev_index = write_rev_file(the_hash_algo, rev_index_name, + curr_rev_index = write_rev_file(the_repository, rev_index_name, idx_objects, nr_objects, pack_hash, opts.flags); free(idx_objects); diff --git a/builtin/init-db.c b/builtin/init-db.c index 196dccdd77..bb853e69f5 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -8,7 +8,6 @@ #include "abspath.h" #include "environment.h" #include "gettext.h" -#include "object-file.h" #include "parse-options.h" #include "path.h" #include "refs.h" @@ -93,10 +92,15 @@ int cmd_init_db(int argc, N_("directory from which templates will be used")), OPT_SET_INT(0, "bare", &is_bare_repository_cfg, N_("create a bare repository"), 1), - { OPTION_CALLBACK, 0, "shared", &init_shared_repository, - N_("permissions"), - N_("specify that the git repository is to be shared amongst several users"), - PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0}, + { + .type = OPTION_CALLBACK, + .long_name = "shared", + .value = &init_shared_repository, + .argh = N_("permissions"), + .help = N_("specify that the git repository is to be shared amongst several users"), + .flags = PARSE_OPT_OPTARG | PARSE_OPT_NONEG, + .callback = shared_callback + }, OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET), OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), N_("separate git dir from working tree")), @@ -134,7 +138,7 @@ int cmd_init_db(int argc, */ saved = repo_settings_get_shared_repository(the_repository); repo_settings_set_shared_repository(the_repository, 0); - switch (safe_create_leading_directories_const(argv[0])) { + switch (safe_create_leading_directories_const(the_repository, argv[0])) { case SCLD_OK: case SCLD_PERMS: break; diff --git a/builtin/log.c b/builtin/log.c index 1d0ae645ab..49cec1176a 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -14,9 +14,8 @@ #include "gettext.h" #include "hex.h" #include "refs.h" -#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "pager.h" #include "color.h" #include "commit.h" @@ -29,6 +28,7 @@ #include "tag.h" #include "reflog-walk.h" #include "patch-ids.h" +#include "path.h" #include "shortlog.h" #include "remote.h" #include "string-list.h" @@ -2330,7 +2330,7 @@ int cmd_format_patch(int argc, */ saved = repo_settings_get_shared_repository(the_repository); repo_settings_set_shared_repository(the_repository, 0); - switch (safe_create_leading_directories_const(output_directory)) { + switch (safe_create_leading_directories_const(the_repository, output_directory)) { case SCLD_OK: case SCLD_EXISTS: break; @@ -2487,7 +2487,7 @@ int cmd_format_patch(int argc, base = get_base_commit(&cfg, list, nr); if (base) { reset_revision_walk(); - clear_object_flags(UNINTERESTING); + clear_object_flags(the_repository, UNINTERESTING); prepare_bases(&bases, base, list, nr); } diff --git a/builtin/ls-files.c b/builtin/ls-files.c index a4431429b7..be74f0a03b 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -6,7 +6,6 @@ * Copyright (C) Linus Torvalds, 2005 */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -234,7 +233,8 @@ static void show_submodule(struct repository *superproject, { struct repository subrepo; - if (repo_submodule_init(&subrepo, superproject, path, null_oid())) + if (repo_submodule_init(&subrepo, superproject, path, + null_oid(superproject->hash_algo))) return; if (repo_read_index(&subrepo) < 0) @@ -245,12 +245,13 @@ static void show_submodule(struct repository *superproject, repo_clear(&subrepo); } -static void expand_objectsize(struct strbuf *line, const struct object_id *oid, +static void expand_objectsize(struct repository *repo, struct strbuf *line, + const struct object_id *oid, const enum object_type type, unsigned int padded) { if (type == OBJ_BLOB) { unsigned long size; - if (oid_object_info(the_repository, oid, &size) < 0) + if (oid_object_info(repo, oid, &size) < 0) die(_("could not get object info about '%s'"), oid_to_hex(oid)); if (padded) @@ -283,10 +284,10 @@ static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, else if (skip_prefix(format, "(objecttype)", &format)) strbuf_addstr(&sb, type_name(object_type(ce->ce_mode))); else if (skip_prefix(format, "(objectsize:padded)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 1); else if (skip_prefix(format, "(objectsize)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 0); else if (skip_prefix(format, "(stage)", &format)) strbuf_addf(&sb, "%d", ce_stage(ce)); @@ -348,7 +349,7 @@ static void show_ce(struct repository *repo, struct dir_struct *dir, } } -static void show_ru_info(struct index_state *istate) +static void show_ru_info(struct repository *repo, struct index_state *istate) { struct string_list_item *item; @@ -370,7 +371,7 @@ static void show_ru_info(struct index_state *istate) if (!ui->mode[i]) continue; printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], - repo_find_unique_abbrev(the_repository, &ui->oid[i], abbrev), + repo_find_unique_abbrev(repo, &ui->oid[i], abbrev), i + 1); write_name(path); } @@ -567,7 +568,7 @@ static int option_parse_exclude_standard(const struct option *opt, int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix, - struct repository *repo UNUSED) + struct repository *repo) { int require_work_tree = 0, show_tag = 0, i; char *max_prefix; @@ -647,15 +648,15 @@ int cmd_ls_files(int argc, show_usage_with_options_if_asked(argc, argv, ls_files_usage, builtin_ls_files_options); - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; prefix = cmd_prefix; if (prefix) prefix_len = strlen(prefix); - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - if (repo_read_index(the_repository) < 0) + if (repo_read_index(repo) < 0) die("index file corrupt"); argc = parse_options(argc, argv, prefix, builtin_ls_files_options, @@ -724,7 +725,7 @@ int cmd_ls_files(int argc, max_prefix = common_prefix(&pathspec); max_prefix_len = get_common_prefix_len(max_prefix); - prune_index(the_repository->index, max_prefix, max_prefix_len); + prune_index(repo->index, max_prefix, max_prefix_len); /* Treat unmatching pathspec elements as errors */ if (pathspec.nr && error_unmatch) @@ -748,13 +749,13 @@ int cmd_ls_files(int argc, */ if (show_stage || show_unmerged) die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u"); - overlay_tree_on_index(the_repository->index, with_tree, max_prefix); + overlay_tree_on_index(repo->index, with_tree, max_prefix); } - show_files(the_repository, &dir); + show_files(repo, &dir); if (show_resolve_undo) - show_ru_info(the_repository->index); + show_ru_info(repo, repo->index); if (ps_matched && report_path_error(ps_matched, &pathspec)) { fprintf(stderr, "Did you forget to 'git add'?\n"); diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 42f34e1236..01a4d4daa1 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -67,9 +67,14 @@ int cmd_ls_remote(int argc, OPT__QUIET(&quiet, N_("do not print remote URL")), OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"), N_("path of git-upload-pack on the remote host")), - { OPTION_STRING, 0, "exec", &uploadpack, N_("exec"), - N_("path of git-upload-pack on the remote host"), - PARSE_OPT_HIDDEN }, + { + .type = OPTION_STRING, + .long_name = "exec", + .value = &uploadpack, + .argh = N_("exec"), + .help = N_("path of git-upload-pack on the remote host"), + .flags = PARSE_OPT_HIDDEN, + }, OPT_BIT('t', "tags", &flags, N_("limit to tags"), REF_TAGS), OPT_BIT('b', "branches", &flags, N_("limit to branches"), REF_BRANCHES), OPT_BIT_F('h', "heads", &flags, diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 8542b5d53e..8aafc30ca4 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -10,7 +10,7 @@ #include "gettext.h" #include "hex.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "tree.h" #include "path.h" #include "quote.h" diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 7e315f374b..2b16b10d2c 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -5,6 +5,7 @@ #include "abspath.h" #include "diff.h" #include "hex.h" +#include "object-file.h" #include "object-name.h" #include "object-store.h" #include "config.h" diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index abfc060e28..03b5100cfa 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -3,7 +3,7 @@ #include "advice.h" #include "gettext.h" #include "hash.h" -#include "merge-recursive.h" +#include "merge-ort-wrappers.h" #include "object-name.h" static const char builtin_merge_recursive_usage[] = @@ -89,7 +89,7 @@ int cmd_merge_recursive(int argc, if (o.verbosity >= 3) printf(_("Merging %s with %s\n"), o.branch1, o.branch2); - failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result); + failed = merge_ort_generic(&o, &h1, &h2, bases_count, bases, &result); free(better1); free(better2); diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 3ec7127b3a..7f41665dfd 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -10,7 +10,7 @@ #include "commit-reach.h" #include "merge-ort.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "parse-options.h" #include "blob.h" #include "merge-blobs.h" @@ -490,6 +490,9 @@ static int real_merge(struct merge_tree_options *o, if (result.clean < 0) die(_("failure to merge")); + if (o->merge_options.mergeability_only) + goto cleanup; + if (show_messages == -1) show_messages = !result.clean; @@ -522,6 +525,8 @@ static int real_merge(struct merge_tree_options *o, } if (o->use_stdin) putchar(line_termination); + +cleanup: merge_finalize(&opt, &result); clear_merge_options(&opt); return !result.clean; /* result.clean < 0 handled above */ @@ -538,6 +543,7 @@ int cmd_merge_tree(int argc, int original_argc; const char *merge_base = NULL; int ret; + int quiet = 0; const char * const merge_tree_usage[] = { N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"), @@ -552,6 +558,10 @@ int cmd_merge_tree(int argc, N_("do a trivial merge only"), MODE_TRIVIAL), OPT_BOOL(0, "messages", &o.show_messages, N_("also show informational/conflict messages")), + OPT_BOOL_F(0, "quiet", + &quiet, + N_("suppress all output; only exit status wanted"), + PARSE_OPT_NONEG), OPT_SET_INT('z', NULL, &line_termination, N_("separate paths with the NUL character"), '\0'), OPT_BOOL_F(0, "name-only", @@ -583,6 +593,14 @@ int cmd_merge_tree(int argc, argc = parse_options(argc, argv, prefix, mt_options, merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION); + if (quiet && o.show_messages == -1) + o.show_messages = 0; + o.merge_options.mergeability_only = quiet; + die_for_incompatible_opt2(quiet, "--quiet", o.show_messages, "--messages"); + die_for_incompatible_opt2(quiet, "--quiet", o.name_only, "--name-only"); + die_for_incompatible_opt2(quiet, "--quiet", o.use_stdin, "--stdin"); + die_for_incompatible_opt2(quiet, "--quiet", !line_termination, "-z"); + if (xopts.nr && o.mode == MODE_TRIVIAL) die(_("--trivial-merge is incompatible with all other options")); for (size_t x = 0; x < xopts.nr; x++) diff --git a/builtin/merge.c b/builtin/merge.c index ba9faf126a..ce90e52fe4 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -39,7 +39,6 @@ #include "rerere.h" #include "help.h" #include "merge.h" -#include "merge-recursive.h" #include "merge-ort-wrappers.h" #include "resolve-undo.h" #include "remote.h" @@ -171,7 +170,7 @@ static struct strategy *get_strategy(const char *name) struct strategy *ret; static struct cmdnames main_cmds = {0}, other_cmds = {0}; static int loaded; - char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM"); + char *default_strategy = NULL; if (!name) return NULL; @@ -250,9 +249,16 @@ static struct option builtin_merge_options[] = { OPT_BOOL(0, "stat", &show_diffstat, N_("show a diffstat at the end of the merge")), OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")), - { OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"), - N_("add (at most <n>) entries from shortlog to merge commit message"), - PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN }, + { + .type = OPTION_INTEGER, + .long_name = "log", + .value = &shortlog_len, + .precision = sizeof(shortlog_len), + .argh = N_("n"), + .help = N_("add (at most <n>) entries from shortlog to merge commit message"), + .flags = PARSE_OPT_OPTARG, + .defval = DEFAULT_MERGE_LOG_LEN, + }, OPT_BOOL(0, "squash", &squash, N_("create a single commit instead of doing a merge")), OPT_BOOL(0, "commit", &option_commit, @@ -274,9 +280,16 @@ static struct option builtin_merge_options[] = { OPT_CALLBACK('m', "message", &merge_msg, N_("message"), N_("merge commit message (for a non-fast-forward merge)"), option_parse_message), - { OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"), - N_("read message from file"), PARSE_OPT_NONEG, - NULL, 0, option_read_message }, + { + .type = OPTION_LOWLEVEL_CALLBACK, + .short_name = 'F', + .long_name = "file", + .value = &merge_msg, + .argh = N_("path"), + .help = N_("read message from file"), + .flags = PARSE_OPT_NONEG, + .ll_callback = option_read_message, + }, OPT_STRING(0, "into-name", &into_name, N_("name"), N_("use <name> instead of the real target")), OPT__VERBOSITY(&verbosity), @@ -289,8 +302,16 @@ static struct option builtin_merge_options[] = { OPT_BOOL(0, "allow-unrelated-histories", &allow_unrelated_histories, N_("allow merging unrelated histories")), OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1), - { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"), - N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, + { + .type = OPTION_STRING, + .short_name = 'S', + .long_name = "gpg-sign", + .value = &sign_commit, + .argh = N_("key-id"), + .help = N_("GPG sign commit"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "", + }, OPT_AUTOSTASH(&autostash), OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")), OPT_BOOL(0, "signoff", &signoff, N_("add a Signed-off-by trailer")), @@ -750,12 +771,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR); - if (!strcmp(strategy, "ort")) - clean = merge_ort_recursive(&o, head, remoteheads->item, - reversed, &result); - else - clean = merge_recursive(&o, head, remoteheads->item, - reversed, &result); + clean = merge_ort_recursive(&o, head, remoteheads->item, + reversed, &result); free_commit_list(reversed); strbuf_release(&o.obuf); @@ -1316,12 +1333,6 @@ int cmd_merge(int argc, if (branch) skip_prefix(branch, "refs/heads/", &branch); - if (!pull_twohead) { - char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM"); - if (default_strategy && !strcmp(default_strategy, "ort")) - pull_twohead = xstrdup("ort"); - } - init_diff_ui_defaults(); git_config(git_merge_config, NULL); @@ -1522,12 +1533,6 @@ int cmd_merge(int argc, fast_forward = FF_NO; } - if (!use_strategies && !pull_twohead && - remoteheads && !remoteheads->next) { - char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM"); - if (default_strategy) - append_strategy(get_strategy(default_strategy)); - } if (!use_strategies) { if (!remoteheads) ; /* already up-to-date */ diff --git a/builtin/mktag.c b/builtin/mktag.c index 6e188dce50..1b1dc0263e 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -6,7 +6,7 @@ #include "strbuf.h" #include "replace-object.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "fsck.h" #include "config.h" @@ -41,7 +41,7 @@ static int mktag_fsck_error_func(struct fsck_options *o UNUSED, fprintf_ln(stderr, _("error: tag input does not pass fsck: %s"), message); return 1; default: - BUG(_("%d (FSCK_IGNORE?) should never trigger this callback"), + BUG("%d (FSCK_IGNORE?) should never trigger this callback", msg_type); } } diff --git a/builtin/mktree.c b/builtin/mktree.c index 3c16faa40e..4b47803467 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -11,7 +11,8 @@ #include "strbuf.h" #include "tree.h" #include "parse-options.h" -#include "object-store-ll.h" +#include "object-file.h" +#include "object-store.h" static struct treeent { unsigned mode; @@ -66,7 +67,7 @@ static void write_tree(struct object_id *oid) strbuf_release(&buf); } -static const char *mktree_usage[] = { +static const char *const mktree_usage[] = { "git mktree [-z] [--missing] [--batch]", NULL }; diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c index 2a938466f5..69a9750732 100644 --- a/builtin/multi-pack-index.c +++ b/builtin/multi-pack-index.c @@ -7,7 +7,7 @@ #include "midx.h" #include "strbuf.h" #include "trace2.h" -#include "object-store-ll.h" +#include "object-store.h" #include "replace-object.h" #include "repository.h" @@ -245,7 +245,7 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv, { struct option *options; static struct option builtin_multi_pack_index_repack_options[] = { - OPT_MAGNITUDE(0, "batch-size", &opts.batch_size, + OPT_UNSIGNED(0, "batch-size", &opts.batch_size, N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")), OPT_BIT(0, "progress", &opts.flags, N_("force progress reporting"), MIDX_PROGRESS), diff --git a/builtin/mv.c b/builtin/mv.c index 55a7d471dc..07548fe96a 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -15,6 +15,7 @@ #include "gettext.h" #include "name-hash.h" #include "object-file.h" +#include "path.h" #include "pathspec.h" #include "lockfile.h" #include "dir.h" @@ -28,7 +29,8 @@ #include "entry.h" static const char * const builtin_mv_usage[] = { - N_("git mv [<options>] <source>... <destination>"), + N_("git mv [-v] [-f] [-n] [-k] <source> <destination>"), + N_("git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>"), NULL }; @@ -37,6 +39,13 @@ enum update_mode { INDEX = (1 << 2), SPARSE = (1 << 3), SKIP_WORKTREE_DIR = (1 << 4), + /* + * A file gets moved implicitly via a move of one of its parent + * directories. This flag causes us to skip the check that we don't try + * to move a file and any of its parent directories at the same point + * in time. + */ + MOVE_VIA_PARENT_DIR = (1 << 5), }; #define DUP_BASENAME 1 @@ -181,6 +190,21 @@ static void remove_empty_src_dirs(const char **src_dir, size_t src_dir_nr) strbuf_release(&a_src_dir); } +struct pathmap_entry { + struct hashmap_entry ent; + const char *path; +}; + +static int pathmap_cmp(const void *cmp_data UNUSED, + const struct hashmap_entry *a, + const struct hashmap_entry *b, + const void *key UNUSED) +{ + const struct pathmap_entry *e1 = container_of(a, struct pathmap_entry, ent); + const struct pathmap_entry *e2 = container_of(b, struct pathmap_entry, ent); + return fspathcmp(e1->path, e2->path); +} + int cmd_mv(int argc, const char **argv, const char *prefix, @@ -211,6 +235,8 @@ int cmd_mv(int argc, struct cache_entry *ce; struct string_list only_match_skip_worktree = STRING_LIST_INIT_DUP; struct string_list dirty_paths = STRING_LIST_INIT_DUP; + struct hashmap moved_dirs = HASHMAP_INIT(pathmap_cmp, NULL); + struct strbuf pathbuf = STRBUF_INIT; int ret; git_config(git_default_config, NULL); @@ -329,6 +355,7 @@ int cmd_mv(int argc, dir_check: if (S_ISDIR(st.st_mode)) { + struct pathmap_entry *entry; char *dst_with_slash; size_t dst_with_slash_len; int j, n; @@ -346,6 +373,11 @@ dir_check: goto act_on_entry; } + entry = xmalloc(sizeof(*entry)); + entry->path = src; + hashmap_entry_init(&entry->ent, fspathhash(src)); + hashmap_add(&moved_dirs, &entry->ent); + /* last - first >= 1 */ modes[i] |= WORKING_DIRECTORY; @@ -366,8 +398,7 @@ dir_check: strvec_push(&sources, path); strvec_push(&destinations, prefixed_path); - memset(modes + argc + j, 0, sizeof(enum update_mode)); - modes[argc + j] |= ce_skip_worktree(ce) ? SPARSE : INDEX; + modes[argc + j] = MOVE_VIA_PARENT_DIR | (ce_skip_worktree(ce) ? SPARSE : INDEX); submodule_gitfiles[argc + j] = NULL; free(prefixed_path); @@ -463,6 +494,32 @@ remove_entry: } } + for (i = 0; i < argc; i++) { + const char *slash_pos; + + if (modes[i] & MOVE_VIA_PARENT_DIR) + continue; + + strbuf_reset(&pathbuf); + strbuf_addstr(&pathbuf, sources.v[i]); + + slash_pos = strrchr(pathbuf.buf, '/'); + while (slash_pos > pathbuf.buf) { + struct pathmap_entry needle; + + strbuf_setlen(&pathbuf, slash_pos - pathbuf.buf); + + needle.path = pathbuf.buf; + hashmap_entry_init(&needle.ent, fspathhash(pathbuf.buf)); + + if (hashmap_get_entry(&moved_dirs, &needle, ent, NULL)) + die(_("cannot move both '%s' and its parent directory '%s'"), + sources.v[i], pathbuf.buf); + + slash_pos = strrchr(pathbuf.buf, '/'); + } + } + if (only_match_skip_worktree.nr) { advise_on_updating_sparse_paths(&only_match_skip_worktree); if (!ignore_errors) { @@ -505,7 +562,8 @@ remove_entry: continue; pos = index_name_pos(the_repository->index, src, strlen(src)); - assert(pos >= 0); + if (pos < 0) + BUG("could not find source in index: '%s'", src); if (!(mode & SPARSE) && !lstat(src, &st)) sparse_and_dirty = ie_modified(the_repository->index, the_repository->index->cache[pos], @@ -555,7 +613,7 @@ remove_entry: */ char *dst_dup = xstrdup(dst); string_list_append(&dirty_paths, dst); - safe_create_leading_directories(dst_dup); + safe_create_leading_directories(the_repository, dst_dup); FREE_AND_NULL(dst_dup); rename(src, dst); } @@ -587,6 +645,8 @@ out: strvec_clear(&dest_paths); strvec_clear(&destinations); strvec_clear(&submodule_gitfiles_to_free); + hashmap_clear_and_free(&moved_dirs, struct pathmap_entry, ent); + strbuf_release(&pathbuf); free(submodule_gitfiles); free(modes); return ret; diff --git a/builtin/name-rev.c b/builtin/name-rev.c index beac166b5c..ff199638de 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -567,7 +567,11 @@ int cmd_name_rev(int argc, { 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; + +#ifndef WITH_BREAKING_CHANGES + int transform_stdin = 0; +#endif + int all = 0, annotate_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 }; struct option opts[] = { OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")), @@ -578,11 +582,13 @@ int cmd_name_rev(int argc, N_("ignore refs matching <pattern>")), OPT_GROUP(""), OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")), +#ifndef WITH_BREAKING_CHANGES OPT_BOOL_F(0, "stdin", &transform_stdin, N_("deprecated: use --annotate-stdin instead"), PARSE_OPT_HIDDEN), +#endif /* WITH_BREAKING_CHANGES */ OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")), OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")), OPT_BOOL(0, "always", &always, @@ -597,12 +603,14 @@ int cmd_name_rev(int argc, git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0); +#ifndef WITH_BREAKING_CHANGES if (transform_stdin) { warning("--stdin is deprecated. Please use --annotate-stdin instead, " "which is functionally equivalent.\n" "This option will be removed in a future release."); annotate_stdin = 1; } +#endif if (all + annotate_stdin + !!argc > 1) { error("Specify either a list, or --all, not both!"); @@ -667,9 +675,9 @@ int cmd_name_rev(int argc, } else if (all) { int i, max; - max = get_max_object_index(); + max = get_max_object_index(the_repository); for (i = 0; i < max; i++) { - struct object *obj = get_indexed_object(i); + struct object *obj = get_indexed_object(the_repository, i); if (!obj || obj->type != OBJ_COMMIT) continue; show_name(obj, NULL, diff --git a/builtin/notes.c b/builtin/notes.c index ff61ec5f2d..a3f433ca4c 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -14,8 +14,9 @@ #include "gettext.h" #include "hex.h" #include "notes.h" +#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "pretty.h" diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 58a9b16126..67941c8a60 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -32,7 +32,7 @@ #include "list.h" #include "packfile.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "replace-object.h" #include "dir.h" #include "midx.h" @@ -41,6 +41,10 @@ #include "promisor-remote.h" #include "pack-mtimes.h" #include "parse-options.h" +#include "blob.h" +#include "tree.h" +#include "path-walk.h" +#include "trace2.h" /* * Objects we are going to pack are collected in the `to_pack` structure. @@ -183,9 +187,15 @@ static inline void oe_set_delta_size(struct packing_data *pack, #define SET_DELTA_CHILD(obj, val) oe_set_delta_child(&to_pack, obj, val) #define SET_DELTA_SIBLING(obj, val) oe_set_delta_sibling(&to_pack, obj, val) -static const char *pack_usage[] = { - N_("git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"), - N_("git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"), +static const char *const pack_usage[] = { + N_("git pack-objects [-q | --progress | --all-progress] [--all-progress-implied]\n" + " [--no-reuse-delta] [--delta-base-offset] [--non-empty]\n" + " [--local] [--incremental] [--window=<n>] [--depth=<n>]\n" + " [--revs [--unpacked | --all]] [--keep-pack=<pack-name>]\n" + " [--cruft] [--cruft-expiration=<time>]\n" + " [--stdout [--filter=<filter-spec>] | <base-name>]\n" + " [--shallow] [--keep-true-parents] [--[no-]sparse]\n" + " [--name-hash-version=<n>] [--path-walk] < <object-list>"), NULL }; @@ -200,12 +210,14 @@ static int keep_unreachable, unpack_unreachable, include_tag; static timestamp_t unpack_unreachable_expiration; static int pack_loose_unreachable; static int cruft; +static int shallow = 0; static timestamp_t cruft_expiration; static int local; static int have_non_local_packs; static int incremental; static int ignore_packed_keep_on_disk; static int ignore_packed_keep_in_core; +static int ignore_packed_keep_in_core_has_cruft; static int allow_ofs_delta; static struct pack_idx_option pack_idx_opts; static const char *base_name; @@ -217,6 +229,7 @@ static int delta_search_threads; static int pack_to_stdout; static int sparse; static int thin; +static int path_walk = -1; static int num_preferred_base; static struct progress *progress_state; @@ -499,7 +512,8 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent if (!usable_delta) { if (oe_type(entry) == OBJ_BLOB && - oe_size_greater_than(&to_pack, entry, big_file_threshold) && + oe_size_greater_than(&to_pack, entry, + repo_settings_get_big_file_threshold(the_repository)) && (st = open_istream(the_repository, &entry->idx.oid, &type, &size, NULL)) != NULL) buf = NULL; @@ -1311,9 +1325,10 @@ static void write_pack_file(void) char *pack_tmp_name = NULL; if (pack_to_stdout) - f = hashfd_throughput(1, "<stdout>", progress_state); + f = hashfd_throughput(the_repository->hash_algo, 1, + "<stdout>", progress_state); else - f = create_tmp_packfile(&pack_tmp_name); + f = create_tmp_packfile(the_repository, &pack_tmp_name); offset = write_pack_header(f, nr_remaining); @@ -1397,7 +1412,8 @@ static void write_pack_file(void) if (write_bitmap_index) { bitmap_writer_init(&bitmap_writer, - the_repository, &to_pack); + the_repository, &to_pack, + NULL); bitmap_writer_set_checksum(&bitmap_writer, hash); bitmap_writer_build_type_index(&bitmap_writer, written_list); @@ -1406,7 +1422,7 @@ static void write_pack_file(void) if (cruft) pack_idx_opts.flags |= WRITE_MTIMES; - stage_tmp_packfiles(the_hash_algo, &tmpname, + stage_tmp_packfiles(the_repository, &tmpname, pack_tmp_name, written_list, nr_written, &to_pack, &pack_idx_opts, hash, @@ -1502,8 +1518,60 @@ static int have_duplicate_entry(const struct object_id *oid, return 1; } +static int want_cruft_object_mtime(struct repository *r, + const struct object_id *oid, + unsigned flags, uint32_t mtime) +{ + struct packed_git **cache; + + for (cache = kept_pack_cache(r, flags); *cache; cache++) { + struct packed_git *p = *cache; + off_t ofs; + uint32_t candidate_mtime; + + ofs = find_pack_entry_one(oid, p); + if (!ofs) + continue; + + /* + * We have a copy of the object 'oid' in a non-cruft + * pack. We can avoid packing an additional copy + * regardless of what the existing copy's mtime is since + * it is outside of a cruft pack. + */ + if (!p->is_cruft) + return 0; + + /* + * If we have a copy of the object 'oid' in a cruft + * pack, then either read the cruft pack's mtime for + * that object, or, if that can't be loaded, assume the + * pack's mtime itself. + */ + if (!load_pack_mtimes(p)) { + uint32_t pos; + if (offset_to_pack_pos(p, ofs, &pos) < 0) + continue; + candidate_mtime = nth_packed_mtime(p, pos); + } else { + candidate_mtime = p->mtime; + } + + /* + * We have a surviving copy of the object in a cruft + * pack whose mtime is greater than or equal to the one + * we are considering. We can thus avoid packing an + * additional copy of that object. + */ + if (mtime <= candidate_mtime) + return 0; + } + + return -1; +} + static int want_found_object(const struct object_id *oid, int exclude, - struct packed_git *p) + struct packed_git *p, uint32_t mtime) { if (exclude) return 1; @@ -1553,12 +1621,29 @@ static int want_found_object(const struct object_id *oid, int exclude, if (ignore_packed_keep_in_core) flags |= IN_CORE_KEEP_PACKS; - if (ignore_packed_keep_on_disk && p->pack_keep) - return 0; - if (ignore_packed_keep_in_core && p->pack_keep_in_core) - return 0; - if (has_object_kept_pack(p->repo, oid, flags)) - return 0; + /* + * If the object is in a pack that we want to ignore, *and* we + * don't have any cruft packs that are being retained, we can + * abort quickly. + */ + if (!ignore_packed_keep_in_core_has_cruft) { + if (ignore_packed_keep_on_disk && p->pack_keep) + return 0; + if (ignore_packed_keep_in_core && p->pack_keep_in_core) + return 0; + if (has_object_kept_pack(p->repo, oid, flags)) + return 0; + } else { + /* + * But if there is at least one cruft pack which + * is being kept, we only want to include the + * provided object if it has a strictly greater + * mtime than any existing cruft copy. + */ + if (!want_cruft_object_mtime(p->repo, oid, flags, + mtime)) + return 0; + } } /* @@ -1577,7 +1662,8 @@ static int want_object_in_pack_one(struct packed_git *p, const struct object_id *oid, int exclude, struct packed_git **found_pack, - off_t *found_offset) + off_t *found_offset, + uint32_t found_mtime) { off_t offset; @@ -1593,7 +1679,7 @@ static int want_object_in_pack_one(struct packed_git *p, *found_offset = offset; *found_pack = p; } - return want_found_object(oid, exclude, p); + return want_found_object(oid, exclude, p, found_mtime); } return -1; } @@ -1607,10 +1693,11 @@ static int want_object_in_pack_one(struct packed_git *p, * function finds if there is any pack that has the object and returns the pack * and its offset in these variables. */ -static int want_object_in_pack(const struct object_id *oid, - int exclude, - struct packed_git **found_pack, - off_t *found_offset) +static int want_object_in_pack_mtime(const struct object_id *oid, + int exclude, + struct packed_git **found_pack, + off_t *found_offset, + uint32_t found_mtime) { int want; struct list_head *pos; @@ -1625,7 +1712,8 @@ static int want_object_in_pack(const struct object_id *oid, * are present we will determine the answer right now. */ if (*found_pack) { - want = want_found_object(oid, exclude, *found_pack); + want = want_found_object(oid, exclude, *found_pack, + found_mtime); if (want != -1) return want; @@ -1636,7 +1724,7 @@ static int want_object_in_pack(const struct object_id *oid, for (m = get_multi_pack_index(the_repository); m; m = m->next) { struct pack_entry e; if (fill_midx_entry(the_repository, oid, &e, m)) { - want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset); + want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime); if (want != -1) return want; } @@ -1644,7 +1732,7 @@ static int want_object_in_pack(const struct object_id *oid, list_for_each(pos, get_packed_git_mru(the_repository)) { struct packed_git *p = list_entry(pos, struct packed_git, mru); - want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset); + want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime); if (!exclude && want > 0) list_move(&p->mru, get_packed_git_mru(the_repository)); @@ -1674,6 +1762,15 @@ static int want_object_in_pack(const struct object_id *oid, return 1; } +static inline int want_object_in_pack(const struct object_id *oid, + int exclude, + struct packed_git **found_pack, + off_t *found_offset) +{ + return want_object_in_pack_mtime(oid, exclude, found_pack, found_offset, + 0); +} + static struct object_entry *create_object_entry(const struct object_id *oid, enum object_type type, uint32_t hash, @@ -1735,7 +1832,8 @@ static int add_object_entry(const struct object_id *oid, enum object_type type, static int add_object_entry_from_bitmap(const struct object_id *oid, enum object_type type, int flags UNUSED, uint32_t name_hash, - struct packed_git *pack, off_t offset) + struct packed_git *pack, off_t offset, + void *payload UNUSED) { display_progress(progress_state, ++nr_seen); @@ -2453,7 +2551,8 @@ static void get_object_details(void) struct object_entry *entry = sorted_by_offset[i]; check_object(entry, i); if (entry->type_valid && - oe_size_greater_than(&to_pack, entry, big_file_threshold)) + oe_size_greater_than(&to_pack, entry, + repo_settings_get_big_file_threshold(the_repository))) entry->no_try_delta = 1; display_progress(progress_state, i + 1); } @@ -2954,6 +3053,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size, struct thread_params { pthread_t thread; struct object_entry **list; + struct packing_region *regions; unsigned list_size; unsigned remaining; int window; @@ -3196,6 +3296,242 @@ static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, cons return 0; } +static int should_attempt_deltas(struct object_entry *entry) +{ + if (DELTA(entry)) + /* This happens if we decided to reuse existing + * delta from a pack. "reuse_delta &&" is implied. + */ + return 0; + + if (!entry->type_valid || + oe_size_less_than(&to_pack, entry, 50)) + return 0; + + if (entry->no_try_delta) + return 0; + + if (!entry->preferred_base) { + if (oe_type(entry) < 0) + die(_("unable to get type of object %s"), + oid_to_hex(&entry->idx.oid)); + } else if (oe_type(entry) < 0) { + /* + * This object is not found, but we + * don't have to include it anyway. + */ + return 0; + } + + return 1; +} + +static void find_deltas_for_region(struct object_entry *list, + struct packing_region *region, + unsigned int *processed) +{ + struct object_entry **delta_list; + unsigned int delta_list_nr = 0; + + ALLOC_ARRAY(delta_list, region->nr); + for (size_t i = 0; i < region->nr; i++) { + struct object_entry *entry = list + region->start + i; + if (should_attempt_deltas(entry)) + delta_list[delta_list_nr++] = entry; + } + + QSORT(delta_list, delta_list_nr, type_size_sort); + find_deltas(delta_list, &delta_list_nr, window, depth, processed); + free(delta_list); +} + +static void find_deltas_by_region(struct object_entry *list, + struct packing_region *regions, + size_t start, size_t nr) +{ + unsigned int processed = 0; + size_t progress_nr; + + if (!nr) + return; + + progress_nr = regions[nr - 1].start + regions[nr - 1].nr; + + if (progress) + progress_state = start_progress(the_repository, + _("Compressing objects by path"), + progress_nr); + + while (nr--) + find_deltas_for_region(list, + ®ions[start++], + &processed); + + display_progress(progress_state, progress_nr); + stop_progress(&progress_state); +} + +static void *threaded_find_deltas_by_path(void *arg) +{ + struct thread_params *me = arg; + + progress_lock(); + while (me->remaining) { + while (me->remaining) { + progress_unlock(); + find_deltas_for_region(to_pack.objects, + me->regions, + me->processed); + progress_lock(); + me->remaining--; + me->regions++; + } + + me->working = 0; + pthread_cond_signal(&progress_cond); + progress_unlock(); + + /* + * We must not set ->data_ready before we wait on the + * condition because the main thread may have set it to 1 + * before we get here. In order to be sure that new + * work is available if we see 1 in ->data_ready, it + * was initialized to 0 before this thread was spawned + * and we reset it to 0 right away. + */ + pthread_mutex_lock(&me->mutex); + while (!me->data_ready) + pthread_cond_wait(&me->cond, &me->mutex); + me->data_ready = 0; + pthread_mutex_unlock(&me->mutex); + + progress_lock(); + } + progress_unlock(); + /* leave ->working 1 so that this doesn't get more work assigned */ + return NULL; +} + +static void ll_find_deltas_by_region(struct object_entry *list, + struct packing_region *regions, + uint32_t start, uint32_t nr) +{ + struct thread_params *p; + int i, ret, active_threads = 0; + unsigned int processed = 0; + uint32_t progress_nr; + init_threaded_search(); + + if (!nr) + return; + + progress_nr = regions[nr - 1].start + regions[nr - 1].nr; + if (delta_search_threads <= 1) { + find_deltas_by_region(list, regions, start, nr); + cleanup_threaded_search(); + return; + } + + if (progress > pack_to_stdout) + fprintf_ln(stderr, + Q_("Path-based delta compression using up to %d thread", + "Path-based delta compression using up to %d threads", + delta_search_threads), + delta_search_threads); + CALLOC_ARRAY(p, delta_search_threads); + + if (progress) + progress_state = start_progress(the_repository, + _("Compressing objects by path"), + progress_nr); + /* Partition the work amongst work threads. */ + for (i = 0; i < delta_search_threads; i++) { + unsigned sub_size = nr / (delta_search_threads - i); + + p[i].window = window; + p[i].depth = depth; + p[i].processed = &processed; + p[i].working = 1; + p[i].data_ready = 0; + + p[i].regions = regions; + p[i].list_size = sub_size; + p[i].remaining = sub_size; + + regions += sub_size; + nr -= sub_size; + } + + /* Start work threads. */ + for (i = 0; i < delta_search_threads; i++) { + if (!p[i].list_size) + continue; + pthread_mutex_init(&p[i].mutex, NULL); + pthread_cond_init(&p[i].cond, NULL); + ret = pthread_create(&p[i].thread, NULL, + threaded_find_deltas_by_path, &p[i]); + if (ret) + die(_("unable to create thread: %s"), strerror(ret)); + active_threads++; + } + + /* + * Now let's wait for work completion. Each time a thread is done + * with its work, we steal half of the remaining work from the + * thread with the largest number of unprocessed objects and give + * it to that newly idle thread. This ensure good load balancing + * until the remaining object list segments are simply too short + * to be worth splitting anymore. + */ + while (active_threads) { + struct thread_params *target = NULL; + struct thread_params *victim = NULL; + unsigned sub_size = 0; + + progress_lock(); + for (;;) { + for (i = 0; !target && i < delta_search_threads; i++) + if (!p[i].working) + target = &p[i]; + if (target) + break; + pthread_cond_wait(&progress_cond, &progress_mutex); + } + + for (i = 0; i < delta_search_threads; i++) + if (p[i].remaining > 2*window && + (!victim || victim->remaining < p[i].remaining)) + victim = &p[i]; + if (victim) { + sub_size = victim->remaining / 2; + target->regions = victim->regions + victim->remaining - sub_size; + victim->list_size -= sub_size; + victim->remaining -= sub_size; + } + target->list_size = sub_size; + target->remaining = sub_size; + target->working = 1; + progress_unlock(); + + pthread_mutex_lock(&target->mutex); + target->data_ready = 1; + pthread_cond_signal(&target->cond); + pthread_mutex_unlock(&target->mutex); + + if (!sub_size) { + pthread_join(target->thread, NULL); + pthread_cond_destroy(&target->cond); + pthread_mutex_destroy(&target->mutex); + active_threads--; + } + } + cleanup_threaded_search(); + free(p); + + display_progress(progress_state, progress_nr); + stop_progress(&progress_state); +} + static void prepare_pack(int window, int depth) { struct object_entry **delta_list; @@ -3220,39 +3556,21 @@ static void prepare_pack(int window, int depth) if (!to_pack.nr_objects || !window || !depth) return; + if (path_walk) + ll_find_deltas_by_region(to_pack.objects, to_pack.regions, + 0, to_pack.nr_regions); + ALLOC_ARRAY(delta_list, to_pack.nr_objects); nr_deltas = n = 0; for (i = 0; i < to_pack.nr_objects; i++) { struct object_entry *entry = to_pack.objects + i; - if (DELTA(entry)) - /* This happens if we decided to reuse existing - * delta from a pack. "reuse_delta &&" is implied. - */ - continue; - - if (!entry->type_valid || - oe_size_less_than(&to_pack, entry, 50)) + if (!should_attempt_deltas(entry)) continue; - if (entry->no_try_delta) - continue; - - if (!entry->preferred_base) { + if (!entry->preferred_base) nr_deltas++; - if (oe_type(entry) < 0) - die(_("unable to get type of object %s"), - oid_to_hex(&entry->idx.oid)); - } else { - if (oe_type(entry) < 0) { - /* - * This object is not found, but we - * don't have to include it anyway. - */ - continue; - } - } delta_list[n++] = entry; } @@ -3606,7 +3924,7 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type entry->no_try_delta = no_try_delta(name); } } else { - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack_mtime(oid, 0, &pack, &offset, mtime)) return; if (!pack && type == OBJ_BLOB && !has_loose_object(oid)) { /* @@ -3680,6 +3998,8 @@ static void mark_pack_kept_in_core(struct string_list *packs, unsigned keep) struct packed_git *p = item->util; if (!p) die(_("could not find pack '%s'"), item->string); + if (p->is_cruft && keep) + ignore_packed_keep_in_core_has_cruft = 1; p->pack_keep_in_core = keep; } } @@ -3844,7 +4164,7 @@ static void show_commit(struct commit *commit, void *data UNUSED) index_commit_for_bitmap(commit); if (use_delta_islands) - propagate_island_marks(commit); + propagate_island_marks(the_repository, commit); } static void show_object(struct object *obj, const char *name, @@ -4160,7 +4480,7 @@ static int mark_bitmap_preferred_tip(const char *refname, if (!peel_iterated_oid(the_repository, oid, &peeled)) oid = &peeled; - object = parse_object_or_die(oid, refname); + object = parse_object_or_die(the_repository, oid, refname); if (object->type == OBJ_COMMIT) object->flags |= NEEDS_BITMAP; @@ -4183,6 +4503,93 @@ static void mark_bitmap_preferred_tips(void) } } +static inline int is_oid_uninteresting(struct repository *repo, + struct object_id *oid) +{ + struct object *o = lookup_object(repo, oid); + return !o || (o->flags & UNINTERESTING); +} + +static int add_objects_by_path(const char *path, + struct oid_array *oids, + enum object_type type, + void *data) +{ + size_t oe_start = to_pack.nr_objects; + size_t oe_end; + unsigned int *processed = data; + + /* + * First, add all objects to the packing data, including the ones + * marked UNINTERESTING (translated to 'exclude') as they can be + * used as delta bases. + */ + for (size_t i = 0; i < oids->nr; i++) { + int exclude; + struct object_info oi = OBJECT_INFO_INIT; + struct object_id *oid = &oids->oid[i]; + + /* Skip objects that do not exist locally. */ + if ((exclude_promisor_objects || arg_missing_action != MA_ERROR) && + oid_object_info_extended(the_repository, oid, &oi, + OBJECT_INFO_FOR_PREFETCH) < 0) + continue; + + exclude = is_oid_uninteresting(the_repository, oid); + + if (exclude && !thin) + continue; + + add_object_entry(oid, type, path, exclude); + } + + oe_end = to_pack.nr_objects; + + /* We can skip delta calculations if it is a no-op. */ + if (oe_end == oe_start || !window) + return 0; + + ALLOC_GROW(to_pack.regions, + to_pack.nr_regions + 1, + to_pack.nr_regions_alloc); + + to_pack.regions[to_pack.nr_regions].start = oe_start; + to_pack.regions[to_pack.nr_regions].nr = oe_end - oe_start; + to_pack.nr_regions++; + + *processed += oids->nr; + display_progress(progress_state, *processed); + + return 0; +} + +static void get_object_list_path_walk(struct rev_info *revs) +{ + struct path_walk_info info = PATH_WALK_INFO_INIT; + unsigned int processed = 0; + int result; + + info.revs = revs; + info.path_fn = add_objects_by_path; + info.path_fn_data = &processed; + + /* + * Allow the --[no-]sparse option to be interesting here, if only + * for testing purposes. Paths with no interesting objects will not + * contribute to the resulting pack, but only create noisy preferred + * base objects. + */ + info.prune_all_uninteresting = sparse; + info.edge_aggressive = shallow; + + trace2_region_enter("pack-objects", "path-walk", revs->repo); + result = walk_objects_by_path(&info); + trace2_region_leave("pack-objects", "path-walk", revs->repo); + + if (result) + die(_("failed to pack objects via path-walk")); +} + static void get_object_list(struct rev_info *revs, int ac, const char **av) { struct setup_revision_opt s_r_opt = { @@ -4238,15 +4645,19 @@ static void get_object_list(struct rev_info *revs, int ac, const char **av) if (write_bitmap_index) mark_bitmap_preferred_tips(); - if (prepare_revision_walk(revs)) - die(_("revision walk setup failed")); - mark_edges_uninteresting(revs, show_edge, sparse); - if (!fn_show_object) fn_show_object = show_object; - traverse_commit_list(revs, - show_commit, fn_show_object, - NULL); + + if (path_walk) { + get_object_list_path_walk(revs); + } else { + if (prepare_revision_walk(revs)) + die(_("revision walk setup failed")); + mark_edges_uninteresting(revs, show_edge, sparse); + traverse_commit_list(revs, + show_commit, fn_show_object, + NULL); + } if (unpack_unreachable_expiration) { revs->ignore_missing_links = 1; @@ -4375,7 +4786,6 @@ int cmd_pack_objects(int argc, struct repository *repo UNUSED) { int use_internal_rev_list = 0; - int shallow = 0; int all_progress_implied = 0; struct strvec rp = STRVEC_INIT; int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0; @@ -4399,16 +4809,16 @@ int cmd_pack_objects(int argc, OPT_CALLBACK_F(0, "index-version", &pack_idx_opts, N_("<version>[,<offset>]"), N_("write the pack index file in the specified idx format version"), PARSE_OPT_NONEG, option_parse_index_version), - OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit, - N_("maximum size of each output pack file")), + OPT_UNSIGNED(0, "max-pack-size", &pack_size_limit, + N_("maximum size of each output pack file")), OPT_BOOL(0, "local", &local, N_("ignore borrowed objects from alternate object store")), OPT_BOOL(0, "incremental", &incremental, N_("ignore packed objects")), OPT_INTEGER(0, "window", &window, N_("limit pack window by objects")), - OPT_MAGNITUDE(0, "window-memory", &window_memory_limit, - N_("limit pack window by memory in addition to object limit")), + OPT_UNSIGNED(0, "window-memory", &window_memory_limit, + N_("limit pack window by memory in addition to object limit")), OPT_INTEGER(0, "depth", &depth, N_("maximum length of delta chain allowed in the resulting pack")), OPT_BOOL(0, "reuse-delta", &reuse_delta, @@ -4456,6 +4866,8 @@ int cmd_pack_objects(int argc, N_("use the sparse reachability algorithm")), OPT_BOOL(0, "thin", &thin, N_("create thin packs")), + OPT_BOOL(0, "path-walk", &path_walk, + N_("use the path-walk API to walk objects when possible")), OPT_BOOL(0, "shallow", &shallow, N_("create packs suitable for shallow fetches")), OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep_on_disk, @@ -4525,6 +4937,17 @@ int cmd_pack_objects(int argc, if (pack_to_stdout != !base_name || argc) usage_with_options(pack_usage, pack_objects_options); + if (path_walk < 0) { + if (use_bitmap_index > 0 || + !use_internal_rev_list) + path_walk = 0; + else if (the_repository->gitdir && + the_repository->settings.pack_use_path_walk) + path_walk = 1; + else + path_walk = git_env_bool("GIT_TEST_PACK_PATH_WALK", 0); + } + if (depth < 0) depth = 0; if (depth >= (1 << OE_DEPTH_BITS)) { @@ -4541,7 +4964,28 @@ int cmd_pack_objects(int argc, window = 0; strvec_push(&rp, "pack-objects"); - if (thin) { + + if (path_walk) { + const char *option = NULL; + if (filter_options.choice) + option = "--filter"; + else if (use_delta_islands) + option = "--delta-islands"; + + if (option) { + warning(_("cannot use %s with %s"), + option, "--path-walk"); + path_walk = 0; + } + } + if (path_walk) { + strvec_push(&rp, "--boundary"); + /* + * We must disable the bitmaps because we are removing + * the --objects / --objects-edge[-aggressive] options. + */ + use_bitmap_index = 0; + } else if (thin) { use_internal_rev_list = 1; strvec_push(&rp, shallow ? "--objects-edge-aggressive" diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index 6dc9e020c7..4138b52ccc 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -13,7 +13,7 @@ #include "hex.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-store.h" #include "strbuf.h" #define BLKSIZE 512 diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index 4fdd68880e..e47bae1c80 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "builtin.h" #include "config.h" #include "gettext.h" @@ -15,7 +13,7 @@ static char const * const pack_refs_usage[] = { int cmd_pack_refs(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; struct string_list included_refs = STRING_LIST_INIT_NODUP; @@ -39,7 +37,7 @@ int cmd_pack_refs(int argc, N_("references to exclude")), OPT_END(), }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); @@ -52,7 +50,7 @@ int cmd_pack_refs(int argc, if (!pack_refs_opts.includes->nr) string_list_append(pack_refs_opts.includes, "refs/tags/*"); - ret = refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); + ret = refs_pack_refs(get_main_ref_store(repo), &pack_refs_opts); clear_ref_exclusions(&excludes); string_list_clear(&included_refs, 0); diff --git a/builtin/prune.c b/builtin/prune.c index 1c357fffd8..e930caa0c0 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -17,7 +17,7 @@ #include "replace-object.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "shallow.h" static const char * const prune_usage[] = { @@ -185,7 +185,7 @@ int cmd_prune(int argc, const char *name = *argv++; if (!repo_get_oid(the_repository, name, &oid)) { - struct object *object = parse_object_or_die(&oid, + struct object *object = parse_object_or_die(the_repository, &oid, name); add_pending_object(&revs, object, ""); } diff --git a/builtin/pull.c b/builtin/pull.c index 9c4a00620a..a1ebc6ad33 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -738,7 +738,8 @@ static const char *get_tracking_branch(const char *remote, const char *refspec) const char *spec_src; const char *merge_branch; - refspec_item_init_or_die(&spec, refspec, REFSPEC_FETCH); + if (!refspec_item_init_fetch(&spec, refspec)) + die(_("invalid refspec '%s'"), refspec); spec_src = spec.src; if (!*spec_src || !strcmp(spec_src, "HEAD")) spec_src = "HEAD"; diff --git a/builtin/read-tree.c b/builtin/read-tree.c index d2a807a828..a8f352f7cd 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -135,9 +135,14 @@ int cmd_read_tree(int argc, N_("3-way merge in presence of adds and removes")), OPT_BOOL(0, "reset", &opts.reset, N_("same as -m, but discard unmerged entries")), - { OPTION_STRING, 0, "prefix", &opts.prefix, N_("<subdirectory>/"), - N_("read the tree into the index under <subdirectory>/"), - PARSE_OPT_NONEG }, + { + .type = OPTION_STRING, + .long_name = "prefix", + .value = &opts.prefix, + .argh = N_("<subdirectory>/"), + .help = N_("read the tree into the index under <subdirectory>/"), + .flags = PARSE_OPT_NONEG, + }, OPT_BOOL('u', NULL, &opts.update, N_("update working tree with merge result")), OPT_CALLBACK_F(0, "exclude-per-directory", &opts, diff --git a/builtin/rebase.c b/builtin/rebase.c index d4715ed35d..2e8c4ee678 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -267,7 +267,8 @@ static int init_basic_state(struct replay_opts *opts, const char *head_name, { FILE *interactive; - if (!is_directory(merge_dir()) && mkdir_in_gitdir(merge_dir())) + if (!is_directory(merge_dir()) && + safe_create_dir_in_gitdir(the_repository, merge_dir())) return error_errno(_("could not create temporary %s"), merge_dir()); refs_delete_reflog(get_main_ref_store(the_repository), "REBASE_HEAD"); @@ -925,7 +926,7 @@ static void fill_branch_base(struct rebase_options *options, options->orig_head, &merge_bases) < 0) exit(128); if (!merge_bases || merge_bases->next) - oidcpy(branch_base, null_oid()); + oidcpy(branch_base, null_oid(the_hash_algo)); else oidcpy(branch_base, &merge_bases->item->object.oid); @@ -1122,9 +1123,15 @@ int cmd_rebase(int argc, OPT_BIT('v', "verbose", &options.flags, N_("display a diffstat of what changed upstream"), REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT), - {OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL, - N_("do not show diffstat of what changed upstream"), - PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT }, + { + .type = OPTION_NEGBIT, + .short_name = 'n', + .long_name = "no-stat", + .value = &options.flags, + .help = N_("do not show diffstat of what changed upstream"), + .flags = PARSE_OPT_NOARG, + .defval = REBASE_DIFFSTAT, + }, OPT_BOOL(0, "signoff", &options.signoff, N_("add a Signed-off-by trailer to each commit")), OPT_BOOL(0, "committer-date-is-author-date", @@ -1190,9 +1197,16 @@ int cmd_rebase(int argc, OPT_BOOL(0, "update-refs", &options.update_refs, N_("update branches that point to commits " "that are being rebased")), - { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"), - N_("GPG-sign commits"), - PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, + { + .type = OPTION_STRING, + .short_name = 'S', + .long_name = "gpg-sign", + .value = &gpg_sign, + .argh = N_("key-id"), + .help = N_("GPG-sign commits"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "", + }, OPT_AUTOSTASH(&options.autostash), OPT_STRING_LIST('x', "exec", &options.exec, N_("exec"), N_("add exec lines after each commit of the " @@ -1575,11 +1589,6 @@ int cmd_rebase(int argc, options.default_backend); } - if (options.type == REBASE_MERGE && - !options.strategy && - getenv("GIT_TEST_MERGE_ALGORITHM")) - options.strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); - switch (options.type) { case REBASE_MERGE: options.state_dir = merge_dir(); @@ -1843,7 +1852,7 @@ int cmd_rebase(int argc, strbuf_addf(&msg, "%s (start): checkout %s", options.reflog_action, options.onto_name); ropts.oid = &options.onto->object.oid; - ropts.orig_head = &options.orig_head->object.oid, + ropts.orig_head = &options.orig_head->object.oid; ropts.flags = RESET_HEAD_DETACH | RESET_ORIG_HEAD | RESET_HEAD_RUN_POST_CHECKOUT_HOOK; ropts.head_msg = msg.buf; diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 7b28fc9df6..a317d6c278 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -31,8 +31,9 @@ #include "tmp-objdir.h" #include "oidset.h" #include "packfile.h" +#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "protocol.h" #include "commit-reach.h" @@ -80,6 +81,7 @@ static int prefer_ofs_delta = 1; static int auto_update_server_info; static int auto_gc = 1; static int reject_thin; +static int skip_connectivity_check; static int stateless_rpc; static const char *service_dir; static const char *head_name; @@ -363,7 +365,7 @@ static void write_head_info(void) strvec_clear(&excludes_vector); if (!sent_capabilities) - show_ref("capabilities^{}", null_oid()); + show_ref("capabilities^{}", null_oid(the_hash_algo)); advertise_shallow_grafts(1); @@ -1505,7 +1507,9 @@ static const char *update(struct command *cmd, struct shallow_info *si) } } - if (!is_null_oid(new_oid) && !repo_has_object_file(the_repository, new_oid)) { + if (!is_null_oid(new_oid) && + !has_object(the_repository, new_oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { error("unpack should have generated %s, " "but I can't find it!", oid_to_hex(new_oid)); ret = "bad pack"; @@ -1935,27 +1939,29 @@ static void execute_commands(struct command *commands, return; } - if (use_sideband) { - memset(&muxer, 0, sizeof(muxer)); - muxer.proc = copy_to_sideband; - muxer.in = -1; - if (!start_async(&muxer)) - err_fd = muxer.in; - /* ...else, continue without relaying sideband */ - } + if (!skip_connectivity_check) { + if (use_sideband) { + memset(&muxer, 0, sizeof(muxer)); + muxer.proc = copy_to_sideband; + muxer.in = -1; + if (!start_async(&muxer)) + err_fd = muxer.in; + /* ...else, continue without relaying sideband */ + } - data.cmds = commands; - data.si = si; - opt.err_fd = err_fd; - opt.progress = err_fd && !quiet; - opt.env = tmp_objdir_env(tmp_objdir); - opt.exclude_hidden_refs_section = "receive"; + data.cmds = commands; + data.si = si; + opt.err_fd = err_fd; + opt.progress = err_fd && !quiet; + opt.env = tmp_objdir_env(tmp_objdir); + opt.exclude_hidden_refs_section = "receive"; - if (check_connected(iterate_receive_command_list, &data, &opt)) - set_connectivity_errors(commands, si); + if (check_connected(iterate_receive_command_list, &data, &opt)) + set_connectivity_errors(commands, si); - if (use_sideband) - finish_async(&muxer); + if (use_sideband) + finish_async(&muxer); + } reject_updates_to_hidden(commands); @@ -2516,6 +2522,7 @@ int cmd_receive_pack(int argc, struct option options[] = { OPT__QUIET(&quiet, N_("quiet")), + OPT_HIDDEN_BOOL(0, "skip-connectivity-check", &skip_connectivity_check, NULL), OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL), OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL), OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"), diff --git a/builtin/reflog.c b/builtin/reflog.c index 95f264989b..3acaf3e32c 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -29,6 +29,9 @@ #define BUILTIN_REFLOG_EXISTS_USAGE \ N_("git reflog exists <ref>") +#define BUILTIN_REFLOG_DROP_USAGE \ + N_("git reflog drop [--all [--single-worktree] | <refs>...]") + static const char *const reflog_show_usage[] = { BUILTIN_REFLOG_SHOW_USAGE, NULL, @@ -54,18 +57,21 @@ static const char *const reflog_exists_usage[] = { NULL, }; +static const char *const reflog_drop_usage[] = { + BUILTIN_REFLOG_DROP_USAGE, + NULL, +}; + static const char *const reflog_usage[] = { BUILTIN_REFLOG_SHOW_USAGE, BUILTIN_REFLOG_LIST_USAGE, BUILTIN_REFLOG_EXPIRE_USAGE, BUILTIN_REFLOG_DELETE_USAGE, + BUILTIN_REFLOG_DROP_USAGE, BUILTIN_REFLOG_EXISTS_USAGE, NULL }; -static timestamp_t default_reflog_expire; -static timestamp_t default_reflog_expire_unreachable; - struct worktree_reflogs { struct worktree *worktree; struct string_list reflogs; @@ -91,131 +97,19 @@ static int collect_reflog(const char *ref, void *cb_data) return 0; } -static struct reflog_expire_cfg { - struct reflog_expire_cfg *next; - timestamp_t expire_total; - timestamp_t expire_unreachable; - char pattern[FLEX_ARRAY]; -} *reflog_expire_cfg, **reflog_expire_cfg_tail; - -static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len) -{ - struct reflog_expire_cfg *ent; - - if (!reflog_expire_cfg_tail) - reflog_expire_cfg_tail = &reflog_expire_cfg; - - for (ent = reflog_expire_cfg; ent; ent = ent->next) - if (!xstrncmpz(ent->pattern, pattern, len)) - return ent; - - FLEX_ALLOC_MEM(ent, pattern, pattern, len); - *reflog_expire_cfg_tail = ent; - reflog_expire_cfg_tail = &(ent->next); - return ent; -} - -/* expiry timer slot */ -#define EXPIRE_TOTAL 01 -#define EXPIRE_UNREACH 02 - -static int reflog_expire_config(const char *var, const char *value, - const struct config_context *ctx, void *cb) -{ - const char *pattern, *key; - size_t pattern_len; - timestamp_t expire; - int slot; - struct reflog_expire_cfg *ent; - - if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0) - return git_default_config(var, value, ctx, cb); - - if (!strcmp(key, "reflogexpire")) { - slot = EXPIRE_TOTAL; - if (git_config_expiry_date(&expire, var, value)) - return -1; - } else if (!strcmp(key, "reflogexpireunreachable")) { - slot = EXPIRE_UNREACH; - if (git_config_expiry_date(&expire, var, value)) - return -1; - } else - return git_default_config(var, value, ctx, cb); - - if (!pattern) { - switch (slot) { - case EXPIRE_TOTAL: - default_reflog_expire = expire; - break; - case EXPIRE_UNREACH: - default_reflog_expire_unreachable = expire; - break; - } - return 0; - } - - ent = find_cfg_ent(pattern, pattern_len); - if (!ent) - return -1; - switch (slot) { - case EXPIRE_TOTAL: - ent->expire_total = expire; - break; - case EXPIRE_UNREACH: - ent->expire_unreachable = expire; - break; - } - return 0; -} - -static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, const char *ref) -{ - struct reflog_expire_cfg *ent; - - if (cb->explicit_expiry == (EXPIRE_TOTAL|EXPIRE_UNREACH)) - return; /* both given explicitly -- nothing to tweak */ - - for (ent = reflog_expire_cfg; ent; ent = ent->next) { - if (!wildmatch(ent->pattern, ref, 0)) { - if (!(cb->explicit_expiry & EXPIRE_TOTAL)) - cb->expire_total = ent->expire_total; - if (!(cb->explicit_expiry & EXPIRE_UNREACH)) - cb->expire_unreachable = ent->expire_unreachable; - return; - } - } - - /* - * If unconfigured, make stash never expire - */ - if (!strcmp(ref, "refs/stash")) { - if (!(cb->explicit_expiry & EXPIRE_TOTAL)) - cb->expire_total = 0; - if (!(cb->explicit_expiry & EXPIRE_UNREACH)) - cb->expire_unreachable = 0; - return; - } - - /* Nothing matched -- use the default value */ - if (!(cb->explicit_expiry & EXPIRE_TOTAL)) - cb->expire_total = default_reflog_expire; - if (!(cb->explicit_expiry & EXPIRE_UNREACH)) - cb->expire_unreachable = default_reflog_expire_unreachable; -} - static int expire_unreachable_callback(const struct option *opt, const char *arg, int unset) { - struct cmd_reflog_expire_cb *cmd = opt->value; + struct reflog_expire_options *opts = opt->value; BUG_ON_OPT_NEG(unset); - if (parse_expiry_date(arg, &cmd->expire_unreachable)) + if (parse_expiry_date(arg, &opts->expire_unreachable)) die(_("invalid timestamp '%s' given to '--%s'"), arg, opt->long_name); - cmd->explicit_expiry |= EXPIRE_UNREACH; + opts->explicit_expiry |= REFLOG_EXPIRE_UNREACH; return 0; } @@ -223,15 +117,15 @@ static int expire_total_callback(const struct option *opt, const char *arg, int unset) { - struct cmd_reflog_expire_cb *cmd = opt->value; + struct reflog_expire_options *opts = opt->value; BUG_ON_OPT_NEG(unset); - if (parse_expiry_date(arg, &cmd->expire_total)) + if (parse_expiry_date(arg, &opts->expire_total)) die(_("invalid timestamp '%s' given to '--%s'"), arg, opt->long_name); - cmd->explicit_expiry |= EXPIRE_TOTAL; + opts->explicit_expiry |= REFLOG_EXPIRE_TOTAL; return 0; } @@ -276,8 +170,8 @@ static int cmd_reflog_list(int argc, const char **argv, const char *prefix, static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, struct repository *repo UNUSED) { - struct cmd_reflog_expire_cb cmd = { 0 }; timestamp_t now = time(NULL); + struct reflog_expire_options opts = REFLOG_EXPIRE_OPTIONS_INIT(now); int i, status, do_all, single_worktree = 0; unsigned int flags = 0; int verbose = 0; @@ -292,15 +186,15 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, N_("update the reference to the value of the top reflog entry"), EXPIRE_REFLOGS_UPDATE_REF), OPT_BOOL(0, "verbose", &verbose, N_("print extra information on screen")), - OPT_CALLBACK_F(0, "expire", &cmd, N_("timestamp"), + OPT_CALLBACK_F(0, "expire", &opts, N_("timestamp"), N_("prune entries older than the specified time"), PARSE_OPT_NONEG, expire_total_callback), - OPT_CALLBACK_F(0, "expire-unreachable", &cmd, N_("timestamp"), + OPT_CALLBACK_F(0, "expire-unreachable", &opts, N_("timestamp"), N_("prune entries older than <time> that are not reachable from the current tip of the branch"), PARSE_OPT_NONEG, expire_unreachable_callback), - OPT_BOOL(0, "stale-fix", &cmd.stalefix, + OPT_BOOL(0, "stale-fix", &opts.stalefix, N_("prune any reflog entries that point to broken commits")), OPT_BOOL(0, "all", &do_all, N_("process the reflogs of all references")), OPT_BOOL(0, "single-worktree", &single_worktree, @@ -308,17 +202,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, OPT_END() }; - default_reflog_expire_unreachable = now - 30 * 24 * 3600; - default_reflog_expire = now - 90 * 24 * 3600; - git_config(reflog_expire_config, NULL); + git_config(reflog_expire_config, &opts); save_commit_buffer = 0; do_all = status = 0; - cmd.explicit_expiry = 0; - cmd.expire_total = default_reflog_expire; - cmd.expire_unreachable = default_reflog_expire_unreachable; - argc = parse_options(argc, argv, prefix, options, reflog_expire_usage, 0); if (verbose) @@ -329,7 +217,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, * even in older repository. We cannot trust what's reachable * from reflog if the repository was pruned with older git. */ - if (cmd.stalefix) { + if (opts.stalefix) { struct rev_info revs; repo_init_revisions(the_repository, &revs, prefix); @@ -363,11 +251,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, for_each_string_list_item(item, &collected.reflogs) { struct expire_reflog_policy_cb cb = { - .cmd = cmd, + .opts = opts, .dry_run = !!(flags & EXPIRE_REFLOGS_DRY_RUN), }; - set_reflog_expiry_param(&cb.cmd, item->string); + reflog_expire_options_set_refname(&cb.opts, item->string); status |= refs_reflog_expire(get_main_ref_store(the_repository), item->string, flags, reflog_expiry_prepare, @@ -380,13 +268,13 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, for (i = 0; i < argc; i++) { char *ref; - struct expire_reflog_policy_cb cb = { .cmd = cmd }; + struct expire_reflog_policy_cb cb = { .opts = opts }; if (!repo_dwim_log(the_repository, argv[i], strlen(argv[i]), NULL, &ref)) { - status |= error(_("%s points nowhere!"), argv[i]); + status |= error(_("reflog could not be found: '%s'"), argv[i]); continue; } - set_reflog_expiry_param(&cb.cmd, ref); + reflog_expire_options_set_refname(&cb.opts, ref); status |= refs_reflog_expire(get_main_ref_store(the_repository), ref, flags, reflog_expiry_prepare, @@ -449,10 +337,64 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix, refname); } +static int cmd_reflog_drop(int argc, const char **argv, const char *prefix, + struct repository *repo) +{ + int ret = 0, do_all = 0, single_worktree = 0; + const struct option options[] = { + OPT_BOOL(0, "all", &do_all, N_("drop the reflogs of all references")), + OPT_BOOL(0, "single-worktree", &single_worktree, + N_("drop reflogs from the current worktree only")), + OPT_END() + }; + + argc = parse_options(argc, argv, prefix, options, reflog_drop_usage, 0); + + if (argc && do_all) + usage(_("references specified along with --all")); + + if (do_all) { + struct worktree_reflogs collected = { + .reflogs = STRING_LIST_INIT_DUP, + }; + struct string_list_item *item; + struct worktree **worktrees, **p; + + worktrees = get_worktrees(); + for (p = worktrees; *p; p++) { + if (single_worktree && !(*p)->is_current) + continue; + collected.worktree = *p; + refs_for_each_reflog(get_worktree_ref_store(*p), + collect_reflog, &collected); + } + free_worktrees(worktrees); + + for_each_string_list_item(item, &collected.reflogs) + ret |= refs_delete_reflog(get_main_ref_store(repo), + item->string); + string_list_clear(&collected.reflogs, 0); + + return ret; + } + + for (int i = 0; i < argc; i++) { + char *ref; + if (!repo_dwim_log(repo, argv[i], strlen(argv[i]), NULL, &ref)) { + ret |= error(_("reflog could not be found: '%s'"), argv[i]); + continue; + } + + ret |= refs_delete_reflog(get_main_ref_store(repo), ref); + free(ref); + } + + return ret; +} + /* * main "reflog" */ - int cmd_reflog(int argc, const char **argv, const char *prefix, @@ -465,6 +407,7 @@ int cmd_reflog(int argc, OPT_SUBCOMMAND("expire", &fn, cmd_reflog_expire), OPT_SUBCOMMAND("delete", &fn, cmd_reflog_delete), OPT_SUBCOMMAND("exists", &fn, cmd_reflog_exists), + OPT_SUBCOMMAND("drop", &fn, cmd_reflog_drop), OPT_END() }; diff --git a/builtin/refs.c b/builtin/refs.c index 44d592a94c..998d2a2c1c 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -91,7 +91,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, git_config(git_fsck_config, &fsck_refs_options); prepare_repo_settings(the_repository); - worktrees = get_worktrees(); + worktrees = get_worktrees_without_reading_head(); for (size_t i = 0; worktrees[i]; i++) ret |= refs_fsck(get_worktree_ref_store(worktrees[i]), &fsck_refs_options, worktrees[i]); diff --git a/builtin/remote.c b/builtin/remote.c index 1b7aad8838..0d6755bcb7 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -14,7 +14,7 @@ #include "rebase.h" #include "refs.h" #include "refspec.h" -#include "object-store-ll.h" +#include "object-store.h" #include "strvec.h" #include "commit-reach.h" #include "progress.h" @@ -454,7 +454,8 @@ static int get_push_ref_states(const struct ref *remote_refs, info->status = PUSH_STATUS_UPTODATE; else if (is_null_oid(&ref->old_oid)) info->status = PUSH_STATUS_CREATE; - else if (repo_has_object_file(the_repository, &ref->old_oid) && + else if (has_object(the_repository, &ref->old_oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR) && ref_newer(&ref->new_oid, &ref->old_oid)) info->status = PUSH_STATUS_FASTFORWARD; else @@ -511,7 +512,7 @@ static int get_head_names(const struct ref *remote_refs, struct ref_states *stat get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0); matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"), - fetch_map, 1); + fetch_map, REMOTE_GUESS_HEAD_ALL); for (ref = matches; ref; ref = ref->next) string_list_append(&states->heads, abbrev_branch(ref->name)); diff --git a/builtin/repack.c b/builtin/repack.c index 75e3752353..5ddc6e7f95 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -17,7 +17,7 @@ #include "midx.h" #include "packfile.h" #include "prune-packed.h" -#include "object-store-ll.h" +#include "object-store.h" #include "promisor-remote.h" #include "shallow.h" #include "pack.h" @@ -43,7 +43,7 @@ static char *packdir, *packtmp_name, *packtmp; static const char *const git_repack_usage[] = { N_("git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" "[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" - "[--write-midx] [--name-hash-version=<n>]"), + "[--write-midx] [--name-hash-version=<n>] [--path-walk]"), NULL }; @@ -63,6 +63,7 @@ struct pack_objects_args { int quiet; int local; int name_hash_version; + int path_walk; struct list_objects_filter_options filter_options; }; @@ -313,6 +314,8 @@ static void prepare_pack_objects(struct child_process *cmd, strvec_pushf(&cmd->args, "--no-reuse-object"); if (args->name_hash_version) strvec_pushf(&cmd->args, "--name-hash-version=%d", args->name_hash_version); + if (args->path_walk) + strvec_pushf(&cmd->args, "--path-walk"); if (args->local) strvec_push(&cmd->args, "--local"); if (args->quiet) @@ -1022,29 +1025,13 @@ static int write_filtered_pack(const struct pack_objects_args *args, return finish_pack_objects_cmd(&cmd, names, local); } -static int existing_cruft_pack_cmp(const void *va, const void *vb) +static void combine_small_cruft_packs(FILE *in, size_t combine_cruft_below_size, + struct existing_packs *existing) { - struct packed_git *a = *(struct packed_git **)va; - struct packed_git *b = *(struct packed_git **)vb; - - if (a->pack_size < b->pack_size) - return -1; - if (a->pack_size > b->pack_size) - return 1; - return 0; -} - -static void collapse_small_cruft_packs(FILE *in, size_t max_size, - struct existing_packs *existing) -{ - struct packed_git **existing_cruft, *p; + struct packed_git *p; struct strbuf buf = STRBUF_INIT; - size_t total_size = 0; - size_t existing_cruft_nr = 0; size_t i; - ALLOC_ARRAY(existing_cruft, existing->cruft_packs.nr); - for (p = get_all_packs(the_repository); p; p = p->next) { if (!(p->is_cruft && p->pack_local)) continue; @@ -1056,24 +1043,7 @@ static void collapse_small_cruft_packs(FILE *in, size_t max_size, if (!string_list_has_string(&existing->cruft_packs, buf.buf)) continue; - if (existing_cruft_nr >= existing->cruft_packs.nr) - BUG("too many cruft packs (found %"PRIuMAX", but knew " - "of %"PRIuMAX")", - (uintmax_t)existing_cruft_nr + 1, - (uintmax_t)existing->cruft_packs.nr); - existing_cruft[existing_cruft_nr++] = p; - } - - QSORT(existing_cruft, existing_cruft_nr, existing_cruft_pack_cmp); - - for (i = 0; i < existing_cruft_nr; i++) { - size_t proposed; - - p = existing_cruft[i]; - proposed = st_add(total_size, p->pack_size); - - if (proposed <= max_size) { - total_size = proposed; + if (p->pack_size < combine_cruft_below_size) { fprintf(in, "-%s\n", pack_basename(p)); } else { retain_cruft_pack(existing, p); @@ -1086,13 +1056,13 @@ static void collapse_small_cruft_packs(FILE *in, size_t max_size, existing->non_kept_packs.items[i].string); strbuf_release(&buf); - free(existing_cruft); } static int write_cruft_pack(const struct pack_objects_args *args, const char *destination, const char *pack_prefix, const char *cruft_expiration, + unsigned long combine_cruft_below_size, struct string_list *names, struct existing_packs *existing) { @@ -1135,8 +1105,9 @@ static int write_cruft_pack(const struct pack_objects_args *args, in = xfdopen(cmd.in, "w"); for_each_string_list_item(item, names) fprintf(in, "%s-%s.pack\n", pack_prefix, item->string); - if (args->max_pack_size && !cruft_expiration) { - collapse_small_cruft_packs(in, args->max_pack_size, existing); + if (combine_cruft_below_size && !cruft_expiration) { + combine_small_cruft_packs(in, combine_cruft_below_size, + existing); } else { for_each_string_list_item(item, &existing->non_kept_packs) fprintf(in, "-%s.pack\n", item->string); @@ -1190,6 +1161,7 @@ int cmd_repack(int argc, const char *opt_window_memory = NULL; const char *opt_depth = NULL; const char *opt_threads = NULL; + unsigned long combine_cruft_below_size = 0ul; struct option builtin_repack_options[] = { OPT_BIT('a', NULL, &pack_everything, @@ -1202,8 +1174,11 @@ int cmd_repack(int argc, PACK_CRUFT), OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"), N_("with --cruft, expire objects older than this")), - OPT_MAGNITUDE(0, "max-cruft-size", &cruft_po_args.max_pack_size, - N_("with --cruft, limit the size of new cruft packs")), + OPT_UNSIGNED(0, "combine-cruft-below-size", + &combine_cruft_below_size, + N_("with --cruft, only repack cruft packs smaller than this")), + OPT_UNSIGNED(0, "max-cruft-size", &cruft_po_args.max_pack_size, + N_("with --cruft, limit the size of new cruft packs")), OPT_BOOL('d', NULL, &delete_redundant, N_("remove redundant packs, and run git-prune-packed")), OPT_BOOL('f', NULL, &po_args.no_reuse_delta, @@ -1212,6 +1187,8 @@ int cmd_repack(int argc, N_("pass --no-reuse-object to git-pack-objects")), OPT_INTEGER(0, "name-hash-version", &po_args.name_hash_version, N_("specify the name hash version to use for grouping similar objects by path")), + OPT_BOOL(0, "path-walk", &po_args.path_walk, + N_("pass --path-walk to git-pack-objects")), OPT_NEGBIT('n', NULL, &run_update_server_info, N_("do not run git-update-server-info"), 1), OPT__QUIET(&po_args.quiet, N_("be quiet")), @@ -1233,8 +1210,8 @@ int cmd_repack(int argc, N_("limits the maximum delta depth")), OPT_STRING(0, "threads", &opt_threads, N_("n"), N_("limits the maximum number of threads")), - OPT_MAGNITUDE(0, "max-pack-size", &po_args.max_pack_size, - N_("maximum size of each packfile")), + OPT_UNSIGNED(0, "max-pack-size", &po_args.max_pack_size, + N_("maximum size of each packfile")), OPT_PARSE_LIST_OBJECTS_FILTER(&po_args.filter_options), OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects, N_("repack objects in packs marked with .keep")), @@ -1445,7 +1422,8 @@ int cmd_repack(int argc, cruft_po_args.quiet = po_args.quiet; ret = write_cruft_pack(&cruft_po_args, packtmp, pack_prefix, - cruft_expiration, &names, + cruft_expiration, + combine_cruft_below_size, &names, &existing); if (ret) goto cleanup; @@ -1472,10 +1450,17 @@ int cmd_repack(int argc, * generate an empty pack (since every object not in the * cruft pack generated above will have an mtime older * than the expiration). + * + * Pretend we don't have a `--combine-cruft-below-size` + * argument, since we're not selectively combining + * anything based on size to generate the limbo cruft + * pack, but rather removing all cruft packs from the + * main repository regardless of size. */ ret = write_cruft_pack(&cruft_po_args, expire_to, pack_prefix, NULL, + 0ul, &names, &existing); if (ret) diff --git a/builtin/replace.c b/builtin/replace.c index 15ec0922ce..48c7c6a2d5 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -19,7 +19,7 @@ #include "run-command.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "replace-object.h" #include "tag.h" #include "wildmatch.h" @@ -305,7 +305,7 @@ static int import_object(struct object_id *oid, enum object_type type, strbuf_release(&result); } else { struct stat st; - int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT; + int flags = INDEX_FORMAT_CHECK | INDEX_WRITE_OBJECT; if (fstat(fd, &st) < 0) { error_errno(_("unable to fstat %s"), filename); diff --git a/builtin/replay.c b/builtin/replay.c index 032c172b65..6172c8aacc 100644 --- a/builtin/replay.c +++ b/builtin/replay.c @@ -20,21 +20,22 @@ #include <oidset.h> #include <tree.h> -static const char *short_commit_name(struct commit *commit) +static const char *short_commit_name(struct repository *repo, + struct commit *commit) { - return repo_find_unique_abbrev(the_repository, &commit->object.oid, + return repo_find_unique_abbrev(repo, &commit->object.oid, DEFAULT_ABBREV); } -static struct commit *peel_committish(const char *name) +static struct commit *peel_committish(struct repository *repo, const char *name) { struct object *obj; struct object_id oid; - if (repo_get_oid(the_repository, name, &oid)) + if (repo_get_oid(repo, name, &oid)) return NULL; - obj = parse_object(the_repository, &oid); - return (struct commit *)repo_peel_to_type(the_repository, name, 0, obj, + obj = parse_object(repo, &oid); + return (struct commit *)repo_peel_to_type(repo, name, 0, obj, OBJ_COMMIT); } @@ -50,7 +51,8 @@ static char *get_author(const char *message) return NULL; } -static struct commit *create_commit(struct tree *tree, +static struct commit *create_commit(struct repository *repo, + struct tree *tree, struct commit *based_on, struct commit *parent) { @@ -62,7 +64,7 @@ static struct commit *create_commit(struct tree *tree, struct commit_extra_header *extra = NULL; struct strbuf msg = STRBUF_INIT; const char *out_enc = get_commit_output_encoding(); - const char *message = repo_logmsg_reencode(the_repository, based_on, + const char *message = repo_logmsg_reencode(repo, based_on, NULL, out_enc); const char *orig_message = NULL; const char *exclude_gpgsig[] = { "gpgsig", NULL }; @@ -79,9 +81,10 @@ static struct commit *create_commit(struct tree *tree, goto out; } - obj = parse_object(the_repository, &ret); + obj = parse_object(repo, &ret); out: + repo_unuse_commit_buffer(the_repository, based_on, message); free_commit_extra_headers(extra); free_commit_list(parents); strbuf_release(&msg); @@ -97,7 +100,8 @@ struct ref_info { int negative_refexprs; }; -static void get_ref_information(struct rev_cmdline_info *cmd_info, +static void get_ref_information(struct repository *repo, + struct rev_cmdline_info *cmd_info, struct ref_info *ref_info) { int i; @@ -132,14 +136,14 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info, if (*refexpr == '^') refexpr++; - if (repo_dwim_ref(the_repository, refexpr, strlen(refexpr), &oid, &fullname, 0) != 1) + if (repo_dwim_ref(repo, refexpr, strlen(refexpr), &oid, &fullname, 0) != 1) can_uniquely_dwim = 0; if (e->flags & BOTTOM) { if (can_uniquely_dwim) strset_add(&ref_info->negative_refs, fullname); if (!ref_info->negative_refexprs) - ref_info->onto = lookup_commit_reference_gently(the_repository, + ref_info->onto = lookup_commit_reference_gently(repo, &e->item->oid, 1); ref_info->negative_refexprs++; } else { @@ -152,7 +156,8 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info, } } -static void determine_replay_mode(struct rev_cmdline_info *cmd_info, +static void determine_replay_mode(struct repository *repo, + struct rev_cmdline_info *cmd_info, const char *onto_name, char **advance_name, struct commit **onto, @@ -160,14 +165,14 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, { struct ref_info rinfo; - get_ref_information(cmd_info, &rinfo); + get_ref_information(repo, cmd_info, &rinfo); if (!rinfo.positive_refexprs) die(_("need some commits to replay")); die_for_incompatible_opt2(!!onto_name, "--onto", !!*advance_name, "--advance"); if (onto_name) { - *onto = peel_committish(onto_name); + *onto = peel_committish(repo, onto_name); if (rinfo.positive_refexprs < strset_get_size(&rinfo.positive_refs)) die(_("all positive revisions given must be references")); @@ -175,8 +180,8 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info, struct object_id oid; char *fullname = NULL; - *onto = peel_committish(*advance_name); - if (repo_dwim_ref(the_repository, *advance_name, strlen(*advance_name), + *onto = peel_committish(repo, *advance_name); + if (repo_dwim_ref(repo, *advance_name, strlen(*advance_name), &oid, &fullname, 0) == 1) { free(*advance_name); *advance_name = fullname; @@ -245,7 +250,8 @@ static struct commit *mapped_commit(kh_oid_map_t *replayed_commits, return kh_value(replayed_commits, pos); } -static struct commit *pick_regular_commit(struct commit *pickme, +static struct commit *pick_regular_commit(struct repository *repo, + struct commit *pickme, kh_oid_map_t *replayed_commits, struct commit *onto, struct merge_options *merge_opt, @@ -257,12 +263,12 @@ static struct commit *pick_regular_commit(struct commit *pickme, base = pickme->parents->item; replayed_base = mapped_commit(replayed_commits, base, onto); - result->tree = repo_get_commit_tree(the_repository, replayed_base); - pickme_tree = repo_get_commit_tree(the_repository, pickme); - base_tree = repo_get_commit_tree(the_repository, base); + result->tree = repo_get_commit_tree(repo, replayed_base); + pickme_tree = repo_get_commit_tree(repo, pickme); + base_tree = repo_get_commit_tree(repo, base); - merge_opt->branch1 = short_commit_name(replayed_base); - merge_opt->branch2 = short_commit_name(pickme); + merge_opt->branch1 = short_commit_name(repo, replayed_base); + merge_opt->branch2 = short_commit_name(repo, pickme); merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2); merge_incore_nonrecursive(merge_opt, @@ -275,13 +281,13 @@ static struct commit *pick_regular_commit(struct commit *pickme, merge_opt->ancestor = NULL; if (!result->clean) return NULL; - return create_commit(result->tree, pickme, replayed_base); + return create_commit(repo, result->tree, pickme, replayed_base); } int cmd_replay(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { const char *advance_name_opt = NULL; char *advance_name = NULL; @@ -329,7 +335,7 @@ int cmd_replay(int argc, "--advance", "--contained"); advance_name = xstrdup_or_null(advance_name_opt); - repo_init_revisions(the_repository, &revs, prefix); + repo_init_revisions(repo, &revs, prefix); /* * Set desired values for rev walking options here. If they @@ -380,7 +386,7 @@ int cmd_replay(int argc, revs.simplify_history = 0; } - determine_replay_mode(&revs.cmdline, onto_name, &advance_name, + determine_replay_mode(repo, &revs.cmdline, onto_name, &advance_name, &onto, &update_refs); if (!onto) /* FIXME: Should handle replaying down to root commit */ @@ -391,7 +397,7 @@ int cmd_replay(int argc, goto cleanup; } - init_basic_merge_options(&merge_opt, the_repository); + init_basic_merge_options(&merge_opt, repo); memset(&result, 0, sizeof(result)); merge_opt.show_rename_progress = 0; last_commit = onto; @@ -406,8 +412,8 @@ int cmd_replay(int argc, if (commit->parents->next) die(_("replaying merge commits is not supported yet!")); - last_commit = pick_regular_commit(commit, replayed_commits, onto, - &merge_opt, &result); + last_commit = pick_regular_commit(repo, commit, replayed_commits, + onto, &merge_opt, &result); if (!last_commit) break; diff --git a/builtin/reset.c b/builtin/reset.c index 73b4537a9a..dc50ffc1ac 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -420,6 +420,9 @@ int cmd_reset(int argc, oidcpy(&oid, &tree->object.oid); } + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + if (patch_mode) { if (reset_type != NONE) die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}"); @@ -457,9 +460,6 @@ int cmd_reset(int argc, if (intent_to_add && reset_type != MIXED) die(_("the option '%s' requires '%s'"), "-N", "--mixed"); - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; - if (repo_read_index(the_repository) < 0) die(_("index file corrupt")); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index bb26bee0d4..0984b607bf 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -14,8 +14,9 @@ #include "object.h" #include "object-name.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "pack-bitmap.h" +#include "parse-options.h" #include "log-tree.h" #include "graph.h" #include "bisect.h" @@ -64,6 +65,7 @@ static const char rev_list_usage[] = " --abbrev-commit\n" " --left-right\n" " --count\n" +" -z\n" " special purpose:\n" " --bisect\n" " --bisect-vars\n" @@ -96,6 +98,9 @@ static int arg_show_object_names = 1; #define DEFAULT_OIDSET_SIZE (16*1024) +static char line_term = '\n'; +static char info_term = ' '; + static int show_disk_usage; static off_t total_disk_usage; static int human_readable; @@ -131,24 +136,37 @@ static void print_missing_object(struct missing_objects_map_entry *entry, { struct strbuf sb = STRBUF_INIT; + if (line_term) + printf("?%s", oid_to_hex(&entry->entry.oid)); + else + printf("%s%cmissing=yes", oid_to_hex(&entry->entry.oid), + info_term); + if (!print_missing_info) { - printf("?%s\n", oid_to_hex(&entry->entry.oid)); + putchar(line_term); return; } if (entry->path && *entry->path) { - struct strbuf path = STRBUF_INIT; + strbuf_addf(&sb, "%cpath=", info_term); - strbuf_addstr(&sb, " path="); - quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP); - strbuf_addbuf(&sb, &path); + if (line_term) { + struct strbuf path = STRBUF_INIT; - strbuf_release(&path); + quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP); + strbuf_addbuf(&sb, &path); + + strbuf_release(&path); + } else { + strbuf_addstr(&sb, entry->path); + } } if (entry->type) - strbuf_addf(&sb, " type=%s", type_name(entry->type)); + strbuf_addf(&sb, "%ctype=%s", info_term, type_name(entry->type)); + + fwrite(sb.buf, sizeof(char), sb.len, stdout); + putchar(line_term); - printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf); strbuf_release(&sb); } @@ -235,13 +253,18 @@ static void show_commit(struct commit *commit, void *data) fputs(info->header_prefix, stdout); if (revs->include_header) { - if (!revs->graph) + if (!revs->graph && line_term) fputs(get_revision_mark(revs, commit), stdout); if (revs->abbrev_commit && revs->abbrev) fputs(repo_find_unique_abbrev(the_repository, &commit->object.oid, revs->abbrev), stdout); else fputs(oid_to_hex(&commit->object.oid), stdout); + + if (!line_term) { + if (commit->object.flags & BOUNDARY) + printf("%cboundary=yes", info_term); + } } if (revs->print_parents) { struct commit_list *parents = commit->parents; @@ -263,7 +286,7 @@ static void show_commit(struct commit *commit, void *data) if (revs->commit_format == CMIT_FMT_ONELINE) putchar(' '); else if (revs->include_header) - putchar('\n'); + putchar(line_term); if (revs->verbose_header) { struct strbuf buf = STRBUF_INIT; @@ -357,10 +380,19 @@ static void show_object(struct object *obj, const char *name, void *cb_data) return; } - if (arg_show_object_names) - show_object_with_name(stdout, obj, name); - else - printf("%s\n", oid_to_hex(&obj->oid)); + printf("%s", oid_to_hex(&obj->oid)); + + if (arg_show_object_names) { + if (line_term) { + putchar(info_term); + for (const char *p = name; *p && *p != '\n'; p++) + putchar(*p); + } else if (*name) { + printf("%cpath=%s", info_term, name); + } + } + + putchar(line_term); } static void show_edge(struct commit *commit) @@ -429,7 +461,8 @@ static int show_object_fast( int exclude UNUSED, uint32_t name_hash UNUSED, struct packed_git *found_pack UNUSED, - off_t found_offset UNUSED) + off_t found_offset UNUSED, + void *payload UNUSED) { fprintf(stdout, "%s\n", oid_to_hex(oid)); return 1; @@ -634,19 +667,18 @@ int cmd_rev_list(int argc, if (!strcmp(arg, "--exclude-promisor-objects")) { fetch_if_missing = 0; revs.exclude_promisor_objects = 1; - break; - } - } - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (skip_prefix(arg, "--missing=", &arg)) { - if (revs.exclude_promisor_objects) - die(_("options '%s' and '%s' cannot be used together"), "--exclude-promisor-objects", "--missing"); - if (parse_missing_action_value(arg)) - break; + } else if (skip_prefix(arg, "--missing=", &arg)) { + parse_missing_action_value(arg); + } else if (!strcmp(arg, "-z")) { + line_term = '\0'; + info_term = '\0'; } } + die_for_incompatible_opt2(revs.exclude_promisor_objects, + "--exclude_promisor_objects", + arg_missing_action, "--missing"); + if (arg_missing_action) revs.do_not_die_on_missing_objects = 1; @@ -755,6 +787,20 @@ int cmd_rev_list(int argc, usage(rev_list_usage); } + + /* + * Reject options currently incompatible with -z. For some options, this + * is not an inherent limitation and support may be implemented in the + * future. + */ + if (!line_term) { + if (revs.graph || revs.verbose_header || show_disk_usage || + info.show_timestamp || info.header_prefix || bisect_list || + use_bitmap_index || revs.edge_hint || revs.left_right || + revs.cherry_mark) + die(_("-z option used with unsupported option")); + } + if (revs.commit_format != CMIT_FMT_USERFORMAT) revs.include_header = 1; if (revs.commit_format != CMIT_FMT_UNSPECIFIED) { @@ -878,7 +924,7 @@ int cmd_rev_list(int argc, free((void *)entry->path); } - oidmap_free(&missing_objects, true); + oidmap_clear(&missing_objects, true); } stop_progress(&progress); diff --git a/builtin/revert.c b/builtin/revert.c index aca6c293cd..e07c2217fe 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -132,8 +132,16 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")), OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"), N_("option for merge strategy")), - { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"), - N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, + { + .type = OPTION_STRING, + .short_name = 'S', + .long_name = "gpg-sign", + .value = &gpg_sign, + .argh = N_("key-id"), + .help = N_("GPG sign commit"), + .flags = PARSE_OPT_OPTARG, + .defval = (intptr_t) "", + }, OPT_END() }; struct option *options = base_options; @@ -252,8 +260,6 @@ static int run_sequencer(int argc, const char **argv, const char *prefix, free(opts->strategy); opts->strategy = xstrdup_or_null(strategy); } - if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM")) - opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); free(options); if (cmd == 'q') { diff --git a/builtin/rm.c b/builtin/rm.c index 12ae086a55..a6565a69cf 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -5,7 +5,6 @@ */ #define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" #include "advice.h" @@ -40,14 +39,12 @@ static struct { } *entry; } list; -static int get_ours_cache_pos(const char *path, int pos) +static int get_ours_cache_pos(const char *path, unsigned int pos) { - int i = -pos - 1; - - while ((i < the_repository->index->cache_nr) && !strcmp(the_repository->index->cache[i]->name, path)) { - if (ce_stage(the_repository->index->cache[i]) == 2) - return i; - i++; + while ((pos < the_repository->index->cache_nr) && !strcmp(the_repository->index->cache[pos]->name, path)) { + if (ce_stage(the_repository->index->cache[pos]) == 2) + return pos; + pos++; } return -1; } @@ -58,7 +55,7 @@ static void print_error_files(struct string_list *files_list, int *errs) { if (files_list->nr) { - int i; + unsigned int i; struct strbuf err_msg = STRBUF_INIT; strbuf_addstr(&err_msg, main_msg); @@ -83,7 +80,7 @@ static void submodules_absorb_gitdir_if_needed(void) pos = index_name_pos(the_repository->index, name, strlen(name)); if (pos < 0) { - pos = get_ours_cache_pos(name, pos); + pos = get_ours_cache_pos(name, -pos - 1); if (pos < 0) continue; } @@ -131,7 +128,7 @@ static int check_local_mod(struct object_id *head, int index_only) * Skip unmerged entries except for populated submodules * that could lose history when removed. */ - pos = get_ours_cache_pos(name, pos); + pos = get_ours_cache_pos(name, -pos - 1); if (pos < 0) continue; @@ -314,7 +311,7 @@ int cmd_rm(int argc, if (pathspec_needs_expanded_index(the_repository->index, &pathspec)) ensure_full_index(the_repository->index); - for (i = 0; i < the_repository->index->cache_nr; i++) { + for (unsigned int i = 0; i < the_repository->index->cache_nr; i++) { const struct cache_entry *ce = the_repository->index->cache[i]; if (!include_sparse && diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 8d461008e2..c6e0e9d051 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -151,7 +150,7 @@ static int send_pack_config(const char *k, const char *v, int cmd_send_pack(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct refspec rs = REFSPEC_INIT_PUSH; const char *remote_name = NULL; @@ -212,7 +211,7 @@ int cmd_send_pack(int argc, OPT_END() }; - git_config(send_pack_config, NULL); + repo_config(repo, send_pack_config, NULL); argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0); if (argc > 0) { dest = argv[0]; @@ -317,7 +316,7 @@ int cmd_send_pack(int argc, set_ref_status_for_push(remote_refs, args.send_mirror, args.force_update); - ret = send_pack(the_repository, &args, fd, conn, remote_refs, &extra_have); + ret = send_pack(repo, &args, fd, conn, remote_refs, &extra_have); if (helper_status) print_helper_status(remote_refs); diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 30075b67be..fe15e11497 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -187,7 +187,7 @@ static void insert_records_from_trailers(struct shortlog *log, ctx->output_encoding); body = strstr(commit_buffer, "\n\n"); if (!body) - return; + goto out; trailer_iterator_init(&iter, body); while (trailer_iterator_advance(&iter)) { @@ -206,6 +206,7 @@ static void insert_records_from_trailers(struct shortlog *log, } trailer_iterator_release(&iter); +out: strbuf_release(&ident); repo_unuse_commit_buffer(the_repository, commit, commit_buffer); } diff --git a/builtin/show-branch.c b/builtin/show-branch.c index fce6b404e9..525b231d87 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -19,7 +19,7 @@ #include "date.h" #include "wildmatch.h" -static const char* show_branch_usage[] = { +static const char*const show_branch_usage[] = { N_("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" @@ -667,9 +667,16 @@ int cmd_show_branch(int ac, N_("show remote-tracking branches")), OPT__COLOR(&showbranch_use_color, N_("color '*!+-' corresponding to the branch")), - { OPTION_INTEGER, 0, "more", &extra, N_("n"), - N_("show <n> more commits after the common ancestor"), - PARSE_OPT_OPTARG, NULL, (intptr_t)1 }, + { + .type = OPTION_INTEGER, + .long_name = "more", + .value = &extra, + .precision = sizeof(extra), + .argh = N_("n"), + .help = N_("show <n> more commits after the common ancestor"), + .flags = PARSE_OPT_OPTARG, + .defval = 1, + }, OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1), OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")), OPT_BOOL(0, "current", &with_current_branch, diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 285cd3e433..623a52a45f 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -5,7 +5,7 @@ #include "hex.h" #include "refs/refs-internal.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "object.h" #include "string-list.h" #include "parse-options.h" @@ -35,7 +35,8 @@ static void show_one(const struct show_one_options *opts, const char *hex; struct object_id peeled; - if (!repo_has_object_file(the_repository, oid)) + if (!has_object(the_repository, oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) die("git show-ref: bad ref %s (%s)", refname, oid_to_hex(oid)); diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 14dcace5f8..1bf01591b2 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -9,6 +9,7 @@ #include "object-file.h" #include "object-name.h" #include "parse-options.h" +#include "path.h" #include "pathspec.h" #include "strbuf.h" #include "string-list.h" @@ -335,7 +336,7 @@ static int write_patterns_and_update(struct pattern_list *pl) sparse_filename = get_sparse_checkout_filename(); - if (safe_create_leading_directories(sparse_filename)) + if (safe_create_leading_directories(the_repository, sparse_filename)) die(_("failed to create directory for sparse-checkout file")); hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR); @@ -491,7 +492,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix, FILE *fp; /* assume we are in a fresh repo, but update the sparse-checkout file */ - if (safe_create_leading_directories(sparse_filename)) + if (safe_create_leading_directories(the_repository, sparse_filename)) die(_("unable to create leading directories of %s"), sparse_filename); fp = xfopen(sparse_filename, "w"); diff --git a/builtin/stash.c b/builtin/stash.c index dbaa999cf1..7cd3ad8aa4 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -13,7 +13,6 @@ #include "lockfile.h" #include "cache-tree.h" #include "unpack-trees.h" -#include "merge-recursive.h" #include "merge-ort-wrappers.h" #include "strvec.h" #include "run-command.h" @@ -1373,6 +1372,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b const char *head_short_sha1 = NULL; const char *branch_ref = NULL; const char *branch_name = "(no branch)"; + char *branch_name_buf = NULL; struct commit *head_commit = NULL; struct commit_list *parents = NULL; struct strbuf msg = STRBUF_INIT; @@ -1405,8 +1405,12 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b branch_ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, NULL, &flags); - if (flags & REF_ISSYMREF) - skip_prefix(branch_ref, "refs/heads/", &branch_name); + + if (flags & REF_ISSYMREF) { + if (skip_prefix(branch_ref, "refs/heads/", &branch_name)) + branch_name = branch_name_buf = xstrdup(branch_name); + } + head_short_sha1 = repo_find_unique_abbrev(the_repository, &head_commit->object.oid, DEFAULT_ABBREV); @@ -1496,6 +1500,7 @@ done: strbuf_release(&msg); strbuf_release(&untracked_files); free_commit_list(parents); + free(branch_name_buf); return ret; } @@ -1790,11 +1795,15 @@ static int push_stash(int argc, const char **argv, const char *prefix, int ret; if (argc) { - force_assume = !strcmp(argv[0], "-p"); + int flags = PARSE_OPT_KEEP_DASHDASH; + + if (push_assumed) + flags |= PARSE_OPT_STOP_AT_NON_OPTION; + argc = parse_options(argc, argv, prefix, options, push_assumed ? git_stash_usage : - git_stash_push_usage, - PARSE_OPT_KEEP_DASHDASH); + git_stash_push_usage, flags); + force_assume |= patch_mode; } if (argc) { diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index c1a8029714..640c0059c3 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -28,7 +28,7 @@ #include "diff.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "advice.h" #include "branch.h" #include "list-objects-filter-options.h" @@ -78,7 +78,7 @@ static int get_default_remote_submodule(const char *module_path, char **default_ int ret; if (repo_submodule_init(&subrepo, the_repository, module_path, - null_oid()) < 0) + null_oid(the_hash_algo)) < 0) return die_message(_("could not get a repository handle for submodule '%s'"), module_path); ret = repo_get_default_remote(&subrepo, default_remote); @@ -308,7 +308,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item, displaypath = get_submodule_displaypath(path, info->prefix, info->super_prefix); - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) die(_("No url found for submodule path '%s' in .gitmodules"), @@ -468,7 +468,7 @@ static void init_submodule(const char *path, const char *prefix, displaypath = get_submodule_displaypath(path, prefix, super_prefix); - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) die(_("No url found for submodule path '%s' in .gitmodules"), @@ -645,14 +645,14 @@ static void status_submodule(const char *path, const struct object_id *ce_oid, if (validate_submodule_path(path) < 0) exit(128); - if (!submodule_from_path(the_repository, null_oid(), path)) + if (!submodule_from_path(the_repository, null_oid(the_hash_algo), path)) die(_("no submodule mapping found in .gitmodules for path '%s'"), path); displaypath = get_submodule_displaypath(path, prefix, super_prefix); if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) { - print_status(flags, 'U', path, null_oid(), displaypath); + print_status(flags, 'U', path, null_oid(the_hash_algo), displaypath); goto cleanup; } @@ -912,7 +912,7 @@ static void generate_submodule_summary(struct summary_cb *info, struct strbuf errmsg = STRBUF_INIT; int total_commits = -1; - if (!info->cached && oideq(&p->oid_dst, null_oid())) { + if (!info->cached && oideq(&p->oid_dst, null_oid(the_hash_algo))) { if (S_ISGITLINK(p->mod_dst)) { struct ref_store *refs = repo_get_submodule_ref_store(the_repository, p->sm_path); @@ -1051,7 +1051,7 @@ static void prepare_submodule_summary(struct summary_cb *info, if (info->for_status && p->status != 'A' && (sub = submodule_from_path(the_repository, - null_oid(), p->sm_path))) { + null_oid(the_hash_algo), p->sm_path))) { char *config_key = NULL; const char *value; int ignore_all = 0; @@ -1259,7 +1259,7 @@ static void sync_submodule(const char *path, const char *prefix, if (validate_submodule_path(path) < 0) exit(128); - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (sub && sub->url) { if (starts_with_dot_dot_slash(sub->url) || @@ -1404,7 +1404,7 @@ static void deinit_submodule(const char *path, const char *prefix, if (validate_submodule_path(path) < 0) exit(128); - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub || !sub->name) goto cleanup; @@ -1739,7 +1739,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, !is_empty_dir(clone_data_path)) die(_("directory not empty: '%s'"), clone_data_path); - if (safe_create_leading_directories_const(sm_gitdir) < 0) + if (safe_create_leading_directories_const(the_repository, sm_gitdir) < 0) die(_("could not create directory '%s'"), sm_gitdir); prepare_possible_alternates(clone_data->name, reference); @@ -1800,7 +1800,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, if (clone_data->require_init && !stat(clone_data_path, &st) && !is_empty_dir(clone_data_path)) die(_("directory not empty: '%s'"), clone_data_path); - if (safe_create_leading_directories_const(clone_data_path) < 0) + if (safe_create_leading_directories_const(the_repository, clone_data_path) < 0) die(_("could not create directory '%s'"), clone_data_path); path = xstrfmt("%s/index", sm_gitdir); unlink_or_warn(path); @@ -1929,7 +1929,7 @@ static int determine_submodule_update_strategy(struct repository *r, enum submodule_update_type update, struct submodule_update_strategy *out) { - const struct submodule *sub = submodule_from_path(r, null_oid(), path); + const struct submodule *sub = submodule_from_path(r, null_oid(the_hash_algo), path); char *key; const char *val; int ret; @@ -2089,7 +2089,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, goto cleanup; } - sub = submodule_from_path(the_repository, null_oid(), ce->name); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name); if (!sub) { next_submodule_warn_missing(suc, out, displaypath); @@ -2485,7 +2485,7 @@ static int remote_submodule_branch(const char *path, const char **branch) char *key; *branch = NULL; - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) return die_message(_("could not initialize submodule at path '%s'"), path); @@ -2531,7 +2531,7 @@ static int ensure_core_worktree(const char *path) const char *cw; struct repository subrepo; - if (repo_submodule_init(&subrepo, the_repository, path, null_oid())) + if (repo_submodule_init(&subrepo, the_repository, path, null_oid(the_hash_algo))) return die_message(_("could not get a repository handle for submodule '%s'"), path); @@ -2644,7 +2644,7 @@ static int update_submodule(struct update_data *update_data) return ret; if (update_data->just_cloned) - oidcpy(&update_data->suboid, null_oid()); + oidcpy(&update_data->suboid, null_oid(the_hash_algo)); else if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path, "HEAD", &update_data->suboid)) return die_message(_("Unable to find current revision in submodule path '%s'"), @@ -2660,8 +2660,10 @@ static int update_submodule(struct update_data *update_data) if (code) return code; code = remote_submodule_branch(update_data->sm_path, &branch); - if (code) + if (code) { + free(remote_name); return code; + } remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch); free(remote_name); @@ -2697,8 +2699,8 @@ static int update_submodule(struct update_data *update_data) struct update_data next = *update_data; next.prefix = NULL; - oidcpy(&next.oid, null_oid()); - oidcpy(&next.suboid, null_oid()); + oidcpy(&next.oid, null_oid(the_hash_algo)); + oidcpy(&next.suboid, null_oid(the_hash_algo)); cp.dir = update_data->sm_path; cp.git_cmd = 1; @@ -3057,7 +3059,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix, if (argc != 2 || !(path = argv[0]) || !(newurl = argv[1])) usage_with_options(usage, options); - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) die(_("no submodule mapping found in .gitmodules for path '%s'"), @@ -3113,7 +3115,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix, if (argc != 1 || !(path = argv[0])) usage_with_options(usage, options); - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) die(_("no submodule mapping found in .gitmodules for path '%s'"), diff --git a/builtin/tag.c b/builtin/tag.c index d3e0943b73..4742b27d16 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -17,8 +17,9 @@ #include "gettext.h" #include "hex.h" #include "refs.h" +#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "tag.h" #include "parse-options.h" @@ -172,7 +173,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid, if (compat) { const struct git_hash_algo *algo = the_repository->hash_algo; - if (convert_object_file(&compat_buf, algo, compat, + if (convert_object_file(the_repository ,&compat_buf, algo, compat, buffer->buf, buffer->len, OBJ_TAG, 1)) goto out; if (sign_buffer(&compat_buf, &compat_sig, keyid)) @@ -479,9 +480,16 @@ int cmd_tag(int argc, int edit_flag = 0; struct option options[] = { OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'), - { OPTION_INTEGER, 'n', NULL, &filter.lines, N_("n"), - N_("print <n> lines of each tag message"), - PARSE_OPT_OPTARG, NULL, 1 }, + { + .type = OPTION_INTEGER, + .short_name = 'n', + .value = &filter.lines, + .precision = sizeof(filter.lines), + .argh = N_("n"), + .help = N_("print <n> lines of each tag message"), + .flags = PARSE_OPT_OPTARG, + .defval = 1, + }, OPT_CMDMODE('d', "delete", &cmdmode, N_("delete tags"), 'd'), OPT_CMDMODE('v', "verify", &cmdmode, N_("verify tags"), 'v'), @@ -513,9 +521,14 @@ int cmd_tag(int argc, N_("do not output a newline after empty formatted refs")), OPT_REF_SORT(&sorting_options), { - OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"), - N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT, - parse_opt_object_name, (intptr_t) "HEAD" + .type = OPTION_CALLBACK, + .long_name = "points-at", + .value = &filter.points_at, + .argh = N_("object"), + .help = N_("print only tags of the object"), + .flags = PARSE_OPT_LASTARG_DEFAULT, + .callback = parse_opt_object_name, + .defval = (intptr_t) "HEAD", }, OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")), diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c index fb5fcbc40a..e33acfc4ee 100644 --- a/builtin/unpack-file.c +++ b/builtin/unpack-file.c @@ -2,8 +2,9 @@ #include "builtin.h" #include "config.h" #include "hex.h" +#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" static char *create_temp_file(struct object_id *oid) { diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 8383bcf404..e905d5f4e1 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -8,7 +8,8 @@ #include "gettext.h" #include "git-zlib.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-file.h" +#include "object-store.h" #include "object.h" #include "delta.h" #include "pack.h" @@ -448,7 +449,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, delta_data = get_data(delta_size); if (!delta_data) return; - if (repo_has_object_file(the_repository, &base_oid)) + if (has_object(the_repository, &base_oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) ; /* Ok we have this one */ else if (resolve_against_held(nr, &base_oid, delta_data, delta_size)) @@ -505,7 +507,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size, * has not been resolved yet. */ oidclr(&obj_list[nr].oid, the_repository->hash_algo); - add_delta_to_list(nr, null_oid(), base_offset, + add_delta_to_list(nr, null_oid(the_hash_algo), base_offset, delta_data, delta_size); return; } @@ -553,7 +555,8 @@ static void unpack_one(unsigned nr) switch (type) { case OBJ_BLOB: - if (!dry_run && size > big_file_threshold) { + if (!dry_run && + size > repo_settings_get_big_file_threshold(the_repository)) { stream_blob(size, nr); return; } @@ -668,6 +671,7 @@ int cmd_unpack_objects(int argc, the_hash_algo->init_fn(&ctx); unpack_all(); git_hash_update(&ctx, buffer, offset); + the_hash_algo->init_fn(&tmp_ctx); git_hash_clone(&tmp_ctx, &ctx); git_hash_final_oid(&oid, &tmp_ctx); if (strict) { diff --git a/builtin/update-index.c b/builtin/update-index.c index b2f6b1a3fb..538b619ba4 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -304,7 +304,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len ce->ce_mode = ce_mode_from_stat(old, st->st_mode); if (index_path(the_repository->index, &ce->oid, path, st, - info_only ? 0 : HASH_WRITE_OBJECT)) { + info_only ? 0 : INDEX_WRITE_OBJECT)) { discard_cache_entry(ce); return -1; } @@ -964,29 +964,51 @@ int cmd_update_index(int argc, N_("like --refresh, but ignore assume-unchanged setting"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, really_refresh_callback), - {OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL, - N_("<mode>,<object>,<path>"), - N_("add the specified entry to the index"), - PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */ - PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, - NULL, 0, - cacheinfo_callback}, + { + .type = OPTION_LOWLEVEL_CALLBACK, + .long_name = "cacheinfo", + .argh = N_("<mode>,<object>,<path>"), + .help = N_("add the specified entry to the index"), + .flags = PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */ + PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, + .ll_callback = cacheinfo_callback, + }, OPT_CALLBACK_F(0, "chmod", &set_executable_bit, "(+|-)x", N_("override the executable bit of the listed files"), PARSE_OPT_NONEG, chmod_callback), - {OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL, - N_("mark files as \"not changing\""), - PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG}, - {OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL, - N_("clear assumed-unchanged bit"), - PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, - {OPTION_SET_INT, 0, "skip-worktree", &mark_skip_worktree_only, NULL, - N_("mark files as \"index-only\""), - PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG}, - {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL, - N_("clear skip-worktree bit"), - PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, + { + .type = OPTION_SET_INT, + .long_name = "assume-unchanged", + .value = &mark_valid_only, + .help = N_("mark files as \"not changing\""), + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + .defval = MARK_FLAG, + }, + { + .type = OPTION_SET_INT, + .long_name = "no-assume-unchanged", + .value = &mark_valid_only, + .help = N_("clear assumed-unchanged bit"), + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + .defval = UNMARK_FLAG, + }, + { + .type = OPTION_SET_INT, + .long_name = "skip-worktree", + .value = &mark_skip_worktree_only, + .help = N_("mark files as \"index-only\""), + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + .defval = MARK_FLAG, + }, + { + .type = OPTION_SET_INT, + .long_name = "no-skip-worktree", + .value = &mark_skip_worktree_only, + .help = N_("clear skip-worktree bit"), + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + .defval = UNMARK_FLAG, + }, OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries, N_("do not touch index-only entries")), OPT_SET_INT(0, "info-only", &info_only, @@ -995,22 +1017,39 @@ int cmd_update_index(int argc, N_("remove named paths even if present in worktree"), 1), OPT_BOOL('z', NULL, &nul_term_line, N_("with --stdin: input lines are terminated by null bytes")), - {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL, - N_("read list of paths to be updated from standard input"), - PARSE_OPT_NONEG | PARSE_OPT_NOARG, - NULL, 0, stdin_callback}, - {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL, - N_("add entries from standard input to the index"), - PARSE_OPT_NONEG | PARSE_OPT_NOARG, - NULL, 0, stdin_cacheinfo_callback}, - {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL, - N_("repopulate stages #2 and #3 for the listed paths"), - PARSE_OPT_NONEG | PARSE_OPT_NOARG, - NULL, 0, unresolve_callback}, - {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL, - N_("only update entries that differ from HEAD"), - PARSE_OPT_NONEG | PARSE_OPT_NOARG, - NULL, 0, reupdate_callback}, + { + .type = OPTION_LOWLEVEL_CALLBACK, + .long_name = "stdin", + .value = &read_from_stdin, + .help = N_("read list of paths to be updated from standard input"), + .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG, + .ll_callback = stdin_callback, + }, + { + .type = OPTION_LOWLEVEL_CALLBACK, + .long_name = "index-info", + .value = &nul_term_line, + .help = N_("add entries from standard input to the index"), + .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG, + .ll_callback = stdin_cacheinfo_callback, + }, + { + .type = OPTION_LOWLEVEL_CALLBACK, + .long_name = "unresolve", + .value = &has_errors, + .help = N_("repopulate stages #2 and #3 for the listed paths"), + .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG, + .ll_callback = unresolve_callback, + }, + { + .type = OPTION_LOWLEVEL_CALLBACK, + .short_name = 'g', + .long_name = "again", + .value = &has_errors, + .help = N_("only update entries that differ from HEAD"), + .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG, + .ll_callback = reupdate_callback, + }, OPT_BIT(0, "ignore-missing", &refresh_args.flags, N_("ignore files missing from worktree"), REFRESH_IGNORE_MISSING), @@ -1036,12 +1075,22 @@ int cmd_update_index(int argc, N_("write out the index even if is not flagged as changed"), 1), OPT_BOOL(0, "fsmonitor", &fsmonitor, N_("enable or disable file system monitor")), - {OPTION_SET_INT, 0, "fsmonitor-valid", &mark_fsmonitor_only, NULL, - N_("mark files as fsmonitor valid"), - PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG}, - {OPTION_SET_INT, 0, "no-fsmonitor-valid", &mark_fsmonitor_only, NULL, - N_("clear fsmonitor valid bit"), - PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, + { + .type = OPTION_SET_INT, + .long_name = "fsmonitor-valid", + .value = &mark_fsmonitor_only, + .help = N_("mark files as fsmonitor valid"), + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + .defval = MARK_FLAG, + }, + { + .type = OPTION_SET_INT, + .long_name = "no-fsmonitor-valid", + .value = &mark_fsmonitor_only, + .help = N_("clear fsmonitor valid bit"), + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + .defval = UNMARK_FLAG, + }, OPT_END() }; diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 4d35bdc4b4..2b1e336ba1 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -5,6 +5,7 @@ #include "config.h" #include "gettext.h" #include "hash.h" +#include "hex.h" #include "refs.h" #include "object-name.h" #include "parse-options.h" @@ -13,7 +14,7 @@ static const char * const git_update_ref_usage[] = { 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]"), + N_("git update-ref [<options>] --stdin [-z] [--batch-updates]"), NULL }; @@ -179,7 +180,8 @@ static int parse_next_oid(const char **next, const char *end, (*next)++; *next = parse_arg(*next, &arg); if (arg.len) { - if (repo_get_oid(the_repository, arg.buf, oid)) + if (repo_get_oid_with_flags(the_repository, arg.buf, oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) goto invalid; } else { /* Without -z, an empty value means all zeros: */ @@ -197,7 +199,8 @@ static int parse_next_oid(const char **next, const char *end, *next += arg.len; if (arg.len) { - if (repo_get_oid(the_repository, arg.buf, oid)) + if (repo_get_oid_with_flags(the_repository, arg.buf, oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) goto invalid; } else if (flags & PARSE_SHA1_ALLOW_EMPTY) { /* With -z, treat an empty value as all zeros: */ @@ -299,7 +302,8 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction, die("symref-update %s: expected old value", refname); if (!strcmp(old_arg, "oid")) { - if (repo_get_oid(the_repository, old_target, &old_oid)) + if (repo_get_oid_with_flags(the_repository, old_target, &old_oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("symref-update %s: invalid oid: %s", refname, old_target); have_old_oid = 1; @@ -500,7 +504,7 @@ static void parse_cmd_symref_verify(struct ref_transaction *transaction, */ old_target = parse_next_refname(&next); if (!old_target) - oidcpy(&old_oid, null_oid()); + oidcpy(&old_oid, null_oid(the_hash_algo)); if (*next != line_termination) die("symref-verify %s: extra input: %s", refname, next); @@ -562,6 +566,49 @@ static void parse_cmd_abort(struct ref_transaction *transaction, report_ok("abort"); } +static void print_rejected_refs(const char *refname, + const struct object_id *old_oid, + const struct object_id *new_oid, + const char *old_target, + const char *new_target, + enum ref_transaction_error err, + void *cb_data UNUSED) +{ + struct strbuf sb = STRBUF_INIT; + const char *reason = ""; + + switch (err) { + case REF_TRANSACTION_ERROR_NAME_CONFLICT: + reason = "refname conflict"; + break; + case REF_TRANSACTION_ERROR_CREATE_EXISTS: + reason = "reference already exists"; + break; + case REF_TRANSACTION_ERROR_NONEXISTENT_REF: + reason = "reference does not exist"; + break; + case REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE: + reason = "incorrect old value provided"; + break; + case REF_TRANSACTION_ERROR_INVALID_NEW_VALUE: + reason = "invalid new value provided"; + break; + case REF_TRANSACTION_ERROR_EXPECTED_SYMREF: + reason = "expected symref but found regular ref"; + break; + default: + reason = "unkown failure"; + } + + strbuf_addf(&sb, "rejected %s %s %s %s\n", refname, + new_oid ? oid_to_hex(new_oid) : new_target, + old_oid ? oid_to_hex(old_oid) : old_target, + reason); + + fwrite(sb.buf, sb.len, 1, stdout); + strbuf_release(&sb); +} + static void parse_cmd_commit(struct ref_transaction *transaction, const char *next, const char *end UNUSED) { @@ -570,6 +617,10 @@ static void parse_cmd_commit(struct ref_transaction *transaction, die("commit: extra input: %s", next); if (ref_transaction_commit(transaction, &error)) die("commit: %s", error.buf); + + ref_transaction_for_each_rejected_update(transaction, + print_rejected_refs, NULL); + report_ok("commit"); ref_transaction_free(transaction); } @@ -606,7 +657,7 @@ static const struct parse_cmd { { "commit", parse_cmd_commit, 0, UPDATE_REFS_CLOSED }, }; -static void update_refs_stdin(void) +static void update_refs_stdin(unsigned int flags) { struct strbuf input = STRBUF_INIT, err = STRBUF_INIT; enum update_refs_state state = UPDATE_REFS_OPEN; @@ -614,7 +665,7 @@ static void update_refs_stdin(void) int i, j; transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - 0, &err); + flags, &err); if (!transaction) die("%s", err.buf); @@ -682,7 +733,7 @@ static void update_refs_stdin(void) */ state = cmd->state; transaction = ref_store_transaction_begin(get_main_ref_store(the_repository), - 0, &err); + flags, &err); if (!transaction) die("%s", err.buf); @@ -698,6 +749,8 @@ static void update_refs_stdin(void) /* Commit by default if no transaction was requested. */ if (ref_transaction_commit(transaction, &err)) die("%s", err.buf); + ref_transaction_for_each_rejected_update(transaction, + print_rejected_refs, NULL); ref_transaction_free(transaction); break; case UPDATE_REFS_STARTED: @@ -724,6 +777,8 @@ int cmd_update_ref(int argc, struct object_id oid, oldoid; int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0; int create_reflog = 0; + unsigned int flags = 0; + struct option options[] = { OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")), OPT_BOOL('d', NULL, &delete, N_("delete the reference")), @@ -732,6 +787,8 @@ int cmd_update_ref(int argc, OPT_BOOL('z', NULL, &end_null, N_("stdin has NUL-terminated arguments")), OPT_BOOL( 0 , "stdin", &read_stdin, N_("read updates from stdin")), OPT_BOOL( 0 , "create-reflog", &create_reflog, N_("create a reflog")), + OPT_BIT('0', "batch-updates", &flags, N_("batch reference updates"), + REF_TRANSACTION_ALLOW_FAILURE), OPT_END(), }; @@ -753,8 +810,10 @@ int cmd_update_ref(int argc, usage_with_options(git_update_ref_usage, options); if (end_null) line_termination = '\0'; - update_refs_stdin(); + update_refs_stdin(flags); return 0; + } else if (flags & REF_TRANSACTION_ALLOW_FAILURE) { + die("--batch-updates can only be used with --stdin"); } if (end_null) @@ -772,7 +831,8 @@ int cmd_update_ref(int argc, refname = argv[0]; value = argv[1]; oldval = argv[2]; - if (repo_get_oid(the_repository, value, &oid)) + if (repo_get_oid_with_flags(the_repository, value, &oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("%s: not a valid SHA1", value); } @@ -783,7 +843,8 @@ int cmd_update_ref(int argc, * must not already exist: */ oidclr(&oldoid, the_repository->hash_algo); - else if (repo_get_oid(the_repository, oldval, &oldoid)) + else if (repo_get_oid_with_flags(the_repository, oldval, &oldoid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("%s: not a valid old SHA1", oldval); } diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c index d7467290a8..ba702d30ef 100644 --- a/builtin/update-server-info.c +++ b/builtin/update-server-info.c @@ -20,8 +20,8 @@ int cmd_update_server_info(int argc, OPT_END() }; - if (repo) - repo_config(repo, git_default_config, NULL); + repo_config(repo, git_default_config, NULL); + argc = parse_options(argc, argv, prefix, options, update_server_info_usage, 0); if (argc > 0) diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 779b7988ca..5f749a30da 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -33,15 +32,15 @@ static int run_gpg_verify(struct commit *commit, unsigned flags) return ret; } -static int verify_commit(const char *name, unsigned flags) +static int verify_commit(struct repository *repo, const char *name, unsigned flags) { struct object_id oid; struct object *obj; - if (repo_get_oid(the_repository, name, &oid)) + if (repo_get_oid(repo, name, &oid)) return error("commit '%s' not found.", name); - obj = parse_object(the_repository, &oid); + obj = parse_object(repo, &oid); if (!obj) return error("%s: unable to read file.", name); if (obj->type != OBJ_COMMIT) @@ -54,7 +53,7 @@ static int verify_commit(const char *name, unsigned flags) int cmd_verify_commit(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -64,7 +63,7 @@ int cmd_verify_commit(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_commit_options, verify_commit_usage, PARSE_OPT_KEEP_ARGV0); @@ -78,7 +77,7 @@ int cmd_verify_commit(int argc, * was received in the process of writing the gpg input: */ signal(SIGPIPE, SIG_IGN); while (i < argc) - if (verify_commit(argv[i++], flags)) + if (verify_commit(repo, argv[i++], flags)) had_error = 1; return had_error; } diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index f6b97048a5..ed1c40338f 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag.sh */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -23,7 +22,7 @@ static const char * const verify_tag_usage[] = { int cmd_verify_tag(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -35,7 +34,7 @@ int cmd_verify_tag(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_tag_options, verify_tag_usage, PARSE_OPT_KEEP_ARGV0); @@ -56,7 +55,7 @@ int cmd_verify_tag(int argc, struct object_id oid; const char *name = argv[i++]; - if (repo_get_oid(the_repository, name, &oid)) { + if (repo_get_oid(repo, name, &oid)) { had_error = !!error("tag '%s' not found.", name); continue; } diff --git a/builtin/worktree.c b/builtin/worktree.c index 48448a8355..2dceeeed8b 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -348,7 +348,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir) char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir); if (file_exists(from_file)) { - if (safe_create_leading_directories(to_file) || + if (safe_create_leading_directories(the_repository, to_file) || copy_file(to_file, from_file, 0666)) error(_("failed to copy '%s' to '%s'; sparse-checkout may not work correctly"), from_file, to_file); @@ -367,7 +367,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir) struct config_set cs = { { 0 } }; int bare; - if (safe_create_leading_directories(to_file) || + if (safe_create_leading_directories(the_repository, to_file) || copy_file(to_file, from_file, 0666)) { error(_("failed to copy worktree config from '%s' to '%s'"), from_file, to_file); @@ -466,7 +466,7 @@ static int add_worktree(const char *path, const char *refname, name = sb_name.buf; repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name); len = sb_repo.len; - if (safe_create_leading_directories_const(sb_repo.buf)) + if (safe_create_leading_directories_const(the_repository, sb_repo.buf)) die_errno(_("could not create leading directories of '%s'"), sb_repo.buf); @@ -498,7 +498,7 @@ static int add_worktree(const char *path, const char *refname, write_file(sb.buf, _("initializing")); strbuf_addf(&sb_git, "%s/.git", path); - if (safe_create_leading_directories_const(sb_git.buf)) + if (safe_create_leading_directories_const(the_repository, sb_git.buf)) die_errno(_("could not create leading directories of '%s'"), sb_git.buf); junk_work_tree = xstrdup(path); @@ -578,7 +578,7 @@ done: strvec_pushl(&opt.env, "GIT_DIR", "GIT_WORK_TREE", NULL); strvec_pushl(&opt.args, - oid_to_hex(null_oid()), + oid_to_hex(null_oid(the_hash_algo)), oid_to_hex(&commit->object.oid), "1", NULL); @@ -621,7 +621,7 @@ static void print_preparing_worktree_line(int detach, else { struct commit *commit = lookup_commit_reference_by_name(branch); if (!commit) - BUG(_("unreachable: invalid reference: %s"), branch); + BUG("unreachable: invalid reference: %s", branch); fprintf_ln(stderr, _("Preparing worktree (detached HEAD %s)"), repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV)); } diff --git a/builtin/write-tree.c b/builtin/write-tree.c index 43f233e69b..5a8dc377ec 100644 --- a/builtin/write-tree.c +++ b/builtin/write-tree.c @@ -31,10 +31,14 @@ int cmd_write_tree(int argc, WRITE_TREE_MISSING_OK), OPT_STRING(0, "prefix", &tree_prefix, N_("<prefix>/"), N_("write tree object for a subdirectory <prefix>")), - { OPTION_BIT, 0, "ignore-cache-tree", &flags, NULL, - N_("only useful for debugging"), - PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, NULL, - WRITE_TREE_IGNORE_CACHE_TREE }, + { + .type = OPTION_BIT, + .long_name = "ignore-cache-tree", + .value = &flags, + .help = N_("only useful for debugging"), + .flags = PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, + .defval = WRITE_TREE_IGNORE_CACHE_TREE, + }, OPT_END() }; diff --git a/bulk-checkin.c b/bulk-checkin.c index 20f2da67b9..678e2ecc2c 100644 --- a/bulk-checkin.c +++ b/bulk-checkin.c @@ -3,7 +3,6 @@ */ #define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "bulk-checkin.h" @@ -18,7 +17,7 @@ #include "tmp-objdir.h" #include "packfile.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" static int odb_transaction_nesting; @@ -44,7 +43,7 @@ static void finish_tmp_packfile(struct strbuf *basename, { char *idx_tmp_name = NULL; - stage_tmp_packfiles(the_hash_algo, basename, pack_tmp_name, + stage_tmp_packfiles(the_repository, basename, pack_tmp_name, written_list, nr_written, NULL, pack_idx_opts, hash, &idx_tmp_name); rename_tmp_packfile_idx(basename, &idx_tmp_name); @@ -56,7 +55,6 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state) { unsigned char hash[GIT_MAX_RAWSZ]; struct strbuf packname = STRBUF_INIT; - int i; if (!state->f) return; @@ -82,7 +80,7 @@ static void flush_bulk_checkin_packfile(struct bulk_checkin_packfile *state) finish_tmp_packfile(&packname, state->pack_tmp_name, state->written, state->nr_written, &state->pack_idx_opts, hash); - for (i = 0; i < state->nr_written; i++) + for (uint32_t i = 0; i < state->nr_written; i++) free(state->written[i]); clear_exit: @@ -131,14 +129,13 @@ static void flush_batch_fsync(void) static int already_written(struct bulk_checkin_packfile *state, struct object_id *oid) { - int i; - /* The object may already exist in the repository */ - if (repo_has_object_file(the_repository, oid)) + if (has_object(the_repository, oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return 1; /* Might want to keep the list sorted */ - for (i = 0; i < state->nr_written; i++) + for (uint32_t i = 0; i < state->nr_written; i++) if (oideq(&state->written[i]->oid, oid)) return 1; @@ -171,7 +168,7 @@ static int stream_blob_to_pack(struct bulk_checkin_packfile *state, unsigned char obuf[16384]; unsigned hdrlen; int status = Z_OK; - int write_object = (flags & HASH_WRITE_OBJECT); + int write_object = (flags & INDEX_WRITE_OBJECT); off_t offset = 0; git_deflate_init(&s, pack_compression_level); @@ -182,13 +179,13 @@ static int stream_blob_to_pack(struct bulk_checkin_packfile *state, while (status != Z_STREAM_END) { if (size && !s.avail_in) { - ssize_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf); + size_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf); ssize_t read_result = read_in_full(fd, ibuf, rsize); if (read_result < 0) die_errno("failed to read from '%s'", path); - if (read_result != rsize) - die("failed to read %d bytes from '%s'", - (int)rsize, path); + if ((size_t)read_result != rsize) + die("failed to read %u bytes from '%s'", + (unsigned)rsize, path); offset += rsize; if (*already_hashed_to < offset) { size_t hsize = offset - *already_hashed_to; @@ -241,10 +238,10 @@ static int stream_blob_to_pack(struct bulk_checkin_packfile *state, static void prepare_to_stream(struct bulk_checkin_packfile *state, unsigned flags) { - if (!(flags & HASH_WRITE_OBJECT) || state->f) + if (!(flags & INDEX_WRITE_OBJECT) || state->f) return; - state->f = create_tmp_packfile(&state->pack_tmp_name); + state->f = create_tmp_packfile(the_repository, &state->pack_tmp_name); reset_pack_idx_option(&state->pack_idx_opts); /* Pretend we are going to write only one object */ @@ -275,7 +272,7 @@ static int deflate_blob_to_pack(struct bulk_checkin_packfile *state, git_hash_update(&ctx, obuf, header_len); /* Note: idx is non-NULL when we are writing */ - if ((flags & HASH_WRITE_OBJECT) != 0) { + if ((flags & INDEX_WRITE_OBJECT) != 0) { CALLOC_ARRAY(idx, 1); prepare_to_stream(state, flags); diff --git a/bulk-checkin.h b/bulk-checkin.h index aa7286a7b3..7246ea58dc 100644 --- a/bulk-checkin.h +++ b/bulk-checkin.h @@ -9,6 +9,21 @@ void prepare_loose_object_bulk_checkin(void); void fsync_loose_object_bulk_checkin(int fd, const char *filename); +/* + * This creates one packfile per large blob unless bulk-checkin + * machinery is "plugged". + * + * This also bypasses the usual "convert-to-git" dance, and that is on + * purpose. We could write a streaming version of the converting + * functions and insert that before feeding the data to fast-import + * (or equivalent in-core API described above). However, that is + * somewhat complicated, as we do not know the size of the filter + * result, which we need to know beforehand when writing a git object. + * Since the primary motivation for trying to stream from the working + * tree file and to avoid mmaping it in core is to deal with large + * binary blobs, they generally do not want to get any conversion, and + * callers should avoid this code path when filters are requested. + */ int index_blob_bulk_checkin(struct object_id *oid, int fd, size_t size, const char *path, unsigned flags); diff --git a/bundle-uri.c b/bundle-uri.c index 744257c49c..c9d65aa0ce 100644 --- a/bundle-uri.c +++ b/bundle-uri.c @@ -14,7 +14,7 @@ #include "fetch-pack.h" #include "remote.h" #include "trace2.h" -#include "object-store-ll.h" +#include "object-store.h" static struct { enum bundle_list_heuristic heuristic; @@ -122,7 +122,7 @@ void print_bundle_list(FILE *fp, struct bundle_list *list) int i; for (i = 0; i < BUNDLE_HEURISTIC__COUNT; i++) { if (heuristics[i].heuristic == list->heuristic) { - printf("\theuristic = %s\n", + fprintf(fp, "\theuristic = %s\n", heuristics[list->heuristic].name); break; } @@ -403,7 +403,7 @@ static int unbundle_from_file(struct repository *r, const char *file) const char *branch_name; int has_old; - if (!skip_prefix(refname->string, "refs/heads/", &branch_name)) + if (!skip_prefix(refname->string, "refs/", &branch_name)) continue; strbuf_setlen(&bundle_ref, bundle_prefix_len); @@ -532,11 +532,13 @@ static int fetch_bundles_by_token(struct repository *r, */ if (!repo_config_get_value(r, "fetch.bundlecreationtoken", - &creationTokenStr) && - sscanf(creationTokenStr, "%"PRIu64, &maxCreationToken) == 1 && - bundles.items[0]->creationToken <= maxCreationToken) { - free(bundles.items); - return 0; + &creationTokenStr)) { + if (sscanf(creationTokenStr, "%"PRIu64, &maxCreationToken) != 1) + maxCreationToken = 0; + if (bundles.items[0]->creationToken <= maxCreationToken) { + free(bundles.items); + return 0; + } } /* @@ -7,7 +7,7 @@ #include "environment.h" #include "gettext.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "repository.h" #include "object.h" #include "commit.h" @@ -384,6 +384,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs) { int i; int ref_count = 0; + struct strset objects = STRSET_INIT; for (i = 0; i < revs->pending.nr; i++) { struct object_array_entry *e = revs->pending.objects + i; @@ -401,6 +402,9 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs) flag = 0; display_ref = (flag & REF_ISSYMREF) ? e->name : ref; + if (strset_contains(&objects, display_ref)) + goto skip_write_ref; + if (e->item->type == OBJ_TAG && !is_tag_in_date_range(e->item, revs)) { e->item->flags |= UNINTERESTING; @@ -423,6 +427,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs) } ref_count++; + strset_add(&objects, display_ref); write_or_die(bundle_fd, oid_to_hex(&e->item->oid), the_hash_algo->hexsz); write_or_die(bundle_fd, " ", 1); write_or_die(bundle_fd, display_ref, strlen(display_ref)); @@ -431,6 +436,8 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs) free(ref); } + strset_clear(&objects); + /* end header */ write_or_die(bundle_fd, "\n", 1); return ref_count; @@ -566,7 +573,6 @@ int create_bundle(struct repository *r, const char *path, */ revs.blob_objects = revs.tree_objects = 0; traverse_commit_list(&revs, write_bundle_prerequisites, NULL, &bpi); - object_array_remove_duplicates(&revs_copy.pending); /* write bundle refs */ ref_count = write_bundle_refs(bundle_fd, &revs_copy); diff --git a/cache-tree.c b/cache-tree.c index bcbcad3d61..fa3858e282 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -10,7 +10,7 @@ #include "cache-tree.h" #include "bulk-checkin.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "read-cache-ll.h" #include "replace-object.h" #include "repository.h" @@ -238,7 +238,9 @@ int cache_tree_fully_valid(struct cache_tree *it) int i; if (!it) return 0; - if (it->entry_count < 0 || !repo_has_object_file(the_repository, &it->oid)) + if (it->entry_count < 0 || + has_object(the_repository, &it->oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return 0; for (i = 0; i < it->subtree_nr; i++) { if (!cache_tree_fully_valid(it->down[i]->cache_tree)) @@ -289,7 +291,9 @@ static int update_one(struct cache_tree *it, } } - if (0 <= it->entry_count && repo_has_object_file(the_repository, &it->oid)) + if (0 <= it->entry_count && + has_object(the_repository, &it->oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return it->entry_count; /* @@ -395,7 +399,8 @@ static int update_one(struct cache_tree *it, ce_missing_ok = mode == S_IFGITLINK || missing_ok || !must_check_existence(ce); if (is_null_oid(oid) || - (!ce_missing_ok && !repo_has_object_file(the_repository, oid))) { + (!ce_missing_ok && !has_object(the_repository, oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))) { strbuf_release(&buffer); if (expected_missing) return -1; @@ -443,7 +448,7 @@ static int update_one(struct cache_tree *it, struct object_id oid; hash_object_file(the_hash_algo, buffer.buf, buffer.len, OBJ_TREE, &oid); - if (repo_has_object_file_with_flags(the_repository, &oid, OBJECT_INFO_SKIP_FETCH_OBJECT)) + if (has_object(the_repository, &oid, HAS_OBJECT_RECHECK_PACKED)) oidcpy(&it->oid, &oid); else to_invalidate = 1; @@ -452,7 +457,7 @@ static int update_one(struct cache_tree *it, OBJ_TREE, &it->oid); } else if (write_object_file_flags(buffer.buf, buffer.len, OBJ_TREE, &it->oid, NULL, flags & WRITE_TREE_SILENT - ? HASH_SILENT : 0)) { + ? WRITE_OBJECT_FILE_SILENT : 0)) { strbuf_release(&buffer); return -1; } diff --git a/ci/check-unsafe-assertions.sh b/ci/check-unsafe-assertions.sh new file mode 100755 index 0000000000..233bd9dfbc --- /dev/null +++ b/ci/check-unsafe-assertions.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +make CHECK_ASSERTION_SIDE_EFFECTS=1 >compiler_output 2>compiler_error +if test $? != 0 +then + echo >&2 "ERROR: The compiler could not verify the following assert()" + echo >&2 " calls are free of side-effects. Please replace with" + echo >&2 " ASSERT() calls." + grep undefined.reference.to..not_supposed_to_survive compiler_error | + sed -e s/:[^:]*$// | sort | uniq | tr ':' ' ' | + while read f l + do + printf "${f}:${l}\n " + awk -v start="$l" 'NR >= start { print; if (/\);/) exit }' $f + done + exit 1 +fi +rm compiler_output compiler_error diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh index da19dada2c..d061a47293 100755 --- a/ci/install-dependencies.sh +++ b/ci/install-dependencies.sh @@ -9,7 +9,7 @@ begin_group "Install dependencies" P4WHENCE=https://cdist2.perforce.com/perforce/r23.2 LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION -JGITWHENCE=https://repo.eclipse.org/content/groups/releases//org/eclipse/jgit/org.eclipse.jgit.pgm/6.8.0.202311291450-r/org.eclipse.jgit.pgm-6.8.0.202311291450-r.sh +JGITWHENCE=https://repo1.maven.org/maven2/org/eclipse/jgit/org.eclipse.jgit.pgm/6.8.0.202311291450-r/org.eclipse.jgit.pgm-6.8.0.202311291450-r.sh # Make sudo a no-op and execute the command directly when running as root. # While using sudo would be fine on most platforms when we are root already, @@ -71,7 +71,6 @@ ubuntu-*|i386/ubuntu-*|debian-*) chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4" || { rm -f "$CUSTOM_PATH/p4" rm -f "$CUSTOM_PATH/p4d" - echo >&2 "P4 download (optional) failed" } wget --quiet \ @@ -79,16 +78,12 @@ ubuntu-*|i386/ubuntu-*|debian-*) tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \ -C "$CUSTOM_PATH" --strip-components=1 \ "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs" && - rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" || { - rm -f "$CUSTOM_PATH/git-lfs" - echo >&2 "LFS download (optional) failed" - } + rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" || + rm -f "$CUSTOM_PATH/git-lfs" wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit" && - chmod a+x "$CUSTOM_PATH/jgit" || { - rm -f "$CUSTOM_PATH/jgit" - echo >&2 "JGit download (optional) failed" - } + chmod a+x "$CUSTOM_PATH/jgit" || + rm -f "$CUSTOM_PATH/jgit" ;; esac ;; @@ -151,7 +146,7 @@ then echo "$(tput setaf 6)Perforce Client Version$(tput sgr0)" p4 -V else - echo >&2 "WARNING: perforce wasn't installed, see above for clues why" + echo >&2 "::warning:: perforce wasn't installed, see above for clues why" fi if type git-lfs >/dev/null 2>&1 @@ -159,7 +154,7 @@ then echo "$(tput setaf 6)Git-LFS Version$(tput sgr0)" git-lfs version else - echo >&2 "WARNING: git-lfs wasn't installed, see above for clues why" + echo >&2 "::warning:: git-lfs wasn't installed, see above for clues why" fi if type jgit >/dev/null 2>&1 @@ -167,7 +162,7 @@ then echo "$(tput setaf 6)JGit Version$(tput sgr0)" jgit version else - echo >&2 "WARNING: JGit wasn't installed, see above for clues why" + echo >&2 "::warning:: JGit wasn't installed, see above for clues why" fi end_group "Install dependencies" diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index 1c69846723..01823fd0f1 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -5,11 +5,6 @@ . ${0%/*}/lib.sh -case "$CI_OS_NAME" in -windows*) cmd //c mklink //j t\\.prove "$(cygpath -aw "$cache_dir/.prove")";; -*) ln -s "$cache_dir/.prove" t/.prove;; -esac - run_tests=t case "$jobname" in @@ -20,7 +15,6 @@ linux-breaking-changes) linux-TEST-vars) export OPENSSL_SHA1_UNSAFE=YesPlease export GIT_TEST_SPLIT_INDEX=yes - export GIT_TEST_MERGE_ALGORITHM=recursive export GIT_TEST_FULL_IN_PACK_ARRAY=true export GIT_TEST_OE_SIZE=10 export GIT_TEST_OE_DELTA_SIZE=5 @@ -57,6 +51,7 @@ case "$jobname" in --warnlevel 2 --werror \ --wrap-mode nofallback \ -Dfuzzers=true \ + -Dtest_output_directory="${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}" \ $MESONFLAGS group "Build" meson compile -C build -- if test -n "$run_tests" diff --git a/ci/run-static-analysis.sh b/ci/run-static-analysis.sh index 0d51e5ce0e..9e9c72681d 100755 --- a/ci/run-static-analysis.sh +++ b/ci/run-static-analysis.sh @@ -26,9 +26,11 @@ then exit 1 fi -make hdr-check || +make check-headers || exit 1 make check-pot +${0%/*}/check-unsafe-assertions.sh + save_good_tree diff --git a/ci/run-test-slice.sh b/ci/run-test-slice.sh index e167e646f7..0444c79c02 100755 --- a/ci/run-test-slice.sh +++ b/ci/run-test-slice.sh @@ -5,11 +5,6 @@ . ${0%/*}/lib.sh -case "$CI_OS_NAME" in -windows*) cmd //c mklink //j t\\.prove "$(cygpath -aw "$cache_dir/.prove")";; -*) ln -s "$cache_dir/.prove" t/.prove;; -esac - group "Run tests" make --quiet -C t T="$(cd t && ./helper/test-tool path-utils slice-tests "$1" "$2" t[0-9]*.sh | tr '\n' ' ')" || diff --git a/ci/test-documentation.sh b/ci/test-documentation.sh index 6c018b673e..49f87f50fd 100755 --- a/ci/test-documentation.sh +++ b/ci/test-documentation.sh @@ -15,6 +15,13 @@ filter_log () { "$1" } +check_docs () { + test -s "$1"/Documentation/git.html && + test -s "$1"/Documentation/git.xml && + test -s "$1"/Documentation/git.1 && + grep "<meta name=\"generator\" content=\"$2 " "$1"/Documentation/git.html +} + make check-builtins make check-docs @@ -23,10 +30,7 @@ make doc > >(tee stdout.log) 2> >(tee stderr.raw >&2) cat stderr.raw filter_log stderr.raw >stderr.log test ! -s stderr.log -test -s Documentation/git.html -test -s Documentation/git.xml -test -s Documentation/git.1 -grep '<meta name="generator" content="AsciiDoc ' Documentation/git.html +check_docs . AsciiDoc rm -f stdout.log stderr.log stderr.raw check_unignored_build_artifacts @@ -37,10 +41,21 @@ make USE_ASCIIDOCTOR=1 doc > >(tee stdout.log) 2> >(tee stderr.raw >&2) cat stderr.raw filter_log stderr.raw >stderr.log test ! -s stderr.log -test -s Documentation/git.html -grep '<meta name="generator" content="Asciidoctor ' Documentation/git.html +check_docs . Asciidoctor rm -f stdout.log stderr.log stderr.raw check_unignored_build_artifacts +# Build docs with Meson and AsciiDoc +meson setup build-asciidoc -Ddocs=html,man -Ddocs_backend=asciidoc +meson compile -C build-asciidoc +check_docs build-asciidoc AsciiDoc +rm -rf build-asciidoc + +# Build docs with Meson and AsciiDoctor +meson setup build-asciidoctor -Ddocs=html,man -Ddocs_backend=asciidoctor +meson compile -C build-asciidoctor +check_docs build-asciidoctor Asciidoctor +rm -rf build-asciidoctor + save_good_tree diff --git a/combine-diff.c b/combine-diff.c index 9527f3160d..dfae9f7995 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -2,7 +2,7 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "convert.h" #include "diff.h" @@ -1066,7 +1066,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, &result_size, NULL, NULL); } else if (textconv) { struct diff_filespec *df = alloc_filespec(elem->path); - fill_filespec(df, null_oid(), 0, st.st_mode); + fill_filespec(df, null_oid(the_hash_algo), 0, st.st_mode); result_size = fill_textconv(opt->repo, textconv, df, &result); free_filespec(df); } else if (0 <= (fd = open(elem->path, O_RDONLY))) { diff --git a/command-list.txt b/command-list.txt index c537114b46..b7ade3ab9f 100644 --- a/command-list.txt +++ b/command-list.txt @@ -96,6 +96,7 @@ git-diagnose ancillaryinterrogators git-diff mainporcelain info git-diff-files plumbinginterrogators git-diff-index plumbinginterrogators +git-diff-pairs plumbinginterrogators git-diff-tree plumbinginterrogators git-difftool ancillaryinterrogators complete git-fast-export ancillarymanipulators diff --git a/commit-graph.c b/commit-graph.c index 1021ccb983..ad3943b690 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -13,8 +13,7 @@ #include "refs.h" #include "hash-lookup.h" #include "commit-graph.h" -#include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oid-array.h" #include "path.h" #include "alloc.h" @@ -223,7 +222,7 @@ static int commit_graph_compatible(struct repository *r) if (replace_refs_enabled(r)) { prepare_replace_object(r); - if (hashmap_get_size(&r->objects->replace_map->map)) + if (oidmap_get_size(&r->objects->replace_map)) return 0; } @@ -1930,6 +1929,8 @@ static int fill_oids_from_packs(struct write_commit_graph_context *ctx, } if (open_pack_index(p)) { ret = error(_("error opening index for %s"), packname.buf); + close_pack(p); + free(p); goto cleanup; } for_each_object_in_pack(p, add_packed_commits, ctx, @@ -2065,7 +2066,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) ctx->graph_name = get_commit_graph_filename(ctx->odb); } - if (safe_create_leading_directories(ctx->graph_name)) { + if (safe_create_leading_directories(the_repository, ctx->graph_name)) { error(_("unable to create leading directories of %s"), ctx->graph_name); return -1; @@ -2090,11 +2091,13 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) return -1; } - f = hashfd(get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer)); + f = hashfd(the_repository->hash_algo, + get_tempfile_fd(graph_layer), get_tempfile_path(graph_layer)); } else { hold_lock_file_for_update_mode(&lk, ctx->graph_name, LOCK_DIE_ON_ERROR, 0444); - f = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk)); + f = hashfd(the_repository->hash_algo, + get_lock_file_fd(&lk), get_lock_file_path(&lk)); } cf = init_chunkfile(f); @@ -2508,7 +2511,17 @@ int write_commit_graph(struct object_directory *odb, const struct commit_graph_opts *opts) { struct repository *r = the_repository; - struct write_commit_graph_context *ctx; + struct write_commit_graph_context ctx = { + .r = r, + .odb = odb, + .append = flags & COMMIT_GRAPH_WRITE_APPEND ? 1 : 0, + .report_progress = flags & COMMIT_GRAPH_WRITE_PROGRESS ? 1 : 0, + .split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0, + .opts = opts, + .total_bloom_filter_data_size = 0, + .write_generation_data = (get_configured_generation_version(r) == 2), + .num_generation_data_overflows = 0, + }; uint32_t i; int res = 0; int replace = 0; @@ -2530,17 +2543,6 @@ int write_commit_graph(struct object_directory *odb, return 0; } - CALLOC_ARRAY(ctx, 1); - ctx->r = r; - ctx->odb = odb; - ctx->append = flags & COMMIT_GRAPH_WRITE_APPEND ? 1 : 0; - ctx->report_progress = flags & COMMIT_GRAPH_WRITE_PROGRESS ? 1 : 0; - ctx->split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0; - ctx->opts = opts; - ctx->total_bloom_filter_data_size = 0; - ctx->write_generation_data = (get_configured_generation_version(r) == 2); - ctx->num_generation_data_overflows = 0; - bloom_settings.hash_version = r->settings.commit_graph_changed_paths_version; bloom_settings.bits_per_entry = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY", bloom_settings.bits_per_entry); @@ -2548,14 +2550,14 @@ int write_commit_graph(struct object_directory *odb, bloom_settings.num_hashes); bloom_settings.max_changed_paths = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS", bloom_settings.max_changed_paths); - ctx->bloom_settings = &bloom_settings; + ctx.bloom_settings = &bloom_settings; init_topo_level_slab(&topo_levels); - ctx->topo_levels = &topo_levels; + ctx.topo_levels = &topo_levels; - prepare_commit_graph(ctx->r); - if (ctx->r->objects->commit_graph) { - struct commit_graph *g = ctx->r->objects->commit_graph; + prepare_commit_graph(ctx.r); + if (ctx.r->objects->commit_graph) { + struct commit_graph *g = ctx.r->objects->commit_graph; while (g) { g->topo_levels = &topo_levels; @@ -2564,15 +2566,15 @@ int write_commit_graph(struct object_directory *odb, } if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS) - ctx->changed_paths = 1; + ctx.changed_paths = 1; if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) { struct commit_graph *g; - g = ctx->r->objects->commit_graph; + g = ctx.r->objects->commit_graph; /* We have changed-paths already. Keep them in the next graph */ if (g && g->bloom_filter_settings) { - ctx->changed_paths = 1; + ctx.changed_paths = 1; /* don't propagate the hash_version unless unspecified */ if (bloom_settings.hash_version == -1) @@ -2585,116 +2587,123 @@ int write_commit_graph(struct object_directory *odb, bloom_settings.hash_version = bloom_settings.hash_version == 2 ? 2 : 1; - if (ctx->split) { - struct commit_graph *g = ctx->r->objects->commit_graph; + if (ctx.split) { + struct commit_graph *g = ctx.r->objects->commit_graph; while (g) { - ctx->num_commit_graphs_before++; + ctx.num_commit_graphs_before++; g = g->base_graph; } - if (ctx->num_commit_graphs_before) { - ALLOC_ARRAY(ctx->commit_graph_filenames_before, ctx->num_commit_graphs_before); - i = ctx->num_commit_graphs_before; - g = ctx->r->objects->commit_graph; + if (ctx.num_commit_graphs_before) { + ALLOC_ARRAY(ctx.commit_graph_filenames_before, ctx.num_commit_graphs_before); + i = ctx.num_commit_graphs_before; + g = ctx.r->objects->commit_graph; while (g) { - ctx->commit_graph_filenames_before[--i] = xstrdup(g->filename); + ctx.commit_graph_filenames_before[--i] = xstrdup(g->filename); g = g->base_graph; } } - if (ctx->opts) - replace = ctx->opts->split_flags & COMMIT_GRAPH_SPLIT_REPLACE; + if (ctx.opts) + replace = ctx.opts->split_flags & COMMIT_GRAPH_SPLIT_REPLACE; } - ctx->approx_nr_objects = repo_approximate_object_count(the_repository); + ctx.approx_nr_objects = repo_approximate_object_count(the_repository); - if (ctx->append && ctx->r->objects->commit_graph) { - struct commit_graph *g = ctx->r->objects->commit_graph; + if (ctx.append && ctx.r->objects->commit_graph) { + struct commit_graph *g = ctx.r->objects->commit_graph; for (i = 0; i < g->num_commits; i++) { struct object_id oid; oidread(&oid, g->chunk_oid_lookup + st_mult(g->hash_len, i), the_repository->hash_algo); - oid_array_append(&ctx->oids, &oid); + oid_array_append(&ctx.oids, &oid); } } if (pack_indexes) { - ctx->order_by_pack = 1; - if ((res = fill_oids_from_packs(ctx, pack_indexes))) + ctx.order_by_pack = 1; + if ((res = fill_oids_from_packs(&ctx, pack_indexes))) goto cleanup; } if (commits) { - if ((res = fill_oids_from_commits(ctx, commits))) + if ((res = fill_oids_from_commits(&ctx, commits))) goto cleanup; } if (!pack_indexes && !commits) { - ctx->order_by_pack = 1; - fill_oids_from_all_packs(ctx); + ctx.order_by_pack = 1; + fill_oids_from_all_packs(&ctx); } - close_reachable(ctx); + close_reachable(&ctx); - copy_oids_to_commits(ctx); + copy_oids_to_commits(&ctx); - if (ctx->commits.nr >= GRAPH_EDGE_LAST_MASK) { + if (ctx.commits.nr >= GRAPH_EDGE_LAST_MASK) { error(_("too many commits to write graph")); res = -1; goto cleanup; } - if (!ctx->commits.nr && !replace) + if (!ctx.commits.nr && !replace) goto cleanup; - if (ctx->split) { - split_graph_merge_strategy(ctx); + if (ctx.split) { + split_graph_merge_strategy(&ctx); if (!replace) - merge_commit_graphs(ctx); + merge_commit_graphs(&ctx); } else - ctx->num_commit_graphs_after = 1; + ctx.num_commit_graphs_after = 1; - ctx->trust_generation_numbers = validate_mixed_generation_chain(ctx->r->objects->commit_graph); + ctx.trust_generation_numbers = validate_mixed_generation_chain(ctx.r->objects->commit_graph); - compute_topological_levels(ctx); - if (ctx->write_generation_data) - compute_generation_numbers(ctx); + compute_topological_levels(&ctx); + if (ctx.write_generation_data) + compute_generation_numbers(&ctx); - if (ctx->changed_paths) - compute_bloom_filters(ctx); + if (ctx.changed_paths) + compute_bloom_filters(&ctx); - res = write_commit_graph_file(ctx); + res = write_commit_graph_file(&ctx); - if (ctx->changed_paths) + if (ctx.changed_paths) deinit_bloom_filters(); - if (ctx->split) - mark_commit_graphs(ctx); + if (ctx.split) + mark_commit_graphs(&ctx); - expire_commit_graphs(ctx); + expire_commit_graphs(&ctx); cleanup: - free(ctx->graph_name); - free(ctx->base_graph_name); - free(ctx->commits.list); - oid_array_clear(&ctx->oids); + free(ctx.graph_name); + free(ctx.base_graph_name); + free(ctx.commits.list); + oid_array_clear(&ctx.oids); clear_topo_level_slab(&topo_levels); - for (i = 0; i < ctx->num_commit_graphs_before; i++) - free(ctx->commit_graph_filenames_before[i]); - free(ctx->commit_graph_filenames_before); + if (ctx.r->objects->commit_graph) { + struct commit_graph *g = ctx.r->objects->commit_graph; - for (i = 0; i < ctx->num_commit_graphs_after; i++) { - free(ctx->commit_graph_filenames_after[i]); - free(ctx->commit_graph_hash_after[i]); + while (g) { + g->topo_levels = NULL; + g = g->base_graph; + } } - free(ctx->commit_graph_filenames_after); - free(ctx->commit_graph_hash_after); - free(ctx); + for (i = 0; i < ctx.num_commit_graphs_before; i++) + free(ctx.commit_graph_filenames_before[i]); + free(ctx.commit_graph_filenames_before); + + for (i = 0; i < ctx.num_commit_graphs_after; i++) { + free(ctx.commit_graph_filenames_after[i]); + free(ctx.commit_graph_hash_after[i]); + } + free(ctx.commit_graph_filenames_after); + free(ctx.commit_graph_hash_after); return res; } @@ -2716,7 +2725,8 @@ static void graph_report(const char *fmt, ...) static int commit_graph_checksum_valid(struct commit_graph *g) { - return hashfile_checksum_valid(g->data, g->data_len); + return hashfile_checksum_valid(the_repository->hash_algo, + g->data, g->data_len); } static int verify_one_commit_graph(struct repository *r, diff --git a/commit-graph.h b/commit-graph.h index 6781940195..13f662827d 100644 --- a/commit-graph.h +++ b/commit-graph.h @@ -1,7 +1,7 @@ #ifndef COMMIT_GRAPH_H #define COMMIT_GRAPH_H -#include "object-store-ll.h" +#include "object-store.h" #include "oidset.h" #define GIT_TEST_COMMIT_GRAPH "GIT_TEST_COMMIT_GRAPH" @@ -9,7 +9,7 @@ #include "hex.h" #include "repository.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "utf8.h" #include "diff.h" #include "revision.h" @@ -29,6 +29,7 @@ #include "tree.h" #include "hook.h" #include "parse.h" +#include "object-file.h" #include "object-file-convert.h" static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **); @@ -780,19 +781,17 @@ static void clear_commit_marks_1(struct commit_list **plist, void clear_commit_marks_many(size_t nr, struct commit **commit, unsigned int mark) { - for (size_t i = 0; i < nr; i++) { - struct commit_list *list = NULL; - - clear_commit_marks_1(&list, *commit, mark); - while (list) - clear_commit_marks_1(&list, pop_commit(&list), mark); - commit++; - } + for (size_t i = 0; i < nr; i++) + clear_commit_marks(commit[i], mark); } void clear_commit_marks(struct commit *commit, unsigned int mark) { - clear_commit_marks_many(1, &commit, mark); + struct commit_list *list = NULL; + + clear_commit_marks_1(&list, commit, mark); + while (list) + clear_commit_marks_1(&list, pop_commit(&list), mark); } struct commit *pop_commit(struct commit_list **stack) @@ -1380,7 +1379,7 @@ static int convert_commit_extra_headers(const struct commit_extra_header *orig, struct commit_extra_header *new; CALLOC_ARRAY(new, 1); if (!strcmp(orig->key, "mergetag")) { - if (convert_object_file(&out, algo, compat, + if (convert_object_file(the_repository, &out, algo, compat, orig->value, orig->len, OBJ_TAG, 1)) { free(new); diff --git a/compat/mingw-posix.h b/compat/mingw-posix.h new file mode 100644 index 0000000000..88e0cf9292 --- /dev/null +++ b/compat/mingw-posix.h @@ -0,0 +1,435 @@ +#ifndef COMPAT_MINGW_POSIX_H +#define COMPAT_MINGW_POSIX_H + +#ifdef __MINGW64_VERSION_MAJOR +#include <stdint.h> +#include <wchar.h> +typedef _sigset_t sigset_t; +#endif +#include <winsock2.h> +#include <ws2tcpip.h> + +/* MinGW-w64 reports to have flockfile, but it does not actually have it. */ +#ifdef __MINGW64_VERSION_MAJOR +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#endif + +/* + * things that are not available in header files + */ + +typedef int uid_t; +typedef int socklen_t; +#ifndef __MINGW64_VERSION_MAJOR +typedef int pid_t; +#define hstrerror strerror +#endif + +#define S_IFLNK 0120000 /* Symbolic link */ +#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK) +#define S_ISSOCK(x) 0 + +#ifndef S_IRWXG +#define S_IRGRP 0 +#define S_IWGRP 0 +#define S_IXGRP 0 +#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#endif +#ifndef S_IRWXO +#define S_IROTH 0 +#define S_IWOTH 0 +#define S_IXOTH 0 +#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif + +#define S_ISUID 0004000 +#define S_ISGID 0002000 +#define S_ISVTX 0001000 + +#define WIFEXITED(x) 1 +#define WIFSIGNALED(x) 0 +#define WEXITSTATUS(x) ((x) & 0xff) +#define WTERMSIG(x) SIGTERM + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN +#endif +#ifndef ELOOP +#define ELOOP EMLINK +#endif +#define SHUT_WR SD_SEND + +#define SIGHUP 1 +#define SIGQUIT 3 +#define SIGKILL 9 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGCHLD 17 + +#define F_GETFD 1 +#define F_SETFD 2 +#define FD_CLOEXEC 0x1 + +#if !defined O_CLOEXEC && defined O_NOINHERIT +#define O_CLOEXEC O_NOINHERIT +#endif + +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif +#ifndef ECONNABORTED +#define ECONNABORTED WSAECONNABORTED +#endif +#ifndef ENOTSOCK +#define ENOTSOCK WSAENOTSOCK +#endif + +struct passwd { + char *pw_name; + char *pw_gecos; + char *pw_dir; +}; + +typedef void (__cdecl *sig_handler_t)(int); +struct sigaction { + sig_handler_t sa_handler; + unsigned sa_flags; +}; +#define SA_RESTART 0 + +struct itimerval { + struct timeval it_value, it_interval; +}; +#define ITIMER_REAL 0 + +struct utsname { + char sysname[16]; + char nodename[1]; + char release[16]; + char version[16]; + char machine[1]; +}; + +/* + * sanitize preprocessor namespace polluted by Windows headers defining + * macros which collide with git local versions + */ +#undef HELP_COMMAND /* from winuser.h */ + +/* + * trivial stubs + */ + +static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED) +{ errno = ENOSYS; return -1; } +static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED) +{ errno = ENOSYS; return -1; } +static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED) +{ errno = ENOSYS; return -1; } +#ifndef __MINGW64_VERSION_MAJOR +static inline pid_t fork(void) +{ errno = ENOSYS; return -1; } +#endif +static inline unsigned int alarm(unsigned int seconds UNUSED) +{ return 0; } +static inline int fsync(int fd) +{ return _commit(fd); } +static inline void sync(void) +{} +static inline uid_t getuid(void) +{ return 1; } +static inline struct passwd *getpwnam(const char *name UNUSED) +{ return NULL; } +static inline int fcntl(int fd UNUSED, int cmd, ...) +{ + if (cmd == F_GETFD || cmd == F_SETFD) + return 0; + errno = EINVAL; + return -1; +} + +#define sigemptyset(x) (void)0 +static inline int sigaddset(sigset_t *set UNUSED, int signum UNUSED) +{ return 0; } +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 0 +static inline int sigprocmask(int how UNUSED, const sigset_t *set UNUSED, sigset_t *oldset UNUSED) +{ return 0; } +static inline pid_t getppid(void) +{ return 1; } +static inline pid_t getpgid(pid_t pid) +{ return pid == 0 ? getpid() : pid; } +static inline pid_t tcgetpgrp(int fd UNUSED) +{ return getpid(); } + +/* + * simple adaptors + */ + +int mingw_mkdir(const char *path, int mode); +#define mkdir mingw_mkdir + +#define WNOHANG 1 +pid_t waitpid(pid_t pid, int *status, int options); + +#define kill mingw_kill +int mingw_kill(pid_t pid, int sig); + +#define locate_in_PATH mingw_locate_in_PATH +char *mingw_locate_in_PATH(const char *cmd); + +/* + * implementations of missing functions + */ + +int pipe(int filedes[2]); +unsigned int sleep (unsigned int seconds); +int mkstemp(char *template); +int gettimeofday(struct timeval *tv, void *tz); +#ifndef __MINGW64_VERSION_MAJOR +struct tm *gmtime_r(const time_t *timep, struct tm *result); +struct tm *localtime_r(const time_t *timep, struct tm *result); +#endif +int getpagesize(void); /* defined in MinGW's libgcc.a */ +struct passwd *getpwuid(uid_t uid); +int setitimer(int type, struct itimerval *in, struct itimerval *out); +int sigaction(int sig, struct sigaction *in, struct sigaction *out); +int link(const char *oldpath, const char *newpath); +int uname(struct utsname *buf); + +/* + * replacements of existing functions + */ + +int mingw_unlink(const char *pathname, int handle_in_use_error); +#ifdef MINGW_DONT_HANDLE_IN_USE_ERROR +# define unlink(path) mingw_unlink(path, 0) +#else +# define unlink(path) mingw_unlink(path, 1) +#endif + +int mingw_rmdir(const char *path); +#define rmdir mingw_rmdir + +int mingw_open (const char *filename, int oflags, ...); +#define open mingw_open +#undef OPEN_RETURNS_EINTR + +int mingw_fgetc(FILE *stream); +#define fgetc mingw_fgetc + +FILE *mingw_fopen (const char *filename, const char *otype); +#define fopen mingw_fopen + +FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream); +#define freopen mingw_freopen + +int mingw_fflush(FILE *stream); +#define fflush mingw_fflush + +ssize_t mingw_write(int fd, const void *buf, size_t len); +#define write mingw_write + +int mingw_access(const char *filename, int mode); +#undef access +#define access mingw_access + +int mingw_chdir(const char *dirname); +#define chdir mingw_chdir + +int mingw_chmod(const char *filename, int mode); +#define chmod mingw_chmod + +char *mingw_mktemp(char *template); +#define mktemp mingw_mktemp + +char *mingw_getcwd(char *pointer, int len); +#define getcwd mingw_getcwd + +#ifdef NO_UNSETENV +#error "NO_UNSETENV is incompatible with the Windows-specific startup code!" +#endif + +/* + * We bind *env() routines (even the mingw_ ones) to private mingw_ versions. + * These talk to the CRT using UNICODE/wchar_t, but maintain the original + * narrow-char API. + * + * Note that the MSCRT maintains both ANSI (getenv()) and UNICODE (_wgetenv()) + * routines and stores both versions of each environment variable in parallel + * (and secretly updates both when you set one or the other), but it uses CP_ACP + * to do the conversion rather than CP_UTF8. + * + * Since everything in the git code base is UTF8, we define the mingw_ routines + * to access the CRT using the UNICODE routines and manually convert them to + * UTF8. This also avoids round-trip problems. + * + * This also helps with our linkage, since "_wenviron" is publicly exported + * from the CRT. But to access "_environ" we would have to statically link + * to the CRT (/MT). + * + * We require NO_SETENV (and let gitsetenv() call our mingw_putenv). + */ +#define getenv mingw_getenv +#define putenv mingw_putenv +#define unsetenv mingw_putenv +char *mingw_getenv(const char *name); +int mingw_putenv(const char *name); + +int mingw_gethostname(char *host, int namelen); +#define gethostname mingw_gethostname + +struct hostent *mingw_gethostbyname(const char *host); +#define gethostbyname mingw_gethostbyname + +int mingw_getaddrinfo(const char *node, const char *service, + const struct addrinfo *hints, struct addrinfo **res); +#define getaddrinfo mingw_getaddrinfo + +int mingw_socket(int domain, int type, int protocol); +#define socket mingw_socket + +int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz); +#define connect mingw_connect + +int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz); +#define bind mingw_bind + +int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen); +#define setsockopt mingw_setsockopt + +int mingw_shutdown(int sockfd, int how); +#define shutdown mingw_shutdown + +int mingw_listen(int sockfd, int backlog); +#define listen mingw_listen + +int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz); +#define accept mingw_accept + +int mingw_rename(const char*, const char*); +#define rename mingw_rename + +#if defined(USE_WIN32_MMAP) || defined(_MSC_VER) +int mingw_getpagesize(void); +#define getpagesize mingw_getpagesize +#endif + +int win32_fsync_no_flush(int fd); +#define fsync_no_flush win32_fsync_no_flush + +#define FSYNC_COMPONENTS_PLATFORM_DEFAULT (FSYNC_COMPONENTS_DEFAULT | FSYNC_COMPONENT_LOOSE_OBJECT) +#define FSYNC_METHOD_DEFAULT (FSYNC_METHOD_BATCH) + +struct rlimit { + unsigned int rlim_cur; +}; +#define RLIMIT_NOFILE 0 + +static inline int getrlimit(int resource, struct rlimit *rlp) +{ + if (resource != RLIMIT_NOFILE) { + errno = EINVAL; + return -1; + } + + rlp->rlim_cur = 2048; + return 0; +} + +/* + * Use mingw specific stat()/lstat()/fstat() implementations on Windows, + * including our own struct stat with 64 bit st_size and nanosecond-precision + * file times. + */ +#ifndef __MINGW64_VERSION_MAJOR +#define off_t off64_t +#define lseek _lseeki64 +#ifndef _MSC_VER +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif +#endif + +struct mingw_stat { + _dev_t st_dev; + _ino_t st_ino; + _mode_t st_mode; + short st_nlink; + short st_uid; + short st_gid; + _dev_t st_rdev; + off64_t st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +}; + +#define st_atime st_atim.tv_sec +#define st_mtime st_mtim.tv_sec +#define st_ctime st_ctim.tv_sec + +#ifdef stat +#undef stat +#endif +#define stat mingw_stat +int mingw_lstat(const char *file_name, struct stat *buf); +int mingw_stat(const char *file_name, struct stat *buf); +int mingw_fstat(int fd, struct stat *buf); +#ifdef fstat +#undef fstat +#endif +#define fstat mingw_fstat +#ifdef lstat +#undef lstat +#endif +#define lstat mingw_lstat + + +int mingw_utime(const char *file_name, const struct utimbuf *times); +#define utime mingw_utime +size_t mingw_strftime(char *s, size_t max, + const char *format, const struct tm *tm); +#define strftime mingw_strftime + +pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env, + const char *dir, + int fhin, int fhout, int fherr); +int mingw_execvp(const char *cmd, char *const *argv); +#define execvp mingw_execvp +int mingw_execv(const char *cmd, char *const *argv); +#define execv mingw_execv + +static inline unsigned int git_ntohl(unsigned int x) +{ return (unsigned int)ntohl(x); } +#define ntohl git_ntohl + +sig_handler_t mingw_signal(int sig, sig_handler_t handler); +#define signal mingw_signal + +int mingw_raise(int sig); +#define raise mingw_raise + +/* + * ANSI emulation wrappers + */ + +int winansi_isatty(int fd); +#define isatty winansi_isatty + +int winansi_dup2(int oldfd, int newfd); +#define dup2 winansi_dup2 + +void winansi_init(void); +HANDLE winansi_get_osfhandle(int fd); + +#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800) +#define PRIuMAX "I64u" +#define PRId64 "I64d" +#else +#include <inttypes.h> +#endif + +#endif /* COMPAT_MINGW_POSIX_H */ diff --git a/compat/mingw.c b/compat/mingw.c index f524c54d06..8a9972a1ca 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -21,6 +21,9 @@ #include "gettext.h" #define SECURITY_WIN32 #include <sspi.h> +#include <winternl.h> + +#define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056) #define HCAST(type, handle) ((type)(intptr_t)handle) @@ -302,7 +305,7 @@ static wchar_t *normalize_ntpath(wchar_t *wbuf) return wbuf; } -int mingw_unlink(const char *pathname) +int mingw_unlink(const char *pathname, int handle_in_use_error) { int ret, tries = 0; wchar_t wpathname[MAX_PATH]; @@ -317,6 +320,9 @@ int mingw_unlink(const char *pathname) while ((ret = _wunlink(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) { if (!is_file_in_use_error(GetLastError())) break; + if (!handle_in_use_error) + return ret; + /* * We assume that some other process had the source or * destination file open at the wrong moment and retry. @@ -621,6 +627,8 @@ int mingw_open (const char *filename, int oflags, ...) wchar_t wfilename[MAX_PATH]; open_fn_t open_fn; + DECLARE_PROC_ADDR(ntdll.dll, NTSTATUS, NTAPI, RtlGetLastNtStatus, void); + va_start(args, oflags); mode = va_arg(args, int); va_end(args); @@ -644,6 +652,21 @@ int mingw_open (const char *filename, int oflags, ...) fd = open_fn(wfilename, oflags, mode); + /* + * Internally, `_wopen()` uses the `CreateFile()` API with CREATE_NEW, + * which may error out with ERROR_ACCESS_DENIED and an NtStatus of + * STATUS_DELETE_PENDING when the file is scheduled for deletion via + * `DeleteFileW()`. The file essentially exists, so we map errno to + * EEXIST instead of EACCESS so that callers don't have to special-case + * this. + * + * This fixes issues for example with the lockfile interface when one + * process has a lock that it is about to commit or release while + * another process wants to acquire it. + */ + if (fd < 0 && create && GetLastError() == ERROR_ACCESS_DENIED && + INIT_PROC_ADDR(RtlGetLastNtStatus) && RtlGetLastNtStatus() == STATUS_DELETE_PENDING) + errno = EEXIST; if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) { DWORD attrs = GetFileAttributesW(wfilename); if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) @@ -2826,31 +2849,44 @@ static void setup_windows_environment(void) } } -static PSID get_current_user_sid(void) +static void get_current_user_sid(PSID *sid, HANDLE *linked_token) { HANDLE token; DWORD len = 0; - PSID result = NULL; + TOKEN_ELEVATION_TYPE elevationType; + DWORD size; + + *sid = NULL; + *linked_token = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) - return NULL; + return; if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) { TOKEN_USER *info = xmalloc((size_t)len); if (GetTokenInformation(token, TokenUser, info, len, &len)) { len = GetLengthSid(info->User.Sid); - result = xmalloc(len); - if (!CopySid(len, result, info->User.Sid)) { + *sid = xmalloc(len); + if (!CopySid(len, *sid, info->User.Sid)) { error(_("failed to copy SID (%ld)"), GetLastError()); - FREE_AND_NULL(result); + FREE_AND_NULL(*sid); } } FREE_AND_NULL(info); } - CloseHandle(token); - return result; + if (GetTokenInformation(token, TokenElevationType, &elevationType, sizeof(elevationType), &size) && + elevationType == TokenElevationTypeLimited) { + /* + * The current process is run by a member of the Administrators + * group, but is not running elevated. + */ + if (!GetTokenInformation(token, TokenLinkedToken, linked_token, sizeof(*linked_token), &size)) + linked_token = NULL; /* there is no linked token */ + } + + CloseHandle(token); } static BOOL user_sid_to_user_name(PSID sid, LPSTR *str) @@ -2931,18 +2967,22 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report) else if (sid && IsValidSid(sid)) { /* Now, verify that the SID matches the current user's */ static PSID current_user_sid; + static HANDLE linked_token; BOOL is_member; if (!current_user_sid) - current_user_sid = get_current_user_sid(); + get_current_user_sid(¤t_user_sid, &linked_token); if (current_user_sid && IsValidSid(current_user_sid) && EqualSid(sid, current_user_sid)) result = 1; else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) && - CheckTokenMembership(NULL, sid, &is_member) && - is_member) + ((CheckTokenMembership(NULL, sid, &is_member) && + is_member) || + (linked_token && + CheckTokenMembership(linked_token, sid, &is_member) && + is_member))) /* * If owned by the Administrators group, and the * current user is an administrator, we consider that diff --git a/compat/mingw.h b/compat/mingw.h index ebfb8ba423..444daedfa5 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -1,185 +1,10 @@ -#ifdef __MINGW64_VERSION_MAJOR -#include <stdint.h> -#include <wchar.h> -typedef _sigset_t sigset_t; -#endif -#include <winsock2.h> -#include <ws2tcpip.h> - -/* MinGW-w64 reports to have flockfile, but it does not actually have it. */ -#ifdef __MINGW64_VERSION_MAJOR -#undef _POSIX_THREAD_SAFE_FUNCTIONS -#endif +#include "mingw-posix.h" struct config_context; int mingw_core_config(const char *var, const char *value, const struct config_context *ctx, void *cb); #define platform_core_config mingw_core_config -/* - * things that are not available in header files - */ - -typedef int uid_t; -typedef int socklen_t; -#ifndef __MINGW64_VERSION_MAJOR -typedef int pid_t; -#define hstrerror strerror -#endif - -#define S_IFLNK 0120000 /* Symbolic link */ -#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK) -#define S_ISSOCK(x) 0 - -#ifndef S_IRWXG -#define S_IRGRP 0 -#define S_IWGRP 0 -#define S_IXGRP 0 -#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#endif -#ifndef S_IRWXO -#define S_IROTH 0 -#define S_IWOTH 0 -#define S_IXOTH 0 -#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#endif - -#define S_ISUID 0004000 -#define S_ISGID 0002000 -#define S_ISVTX 0001000 - -#define WIFEXITED(x) 1 -#define WIFSIGNALED(x) 0 -#define WEXITSTATUS(x) ((x) & 0xff) -#define WTERMSIG(x) SIGTERM - -#ifndef EWOULDBLOCK -#define EWOULDBLOCK EAGAIN -#endif -#ifndef ELOOP -#define ELOOP EMLINK -#endif -#define SHUT_WR SD_SEND - -#define SIGHUP 1 -#define SIGQUIT 3 -#define SIGKILL 9 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGCHLD 17 - -#define F_GETFD 1 -#define F_SETFD 2 -#define FD_CLOEXEC 0x1 - -#if !defined O_CLOEXEC && defined O_NOINHERIT -#define O_CLOEXEC O_NOINHERIT -#endif - -#ifndef EAFNOSUPPORT -#define EAFNOSUPPORT WSAEAFNOSUPPORT -#endif -#ifndef ECONNABORTED -#define ECONNABORTED WSAECONNABORTED -#endif -#ifndef ENOTSOCK -#define ENOTSOCK WSAENOTSOCK -#endif - -struct passwd { - char *pw_name; - char *pw_gecos; - char *pw_dir; -}; - -typedef void (__cdecl *sig_handler_t)(int); -struct sigaction { - sig_handler_t sa_handler; - unsigned sa_flags; -}; -#define SA_RESTART 0 - -struct itimerval { - struct timeval it_value, it_interval; -}; -#define ITIMER_REAL 0 - -struct utsname { - char sysname[16]; - char nodename[1]; - char release[16]; - char version[16]; - char machine[1]; -}; - -/* - * sanitize preprocessor namespace polluted by Windows headers defining - * macros which collide with git local versions - */ -#undef HELP_COMMAND /* from winuser.h */ - -/* - * trivial stubs - */ - -static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED) -{ errno = ENOSYS; return -1; } -static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED) -{ errno = ENOSYS; return -1; } -static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED) -{ errno = ENOSYS; return -1; } -#ifndef __MINGW64_VERSION_MAJOR -static inline pid_t fork(void) -{ errno = ENOSYS; return -1; } -#endif -static inline unsigned int alarm(unsigned int seconds UNUSED) -{ return 0; } -static inline int fsync(int fd) -{ return _commit(fd); } -static inline void sync(void) -{} -static inline uid_t getuid(void) -{ return 1; } -static inline struct passwd *getpwnam(const char *name UNUSED) -{ return NULL; } -static inline int fcntl(int fd UNUSED, int cmd, ...) -{ - if (cmd == F_GETFD || cmd == F_SETFD) - return 0; - errno = EINVAL; - return -1; -} - -#define sigemptyset(x) (void)0 -static inline int sigaddset(sigset_t *set UNUSED, int signum UNUSED) -{ return 0; } -#define SIG_BLOCK 0 -#define SIG_UNBLOCK 0 -static inline int sigprocmask(int how UNUSED, const sigset_t *set UNUSED, sigset_t *oldset UNUSED) -{ return 0; } -static inline pid_t getppid(void) -{ return 1; } -static inline pid_t getpgid(pid_t pid) -{ return pid == 0 ? getpid() : pid; } -static inline pid_t tcgetpgrp(int fd UNUSED) -{ return getpid(); } - -/* - * simple adaptors - */ - -int mingw_mkdir(const char *path, int mode); -#define mkdir mingw_mkdir - -#define WNOHANG 1 -pid_t waitpid(pid_t pid, int *status, int options); - -#define kill mingw_kill -int mingw_kill(pid_t pid, int sig); - -#define locate_in_PATH mingw_locate_in_PATH -char *mingw_locate_in_PATH(const char *cmd); - #ifndef NO_OPENSSL #include <openssl/ssl.h> static inline int mingw_SSL_set_fd(SSL *ssl, int fd) @@ -202,249 +27,6 @@ static inline int mingw_SSL_set_wfd(SSL *ssl, int fd) #endif /* - * implementations of missing functions - */ - -int pipe(int filedes[2]); -unsigned int sleep (unsigned int seconds); -int mkstemp(char *template); -int gettimeofday(struct timeval *tv, void *tz); -#ifndef __MINGW64_VERSION_MAJOR -struct tm *gmtime_r(const time_t *timep, struct tm *result); -struct tm *localtime_r(const time_t *timep, struct tm *result); -#endif -int getpagesize(void); /* defined in MinGW's libgcc.a */ -struct passwd *getpwuid(uid_t uid); -int setitimer(int type, struct itimerval *in, struct itimerval *out); -int sigaction(int sig, struct sigaction *in, struct sigaction *out); -int link(const char *oldpath, const char *newpath); -int uname(struct utsname *buf); - -/* - * replacements of existing functions - */ - -int mingw_unlink(const char *pathname); -#define unlink mingw_unlink - -int mingw_rmdir(const char *path); -#define rmdir mingw_rmdir - -int mingw_open (const char *filename, int oflags, ...); -#define open mingw_open -#undef OPEN_RETURNS_EINTR - -int mingw_fgetc(FILE *stream); -#define fgetc mingw_fgetc - -FILE *mingw_fopen (const char *filename, const char *otype); -#define fopen mingw_fopen - -FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream); -#define freopen mingw_freopen - -int mingw_fflush(FILE *stream); -#define fflush mingw_fflush - -ssize_t mingw_write(int fd, const void *buf, size_t len); -#define write mingw_write - -int mingw_access(const char *filename, int mode); -#undef access -#define access mingw_access - -int mingw_chdir(const char *dirname); -#define chdir mingw_chdir - -int mingw_chmod(const char *filename, int mode); -#define chmod mingw_chmod - -char *mingw_mktemp(char *template); -#define mktemp mingw_mktemp - -char *mingw_getcwd(char *pointer, int len); -#define getcwd mingw_getcwd - -#ifdef NO_UNSETENV -#error "NO_UNSETENV is incompatible with the Windows-specific startup code!" -#endif - -/* - * We bind *env() routines (even the mingw_ ones) to private mingw_ versions. - * These talk to the CRT using UNICODE/wchar_t, but maintain the original - * narrow-char API. - * - * Note that the MSCRT maintains both ANSI (getenv()) and UNICODE (_wgetenv()) - * routines and stores both versions of each environment variable in parallel - * (and secretly updates both when you set one or the other), but it uses CP_ACP - * to do the conversion rather than CP_UTF8. - * - * Since everything in the git code base is UTF8, we define the mingw_ routines - * to access the CRT using the UNICODE routines and manually convert them to - * UTF8. This also avoids round-trip problems. - * - * This also helps with our linkage, since "_wenviron" is publicly exported - * from the CRT. But to access "_environ" we would have to statically link - * to the CRT (/MT). - * - * We require NO_SETENV (and let gitsetenv() call our mingw_putenv). - */ -#define getenv mingw_getenv -#define putenv mingw_putenv -#define unsetenv mingw_putenv -char *mingw_getenv(const char *name); -int mingw_putenv(const char *name); - -int mingw_gethostname(char *host, int namelen); -#define gethostname mingw_gethostname - -struct hostent *mingw_gethostbyname(const char *host); -#define gethostbyname mingw_gethostbyname - -int mingw_getaddrinfo(const char *node, const char *service, - const struct addrinfo *hints, struct addrinfo **res); -#define getaddrinfo mingw_getaddrinfo - -int mingw_socket(int domain, int type, int protocol); -#define socket mingw_socket - -int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz); -#define connect mingw_connect - -int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz); -#define bind mingw_bind - -int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen); -#define setsockopt mingw_setsockopt - -int mingw_shutdown(int sockfd, int how); -#define shutdown mingw_shutdown - -int mingw_listen(int sockfd, int backlog); -#define listen mingw_listen - -int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz); -#define accept mingw_accept - -int mingw_rename(const char*, const char*); -#define rename mingw_rename - -#if defined(USE_WIN32_MMAP) || defined(_MSC_VER) -int mingw_getpagesize(void); -#define getpagesize mingw_getpagesize -#endif - -int win32_fsync_no_flush(int fd); -#define fsync_no_flush win32_fsync_no_flush - -#define FSYNC_COMPONENTS_PLATFORM_DEFAULT (FSYNC_COMPONENTS_DEFAULT | FSYNC_COMPONENT_LOOSE_OBJECT) -#define FSYNC_METHOD_DEFAULT (FSYNC_METHOD_BATCH) - -struct rlimit { - unsigned int rlim_cur; -}; -#define RLIMIT_NOFILE 0 - -static inline int getrlimit(int resource, struct rlimit *rlp) -{ - if (resource != RLIMIT_NOFILE) { - errno = EINVAL; - return -1; - } - - rlp->rlim_cur = 2048; - return 0; -} - -/* - * Use mingw specific stat()/lstat()/fstat() implementations on Windows, - * including our own struct stat with 64 bit st_size and nanosecond-precision - * file times. - */ -#ifndef __MINGW64_VERSION_MAJOR -#define off_t off64_t -#define lseek _lseeki64 -#ifndef _MSC_VER -struct timespec { - time_t tv_sec; - long tv_nsec; -}; -#endif -#endif - -struct mingw_stat { - _dev_t st_dev; - _ino_t st_ino; - _mode_t st_mode; - short st_nlink; - short st_uid; - short st_gid; - _dev_t st_rdev; - off64_t st_size; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; -}; - -#define st_atime st_atim.tv_sec -#define st_mtime st_mtim.tv_sec -#define st_ctime st_ctim.tv_sec - -#ifdef stat -#undef stat -#endif -#define stat mingw_stat -int mingw_lstat(const char *file_name, struct stat *buf); -int mingw_stat(const char *file_name, struct stat *buf); -int mingw_fstat(int fd, struct stat *buf); -#ifdef fstat -#undef fstat -#endif -#define fstat mingw_fstat -#ifdef lstat -#undef lstat -#endif -#define lstat mingw_lstat - - -int mingw_utime(const char *file_name, const struct utimbuf *times); -#define utime mingw_utime -size_t mingw_strftime(char *s, size_t max, - const char *format, const struct tm *tm); -#define strftime mingw_strftime - -pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env, - const char *dir, - int fhin, int fhout, int fherr); -int mingw_execvp(const char *cmd, char *const *argv); -#define execvp mingw_execvp -int mingw_execv(const char *cmd, char *const *argv); -#define execv mingw_execv - -static inline unsigned int git_ntohl(unsigned int x) -{ return (unsigned int)ntohl(x); } -#define ntohl git_ntohl - -sig_handler_t mingw_signal(int sig, sig_handler_t handler); -#define signal mingw_signal - -int mingw_raise(int sig); -#define raise mingw_raise - -/* - * ANSI emulation wrappers - */ - -int winansi_isatty(int fd); -#define isatty winansi_isatty - -int winansi_dup2(int oldfd, int newfd); -#define dup2 winansi_dup2 - -void winansi_init(void); -HANDLE winansi_get_osfhandle(int fd); - -/* * git specific compatibility */ @@ -457,12 +39,6 @@ static inline void convert_slashes(char *path) #define PATH_SEP ';' char *mingw_query_user_email(void); #define query_user_email mingw_query_user_email -#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800) -#define PRIuMAX "I64u" -#define PRId64 "I64d" -#else -#include <inttypes.h> -#endif /** * Verifies that the specified path is owned by the user running the diff --git a/compat/msvc-posix.h b/compat/msvc-posix.h new file mode 100644 index 0000000000..c500b8b4aa --- /dev/null +++ b/compat/msvc-posix.h @@ -0,0 +1,33 @@ +#ifndef COMPAT_MSVC_POSIX_H +#define COMPAT_MSVC_POSIX_H + +#include <direct.h> +#include <process.h> +#include <malloc.h> +#include <io.h> + +#pragma warning(disable: 4018) /* signed/unsigned comparison */ +#pragma warning(disable: 4244) /* type conversion, possible loss of data */ +#pragma warning(disable: 4090) /* 'function' : different 'const' qualifiers (ALLOC_GROW etc.)*/ + +/* porting function */ +#define inline __inline +#define __inline__ __inline +#define __attribute__(x) +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define ftruncate _chsize +#define strtoull _strtoui64 +#define strtoll _strtoi64 + +#undef ERROR + +#define ftello _ftelli64 + +typedef int sigset_t; +/* open for reading, writing, or both (not in fcntl.h) */ +#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR) + +#include "mingw-posix.h" + +#endif /* COMPAT_MSVC_POSIX_H */ diff --git a/compat/msvc.h b/compat/msvc.h index 1d7a8c6145..2b87c0a7c7 100644 --- a/compat/msvc.h +++ b/compat/msvc.h @@ -1,33 +1,7 @@ #ifndef __MSVC__HEAD #define __MSVC__HEAD -#include <direct.h> -#include <process.h> -#include <malloc.h> -#include <io.h> - -#pragma warning(disable: 4018) /* signed/unsigned comparison */ -#pragma warning(disable: 4244) /* type conversion, possible loss of data */ -#pragma warning(disable: 4090) /* 'function' : different 'const' qualifiers (ALLOC_GROW etc.)*/ - -/* porting function */ -#define inline __inline -#define __inline__ __inline -#define __attribute__(x) -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#define ftruncate _chsize -#define strtoull _strtoui64 -#define strtoll _strtoi64 - -#undef ERROR - -#define ftello _ftelli64 - -typedef int sigset_t; -/* open for reading, writing, or both (not in fcntl.h) */ -#define O_ACCMODE (_O_RDONLY | _O_WRONLY | _O_RDWR) - -#include "compat/mingw.h" +#include "msvc-posix.h" +#include "mingw.h" #endif diff --git a/compat/open.c b/compat/open.c index eb3754a23b..37ae2b1aeb 100644 --- a/compat/open.c +++ b/compat/open.c @@ -1,5 +1,6 @@ #include "git-compat-util.h" +#ifdef OPEN_RETURNS_EINTR #undef open int git_open_with_retry(const char *path, int flags, ...) { @@ -23,3 +24,31 @@ int git_open_with_retry(const char *path, int flags, ...) return ret; } +#endif + +int git_open_cloexec(const char *name, int flags) +{ + int fd; + static int o_cloexec = O_CLOEXEC; + + fd = open(name, flags | o_cloexec); + if ((o_cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) { + /* Try again w/o O_CLOEXEC: the kernel might not support it */ + o_cloexec &= ~O_CLOEXEC; + fd = open(name, flags | o_cloexec); + } + +#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) + { + static int fd_cloexec = FD_CLOEXEC; + + if (!o_cloexec && 0 <= fd && fd_cloexec) { + /* Opened w/o O_CLOEXEC? try with fcntl(2) to add it */ + int flags = fcntl(fd, F_GETFD); + if (fcntl(fd, F_SETFD, flags | fd_cloexec)) + fd_cloexec = 0; + } + } +#endif + return fd; +} diff --git a/compat/posix.h b/compat/posix.h new file mode 100644 index 0000000000..067a00f33b --- /dev/null +++ b/compat/posix.h @@ -0,0 +1,541 @@ +#ifndef COMPAT_POSIX_H +#define COMPAT_POSIX_H + +#define _FILE_OFFSET_BITS 64 + +/* + * Derived from Linux "Features Test Macro" header + * Convenience macros to test the versions of gcc (or + * a compatible compiler). + * Use them like this: + * #if GIT_GNUC_PREREQ (2,8) + * ... code requiring gcc 2.8 or later ... + * #endif + * + * This macro of course is not part of POSIX, but we need it for the UNUSED + * macro which is used by some of our POSIX compatibility wrappers. +*/ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define GIT_GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else + #define GIT_GNUC_PREREQ(maj, min) 0 +#endif + +/* + * UNUSED marks a function parameter that is always unused. It also + * can be used to annotate a function, a variable, or a type that is + * always unused. + * + * A callback interface may dictate that a function accepts a + * parameter at that position, but the implementation of the function + * may not need to use the parameter. In such a case, mark the parameter + * with UNUSED. + * + * When a parameter may be used or unused, depending on conditional + * compilation, consider using MAYBE_UNUSED instead. + */ +#if GIT_GNUC_PREREQ(4, 5) +#define UNUSED __attribute__((unused)) \ + __attribute__((deprecated ("parameter declared as UNUSED"))) +#elif defined(__GNUC__) +#define UNUSED __attribute__((unused)) \ + __attribute__((deprecated)) +#else +#define UNUSED +#endif + +#ifdef __MINGW64__ +#define _POSIX_C_SOURCE 1 +#elif defined(__sun__) + /* + * On Solaris, when _XOPEN_EXTENDED is set, its header file + * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE + * setting to say we are XPG5 or XPG6. Also on Solaris, + * XPG6 programs must be compiled with a c99 compiler, while + * non XPG6 programs must be compiled with a pre-c99 compiler. + */ +# if __STDC_VERSION__ - 0 >= 199901L +# define _XOPEN_SOURCE 600 +# else +# define _XOPEN_SOURCE 500 +# endif +#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ + !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__MirBSD__) && \ + !defined(__USLC__) && !defined(_M_UNIX) && !defined(__sgi) && \ + !defined(__TANDEM) && !defined(__QNX__) && !defined(__CYGWIN__) +#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500 */ +#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */ +#endif +#define _ALL_SOURCE 1 +#define _GNU_SOURCE 1 +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 +#define _NETBSD_SOURCE 1 +#define _SGI_SOURCE 1 + +#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */ +# if !defined(_WIN32_WINNT) +# define _WIN32_WINNT 0x0600 +# endif +#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */ +#include <winsock2.h> +#ifndef NO_UNIX_SOCKETS +#include <afunix.h> +#endif +#include <windows.h> +#define GIT_WINDOWS_NATIVE +#endif + +#include <unistd.h> +#include <stdio.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdbool.h> +#include <string.h> +#ifdef HAVE_STRINGS_H +#include <strings.h> /* for strcasecmp() */ +#endif +#include <errno.h> +#include <limits.h> +#include <locale.h> +#ifdef NEEDS_SYS_PARAM_H +#include <sys/param.h> +#endif +#include <sys/types.h> +#include <dirent.h> +#include <sys/time.h> +#include <time.h> +#include <signal.h> +#include <assert.h> +#include <regex.h> +#include <utime.h> +#include <syslog.h> +#if !defined(NO_POLL_H) +#include <poll.h> +#elif !defined(NO_SYS_POLL_H) +#include <sys/poll.h> +#else +/* Pull the compat stuff */ +#include <poll.h> +#endif +#ifdef HAVE_BSD_SYSCTL +#include <sys/sysctl.h> +#endif + +#if defined(__MINGW32__) +#include "mingw-posix.h" +#elif defined(_MSC_VER) +#include "msvc-posix.h" +#else +#include <sys/utsname.h> +#include <sys/wait.h> +#include <sys/resource.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/statvfs.h> +#include <termios.h> +#ifndef NO_SYS_SELECT_H +#include <sys/select.h> +#endif +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <pwd.h> +#include <sys/un.h> +#ifndef NO_INTTYPES_H +#include <inttypes.h> +#else +#include <stdint.h> +#endif +#ifdef HAVE_ARC4RANDOM_LIBBSD +#include <bsd/stdlib.h> +#endif +#ifdef HAVE_GETRANDOM +#include <sys/random.h> +#endif +#ifdef NO_INTPTR_T +/* + * On I16LP32, ILP32 and LP64 "long" is the safe bet, however + * on LLP86, IL33LLP64 and P64 it needs to be "long long", + * while on IP16 and IP16L32 it is "int" (resp. "short") + * Size needs to match (or exceed) 'sizeof(void *)'. + * We can't take "long long" here as not everybody has it. + */ +typedef long intptr_t; +typedef unsigned long uintptr_t; +#endif +#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */ +#include <grp.h> +#define _ALL_SOURCE 1 +#endif + +#ifdef MKDIR_WO_TRAILING_SLASH +#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b)) +int compat_mkdir_wo_trailing_slash(const char*, mode_t); +#endif + +#ifdef time +#undef time +#endif +static inline time_t git_time(time_t *tloc) +{ + struct timeval tv; + + /* + * Avoid time(NULL), which can disagree with gettimeofday(2) + * and filesystem timestamps. + */ + gettimeofday(&tv, NULL); + + if (tloc) + *tloc = tv.tv_sec; + return tv.tv_sec; +} +#define time git_time + +#ifdef NO_STRUCT_ITIMERVAL +struct itimerval { + struct timeval it_interval; + struct timeval it_value; +}; +#endif + +#ifdef NO_SETITIMER +static inline int git_setitimer(int which UNUSED, + const struct itimerval *value UNUSED, + struct itimerval *newvalue UNUSED) { + return 0; /* pretend success */ +} +#undef setitimer +#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue) +#endif + +#ifndef NO_LIBGEN_H +#include <libgen.h> +#else +#define basename gitbasename +char *gitbasename(char *); +#define dirname gitdirname +char *gitdirname(char *); +#endif + +#ifndef NO_ICONV +#include <iconv.h> +#endif + +/* On most systems <netdb.h> would have given us this, but + * not on some systems (e.g. z/OS). + */ +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + +/* On most systems <limits.h> would have given us this, but + * not on some systems (e.g. GNU/Hurd). + */ +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + +typedef uintmax_t timestamp_t; +#define PRItime PRIuMAX +#define parse_timestamp strtoumax +#define TIME_MAX UINTMAX_MAX +#define TIME_MIN 0 + +int lstat_cache_aware_rmdir(const char *path); +#if !defined(__MINGW32__) && !defined(_MSC_VER) +#define rmdir lstat_cache_aware_rmdir +#endif + +#if defined(NO_MMAP) || defined(USE_WIN32_MMAP) + +#ifndef PROT_READ +#define PROT_READ 1 +#define PROT_WRITE 2 +#define MAP_PRIVATE 1 +#endif + +#define mmap git_mmap +#define munmap git_munmap +void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); +int git_munmap(void *start, size_t length); + +#else /* NO_MMAP || USE_WIN32_MMAP */ + +#include <sys/mman.h> + +#endif /* NO_MMAP || USE_WIN32_MMAP */ + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#ifdef NEEDS_MODE_TRANSLATION +#undef S_IFMT +#undef S_IFREG +#undef S_IFDIR +#undef S_IFLNK +#undef S_IFBLK +#undef S_IFCHR +#undef S_IFIFO +#undef S_IFSOCK +#define S_IFMT 0170000 +#define S_IFREG 0100000 +#define S_IFDIR 0040000 +#define S_IFLNK 0120000 +#define S_IFBLK 0060000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 +#define S_IFSOCK 0140000 +#ifdef stat +#undef stat +#endif +#define stat(path, buf) git_stat(path, buf) +int git_stat(const char *, struct stat *); +#ifdef fstat +#undef fstat +#endif +#define fstat(fd, buf) git_fstat(fd, buf) +int git_fstat(int, struct stat *); +#ifdef lstat +#undef lstat +#endif +#define lstat(path, buf) git_lstat(path, buf) +int git_lstat(const char *, struct stat *); +#endif + +#ifdef NO_PREAD +#define pread git_pread +ssize_t git_pread(int fd, void *buf, size_t count, off_t offset); +#endif + +#ifdef NO_SETENV +#define setenv gitsetenv +int gitsetenv(const char *, const char *, int); +#endif + +#ifdef NO_MKDTEMP +#define mkdtemp gitmkdtemp +char *gitmkdtemp(char *); +#endif + +#ifdef NO_UNSETENV +#define unsetenv gitunsetenv +int gitunsetenv(const char *); +#endif + +#ifdef NO_STRCASESTR +#define strcasestr gitstrcasestr +char *gitstrcasestr(const char *haystack, const char *needle); +#endif + +#ifdef NO_STRLCPY +#define strlcpy gitstrlcpy +size_t gitstrlcpy(char *, const char *, size_t); +#endif + +#ifdef NO_STRTOUMAX +#define strtoumax gitstrtoumax +uintmax_t gitstrtoumax(const char *, char **, int); +#define strtoimax gitstrtoimax +intmax_t gitstrtoimax(const char *, char **, int); +#endif + +#ifdef NO_HSTRERROR +#define hstrerror githstrerror +const char *githstrerror(int herror); +#endif + +#ifdef NO_MEMMEM +#define memmem gitmemmem +void *gitmemmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); +#endif + +#ifdef OVERRIDE_STRDUP +#ifdef strdup +#undef strdup +#endif +#define strdup gitstrdup +char *gitstrdup(const char *s); +#endif + +#ifdef NO_GETPAGESIZE +#define getpagesize() sysconf(_SC_PAGESIZE) +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#ifdef FREAD_READS_DIRECTORIES +# if !defined(SUPPRESS_FOPEN_REDEFINITION) +# ifdef fopen +# undef fopen +# endif +# define fopen(a,b) git_fopen(a,b) +# endif +FILE *git_fopen(const char*, const char*); +#endif + +#ifdef SNPRINTF_RETURNS_BOGUS +#ifdef snprintf +#undef snprintf +#endif +#define snprintf git_snprintf +int git_snprintf(char *str, size_t maxsize, + const char *format, ...); +#ifdef vsnprintf +#undef vsnprintf +#endif +#define vsnprintf git_vsnprintf +int git_vsnprintf(char *str, size_t maxsize, + const char *format, va_list ap); +#endif + +#ifdef OPEN_RETURNS_EINTR +#undef open +#define open git_open_with_retry +int git_open_with_retry(const char *path, int flag, ...); +#endif + +#ifdef __GLIBC_PREREQ +#if __GLIBC_PREREQ(2, 1) +#define HAVE_STRCHRNUL +#endif +#endif + +#ifndef HAVE_STRCHRNUL +#define strchrnul gitstrchrnul +static inline char *gitstrchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; + return (char *)s; +} +#endif + +#ifdef NO_INET_PTON +int inet_pton(int af, const char *src, void *dst); +#endif + +#ifdef NO_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif + +#ifdef NO_PTHREADS +#define atexit git_atexit +int git_atexit(void (*handler)(void)); +#endif + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 256 +#endif + +#include "../sane-ctype.h" + +void git_stable_qsort(void *base, size_t nmemb, size_t size, + int(*compar)(const void *, const void *)); +#ifdef INTERNAL_QSORT +#define qsort git_stable_qsort +#endif + +#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar) +static inline void sane_qsort(void *base, size_t nmemb, size_t size, + int(*compar)(const void *, const void *)) +{ + if (nmemb > 1) + qsort(base, nmemb, size, compar); +} + +#define STABLE_QSORT(base, n, compar) \ + git_stable_qsort((base), (n), sizeof(*(base)), compar) + +#ifndef HAVE_ISO_QSORT_S +int git_qsort_s(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *, void *), void *ctx); +#define qsort_s git_qsort_s +#endif + +#define QSORT_S(base, n, compar, ctx) do { \ + if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \ + BUG("qsort_s() failed"); \ +} while (0) + +#ifdef NO_NSEC +#undef USE_NSEC +#define ST_CTIME_NSEC(st) 0 +#define ST_MTIME_NSEC(st) 0 +#else +#ifdef USE_ST_TIMESPEC +#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec)) +#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec)) +#else +#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec)) +#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec)) +#endif +#endif + +#ifndef va_copy +/* + * Since an obvious implementation of va_list would be to make it a + * pointer into the stack frame, a simple assignment will work on + * many systems. But let's try to be more portable. + */ +#ifdef __va_copy +#define va_copy(dst, src) __va_copy(dst, src) +#else +#define va_copy(dst, src) ((dst) = (src)) +#endif +#endif + +#ifndef _POSIX_THREAD_SAFE_FUNCTIONS +static inline void git_flockfile(FILE *fh UNUSED) +{ + ; /* nothing */ +} +static inline void git_funlockfile(FILE *fh UNUSED) +{ + ; /* nothing */ +} +#undef flockfile +#undef funlockfile +#undef getc_unlocked +#define flockfile(fh) git_flockfile(fh) +#define funlockfile(fh) git_funlockfile(fh) +#define getc_unlocked(fh) getc(fh) +#endif + +#ifdef FILENO_IS_A_MACRO +int git_fileno(FILE *stream); +# ifndef COMPAT_CODE_FILENO +# undef fileno +# define fileno(p) git_fileno(p) +# endif +#endif + +#ifdef NEED_ACCESS_ROOT_HANDLER +int git_access(const char *path, int mode); +# ifndef COMPAT_CODE_ACCESS +# ifdef access +# undef access +# endif +# define access(path, mode) git_access(path, mode) +# endif +#endif + +#endif /* COMPAT_POSIX_H */ diff --git a/compat/regex/regex_internal.c b/compat/regex/regex_internal.c index ec5cc5d2dd..4a4f849629 100644 --- a/compat/regex/regex_internal.c +++ b/compat/regex/regex_internal.c @@ -1232,7 +1232,10 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src) is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) { if (dest->elems[id] == src->elems[is]) - is--, id--; + { + is--; + id--; + } else if (dest->elems[id] < src->elems[is]) dest->elems[--sbase] = src->elems[is--]; else /* if (dest->elems[id] > src->elems[is]) */ diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c index 2eeec82f40..c08f1bbe1f 100644 --- a/compat/regex/regexec.c +++ b/compat/regex/regexec.c @@ -2210,7 +2210,7 @@ sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, /* mctx->bkref_ents may have changed, reload the pointer. */ entry = mctx->bkref_ents + enabled_idx; } - while (enabled_idx++, entry++->more); + while ((void)enabled_idx++, entry++->more); } err = REG_NOERROR; free_return: diff --git a/compat/zlib-compat.h b/compat/zlib-compat.h index 0c60e3af33..ac08276622 100644 --- a/compat/zlib-compat.h +++ b/compat/zlib-compat.h @@ -4,8 +4,8 @@ #ifdef HAVE_ZLIB_NG # include <zlib-ng.h> -# define z_stream zng_stream -#define gz_header_s zng_gz_header_s +# define z_stream_s zng_stream_s +# define gz_header_s zng_gz_header_s # define crc32(crc, buf, len) zng_crc32(crc, buf, len) diff --git a/compiler-tricks/not-constant.c b/compiler-tricks/not-constant.c new file mode 100644 index 0000000000..9fb4f275b1 --- /dev/null +++ b/compiler-tricks/not-constant.c @@ -0,0 +1,2 @@ +#include <git-compat-util.h> +int false_but_the_compiler_does_not_know_it_ = 0; @@ -31,7 +31,7 @@ #include "hashmap.h" #include "string-list.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "pager.h" #include "path.h" #include "utf8.h" @@ -1490,11 +1490,6 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - if (!strcmp(var, "core.bigfilethreshold")) { - big_file_threshold = git_config_ulong(var, value, ctx->kvi); - return 0; - } - if (!strcmp(var, "core.autocrlf")) { if (value && !strcasecmp(value, "input")) { auto_crlf = AUTO_CRLF_INPUT; @@ -1600,11 +1595,6 @@ static int git_default_core_config(const char *var, const char *value, return 0; } - if (!strcmp(var, "core.preloadindex")) { - core_preload_index = git_config_bool(var, value); - return 0; - } - if (!strcmp(var, "core.createobject")) { if (!value) return config_error_nonbool(var); @@ -2521,6 +2511,10 @@ void repo_config_clear(struct repository *repo) void repo_config(struct repository *repo, config_fn_t fn, void *data) { + if (!repo) { + read_very_early_config(fn, data); + return; + } git_config_check_init(repo); configset_iter(repo->config, fn, data); } @@ -219,6 +219,15 @@ void read_very_early_config(config_fn_t cb, void *data); * repo-specific one; by overwriting, the higher-priority repo-specific * value is left at the end). * + * In cases where the repository variable is NULL, repo_config() will + * skip the per-repository config but retain system and global configs + * by calling read_very_early_config() which also ignores one-time + * overrides like "git -c var=val". This is to support handling "git foo -h" + * (which lets git.c:run_builtin() to pass NULL and have the cmd_foo() + * call repo_config() before calling parse_options() to notice "-h", give + * help and exit) for a command that ordinarily require a repository + * so this limitation may be OK (but if needed you are welcome to fix it). + * * Unlike git_config_from_file(), this function respects includes. */ void repo_config(struct repository *r, config_fn_t fn, void *); diff --git a/config.mak.dev b/config.mak.dev index 0fd8cc4d35..e86b6e1b34 100644 --- a/config.mak.dev +++ b/config.mak.dev @@ -39,6 +39,11 @@ DEVELOPER_CFLAGS += -Wunused DEVELOPER_CFLAGS += -Wvla DEVELOPER_CFLAGS += -Wwrite-strings DEVELOPER_CFLAGS += -fno-common +DEVELOPER_CFLAGS += -Wunreachable-code + +ifneq ($(filter clang9,$(COMPILER_FEATURES)),) +DEVELOPER_CFLAGS += -Wcomma +endif ifneq ($(filter clang4,$(COMPILER_FEATURES)),) DEVELOPER_CFLAGS += -Wtautological-constant-out-of-range-compare diff --git a/config.mak.uname b/config.mak.uname index b12d4e168a..b1c5c4d5e8 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -48,18 +48,18 @@ ifeq ($(uname_S),OSF1) endif ifeq ($(uname_S),Linux) HAVE_ALLOCA_H = YesPlease + # override in config.mak if you have glibc >= 2.38 NO_STRLCPY = YesPlease + CSPRNG_METHOD = getrandom HAVE_PATHS_H = YesPlease LIBC_CONTAINS_LIBINTL = YesPlease HAVE_DEV_TTY = YesPlease HAVE_CLOCK_GETTIME = YesPlease HAVE_CLOCK_MONOTONIC = YesPlease - # -lrt is needed for clock_gettime on glibc <= 2.16 - NEEDS_LIBRT = YesPlease HAVE_SYNC_FILE_RANGE = YesPlease HAVE_GETDELIM = YesPlease FREAD_READS_DIRECTORIES = UnfortunatelyYes - BASIC_CFLAGS += -DHAVE_SYSINFO + HAVE_SYSINFO = YesPlease PROCFS_EXECUTABLE_PATH = /proc/self/exe HAVE_PLATFORM_PROCINFO = YesPlease COMPAT_OBJS += compat/linux/procinfo.o @@ -190,9 +190,6 @@ ifeq ($(uname_S),SunOS) SHELL_PATH = /bin/bash SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin HAVE_ALLOCA_H = YesPlease - NO_STRCASESTR = YesPlease - NO_MEMMEM = YesPlease - NO_MKDTEMP = YesPlease NO_REGEX = YesPlease NO_MSGFMT_EXTENDED_OPTIONS = YesPlease HAVE_DEV_TTY = YesPlease @@ -202,7 +199,10 @@ ifeq ($(uname_S),SunOS) NO_IPV6 = YesPlease NO_SOCKADDR_STORAGE = YesPlease NO_UNSETENV = YesPlease + NO_MKDTEMP = YesPlease + NO_MEMMEM = YesPlease NO_SETENV = YesPlease + NO_STRCASESTR = YesPlease NO_STRLCPY = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp @@ -212,23 +212,45 @@ ifeq ($(uname_S),SunOS) NO_IPV6 = YesPlease NO_SOCKADDR_STORAGE = YesPlease NO_UNSETENV = YesPlease + NO_MKDTEMP = YesPlease + NO_MEMMEM = YesPlease NO_SETENV = YesPlease + NO_STRCASESTR = YesPlease NO_STRLCPY = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp endif ifeq ($(uname_R),5.8) NO_UNSETENV = YesPlease + NO_MKDTEMP = YesPlease + NO_MEMMEM = YesPlease NO_SETENV = YesPlease + NO_STRCASESTR = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp endif ifeq ($(uname_R),5.9) NO_UNSETENV = YesPlease + NO_MKDTEMP = YesPlease + NO_MEMMEM = YesPlease NO_SETENV = YesPlease + NO_STRCASESTR = YesPlease NO_STRTOUMAX = YesPlease GIT_TEST_CMP = cmp endif + ifeq ($(uname_R),5.10) + NO_UNSETENV = YesPlease + NO_MKDTEMP = YesPlease + NO_MEMMEM = YesPlease + NO_SETENV = YesPlease + NO_STRCASESTR = YesPlease + GIT_TEST_CMP = cmp + endif + ifeq ($(uname_R),5.11) + NO_UNSETENV = YesPlease + NO_SETENV = YesPlease + GIT_TEST_CMP = cmp + endif INSTALL = /usr/ucb/install TAR = gtar BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ @@ -246,9 +268,16 @@ ifeq ($(uname_O),Cygwin) # Try commenting this out if you suspect MMAP is more efficient NO_MMAP = YesPlease else - NO_REGEX = UnfortunatelyYes + ifeq ($(shell expr "$(uname_R)" : '1\.7\.'),4) + NO_REGEX = UnfortunatelyYes + endif endif HAVE_DEV_TTY = YesPlease + HAVE_GETDELIM = YesPlease + HAVE_CLOCK_GETTIME = YesPlease + HAVE_CLOCK_MONOTONIC = YesPlease + HAVE_SYSINFO = YesPlease + CSPRNG_METHOD = arc4random HAVE_ALLOCA_H = YesPlease NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes @@ -294,17 +323,14 @@ ifeq ($(uname_S),FreeBSD) FILENO_IS_A_MACRO = UnfortunatelyYes endif ifeq ($(uname_S),OpenBSD) - NO_STRCASESTR = YesPlease - NO_MEMMEM = YesPlease + DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease USE_ST_TIMESPEC = YesPlease NEEDS_LIBICONV = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib HAVE_PATHS_H = YesPlease HAVE_BSD_SYSCTL = YesPlease - HAVE_BSD_KERN_PROC_SYSCTL = YesPlease CSPRNG_METHOD = arc4random - PROCFS_EXECUTABLE_PATH = /proc/curproc/file FREAD_READS_DIRECTORIES = UnfortunatelyYes FILENO_IS_A_MACRO = UnfortunatelyYes endif @@ -432,7 +458,11 @@ ifeq ($(uname_S),Windows) ifeq (MINGW32,$(MSYSTEM)) prefix = /mingw32 else - prefix = /mingw64 + ifeq (CLANGARM64,$(MSYSTEM)) + prefix = /clangarm64 + else + prefix = /mingw64 + endif endif # Prepend MSVC 64-bit tool-chain to PATH. # @@ -485,7 +515,7 @@ ifeq ($(uname_S),Windows) NO_POSIX_GOODIES = UnfortunatelyYes NATIVE_CRLF = YesPlease DEFAULT_HELP_FORMAT = html -ifeq (/mingw64,$(subst 32,64,$(prefix))) +ifeq (/mingw64,$(subst 32,64,$(subst clangarm,mingw,$(prefix)))) # Move system config into top-level /etc/ ETC_GITCONFIG = ../etc/gitconfig ETC_GITATTRIBUTES = ../etc/gitattributes @@ -724,6 +754,10 @@ ifeq ($(uname_S),MINGW) prefix = /mingw64 HOST_CPU = x86_64 BASIC_LDFLAGS += -Wl,--pic-executable,-e,mainCRTStartup + else ifeq (CLANGARM64,$(MSYSTEM)) + prefix = /clangarm64 + HOST_CPU = aarch64 + BASIC_LDFLAGS += -Wl,--pic-executable,-e,mainCRTStartup else COMPAT_CFLAGS += -D_USE_32BIT_TIME_T BASIC_LDFLAGS += -Wl,--large-address-aware @@ -738,8 +772,10 @@ ifeq ($(uname_S),MINGW) HAVE_LIBCHARSET_H = YesPlease USE_GETTEXT_SCHEME = fallthrough USE_LIBPCRE = YesPlease - USE_NED_ALLOCATOR = YesPlease - ifeq (/mingw64,$(subst 32,64,$(prefix))) + ifneq (CLANGARM64,$(MSYSTEM)) + USE_NED_ALLOCATOR = YesPlease + endif + ifeq (/mingw64,$(subst 32,64,$(subst clangarm,mingw,$(prefix)))) # Move system config into top-level /etc/ ETC_GITCONFIG = ../etc/gitconfig ETC_GITATTRIBUTES = ../etc/gitattributes @@ -759,79 +795,3 @@ ifeq ($(uname_S),QNX) NO_STRCASESTR = YesPlease NO_STRLCPY = YesPlease endif - -vcxproj: - # Require clean work tree - git update-index -q --refresh && \ - git diff-files --quiet && \ - git diff-index --cached --quiet HEAD -- - - # Make .vcxproj files and add them - perl contrib/buildsystems/generate -g Vcxproj - git add -f git.sln {*,*/lib,t/helper/*}/*.vcxproj - - # Generate the LinkOrCopyBuiltins.targets and LinkOrCopyRemoteHttp.targets file - (echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \ - echo ' <Target Name="CopyBuiltins_AfterBuild" AfterTargets="AfterBuild">' && \ - for name in $(BUILT_INS);\ - do \ - echo ' <Copy SourceFiles="$$(OutDir)\git.exe" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \ - done && \ - echo ' </Target>' && \ - echo '</Project>') >git/LinkOrCopyBuiltins.targets - (echo '<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">' && \ - echo ' <Target Name="CopyBuiltins_AfterBuild" AfterTargets="AfterBuild">' && \ - for name in $(REMOTE_CURL_ALIASES); \ - do \ - echo ' <Copy SourceFiles="$$(OutDir)\'"$(REMOTE_CURL_PRIMARY)"'" DestinationFiles="$$(OutDir)\'"$$name"'" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />'; \ - done && \ - echo ' </Target>' && \ - echo '</Project>') >git-remote-http/LinkOrCopyRemoteHttp.targets - git add -f git/LinkOrCopyBuiltins.targets git-remote-http/LinkOrCopyRemoteHttp.targets - - # Add generated headers - $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(GENERATED_H) - git add -f $(GENERATED_H) - - # Add scripts - rm -f perl/perl.mak - $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(SCRIPT_LIB) $(SCRIPTS) - # Strip out the sane tool path, needed only for building - sed -i '/^git_broken_path_fix ".*/d' git-sh-setup - git add -f $(SCRIPT_LIB) $(SCRIPTS) - - # Add Perl module - $(MAKE) $(LIB_PERL_GEN) - git add -f perl/build - - # Add bin-wrappers, for testing - rm -rf bin-wrappers/ - $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(test_bindir_programs) - # Ensure that the GIT_EXEC_PATH is a Unix-y one, and that the absolute - # path of the repository is not hard-coded (GIT_EXEC_PATH will be set - # by test-lib.sh according to the current setup) - sed -i -e 's/^\(GIT_EXEC_PATH\)=.*/test -n "$${\1##*:*}" ||\ - \1="$$(cygpath -u "$$\1")"/' \ - -e "s|'$$(pwd)|\"\$$GIT_EXEC_PATH\"'|g" bin-wrappers/* - # Ensure that test-* helpers find the .dll files copied to top-level - sed -i 's|^PATH=.*|&:"$$GIT_EXEC_PATH"|' bin-wrappers/test-* - # We do not want to force hard-linking builtins - sed -i 's|\(git\)-\([-a-z]*\)\.exe"|\1.exe" \2|g' \ - bin-wrappers/git-{receive-pack,upload-archive} - git add -f $(test_bindir_programs) - - # Add templates - $(MAKE) -C templates - git add -f templates/boilerplates.made templates/blt/ - - # Add the translated messages - make MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(MOFILES) - git add -f $(MOFILES) - - # Add build options - $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 GIT-BUILD-OPTIONS - git add -f GIT-BUILD-OPTIONS - - # Commit the whole shebang - git commit -m "Generate Visual Studio solution" \ - -m "Auto-generated by \`$(MAKE)$(MAKEFLAGS) $@\`" diff --git a/configure.ac b/configure.ac index 5923edc44a..f6caab919a 100644 --- a/configure.ac +++ b/configure.ac @@ -1066,6 +1066,33 @@ AC_CHECK_LIB([iconv], [locale_charset], [AC_CHECK_LIB([charset], [locale_charset], [CHARSET_LIB=-lcharset])]) GIT_CONF_SUBST([CHARSET_LIB]) + +# +# Define HAVE_SYSINFO=YesPlease if sysinfo is available. +# +AC_DEFUN([HAVE_SYSINFO_SRC], [ +AC_LANG_PROGRAM([[ +#include <stdint.h> +#include <sys/sysinfo.h> +]], [[ +struct sysinfo si; +uint64_t t = 0; +if (!sysinfo(&si)) { + t = si.totalram; + if (si.mem_unit > 1) + t *= (uint64_t)si.mem_unit; +} +return t; +]])]) + +AC_MSG_CHECKING([for sysinfo]) +AC_COMPILE_IFELSE([HAVE_SYSINFO_SRC], + [AC_MSG_RESULT([yes]) + HAVE_SYSINFO=YesPlease], + [AC_MSG_RESULT([no]) + HAVE_SYSINFO=]) +GIT_CONF_SUBST([HAVE_SYSINFO]) + # # Define HAVE_CLOCK_GETTIME=YesPlease if clock_gettime is available. GIT_CHECK_FUNC(clock_gettime, diff --git a/connected.c b/connected.c index 3099da84f3..4415388beb 100644 --- a/connected.c +++ b/connected.c @@ -3,7 +3,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "run-command.h" #include "sigchain.h" #include "connected.h" diff --git a/contrib/buildsystems/Generators.pm b/contrib/buildsystems/Generators.pm deleted file mode 100644 index aa4cbaa2ad..0000000000 --- a/contrib/buildsystems/Generators.pm +++ /dev/null @@ -1,42 +0,0 @@ -package Generators; -require Exporter; - -use strict; -use File::Basename; -no strict 'refs'; -use vars qw($VERSION @AVAILABLE); - -our $VERSION = '1.00'; -our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE); -@ISA = qw(Exporter); - -BEGIN { - local(*D); - my $me = $INC{"Generators.pm"}; - die "Couldn't find myself in \@INC, which is required to load the generators!" if ("$me" eq ""); - $me = dirname($me); - if (opendir(D,"$me/Generators")) { - foreach my $gen (readdir(D)) { - next unless ($gen =~ /\.pm$/); - require "${me}/Generators/$gen"; - $gen =~ s,\.pm,,; - push(@AVAILABLE, $gen); - } - closedir(D); - my $gens = join(', ', @AVAILABLE); - } - - push @EXPORT_OK, qw(available); -} - -sub available { - return @AVAILABLE; -} - -sub generate { - my ($gen, $git_dir, $out_dir, $rel_dir, %build_structure) = @_; - return eval("Generators::${gen}::generate(\$git_dir, \$out_dir, \$rel_dir, \%build_structure)") if grep(/^$gen$/, @AVAILABLE); - die "Generator \"${gen}\" is not available!\nAvailable generators are: @AVAILABLE\n"; -} - -1; diff --git a/contrib/buildsystems/Generators/QMake.pm b/contrib/buildsystems/Generators/QMake.pm deleted file mode 100644 index ff3b657e61..0000000000 --- a/contrib/buildsystems/Generators/QMake.pm +++ /dev/null @@ -1,189 +0,0 @@ -package Generators::QMake; -require Exporter; - -use strict; -use vars qw($VERSION); - -our $VERSION = '1.00'; -our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE); -@ISA = qw(Exporter); - -BEGIN { - push @EXPORT_OK, qw(generate); -} - -sub generate { - my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; - - my @libs = @{$build_structure{"LIBS"}}; - foreach (@libs) { - createLibProject($_, $git_dir, $out_dir, $rel_dir, %build_structure); - } - - my @apps = @{$build_structure{"APPS"}}; - foreach (@apps) { - createAppProject($_, $git_dir, $out_dir, $rel_dir, %build_structure); - } - - createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure); - return 0; -} - -sub createLibProject { - my ($libname, $git_dir, $out_dir, $rel_dir, %build_structure) = @_; - print "Generate $libname lib project\n"; - $rel_dir = "../$rel_dir"; - - my $sources = join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"LIBS_${libname}_SOURCES"}}))); - my $defines = join(" \\\n\t", sort(@{$build_structure{"LIBS_${libname}_DEFINES"}})); - my $includes= join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"LIBS_${libname}_INCLUDES"}}))); - my $cflags = join(" ", sort(@{$build_structure{"LIBS_${libname}_CFLAGS"}})); - - my $cflags_debug = $cflags; - $cflags_debug =~ s/-MT/-MTd/; - $cflags_debug =~ s/-O.//; - - my $cflags_release = $cflags; - $cflags_release =~ s/-MTd/-MT/; - - my @tmp = @{$build_structure{"LIBS_${libname}_LFLAGS"}}; - my @tmp2 = (); - foreach (@tmp) { - if (/^-LTCG/) { - } elsif (/^-L/) { - $_ =~ s/^-L/-LIBPATH:$rel_dir\//; - } - push(@tmp2, $_); - } - my $lflags = join(" ", sort(@tmp)); - - my $target = $libname; - $target =~ s/\//_/g; - $defines =~ s/-D//g; - $defines =~ s/"/\\\\"/g; - $includes =~ s/-I//g; - mkdir "$target" || die "Could not create the directory $target for lib project!\n"; - open F, ">$target/$target.pro" || die "Could not open $target/$target.pro for writing!\n"; - print F << "EOM"; -TEMPLATE = lib -TARGET = $target -DESTDIR = $rel_dir - -CONFIG -= qt -CONFIG += static - -QMAKE_CFLAGS = -QMAKE_CFLAGS_RELEASE = $cflags_release -QMAKE_CFLAGS_DEBUG = $cflags_debug -QMAKE_LIBFLAGS = $lflags - -DEFINES += \\ - $defines - -INCLUDEPATH += \\ - $includes - -SOURCES += \\ - $sources -EOM - close F; -} - -sub createAppProject { - my ($appname, $git_dir, $out_dir, $rel_dir, %build_structure) = @_; - print "Generate $appname app project\n"; - $rel_dir = "../$rel_dir"; - - my $sources = join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"APPS_${appname}_SOURCES"}}))); - my $defines = join(" \\\n\t", sort(@{$build_structure{"APPS_${appname}_DEFINES"}})); - my $includes= join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"APPS_${appname}_INCLUDES"}}))); - my $cflags = join(" ", sort(@{$build_structure{"APPS_${appname}_CFLAGS"}})); - - my $cflags_debug = $cflags; - $cflags_debug =~ s/-MT/-MTd/; - $cflags_debug =~ s/-O.//; - - my $cflags_release = $cflags; - $cflags_release =~ s/-MTd/-MT/; - - my $libs; - foreach (sort(@{$build_structure{"APPS_${appname}_LIBS"}})) { - $_ =~ s/\//_/g; - $libs .= " $_"; - } - my @tmp = @{$build_structure{"APPS_${appname}_LFLAGS"}}; - my @tmp2 = (); - foreach (@tmp) { - # next if ($_ eq "-NODEFAULTLIB:MSVCRT.lib"); - if (/^-LTCG/) { - } elsif (/^-L/) { - $_ =~ s/^-L/-LIBPATH:$rel_dir\//; - } - push(@tmp2, $_); - } - my $lflags = join(" ", sort(@tmp)); - - my $target = $appname; - $target =~ s/\.exe//; - $target =~ s/\//_/g; - $defines =~ s/-D//g; - $defines =~ s/"/\\\\"/g; - $includes =~ s/-I//g; - mkdir "$target" || die "Could not create the directory $target for app project!\n"; - open F, ">$target/$target.pro" || die "Could not open $target/$target.pro for writing!\n"; - print F << "EOM"; -TEMPLATE = app -TARGET = $target -DESTDIR = $rel_dir - -CONFIG -= qt embed_manifest_exe -CONFIG += console - -QMAKE_CFLAGS = -QMAKE_CFLAGS_RELEASE = $cflags_release -QMAKE_CFLAGS_DEBUG = $cflags_debug -QMAKE_LFLAGS = $lflags -LIBS = $libs - -DEFINES += \\ - $defines - -INCLUDEPATH += \\ - $includes - -win32:QMAKE_LFLAGS += -LIBPATH:$rel_dir -else: QMAKE_LFLAGS += -L$rel_dir - -SOURCES += \\ - $sources -EOM - close F; -} - -sub createGlueProject { - my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; - my $libs = join(" \\ \n", map("\t$_|$_.pro", @{$build_structure{"LIBS"}})); - my $apps = join(" \\ \n", map("\t$_|$_.pro", @{$build_structure{"APPS"}})); - $libs =~ s/\.a//g; - $libs =~ s/\//_/g; - $libs =~ s/\|/\//g; - $apps =~ s/\.exe//g; - $apps =~ s/\//_/g; - $apps =~ s/\|/\//g; - - my $filename = $out_dir; - $filename =~ s/.*\/([^\/]+)$/$1/; - $filename =~ s/\/$//; - print "Generate glue project $filename.pro\n"; - open F, ">$filename.pro" || die "Could not open $filename.pro for writing!\n"; - print F << "EOM"; -TEMPLATE = subdirs -CONFIG += ordered -SUBDIRS += \\ -$libs \\ -$apps -EOM - close F; -} - -1; diff --git a/contrib/buildsystems/Generators/Vcproj.pm b/contrib/buildsystems/Generators/Vcproj.pm deleted file mode 100644 index 737647e76a..0000000000 --- a/contrib/buildsystems/Generators/Vcproj.pm +++ /dev/null @@ -1,579 +0,0 @@ -package Generators::Vcproj; -require Exporter; - -use strict; -use vars qw($VERSION); -use Digest::SHA qw(sha256_hex); - -our $VERSION = '1.00'; -our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE); -@ISA = qw(Exporter); - -BEGIN { - push @EXPORT_OK, qw(generate); -} - -sub generate_guid ($) { - my $hex = sha256_hex($_[0]); - $hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12}).*/{$1-$2-$3-$4-$5}/; - $hex =~ tr/a-z/A-Z/; - return $hex; -} - -sub generate { - my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; - my @libs = @{$build_structure{"LIBS"}}; - foreach (@libs) { - createLibProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure); - } - - my @apps = @{$build_structure{"APPS"}}; - foreach (@apps) { - createAppProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure); - } - - createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure); - return 0; -} - -sub createLibProject { - my ($libname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_; - print "Generate $libname vcproj lib project\n"; - $rel_dir = "..\\$rel_dir"; - $rel_dir =~ s/\//\\/g; - - my $target = $libname; - $target =~ s/\//_/g; - $target =~ s/\.a//; - - my $uuid = generate_guid($libname); - $$build_structure{"LIBS_${target}_GUID"} = $uuid; - - my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"LIBS_${libname}_SOURCES"}})); - my @sources; - foreach (@srcs) { - $_ =~ s/\//\\/g; - push(@sources, $_); - } - my $defines = join(",", sort(@{$$build_structure{"LIBS_${libname}_DEFINES"}})); - my $includes= join(";", sort(map(""$rel_dir\\$_"", @{$$build_structure{"LIBS_${libname}_INCLUDES"}}))); - my $cflags = join(" ", sort(@{$$build_structure{"LIBS_${libname}_CFLAGS"}})); - $cflags =~ s/\"/"/g; - $cflags =~ s/</</g; - $cflags =~ s/>/>/g; - - my $cflags_debug = $cflags; - $cflags_debug =~ s/-MT/-MTd/; - $cflags_debug =~ s/-O.//; - - my $cflags_release = $cflags; - $cflags_release =~ s/-MTd/-MT/; - - my @tmp = @{$$build_structure{"LIBS_${libname}_LFLAGS"}}; - my @tmp2 = (); - foreach (@tmp) { - if (/^-LTCG/) { - } elsif (/^-L/) { - $_ =~ s/^-L/-LIBPATH:$rel_dir\//; - } - push(@tmp2, $_); - } - my $lflags = join(" ", sort(@tmp)); - - $defines =~ s/-D//g; - $defines =~ s/\"/\\"/g; - $defines =~ s/</</g; - $defines =~ s/>/>/g; - $defines =~ s/\'//g; - $includes =~ s/-I//g; - mkdir "$target" || die "Could not create the directory $target for lib project!\n"; - open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n"; - binmode F, ":crlf"; - print F << "EOM"; -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9,00" - Name="$target" - ProjectGUID="$uuid"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$rel_dir" - ConfigurationType="4" - CharacterSet="0" - IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="$cflags_debug" - Optimization="0" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories="$includes" - PreprocessorDefinitions="WIN32,_DEBUG,$defines" - MinimalRebuild="true" - RuntimeLibrary="1" - UsePrecompiledHeader="0" - ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - SuppressStartupBanner="true" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$rel_dir" - ConfigurationType="4" - CharacterSet="0" - WholeProgramOptimization="1" - IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="$cflags_release" - Optimization="2" - InlineFunctionExpansion="1" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="$includes" - PreprocessorDefinitions="WIN32,NDEBUG,$defines" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - SuppressStartupBanner="true" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> -EOM - foreach(@sources) { - print F << "EOM"; - <File - RelativePath="$_"/> -EOM - } - print F << "EOM"; - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> -EOM - close F; -} - -sub createAppProject { - my ($appname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_; - print "Generate $appname vcproj app project\n"; - $rel_dir = "..\\$rel_dir"; - $rel_dir =~ s/\//\\/g; - - my $target = $appname; - $target =~ s/\//_/g; - $target =~ s/\.exe//; - - my $uuid = generate_guid($appname); - $$build_structure{"APPS_${target}_GUID"} = $uuid; - - my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"APPS_${appname}_SOURCES"}})); - my @sources; - foreach (@srcs) { - $_ =~ s/\//\\/g; - push(@sources, $_); - } - my $defines = join(",", sort(@{$$build_structure{"APPS_${appname}_DEFINES"}})); - my $includes= join(";", sort(map(""$rel_dir\\$_"", @{$$build_structure{"APPS_${appname}_INCLUDES"}}))); - my $cflags = join(" ", sort(@{$$build_structure{"APPS_${appname}_CFLAGS"}})); - $cflags =~ s/\"/"/g; - $cflags =~ s/</</g; - $cflags =~ s/>/>/g; - - my $cflags_debug = $cflags; - $cflags_debug =~ s/-MT/-MTd/; - $cflags_debug =~ s/-O.//; - - my $cflags_release = $cflags; - $cflags_release =~ s/-MTd/-MT/; - - my $libs; - foreach (sort(@{$$build_structure{"APPS_${appname}_LIBS"}})) { - $_ =~ s/\//_/g; - $libs .= " $_"; - } - my @tmp = @{$$build_structure{"APPS_${appname}_LFLAGS"}}; - my @tmp2 = (); - foreach (@tmp) { - if (/^-LTCG/) { - } elsif (/^-L/) { - $_ =~ s/^-L/-LIBPATH:$rel_dir\//; - } - push(@tmp2, $_); - } - my $lflags = join(" ", sort(@tmp)) . " -LIBPATH:$rel_dir"; - - $defines =~ s/-D//g; - $defines =~ s/\"/\\"/g; - $defines =~ s/</</g; - $defines =~ s/>/>/g; - $defines =~ s/\'//g; - $defines =~ s/\\\\/\\/g; - $includes =~ s/-I//g; - mkdir "$target" || die "Could not create the directory $target for lib project!\n"; - open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n"; - binmode F, ":crlf"; - print F << "EOM"; -<?xml version="1.0" encoding = "Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9,00" - Name="$target" - ProjectGUID="$uuid"> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$rel_dir" - ConfigurationType="1" - CharacterSet="0" - IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="$cflags_debug" - Optimization="0" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories="$includes" - PreprocessorDefinitions="WIN32,_DEBUG,$defines" - MinimalRebuild="true" - RuntimeLibrary="1" - UsePrecompiledHeader="0" - ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="$libs" - AdditionalOptions="$lflags" - LinkIncremental="2" - GenerateDebugInformation="true" - SubSystem="1" - TargetMachine="1" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$rel_dir" - ConfigurationType="1" - CharacterSet="0" - WholeProgramOptimization="1" - IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="$cflags_release" - Optimization="2" - InlineFunctionExpansion="1" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="$includes" - PreprocessorDefinitions="WIN32,NDEBUG,$defines" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="$libs" - AdditionalOptions="$lflags" - LinkIncremental="1" - GenerateDebugInformation="true" - SubSystem="1" - TargetMachine="1" - OptimizeReferences="2" - EnableCOMDATFolding="2" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> -EOM - foreach(@sources) { - print F << "EOM"; - <File - RelativePath="$_"/> -EOM - } - print F << "EOM"; - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> -EOM - close F; -} - -sub createGlueProject { - my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; - print "Generate solutions file\n"; - $rel_dir = "..\\$rel_dir"; - $rel_dir =~ s/\//\\/g; - my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 10.00\n# Visual Studio 2008\n"; - my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = "; - my $SLN_POST = "\nEndProject\n"; - - my @libs = @{$build_structure{"LIBS"}}; - my @tmp; - foreach (@libs) { - $_ =~ s/\//_/g; - $_ =~ s/\.a//; - push(@tmp, $_); - } - @libs = @tmp; - - my @apps = @{$build_structure{"APPS"}}; - @tmp = (); - foreach (@apps) { - $_ =~ s/\//_/g; - $_ =~ s/\.exe//; - if ($_ eq "git" ) { - unshift(@tmp, $_); - } else { - push(@tmp, $_); - } - } - @apps = @tmp; - - open F, ">git.sln" || die "Could not open git.sln for writing!\n"; - binmode F, ":crlf"; - print F "$SLN_HEAD"; - - my $uuid_libgit = $build_structure{"LIBS_libgit_GUID"}; - my $uuid_xdiff_lib = $build_structure{"LIBS_xdiff_lib_GUID"}; - foreach (@apps) { - my $appname = $_; - my $uuid = $build_structure{"APPS_${appname}_GUID"}; - print F "$SLN_PRE"; - print F "\"${appname}\", \"${appname}\\${appname}.vcproj\", \"${uuid}\"\n"; - print F " ProjectSection(ProjectDependencies) = postProject\n"; - print F " ${uuid_libgit} = ${uuid_libgit}\n"; - print F " ${uuid_xdiff_lib} = ${uuid_xdiff_lib}\n"; - print F " EndProjectSection"; - print F "$SLN_POST"; - } - foreach (@libs) { - my $libname = $_; - my $uuid = $build_structure{"LIBS_${libname}_GUID"}; - print F "$SLN_PRE"; - print F "\"${libname}\", \"${libname}\\${libname}.vcproj\", \"${uuid}\""; - print F "$SLN_POST"; - } - - print F << "EOM"; -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection -EOM - print F << "EOM"; - GlobalSection(ProjectConfigurationPlatforms) = postSolution -EOM - foreach (@apps) { - my $appname = $_; - my $uuid = $build_structure{"APPS_${appname}_GUID"}; - print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n"; - print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n"; - print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n"; - print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n"; - } - foreach (@libs) { - my $libname = $_; - my $uuid = $build_structure{"LIBS_${libname}_GUID"}; - print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n"; - print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n"; - print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n"; - print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n"; - } - - print F << "EOM"; - EndGlobalSection -EndGlobal -EOM - close F; -} - -1; diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm deleted file mode 100644 index b2e68a1671..0000000000 --- a/contrib/buildsystems/Generators/Vcxproj.pm +++ /dev/null @@ -1,402 +0,0 @@ -package Generators::Vcxproj; -require Exporter; - -use strict; -use vars qw($VERSION); -use Digest::SHA qw(sha256_hex); - -our $VERSION = '1.00'; -our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE); -@ISA = qw(Exporter); - -BEGIN { - push @EXPORT_OK, qw(generate); -} - -sub generate_guid ($) { - my $hex = sha256_hex($_[0]); - $hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12}).*/{$1-$2-$3-$4-$5}/; - $hex =~ tr/a-z/A-Z/; - return $hex; -} - -sub generate { - my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; - my @libs = @{$build_structure{"LIBS"}}; - foreach (@libs) { - createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 1); - } - - my @apps = @{$build_structure{"APPS"}}; - foreach (@apps) { - createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 0); - } - - createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure); - return 0; -} - -sub createProject { - my ($name, $git_dir, $out_dir, $rel_dir, $build_structure, $static_library) = @_; - my $label = $static_library ? "lib" : "app"; - my $prefix = $static_library ? "LIBS_" : "APPS_"; - my $config_type = $static_library ? "StaticLibrary" : "Application"; - print "Generate $name vcxproj $label project\n"; - my $cdup = $name; - $cdup =~ s/[^\/]+/../g; - $cdup =~ s/\//\\/g; - $rel_dir = $rel_dir eq "." ? $cdup : "$cdup\\$rel_dir"; - $rel_dir =~ s/\//\\/g; - - my $target = $name; - if ($static_library) { - $target =~ s/\.a//; - } else { - $target =~ s/\.exe//; - } - - my $uuid = generate_guid($name); - $$build_structure{"$prefix${target}_GUID"} = $uuid; - my $vcxproj = $target; - $vcxproj =~ s/(.*\/)?(.*)/$&\/$2.vcxproj/; - $vcxproj =~ s/([^\/]*)(\/lib)\/(lib.vcxproj)/$1$2\/$1_$3/; - $$build_structure{"$prefix${target}_VCXPROJ"} = $vcxproj; - - my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"$prefix${name}_SOURCES"}})); - my @sources; - foreach (@srcs) { - $_ =~ s/\//\\/g; - push(@sources, $_); - } - my $defines = join(";", sort(@{$$build_structure{"$prefix${name}_DEFINES"}})); - my $includes= join(";", sort(map { s/^-I//; s/\//\\/g; File::Spec->file_name_is_absolute($_) ? $_ : "$rel_dir\\$_" } @{$$build_structure{"$prefix${name}_INCLUDES"}})); - my $cflags = join(" ", sort(map { s/^-[GLMOWZ].*//; s/.* .*/"$&"/; $_; } @{$$build_structure{"$prefix${name}_CFLAGS"}})); - $cflags =~ s/</</g; - $cflags =~ s/>/>/g; - - my $libs_release = "\n "; - my $libs_debug = "\n "; - if (!$static_library && $name ne 'headless-git') { - $libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib|reftable\/libreftable\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}})); - $libs_debug = $libs_release; - $libs_debug =~ s/zlib\.lib/zlibd\.lib/g; - $libs_debug =~ s/libexpat\.lib/libexpatd\.lib/g; - $libs_debug =~ s/libcurl\.lib/libcurl-d\.lib/g; - } - - $defines =~ s/-D//g; - $defines =~ s/</</g; - $defines =~ s/>/>/g; - $defines =~ s/\'//g; - - die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target"); - - open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n"; - binmode F, ":crlf :utf8"; - print F chr(0xFEFF); - print F << "EOM"; -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>$uuid</ProjectGuid> - <Keyword>Win32Proj</Keyword> - <VCPKGArch Condition="'\$(Platform)'=='Win32'">x86-windows</VCPKGArch> - <VCPKGArch Condition="'\$(Platform)'!='Win32'">x64-windows</VCPKGArch> - <VCPKGArchDirectory>$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)</VCPKGArchDirectory> - <VCPKGBinDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\bin</VCPKGBinDirectory> - <VCPKGLibDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\lib</VCPKGLibDirectory> - <VCPKGBinDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\bin</VCPKGBinDirectory> - <VCPKGLibDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\lib</VCPKGLibDirectory> - <VCPKGIncludeDirectory>\$(VCPKGArchDirectory)\\include</VCPKGIncludeDirectory> - <VCPKGLibs Condition="'\$(Configuration)'=='Debug'">$libs_debug</VCPKGLibs> - <VCPKGLibs Condition="'\$(Configuration)'!='Debug'">$libs_release</VCPKGLibs> - </PropertyGroup> - <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'\$(Configuration)'=='Debug'" Label="Configuration"> - <UseDebugLibraries>true</UseDebugLibraries> - <LinkIncremental>true</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'\$(Configuration)'=='Release'" Label="Configuration"> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - </PropertyGroup> - <PropertyGroup> - <ConfigurationType>$config_type</ConfigurationType> - <PlatformToolset>v140</PlatformToolset> - <!-- <CharacterSet>UTF-8</CharacterSet> --> - <OutDir>..\\</OutDir> - <!-- <IntDir>\$(ProjectDir)\$(Configuration)\\</IntDir> --> - </PropertyGroup> - <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="Shared"> - </ImportGroup> - <ImportGroup Label="PropertySheets"> - <Import Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup> - <GenerateManifest>false</GenerateManifest> - <EnableManagedIncrementalBuild>true</EnableManagedIncrementalBuild> - </PropertyGroup> - <ItemDefinitionGroup> - <ClCompile> - <AdditionalOptions>$cflags %(AdditionalOptions)</AdditionalOptions> - <AdditionalIncludeDirectories>$cdup;$cdup\\compat;$cdup\\compat\\regex;$cdup\\compat\\win32;$cdup\\compat\\poll;$cdup\\compat\\vcbuild\\include;\$(VCPKGIncludeDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <EnableParallelCodeGeneration /> - <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> - <PrecompiledHeader /> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - </ClCompile> - <Lib> - <SuppressStartupBanner>true</SuppressStartupBanner> - </Lib> - <Link> - <AdditionalLibraryDirectories>\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> - <AdditionalDependencies>\$(VCPKGLibs);\$(AdditionalDependencies)</AdditionalDependencies> - <AdditionalOptions>invalidcontinue.obj %(AdditionalOptions)</AdditionalOptions> - <EntryPointSymbol>wmainCRTStartup</EntryPointSymbol> - <ManifestFile>$cdup\\compat\\win32\\git.manifest</ManifestFile> - <SubSystem>Console</SubSystem> - </Link> -EOM - if ($target eq 'libgit') { - print F << "EOM"; - <PreBuildEvent Condition="!Exists('$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)\\include\\openssl\\ssl.h')"> - <Message>Initialize VCPKG</Message> - <Command>del "$cdup\\compat\\vcbuild\\vcpkg"</Command> - <Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat"</Command> - </PreBuildEvent> -EOM - } - print F << "EOM"; - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'\$(Platform)'=='Win32'"> - <Link> - <TargetMachine>MachineX86</TargetMachine> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'\$(Configuration)'=='Debug'"> - <ClCompile> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'\$(Configuration)'=='Release'"> - <ClCompile> - <Optimization>MaxSpeed</Optimization> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> - <FunctionLevelLinking>true</FunctionLevelLinking> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemGroup> -EOM - foreach(@sources) { - print F << "EOM"; - <ClCompile Include="$_" /> -EOM - } - print F << "EOM"; - </ItemGroup> -EOM - if ((!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') && !($name =~ /headless-git/)) { - my $uuid_libgit = $$build_structure{"LIBS_libgit_GUID"}; - my $uuid_libreftable = $$build_structure{"LIBS_reftable/libreftable_GUID"}; - my $uuid_xdiff_lib = $$build_structure{"LIBS_xdiff/lib_GUID"}; - - print F << "EOM"; - <ItemGroup> - <ProjectReference Include="$cdup\\libgit\\libgit.vcxproj"> - <Project>$uuid_libgit</Project> - <ReferenceOutputAssembly>false</ReferenceOutputAssembly> - </ProjectReference> -EOM - if (!($name =~ /xdiff|libreftable/)) { - print F << "EOM"; - <ProjectReference Include="$cdup\\reftable\\libreftable\\libreftable.vcxproj"> - <Project>$uuid_libreftable</Project> - <ReferenceOutputAssembly>false</ReferenceOutputAssembly> - </ProjectReference> -EOM - } - if (!($name =~ 'xdiff')) { - print F << "EOM"; - <ProjectReference Include="$cdup\\xdiff\\lib\\xdiff_lib.vcxproj"> - <Project>$uuid_xdiff_lib</Project> - <ReferenceOutputAssembly>false</ReferenceOutputAssembly> - </ProjectReference> -EOM - } - if ($name =~ /(test-(line-buffer|svn-fe)|^git-remote-testsvn)\.exe$/) { - my $uuid_vcs_svn_lib = $$build_structure{"LIBS_vcs-svn/lib_GUID"}; - print F << "EOM"; - <ProjectReference Include="$cdup\\vcs-svn\\lib\\vcs-svn_lib.vcxproj"> - <Project>$uuid_vcs_svn_lib</Project> - <ReferenceOutputAssembly>false</ReferenceOutputAssembly> - </ProjectReference> -EOM - } - print F << "EOM"; - </ItemGroup> -EOM - } - print F << "EOM"; - <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" /> -EOM - if (!$static_library) { - print F << "EOM"; - <Target Name="${target}_AfterBuild" AfterTargets="AfterBuild"> - <ItemGroup> - <DLLsAndPDBs Include="\$(VCPKGBinDirectory)\\*.dll;\$(VCPKGBinDirectory)\\*.pdb" /> - </ItemGroup> - <Copy SourceFiles="@(DLLsAndPDBs)" DestinationFolder="\$(OutDir)" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" /> - <MakeDir Directories="..\\templates\\blt\\branches" /> - </Target> -EOM - } - if ($target eq 'git') { - print F " <Import Project=\"LinkOrCopyBuiltins.targets\" />\n"; - } - if ($target eq 'git-remote-http') { - print F " <Import Project=\"LinkOrCopyRemoteHttp.targets\" />\n"; - } - print F << "EOM"; -</Project> -EOM - close F; -} - -sub createGlueProject { - my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; - print "Generate solutions file\n"; - $rel_dir = "..\\$rel_dir"; - $rel_dir =~ s/\//\\/g; - my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\n"; - my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = "; - my $SLN_POST = "\nEndProject\n"; - - my @libs = @{$build_structure{"LIBS"}}; - my @tmp; - foreach (@libs) { - $_ =~ s/\.a//; - push(@tmp, $_); - } - @libs = @tmp; - - my @apps = @{$build_structure{"APPS"}}; - @tmp = (); - foreach (@apps) { - $_ =~ s/\.exe//; - if ($_ eq "git" ) { - unshift(@tmp, $_); - } else { - push(@tmp, $_); - } - } - @apps = @tmp; - - open F, ">git.sln" || die "Could not open git.sln for writing!\n"; - binmode F, ":crlf :utf8"; - print F chr(0xFEFF); - print F "$SLN_HEAD"; - - foreach (@apps) { - my $appname = $_; - my $uuid = $build_structure{"APPS_${appname}_GUID"}; - print F "$SLN_PRE"; - my $vcxproj = $build_structure{"APPS_${appname}_VCXPROJ"}; - $vcxproj =~ s/\//\\/g; - $appname =~ s/.*\///; - print F "\"${appname}\", \"${vcxproj}\", \"${uuid}\""; - print F "$SLN_POST"; - } - foreach (@libs) { - my $libname = $_; - my $uuid = $build_structure{"LIBS_${libname}_GUID"}; - print F "$SLN_PRE"; - my $vcxproj = $build_structure{"LIBS_${libname}_VCXPROJ"}; - $vcxproj =~ s/\//\\/g; - $libname =~ s/\//_/g; - print F "\"${libname}\", \"${vcxproj}\", \"${uuid}\""; - print F "$SLN_POST"; - } - - print F << "EOM"; -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection -EOM - print F << "EOM"; - GlobalSection(ProjectConfigurationPlatforms) = postSolution -EOM - foreach (@apps) { - my $appname = $_; - my $uuid = $build_structure{"APPS_${appname}_GUID"}; - print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n"; - print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n"; - print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n"; - print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n"; - print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n"; - print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n"; - print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n"; - print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n"; - } - foreach (@libs) { - my $libname = $_; - my $uuid = $build_structure{"LIBS_${libname}_GUID"}; - print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n"; - print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n"; - print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n"; - print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n"; - print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n"; - print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n"; - print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n"; - print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n"; - } - - print F << "EOM"; - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal -EOM - close F; -} - -1; diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl deleted file mode 100755 index 069be7e4be..0000000000 --- a/contrib/buildsystems/engine.pl +++ /dev/null @@ -1,395 +0,0 @@ -#!/usr/bin/perl -w -###################################################################### -# Do not call this script directly! -# -# The generate script ensures that @INC is correct before the engine -# is executed. -# -# Copyright (C) 2009 Marius Storm-Olsen <mstormo@gmail.com> -###################################################################### -use strict; -use File::Basename; -use File::Spec; -use Cwd; -use Generators; -use Text::ParseWords; - -my (%build_structure, %compile_options, @makedry); -my $out_dir = getcwd(); -my $git_dir = $out_dir; -$git_dir =~ s=\\=/=g; -$git_dir = dirname($git_dir) while (!-e "$git_dir/git.c" && "$git_dir" ne ""); -die "Couldn't find Git repo" if ("$git_dir" eq ""); - -my @gens = Generators::available(); -my $gen = "Vcproj"; - -sub showUsage -{ - my $genlist = join(', ', @gens); - print << "EOM"; -generate usage: - -g <GENERATOR> --gen <GENERATOR> Specify the buildsystem generator (default: $gen) - Available: $genlist - -o <PATH> --out <PATH> Specify output directory generation (default: .) - --make-out <PATH> Write the output of GNU Make into a file - -i <FILE> --in <FILE> Specify input file, instead of running GNU Make - -h,-? --help This help -EOM - exit 0; -} - -# Parse command-line options -my $make_out; -while (@ARGV) { - my $arg = shift @ARGV; - if ("$arg" eq "-h" || "$arg" eq "--help" || "$arg" eq "-?") { - showUsage(); - exit(0); - } elsif("$arg" eq "--out" || "$arg" eq "-o") { - $out_dir = shift @ARGV; - } elsif("$arg" eq "--make-out") { - $make_out = shift @ARGV; - } elsif("$arg" eq "--gen" || "$arg" eq "-g") { - $gen = shift @ARGV; - } elsif("$arg" eq "--in" || "$arg" eq "-i") { - my $infile = shift @ARGV; - open(F, "<$infile") || die "Couldn't open file $infile"; - @makedry = <F>; - close(F); - } else { - die "Unknown option: " . $arg; - } -} - -# NOT using File::Spec->rel2abs($path, $base) here, as -# it fails badly for me in the msysgit environment -$git_dir = File::Spec->rel2abs($git_dir); -$out_dir = File::Spec->rel2abs($out_dir); -my $rel_dir = makeOutRel2Git($git_dir, $out_dir); - -# Print some information so the user feels informed -print << "EOM"; ------ -Generator: $gen -Git dir: $git_dir -Out dir: $out_dir ------ -Running GNU Make to figure out build structure... -EOM - -# Pipe a make --dry-run into a variable, if not already loaded from file -# Capture the make dry stderr to file for review (will be empty for a release build). - -my $ErrsFile = "msvc-build-makedryerrors.txt"; -@makedry = `make -C $git_dir -n MSVC=1 SKIP_VCPKG=1 V=1 2>$ErrsFile` -if !@makedry; -# test for an empty Errors file and remove it -unlink $ErrsFile if -f -z $ErrsFile; - -if (defined $make_out) { - open OUT, ">" . $make_out; - print OUT @makedry; - close OUT; -} - -# Parse the make output into usable info -parseMakeOutput(); - -# Finally, ask the generator to start generating.. -Generators::generate($gen, $git_dir, $out_dir, $rel_dir, %build_structure); - -# main flow ends here -# ------------------------------------------------------------------------------------------------- - - -# 1) path: /foo/bar/baz 2) path: /foo/bar/baz 3) path: /foo/bar/baz -# base: /foo/bar/baz/temp base: /foo/bar base: /tmp -# rel: .. rel: baz rel: ../foo/bar/baz -sub makeOutRel2Git -{ - my ($path, $base) = @_; - my $rel; - if ("$path" eq "$base") { - return "."; - } elsif ($base =~ /^$path/) { - # case 1 - my $tmp = $base; - $tmp =~ s/^$path//; - foreach (split('/', $tmp)) { - $rel .= "../" if ("$_" ne ""); - } - } elsif ($path =~ /^$base/) { - # case 2 - $rel = $path; - $rel =~ s/^$base//; - $rel = "./$rel"; - } else { - my $tmp = $base; - foreach (split('/', $tmp)) { - $rel .= "../" if ("$_" ne ""); - } - $rel .= $path; - } - $rel =~ s/\/\//\//g; # simplify - $rel =~ s/\/$//; # don't end with / - return $rel; -} - -sub parseMakeOutput -{ - print "Parsing GNU Make output to figure out build structure...\n"; - my $line = 0; - while (my $text = shift @makedry) { - my $ate_next; - do { - $ate_next = 0; - $line++; - chomp $text; - chop $text if ($text =~ /\r$/); - if ($text =~ /\\$/) { - $text =~ s/\\$//; - $text .= shift @makedry; - $ate_next = 1; - } - } while($ate_next); - - if ($text =~ /^test /) { - # options to test (eg -o) may be mistaken for linker options - next; - } - - if ($text =~ /^(mkdir|msgfmt) /) { - # options to the Portable Object translations - # the line "mkdir ... && msgfmt ..." contains no linker options - next; - } - - if($text =~ / -c /) { - # compilation - handleCompileLine($text, $line); - - } elsif ($text =~ / -o /) { - # linking executable - handleLinkLine($text, $line); - - } elsif ($text =~ /\.o / && $text =~ /\.a /) { - # libifying - handleLibLine($text, $line); -# -# } elsif ($text =~ /^cp /) { -# # copy file around -# -# } elsif ($text =~ /^rm -f /) { -# # shell command -# -# } elsif ($text =~ /^make[ \[]/) { -# # make output -# -# } elsif ($text =~ /^echo /) { -# # echo to file -# -# } elsif ($text =~ /^if /) { -# # shell conditional -# -# } elsif ($text =~ /^tclsh /) { -# # translation stuff -# -# } elsif ($text =~ /^umask /) { -# # handling boilerplates -# -# } elsif ($text =~ /\$\(\:\)/) { -# # ignore -# -# } elsif ($text =~ /^FLAGS=/) { -# # flags check for dependencies -# -# } elsif ($text =~ /^'\/usr\/bin\/perl' -MError -e/) { -# # perl commands for copying files -# -# } elsif ($text =~ /generate-cmdlist\.sh/) { -# # command for generating list of commands -# -# } elsif ($text =~ /new locations or Tcl/) { -# # command for detecting Tcl/Tk changes -# -# } elsif ($text =~ /mkdir -p/) { -# # command creating path -# -# } elsif ($text =~ /: no custom templates yet/) { -# # whatever -# -# } else { -# print "Unhandled (line: $line): $text\n"; - } - } - -# use Data::Dumper; -# print "Parsed build structure:\n"; -# print Dumper(%build_structure); -} - -# variables for the compilation part of each step -my (@defines, @incpaths, @cflags, @sources); - -sub clearCompileStep -{ - @defines = (); - @incpaths = (); - @cflags = (); - @sources = (); -} - -sub removeDuplicates -{ - my (%dupHash, $entry); - %dupHash = map { $_, 1 } @defines; - @defines = keys %dupHash; - - %dupHash = map { $_, 1 } @incpaths; - @incpaths = keys %dupHash; - - %dupHash = map { $_, 1 } @cflags; - @cflags = keys %dupHash; -} - -sub handleCompileLine -{ - my ($line, $lineno) = @_; - my @parts = shellwords($line); - my $sourcefile; - shift(@parts); # ignore cmd - while (my $part = shift @parts) { - if ("$part" eq "-o") { - # ignore object file - shift @parts; - } elsif ("$part" eq "-c") { - # ignore compile flag - } elsif ("$part" eq "-c") { - } elsif ($part =~ /^.?-I/) { - push(@incpaths, $part); - } elsif ($part =~ /^.?-D/) { - push(@defines, $part); - } elsif ($part =~ /^-/) { - push(@cflags, $part); - } elsif ($part =~ /\.(c|cc|cpp)$/) { - $sourcefile = $part; - } else { - die "Unhandled compiler option @ line $lineno: $part"; - } - } - @{$compile_options{"${sourcefile}_CFLAGS"}} = @cflags; - @{$compile_options{"${sourcefile}_DEFINES"}} = @defines; - @{$compile_options{"${sourcefile}_INCPATHS"}} = @incpaths; - clearCompileStep(); -} - -sub handleLibLine -{ - my ($line, $lineno) = @_; - my (@objfiles, @lflags, $libout, $part); - # kill cmd and rm 'prefix' - $line =~ s/^rm -f .* && .* rcs //; - my @parts = shellwords($line); - while ($part = shift @parts) { - if ($part =~ /^-/) { - push(@lflags, $part); - } elsif ($part =~ /\.(o|obj)$/) { - push(@objfiles, $part); - } elsif ($part =~ /\.(a|lib)$/) { - $libout = $part; - $libout =~ s/\.a$//; - } else { - die "Unhandled lib option @ line $lineno: $part"; - } - } -# print "LibOut: '$libout'\nLFlags: @lflags\nOfiles: @objfiles\n"; -# exit(1); - foreach (@objfiles) { - my $sourcefile = $_; - $sourcefile =~ s/\.o$/.c/; - push(@sources, $sourcefile); - push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}}); - push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}}); - push(@incpaths, @{$compile_options{"${sourcefile}_INCPATHS"}}); - } - removeDuplicates(); - - push(@{$build_structure{"LIBS"}}, $libout); - @{$build_structure{"LIBS_${libout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_SOURCES", - "_OBJECTS"); - @{$build_structure{"LIBS_${libout}_DEFINES"}} = @defines; - @{$build_structure{"LIBS_${libout}_INCLUDES"}} = @incpaths; - @{$build_structure{"LIBS_${libout}_CFLAGS"}} = @cflags; - @{$build_structure{"LIBS_${libout}_LFLAGS"}} = @lflags; - @{$build_structure{"LIBS_${libout}_SOURCES"}} = @sources; - @{$build_structure{"LIBS_${libout}_OBJECTS"}} = @objfiles; - clearCompileStep(); -} - -sub handleLinkLine -{ - my ($line, $lineno) = @_; - my (@objfiles, @lflags, @libs, $appout, $part); - my @parts = shellwords($line); - shift(@parts); # ignore cmd - while ($part = shift @parts) { - if ($part =~ /^-IGNORE/) { - push(@lflags, $part); - } elsif ($part =~ /^-[GRIMDO]/) { - # eat compiler flags - } elsif ("$part" eq "-o") { - $appout = shift @parts; - } elsif ("$part" eq "-lz") { - push(@libs, "zlib.lib"); - } elsif ("$part" eq "-lcrypto") { - push(@libs, "libcrypto.lib"); - } elsif ("$part" eq "-lssl") { - push(@libs, "libssl.lib"); - } elsif ("$part" eq "-lcurl") { - push(@libs, "libcurl.lib"); - } elsif ("$part" eq "-lexpat") { - push(@libs, "libexpat.lib"); - } elsif ("$part" eq "-liconv") { - push(@libs, "iconv.lib"); - } elsif ($part =~ /^[-\/]/) { - push(@lflags, $part); - } elsif ($part =~ /\.(a|lib)$/) { - $part =~ s/\.a$/.lib/; - push(@libs, $part); - } elsif ($part eq 'invalidcontinue.obj') { - # ignore - known to MSVC - } elsif ($part =~ /\.o$/) { - push(@objfiles, $part); - } elsif ($part =~ /\.obj$/) { - # do nothing, 'make' should not be producing .obj, only .o files - } else { - die "Unhandled link option @ line $lineno: $part"; - } - } -# print "AppOut: '$appout'\nLFlags: @lflags\nLibs : @libs\nOfiles: @objfiles\n"; -# exit(1); - foreach (@objfiles) { - my $sourcefile = $_; - $sourcefile =~ s/^headless-git\.o$/compat\/win32\/headless.c/; - $sourcefile =~ s/\.o$/.c/; - push(@sources, $sourcefile); - push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}}); - push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}}); - push(@incpaths, @{$compile_options{"${sourcefile}_INCPATHS"}}); - } - removeDuplicates(); - - removeDuplicates(); - push(@{$build_structure{"APPS"}}, $appout); - @{$build_structure{"APPS_${appout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_LFLAGS", - "_SOURCES", "_OBJECTS", "_LIBS"); - @{$build_structure{"APPS_${appout}_DEFINES"}} = @defines; - @{$build_structure{"APPS_${appout}_INCLUDES"}} = @incpaths; - @{$build_structure{"APPS_${appout}_CFLAGS"}} = @cflags; - @{$build_structure{"APPS_${appout}_LFLAGS"}} = @lflags; - @{$build_structure{"APPS_${appout}_SOURCES"}} = @sources; - @{$build_structure{"APPS_${appout}_OBJECTS"}} = @objfiles; - @{$build_structure{"APPS_${appout}_LIBS"}} = @libs; - clearCompileStep(); -} diff --git a/contrib/buildsystems/generate b/contrib/buildsystems/generate deleted file mode 100755 index bc10f25ff2..0000000000 --- a/contrib/buildsystems/generate +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/perl -w -###################################################################### -# Generate buildsystem files -# -# This script generate buildsystem files based on the output of a -# GNU Make --dry-run, enabling Windows users to develop Git with their -# trusted IDE with native projects. -# -# Note: -# It is not meant as *the* way of building Git with MSVC, but merely a -# convenience. The correct way of building Git with MSVC is to use the -# GNU Make tool to build with the maintained Makefile in the root of -# the project. If you have the msysgit environment installed and -# available in your current console, together with the Visual Studio -# environment you wish to build for, all you have to do is run the -# command: -# make MSVC=1 -# -# Copyright (C) 2009 Marius Storm-Olsen <mstormo@gmail.com> -###################################################################### -use strict; -use File::Basename; -use Cwd; - -my $git_dir = getcwd(); -$git_dir =~ s=\\=/=g; -$git_dir = dirname($git_dir) while (!-e "$git_dir/git.c" && "$git_dir" ne ""); -die "Couldn't find Git repo" if ("$git_dir" eq ""); -exec join(" ", ("PERL5LIB=${git_dir}/contrib/buildsystems ${git_dir}/contrib/buildsystems/engine.pl", @ARGV)); diff --git a/contrib/buildsystems/parse.pl b/contrib/buildsystems/parse.pl deleted file mode 100755 index c9656ece99..0000000000 --- a/contrib/buildsystems/parse.pl +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/perl -w -###################################################################### -# Do not call this script directly! -# -# The generate script ensures that @INC is correct before the engine -# is executed. -# -# Copyright (C) 2009 Marius Storm-Olsen <mstormo@gmail.com> -###################################################################### -use strict; -use File::Basename; -use Cwd; - -my $file = $ARGV[0]; -die "No file provided!" if !defined $file; - -my ($cflags, $target, $type, $line); - -open(F, "<$file") || die "Couldn't open file $file"; -my @data = <F>; -close(F); - -while (my $text = shift @data) { - my $ate_next; - do { - $ate_next = 0; - $line++; - chomp $text; - chop $text if ($text =~ /\r$/); - if ($text =~ /\\$/) { - $text =~ s/\\$//; - $text .= shift @data; - $ate_next = 1; - } - } while($ate_next); - - if($text =~ / -c /) { - # compilation - handleCompileLine($text, $line); - - } elsif ($text =~ / -o /) { - # linking executable - handleLinkLine($text, $line); - - } elsif ($text =~ /\.o / && $text =~ /\.a /) { - # libifying - handleLibLine($text, $line); - -# } elsif ($text =~ /^cp /) { -# # copy file around -# -# } elsif ($text =~ /^rm -f /) { -# # shell command -# -# } elsif ($text =~ /^make[ \[]/) { -# # make output -# -# } elsif ($text =~ /^echo /) { -# # echo to file -# -# } elsif ($text =~ /^if /) { -# # shell conditional -# -# } elsif ($text =~ /^tclsh /) { -# # translation stuff -# -# } elsif ($text =~ /^umask /) { -# # handling boilerplates -# -# } elsif ($text =~ /\$\(\:\)/) { -# # ignore -# -# } elsif ($text =~ /^FLAGS=/) { -# # flags check for dependencies -# -# } elsif ($text =~ /^'\/usr\/bin\/perl' -MError -e/) { -# # perl commands for copying files -# -# } elsif ($text =~ /generate-cmdlist\.sh/) { -# # command for generating list of commands -# -# } elsif ($text =~ /^test / && $text =~ /|| rm -f /) { -# # commands removing executables, if they exist -# -# } elsif ($text =~ /new locations or Tcl/) { -# # command for detecting Tcl/Tk changes -# -# } elsif ($text =~ /mkdir -p/) { -# # command creating path -# -# } elsif ($text =~ /: no custom templates yet/) { -# # whatever - - } else { -# print "Unhandled (line: $line): $text\n"; - } -} -close(F); - -# use Data::Dumper; -# print "Parsed build structure:\n"; -# print Dumper(%build_structure); - -# ------------------------------------------------------------------- -# Functions under here -# ------------------------------------------------------------------- -my (%build_structure, @defines, @incpaths, @cflags, @sources); - -sub clearCompileStep -{ - @defines = (); - @incpaths = (); - @cflags = (); - @sources = (); -} - -sub removeDuplicates -{ - my (%dupHash, $entry); - %dupHash = map { $_, 1 } @defines; - @defines = keys %dupHash; - - %dupHash = map { $_, 1 } @incpaths; - @incpaths = keys %dupHash; - - %dupHash = map { $_, 1 } @cflags; - @cflags = keys %dupHash; - - %dupHash = map { $_, 1 } @sources; - @sources = keys %dupHash; -} - -sub handleCompileLine -{ - my ($line, $lineno) = @_; - my @parts = split(' ', $line); - shift(@parts); # ignore cmd - while (my $part = shift @parts) { - if ("$part" eq "-o") { - # ignore object file - shift @parts; - } elsif ("$part" eq "-c") { - # ignore compile flag - } elsif ("$part" eq "-c") { - } elsif ($part =~ /^.?-I/) { - push(@incpaths, $part); - } elsif ($part =~ /^.?-D/) { - push(@defines, $part); - } elsif ($part =~ /^-/) { - push(@cflags, $part); - } elsif ($part =~ /\.(c|cc|cpp)$/) { - push(@sources, $part); - } else { - die "Unhandled compiler option @ line $lineno: $part"; - } - } - #print "Sources: @sources\nCFlags: @cflags\nDefine: @defines\nIncpat: @incpaths\n"; - #exit(1); -} - -sub handleLibLine -{ - my ($line, $lineno) = @_; - my (@objfiles, @lflags, $libout, $part); - # kill cmd and rm 'prefix' - $line =~ s/^rm -f .* && .* rcs //; - my @parts = split(' ', $line); - while ($part = shift @parts) { - if ($part =~ /^-/) { - push(@lflags, $part); - } elsif ($part =~ /\.(o|obj)$/) { - push(@objfiles, $part); - } elsif ($part =~ /\.(a|lib)$/) { - $libout = $part; - } else { - die "Unhandled lib option @ line $lineno: $part"; - } - } - #print "LibOut: '$libout'\nLFlags: @lflags\nOfiles: @objfiles\n"; - #exit(1); - removeDuplicates(); - push(@{$build_structure{"LIBS"}}, $libout); - @{$build_structure{"LIBS_${libout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_SOURCES", - "_OBJECTS"); - @{$build_structure{"LIBS_${libout}_DEFINES"}} = @defines; - @{$build_structure{"LIBS_${libout}_INCLUDES"}} = @incpaths; - @{$build_structure{"LIBS_${libout}_CFLAGS"}} = @cflags; - @{$build_structure{"LIBS_${libout}_SOURCES"}} = @sources; - @{$build_structure{"LIBS_${libout}_OBJECTS"}} = @objfiles; - clearCompileStep(); -} - -sub handleLinkLine -{ - my ($line, $lineno) = @_; - my (@objfiles, @lflags, @libs, $appout, $part); - my @parts = split(' ', $line); - shift(@parts); # ignore cmd - while ($part = shift @parts) { - if ($part =~ /^-[GRIDO]/) { - # eat compiler flags - } elsif ("$part" eq "-o") { - $appout = shift @parts; - } elsif ($part =~ /^-/) { - push(@lflags, $part); - } elsif ($part =~ /\.(a|lib)$/) { - push(@libs, $part); - } elsif ($part =~ /\.(o|obj)$/) { - push(@objfiles, $part); - } else { - die "Unhandled lib option @ line $lineno: $part"; - } - } - #print "AppOut: '$appout'\nLFlags: @lflags\nLibs : @libs\nOfiles: @objfiles\n"; - #exit(1); - removeDuplicates(); - push(@{$build_structure{"APPS"}}, $appout); - @{$build_structure{"APPS_${appout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_LFLAGS", - "_SOURCES", "_OBJECTS", "_LIBS"); - @{$build_structure{"APPS_${appout}_DEFINES"}} = @defines; - @{$build_structure{"APPS_${appout}_INCLUDES"}} = @incpaths; - @{$build_structure{"APPS_${appout}_CFLAGS"}} = @cflags; - @{$build_structure{"APPS_${appout}_LFLAGS"}} = @lflags; - @{$build_structure{"APPS_${appout}_SOURCES"}} = @sources; - @{$build_structure{"APPS_${appout}_OBJECTS"}} = @objfiles; - @{$build_structure{"APPS_${appout}_LIBS"}} = @libs; - clearCompileStep(); -} diff --git a/contrib/coccinelle/meson.build b/contrib/coccinelle/meson.build index 5d76a7fee6..dc3f73c2e7 100644 --- a/contrib/coccinelle/meson.build +++ b/contrib/coccinelle/meson.build @@ -1,23 +1,13 @@ -spatch = find_program('spatch', required: get_option('coccinelle')) +coccinelle_opt = get_option('coccinelle').require( + fs.exists(meson.project_source_root() / '.git'), + error_message: 'coccinelle can only be run from a git checkout', +) + +spatch = find_program('spatch', required: coccinelle_opt) if not spatch.found() subdir_done() endif -third_party_sources = [ - ':!contrib', - ':!compat/inet_ntop.c', - ':!compat/inet_pton.c', - ':!compat/nedmalloc', - ':!compat/obstack.*', - ':!compat/poll', - ':!compat/regex', - ':!sha1collisiondetection', - ':!sha1dc', - ':!t/unit-tests/clar', - ':!t/unit-tests/clar', - ':!t/t[0-9][0-9][0-9][0-9]*', -] - rules = [ 'array.cocci', 'commit.cocci', @@ -50,18 +40,18 @@ concatenated_rules = custom_target( capture: true, ) -sources = [ ] -foreach source : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.c', third_party_sources, check: true).stdout().split() - sources += source +coccinelle_sources = [] +foreach source : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.c', third_party_excludes, check: true).stdout().split() + coccinelle_sources += source endforeach -headers = [ ] -foreach header : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.h', third_party_sources, check: true).stdout().split() - headers += meson.project_source_root() / header +coccinelle_headers = [] +foreach header : headers_to_check + coccinelle_headers += meson.project_source_root() / header endforeach patches = [ ] -foreach source : sources +foreach source : coccinelle_sources patches += custom_target( command: [ spatch, @@ -73,7 +63,7 @@ foreach source : sources input: meson.project_source_root() / source, output: source.underscorify() + '.patch', capture: true, - depend_files: headers, + depend_files: coccinelle_headers, ) endforeach diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 413911be3b..e3d88b0672 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -234,6 +234,17 @@ __git_dequote () done } +# Prints the number of slash-separated components in a path. +# 1: Path to count components of. +__git_count_path_components () +{ + local path="$1" + local relative="${path#/}" + relative="${relative%/}" + local slashes="/${relative//[^\/]}" + echo "${#slashes}" +} + # The following function is based on code from: # # bash_completion - programmable completion functions for bash 3.2+ @@ -779,16 +790,39 @@ __git_tags () __git_dwim_remote_heads () { local pfx="${1-}" cur_="${2-}" sfx="${3-}" - local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers # employ the heuristic used by git checkout and git switch # Try to find a remote branch that cur_es the completion word # but only output if the branch name is unique - __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ - --sort="refname:strip=3" \ - ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ - "refs/remotes/*/$cur_*" "refs/remotes/*/$cur_*/**" | \ - uniq -u + local awk_script=' + function casemap(s) { + if (ENVIRON["IGNORE_CASE"]) + return tolower(s) + else + return s + } + BEGIN { + split(ENVIRON["REMOTES"], remotes, /\n/) + for (i in remotes) + remotes[i] = "refs/remotes/" casemap(remotes[i]) + cur_ = casemap(ENVIRON["CUR_"]) + } + { + ref_case = casemap($0) + for (i in remotes) { + if (index(ref_case, remotes[i] "/" cur_) == 1) { + branch = substr($0, length(remotes[i] "/") + 1) + print ENVIRON["PFX"] branch ENVIRON["SFX"] + break + } + } + } + ' + __git for-each-ref --format='%(refname)' refs/remotes/ | + PFX="$pfx" SFX="$sfx" CUR_="$cur_" \ + IGNORE_CASE=${GIT_COMPLETION_IGNORE_CASE+1} \ + REMOTES="$(__git_remotes | sort -r)" awk "$awk_script" | + sort | uniq -u } # Lists refs from the local (by default) or from a remote repository. @@ -894,7 +928,8 @@ __git_refs () case "HEAD" in $match*|$umatch*) echo "${pfx}HEAD$sfx" ;; esac - __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \ + local strip="$(__git_count_path_components "refs/remotes/$remote")" + __git for-each-ref --format="$fer_pfx%(refname:strip=$strip)$sfx" \ ${GIT_COMPLETION_IGNORE_CASE+--ignore-case} \ "refs/remotes/$remote/$match*" \ "refs/remotes/$remote/$match*/**" diff --git a/contrib/completion/meson.build b/contrib/completion/meson.build index 3a9ddab594..576125b083 100644 --- a/contrib/completion/meson.build +++ b/contrib/completion/meson.build @@ -14,3 +14,21 @@ foreach script : [ ) endif endforeach + +# We have to discern between the test dependency and the installed file. Our +# tests assume the completion scripts to have the same name as the in-tree +# files, but the installed filenames need to match the executable's basename. +if meson.version().version_compare('>=1.3.0') + fs.copyfile('git-completion.bash', 'git', + install: true, + install_dir: get_option('datadir') / 'bash-completion/completions', + ) +else + configure_file( + input: 'git-completion.bash', + output: 'git', + copy: true, + install: true, + install_dir: get_option('datadir') / 'bash-completion/completions', + ) +endif diff --git a/contrib/credential/netrc/meson.build b/contrib/credential/netrc/meson.build index a990dbb86d..16fa69e317 100644 --- a/contrib/credential/netrc/meson.build +++ b/contrib/credential/netrc/meson.build @@ -7,14 +7,16 @@ credential_netrc = custom_target( install_dir: get_option('libexecdir') / 'git-core', ) -credential_netrc_testenv = test_environment -credential_netrc_testenv.set('CREDENTIAL_NETRC_PATH', credential_netrc.full_path()) +if get_option('tests') + credential_netrc_testenv = test_environment + credential_netrc_testenv.set('CREDENTIAL_NETRC_PATH', credential_netrc.full_path()) -test('t-git-credential-netrc', - shell, - args: [ meson.current_source_dir() / 't-git-credential-netrc.sh' ], - workdir: meson.current_source_dir(), - env: credential_netrc_testenv, - depends: test_dependencies + bin_wrappers + [credential_netrc], - timeout: 0, -) + test('t-git-credential-netrc', + shell, + args: [ meson.current_source_dir() / 't-git-credential-netrc.sh' ], + workdir: meson.current_source_dir(), + env: credential_netrc_testenv, + depends: test_dependencies + bin_wrappers + [credential_netrc], + kwargs: test_kwargs, + ) +endif diff --git a/contrib/subtree/README b/contrib/subtree/README index c686b4a69b..65d167b678 100644 --- a/contrib/subtree/README +++ b/contrib/subtree/README @@ -1,5 +1,5 @@ -Please read git-subtree.txt for documentation. +Please read git-subtree.adoc for documentation. Please don't contact me using github mail; it's slow, ugly, and worst of all, redundant. Email me instead at apenwarr@gmail.com and I'll be happy to diff --git a/contrib/subtree/git-subtree.adoc b/contrib/subtree/git-subtree.adoc index 004abf415b..b2bcbcad0d 100644 --- a/contrib/subtree/git-subtree.adoc +++ b/contrib/subtree/git-subtree.adoc @@ -9,14 +9,14 @@ git-subtree - Merge subtrees together and split repository into subtrees SYNOPSIS -------- [verse] -'git subtree' [<options>] -P <prefix> add <local-commit> -'git subtree' [<options>] -P <prefix> add <repository> <remote-ref> -'git subtree' [<options>] -P <prefix> merge <local-commit> [<repository>] -'git subtree' [<options>] -P <prefix> split [<local-commit>] +'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <local-commit> +'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <repository> <remote-ref> +'git subtree' [<options>] -P <prefix> [-S[<keyid>]] merge <local-commit> [<repository>] +'git subtree' [<options>] -P <prefix> [-S[<keyid>]] split [<local-commit>] [verse] -'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref> -'git subtree' [<options>] -P <prefix> push <repository> <refspec> +'git subtree' [<options>] -P <prefix> [-S[<keyid>]] pull <repository> <remote-ref> +'git subtree' [<options>] -P <prefix> [-S[<keyid>]] push <repository> <refspec> DESCRIPTION ----------- @@ -149,6 +149,13 @@ OPTIONS FOR ALL COMMANDS want to manipulate. This option is mandatory for all commands. +-S[<keyid>]:: +--gpg-sign[=<keyid>]:: +--no-gpg-sign:: + GPG-sign commits. The `keyid` argument is optional and + defaults to the committer identity; `--no-gpg-sign` is useful to + countermand a `--gpg-sign` option given earlier on the command line. + OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin') ----------------------------------------------------------------------------------- These options for 'add' and 'merge' may also be given to 'pull' (which diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index 15ae86db1b..3fddba797c 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -26,12 +26,12 @@ then fi OPTS_SPEC="\ -git subtree add --prefix=<prefix> <commit> -git subtree add --prefix=<prefix> <repository> <ref> -git subtree merge --prefix=<prefix> <commit> -git subtree split --prefix=<prefix> [<commit>] -git subtree pull --prefix=<prefix> <repository> <ref> -git subtree push --prefix=<prefix> <repository> <refspec> +git subtree add --prefix=<prefix> [-S[=<key-id>]] <commit> +git subtree add --prefix=<prefix> [-S[=<key-id>]] <repository> <ref> +git subtree merge --prefix=<prefix> [-S[=<key-id>]] <commit> +git subtree split --prefix=<prefix> [-S[=<key-id>]] [<commit>] +git subtree pull --prefix=<prefix> [-S[=<key-id>]] <repository> <ref> +git subtree push --prefix=<prefix> [-S[=<key-id>]] <repository> <refspec> -- h,help! show the help q,quiet! quiet @@ -46,6 +46,7 @@ rejoin merge the new branch back into HEAD options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin') squash merge subtree changes as a single commit m,message!= use the given message as the commit message for the merge commit +S,gpg-sign?key-id GPG-sign commits. The keyid argument is optional and defaults to the committer identity " indent=0 @@ -115,7 +116,7 @@ main () { then set -- -h fi - set_args="$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" + set_args="$(echo "$OPTS_SPEC" | git rev-parse --parseopt --stuck-long -- "$@" || echo exit $?)" eval "$set_args" . git-sh-setup require_work_tree @@ -131,9 +132,6 @@ main () { opt="$1" shift case "$opt" in - --annotate|-b|-P|-m|--onto) - shift - ;; --rejoin) arg_split_rejoin=1 ;; @@ -171,48 +169,44 @@ main () { arg_split_annotate= arg_addmerge_squash= arg_addmerge_message= + arg_gpg_sign= while test $# -gt 0 do opt="$1" shift case "$opt" in - -q) + --quiet) arg_quiet=1 ;; - -d) + --debug) arg_debug=1 ;; - --annotate) + --annotate=*) test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" - arg_split_annotate="$1" - shift + arg_split_annotate="${opt#*=}" ;; --no-annotate) test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" arg_split_annotate= ;; - -b) + --branch=*) test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" - arg_split_branch="$1" - shift + arg_split_branch="${opt#*=}" ;; - -P) - arg_prefix="${1%/}" - shift + --prefix=*) + arg_prefix="${opt#*=}" ;; - -m) + --message=*) test -n "$allow_addmerge" || die_incompatible_opt "$opt" "$arg_command" - arg_addmerge_message="$1" - shift + arg_addmerge_message="${opt#*=}" ;; --no-prefix) arg_prefix= ;; - --onto) + --onto=*) test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" - arg_split_onto="$1" - shift + arg_split_onto="${opt#*=}" ;; --no-onto) test -n "$allow_split" || die_incompatible_opt "$opt" "$arg_command" @@ -240,6 +234,9 @@ main () { test -n "$allow_addmerge" || die_incompatible_opt "$opt" "$arg_command" arg_addmerge_squash= ;; + --gpg-sign=* | --gpg-sign | --no-gpg-sign) + arg_gpg_sign="$opt" + ;; --) break ;; @@ -272,6 +269,7 @@ main () { debug "quiet: {$arg_quiet}" debug "dir: {$dir}" debug "opts: {$*}" + debug "gpg-sign: {$arg_gpg_sign}" debug "cmd_$arg_command" "$@" @@ -537,7 +535,7 @@ copy_commit () { printf "%s" "$arg_split_annotate" cat ) | - git commit-tree "$2" $3 # reads the rest of stdin + git commit-tree $arg_gpg_sign "$2" $3 # reads the rest of stdin ) || die "fatal: can't copy commit $1" } @@ -683,10 +681,10 @@ new_squash_commit () { if test -n "$old" then squash_msg "$dir" "$oldsub" "$newsub" | - git commit-tree "$tree" -p "$old" || exit $? + git commit-tree $arg_gpg_sign "$tree" -p "$old" || exit $? else squash_msg "$dir" "" "$newsub" | - git commit-tree "$tree" || exit $? + git commit-tree $arg_gpg_sign "$tree" || exit $? fi } @@ -925,11 +923,11 @@ cmd_add_commit () { then rev=$(new_squash_commit "" "" "$rev") || exit $? commit=$(add_squashed_msg "$rev" "$dir" | - git commit-tree "$tree" $headp -p "$rev") || exit $? + git commit-tree $arg_gpg_sign "$tree" $headp -p "$rev") || exit $? else revp=$(peel_committish "$rev") || exit $? commit=$(add_msg "$dir" $headrev "$rev" | - git commit-tree "$tree" $headp -p "$revp") || exit $? + git commit-tree $arg_gpg_sign "$tree" $headp -p "$revp") || exit $? fi git reset "$commit" || exit $? @@ -1080,9 +1078,9 @@ cmd_merge () { if test -n "$arg_addmerge_message" then git merge --no-ff -Xsubtree="$arg_prefix" \ - --message="$arg_addmerge_message" "$rev" + --message="$arg_addmerge_message" $arg_gpg_sign "$rev" else - git merge --no-ff -Xsubtree="$arg_prefix" $rev + git merge --no-ff -Xsubtree="$arg_prefix" $arg_gpg_sign $rev fi } diff --git a/contrib/subtree/meson.build b/contrib/subtree/meson.build index 9c72b23625..98dd8e0c8e 100644 --- a/contrib/subtree/meson.build +++ b/contrib/subtree/meson.build @@ -12,16 +12,18 @@ git_subtree = custom_target( install_dir: get_option('libexecdir') / 'git-core', ) -subtree_test_environment = test_environment -subtree_test_environment.prepend('PATH', meson.current_build_dir()) +if get_option('tests') + subtree_test_environment = test_environment + subtree_test_environment.prepend('PATH', meson.current_build_dir()) -test('t7900-subtree', shell, - args: [ 't7900-subtree.sh' ], - env: subtree_test_environment, - workdir: meson.current_source_dir() / 't', - depends: test_dependencies + bin_wrappers + [ git_subtree ], - timeout: 0, -) + test('t7900-subtree', shell, + args: [ 't7900-subtree.sh' ], + env: subtree_test_environment, + workdir: meson.current_source_dir() / 't', + depends: test_dependencies + bin_wrappers + [ git_subtree ], + kwargs: test_kwargs, + ) +endif if get_option('docs').contains('man') subtree_xml = custom_target( diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh index 3c6103f6d2..3edbb33af4 100755 --- a/contrib/subtree/t/t7900-subtree.sh +++ b/contrib/subtree/t/t7900-subtree.sh @@ -11,6 +11,7 @@ and push subcommands of git subtree. TEST_DIRECTORY=$(pwd)/../../../t . "$TEST_DIRECTORY"/test-lib.sh +. "$TEST_DIRECTORY"/lib-gpg.sh # Use our own wrapper around test-lib.sh's test_create_repo, in order # to set log.date=relative. `git subtree` parses the output of `git @@ -1563,4 +1564,116 @@ test_expect_success 'subtree descendant check' ' ) ' +test_expect_success GPG 'add subproj with GPG signing using -S flag' ' + subtree_test_create_repo "$test_count" && + subtree_test_create_repo "$test_count/sub proj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/sub proj" sub1 && + ( + cd "$test_count" && + git fetch ./"sub proj" HEAD && + git subtree add --prefix="sub dir" -S FETCH_HEAD && + git verify-commit HEAD && + test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" + ) +' + +test_expect_success GPG 'add subproj with GPG signing using --gpg-sign flag' ' + subtree_test_create_repo "$test_count" && + subtree_test_create_repo "$test_count/sub proj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/sub proj" sub1 && + ( + cd "$test_count" && + git fetch ./"sub proj" HEAD && + git subtree add --prefix="sub dir" --gpg-sign FETCH_HEAD && + git verify-commit HEAD && + test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" + ) +' + +test_expect_success GPG 'add subproj with GPG signing using specific key ID' ' + subtree_test_create_repo "$test_count" && + subtree_test_create_repo "$test_count/sub proj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/sub proj" sub1 && + ( + cd "$test_count" && + git fetch ./"sub proj" HEAD && + git subtree add --prefix="sub dir" -S"$GIT_COMMITTER_EMAIL" FETCH_HEAD && + git verify-commit HEAD && + test "$(last_commit_subject)" = "Add '\''sub dir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" + ) +' + +test_expect_success GPG 'merge with GPG signing' ' + subtree_test_create_repo "$test_count" && + subtree_test_create_repo "$test_count/sub proj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/sub proj" sub1 && + ( + cd "$test_count" && + git fetch ./"sub proj" HEAD && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$test_count/sub proj" sub2 && + ( + cd "$test_count" && + git fetch ./"sub proj" HEAD && + git subtree merge --prefix="sub dir" -S FETCH_HEAD && + git verify-commit HEAD + ) +' + +test_expect_success GPG 'split with GPG signing and --rejoin' ' + subtree_test_create_repo "$test_count" && + subtree_test_create_repo "$test_count/sub proj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/sub proj" sub1 && + ( + cd "$test_count" && + git fetch ./"sub proj" HEAD && + git subtree add --prefix="sub dir" FETCH_HEAD + ) && + test_create_commit "$test_count" "sub dir/main-sub1" && + ( + cd "$test_count" && + git subtree split --prefix="sub dir" --rejoin -S && + git verify-commit HEAD + ) +' + +test_expect_success GPG 'add with --squash and GPG signing' ' + subtree_test_create_repo "$test_count" && + subtree_test_create_repo "$test_count/sub proj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/sub proj" sub1 && + ( + cd "$test_count" && + git fetch ./"sub proj" HEAD && + git subtree add --prefix="sub dir" --squash -S FETCH_HEAD && + git verify-commit HEAD && + # With --squash, the commit subject should reference the squash commit (first parent of merge) + squash_commit=$(git rev-parse HEAD^2) && + test "$(last_commit_subject)" = "Merge commit '\''$squash_commit'\'' as '\''sub dir'\''" + ) +' + +test_expect_success GPG 'pull with GPG signing' ' + subtree_test_create_repo "$test_count" && + subtree_test_create_repo "$test_count/sub proj" && + test_create_commit "$test_count" main1 && + test_create_commit "$test_count/sub proj" sub1 && + ( + cd "$test_count" && + git subtree add --prefix="sub dir" ./"sub proj" HEAD + ) && + test_create_commit "$test_count/sub proj" sub2 && + ( + cd "$test_count" && + git subtree pull --prefix="sub dir" -S ./"sub proj" HEAD && + git verify-commit HEAD + ) +' + test_done @@ -8,7 +8,7 @@ #include "copy.h" #include "gettext.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-file.h" #include "attr.h" #include "run-command.h" #include "quote.h" diff --git a/csum-file.c b/csum-file.c index b58c183a4f..6e21e3cac8 100644 --- a/csum-file.c +++ b/csum-file.c @@ -8,8 +8,6 @@ * able to verify hasn't been messed with afterwards. */ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "csum-file.h" #include "git-zlib.h" @@ -148,21 +146,23 @@ void hashwrite(struct hashfile *f, const void *buf, unsigned int count) } } -struct hashfile *hashfd_check(const char *name) +struct hashfile *hashfd_check(const struct git_hash_algo *algop, + const char *name) { int sink, check; struct hashfile *f; sink = xopen("/dev/null", O_WRONLY); check = xopen(name, O_RDONLY); - f = hashfd(sink, name); + f = hashfd(algop, sink, name); f->check_fd = check; f->check_buffer = xmalloc(f->buffer_len); return f; } -static struct hashfile *hashfd_internal(int fd, const char *name, +static struct hashfile *hashfd_internal(const struct git_hash_algo *algop, + int fd, const char *name, struct progress *tp, size_t buffer_len) { @@ -176,7 +176,7 @@ static struct hashfile *hashfd_internal(int fd, const char *name, f->do_crc = 0; f->skip_hash = 0; - f->algop = unsafe_hash_algo(the_hash_algo); + f->algop = unsafe_hash_algo(algop); f->algop->init_fn(&f->ctx); f->buffer_len = buffer_len; @@ -186,17 +186,19 @@ static struct hashfile *hashfd_internal(int fd, const char *name, return f; } -struct hashfile *hashfd(int fd, const char *name) +struct hashfile *hashfd(const struct git_hash_algo *algop, + int fd, const char *name) { /* * Since we are not going to use a progress meter to * measure the rate of data passing through this hashfile, * use a larger buffer size to reduce fsync() calls. */ - return hashfd_internal(fd, name, NULL, 128 * 1024); + return hashfd_internal(algop, fd, name, NULL, 128 * 1024); } -struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp) +struct hashfile *hashfd_throughput(const struct git_hash_algo *algop, + int fd, const char *name, struct progress *tp) { /* * Since we are expecting to report progress of the @@ -204,7 +206,7 @@ struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp * size so the progress indicators arrive at a more * frequent rate. */ - return hashfd_internal(fd, name, tp, 8 * 1024); + return hashfd_internal(algop, fd, name, tp, 8 * 1024); } void hashfile_checkpoint_init(struct hashfile *f, @@ -246,13 +248,15 @@ uint32_t crc32_end(struct hashfile *f) return f->crc32; } -int hashfile_checksum_valid(const unsigned char *data, size_t total_len) +int hashfile_checksum_valid(const struct git_hash_algo *algop, + const unsigned char *data, size_t total_len) { unsigned char got[GIT_MAX_RAWSZ]; struct git_hash_ctx ctx; - const struct git_hash_algo *algop = unsafe_hash_algo(the_hash_algo); size_t data_len = total_len - algop->rawsz; + algop = unsafe_hash_algo(algop); + if (total_len < algop->rawsz) return 0; /* say "too short"? */ diff --git a/csum-file.h b/csum-file.h index ffccbf0996..07ae11024a 100644 --- a/csum-file.h +++ b/csum-file.h @@ -45,9 +45,12 @@ int hashfile_truncate(struct hashfile *, struct hashfile_checkpoint *); #define CSUM_FSYNC 2 #define CSUM_HASH_IN_STREAM 4 -struct hashfile *hashfd(int fd, const char *name); -struct hashfile *hashfd_check(const char *name); -struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp); +struct hashfile *hashfd(const struct git_hash_algo *algop, + int fd, const char *name); +struct hashfile *hashfd_check(const struct git_hash_algo *algop, + const char *name); +struct hashfile *hashfd_throughput(const struct git_hash_algo *algop, + int fd, const char *name, struct progress *tp); /* * Free the hashfile without flushing its contents to disk. This only @@ -66,7 +69,8 @@ void crc32_begin(struct hashfile *); uint32_t crc32_end(struct hashfile *); /* Verify checksum validity while reading. Returns non-zero on success. */ -int hashfile_checksum_valid(const unsigned char *data, size_t len); +int hashfile_checksum_valid(const struct git_hash_algo *algop, + const unsigned char *data, size_t len); /* * Returns the total number of bytes fed to the hashfile so far (including ones diff --git a/decorate.c b/decorate.c index e161e13772..9f24925263 100644 --- a/decorate.c +++ b/decorate.c @@ -3,8 +3,6 @@ * data. */ -#define DISABLE_SIGN_COMPARE_WARNINGS - #include "git-compat-util.h" #include "object.h" #include "decorate.h" @@ -16,9 +14,8 @@ static unsigned int hash_obj(const struct object *obj, unsigned int n) static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration) { - int size = n->size; struct decoration_entry *entries = n->entries; - unsigned int j = hash_obj(base, size); + unsigned int j = hash_obj(base, n->size); while (entries[j].base) { if (entries[j].base == base) { @@ -26,7 +23,7 @@ static void *insert_decoration(struct decoration *n, const struct object *base, entries[j].decoration = decoration; return old; } - if (++j >= size) + if (++j >= n->size) j = 0; } entries[j].base = base; @@ -37,8 +34,8 @@ static void *insert_decoration(struct decoration *n, const struct object *base, static void grow_decoration(struct decoration *n) { - int i; - int old_size = n->size; + unsigned int i; + unsigned int old_size = n->size; struct decoration_entry *old_entries = n->entries; n->size = (old_size + 1000) * 3 / 2; @@ -59,9 +56,7 @@ static void grow_decoration(struct decoration *n) void *add_decoration(struct decoration *n, const struct object *obj, void *decoration) { - int nr = n->nr + 1; - - if (nr > n->size * 2 / 3) + if ((n->nr + 1) > n->size * 2 / 3) grow_decoration(n); return insert_decoration(n, obj, decoration); } diff --git a/delta-islands.c b/delta-islands.c index 3aec43fada..36c94799d6 100644 --- a/delta-islands.c +++ b/delta-islands.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -267,8 +266,7 @@ void resolve_tree_islands(struct repository *r, QSORT(todo, nr, tree_depth_compare); if (progress) - progress_state = start_progress(the_repository, - _("Propagating island marks"), nr); + progress_state = start_progress(r, _("Propagating island marks"), nr); for (i = 0; i < nr; i++) { struct object_entry *ent = todo[i].entry; @@ -490,9 +488,9 @@ void load_delta_islands(struct repository *r, int progress) island_marks = kh_init_oid_map(); - git_config(island_config_callback, &ild); + repo_config(r, island_config_callback, &ild); ild.remote_islands = kh_init_str(); - refs_for_each_ref(get_main_ref_store(the_repository), + refs_for_each_ref(get_main_ref_store(r), find_island_for_ref, &ild); free_config_regexes(&ild); deduplicate_islands(ild.remote_islands, r); @@ -502,7 +500,7 @@ void load_delta_islands(struct repository *r, int progress) fprintf(stderr, _("Marked %d islands, done.\n"), island_counter); } -void propagate_island_marks(struct commit *commit) +void propagate_island_marks(struct repository *r, struct commit *commit) { khiter_t pos = kh_get_oid_map(island_marks, commit->object.oid); @@ -510,8 +508,8 @@ void propagate_island_marks(struct commit *commit) struct commit_list *p; struct island_bitmap *root_marks = kh_value(island_marks, pos); - repo_parse_commit(the_repository, commit); - set_island_marks(&repo_get_commit_tree(the_repository, commit)->object, + repo_parse_commit(r, commit); + set_island_marks(&repo_get_commit_tree(r, commit)->object, root_marks); for (p = commit->parents; p; p = p->next) set_island_marks(&p->item->object, root_marks); diff --git a/delta-islands.h b/delta-islands.h index 8d1591ae28..6107660306 100644 --- a/delta-islands.h +++ b/delta-islands.h @@ -12,7 +12,7 @@ void resolve_tree_islands(struct repository *r, int progress, struct packing_data *to_pack); void load_delta_islands(struct repository *r, int progress); -void propagate_island_marks(struct commit *commit); +void propagate_island_marks(struct repository *r, struct commit *commit); int compute_pack_layers(struct packing_data *to_pack); void free_island_marks(void); diff --git a/detect-compiler b/detect-compiler index a87650b71b..124ebdd4c9 100755 --- a/detect-compiler +++ b/detect-compiler @@ -9,7 +9,7 @@ CC="$*" # # FreeBSD clang version 3.4.1 (tags/RELEASE...) get_version_line() { - LANG=C LC_ALL=C $CC -v 2>&1 | grep ' version ' + LANG=C LC_ALL=C $CC -v 2>&1 | sed -n '/ version /{p;q;}' } get_family() { diff --git a/diagnose.c b/diagnose.c index bd485effea..b1be74be98 100644 --- a/diagnose.c +++ b/diagnose.c @@ -7,7 +7,7 @@ #include "gettext.h" #include "hex.h" #include "strvec.h" -#include "object-store-ll.h" +#include "object-store.h" #include "packfile.h" #include "parse-options.h" #include "repository.h" diff --git a/diff-delta.c b/diff-delta.c index a4faf73829..71d37368d6 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -438,19 +438,31 @@ create_delta(const struct delta_index *index, op = out + outpos++; i = 0x80; - if (moff & 0x000000ff) - out[outpos++] = moff >> 0, i |= 0x01; - if (moff & 0x0000ff00) - out[outpos++] = moff >> 8, i |= 0x02; - if (moff & 0x00ff0000) - out[outpos++] = moff >> 16, i |= 0x04; - if (moff & 0xff000000) - out[outpos++] = moff >> 24, i |= 0x08; - - if (msize & 0x00ff) - out[outpos++] = msize >> 0, i |= 0x10; - if (msize & 0xff00) - out[outpos++] = msize >> 8, i |= 0x20; + if (moff & 0x000000ff) { + out[outpos++] = moff >> 0; + i |= 0x01; + } + if (moff & 0x0000ff00) { + out[outpos++] = moff >> 8; + i |= 0x02; + } + if (moff & 0x00ff0000) { + out[outpos++] = moff >> 16; + i |= 0x04; + } + if (moff & 0xff000000) { + out[outpos++] = moff >> 24; + i |= 0x08; + } + + if (msize & 0x00ff) { + out[outpos++] = msize >> 0; + i |= 0x10; + } + if (msize & 0xff00) { + out[outpos++] = msize >> 8; + i |= 0x20; + } *op = i; diff --git a/diff-lib.c b/diff-lib.c index 353b473ed5..244468dd1a 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -172,7 +172,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option) * these from (stage - 2). */ dpath = combine_diff_path_new(ce->name, ce_namelen(ce), - wt_mode, null_oid(), 2); + wt_mode, null_oid(the_hash_algo), 2); while (i < entries) { struct cache_entry *nce = istate->cache[i]; @@ -257,7 +257,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option) ce_intent_to_add(ce)) { newmode = ce_mode_from_stat(ce, st.st_mode); diff_addremove(&revs->diffopt, '+', newmode, - null_oid(), 0, ce->name, 0); + null_oid(the_hash_algo), 0, ce->name, 0); continue; } @@ -274,7 +274,7 @@ void run_diff_files(struct rev_info *revs, unsigned int option) } oldmode = ce->ce_mode; old_oid = &ce->oid; - new_oid = changed ? null_oid() : &ce->oid; + new_oid = changed ? null_oid(the_hash_algo) : &ce->oid; diff_change(&revs->diffopt, oldmode, newmode, old_oid, new_oid, !is_null_oid(old_oid), @@ -330,7 +330,7 @@ static int get_stat_data(const struct cache_entry *ce, 0, dirty_submodule); if (changed) { mode = ce_mode_from_stat(ce, st.st_mode); - oid = null_oid(); + oid = null_oid(the_hash_algo); } } @@ -402,7 +402,7 @@ static int show_modified(struct rev_info *revs, p = combine_diff_path_new(new_entry->name, ce_namelen(new_entry), - mode, null_oid(), 2); + mode, null_oid(the_hash_algo), 2); p->parent[0].status = DIFF_STATUS_MODIFIED; p->parent[0].mode = new_entry->ce_mode; oidcpy(&p->parent[0].oid, &new_entry->oid); diff --git a/diff-no-index.c b/diff-no-index.c index 6f277892d3..4aeeb98cfa 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -15,20 +15,45 @@ #include "gettext.h" #include "revision.h" #include "parse-options.h" +#include "pathspec.h" #include "string-list.h" #include "dir.h" -static int read_directory_contents(const char *path, struct string_list *list) +static int read_directory_contents(const char *path, struct string_list *list, + const struct pathspec *pathspec, + int skip) { + struct strbuf match = STRBUF_INIT; + int len; DIR *dir; struct dirent *e; if (!(dir = opendir(path))) return error("Could not open directory %s", path); - while ((e = readdir_skip_dot_and_dotdot(dir))) + if (pathspec) { + strbuf_addstr(&match, path); + strbuf_complete(&match, '/'); + strbuf_remove(&match, 0, skip); + + len = match.len; + } + + while ((e = readdir_skip_dot_and_dotdot(dir))) { + if (pathspec) { + strbuf_setlen(&match, len); + strbuf_addstr(&match, e->d_name); + + if (!match_leading_pathspec(NULL, pathspec, + match.buf, match.len, + 0, NULL, e->d_type == DT_DIR ? 1 : 0)) + continue; + } + string_list_insert(list, e->d_name); + } + strbuf_release(&match); closedir(dir); return 0; } @@ -113,7 +138,8 @@ static void populate_from_stdin(struct diff_filespec *s) populate_common(s, &buf); } -static struct diff_filespec *noindex_filespec(const char *name, int mode, +static struct diff_filespec *noindex_filespec(const struct git_hash_algo *algop, + const char *name, int mode, enum special special) { struct diff_filespec *s; @@ -121,7 +147,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode, if (!name) name = "/dev/null"; s = alloc_filespec(name); - fill_filespec(s, null_oid(), 0, mode); + fill_filespec(s, null_oid(algop), 0, mode); if (special == SPECIAL_STDIN) populate_from_stdin(s); else if (special == SPECIAL_PIPE) @@ -129,8 +155,9 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode, return s; } -static int queue_diff(struct diff_options *o, - const char *name1, const char *name2, int recursing) +static int queue_diff(struct diff_options *o, const struct git_hash_algo *algop, + const char *name1, const char *name2, int recursing, + const struct pathspec *ps, int skip1, int skip2) { int mode1 = 0, mode2 = 0; enum special special1 = SPECIAL_NONE, special2 = SPECIAL_NONE; @@ -145,14 +172,14 @@ static int queue_diff(struct diff_options *o, if (S_ISDIR(mode1)) { /* 2 is file that is created */ - d1 = noindex_filespec(NULL, 0, SPECIAL_NONE); - d2 = noindex_filespec(name2, mode2, special2); + d1 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE); + d2 = noindex_filespec(algop, name2, mode2, special2); name2 = NULL; mode2 = 0; } else { /* 1 is file that is deleted */ - d1 = noindex_filespec(name1, mode1, special1); - d2 = noindex_filespec(NULL, 0, SPECIAL_NONE); + d1 = noindex_filespec(algop, name1, mode1, special1); + d2 = noindex_filespec(algop, NULL, 0, SPECIAL_NONE); name1 = NULL; mode1 = 0; } @@ -170,9 +197,9 @@ static int queue_diff(struct diff_options *o, int i1, i2, ret = 0; size_t len1 = 0, len2 = 0; - if (name1 && read_directory_contents(name1, &p1)) + if (name1 && read_directory_contents(name1, &p1, ps, skip1)) return -1; - if (name2 && read_directory_contents(name2, &p2)) { + if (name2 && read_directory_contents(name2, &p2, ps, skip2)) { string_list_clear(&p1, 0); return -1; } @@ -217,7 +244,7 @@ static int queue_diff(struct diff_options *o, n2 = buffer2.buf; } - ret = queue_diff(o, n1, n2, 1); + ret = queue_diff(o, algop, n1, n2, 1, ps, skip1, skip2); } string_list_clear(&p1, 0); string_list_clear(&p2, 0); @@ -234,8 +261,8 @@ static int queue_diff(struct diff_options *o, SWAP(special1, special2); } - d1 = noindex_filespec(name1, mode1, special1); - d2 = noindex_filespec(name2, mode2, special2); + d1 = noindex_filespec(algop, name1, mode1, special1); + d2 = noindex_filespec(algop, name2, mode2, special2); diff_queue(&diff_queued_diff, d1, d2); return 0; } @@ -257,8 +284,10 @@ static void append_basename(struct strbuf *path, const char *dir, const char *fi * DWIM "diff D F" into "diff D/F F" and "diff F D" into "diff F D/F" * Note that we append the basename of F to D/, so "diff a/b/file D" * becomes "diff a/b/file D/file", not "diff a/b/file D/a/b/file". + * + * Return 1 if both paths are directories, 0 otherwise. */ -static void fixup_paths(const char **path, struct strbuf *replacement) +static int fixup_paths(const char **path, struct strbuf *replacement) { struct stat st; unsigned int isdir0 = 0, isdir1 = 0; @@ -281,27 +310,31 @@ static void fixup_paths(const char **path, struct strbuf *replacement) if ((isdir0 && ispipe1) || (ispipe0 && isdir1)) die(_("cannot compare a named pipe to a directory")); - if (isdir0 == isdir1) - return; + /* if both paths are directories, we will enable pathspecs */ + if (isdir0 && isdir1) + return 1; + if (isdir0) { append_basename(replacement, path[0], path[1]); path[0] = replacement->buf; - } else { + } else if (isdir1) { append_basename(replacement, path[1], path[0]); path[1] = replacement->buf; } + + return 0; } static const char * const diff_no_index_usage[] = { - N_("git diff --no-index [<options>] <path> <path>"), + N_("git diff --no-index [<options>] <path> <path> [<pathspec>...]"), NULL }; -int diff_no_index(struct rev_info *revs, - int implicit_no_index, - int argc, const char **argv) +int diff_no_index(struct rev_info *revs, const struct git_hash_algo *algop, + int implicit_no_index, int argc, const char **argv) { - int i, no_index; + struct pathspec pathspec, *ps = NULL; + int i, no_index, skip1 = 0, skip2 = 0; int ret = 1; const char *paths[2]; char *to_free[ARRAY_SIZE(paths)] = { 0 }; @@ -317,13 +350,12 @@ int diff_no_index(struct rev_info *revs, options = add_diff_options(no_index_options, &revs->diffopt); argc = parse_options(argc, argv, revs->prefix, options, diff_no_index_usage, 0); - if (argc != 2) { + if (argc < 2) { if (implicit_no_index) warning(_("Not a git repository. Use --no-index to " "compare two paths outside a working tree")); usage_with_options(diff_no_index_usage, options); } - FREE_AND_NULL(options); for (i = 0; i < 2; i++) { const char *p = argv[i]; if (!strcmp(p, "-")) @@ -337,7 +369,23 @@ int diff_no_index(struct rev_info *revs, paths[i] = p; } - fixup_paths(paths, &replacement); + if (fixup_paths(paths, &replacement)) { + parse_pathspec(&pathspec, PATHSPEC_FROMTOP | PATHSPEC_ATTR, + PATHSPEC_PREFER_FULL | PATHSPEC_NO_REPOSITORY, + NULL, &argv[2]); + if (pathspec.nr) + ps = &pathspec; + + skip1 = strlen(paths[0]); + skip1 += paths[0][skip1] == '/' ? 0 : 1; + skip2 = strlen(paths[1]); + skip2 += paths[1][skip2] == '/' ? 0 : 1; + } else if (argc > 2) { + warning(_("Limiting comparison with pathspecs is only " + "supported if both paths are directories.")); + usage_with_options(diff_no_index_usage, options); + } + FREE_AND_NULL(options); revs->diffopt.skip_stat_unmatch = 1; if (!revs->diffopt.output_format) @@ -354,7 +402,8 @@ int diff_no_index(struct rev_info *revs, setup_diff_pager(&revs->diffopt); revs->diffopt.flags.exit_with_status = 1; - if (queue_diff(&revs->diffopt, paths[0], paths[1], 0)) + if (queue_diff(&revs->diffopt, algop, paths[0], paths[1], 0, ps, + skip1, skip2)) goto out; diff_set_mnemonic_prefix(&revs->diffopt, "1/", "2/"); diffcore_std(&revs->diffopt); @@ -370,5 +419,7 @@ out: for (i = 0; i < ARRAY_SIZE(to_free); i++) free(to_free[i]); strbuf_release(&replacement); + if (ps) + clear_pathspec(ps); return ret; } @@ -23,7 +23,7 @@ #include "color.h" #include "run-command.h" #include "utf8.h" -#include "object-store-ll.h" +#include "object-store.h" #include "userdiff.h" #include "submodule.h" #include "hashmap.h" @@ -892,7 +892,7 @@ static void fill_es_indent_data(struct emitted_diff_symbol *es) /* skip any \v \f \r at start of indentation */ while (s[off] == '\f' || s[off] == '\v' || - (s[off] == '\r' && off < len - 1)) + (off < len - 1 && s[off] == '\r')) off++; /* calculate the visual width of indentation */ @@ -4193,7 +4193,8 @@ int diff_populate_filespec(struct repository *r, * is probably fine. */ if (check_binary && - s->size > big_file_threshold && s->is_binary == -1) { + s->size > repo_settings_get_big_file_threshold(the_repository) && + s->is_binary == -1) { s->is_binary = 1; return 0; } @@ -4243,7 +4244,8 @@ object_read: if (size_only || check_binary) { if (size_only) return 0; - if (s->size > big_file_threshold && s->is_binary == -1) { + if (s->size > repo_settings_get_big_file_threshold(the_repository) && + s->is_binary == -1) { s->is_binary = 1; return 0; } @@ -4344,7 +4346,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r, die_errno("readlink(%s)", one->path); prep_temp_blob(r->index, one->path, temp, sb.buf, sb.len, (one->oid_valid ? - &one->oid : null_oid()), + &one->oid : null_oid(the_hash_algo)), (one->oid_valid ? one->mode : S_IFLNK)); strbuf_release(&sb); @@ -4353,7 +4355,7 @@ static struct diff_tempfile *prepare_temp_file(struct repository *r, /* we can borrow from the file in the work tree */ temp->name = one->path; if (!one->oid_valid) - oid_to_hex_r(temp->hex, null_oid()); + oid_to_hex_r(temp->hex, null_oid(the_hash_algo)); else oid_to_hex_r(temp->hex, &one->oid); /* Even though we may sometimes borrow the @@ -5892,10 +5894,15 @@ struct option *add_diff_options(const struct option *opts, OPT_CALLBACK_F(0, "diff-filter", options, N_("[(A|C|D|M|R|T|U|X|B)...[*]]"), N_("select files by diff type"), PARSE_OPT_NONEG, diff_opt_diff_filter), - { OPTION_CALLBACK, 0, "output", options, N_("<file>"), - N_("output to a specific file"), - PARSE_OPT_NONEG, NULL, 0, diff_opt_output }, - + { + .type = OPTION_CALLBACK, + .long_name = "output", + .value = options, + .argh = N_("<file>"), + .help = N_("output to a specific file"), + .flags = PARSE_OPT_NONEG, + .ll_callback = diff_opt_output, + }, OPT_END() }; @@ -6647,8 +6654,8 @@ static void create_filepairs_for_header_only_notifications(struct diff_options * one = alloc_filespec(e->key); two = alloc_filespec(e->key); - fill_filespec(one, null_oid(), 0, 0); - fill_filespec(two, null_oid(), 0, 0); + fill_filespec(one, null_oid(the_hash_algo), 0, 0); + fill_filespec(two, null_oid(the_hash_algo), 0, 0); p = diff_queue(q, one, two); p->status = DIFF_STATUS_MODIFIED; } @@ -7085,7 +7092,7 @@ void diffcore_std(struct diff_options *options) diffcore_order(options->orderfile); if (options->rotate_to) diffcore_rotate(options); - if (!options->found_follow) + if (!options->found_follow && !options->skip_resolving_statuses) /* See try_to_follow_renames() in tree-diff.c */ diff_resolve_rename_copy(); diffcore_apply_filter(options); @@ -7161,16 +7168,19 @@ void compute_diffstat(struct diff_options *options, options->found_changes = !!diffstat->nr; } -void diff_addremove(struct diff_options *options, - int addremove, unsigned mode, - const struct object_id *oid, - int oid_valid, - const char *concatpath, unsigned dirty_submodule) +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue, + struct diff_options *options, + int addremove, unsigned mode, + const struct object_id *oid, + int oid_valid, + const char *concatpath, + unsigned dirty_submodule) { struct diff_filespec *one, *two; + struct diff_filepair *pair; if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options)) - return; + return NULL; /* This may look odd, but it is a preparation for * feeding "there are unchanged files which should @@ -7190,7 +7200,7 @@ void diff_addremove(struct diff_options *options, if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) - return; + return NULL; one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); @@ -7202,25 +7212,29 @@ void diff_addremove(struct diff_options *options, two->dirty_submodule = dirty_submodule; } - diff_queue(&diff_queued_diff, one, two); + pair = diff_queue(queue, one, two); if (!options->flags.diff_from_contents) options->flags.has_changes = 1; + + return pair; } -void diff_change(struct diff_options *options, - unsigned old_mode, unsigned new_mode, - const struct object_id *old_oid, - const struct object_id *new_oid, - int old_oid_valid, int new_oid_valid, - const char *concatpath, - unsigned old_dirty_submodule, unsigned new_dirty_submodule) +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue, + struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *concatpath, + unsigned old_dirty_submodule, + unsigned new_dirty_submodule) { struct diff_filespec *one, *two; struct diff_filepair *p; if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) && is_submodule_ignored(concatpath, options)) - return; + return NULL; if (options->flags.reverse_diff) { SWAP(old_mode, new_mode); @@ -7231,7 +7245,7 @@ void diff_change(struct diff_options *options, if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) - return; + return NULL; one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); @@ -7239,19 +7253,42 @@ void diff_change(struct diff_options *options, fill_filespec(two, new_oid, new_oid_valid, new_mode); one->dirty_submodule = old_dirty_submodule; two->dirty_submodule = new_dirty_submodule; - p = diff_queue(&diff_queued_diff, one, two); + p = diff_queue(queue, one, two); if (options->flags.diff_from_contents) - return; + return p; if (options->flags.quick && options->skip_stat_unmatch && !diff_filespec_check_stat_unmatch(options->repo, p)) { diff_free_filespec_data(p->one); diff_free_filespec_data(p->two); - return; + return p; } options->flags.has_changes = 1; + + return p; +} + +void diff_addremove(struct diff_options *options, int addremove, unsigned mode, + const struct object_id *oid, int oid_valid, + const char *concatpath, unsigned dirty_submodule) +{ + diff_queue_addremove(&diff_queued_diff, options, addremove, mode, oid, + oid_valid, concatpath, dirty_submodule); +} + +void diff_change(struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *concatpath, + unsigned old_dirty_submodule, unsigned new_dirty_submodule) +{ + diff_queue_change(&diff_queued_diff, options, old_mode, new_mode, + old_oid, new_oid, old_oid_valid, new_oid_valid, + concatpath, old_dirty_submodule, new_dirty_submodule); } struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path) @@ -353,6 +353,14 @@ struct diff_options { /* to support internal diff recursion by --follow hack*/ int found_follow; + /* + * By default, diffcore_std() resolves the statuses for queued diff file + * pairs by calling diff_resolve_rename_copy(). If status information + * has already been manually set, this option prevents diffcore_std() + * from resetting statuses. + */ + int skip_resolving_statuses; + /* Callback which allows tweaking the options in diff_setup_done(). */ void (*set_default)(struct diff_options *); @@ -508,6 +516,31 @@ void diff_set_default_prefix(struct diff_options *options); int diff_can_quit_early(struct diff_options *); +/* + * Stages changes in the provided diff queue for file additions and deletions. + * If a file pair gets queued, it is returned. + */ +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue, + struct diff_options *, + int addremove, unsigned mode, + const struct object_id *oid, + int oid_valid, const char *fullpath, + unsigned dirty_submodule); + +/* + * Stages changes in the provided diff queue for file modifications. + * If a file pair gets queued, it is returned. + */ +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue, + struct diff_options *, + unsigned mode1, unsigned mode2, + const struct object_id *old_oid, + const struct object_id *new_oid, + int old_oid_valid, int new_oid_valid, + const char *fullpath, + unsigned dirty_submodule1, + unsigned dirty_submodule2); + void diff_addremove(struct diff_options *, int addremove, unsigned mode, @@ -656,7 +689,7 @@ void flush_one_hunk(struct object_id *result, struct git_hash_ctx *ctx); int diff_result_code(struct rev_info *); -int diff_no_index(struct rev_info *, +int diff_no_index(struct rev_info *, const struct git_hash_algo *algop, int implicit_no_index, int, const char **); int index_differs_from(struct repository *r, const char *def, diff --git a/diffcore-rename.c b/diffcore-rename.c index 91b77993c7..7723bc3334 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -8,7 +8,7 @@ #include "git-compat-util.h" #include "diff.h" #include "diffcore.h" -#include "object-store-ll.h" +#include "object-file.h" #include "hashmap.h" #include "mem-pool.h" #include "oid-array.h" @@ -33,7 +33,7 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filepair *p) { /* Lookup by p->ONE->path */ int idx = break_idx ? strintmap_get(break_idx, p->one->path) : -1; - return (idx == -1) ? NULL : &rename_dst[idx]; + return (idx == -1 || idx == rename_dst_nr) ? NULL : &rename_dst[idx]; } /* @@ -1406,7 +1406,7 @@ void diffcore_rename_extended(struct diff_options *options, trace2_region_enter("diff", "setup", options->repo); info.setup = 0; - assert(!dir_rename_count || strmap_empty(dir_rename_count)); + ASSERT(!dir_rename_count || strmap_empty(dir_rename_count)); want_copies = (detect_rename == DIFF_DETECT_COPY); if (dirs_removed && (break_idx || want_copies)) BUG("dirs_removed incompatible with break/copy detection"); @@ -1669,9 +1669,10 @@ void diffcore_rename_extended(struct diff_options *options, if (DIFF_PAIR_BROKEN(p)) { /* broken delete */ struct diff_rename_dst *dst = locate_rename_dst(p); - if (!dst) - BUG("tracking failed somehow; failed to find associated dst for broken pair"); - if (dst->is_rename) + if (options->single_follow && dst && + strcmp(dst->p->two->path, p->two->path)) + dst = NULL; + if (dst && dst->is_rename) /* counterpart is now rename/copy */ pair_to_free = p; } diff --git a/dir-iterator.c b/dir-iterator.c index de619846f2..857e1d9bda 100644 --- a/dir-iterator.c +++ b/dir-iterator.c @@ -193,9 +193,9 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) if (S_ISDIR(iter->base.st.st_mode) && push_level(iter)) { if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) - goto error_out; + return ITER_ERROR; if (iter->levels_nr == 0) - goto error_out; + return ITER_ERROR; } /* Loop until we find an entry that we can give back to the caller. */ @@ -211,11 +211,11 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) int ret = next_directory_entry(level->dir, iter->base.path.buf, &de); if (ret < 0) { if (iter->flags & DIR_ITERATOR_PEDANTIC) - goto error_out; + return ITER_ERROR; continue; } else if (ret > 0) { if (pop_level(iter) == 0) - return dir_iterator_abort(dir_iterator); + return ITER_DONE; continue; } @@ -223,7 +223,7 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) } else { if (level->entries_idx >= level->entries.nr) { if (pop_level(iter) == 0) - return dir_iterator_abort(dir_iterator); + return ITER_DONE; continue; } @@ -232,22 +232,21 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator) if (prepare_next_entry_data(iter, name)) { if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC) - goto error_out; + return ITER_ERROR; continue; } return ITER_OK; } - -error_out: - dir_iterator_abort(dir_iterator); - return ITER_ERROR; } -int dir_iterator_abort(struct dir_iterator *dir_iterator) +void dir_iterator_free(struct dir_iterator *dir_iterator) { struct dir_iterator_int *iter = (struct dir_iterator_int *)dir_iterator; + if (!iter) + return; + for (; iter->levels_nr; iter->levels_nr--) { struct dir_iterator_level *level = &iter->levels[iter->levels_nr - 1]; @@ -266,7 +265,6 @@ int dir_iterator_abort(struct dir_iterator *dir_iterator) free(iter->levels); strbuf_release(&iter->base.path); free(iter); - return ITER_DONE; } struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) @@ -301,7 +299,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags) return dir_iterator; error_out: - dir_iterator_abort(dir_iterator); + dir_iterator_free(dir_iterator); errno = saved_errno; return NULL; } diff --git a/dir-iterator.h b/dir-iterator.h index 6d438809b6..ccd6a19734 100644 --- a/dir-iterator.h +++ b/dir-iterator.h @@ -28,7 +28,7 @@ * * while ((ok = dir_iterator_advance(iter)) == ITER_OK) { * if (want_to_stop_iteration()) { - * ok = dir_iterator_abort(iter); + * ok = ITER_DONE; * break; * } * @@ -39,6 +39,7 @@ * * if (ok != ITER_DONE) * handle_error(); + * dir_iterator_free(iter); * * Callers are allowed to modify iter->path while they are working, * but they must restore it to its original contents before calling @@ -107,11 +108,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags); */ int dir_iterator_advance(struct dir_iterator *iterator); -/* - * End the iteration before it has been exhausted. Free the - * dir_iterator and any associated resources and return ITER_DONE. On - * error, free the dir_iterator and return ITER_ERROR. - */ -int dir_iterator_abort(struct dir_iterator *iterator); +/* Free the dir_iterator and any associated resources. */ +void dir_iterator_free(struct dir_iterator *iterator); #endif @@ -18,7 +18,6 @@ #include "gettext.h" #include "name-hash.h" #include "object-file.h" -#include "object-store-ll.h" #include "path.h" #include "refs.h" #include "repository.h" @@ -398,9 +397,12 @@ static int match_pathspec_item(struct index_state *istate, strncmp(item->match, name - prefix, item->prefix)) return 0; - if (item->attr_match_nr && - !match_pathspec_attrs(istate, name - prefix, namelen + prefix, item)) - return 0; + if (item->attr_match_nr) { + if (!istate) + BUG("magic PATHSPEC_ATTR requires an index"); + if (!match_pathspec_attrs(istate, name - prefix, namelen + prefix, item)) + return 0; + } /* If the match was just the prefix, we matched */ if (!*match) @@ -519,7 +521,8 @@ static int do_match_pathspec(struct index_state *istate, ( exclude && !(ps->items[i].magic & PATHSPEC_EXCLUDE))) continue; - if (seen && seen[i] == MATCHED_EXACTLY) + if (seen && seen[i] == MATCHED_EXACTLY && + ps->items[i].nowildcard_len == ps->items[i].len) continue; /* * Make exclude patterns optional and never report @@ -577,6 +580,16 @@ int match_pathspec(struct index_state *istate, prefix, seen, flags); } +int match_leading_pathspec(struct index_state *istate, + const struct pathspec *ps, + const char *name, int namelen, + int prefix, char *seen, int is_dir) +{ + unsigned flags = is_dir ? DO_MATCH_DIRECTORY | DO_MATCH_LEADING_PATHSPEC : 0; + return match_pathspec_with_flags(istate, ps, name, namelen, + prefix, seen, flags); +} + /** * Check if a submodule is a superset of the pathspec */ @@ -4035,7 +4048,7 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree, */ i++; - sub = submodule_from_path(&subrepo, null_oid(), ce->name); + sub = submodule_from_path(&subrepo, null_oid(the_hash_algo), ce->name); if (!sub || !is_submodule_active(&subrepo, ce->name)) /* .gitmodules broken or inactive sub */ continue; @@ -4063,12 +4076,12 @@ void connect_work_tree_and_git_dir(const char *work_tree_, /* Prepare .git file */ strbuf_addf(&gitfile_sb, "%s/.git", work_tree_); - if (safe_create_leading_directories_const(gitfile_sb.buf)) + if (safe_create_leading_directories_const(the_repository, gitfile_sb.buf)) die(_("could not create directories for %s"), gitfile_sb.buf); /* Prepare config file */ strbuf_addf(&cfg_sb, "%s/config", git_dir_); - if (safe_create_leading_directories_const(cfg_sb.buf)) + if (safe_create_leading_directories_const(the_repository, cfg_sb.buf)) die(_("could not create directories for %s"), cfg_sb.buf); git_dir = real_pathdup(git_dir_, 1); @@ -43,7 +43,6 @@ struct repository; * */ -struct repository; struct dir_entry { unsigned int len; @@ -1,7 +1,7 @@ #define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" -#include "object-store-ll.h" +#include "object-store.h" #include "dir.h" #include "environment.h" #include "gettext.h" diff --git a/environment.c b/environment.c index 9e4c7781be..7bf0390a33 100644 --- a/environment.c +++ b/environment.c @@ -49,7 +49,6 @@ int fsync_object_files = -1; int use_fsync = -1; enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT; enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT; -unsigned long big_file_threshold = 512 * 1024 * 1024; char *editor_program; char *askpass_program; char *excludes_file; @@ -82,6 +81,16 @@ int max_allowed_tree_depth = * the stack overflow can occur. */ 512; +#elif defined(GIT_WINDOWS_NATIVE) && defined(__clang__) && defined(__aarch64__) + /* + * Similar to Visual C, it seems that on Windows/ARM64 the clang-based + * builds have a smaller stack space available. When running out of + * that stack space, a `STATUS_STACK_OVERFLOW` is produced. When the + * Git command was run from an MSYS2 Bash, this unfortunately results + * in an exit code 127. Let's prevent that by lowering the maximal + * tree depth; This value seems to be low enough. + */ + 1280; #else 2048; #endif @@ -104,10 +113,7 @@ const char *comment_line_str = "#"; char *comment_line_str_to_free; int auto_comment_line_char; -/* Parallel index stat data preload? */ -int core_preload_index = 1; - -/* This is set by setup_git_dir_gently() and/or git_default_config() */ +/* This is set by setup_git_directory_gently() and/or git_default_config() */ char *git_work_tree_cfg; /* diff --git a/environment.h b/environment.h index 45e690f203..9a3d05d414 100644 --- a/environment.h +++ b/environment.h @@ -152,13 +152,9 @@ extern char *apply_default_ignorewhitespace; extern char *git_attributes_file; extern int zlib_compression_level; extern int pack_compression_level; -extern size_t packed_git_window_size; -extern size_t packed_git_limit; -extern unsigned long big_file_threshold; extern unsigned long pack_size_limit_cfg; extern int max_allowed_tree_depth; -extern int core_preload_index; extern int precomposed_unicode; extern int protect_hfs; extern int protect_ntfs; diff --git a/ewah/ewah_bitmap.c b/ewah/ewah_bitmap.c index 67f8f588e0..056c410efb 100644 --- a/ewah/ewah_bitmap.c +++ b/ewah/ewah_bitmap.c @@ -371,6 +371,39 @@ void ewah_iterator_init(struct ewah_iterator *it, struct ewah_bitmap *parent) read_new_rlw(it); } +void ewah_or_iterator_init(struct ewah_or_iterator *it, + struct ewah_bitmap **parents, size_t nr) +{ + size_t i; + + memset(it, 0, sizeof(*it)); + + ALLOC_ARRAY(it->its, nr); + for (i = 0; i < nr; i++) + ewah_iterator_init(&it->its[it->nr++], parents[i]); +} + +int ewah_or_iterator_next(eword_t *next, struct ewah_or_iterator *it) +{ + eword_t buf, out = 0; + size_t i; + int ret = 0; + + for (i = 0; i < it->nr; i++) + if (ewah_iterator_next(&buf, &it->its[i])) { + out |= buf; + ret = 1; + } + + *next = out; + return ret; +} + +void ewah_or_iterator_release(struct ewah_or_iterator *it) +{ + free(it->its); +} + void ewah_xor( struct ewah_bitmap *ewah_i, struct ewah_bitmap *ewah_j, diff --git a/ewah/ewok.h b/ewah/ewok.h index 5e357e2493..c29d354236 100644 --- a/ewah/ewok.h +++ b/ewah/ewok.h @@ -148,6 +148,18 @@ void ewah_iterator_init(struct ewah_iterator *it, struct ewah_bitmap *parent); */ int ewah_iterator_next(eword_t *next, struct ewah_iterator *it); +struct ewah_or_iterator { + struct ewah_iterator *its; + size_t nr; +}; + +void ewah_or_iterator_init(struct ewah_or_iterator *it, + struct ewah_bitmap **parents, size_t nr); + +int ewah_or_iterator_next(eword_t *next, struct ewah_or_iterator *it); + +void ewah_or_iterator_release(struct ewah_or_iterator *it); + void ewah_xor( struct ewah_bitmap *ewah_i, struct ewah_bitmap *ewah_j, diff --git a/fetch-pack.c b/fetch-pack.c index 1ed5e11dd5..fa4231fee7 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -24,7 +24,7 @@ #include "oid-array.h" #include "oidset.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "connected.h" #include "fetch-negotiator.h" @@ -769,9 +769,7 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator, if (!commit) { struct object *o; - if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid, - OBJECT_INFO_QUICK | - OBJECT_INFO_SKIP_FETCH_OBJECT)) + if (!has_object(the_repository, &ref->old_oid, 0)) continue; o = parse_object(the_repository, &ref->old_oid); if (!o || o->type != OBJ_COMMIT) @@ -1985,7 +1983,8 @@ static void update_shallow(struct fetch_pack_args *args, struct oid_array extra = OID_ARRAY_INIT; struct object_id *oid = si->shallow->oid; for (i = 0; i < si->shallow->nr; i++) - if (repo_has_object_file(the_repository, &oid[i])) + if (has_object(the_repository, &oid[i], + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) oid_array_append(&extra, &oid[i]); if (extra.nr) { setup_alternate_shallow(&shallow_lock, diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c index 5b63c3b088..501b5acdd4 100644 --- a/fmt-merge-msg.c +++ b/fmt-merge-msg.c @@ -6,7 +6,7 @@ #include "environment.h" #include "refs.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "diff.h" #include "diff-merges.h" #include "hex.h" @@ -4,7 +4,7 @@ #include "date.h" #include "dir.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "repository.h" #include "object.h" @@ -30,6 +30,8 @@ enum fsck_msg_type { FUNC(BAD_EMAIL, ERROR) \ FUNC(BAD_NAME, ERROR) \ FUNC(BAD_OBJECT_SHA1, ERROR) \ + FUNC(BAD_PACKED_REF_ENTRY, ERROR) \ + FUNC(BAD_PACKED_REF_HEADER, ERROR) \ FUNC(BAD_PARENT_SHA1, ERROR) \ FUNC(BAD_REF_CONTENT, ERROR) \ FUNC(BAD_REF_FILETYPE, ERROR) \ @@ -53,6 +55,8 @@ enum fsck_msg_type { FUNC(MISSING_TYPE, ERROR) \ FUNC(MISSING_TYPE_ENTRY, ERROR) \ FUNC(MULTIPLE_AUTHORS, ERROR) \ + FUNC(PACKED_REF_ENTRY_NOT_TERMINATED, ERROR) \ + FUNC(PACKED_REF_UNSORTED, ERROR) \ FUNC(TREE_NOT_SORTED, ERROR) \ FUNC(UNKNOWN_TYPE, ERROR) \ FUNC(ZERO_PADDED_DATE, ERROR) \ @@ -80,6 +84,7 @@ enum fsck_msg_type { FUNC(LARGE_PATHNAME, WARN) \ /* infos (reported as warnings, but ignored by default) */ \ FUNC(BAD_FILEMODE, INFO) \ + FUNC(EMPTY_PACKED_REFS_FILE, INFO) \ FUNC(GITMODULES_PARSE, INFO) \ FUNC(GITIGNORE_SYMLINK, INFO) \ FUNC(GITATTRIBUTES_SYMLINK, INFO) \ diff --git a/generate-configlist.sh b/generate-configlist.sh index dffdaada8b..75c39ade20 100755 --- a/generate-configlist.sh +++ b/generate-configlist.sh @@ -13,10 +13,17 @@ print_config_list () { cat <<EOF static const char *config_name_list[] = { EOF - grep -h '^[a-zA-Z].*\..*::$' "$SOURCE_DIR"/Documentation/*config.adoc "$SOURCE_DIR"/Documentation/config/*.adoc | - sed '/deprecated/d; s/::$//; s/, */\n/g' | - sort | - sed 's/^.*$/ "&",/' + sed -e ' + /^`*[a-zA-Z].*\..*`*::$/ { + /deprecated/d; + s/::$//; + s/`//g; + s/^.*$/ "&",/; + p;}; + d' \ + "$SOURCE_DIR"/Documentation/*config.adoc \ + "$SOURCE_DIR"/Documentation/config/*.adoc | + sort cat <<EOF NULL, }; diff --git a/git-compat-util.h b/git-compat-util.h index 21cab99567..5bd69ec040 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -23,26 +23,9 @@ #include <crtdbg.h> #endif -struct strbuf; - - -#define _FILE_OFFSET_BITS 64 +#include "compat/posix.h" - -/* Derived from Linux "Features Test Macro" header - * Convenience macros to test the versions of gcc (or - * a compatible compiler). - * Use them like this: - * #if GIT_GNUC_PREREQ (2,8) - * ... code requiring gcc 2.8 or later ... - * #endif -*/ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) -# define GIT_GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -#else - #define GIT_GNUC_PREREQ(maj, min) 0 -#endif +struct strbuf; #if defined(__GNUC__) || defined(__clang__) # define PRAGMA(pragma) _Pragma(#pragma) @@ -110,12 +93,19 @@ DISABLE_WARNING(-Wsign-compare) # define BARF_UNLESS_COPYABLE(dst, src) \ BUILD_ASSERT_OR_ZERO(__builtin_types_compatible_p(__typeof__(*(dst)), \ __typeof__(*(src)))) + +# define BARF_UNLESS_SIGNED(var) BUILD_ASSERT_OR_ZERO(((__typeof__(var)) -1) < 0) +# define BARF_UNLESS_UNSIGNED(var) BUILD_ASSERT_OR_ZERO(((__typeof__(var)) -1) > 0) #else # define BARF_UNLESS_AN_ARRAY(arr) 0 # define BARF_UNLESS_COPYABLE(dst, src) \ BUILD_ASSERT_OR_ZERO(0 ? ((*(dst) = *(src)), 0) : \ sizeof(*(dst)) == sizeof(*(src))) + +# define BARF_UNLESS_SIGNED(var) 0 +# define BARF_UNLESS_UNSIGNED(var) 0 #endif + /* * ARRAY_SIZE - get the number of elements in a visible array * @x: the array whose size you want. @@ -176,71 +166,6 @@ DISABLE_WARNING(-Wsign-compare) /* Approximation of the length of the decimal representation of this type. */ #define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) -#ifdef __MINGW64__ -#define _POSIX_C_SOURCE 1 -#elif defined(__sun__) - /* - * On Solaris, when _XOPEN_EXTENDED is set, its header file - * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE - * setting to say we are XPG5 or XPG6. Also on Solaris, - * XPG6 programs must be compiled with a c99 compiler, while - * non XPG6 programs must be compiled with a pre-c99 compiler. - */ -# if __STDC_VERSION__ - 0 >= 199901L -# define _XOPEN_SOURCE 600 -# else -# define _XOPEN_SOURCE 500 -# endif -#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \ - !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \ - !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \ - !defined(__CYGWIN__) -#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */ -#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */ -#endif -#define _ALL_SOURCE 1 -#define _GNU_SOURCE 1 -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#define _NETBSD_SOURCE 1 -#define _SGI_SOURCE 1 - -/* - * UNUSED marks a function parameter that is always unused. It also - * can be used to annotate a function, a variable, or a type that is - * always unused. - * - * A callback interface may dictate that a function accepts a - * parameter at that position, but the implementation of the function - * may not need to use the parameter. In such a case, mark the parameter - * with UNUSED. - * - * When a parameter may be used or unused, depending on conditional - * compilation, consider using MAYBE_UNUSED instead. - */ -#if GIT_GNUC_PREREQ(4, 5) -#define UNUSED __attribute__((unused)) \ - __attribute__((deprecated ("parameter declared as UNUSED"))) -#elif defined(__GNUC__) -#define UNUSED __attribute__((unused)) \ - __attribute__((deprecated)) -#else -#define UNUSED -#endif - -#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */ -# if !defined(_WIN32_WINNT) -# define _WIN32_WINNT 0x0600 -# endif -#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */ -#include <winsock2.h> -#ifndef NO_UNIX_SOCKETS -#include <afunix.h> -#endif -#include <windows.h> -#define GIT_WINDOWS_NATIVE -#endif - #if defined(NO_UNIX_SOCKETS) || !defined(GIT_WINDOWS_NATIVE) static inline int _have_unix_sockets(void) { @@ -253,45 +178,6 @@ static inline int _have_unix_sockets(void) #define have_unix_sockets _have_unix_sockets #endif -#include <unistd.h> -#include <stdio.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stddef.h> -#include <stdlib.h> -#include <stdarg.h> -#include <stdbool.h> -#include <string.h> -#ifdef HAVE_STRINGS_H -#include <strings.h> /* for strcasecmp() */ -#endif -#include <errno.h> -#include <limits.h> -#include <locale.h> -#ifdef NEEDS_SYS_PARAM_H -#include <sys/param.h> -#endif -#include <sys/types.h> -#include <dirent.h> -#include <sys/time.h> -#include <time.h> -#include <signal.h> -#include <assert.h> -#include <regex.h> -#include <utime.h> -#include <syslog.h> -#if !defined(NO_POLL_H) -#include <poll.h> -#elif !defined(NO_SYS_POLL_H) -#include <sys/poll.h> -#else -/* Pull the compat stuff */ -#include <poll.h> -#endif -#ifdef HAVE_BSD_SYSCTL -#include <sys/sysctl.h> -#endif - /* Used by compat/win32/path-utils.h, and more */ static inline int is_xplatform_dir_sep(int c) { @@ -308,48 +194,6 @@ static inline int is_xplatform_dir_sep(int c) #elif defined(_MSC_VER) #include "compat/win32/path-utils.h" #include "compat/msvc.h" -#else -#include <sys/utsname.h> -#include <sys/wait.h> -#include <sys/resource.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/statvfs.h> -#include <termios.h> -#ifndef NO_SYS_SELECT_H -#include <sys/select.h> -#endif -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <pwd.h> -#include <sys/un.h> -#ifndef NO_INTTYPES_H -#include <inttypes.h> -#else -#include <stdint.h> -#endif -#ifdef HAVE_ARC4RANDOM_LIBBSD -#include <bsd/stdlib.h> -#endif -#ifdef HAVE_GETRANDOM -#include <sys/random.h> -#endif -#ifdef NO_INTPTR_T -/* - * On I16LP32, ILP32 and LP64 "long" is the safe bet, however - * on LLP86, IL33LLP64 and P64 it needs to be "long long", - * while on IP16 and IP16L32 it is "int" (resp. "short") - * Size needs to match (or exceed) 'sizeof(void *)'. - * We can't take "long long" here as not everybody has it. - */ -typedef long intptr_t; -typedef unsigned long uintptr_t; -#endif -#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */ -#include <grp.h> -#define _ALL_SOURCE 1 #endif /* used on Mac OS X */ @@ -370,60 +214,6 @@ static inline const char *precompose_string_if_needed(const char *in) #define probe_utf8_pathname_composition() #endif -#ifdef MKDIR_WO_TRAILING_SLASH -#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b)) -int compat_mkdir_wo_trailing_slash(const char*, mode_t); -#endif - -#ifdef time -#undef time -#endif -static inline time_t git_time(time_t *tloc) -{ - struct timeval tv; - - /* - * Avoid time(NULL), which can disagree with gettimeofday(2) - * and filesystem timestamps. - */ - gettimeofday(&tv, NULL); - - if (tloc) - *tloc = tv.tv_sec; - return tv.tv_sec; -} -#define time git_time - -#ifdef NO_STRUCT_ITIMERVAL -struct itimerval { - struct timeval it_interval; - struct timeval it_value; -}; -#endif - -#ifdef NO_SETITIMER -static inline int git_setitimer(int which UNUSED, - const struct itimerval *value UNUSED, - struct itimerval *newvalue UNUSED) { - return 0; /* pretend success */ -} -#undef setitimer -#define setitimer(which,value,ovalue) git_setitimer(which,value,ovalue) -#endif - -#ifndef NO_LIBGEN_H -#include <libgen.h> -#else -#define basename gitbasename -char *gitbasename(char *); -#define dirname gitdirname -char *gitdirname(char *); -#endif - -#ifndef NO_ICONV -#include <iconv.h> -#endif - #ifndef NO_OPENSSL #ifdef __APPLE__ #undef __AVAILABILITY_MACROS_USES_AVAILABILITY @@ -441,34 +231,6 @@ char *gitdirname(char *); # include <sys/sysinfo.h> #endif -/* On most systems <netdb.h> would have given us this, but - * not on some systems (e.g. z/OS). - */ -#ifndef NI_MAXHOST -#define NI_MAXHOST 1025 -#endif - -#ifndef NI_MAXSERV -#define NI_MAXSERV 32 -#endif - -/* On most systems <limits.h> would have given us this, but - * not on some systems (e.g. GNU/Hurd). - */ -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif - -#ifndef NAME_MAX -#define NAME_MAX 255 -#endif - -typedef uintmax_t timestamp_t; -#define PRItime PRIuMAX -#define parse_timestamp strtoumax -#define TIME_MAX UINTMAX_MAX -#define TIME_MIN 0 - #ifndef PATH_SEP #define PATH_SEP ':' #endif @@ -492,11 +254,6 @@ static inline int noop_core_config(const char *var UNUSED, #define platform_core_config noop_core_config #endif -int lstat_cache_aware_rmdir(const char *path); -#if !defined(__MINGW32__) && !defined(_MSC_VER) -#define rmdir lstat_cache_aware_rmdir -#endif - #ifndef has_dos_drive_prefix static inline int git_has_dos_drive_prefix(const char *path UNUSED) { @@ -826,25 +583,6 @@ static inline bool strip_suffix(const char *str, const char *suffix, memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \ } while (0) -#if defined(NO_MMAP) || defined(USE_WIN32_MMAP) - -#ifndef PROT_READ -#define PROT_READ 1 -#define PROT_WRITE 2 -#define MAP_PRIVATE 1 -#endif - -#define mmap git_mmap -#define munmap git_munmap -void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); -int git_munmap(void *start, size_t length); - -#else /* NO_MMAP || USE_WIN32_MMAP */ - -#include <sys/mman.h> - -#endif /* NO_MMAP || USE_WIN32_MMAP */ - #ifdef NO_MMAP /* This value must be multiple of (pagesize * 2) */ @@ -860,176 +598,17 @@ int git_munmap(void *start, size_t length); #endif /* NO_MMAP */ -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - #ifdef NO_ST_BLOCKS_IN_STRUCT_STAT #define on_disk_bytes(st) ((st).st_size) #else #define on_disk_bytes(st) ((st).st_blocks * 512) #endif -#ifdef NEEDS_MODE_TRANSLATION -#undef S_IFMT -#undef S_IFREG -#undef S_IFDIR -#undef S_IFLNK -#undef S_IFBLK -#undef S_IFCHR -#undef S_IFIFO -#undef S_IFSOCK -#define S_IFMT 0170000 -#define S_IFREG 0100000 -#define S_IFDIR 0040000 -#define S_IFLNK 0120000 -#define S_IFBLK 0060000 -#define S_IFCHR 0020000 -#define S_IFIFO 0010000 -#define S_IFSOCK 0140000 -#ifdef stat -#undef stat -#endif -#define stat(path, buf) git_stat(path, buf) -int git_stat(const char *, struct stat *); -#ifdef fstat -#undef fstat -#endif -#define fstat(fd, buf) git_fstat(fd, buf) -int git_fstat(int, struct stat *); -#ifdef lstat -#undef lstat -#endif -#define lstat(path, buf) git_lstat(path, buf) -int git_lstat(const char *, struct stat *); -#endif - #define DEFAULT_PACKED_GIT_LIMIT \ ((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256)) -#ifdef NO_PREAD -#define pread git_pread -ssize_t git_pread(int fd, void *buf, size_t count, off_t offset); -#endif - -#ifdef NO_SETENV -#define setenv gitsetenv -int gitsetenv(const char *, const char *, int); -#endif - -#ifdef NO_MKDTEMP -#define mkdtemp gitmkdtemp -char *gitmkdtemp(char *); -#endif - -#ifdef NO_UNSETENV -#define unsetenv gitunsetenv -int gitunsetenv(const char *); -#endif - -#ifdef NO_STRCASESTR -#define strcasestr gitstrcasestr -char *gitstrcasestr(const char *haystack, const char *needle); -#endif - -#ifdef NO_STRLCPY -#define strlcpy gitstrlcpy -size_t gitstrlcpy(char *, const char *, size_t); -#endif - -#ifdef NO_STRTOUMAX -#define strtoumax gitstrtoumax -uintmax_t gitstrtoumax(const char *, char **, int); -#define strtoimax gitstrtoimax -intmax_t gitstrtoimax(const char *, char **, int); -#endif - -#ifdef NO_HSTRERROR -#define hstrerror githstrerror -const char *githstrerror(int herror); -#endif - -#ifdef NO_MEMMEM -#define memmem gitmemmem -void *gitmemmem(const void *haystack, size_t haystacklen, - const void *needle, size_t needlelen); -#endif - -#ifdef OVERRIDE_STRDUP -#ifdef strdup -#undef strdup -#endif -#define strdup gitstrdup -char *gitstrdup(const char *s); -#endif - -#ifdef NO_GETPAGESIZE -#define getpagesize() sysconf(_SC_PAGESIZE) -#endif - -#ifndef O_CLOEXEC -#define O_CLOEXEC 0 -#endif - -#ifdef FREAD_READS_DIRECTORIES -# if !defined(SUPPRESS_FOPEN_REDEFINITION) -# ifdef fopen -# undef fopen -# endif -# define fopen(a,b) git_fopen(a,b) -# endif -FILE *git_fopen(const char*, const char*); -#endif - -#ifdef SNPRINTF_RETURNS_BOGUS -#ifdef snprintf -#undef snprintf -#endif -#define snprintf git_snprintf -int git_snprintf(char *str, size_t maxsize, - const char *format, ...); -#ifdef vsnprintf -#undef vsnprintf -#endif -#define vsnprintf git_vsnprintf -int git_vsnprintf(char *str, size_t maxsize, - const char *format, va_list ap); -#endif - -#ifdef OPEN_RETURNS_EINTR -#undef open -#define open git_open_with_retry -int git_open_with_retry(const char *path, int flag, ...); -#endif - -#ifdef __GLIBC_PREREQ -#if __GLIBC_PREREQ(2, 1) -#define HAVE_STRCHRNUL -#endif -#endif - -#ifndef HAVE_STRCHRNUL -#define strchrnul gitstrchrnul -static inline char *gitstrchrnul(const char *s, int c) -{ - while (*s && *s != c) - s++; - return (char *)s; -} -#endif - -#ifdef NO_INET_PTON -int inet_pton(int af, const char *src, void *dst); -#endif - -#ifdef NO_INET_NTOP -const char *inet_ntop(int af, const void *src, char *dst, size_t size); -#endif - -#ifdef NO_PTHREADS -#define atexit git_atexit -int git_atexit(void (*handler)(void)); -#endif +int git_open_cloexec(const char *name, int flags); +#define git_open(name) git_open_cloexec(name, O_RDONLY) static inline size_t st_add(size_t a, size_t b) { @@ -1091,6 +670,22 @@ static inline int cast_size_t_to_int(size_t a) return (int)a; } +static inline uint64_t u64_mult(uint64_t a, uint64_t b) +{ + if (unsigned_mult_overflows(a, b)) + die("uint64_t overflow: %"PRIuMAX" * %"PRIuMAX, + (uintmax_t)a, (uintmax_t)b); + return a * b; +} + +static inline uint64_t u64_add(uint64_t a, uint64_t b) +{ + if (unsigned_add_overflows(a, b)) + die("uint64_t overflow: %"PRIuMAX" + %"PRIuMAX, + (uintmax_t)a, (uintmax_t)b); + return a + b; +} + /* * Limit size of IO chunks, because huge chunks only cause pain. OS X * 64-bit is buggy, returning EINVAL if len >= INT_MAX; and even in @@ -1297,12 +892,6 @@ static inline size_t xsize_t(off_t len) return (size_t) len; } -#ifndef HOST_NAME_MAX -#define HOST_NAME_MAX 256 -#endif - -#include "sane-ctype.h" - /* * Like skip_prefix, but compare case-insensitively. Note that the comparison * is done via tolower(), so it is strictly ASCII (no multi-byte characters or @@ -1368,34 +957,6 @@ static inline int strtol_i(char const *s, int base, int *result) return 0; } -void git_stable_qsort(void *base, size_t nmemb, size_t size, - int(*compar)(const void *, const void *)); -#ifdef INTERNAL_QSORT -#define qsort git_stable_qsort -#endif - -#define QSORT(base, n, compar) sane_qsort((base), (n), sizeof(*(base)), compar) -static inline void sane_qsort(void *base, size_t nmemb, size_t size, - int(*compar)(const void *, const void *)) -{ - if (nmemb > 1) - qsort(base, nmemb, size, compar); -} - -#define STABLE_QSORT(base, n, compar) \ - git_stable_qsort((base), (n), sizeof(*(base)), compar) - -#ifndef HAVE_ISO_QSORT_S -int git_qsort_s(void *base, size_t nmemb, size_t size, - int (*compar)(const void *, const void *, void *), void *ctx); -#define qsort_s git_qsort_s -#endif - -#define QSORT_S(base, n, compar, ctx) do { \ - if (qsort_s((base), (n), sizeof(*(base)), compar, ctx)) \ - BUG("qsort_s() failed"); \ -} while (0) - #ifndef REG_STARTEND #error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd" #endif @@ -1420,39 +981,12 @@ int git_regcomp(regex_t *preg, const char *pattern, int cflags); # define FORCE_DIR_SET_GID 0 #endif -#ifdef NO_NSEC -#undef USE_NSEC -#define ST_CTIME_NSEC(st) 0 -#define ST_MTIME_NSEC(st) 0 -#else -#ifdef USE_ST_TIMESPEC -#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec)) -#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec)) -#else -#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec)) -#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec)) -#endif -#endif - #ifdef UNRELIABLE_FSTAT #define fstat_is_reliable() 0 #else #define fstat_is_reliable() 1 #endif -#ifndef va_copy -/* - * Since an obvious implementation of va_list would be to make it a - * pointer into the stack frame, a simple assignment will work on - * many systems. But let's try to be more portable. - */ -#ifdef __va_copy -#define va_copy(dst, src) __va_copy(dst, src) -#else -#define va_copy(dst, src) ((dst) = (src)) -#endif -#endif - /* usage.c: only to be used for testing BUG() implementation (see test-tool) */ extern int BUG_exit_code; @@ -1462,6 +996,8 @@ extern int bug_called_must_BUG; __attribute__((format (printf, 3, 4))) NORETURN void BUG_fl(const char *file, int line, const char *fmt, ...); #define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__) +/* ASSERT: like assert(), but won't be compiled out with NDEBUG */ +#define ASSERT(a) if (!(a)) BUG("Assertion `" #a "' failed.") __attribute__((format (printf, 3, 4))) void bug_fl(const char *file, int line, const char *fmt, ...); #define bug(...) bug_fl(__FILE__, __LINE__, __VA_ARGS__) @@ -1482,41 +1018,6 @@ void bug_fl(const char *file, int line, const char *fmt, ...); # define SHELL_PATH "/bin/sh" #endif -#ifndef _POSIX_THREAD_SAFE_FUNCTIONS -static inline void git_flockfile(FILE *fh UNUSED) -{ - ; /* nothing */ -} -static inline void git_funlockfile(FILE *fh UNUSED) -{ - ; /* nothing */ -} -#undef flockfile -#undef funlockfile -#undef getc_unlocked -#define flockfile(fh) git_flockfile(fh) -#define funlockfile(fh) git_funlockfile(fh) -#define getc_unlocked(fh) getc(fh) -#endif - -#ifdef FILENO_IS_A_MACRO -int git_fileno(FILE *stream); -# ifndef COMPAT_CODE_FILENO -# undef fileno -# define fileno(p) git_fileno(p) -# endif -#endif - -#ifdef NEED_ACCESS_ROOT_HANDLER -int git_access(const char *path, int mode); -# ifndef COMPAT_CODE_ACCESS -# ifdef access -# undef access -# endif -# define access(path, mode) git_access(path, mode) -# endif -#endif - /* * Our code often opens a path to an optional file, to work on its * contents when we can successfully open it. We can ignore a failure @@ -1585,4 +1086,20 @@ static inline void *container_of_or_null_offset(void *ptr, size_t offset) ((uintptr_t)&(ptr)->member - (uintptr_t)(ptr)) #endif /* !__GNUC__ */ +/* + * Prevent an overly clever compiler from optimizing an expression + * out, triggering a false positive when building with the + * -Wunreachable-code option. false_but_the_compiler_does_not_know_it_ + * is defined in a compilation unit separate from where the macro is + * used, initialized to 0, and never modified. + */ +#define NOT_CONSTANT(expr) ((expr) || false_but_the_compiler_does_not_know_it_) +extern int false_but_the_compiler_does_not_know_it_; + +#ifdef CHECK_ASSERTION_SIDE_EFFECTS +#undef assert +extern int not_supposed_to_survive; +#define assert(expr) ((void)(not_supposed_to_survive || (expr))) +#endif /* CHECK_ASSERTION_SIDE_EFFECTS */ + #endif diff --git a/git-curl-compat.h b/git-curl-compat.h index 703756ba85..aa8eed7ed2 100644 --- a/git-curl-compat.h +++ b/git-curl-compat.h @@ -45,4 +45,11 @@ #define GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR 1 #endif +/** + * CURLOPT_TCP_KEEPCNT was added in 8.9.0, released in July, 2024. + */ +#if LIBCURL_VERSION_NUM >= 0x080900 +#define GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT +#endif + #endif diff --git a/git-cvsserver.perl b/git-cvsserver.perl index a4e1bad33c..d8d5422cbc 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -4986,13 +4986,13 @@ sub gethistorydense return $result; } -=head2 escapeRefName +=head2 unescapeRefName -Apply an escape mechanism to compensate for characters that +Undo an escape mechanism to compensate for characters that git ref names can have that CVS tags can not. =cut -sub escapeRefName +sub unescapeRefName { my($self,$refName)=@_; @@ -5009,27 +5009,6 @@ sub escapeRefName # = "_-xx-" Where "xx" is the hexadecimal representation of the # desired ASCII character byte. (for anything else) - if(! $refName=~/^[1-9][0-9]*(\.[1-9][0-9]*)*$/) - { - $refName=~s/_-/_-u--/g; - $refName=~s/\./_-p-/g; - $refName=~s%/%_-s-%g; - $refName=~s/[^-_a-zA-Z0-9]/sprintf("_-%02x-",$1)/eg; - } -} - -=head2 unescapeRefName - -Undo an escape mechanism to compensate for characters that -git ref names can have that CVS tags can not. - -=cut -sub unescapeRefName -{ - my($self,$refName)=@_; - - # see escapeRefName() for description of escape mechanism. - $refName=~s/_-([spu]|[0-9a-f][0-9a-f])-/unescapeRefNameChar($1)/eg; # allowed tag names diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 3a51d4507c..24fa317aaa 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -295,15 +295,18 @@ then if test -n "$state_commit" then echo "Populating map from $state_branch ($state_commit)" 1>&2 - perl -e'open(MAP, "-|", "git show $ARGV[0]:filter.map") or die; - while (<MAP>) { - m/(.*):(.*)/ or die; - open F, ">../map/$1" or die; - print F "$2" or die; - close(F) or die; - } - close(MAP) or die;' "$state_commit" \ - || die "Unable to load state from $state_branch:filter.map" + + git show "$state_commit:filter.map" >"$tempdir"/filter-map || + die "Unable to load state from $state_branch:filter.map" + while read line + do + case "$line" in + *:*) + echo "${line%:*}" >../map/"${line#*:}";; + *) + die "Unable to load state from $state_branch:filter.map";; + esac + done <"$tempdir"/filter-map else echo "Branch $state_branch does not exist. Will create" 1>&2 fi @@ -633,15 +636,13 @@ if test -n "$state_branch" then echo "Saving rewrite state to $state_branch" 1>&2 state_blob=$( - perl -e'opendir D, "../map" or die; - open H, "|-", "git hash-object -w --stdin" or die; - foreach (sort readdir(D)) { - next if m/^\.\.?$/; - open F, "<../map/$_" or die; - chomp($f = <F>); - print H "$_:$f\n" or die; - } - close(H) or die;' || die "Unable to save state") + for file in ../map/* + do + from_commit=$(basename "$file") + to_commit=$(cat "$file") + echo "$from_commit:$to_commit" + done | git hash-object -w --stdin || die "Unable to save state" + ) state_tree=$(printf '100644 blob %s\tfilter.map\n' "$state_blob" | git mktree) if test -n "$state_commit" then diff --git a/git-gui/.gitattributes b/git-gui/.gitattributes index 118d56cfbd..889d58257f 100644 --- a/git-gui/.gitattributes +++ b/git-gui/.gitattributes @@ -4,3 +4,4 @@ git-gui.sh encoding=UTF-8 /po/*.po encoding=UTF-8 /GIT-VERSION-GEN eol=lf Makefile whitespace=!indent,trail,space +meson.build whitespace=space diff --git a/git-gui/.gitignore b/git-gui/.gitignore index 6483b21cbf..ff6e0be4b4 100644 --- a/git-gui/.gitignore +++ b/git-gui/.gitignore @@ -2,7 +2,7 @@ config.mak Git Gui.app* git-gui.tcl +GIT-GUI-BUILD-OPTIONS GIT-VERSION-FILE -GIT-GUI-VARS git-gui lib/tclIndex diff --git a/git-gui/GIT-GUI-BUILD-OPTIONS.in b/git-gui/GIT-GUI-BUILD-OPTIONS.in new file mode 100644 index 0000000000..5fd885c2bf --- /dev/null +++ b/git-gui/GIT-GUI-BUILD-OPTIONS.in @@ -0,0 +1,7 @@ +GITGUI_GITEXECDIR=@GITGUI_GITEXECDIR@ +GITGUI_LIBDIR=@GITGUI_LIBDIR@ +GITGUI_RELATIVE=@GITGUI_RELATIVE@ +SHELL_PATH=@SHELL_PATH@ +TCLTK_PATH=@TCLTK_PATH@ +TCL_PATH=@TCL_PATH@ +TKEXECUTABLE=@TKEXECUTABLE@ diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN index 92373d251a..c2767b4136 100755 --- a/git-gui/GIT-VERSION-GEN +++ b/git-gui/GIT-VERSION-GEN @@ -1,19 +1,33 @@ #!/bin/sh -GVF=GIT-VERSION-FILE DEF_VER=0.21.GITGUI LF=' ' +if test "$#" -ne 2 +then + echo >&2 "usage: $0 <SOURCE_DIR> <OUTPUT>" + exit 1 +fi + +SOURCE_DIR="$1" +OUTPUT="$2" + +# Protect us from reading Git version information outside of the Git directory +# in case it is not a repository itself, but embedded in an unrelated +# repository. +GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.." +export GIT_CEILING_DIRECTORIES + tree_search () { head=$1 tree=$2 - for p in $(git rev-list --parents --max-count=1 $head 2>/dev/null) + for p in $(git -C "$SOURCE_DIR" rev-list --parents --max-count=1 $head 2>/dev/null) do - test $tree = $(git rev-parse $p^{tree} 2>/dev/null) && - vn=$(git describe --abbrev=4 $p 2>/dev/null) && + test $tree = $(git -C "$SOURCE_DIR" rev-parse $p^{tree} 2>/dev/null) && + vn=$(git -C "$SOURCE_DIR" describe --abbrev=4 $p 2>/dev/null) && case "$vn" in gitgui-[0-9]*) echo $vn; break;; esac @@ -34,14 +48,14 @@ tree_search () # If we are at the toplevel or the merge assumption fails # try looking for a gitgui-* tag. -if test -f version && - VN=$(cat version) +if test -f "$SOURCE_DIR"/version && + VN=$(cat "$SOURCE_DIR"/version) then : happy -elif prefix="$(git rev-parse --show-prefix 2>/dev/null)" +elif prefix="$(git -C "$SOURCE_DIR" rev-parse --show-prefix 2>/dev/null)" test -n "$prefix" && - head=$(git rev-list --max-count=1 HEAD -- . 2>/dev/null) && - tree=$(git rev-parse --verify "HEAD:$prefix" 2>/dev/null) && + head=$(git -C "$SOURCE_DIR" rev-list --max-count=1 HEAD -- . 2>/dev/null) && + tree=$(git -C "$SOURCE_DIR" rev-parse --verify "HEAD:$prefix" 2>/dev/null) && VN=$(tree_search $head $tree) case "$VN" in gitgui-[0-9]*) : happy ;; @@ -49,7 +63,7 @@ elif prefix="$(git rev-parse --show-prefix 2>/dev/null)" esac then VN=$(echo "$VN" | sed -e 's/^gitgui-//;s/-/./g'); -elif VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && +elif VN=$(git -C "$SOURCE_DIR" describe --abbrev=4 HEAD 2>/dev/null) && case "$VN" in gitgui-[0-9]*) : happy ;; *) (exit 1) ;; @@ -60,7 +74,7 @@ else VN="$DEF_VER" fi -dirty=$(sh -c 'git diff-index --name-only HEAD' 2>/dev/null) || dirty= +dirty=$(git -C "$SOURCE_DIR" diff-index --name-only HEAD 2>/dev/null) || dirty= case "$dirty" in '') ;; @@ -68,13 +82,13 @@ case "$dirty" in VN="$VN-dirty" ;; esac -if test -r $GVF +if test -r "$OUTPUT" then - VC=$(sed -e 's/^GITGUI_VERSION = //' <$GVF) + VC=$(sed -e 's/^GITGUI_VERSION=//' <"$OUTPUT") else VC=unset fi test "$VN" = "$VC" || { - echo >&2 "GITGUI_VERSION = $VN" - echo "GITGUI_VERSION = $VN" >$GVF + echo >&2 "GITGUI_VERSION=$VN" + echo "GITGUI_VERSION=$VN" >"$OUTPUT" } diff --git a/git-gui/Makefile b/git-gui/Makefile index 6c5a12bc32..8672dd2d6b 100644 --- a/git-gui/Makefile +++ b/git-gui/Makefile @@ -9,10 +9,7 @@ all:: # GIT-VERSION-FILE: FORCE - @$(SHELL_PATH) ./GIT-VERSION-GEN -ifneq ($(MAKECMDGOALS),clean) --include GIT-VERSION-FILE -endif + @$(SHELL_PATH) ./GIT-VERSION-GEN . $@ uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') @@ -76,7 +73,6 @@ ifndef V QUIET_INDEX = $(QUIET)echo ' ' INDEX $(dir $@) && QUIET_MSGFMT0 = $(QUIET)printf ' MSGFMT %12s ' $@ && v=` QUIET_MSGFMT1 = 2>&1` && echo "$$v" | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages*//g' - QUIET_2DEVNULL = 2>/dev/null INSTALL_D0 = dir= INSTALL_D1 = && echo ' ' DEST $$dir && $(INSTALL) -d -m 755 "$$dir" @@ -114,7 +110,8 @@ ifeq ($(uname_S),Darwin) TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app endif endif - TKEXECUTABLE = $(shell basename "$(TKFRAMEWORK)" .app) + TKEXECUTABLE = $(TKFRAMEWORK)/Contents/MacOS/$(shell basename "$(TKFRAMEWORK)" .app) + TKEXECUTABLE_SQ = $(subst ','\'',$(TKEXECUTABLE)) endif ifeq ($(findstring $(firstword -$(MAKEFLAGS)),s),s) @@ -128,21 +125,17 @@ gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) TCL_PATH_SQ = $(subst ','\'',$(TCL_PATH)) TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) -TCLTK_PATH_SED = $(subst ','\'',$(subst \,\\,$(TCLTK_PATH))) gg_libdir ?= $(sharedir)/git-gui/lib libdir_SQ = $(subst ','\'',$(gg_libdir)) -libdir_SED = $(subst ','\'',$(subst \,\\,$(gg_libdir_sed_in))) exedir = $(dir $(gitexecdir))share/git-gui/lib -GITGUI_SCRIPT := $$0 GITGUI_RELATIVE := GITGUI_MACOSXAPP := ifeq ($(exedir),$(gg_libdir)) GITGUI_RELATIVE := 1 endif -gg_libdir_sed_in := $(gg_libdir) ifeq ($(uname_S),Darwin) ifeq ($(shell test -d $(TKFRAMEWORK) && echo y),y) GITGUI_MACOSXAPP := YesPlease @@ -159,41 +152,15 @@ endif ifdef GITGUI_MACOSXAPP GITGUI_MAIN := git-gui.tcl -git-gui: GIT-VERSION-FILE GIT-GUI-VARS - $(QUIET_GEN)rm -f $@ $@+ && \ - echo '#!$(SHELL_PATH_SQ)' >$@+ && \ - echo 'if test "z$$*" = zversion ||' >>$@+ && \ - echo ' test "z$$*" = z--version' >>$@+ && \ - echo then >>$@+ && \ - echo ' 'echo \'git-gui version '$(GITGUI_VERSION)'\' >>$@+ && \ - echo else >>$@+ && \ - echo ' libdir="$${GIT_GUI_LIB_DIR:-$(libdir_SQ)}"' >>$@+ && \ - echo ' 'exec \"'$$libdir/Git Gui.app/Contents/MacOS/$(subst \,,$(TKEXECUTABLE))'\" \ - '"$$0" "$$@"' >>$@+ && \ - echo fi >>$@+ && \ - chmod +x $@+ && \ - mv $@+ $@ - -Git\ Gui.app: GIT-VERSION-FILE GIT-GUI-VARS \ +git-gui: generate-macos-wrapper.sh GIT-VERSION-FILE GIT-GUI-BUILD-OPTIONS + $(QUIET_GEN)$(SHELL_PATH) generate-macos-wrapper.sh "$@" ./GIT-GUI-BUILD-OPTIONS ./GIT-VERSION-FILE + +Git\ Gui.app: GIT-VERSION-FILE GIT-GUI-BUILD-OPTIONS \ macosx/Info.plist \ macosx/git-gui.icns \ macosx/AppMain.tcl \ - $(TKFRAMEWORK)/Contents/MacOS/$(TKEXECUTABLE) - $(QUIET_GEN)rm -rf '$@' '$@'+ && \ - mkdir -p '$@'+/Contents/MacOS && \ - mkdir -p '$@'+/Contents/Resources/Scripts && \ - cp '$(subst ','\'',$(subst \,,$(TKFRAMEWORK)/Contents/MacOS/$(TKEXECUTABLE)))' \ - '$@'+/Contents/MacOS && \ - cp macosx/git-gui.icns '$@'+/Contents/Resources && \ - sed -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ - -e 's/@@GITGUI_TKEXECUTABLE@@/$(TKEXECUTABLE)/g' \ - macosx/Info.plist \ - >'$@'+/Contents/Info.plist && \ - sed -e 's|@@gitexecdir@@|$(gitexecdir_SQ)|' \ - -e 's|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \ - macosx/AppMain.tcl \ - >'$@'+/Contents/Resources/Scripts/AppMain.tcl && \ - mv '$@'+ '$@' + $(TKEXECUTABLE) + $(QUIET_GEN)$(SHELL_PATH) generate-macos-app.sh . "$@" ./GIT-GUI-BUILD-OPTIONS ./GIT-VERSION-FILE endif ifdef GITGUI_WINDOWS_WRAPPER @@ -203,18 +170,8 @@ git-gui: windows/git-gui.sh cp $< $@ endif -$(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-VARS - $(QUIET_GEN)rm -f $@ $@+ && \ - sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ - -e 's|@@SHELL_PATH@@|$(SHELL_PATH_SQ)|' \ - -e '1,30s|^ argv0=$$0| argv0=$(GITGUI_SCRIPT)|' \ - -e '1,30s|^ exec wish | exec '\''$(TCLTK_PATH_SED)'\'' |' \ - -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ - -e 's|@@GITGUI_RELATIVE@@|$(GITGUI_RELATIVE)|' \ - -e '$(GITGUI_RELATIVE)s|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \ - git-gui.sh >$@+ && \ - chmod +x $@+ && \ - mv $@+ $@ +$(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-BUILD-OPTIONS + $(QUIET_GEN)$(SHELL_PATH) generate-git-gui.sh "$<" "$@" ./GIT-GUI-BUILD-OPTIONS ./GIT-VERSION-FILE XGETTEXT ?= xgettext ifdef NO_MSGFMT @@ -239,35 +196,21 @@ update-po:: $(PO_TEMPLATE) $(ALL_MSGFILES): %.msg : %.po $(QUIET_MSGFMT0)$(MSGFMT) --statistics --tcl -l $(basename $(notdir $<)) -d $(dir $@) $< $(QUIET_MSGFMT1) -lib/tclIndex: $(ALL_LIBFILES) GIT-GUI-VARS - $(QUIET_INDEX)if echo \ - $(foreach p,$(PRELOAD_FILES),source $p\;) \ - auto_mkindex lib $(patsubst lib/%,%,$(sort $(ALL_LIBFILES))) \ - | $(TCL_PATH) $(QUIET_2DEVNULL); then : ok; \ - else \ - echo >&2 " * $(TCL_PATH) failed; using unoptimized loading"; \ - rm -f $@ ; \ - echo '# Autogenerated by git-gui Makefile' >$@ && \ - echo >>$@ && \ - $(foreach p,$(PRELOAD_FILES) $(sort $(ALL_LIBFILES)),echo '$(subst lib/,,$p)' >>$@ &&) \ - echo >>$@ ; \ - fi - -TRACK_VARS = \ - $(subst ','\'',SHELL_PATH='$(SHELL_PATH_SQ)') \ - $(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \ - $(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \ - $(subst ','\'',gitexecdir='$(gitexecdir_SQ)') \ - $(subst ','\'',gg_libdir='$(libdir_SQ)') \ - GITGUI_MACOSXAPP=$(GITGUI_MACOSXAPP) \ -#end TRACK_VARS - -GIT-GUI-VARS: FORCE - @VARS='$(TRACK_VARS)'; \ - if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \ - echo >&2 " * new locations or Tcl/Tk interpreter"; \ - echo >$@ "$$VARS"; \ - fi +lib/tclIndex: $(ALL_LIBFILES) generate-tclindex.sh GIT-GUI-BUILD-OPTIONS + $(QUIET_INDEX)$(SHELL_PATH) generate-tclindex.sh . ./GIT-GUI-BUILD-OPTIONS $(ALL_LIBFILES) + +GIT-GUI-BUILD-OPTIONS: FORCE + @sed \ + -e 's|@GITGUI_GITEXECDIR@|$(gitexecdir_SQ)|' \ + -e 's|@GITGUI_LIBDIR@|$(libdir_SQ)|' \ + -e 's|@GITGUI_RELATIVE@|$(GITGUI_RELATIVE)|' \ + -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \ + -e 's|@TCLTK_PATH@|$(TCLTK_PATH_SQ)|' \ + -e 's|@TCL_PATH@|$(TCL_PATH_SQ)|' \ + -e 's|@TKEXECUTABLE@|$(TKEXECUTABLE_SQ)|' \ + $@.in >$@+ + @if grep -q '^[A-Z][A-Z_]*=@.*@$$' $@+; then echo "Unsubstituted build options in $@" >&2 && exit 1; fi + @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi ifdef GITGUI_MACOSXAPP all:: git-gui Git\ Gui.app @@ -317,13 +260,13 @@ endif $(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(REMOVE_D1) $(QUIET)$(REMOVE_D0)`dirname '$(DESTDIR_SQ)$(libdir_SQ)'` $(REMOVE_D1) -dist-version: +dist-version: GIT-VERSION-FILE @mkdir -p $(TARDIR) - @echo $(GITGUI_VERSION) > $(TARDIR)/version + @sed 's|^GITGUI_VERSION=||' <GIT-VERSION-FILE >$(TARDIR)/version clean:: - $(RM_RF) $(GITGUI_MAIN) lib/tclIndex po/*.msg - $(RM_RF) GIT-VERSION-FILE GIT-GUI-VARS + $(RM_RF) $(GITGUI_MAIN) lib/tclIndex po/*.msg $(PO_TEMPLATE) + $(RM_RF) GIT-VERSION-FILE GIT-GUI-BUILD-OPTIONS ifdef GITGUI_MACOSXAPP $(RM_RF) 'Git Gui.app'* git-gui endif diff --git a/git-gui/generate-git-gui.sh b/git-gui/generate-git-gui.sh new file mode 100755 index 0000000000..39dfafdc4a --- /dev/null +++ b/git-gui/generate-git-gui.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +set -e + +if test "$#" -ne 4 +then + echo >&2 "usage: $0 <INPUT> <OUTPUT> <BUILD_OPTIONS> <VERSION_FILE>" + exit 1 +fi + +INPUT="$1" +OUTPUT="$2" +BUILD_OPTIONS="$3" +VERSION_FILE="$4" + +. "${BUILD_OPTIONS}" +. "${VERSION_FILE}" + +rm -f "$OUTPUT" "$OUTPUT+" +sed \ + -e "1s|#!.*/sh|#!$SHELL_PATH|" \ + -e "s|@@SHELL_PATH@@|$SHELL_PATH|" \ + -e "1,30s|^ exec wish | exec '$TCLTK_PATH' |" \ + -e "s|@@GITGUI_VERSION@@|$GITGUI_VERSION|g" \ + -e "s|@@GITGUI_RELATIVE@@|$GITGUI_RELATIVE|" \ + -e "${GITGUI_RELATIVE}s|@@GITGUI_LIBDIR@@|$GITGUI_LIBDIR|" \ + "$INPUT" >"$OUTPUT"+ +chmod +x "$OUTPUT"+ +mv "$OUTPUT"+ "$OUTPUT" diff --git a/git-gui/generate-macos-app.sh b/git-gui/generate-macos-app.sh new file mode 100755 index 0000000000..71b9fa67a4 --- /dev/null +++ b/git-gui/generate-macos-app.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +set -e + +SOURCE_DIR="$1" +OUTPUT="$2" +BUILD_OPTIONS="$3" +VERSION_FILE="$4" + +. "$BUILD_OPTIONS" +. "$VERSION_FILE" + +rm -rf "$OUTPUT" "$OUTPUT+" + +mkdir -p "$OUTPUT+/Contents/MacOS" +mkdir -p "$OUTPUT+/Contents/Resources/Scripts" + +cp "$TKEXECUTABLE" "$OUTPUT+/Contents/MacOS" +cp "$SOURCE_DIR/macosx/git-gui.icns" "$OUTPUT+/Contents/Resources" +sed \ + -e "s/@@GITGUI_VERSION@@/$GITGUI_VERSION/g" \ + -e "s/@@GITGUI_TKEXECUTABLE@@/$(basename "$TKEXECUTABLE")/g" \ + "$SOURCE_DIR/macosx/Info.plist" \ + >"$OUTPUT+/Contents/Info.plist" +sed \ + -e "s|@@gitexecdir@@|$GITGUI_GITEXECDIR|" \ + -e "s|@@GITGUI_LIBDIR@@|$GITGUI_LIBDIR|" \ + "$SOURCE_DIR/macosx/AppMain.tcl" \ + >"$OUTPUT+/Contents/Resources/Scripts/AppMain.tcl" +mv "$OUTPUT+" "$OUTPUT" diff --git a/git-gui/generate-macos-wrapper.sh b/git-gui/generate-macos-wrapper.sh new file mode 100755 index 0000000000..0304937f41 --- /dev/null +++ b/git-gui/generate-macos-wrapper.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +set -e + +if test "$#" -ne 3 +then + echo >&2 "usage: $0 <OUTPUT> <BUILD_OPTIONS> <VERSION_FILE>" + exit 1 +fi + +OUTPUT="$1" +BUILD_OPTIONS="$2" +VERSION_FILE="$3" + +. "$BUILD_OPTIONS" + +rm -f "$OUTPUT" "$OUTPUT+" + +( + echo "#!$SHELL_PATH" + cat "$BUILD_OPTIONS" "$VERSION_FILE" + cat <<-'EOF' + if test "z$*" = zversion || + test "z$*" = z--version + then + echo "git-gui version $GITGUI_VERSION" + else + libdir="${GIT_GUI_LIB_DIR:-$GITGUI_LIBDIR}" + exec "$libdir/Git Gui.app/Contents/MacOS/$(basename "$TKEXECUTABLE")" "$0" "$@" + fi + EOF +) >"$OUTPUT+" + +chmod +x "$OUTPUT+" +mv "$OUTPUT+" "$OUTPUT" diff --git a/git-gui/generate-tclindex.sh b/git-gui/generate-tclindex.sh new file mode 100755 index 0000000000..0b031d8339 --- /dev/null +++ b/git-gui/generate-tclindex.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +if test "$#" -lt 3 +then + echo >&2 "usage: $0 <BUILD_DIR> <BUILD_OPTIONS> <LIBFILE> [<LIBFILE>...]" + exit 1 +fi + +BUILD_DIR="$1" +BUILD_OPTIONS="$2" +shift 2 +LIBFILES="$(echo "$@" | sort | sed 's|lib/||g')" + +. "$BUILD_OPTIONS" + +cd "$BUILD_DIR" + +if { + echo "source lib/class.tcl;" + echo "auto_mkindex lib $LIBFILES" +} | "$TCL_PATH" +then + : ok +else + echo >&2 " * $TCL_PATH failed; using unoptimized loading" + rm -f lib/tclIndex + echo '# Autogenerated by git-gui Makefile' >lib/tclIndex + echo >>lib/tclIndex + echo "class.tcl" >>lib/tclIndex + printf "%s\n" $LIBFILES >>lib/tclIndex + echo >>lib/tclIndex +fi diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh index 887d6d596c..28572c889c 100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@ -880,6 +880,12 @@ proc apply_config {} { color::sync_with_theme } } + + global comment_string + set comment_string [get_config core.commentstring] + if {$comment_string eq {}} { + set comment_string [get_config core.commentchar] + } } set default_config(branch.autosetupmerge) true @@ -890,6 +896,8 @@ set default_config(merge.summary) false set default_config(merge.verbosity) 2 set default_config(user.name) {} set default_config(user.email) {} +set default_config(core.commentchar) "#" +set default_config(core.commentstring) {} set default_config(gui.encoding) [encoding system] set default_config(gui.matchtrackingbranch) false diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl index 208dc2817c..a570f9cdc6 100644 --- a/git-gui/lib/commit.tcl +++ b/git-gui/lib/commit.tcl @@ -211,7 +211,9 @@ You must stage at least 1 file before you can commit. # Strip trailing whitespace regsub -all -line {[ \t\r]+$} $msg {} msg # Strip comment lines - regsub -all {(^|\n)#[^\n]*} $msg {\1} msg + global comment_string + set cmt_rx [strcat {(^|\n)} [regsub -all {\W} $comment_string {\\&}] {[^\n]*}] + regsub -all $cmt_rx $msg {\1} msg # Strip leading empty lines regsub {^\n*} $msg {} msg # Compress consecutive empty lines diff --git a/git-gui/lib/meson.build b/git-gui/lib/meson.build new file mode 100644 index 0000000000..4b9efab774 --- /dev/null +++ b/git-gui/lib/meson.build @@ -0,0 +1,74 @@ +libfiles = [ + 'about.tcl', + 'blame.tcl', + 'branch_checkout.tcl', + 'branch_create.tcl', + 'branch_delete.tcl', + 'branch_rename.tcl', + 'branch.tcl', + 'browser.tcl', + 'checkout_op.tcl', + 'choose_font.tcl', + 'choose_repository.tcl', + 'choose_rev.tcl', + 'chord.tcl', + 'class.tcl', + 'commit.tcl', + 'console.tcl', + 'database.tcl', + 'date.tcl', + 'diff.tcl', + 'encoding.tcl', + 'error.tcl', + 'index.tcl', + 'line.tcl', + 'logo.tcl', + 'merge.tcl', + 'mergetool.tcl', + 'option.tcl', + 'remote_add.tcl', + 'remote_branch_delete.tcl', + 'remote.tcl', + 'search.tcl', + 'shortcut.tcl', + 'spellcheck.tcl', + 'sshkey.tcl', + 'status_bar.tcl', + 'themed.tcl', + 'tools_dlg.tcl', + 'tools.tcl', + 'transport.tcl', + 'win32.tcl', +] + +nontcl_libfiles = [ + 'git-gui.ico', + 'win32_shortcut.js', +] + +foreach file : libfiles + nontcl_libfiles + configure_file( + input: file, + output: file, + copy: true, + install: true, + install_dir: get_option('datadir') / 'git-gui/lib', + ) +endforeach + +custom_target( + output: 'tclIndex', + command: [ + shell, + meson.project_source_root() / 'generate-tclindex.sh', + meson.project_build_root(), + meson.project_build_root() / 'GIT-GUI-BUILD-OPTIONS', + libfiles, + ], + depend_files: [ + libfiles, + build_options, + ], + install: true, + install_dir: get_option('datadir') / 'git-gui/lib', +) diff --git a/git-gui/meson.build b/git-gui/meson.build new file mode 100644 index 0000000000..cdae85e4b9 --- /dev/null +++ b/git-gui/meson.build @@ -0,0 +1,148 @@ +project('git-gui', + meson_version: '>=0.61.0', +) + +fs = import('fs') + +shell = find_program('sh') +tclsh = find_program('tclsh') +wish = find_program('wish') + +build_options_config = configuration_data() +if target_machine.system() == 'windows' + build_options_config.set('GITGUI_RELATIVE', '1') +else + build_options_config.set('GITGUI_RELATIVE', '') +endif +build_options_config.set_quoted('GITGUI_GITEXECDIR', get_option('prefix') / get_option('libexecdir') / 'git-core') +build_options_config.set_quoted('GITGUI_LIBDIR', get_option('prefix') / get_option('datadir') / 'git-gui/lib') +build_options_config.set_quoted('SHELL_PATH', fs.as_posix(shell.full_path())) +build_options_config.set_quoted('TCLTK_PATH', fs.as_posix(wish.full_path())) +build_options_config.set_quoted('TCL_PATH', fs.as_posix(tclsh.full_path())) +if target_machine.system() == 'darwin' + tkexecutables = [ + '/Library/Frameworks/Tk.framework/Resources/Wish.app/Contents/MacOS/Wish', + '/System/Library/Frameworks/Tk.framework/Resources/Wish.app/Contents/MacOS/Wish', + '/System/Library/Frameworks/Tk.framework/Resources/Wish Shell.app/Contents/MacOS/Wish Shell', + ] + tkexecutable = find_program(tkexecutables) + build_options_config.set_quoted('TKEXECUTABLE', tkexecutable.full_path()) +else + build_options_config.set('TKEXECUTABLE', '') +endif + +build_options = configure_file( + input: 'GIT-GUI-BUILD-OPTIONS.in', + output: 'GIT-GUI-BUILD-OPTIONS', + configuration: build_options_config, +) + +version_file = custom_target( + input: 'GIT-VERSION-GEN', + output: 'GIT-VERSION-FILE', + command: [ + shell, + '@INPUT@', + meson.current_source_dir(), + '@OUTPUT@', + ], + build_always_stale: true, +) + +configure_file( + input: 'git-gui--askpass', + output: 'git-gui--askpass', + copy: true, + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +gitgui_main = 'git-gui' +gitgui_main_install_dir = get_option('libexecdir') / 'git-core' + +if target_machine.system() == 'windows' + gitgui_main = 'git-gui.tcl' + + configure_file( + input: 'windows/git-gui.sh', + output: 'git-gui', + copy: true, + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) +elif target_machine.system() == 'darwin' + gitgui_main = 'git-gui.tcl' + gitgui_main_install_dir = get_option('datadir') / 'git-gui/lib' + + custom_target( + output: 'git-gui', + command: [ + shell, + meson.current_source_dir() / 'generate-macos-wrapper.sh', + '@OUTPUT@', + meson.current_build_dir() / 'GIT-GUI-BUILD-OPTIONS', + meson.current_build_dir() / 'GIT-VERSION-FILE', + ], + depends: [ + version_file, + ], + depend_files: [ + build_options, + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + + custom_target( + output: 'Git Gui.app', + command: [ + shell, + meson.current_source_dir() / 'generate-macos-app.sh', + meson.current_source_dir(), + meson.current_build_dir() / 'Git Gui.app', + meson.current_build_dir() / 'GIT-GUI-BUILD-OPTIONS', + meson.current_build_dir() / 'GIT-VERSION-FILE', + ], + depends: [ + version_file, + ], + depend_files: [ + build_options, + 'macosx/AppMain.tcl', + 'macosx/Info.plist', + 'macosx/git-gui.icns', + ], + build_by_default: true, + install: true, + install_dir: get_option('datadir') / 'git-gui/lib', + ) +endif + +custom_target( + input: 'git-gui.sh', + output: gitgui_main, + command: [ + shell, + meson.current_source_dir() / 'generate-git-gui.sh', + '@INPUT@', + '@OUTPUT@', + meson.current_build_dir() / 'GIT-GUI-BUILD-OPTIONS', + meson.current_build_dir() / 'GIT-VERSION-FILE', + ], + depends: [ + version_file, + ], + depend_files: [ + build_options, + ], + install: true, + install_dir: gitgui_main_install_dir, +) + +install_symlink('git-citool', + install_dir: get_option('libexecdir') / 'git-core', + pointing_to: 'git-gui', +) + +subdir('lib') +subdir('po') diff --git a/git-gui/po/.gitignore b/git-gui/po/.gitignore index a89cf44969..b900bb98d5 100644 --- a/git-gui/po/.gitignore +++ b/git-gui/po/.gitignore @@ -1,2 +1,3 @@ *.msg *~ +/git-gui.pot diff --git a/git-gui/po/README b/git-gui/po/README index 116233100d..4a1aa79a49 100644 --- a/git-gui/po/README +++ b/git-gui/po/README @@ -21,8 +21,8 @@ them. You would then need to clone the git-gui project repository and create a feature branch to begin working: - $ git clone git://repo.or.cz/git-gui.git - $ cd git-gui.git + $ git clone https://github.com/j6t/git-gui + $ cd git-gui $ git checkout -b my-translation The "git checkout" command creates a new branch to keep your work @@ -47,6 +47,10 @@ language, you do not have to perform any step in this section, but keep reading, because we are covering the basics. If you did not find your language, you would need to start one yourself. +Generate po/git-gui.pot using + + $ make po/git-gui.pot + Copy po/git-gui.pot file to po/af.po (replace "af" with the code for your language). Edit the first several lines to match existing *.po files to make it clear this is a translation table for git-gui project, @@ -153,7 +157,7 @@ your patch series to the maintainer and the Git mailing list: $ git add po/af.po $ git commit -s -m 'git-gui: added Afrikaans translation.' $ git send-email --to 'git@vger.kernel.org' \ - --cc 'Pat Thoyts <patthoyts@users.sourceforge.net>' \ + --cc 'Johannes Sixt <j6t@kdbg.org>' \ --subject 'git-gui: Afrikaans translation' \ master.. @@ -169,18 +173,7 @@ In any case, make sure you are up to date before starting your work: $ git checkout master $ git pull - -In the former case, you will edit po/af.po (again, replace "af" with -your language code), and after testing and updating the Last-Translator: -and PO-Revision-Date: lines, "add/commit/push" as in the previous -section. - -By comparing "POT-Creation-Date:" line in po/git-gui.pot file and -po/af.po file, you can tell if there are new messages that need to be -translated. You would need the GNU gettext package to perform this -step. - - $ msgmerge -U po/af.po po/git-gui.pot + $ make ALL_POFILES=po/af.po update-po This updates po/af.po (again, replace "af" with your language code) so that it contains msgid lines (i.e. the original) that @@ -200,52 +193,5 @@ watch out for: - New messages added to the software will have msgstr lines with empty strings. You would need to translate them. -The po/git-gui.pot file is updated by the internationalization -coordinator from time to time. You _could_ update it yourself, but -translators are discouraged from doing so because we would want all -language teams to be working off of the same version of git-gui.pot. - -**************************************************************** - -This section is a note to the internationalization coordinator, and -translators do not have to worry about it too much. - -The message template file po/git-gui.pot needs to be kept up to date -relative to the software the translations apply to, and it is the -responsibility of the internationalization coordinator. - -When updating po/git-gui.pot file, however, _never_ run "msgmerge -U -po/xx.po" for individual language translations, unless you are absolutely -sure that there is no outstanding work on translation for language xx. -Doing so will create unnecessary merge conflicts and force needless -re-translation on translators. The translator however may not have access -to the msgmerge tool, in which case the coordinator may run it for the -translator as a service. - -But mistakes do happen. Suppose a translation was based on an older -version X, the POT file was updated at version Y and then msgmerge was run -at version Z for the language, and the translator sent in a patch based on -version X: - - ? translated - / - ---X---Y---Z (master) - -The coordinator could recover from such a mistake by first applying the -patch to X, replace the translated file in Z, and then running msgmerge -again based on the updated POT file and commit the result. The sequence -would look like this: - - $ git checkout X - $ git am -s xx.patch - $ git checkout master - $ git checkout HEAD@{1} po/xx.po - $ msgmerge -U po/xx.po po/git-gui.pot - $ git commit -c HEAD@{1} po/xx.po - -State in the message that the translated messages are based on a slightly -older version, and msgmerge was run to incorporate changes to message -templates from the updated POT file. The result needs to be further -translated, but at least the messages that were updated by the patch that -were not changed by the POT update will survive the process and do not -need to be re-translated. +After testing and updating the Last-Translator: and PO-Revision-Date: +lines, "add/commit/push" as in the previous section. diff --git a/git-gui/po/git-gui.pot b/git-gui/po/git-gui.pot deleted file mode 100644 index b79ed4e133..0000000000 --- a/git-gui/po/git-gui.pot +++ /dev/null @@ -1,2666 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-08 22:54+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#: git-gui.sh:847 -#, tcl-format -msgid "Invalid font specified in %s:" -msgstr "" - -#: git-gui.sh:901 -msgid "Main Font" -msgstr "" - -#: git-gui.sh:902 -msgid "Diff/Console Font" -msgstr "" - -#: git-gui.sh:917 git-gui.sh:931 git-gui.sh:944 git-gui.sh:1034 git-gui.sh:1053 -#: git-gui.sh:3212 -msgid "git-gui: fatal error" -msgstr "" - -#: git-gui.sh:918 -msgid "Cannot find git in PATH." -msgstr "" - -#: git-gui.sh:945 -msgid "Cannot parse Git version string:" -msgstr "" - -#: git-gui.sh:970 -#, tcl-format -msgid "" -"Git version cannot be determined.\n" -"\n" -"%s claims it is version '%s'.\n" -"\n" -"%s requires at least Git 1.5.0 or later.\n" -"\n" -"Assume '%s' is version 1.5.0?\n" -msgstr "" - -#: git-gui.sh:1267 -msgid "Git directory not found:" -msgstr "" - -#: git-gui.sh:1301 -msgid "Cannot move to top of working directory:" -msgstr "" - -#: git-gui.sh:1309 -msgid "Cannot use bare repository:" -msgstr "" - -#: git-gui.sh:1317 -msgid "No working directory" -msgstr "" - -#: git-gui.sh:1491 lib/checkout_op.tcl:306 -msgid "Refreshing file status..." -msgstr "" - -#: git-gui.sh:1551 -msgid "Scanning for modified files ..." -msgstr "" - -#: git-gui.sh:1629 -msgid "Calling prepare-commit-msg hook..." -msgstr "" - -#: git-gui.sh:1646 -msgid "Commit declined by prepare-commit-msg hook." -msgstr "" - -#: git-gui.sh:1804 lib/browser.tcl:252 -msgid "Ready." -msgstr "" - -#: git-gui.sh:1968 -#, tcl-format -msgid "" -"Display limit (gui.maxfilesdisplayed = %s) reached, not showing all %s files." -msgstr "" - -#: git-gui.sh:2091 -msgid "Unmodified" -msgstr "" - -#: git-gui.sh:2093 -msgid "Modified, not staged" -msgstr "" - -#: git-gui.sh:2094 git-gui.sh:2106 -msgid "Staged for commit" -msgstr "" - -#: git-gui.sh:2095 git-gui.sh:2107 -msgid "Portions staged for commit" -msgstr "" - -#: git-gui.sh:2096 git-gui.sh:2108 -msgid "Staged for commit, missing" -msgstr "" - -#: git-gui.sh:2098 -msgid "File type changed, not staged" -msgstr "" - -#: git-gui.sh:2099 git-gui.sh:2100 -msgid "File type changed, old type staged for commit" -msgstr "" - -#: git-gui.sh:2101 -msgid "File type changed, staged" -msgstr "" - -#: git-gui.sh:2102 -msgid "File type change staged, modification not staged" -msgstr "" - -#: git-gui.sh:2103 -msgid "File type change staged, file missing" -msgstr "" - -#: git-gui.sh:2105 -msgid "Untracked, not staged" -msgstr "" - -#: git-gui.sh:2110 -msgid "Missing" -msgstr "" - -#: git-gui.sh:2111 -msgid "Staged for removal" -msgstr "" - -#: git-gui.sh:2112 -msgid "Staged for removal, still present" -msgstr "" - -#: git-gui.sh:2114 git-gui.sh:2115 git-gui.sh:2116 git-gui.sh:2117 -#: git-gui.sh:2118 git-gui.sh:2119 -msgid "Requires merge resolution" -msgstr "" - -#: git-gui.sh:2164 -msgid "Couldn't find gitk in PATH" -msgstr "" - -#: git-gui.sh:2210 git-gui.sh:2245 -#, tcl-format -msgid "Starting %s... please wait..." -msgstr "" - -#: git-gui.sh:2224 -msgid "Couldn't find git gui in PATH" -msgstr "" - -#: git-gui.sh:2726 lib/choose_repository.tcl:53 -msgid "Repository" -msgstr "" - -#: git-gui.sh:2727 -msgid "Edit" -msgstr "" - -#: git-gui.sh:2729 lib/choose_rev.tcl:567 -msgid "Branch" -msgstr "" - -#: git-gui.sh:2732 lib/choose_rev.tcl:554 -msgid "Commit@@noun" -msgstr "" - -#: git-gui.sh:2735 lib/merge.tcl:127 lib/merge.tcl:174 -msgid "Merge" -msgstr "" - -#: git-gui.sh:2736 lib/choose_rev.tcl:563 -msgid "Remote" -msgstr "" - -#: git-gui.sh:2739 -msgid "Tools" -msgstr "" - -#: git-gui.sh:2748 -msgid "Explore Working Copy" -msgstr "" - -#: git-gui.sh:2763 -msgid "Git Bash" -msgstr "" - -#: git-gui.sh:2772 -msgid "Browse Current Branch's Files" -msgstr "" - -#: git-gui.sh:2776 -msgid "Browse Branch Files..." -msgstr "" - -#: git-gui.sh:2781 -msgid "Visualize Current Branch's History" -msgstr "" - -#: git-gui.sh:2785 -msgid "Visualize All Branch History" -msgstr "" - -#: git-gui.sh:2792 -#, tcl-format -msgid "Browse %s's Files" -msgstr "" - -#: git-gui.sh:2794 -#, tcl-format -msgid "Visualize %s's History" -msgstr "" - -#: git-gui.sh:2799 lib/database.tcl:40 -msgid "Database Statistics" -msgstr "" - -#: git-gui.sh:2802 lib/database.tcl:33 -msgid "Compress Database" -msgstr "" - -#: git-gui.sh:2805 -msgid "Verify Database" -msgstr "" - -#: git-gui.sh:2812 git-gui.sh:2816 git-gui.sh:2820 -msgid "Create Desktop Icon" -msgstr "" - -#: git-gui.sh:2828 lib/choose_repository.tcl:209 lib/choose_repository.tcl:217 -msgid "Quit" -msgstr "" - -#: git-gui.sh:2836 -msgid "Undo" -msgstr "" - -#: git-gui.sh:2839 -msgid "Redo" -msgstr "" - -#: git-gui.sh:2843 git-gui.sh:3461 -msgid "Cut" -msgstr "" - -#: git-gui.sh:2846 git-gui.sh:3464 git-gui.sh:3540 git-gui.sh:3633 -#: lib/console.tcl:69 -msgid "Copy" -msgstr "" - -#: git-gui.sh:2849 git-gui.sh:3467 -msgid "Paste" -msgstr "" - -#: git-gui.sh:2852 git-gui.sh:3470 lib/remote_branch_delete.tcl:39 -#: lib/branch_delete.tcl:28 -msgid "Delete" -msgstr "" - -#: git-gui.sh:2856 git-gui.sh:3474 git-gui.sh:3637 lib/console.tcl:71 -msgid "Select All" -msgstr "" - -#: git-gui.sh:2865 -msgid "Create..." -msgstr "" - -#: git-gui.sh:2871 -msgid "Checkout..." -msgstr "" - -#: git-gui.sh:2877 -msgid "Rename..." -msgstr "" - -#: git-gui.sh:2882 -msgid "Delete..." -msgstr "" - -#: git-gui.sh:2887 -msgid "Reset..." -msgstr "" - -#: git-gui.sh:2897 -msgid "Done" -msgstr "" - -#: git-gui.sh:2899 -msgid "Commit@@verb" -msgstr "" - -#: git-gui.sh:2908 git-gui.sh:3400 -msgid "Amend Last Commit" -msgstr "" - -#: git-gui.sh:2918 git-gui.sh:3361 lib/remote_branch_delete.tcl:101 -msgid "Rescan" -msgstr "" - -#: git-gui.sh:2924 -msgid "Stage To Commit" -msgstr "" - -#: git-gui.sh:2930 -msgid "Stage Changed Files To Commit" -msgstr "" - -#: git-gui.sh:2936 -msgid "Unstage From Commit" -msgstr "" - -#: git-gui.sh:2942 lib/index.tcl:521 -msgid "Revert Changes" -msgstr "" - -#: git-gui.sh:2950 git-gui.sh:3700 git-gui.sh:3731 -msgid "Show Less Context" -msgstr "" - -#: git-gui.sh:2954 git-gui.sh:3704 git-gui.sh:3735 -msgid "Show More Context" -msgstr "" - -#: git-gui.sh:2961 git-gui.sh:3374 git-gui.sh:3485 -msgid "Sign Off" -msgstr "" - -#: git-gui.sh:2977 -msgid "Local Merge..." -msgstr "" - -#: git-gui.sh:2982 -msgid "Abort Merge..." -msgstr "" - -#: git-gui.sh:2994 git-gui.sh:3022 -msgid "Add..." -msgstr "" - -#: git-gui.sh:2998 -msgid "Push..." -msgstr "" - -#: git-gui.sh:3002 -msgid "Delete Branch..." -msgstr "" - -#: git-gui.sh:3012 git-gui.sh:3666 -msgid "Options..." -msgstr "" - -#: git-gui.sh:3023 -msgid "Remove..." -msgstr "" - -#: git-gui.sh:3032 lib/choose_repository.tcl:67 -msgid "Help" -msgstr "" - -#: git-gui.sh:3036 git-gui.sh:3040 lib/choose_repository.tcl:61 -#: lib/choose_repository.tcl:70 lib/about.tcl:14 -#, tcl-format -msgid "About %s" -msgstr "" - -#: git-gui.sh:3064 -msgid "Online Documentation" -msgstr "" - -#: git-gui.sh:3067 lib/choose_repository.tcl:64 lib/choose_repository.tcl:73 -msgid "Show SSH Key" -msgstr "" - -#: git-gui.sh:3097 git-gui.sh:3229 -msgid "usage:" -msgstr "" - -#: git-gui.sh:3101 git-gui.sh:3233 -msgid "Usage" -msgstr "" - -#: git-gui.sh:3182 lib/blame.tcl:575 -msgid "Error" -msgstr "" - -#: git-gui.sh:3213 -#, tcl-format -msgid "fatal: cannot stat path %s: No such file or directory" -msgstr "" - -#: git-gui.sh:3246 -msgid "Current Branch:" -msgstr "" - -#: git-gui.sh:3271 -msgid "Unstaged Changes" -msgstr "" - -#: git-gui.sh:3293 -msgid "Staged Changes (Will Commit)" -msgstr "" - -#: git-gui.sh:3367 -msgid "Stage Changed" -msgstr "" - -#: git-gui.sh:3386 lib/transport.tcl:137 -msgid "Push" -msgstr "" - -#: git-gui.sh:3413 -msgid "Initial Commit Message:" -msgstr "" - -#: git-gui.sh:3414 -msgid "Amended Commit Message:" -msgstr "" - -#: git-gui.sh:3415 -msgid "Amended Initial Commit Message:" -msgstr "" - -#: git-gui.sh:3416 -msgid "Amended Merge Commit Message:" -msgstr "" - -#: git-gui.sh:3417 -msgid "Merge Commit Message:" -msgstr "" - -#: git-gui.sh:3418 -msgid "Commit Message:" -msgstr "" - -#: git-gui.sh:3477 git-gui.sh:3641 lib/console.tcl:73 -msgid "Copy All" -msgstr "" - -#: git-gui.sh:3501 lib/blame.tcl:106 -msgid "File:" -msgstr "" - -#: git-gui.sh:3549 lib/choose_repository.tcl:1100 -msgid "Open" -msgstr "" - -#: git-gui.sh:3629 -msgid "Refresh" -msgstr "" - -#: git-gui.sh:3650 -msgid "Decrease Font Size" -msgstr "" - -#: git-gui.sh:3654 -msgid "Increase Font Size" -msgstr "" - -#: git-gui.sh:3662 lib/blame.tcl:296 -msgid "Encoding" -msgstr "" - -#: git-gui.sh:3673 -msgid "Apply/Reverse Hunk" -msgstr "" - -#: git-gui.sh:3678 -msgid "Apply/Reverse Line" -msgstr "" - -#: git-gui.sh:3684 git-gui.sh:3794 git-gui.sh:3805 -msgid "Revert Hunk" -msgstr "" - -#: git-gui.sh:3689 git-gui.sh:3801 git-gui.sh:3812 -msgid "Revert Line" -msgstr "" - -#: git-gui.sh:3694 git-gui.sh:3791 -msgid "Undo Last Revert" -msgstr "" - -#: git-gui.sh:3713 -msgid "Run Merge Tool" -msgstr "" - -#: git-gui.sh:3718 -msgid "Use Remote Version" -msgstr "" - -#: git-gui.sh:3722 -msgid "Use Local Version" -msgstr "" - -#: git-gui.sh:3726 -msgid "Revert To Base" -msgstr "" - -#: git-gui.sh:3744 -msgid "Visualize These Changes In The Submodule" -msgstr "" - -#: git-gui.sh:3748 -msgid "Visualize Current Branch History In The Submodule" -msgstr "" - -#: git-gui.sh:3752 -msgid "Visualize All Branch History In The Submodule" -msgstr "" - -#: git-gui.sh:3757 -msgid "Start git gui In The Submodule" -msgstr "" - -#: git-gui.sh:3793 -msgid "Unstage Hunk From Commit" -msgstr "" - -#: git-gui.sh:3797 -msgid "Unstage Lines From Commit" -msgstr "" - -#: git-gui.sh:3798 git-gui.sh:3809 -msgid "Revert Lines" -msgstr "" - -#: git-gui.sh:3800 -msgid "Unstage Line From Commit" -msgstr "" - -#: git-gui.sh:3804 -msgid "Stage Hunk For Commit" -msgstr "" - -#: git-gui.sh:3808 -msgid "Stage Lines For Commit" -msgstr "" - -#: git-gui.sh:3811 -msgid "Stage Line For Commit" -msgstr "" - -#: git-gui.sh:3861 -msgid "Initializing..." -msgstr "" - -#: git-gui.sh:4017 -#, tcl-format -msgid "" -"Possible environment issues exist.\n" -"\n" -"The following environment variables are probably\n" -"going to be ignored by any Git subprocess run\n" -"by %s:\n" -"\n" -msgstr "" - -#: git-gui.sh:4046 -msgid "" -"\n" -"This is due to a known issue with the\n" -"Tcl binary distributed by Cygwin." -msgstr "" - -#: git-gui.sh:4051 -#, tcl-format -msgid "" -"\n" -"\n" -"A good replacement for %s\n" -"is placing values for the user.name and\n" -"user.email settings into your personal\n" -"~/.gitconfig file.\n" -msgstr "" - -#: lib/spellcheck.tcl:57 -msgid "Unsupported spell checker" -msgstr "" - -#: lib/spellcheck.tcl:65 -msgid "Spell checking is unavailable" -msgstr "" - -#: lib/spellcheck.tcl:68 -msgid "Invalid spell checking configuration" -msgstr "" - -#: lib/spellcheck.tcl:70 -#, tcl-format -msgid "Reverting dictionary to %s." -msgstr "" - -#: lib/spellcheck.tcl:73 -msgid "Spell checker silently failed on startup" -msgstr "" - -#: lib/spellcheck.tcl:80 -msgid "Unrecognized spell checker" -msgstr "" - -#: lib/spellcheck.tcl:186 -msgid "No Suggestions" -msgstr "" - -#: lib/spellcheck.tcl:388 -msgid "Unexpected EOF from spell checker" -msgstr "" - -#: lib/spellcheck.tcl:392 -msgid "Spell Checker Failed" -msgstr "" - -#: lib/transport.tcl:6 lib/remote_add.tcl:132 -#, tcl-format -msgid "fetch %s" -msgstr "" - -#: lib/transport.tcl:7 -#, tcl-format -msgid "Fetching new changes from %s" -msgstr "" - -#: lib/transport.tcl:18 -#, tcl-format -msgid "remote prune %s" -msgstr "" - -#: lib/transport.tcl:19 -#, tcl-format -msgid "Pruning tracking branches deleted from %s" -msgstr "" - -#: lib/transport.tcl:25 -msgid "fetch all remotes" -msgstr "" - -#: lib/transport.tcl:26 -msgid "Fetching new changes from all remotes" -msgstr "" - -#: lib/transport.tcl:40 -msgid "remote prune all remotes" -msgstr "" - -#: lib/transport.tcl:41 -msgid "Pruning tracking branches deleted from all remotes" -msgstr "" - -#: lib/transport.tcl:54 lib/transport.tcl:92 lib/transport.tcl:110 -#: lib/remote_add.tcl:162 -#, tcl-format -msgid "push %s" -msgstr "" - -#: lib/transport.tcl:55 -#, tcl-format -msgid "Pushing changes to %s" -msgstr "" - -#: lib/transport.tcl:93 -#, tcl-format -msgid "Mirroring to %s" -msgstr "" - -#: lib/transport.tcl:111 -#, tcl-format -msgid "Pushing %s %s to %s" -msgstr "" - -#: lib/transport.tcl:132 -msgid "Push Branches" -msgstr "" - -#: lib/transport.tcl:141 lib/checkout_op.tcl:580 lib/remote_add.tcl:34 -#: lib/browser.tcl:292 lib/branch_checkout.tcl:30 lib/branch_rename.tcl:32 -#: lib/choose_font.tcl:45 lib/option.tcl:127 lib/tools_dlg.tcl:41 -#: lib/tools_dlg.tcl:202 lib/tools_dlg.tcl:345 lib/remote_branch_delete.tcl:43 -#: lib/branch_create.tcl:37 lib/branch_delete.tcl:34 lib/merge.tcl:178 -msgid "Cancel" -msgstr "" - -#: lib/transport.tcl:147 -msgid "Source Branches" -msgstr "" - -#: lib/transport.tcl:162 -msgid "Destination Repository" -msgstr "" - -#: lib/transport.tcl:165 lib/remote_branch_delete.tcl:51 -msgid "Remote:" -msgstr "" - -#: lib/transport.tcl:187 lib/remote_branch_delete.tcl:72 -msgid "Arbitrary Location:" -msgstr "" - -#: lib/transport.tcl:205 -msgid "Transfer Options" -msgstr "" - -#: lib/transport.tcl:207 -msgid "Force overwrite existing branch (may discard changes)" -msgstr "" - -#: lib/transport.tcl:211 -msgid "Use thin pack (for slow network connections)" -msgstr "" - -#: lib/transport.tcl:215 -msgid "Include tags" -msgstr "" - -#: lib/transport.tcl:229 -#, tcl-format -msgid "%s (%s): Push" -msgstr "" - -#: lib/checkout_op.tcl:85 -#, tcl-format -msgid "Fetching %s from %s" -msgstr "" - -#: lib/checkout_op.tcl:133 -#, tcl-format -msgid "fatal: Cannot resolve %s" -msgstr "" - -#: lib/checkout_op.tcl:146 lib/sshkey.tcl:58 lib/console.tcl:81 -#: lib/database.tcl:30 -msgid "Close" -msgstr "" - -#: lib/checkout_op.tcl:175 -#, tcl-format -msgid "Branch '%s' does not exist." -msgstr "" - -#: lib/checkout_op.tcl:194 -#, tcl-format -msgid "Failed to configure simplified git-pull for '%s'." -msgstr "" - -#: lib/checkout_op.tcl:202 lib/branch_rename.tcl:102 -#, tcl-format -msgid "Branch '%s' already exists." -msgstr "" - -#: lib/checkout_op.tcl:229 -#, tcl-format -msgid "" -"Branch '%s' already exists.\n" -"\n" -"It cannot fast-forward to %s.\n" -"A merge is required." -msgstr "" - -#: lib/checkout_op.tcl:243 -#, tcl-format -msgid "Merge strategy '%s' not supported." -msgstr "" - -#: lib/checkout_op.tcl:262 -#, tcl-format -msgid "Failed to update '%s'." -msgstr "" - -#: lib/checkout_op.tcl:274 -msgid "Staging area (index) is already locked." -msgstr "" - -#: lib/checkout_op.tcl:289 -msgid "" -"Last scanned state does not match repository state.\n" -"\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before the current branch can be changed.\n" -"\n" -"The rescan will be automatically started now.\n" -msgstr "" - -#: lib/checkout_op.tcl:345 -#, tcl-format -msgid "Updating working directory to '%s'..." -msgstr "" - -#: lib/checkout_op.tcl:346 -msgid "files checked out" -msgstr "" - -#: lib/checkout_op.tcl:377 -#, tcl-format -msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "" - -#: lib/checkout_op.tcl:378 -msgid "File level merge required." -msgstr "" - -#: lib/checkout_op.tcl:382 -#, tcl-format -msgid "Staying on branch '%s'." -msgstr "" - -#: lib/checkout_op.tcl:453 -msgid "" -"You are no longer on a local branch.\n" -"\n" -"If you wanted to be on a branch, create one now starting from 'This Detached " -"Checkout'." -msgstr "" - -#: lib/checkout_op.tcl:504 lib/checkout_op.tcl:508 -#, tcl-format -msgid "Checked out '%s'." -msgstr "" - -#: lib/checkout_op.tcl:536 -#, tcl-format -msgid "Resetting '%s' to '%s' will lose the following commits:" -msgstr "" - -#: lib/checkout_op.tcl:558 -msgid "Recovering lost commits may not be easy." -msgstr "" - -#: lib/checkout_op.tcl:563 -#, tcl-format -msgid "Reset '%s'?" -msgstr "" - -#: lib/checkout_op.tcl:568 lib/tools_dlg.tcl:336 lib/merge.tcl:170 -msgid "Visualize" -msgstr "" - -#: lib/checkout_op.tcl:572 lib/branch_create.tcl:85 -msgid "Reset" -msgstr "" - -#: lib/checkout_op.tcl:636 -#, tcl-format -msgid "" -"Failed to set current branch.\n" -"\n" -"This working directory is only partially switched. We successfully updated " -"your files, but failed to update an internal Git file.\n" -"\n" -"This should not have occurred. %s will now close and give up." -msgstr "" - -#: lib/remote_add.tcl:20 -#, tcl-format -msgid "%s (%s): Add Remote" -msgstr "" - -#: lib/remote_add.tcl:25 -msgid "Add New Remote" -msgstr "" - -#: lib/remote_add.tcl:30 lib/tools_dlg.tcl:37 -msgid "Add" -msgstr "" - -#: lib/remote_add.tcl:39 -msgid "Remote Details" -msgstr "" - -#: lib/remote_add.tcl:41 lib/tools_dlg.tcl:51 lib/branch_create.tcl:44 -msgid "Name:" -msgstr "" - -#: lib/remote_add.tcl:50 -msgid "Location:" -msgstr "" - -#: lib/remote_add.tcl:60 -msgid "Further Action" -msgstr "" - -#: lib/remote_add.tcl:63 -msgid "Fetch Immediately" -msgstr "" - -#: lib/remote_add.tcl:69 -msgid "Initialize Remote Repository and Push" -msgstr "" - -#: lib/remote_add.tcl:75 -msgid "Do Nothing Else Now" -msgstr "" - -#: lib/remote_add.tcl:100 -msgid "Please supply a remote name." -msgstr "" - -#: lib/remote_add.tcl:113 -#, tcl-format -msgid "'%s' is not an acceptable remote name." -msgstr "" - -#: lib/remote_add.tcl:124 -#, tcl-format -msgid "Failed to add remote '%s' of location '%s'." -msgstr "" - -#: lib/remote_add.tcl:133 -#, tcl-format -msgid "Fetching the %s" -msgstr "" - -#: lib/remote_add.tcl:156 -#, tcl-format -msgid "Do not know how to initialize repository at location '%s'." -msgstr "" - -#: lib/remote_add.tcl:163 -#, tcl-format -msgid "Setting up the %s (at %s)" -msgstr "" - -#: lib/browser.tcl:17 -msgid "Starting..." -msgstr "" - -#: lib/browser.tcl:27 -#, tcl-format -msgid "%s (%s): File Browser" -msgstr "" - -#: lib/browser.tcl:132 lib/browser.tcl:149 -#, tcl-format -msgid "Loading %s..." -msgstr "" - -#: lib/browser.tcl:193 -msgid "[Up To Parent]" -msgstr "" - -#: lib/browser.tcl:275 -#, tcl-format -msgid "%s (%s): Browse Branch Files" -msgstr "" - -#: lib/browser.tcl:282 -msgid "Browse Branch Files" -msgstr "" - -#: lib/browser.tcl:288 lib/choose_repository.tcl:437 -#: lib/choose_repository.tcl:524 lib/choose_repository.tcl:533 -#: lib/choose_repository.tcl:1115 -msgid "Browse" -msgstr "" - -#: lib/browser.tcl:297 lib/branch_checkout.tcl:35 lib/tools_dlg.tcl:321 -msgid "Revision" -msgstr "" - -#: lib/index.tcl:6 -msgid "Unable to unlock the index." -msgstr "" - -#: lib/index.tcl:30 -msgid "Index Error" -msgstr "" - -#: lib/index.tcl:32 -msgid "" -"Updating the Git index failed. A rescan will be automatically started to " -"resynchronize git-gui." -msgstr "" - -#: lib/index.tcl:43 -msgid "Continue" -msgstr "" - -#: lib/index.tcl:46 -msgid "Unlock Index" -msgstr "" - -#: lib/index.tcl:77 lib/index.tcl:146 lib/index.tcl:220 lib/index.tcl:587 -#: lib/choose_repository.tcl:999 -msgid "files" -msgstr "" - -#: lib/index.tcl:326 -msgid "Unstaging selected files from commit" -msgstr "" - -#: lib/index.tcl:330 -#, tcl-format -msgid "Unstaging %s from commit" -msgstr "" - -#: lib/index.tcl:369 -msgid "Ready to commit." -msgstr "" - -#: lib/index.tcl:378 -msgid "Adding selected files" -msgstr "" - -#: lib/index.tcl:382 -#, tcl-format -msgid "Adding %s" -msgstr "" - -#: lib/index.tcl:412 -#, tcl-format -msgid "Stage %d untracked files?" -msgstr "" - -#: lib/index.tcl:420 -msgid "Adding all changed files" -msgstr "" - -#: lib/index.tcl:503 -#, tcl-format -msgid "Revert changes in file %s?" -msgstr "" - -#: lib/index.tcl:508 -#, tcl-format -msgid "Revert changes in these %i files?" -msgstr "" - -#: lib/index.tcl:517 -msgid "Any unstaged changes will be permanently lost by the revert." -msgstr "" - -#: lib/index.tcl:520 lib/index.tcl:563 -msgid "Do Nothing" -msgstr "" - -#: lib/index.tcl:545 -#, tcl-format -msgid "Delete untracked file %s?" -msgstr "" - -#: lib/index.tcl:550 -#, tcl-format -msgid "Delete these %i untracked files?" -msgstr "" - -#: lib/index.tcl:560 -msgid "Files will be permanently deleted." -msgstr "" - -#: lib/index.tcl:564 -msgid "Delete Files" -msgstr "" - -#: lib/index.tcl:586 -msgid "Deleting" -msgstr "" - -#: lib/index.tcl:665 -msgid "Encountered errors deleting files:\n" -msgstr "" - -#: lib/index.tcl:674 -#, tcl-format -msgid "None of the %d selected files could be deleted." -msgstr "" - -#: lib/index.tcl:679 -#, tcl-format -msgid "%d of the %d selected files could not be deleted." -msgstr "" - -#: lib/index.tcl:726 -msgid "Reverting selected files" -msgstr "" - -#: lib/index.tcl:730 -#, tcl-format -msgid "Reverting %s" -msgstr "" - -#: lib/branch_checkout.tcl:16 -#, tcl-format -msgid "%s (%s): Checkout Branch" -msgstr "" - -#: lib/branch_checkout.tcl:21 -msgid "Checkout Branch" -msgstr "" - -#: lib/branch_checkout.tcl:26 -msgid "Checkout" -msgstr "" - -#: lib/branch_checkout.tcl:39 lib/option.tcl:310 lib/branch_create.tcl:69 -msgid "Options" -msgstr "" - -#: lib/branch_checkout.tcl:42 lib/branch_create.tcl:92 -msgid "Fetch Tracking Branch" -msgstr "" - -#: lib/branch_checkout.tcl:47 -msgid "Detach From Local Branch" -msgstr "" - -#: lib/status_bar.tcl:263 -#, tcl-format -msgid "%s ... %*i of %*i %s (%3i%%)" -msgstr "" - -#: lib/remote.tcl:200 -msgid "Push to" -msgstr "" - -#: lib/remote.tcl:218 -msgid "Remove Remote" -msgstr "" - -#: lib/remote.tcl:223 -msgid "Prune from" -msgstr "" - -#: lib/remote.tcl:228 -msgid "Fetch from" -msgstr "" - -#: lib/remote.tcl:249 lib/remote.tcl:253 lib/remote.tcl:258 lib/remote.tcl:264 -msgid "All" -msgstr "" - -#: lib/branch_rename.tcl:15 -#, tcl-format -msgid "%s (%s): Rename Branch" -msgstr "" - -#: lib/branch_rename.tcl:23 -msgid "Rename Branch" -msgstr "" - -#: lib/branch_rename.tcl:28 -msgid "Rename" -msgstr "" - -#: lib/branch_rename.tcl:38 -msgid "Branch:" -msgstr "" - -#: lib/branch_rename.tcl:46 -msgid "New Name:" -msgstr "" - -#: lib/branch_rename.tcl:81 -msgid "Please select a branch to rename." -msgstr "" - -#: lib/branch_rename.tcl:92 lib/branch_create.tcl:154 -msgid "Please supply a branch name." -msgstr "" - -#: lib/branch_rename.tcl:112 lib/branch_create.tcl:165 -#, tcl-format -msgid "'%s' is not an acceptable branch name." -msgstr "" - -#: lib/branch_rename.tcl:123 -#, tcl-format -msgid "Failed to rename '%s'." -msgstr "" - -#: lib/choose_font.tcl:41 -msgid "Select" -msgstr "" - -#: lib/choose_font.tcl:55 -msgid "Font Family" -msgstr "" - -#: lib/choose_font.tcl:76 -msgid "Font Size" -msgstr "" - -#: lib/choose_font.tcl:93 -msgid "Font Example" -msgstr "" - -#: lib/choose_font.tcl:105 -msgid "" -"This is example text.\n" -"If you like this text, it can be your font." -msgstr "" - -#: lib/option.tcl:11 -#, tcl-format -msgid "Invalid global encoding '%s'" -msgstr "" - -#: lib/option.tcl:19 -#, tcl-format -msgid "Invalid repo encoding '%s'" -msgstr "" - -#: lib/option.tcl:119 -msgid "Restore Defaults" -msgstr "" - -#: lib/option.tcl:123 -msgid "Save" -msgstr "" - -#: lib/option.tcl:133 -#, tcl-format -msgid "%s Repository" -msgstr "" - -#: lib/option.tcl:134 -msgid "Global (All Repositories)" -msgstr "" - -#: lib/option.tcl:140 -msgid "User Name" -msgstr "" - -#: lib/option.tcl:141 -msgid "Email Address" -msgstr "" - -#: lib/option.tcl:143 -msgid "Summarize Merge Commits" -msgstr "" - -#: lib/option.tcl:144 -msgid "Merge Verbosity" -msgstr "" - -#: lib/option.tcl:145 -msgid "Show Diffstat After Merge" -msgstr "" - -#: lib/option.tcl:146 -msgid "Use Merge Tool" -msgstr "" - -#: lib/option.tcl:148 -msgid "Trust File Modification Timestamps" -msgstr "" - -#: lib/option.tcl:149 -msgid "Prune Tracking Branches During Fetch" -msgstr "" - -#: lib/option.tcl:150 -msgid "Match Tracking Branches" -msgstr "" - -#: lib/option.tcl:151 -msgid "Use Textconv For Diffs and Blames" -msgstr "" - -#: lib/option.tcl:152 -msgid "Blame Copy Only On Changed Files" -msgstr "" - -#: lib/option.tcl:153 -msgid "Maximum Length of Recent Repositories List" -msgstr "" - -#: lib/option.tcl:154 -msgid "Minimum Letters To Blame Copy On" -msgstr "" - -#: lib/option.tcl:155 -msgid "Blame History Context Radius (days)" -msgstr "" - -#: lib/option.tcl:156 -msgid "Number of Diff Context Lines" -msgstr "" - -#: lib/option.tcl:157 -msgid "Additional Diff Parameters" -msgstr "" - -#: lib/option.tcl:158 -msgid "Commit Message Text Width" -msgstr "" - -#: lib/option.tcl:159 -msgid "New Branch Name Template" -msgstr "" - -#: lib/option.tcl:160 -msgid "Default File Contents Encoding" -msgstr "" - -#: lib/option.tcl:161 -msgid "Warn before committing to a detached head" -msgstr "" - -#: lib/option.tcl:162 -msgid "Staging of untracked files" -msgstr "" - -#: lib/option.tcl:163 -msgid "Show untracked files" -msgstr "" - -#: lib/option.tcl:164 -msgid "Tab spacing" -msgstr "" - -#: lib/option.tcl:182 lib/option.tcl:197 lib/option.tcl:220 lib/option.tcl:282 -#: lib/database.tcl:57 -#, tcl-format -msgid "%s:" -msgstr "" - -#: lib/option.tcl:210 -msgid "Change" -msgstr "" - -#: lib/option.tcl:254 -msgid "Spelling Dictionary:" -msgstr "" - -#: lib/option.tcl:284 -msgid "Change Font" -msgstr "" - -#: lib/option.tcl:288 -#, tcl-format -msgid "Choose %s" -msgstr "" - -#: lib/option.tcl:294 -msgid "pt." -msgstr "" - -#: lib/option.tcl:308 -msgid "Preferences" -msgstr "" - -#: lib/option.tcl:345 -msgid "Failed to completely save options:" -msgstr "" - -#: lib/encoding.tcl:443 -msgid "Default" -msgstr "" - -#: lib/encoding.tcl:448 -#, tcl-format -msgid "System (%s)" -msgstr "" - -#: lib/encoding.tcl:459 lib/encoding.tcl:465 -msgid "Other" -msgstr "" - -#: lib/tools.tcl:76 -#, tcl-format -msgid "Running %s requires a selected file." -msgstr "" - -#: lib/tools.tcl:92 -#, tcl-format -msgid "Are you sure you want to run %1$s on file \"%2$s\"?" -msgstr "" - -#: lib/tools.tcl:96 -#, tcl-format -msgid "Are you sure you want to run %s?" -msgstr "" - -#: lib/tools.tcl:118 -#, tcl-format -msgid "Tool: %s" -msgstr "" - -#: lib/tools.tcl:119 -#, tcl-format -msgid "Running: %s" -msgstr "" - -#: lib/tools.tcl:158 -#, tcl-format -msgid "Tool completed successfully: %s" -msgstr "" - -#: lib/tools.tcl:160 -#, tcl-format -msgid "Tool failed: %s" -msgstr "" - -#: lib/mergetool.tcl:8 -msgid "Force resolution to the base version?" -msgstr "" - -#: lib/mergetool.tcl:9 -msgid "Force resolution to this branch?" -msgstr "" - -#: lib/mergetool.tcl:10 -msgid "Force resolution to the other branch?" -msgstr "" - -#: lib/mergetool.tcl:14 -#, tcl-format -msgid "" -"Note that the diff shows only conflicting changes.\n" -"\n" -"%s will be overwritten.\n" -"\n" -"This operation can be undone only by restarting the merge." -msgstr "" - -#: lib/mergetool.tcl:45 -#, tcl-format -msgid "File %s seems to have unresolved conflicts, still stage?" -msgstr "" - -#: lib/mergetool.tcl:60 -#, tcl-format -msgid "Adding resolution for %s" -msgstr "" - -#: lib/mergetool.tcl:141 -msgid "Cannot resolve deletion or link conflicts using a tool" -msgstr "" - -#: lib/mergetool.tcl:146 -msgid "Conflict file does not exist" -msgstr "" - -#: lib/mergetool.tcl:246 -#, tcl-format -msgid "Not a GUI merge tool: '%s'" -msgstr "" - -#: lib/mergetool.tcl:275 -#, tcl-format -msgid "Unsupported merge tool '%s'" -msgstr "" - -#: lib/mergetool.tcl:310 -msgid "Merge tool is already running, terminate it?" -msgstr "" - -#: lib/mergetool.tcl:330 -#, tcl-format -msgid "" -"Error retrieving versions:\n" -"%s" -msgstr "" - -#: lib/mergetool.tcl:350 -#, tcl-format -msgid "" -"Could not start the merge tool:\n" -"\n" -"%s" -msgstr "" - -#: lib/mergetool.tcl:354 -msgid "Running merge tool..." -msgstr "" - -#: lib/mergetool.tcl:382 lib/mergetool.tcl:390 -msgid "Merge tool failed." -msgstr "" - -#: lib/tools_dlg.tcl:22 -#, tcl-format -msgid "%s (%s): Add Tool" -msgstr "" - -#: lib/tools_dlg.tcl:28 -msgid "Add New Tool Command" -msgstr "" - -#: lib/tools_dlg.tcl:34 -msgid "Add globally" -msgstr "" - -#: lib/tools_dlg.tcl:46 -msgid "Tool Details" -msgstr "" - -#: lib/tools_dlg.tcl:49 -msgid "Use '/' separators to create a submenu tree:" -msgstr "" - -#: lib/tools_dlg.tcl:60 -msgid "Command:" -msgstr "" - -#: lib/tools_dlg.tcl:71 -msgid "Show a dialog before running" -msgstr "" - -#: lib/tools_dlg.tcl:77 -msgid "Ask the user to select a revision (sets $REVISION)" -msgstr "" - -#: lib/tools_dlg.tcl:82 -msgid "Ask the user for additional arguments (sets $ARGS)" -msgstr "" - -#: lib/tools_dlg.tcl:89 -msgid "Don't show the command output window" -msgstr "" - -#: lib/tools_dlg.tcl:94 -msgid "Run only if a diff is selected ($FILENAME not empty)" -msgstr "" - -#: lib/tools_dlg.tcl:118 -msgid "Please supply a name for the tool." -msgstr "" - -#: lib/tools_dlg.tcl:126 -#, tcl-format -msgid "Tool '%s' already exists." -msgstr "" - -#: lib/tools_dlg.tcl:148 -#, tcl-format -msgid "" -"Could not add tool:\n" -"%s" -msgstr "" - -#: lib/tools_dlg.tcl:187 -#, tcl-format -msgid "%s (%s): Remove Tool" -msgstr "" - -#: lib/tools_dlg.tcl:193 -msgid "Remove Tool Commands" -msgstr "" - -#: lib/tools_dlg.tcl:198 -msgid "Remove" -msgstr "" - -#: lib/tools_dlg.tcl:231 -msgid "(Blue denotes repository-local tools)" -msgstr "" - -#: lib/tools_dlg.tcl:283 -#, tcl-format -msgid "%s (%s):" -msgstr "" - -#: lib/tools_dlg.tcl:292 -#, tcl-format -msgid "Run Command: %s" -msgstr "" - -#: lib/tools_dlg.tcl:306 -msgid "Arguments" -msgstr "" - -#: lib/tools_dlg.tcl:341 -msgid "OK" -msgstr "" - -#: lib/search.tcl:48 -msgid "Find:" -msgstr "" - -#: lib/search.tcl:50 -msgid "Next" -msgstr "" - -#: lib/search.tcl:51 -msgid "Prev" -msgstr "" - -#: lib/search.tcl:52 -msgid "RegExp" -msgstr "" - -#: lib/search.tcl:54 -msgid "Case" -msgstr "" - -#: lib/shortcut.tcl:8 lib/shortcut.tcl:43 lib/shortcut.tcl:75 -#, tcl-format -msgid "%s (%s): Create Desktop Icon" -msgstr "" - -#: lib/shortcut.tcl:24 lib/shortcut.tcl:65 -msgid "Cannot write shortcut:" -msgstr "" - -#: lib/shortcut.tcl:140 -msgid "Cannot write icon:" -msgstr "" - -#: lib/remote_branch_delete.tcl:29 -#, tcl-format -msgid "%s (%s): Delete Branch Remotely" -msgstr "" - -#: lib/remote_branch_delete.tcl:34 -msgid "Delete Branch Remotely" -msgstr "" - -#: lib/remote_branch_delete.tcl:48 -msgid "From Repository" -msgstr "" - -#: lib/remote_branch_delete.tcl:88 -msgid "Branches" -msgstr "" - -#: lib/remote_branch_delete.tcl:110 -msgid "Delete Only If" -msgstr "" - -#: lib/remote_branch_delete.tcl:112 -msgid "Merged Into:" -msgstr "" - -#: lib/remote_branch_delete.tcl:120 lib/branch_delete.tcl:53 -msgid "Always (Do not perform merge checks)" -msgstr "" - -#: lib/remote_branch_delete.tcl:153 -msgid "A branch is required for 'Merged Into'." -msgstr "" - -#: lib/remote_branch_delete.tcl:185 -#, tcl-format -msgid "" -"The following branches are not completely merged into %s:\n" -"\n" -" - %s" -msgstr "" - -#: lib/remote_branch_delete.tcl:190 -#, tcl-format -msgid "" -"One or more of the merge tests failed because you have not fetched the " -"necessary commits. Try fetching from %s first." -msgstr "" - -#: lib/remote_branch_delete.tcl:208 -msgid "Please select one or more branches to delete." -msgstr "" - -#: lib/remote_branch_delete.tcl:218 lib/branch_delete.tcl:115 -msgid "" -"Recovering deleted branches is difficult.\n" -"\n" -"Delete the selected branches?" -msgstr "" - -#: lib/remote_branch_delete.tcl:227 -#, tcl-format -msgid "Deleting branches from %s" -msgstr "" - -#: lib/remote_branch_delete.tcl:300 -msgid "No repository selected." -msgstr "" - -#: lib/remote_branch_delete.tcl:305 -#, tcl-format -msgid "Scanning %s..." -msgstr "" - -#: lib/choose_repository.tcl:45 -msgid "Git Gui" -msgstr "" - -#: lib/choose_repository.tcl:104 lib/choose_repository.tcl:427 -msgid "Create New Repository" -msgstr "" - -#: lib/choose_repository.tcl:110 -msgid "New..." -msgstr "" - -#: lib/choose_repository.tcl:117 lib/choose_repository.tcl:511 -msgid "Clone Existing Repository" -msgstr "" - -#: lib/choose_repository.tcl:128 -msgid "Clone..." -msgstr "" - -#: lib/choose_repository.tcl:135 lib/choose_repository.tcl:1105 -msgid "Open Existing Repository" -msgstr "" - -#: lib/choose_repository.tcl:141 -msgid "Open..." -msgstr "" - -#: lib/choose_repository.tcl:154 -msgid "Recent Repositories" -msgstr "" - -#: lib/choose_repository.tcl:164 -msgid "Open Recent Repository:" -msgstr "" - -#: lib/choose_repository.tcl:331 lib/choose_repository.tcl:338 -#: lib/choose_repository.tcl:345 -#, tcl-format -msgid "Failed to create repository %s:" -msgstr "" - -#: lib/choose_repository.tcl:422 lib/branch_create.tcl:33 -msgid "Create" -msgstr "" - -#: lib/choose_repository.tcl:432 -msgid "Directory:" -msgstr "" - -#: lib/choose_repository.tcl:462 lib/choose_repository.tcl:588 -#: lib/choose_repository.tcl:1139 -msgid "Git Repository" -msgstr "" - -#: lib/choose_repository.tcl:487 -#, tcl-format -msgid "Directory %s already exists." -msgstr "" - -#: lib/choose_repository.tcl:491 -#, tcl-format -msgid "File %s already exists." -msgstr "" - -#: lib/choose_repository.tcl:506 -msgid "Clone" -msgstr "" - -#: lib/choose_repository.tcl:519 -msgid "Source Location:" -msgstr "" - -#: lib/choose_repository.tcl:528 -msgid "Target Directory:" -msgstr "" - -#: lib/choose_repository.tcl:538 -msgid "Clone Type:" -msgstr "" - -#: lib/choose_repository.tcl:543 -msgid "Standard (Fast, Semi-Redundant, Hardlinks)" -msgstr "" - -#: lib/choose_repository.tcl:548 -msgid "Full Copy (Slower, Redundant Backup)" -msgstr "" - -#: lib/choose_repository.tcl:553 -msgid "Shared (Fastest, Not Recommended, No Backup)" -msgstr "" - -#: lib/choose_repository.tcl:560 -msgid "Recursively clone submodules too" -msgstr "" - -#: lib/choose_repository.tcl:594 lib/choose_repository.tcl:641 -#: lib/choose_repository.tcl:790 lib/choose_repository.tcl:864 -#: lib/choose_repository.tcl:1145 lib/choose_repository.tcl:1153 -#, tcl-format -msgid "Not a Git repository: %s" -msgstr "" - -#: lib/choose_repository.tcl:630 -msgid "Standard only available for local repository." -msgstr "" - -#: lib/choose_repository.tcl:634 -msgid "Shared only available for local repository." -msgstr "" - -#: lib/choose_repository.tcl:655 -#, tcl-format -msgid "Location %s already exists." -msgstr "" - -#: lib/choose_repository.tcl:666 -msgid "Failed to configure origin" -msgstr "" - -#: lib/choose_repository.tcl:678 -msgid "Counting objects" -msgstr "" - -#: lib/choose_repository.tcl:679 -msgid "buckets" -msgstr "" - -#: lib/choose_repository.tcl:703 -#, tcl-format -msgid "Unable to copy objects/info/alternates: %s" -msgstr "" - -#: lib/choose_repository.tcl:740 -#, tcl-format -msgid "Nothing to clone from %s." -msgstr "" - -#: lib/choose_repository.tcl:742 lib/choose_repository.tcl:962 -#: lib/choose_repository.tcl:974 -msgid "The 'master' branch has not been initialized." -msgstr "" - -#: lib/choose_repository.tcl:755 -msgid "Hardlinks are unavailable. Falling back to copying." -msgstr "" - -#: lib/choose_repository.tcl:769 -#, tcl-format -msgid "Cloning from %s" -msgstr "" - -#: lib/choose_repository.tcl:800 -msgid "Copying objects" -msgstr "" - -#: lib/choose_repository.tcl:801 -msgid "KiB" -msgstr "" - -#: lib/choose_repository.tcl:825 -#, tcl-format -msgid "Unable to copy object: %s" -msgstr "" - -#: lib/choose_repository.tcl:837 -msgid "Linking objects" -msgstr "" - -#: lib/choose_repository.tcl:838 -msgid "objects" -msgstr "" - -#: lib/choose_repository.tcl:846 -#, tcl-format -msgid "Unable to hardlink object: %s" -msgstr "" - -#: lib/choose_repository.tcl:903 -msgid "Cannot fetch branches and objects. See console output for details." -msgstr "" - -#: lib/choose_repository.tcl:914 -msgid "Cannot fetch tags. See console output for details." -msgstr "" - -#: lib/choose_repository.tcl:938 -msgid "Cannot determine HEAD. See console output for details." -msgstr "" - -#: lib/choose_repository.tcl:947 -#, tcl-format -msgid "Unable to cleanup %s" -msgstr "" - -#: lib/choose_repository.tcl:953 -msgid "Clone failed." -msgstr "" - -#: lib/choose_repository.tcl:960 -msgid "No default branch obtained." -msgstr "" - -#: lib/choose_repository.tcl:971 -#, tcl-format -msgid "Cannot resolve %s as a commit." -msgstr "" - -#: lib/choose_repository.tcl:998 -msgid "Creating working directory" -msgstr "" - -#: lib/choose_repository.tcl:1028 -msgid "Initial file checkout failed." -msgstr "" - -#: lib/choose_repository.tcl:1072 -msgid "Cloning submodules" -msgstr "" - -#: lib/choose_repository.tcl:1087 -msgid "Cannot clone submodules." -msgstr "" - -#: lib/choose_repository.tcl:1110 -msgid "Repository:" -msgstr "" - -#: lib/choose_repository.tcl:1159 -#, tcl-format -msgid "Failed to open repository %s:" -msgstr "" - -#: lib/about.tcl:26 -msgid "git-gui - a graphical user interface for Git." -msgstr "" - -#: lib/blame.tcl:74 -#, tcl-format -msgid "%s (%s): File Viewer" -msgstr "" - -#: lib/blame.tcl:80 -msgid "Commit:" -msgstr "" - -#: lib/blame.tcl:282 -msgid "Copy Commit" -msgstr "" - -#: lib/blame.tcl:286 -msgid "Find Text..." -msgstr "" - -#: lib/blame.tcl:290 -msgid "Goto Line..." -msgstr "" - -#: lib/blame.tcl:299 -msgid "Do Full Copy Detection" -msgstr "" - -#: lib/blame.tcl:303 -msgid "Show History Context" -msgstr "" - -#: lib/blame.tcl:306 -msgid "Blame Parent Commit" -msgstr "" - -#: lib/blame.tcl:468 -#, tcl-format -msgid "Reading %s..." -msgstr "" - -#: lib/blame.tcl:596 -msgid "Loading copy/move tracking annotations..." -msgstr "" - -#: lib/blame.tcl:613 -msgid "lines annotated" -msgstr "" - -#: lib/blame.tcl:815 -msgid "Loading original location annotations..." -msgstr "" - -#: lib/blame.tcl:818 -msgid "Annotation complete." -msgstr "" - -#: lib/blame.tcl:849 -msgid "Busy" -msgstr "" - -#: lib/blame.tcl:850 -msgid "Annotation process is already running." -msgstr "" - -#: lib/blame.tcl:889 -msgid "Running thorough copy detection..." -msgstr "" - -#: lib/blame.tcl:957 -msgid "Loading annotation..." -msgstr "" - -#: lib/blame.tcl:1010 -msgid "Author:" -msgstr "" - -#: lib/blame.tcl:1014 -msgid "Committer:" -msgstr "" - -#: lib/blame.tcl:1019 -msgid "Original File:" -msgstr "" - -#: lib/blame.tcl:1067 -msgid "Cannot find HEAD commit:" -msgstr "" - -#: lib/blame.tcl:1122 -msgid "Cannot find parent commit:" -msgstr "" - -#: lib/blame.tcl:1137 -msgid "Unable to display parent" -msgstr "" - -#: lib/blame.tcl:1138 lib/diff.tcl:345 -msgid "Error loading diff:" -msgstr "" - -#: lib/blame.tcl:1279 -msgid "Originally By:" -msgstr "" - -#: lib/blame.tcl:1285 -msgid "In File:" -msgstr "" - -#: lib/blame.tcl:1290 -msgid "Copied Or Moved Here By:" -msgstr "" - -#: lib/diff.tcl:77 -#, tcl-format -msgid "" -"No differences detected.\n" -"\n" -"%s has no changes.\n" -"\n" -"The modification date of this file was updated by another application, but " -"the content within the file was not changed.\n" -"\n" -"A rescan will be automatically started to find other files which may have " -"the same state." -msgstr "" - -#: lib/diff.tcl:117 -#, tcl-format -msgid "Loading diff of %s..." -msgstr "" - -#: lib/diff.tcl:143 -msgid "" -"LOCAL: deleted\n" -"REMOTE:\n" -msgstr "" - -#: lib/diff.tcl:148 -msgid "" -"REMOTE: deleted\n" -"LOCAL:\n" -msgstr "" - -#: lib/diff.tcl:155 -msgid "LOCAL:\n" -msgstr "" - -#: lib/diff.tcl:158 -msgid "REMOTE:\n" -msgstr "" - -#: lib/diff.tcl:220 lib/diff.tcl:344 -#, tcl-format -msgid "Unable to display %s" -msgstr "" - -#: lib/diff.tcl:221 -msgid "Error loading file:" -msgstr "" - -#: lib/diff.tcl:227 -msgid "Git Repository (subproject)" -msgstr "" - -#: lib/diff.tcl:239 -msgid "* Binary file (not showing content)." -msgstr "" - -#: lib/diff.tcl:244 -#, tcl-format -msgid "" -"* Untracked file is %d bytes.\n" -"* Showing only first %d bytes.\n" -msgstr "" - -#: lib/diff.tcl:250 -#, tcl-format -msgid "" -"\n" -"* Untracked file clipped here by %s.\n" -"* To see the entire file, use an external editor.\n" -msgstr "" - -#: lib/diff.tcl:583 -msgid "Failed to unstage selected hunk." -msgstr "" - -#: lib/diff.tcl:591 -msgid "Failed to revert selected hunk." -msgstr "" - -#: lib/diff.tcl:594 -msgid "Failed to stage selected hunk." -msgstr "" - -#: lib/diff.tcl:687 -msgid "Failed to unstage selected line." -msgstr "" - -#: lib/diff.tcl:696 -msgid "Failed to revert selected line." -msgstr "" - -#: lib/diff.tcl:700 -msgid "Failed to stage selected line." -msgstr "" - -#: lib/diff.tcl:889 -msgid "Failed to undo last revert." -msgstr "" - -#: lib/sshkey.tcl:34 -msgid "No keys found." -msgstr "" - -#: lib/sshkey.tcl:37 -#, tcl-format -msgid "Found a public key in: %s" -msgstr "" - -#: lib/sshkey.tcl:43 -msgid "Generate Key" -msgstr "" - -#: lib/sshkey.tcl:61 -msgid "Copy To Clipboard" -msgstr "" - -#: lib/sshkey.tcl:75 -msgid "Your OpenSSH Public Key" -msgstr "" - -#: lib/sshkey.tcl:83 -msgid "Generating..." -msgstr "" - -#: lib/sshkey.tcl:89 -#, tcl-format -msgid "" -"Could not start ssh-keygen:\n" -"\n" -"%s" -msgstr "" - -#: lib/sshkey.tcl:116 -msgid "Generation failed." -msgstr "" - -#: lib/sshkey.tcl:123 -msgid "Generation succeeded, but no keys found." -msgstr "" - -#: lib/sshkey.tcl:126 -#, tcl-format -msgid "Your key is in: %s" -msgstr "" - -#: lib/branch_create.tcl:23 -#, tcl-format -msgid "%s (%s): Create Branch" -msgstr "" - -#: lib/branch_create.tcl:28 -msgid "Create New Branch" -msgstr "" - -#: lib/branch_create.tcl:42 -msgid "Branch Name" -msgstr "" - -#: lib/branch_create.tcl:57 -msgid "Match Tracking Branch Name" -msgstr "" - -#: lib/branch_create.tcl:66 -msgid "Starting Revision" -msgstr "" - -#: lib/branch_create.tcl:72 -msgid "Update Existing Branch:" -msgstr "" - -#: lib/branch_create.tcl:75 -msgid "No" -msgstr "" - -#: lib/branch_create.tcl:80 -msgid "Fast Forward Only" -msgstr "" - -#: lib/branch_create.tcl:97 -msgid "Checkout After Creation" -msgstr "" - -#: lib/branch_create.tcl:132 -msgid "Please select a tracking branch." -msgstr "" - -#: lib/branch_create.tcl:141 -#, tcl-format -msgid "Tracking branch %s is not a branch in the remote repository." -msgstr "" - -#: lib/console.tcl:59 -msgid "Working... please wait..." -msgstr "" - -#: lib/console.tcl:186 -msgid "Success" -msgstr "" - -#: lib/console.tcl:200 -msgid "Error: Command Failed" -msgstr "" - -#: lib/line.tcl:17 -msgid "Goto Line:" -msgstr "" - -#: lib/line.tcl:23 -msgid "Go" -msgstr "" - -#: lib/choose_rev.tcl:52 -msgid "This Detached Checkout" -msgstr "" - -#: lib/choose_rev.tcl:60 -msgid "Revision Expression:" -msgstr "" - -#: lib/choose_rev.tcl:72 -msgid "Local Branch" -msgstr "" - -#: lib/choose_rev.tcl:77 -msgid "Tracking Branch" -msgstr "" - -#: lib/choose_rev.tcl:82 lib/choose_rev.tcl:544 -msgid "Tag" -msgstr "" - -#: lib/choose_rev.tcl:321 -#, tcl-format -msgid "Invalid revision: %s" -msgstr "" - -#: lib/choose_rev.tcl:342 -msgid "No revision selected." -msgstr "" - -#: lib/choose_rev.tcl:350 -msgid "Revision expression is empty." -msgstr "" - -#: lib/choose_rev.tcl:537 -msgid "Updated" -msgstr "" - -#: lib/choose_rev.tcl:565 -msgid "URL" -msgstr "" - -#: lib/commit.tcl:9 -msgid "" -"There is nothing to amend.\n" -"\n" -"You are about to create the initial commit. There is no commit before this " -"to amend.\n" -msgstr "" - -#: lib/commit.tcl:18 -msgid "" -"Cannot amend while merging.\n" -"\n" -"You are currently in the middle of a merge that has not been fully " -"completed. You cannot amend the prior commit unless you first abort the " -"current merge activity.\n" -msgstr "" - -#: lib/commit.tcl:56 -msgid "Error loading commit data for amend:" -msgstr "" - -#: lib/commit.tcl:83 -msgid "Unable to obtain your identity:" -msgstr "" - -#: lib/commit.tcl:88 -msgid "Invalid GIT_COMMITTER_IDENT:" -msgstr "" - -#: lib/commit.tcl:138 -#, tcl-format -msgid "warning: Tcl does not support encoding '%s'." -msgstr "" - -#: lib/commit.tcl:158 -msgid "" -"Last scanned state does not match repository state.\n" -"\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before another commit can be created.\n" -"\n" -"The rescan will be automatically started now.\n" -msgstr "" - -#: lib/commit.tcl:182 -#, tcl-format -msgid "" -"Unmerged files cannot be committed.\n" -"\n" -"File %s has merge conflicts. You must resolve them and stage the file " -"before committing.\n" -msgstr "" - -#: lib/commit.tcl:190 -#, tcl-format -msgid "" -"Unknown file state %s detected.\n" -"\n" -"File %s cannot be committed by this program.\n" -msgstr "" - -#: lib/commit.tcl:198 -msgid "" -"No changes to commit.\n" -"\n" -"You must stage at least 1 file before you can commit.\n" -msgstr "" - -#: lib/commit.tcl:213 -msgid "" -"Please supply a commit message.\n" -"\n" -"A good commit message has the following format:\n" -"\n" -"- First line: Describe in one sentence what you did.\n" -"- Second line: Blank\n" -"- Remaining lines: Describe why this change is good.\n" -msgstr "" - -#: lib/commit.tcl:244 -msgid "Calling pre-commit hook..." -msgstr "" - -#: lib/commit.tcl:259 -msgid "Commit declined by pre-commit hook." -msgstr "" - -#: lib/commit.tcl:278 -msgid "" -"You are about to commit on a detached head. This is a potentially dangerous " -"thing to do because if you switch to another branch you will lose your " -"changes and it can be difficult to retrieve them later from the reflog. You " -"should probably cancel this commit and create a new branch to continue.\n" -" \n" -" Do you really want to proceed with your Commit?" -msgstr "" - -#: lib/commit.tcl:299 -msgid "Calling commit-msg hook..." -msgstr "" - -#: lib/commit.tcl:314 -msgid "Commit declined by commit-msg hook." -msgstr "" - -#: lib/commit.tcl:327 -msgid "Committing changes..." -msgstr "" - -#: lib/commit.tcl:344 -msgid "write-tree failed:" -msgstr "" - -#: lib/commit.tcl:345 lib/commit.tcl:395 lib/commit.tcl:422 -msgid "Commit failed." -msgstr "" - -#: lib/commit.tcl:362 -#, tcl-format -msgid "Commit %s appears to be corrupt" -msgstr "" - -#: lib/commit.tcl:367 -msgid "" -"No changes to commit.\n" -"\n" -"No files were modified by this commit and it was not a merge commit.\n" -"\n" -"A rescan will be automatically started now.\n" -msgstr "" - -#: lib/commit.tcl:374 -msgid "No changes to commit." -msgstr "" - -#: lib/commit.tcl:394 -msgid "commit-tree failed:" -msgstr "" - -#: lib/commit.tcl:421 -msgid "update-ref failed:" -msgstr "" - -#: lib/commit.tcl:514 -#, tcl-format -msgid "Created commit %s: %s" -msgstr "" - -#: lib/branch_delete.tcl:16 -#, tcl-format -msgid "%s (%s): Delete Branch" -msgstr "" - -#: lib/branch_delete.tcl:21 -msgid "Delete Local Branch" -msgstr "" - -#: lib/branch_delete.tcl:39 -msgid "Local Branches" -msgstr "" - -#: lib/branch_delete.tcl:51 -msgid "Delete Only If Merged Into" -msgstr "" - -#: lib/branch_delete.tcl:103 -#, tcl-format -msgid "The following branches are not completely merged into %s:" -msgstr "" - -#: lib/branch_delete.tcl:131 -#, tcl-format -msgid " - %s:" -msgstr "" - -#: lib/branch_delete.tcl:141 -#, tcl-format -msgid "" -"Failed to delete branches:\n" -"%s" -msgstr "" - -#: lib/date.tcl:25 -#, tcl-format -msgid "Invalid date from Git: %s" -msgstr "" - -#: lib/database.tcl:42 -msgid "Number of loose objects" -msgstr "" - -#: lib/database.tcl:43 -msgid "Disk space used by loose objects" -msgstr "" - -#: lib/database.tcl:44 -msgid "Number of packed objects" -msgstr "" - -#: lib/database.tcl:45 -msgid "Number of packs" -msgstr "" - -#: lib/database.tcl:46 -msgid "Disk space used by packed objects" -msgstr "" - -#: lib/database.tcl:47 -msgid "Packed objects waiting for pruning" -msgstr "" - -#: lib/database.tcl:48 -msgid "Garbage files" -msgstr "" - -#: lib/database.tcl:66 -#, tcl-format -msgid "%s (%s): Database Statistics" -msgstr "" - -#: lib/database.tcl:72 -msgid "Compressing the object database" -msgstr "" - -#: lib/database.tcl:83 -msgid "Verifying the object database with fsck-objects" -msgstr "" - -#: lib/database.tcl:107 -#, tcl-format -msgid "" -"This repository currently has approximately %i loose objects.\n" -"\n" -"To maintain optimal performance it is strongly recommended that you compress " -"the database.\n" -"\n" -"Compress the database now?" -msgstr "" - -#: lib/error.tcl:20 -#, tcl-format -msgid "%s: error" -msgstr "" - -#: lib/error.tcl:36 -#, tcl-format -msgid "%s: warning" -msgstr "" - -#: lib/error.tcl:80 -#, tcl-format -msgid "%s hook failed:" -msgstr "" - -#: lib/error.tcl:96 -msgid "You must correct the above errors before committing." -msgstr "" - -#: lib/error.tcl:116 -#, tcl-format -msgid "%s (%s): error" -msgstr "" - -#: lib/merge.tcl:13 -msgid "" -"Cannot merge while amending.\n" -"\n" -"You must finish amending this commit before starting any type of merge.\n" -msgstr "" - -#: lib/merge.tcl:27 -msgid "" -"Last scanned state does not match repository state.\n" -"\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before a merge can be performed.\n" -"\n" -"The rescan will be automatically started now.\n" -msgstr "" - -#: lib/merge.tcl:45 -#, tcl-format -msgid "" -"You are in the middle of a conflicted merge.\n" -"\n" -"File %s has merge conflicts.\n" -"\n" -"You must resolve them, stage the file, and commit to complete the current " -"merge. Only then can you begin another merge.\n" -msgstr "" - -#: lib/merge.tcl:55 -#, tcl-format -msgid "" -"You are in the middle of a change.\n" -"\n" -"File %s is modified.\n" -"\n" -"You should complete the current commit before starting a merge. Doing so " -"will help you abort a failed merge, should the need arise.\n" -msgstr "" - -#: lib/merge.tcl:108 -#, tcl-format -msgid "%s of %s" -msgstr "" - -#: lib/merge.tcl:126 -#, tcl-format -msgid "Merging %s and %s..." -msgstr "" - -#: lib/merge.tcl:137 -msgid "Merge completed successfully." -msgstr "" - -#: lib/merge.tcl:139 -msgid "Merge failed. Conflict resolution is required." -msgstr "" - -#: lib/merge.tcl:156 -#, tcl-format -msgid "%s (%s): Merge" -msgstr "" - -#: lib/merge.tcl:164 -#, tcl-format -msgid "Merge Into %s" -msgstr "" - -#: lib/merge.tcl:183 -msgid "Revision To Merge" -msgstr "" - -#: lib/merge.tcl:218 -msgid "" -"Cannot abort while amending.\n" -"\n" -"You must finish amending this commit.\n" -msgstr "" - -#: lib/merge.tcl:228 -msgid "" -"Abort merge?\n" -"\n" -"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" -"\n" -"Continue with aborting the current merge?" -msgstr "" - -#: lib/merge.tcl:234 -msgid "" -"Reset changes?\n" -"\n" -"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" -"\n" -"Continue with resetting the current changes?" -msgstr "" - -#: lib/merge.tcl:246 -msgid "Aborting" -msgstr "" - -#: lib/merge.tcl:247 -msgid "files reset" -msgstr "" - -#: lib/merge.tcl:277 -msgid "Abort failed." -msgstr "" - -#: lib/merge.tcl:279 -msgid "Abort completed. Ready." -msgstr "" diff --git a/git-gui/po/meson.build b/git-gui/po/meson.build new file mode 100644 index 0000000000..00cae74338 --- /dev/null +++ b/git-gui/po/meson.build @@ -0,0 +1,38 @@ +languages = [ + 'bg', + 'de', + 'el', + 'fr', + 'hu', + 'it', + 'ja', + 'nb', + 'pt_br', + 'pt_pt', + 'ru', + 'sv', + 'vi', + 'zh_cn', +] + +msgfmt = find_program('msgfmt', required: false) +if not msgfmt.found() + subdir_done() +endif + +foreach language : languages + custom_target( + input: language + '.po', + output: language + '.msg', + command: [ + msgfmt, + '--statistics', + '--tcl', + '--locale=' + language, + '-d', meson.current_build_dir(), + '@INPUT@', + ], + install: true, + install_dir: get_option('datadir') / 'git-gui/lib/msgs', + ) +endforeach diff --git a/git-request-pull.sh b/git-request-pull.sh index 775ba8ea11..6a7b793678 100755 --- a/git-request-pull.sh +++ b/git-request-pull.sh @@ -78,41 +78,47 @@ fi merge_base=$(git merge-base $baserev $headrev) || die "fatal: No commits in common between $base and $head" -# $head is the refname from the command line. -# Find a ref with the same name as $head that exists at the remote +find_matching_ref () { + while read sha1 ref + do + case "$ref" in + *"^"?*) + ref="${ref%"^"*}" + deref=true + ;; + *) + deref= + ;; + esac + + if test "$sha1" = "${remote:-HEAD}" + then + echo "$sha1 $sha1" + break + fi + + case "$ref" in + "${remote:-HEAD}"|*"/${remote:-HEAD}") + if test -z "$deref" + then + # Remember the matching unpeeled object on the + # remote side. + remote_sha1="$sha1" + fi + + if test "$sha1" = "$headrev" + then + echo "${remote_sha1:-$headrev} $ref" + break + fi + ;; + esac + done +} + +# Find a ref with the same name as $remote that exists at the remote # and points to the same commit as the local object. -find_matching_ref=' - my ($head,$headrev) = (@ARGV); - my $pattern = qr{/\Q$head\E$}; - my ($remote_sha1, $found); - - while (<STDIN>) { - chomp; - my ($sha1, $ref, $deref) = /^(\S+)\s+([^^]+)(\S*)$/; - - if ($sha1 eq $head) { - $found = $remote_sha1 = $sha1; - break; - } - - if ($ref eq $head || $ref =~ $pattern) { - if ($deref eq "") { - # Remember the matching object on the remote side - $remote_sha1 = $sha1; - } - if ($sha1 eq $headrev) { - $found = $ref; - break; - } - } - } - if ($found) { - $remote_sha1 = $headrev if ! defined $remote_sha1; - print "$remote_sha1 $found\n"; - } -' - -set fnord $(git ls-remote "$url" | @PERL_PATH@ -e "$find_matching_ref" "${remote:-HEAD}" "$headrev") +set fnord $(git ls-remote "$url" | find_matching_ref) remote_sha1=$2 ref=$3 diff --git a/git-send-email.perl b/git-send-email.perl index 798d59b84f..cb6dca2500 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -41,6 +41,8 @@ git send-email --translate-aliases --subject <str> * Email "Subject:" --reply-to <str> * Email "Reply-To:" --in-reply-to <str> * Email "In-Reply-To:" + --[no-]outlook-id-fix * The SMTP host is an Outlook server that munges the + Message-ID. Retrieve it from the server. --[no-]xmailer * Add "X-Mailer:" header (default). --[no-]annotate * Review each patch that will be sent in an editor. --compose * Open an editor for introduction. @@ -68,7 +70,7 @@ git send-email --translate-aliases --smtp-auth <str> * Space-separated list of allowed AUTH mechanisms, or "none" to disable authentication. This setting forces to use one of the listed mechanisms. - --no-smtp-auth Disable SMTP authentication. Shorthand for + --no-smtp-auth * Disable SMTP authentication. Shorthand for `--smtp-auth=none` --smtp-debug <0|1> * Disable, enable Net::SMTP debug. @@ -290,6 +292,7 @@ my $validate = 1; my $mailmap = 0; my $target_xfer_encoding = 'auto'; my $forbid_sendmail_variables = 1; +my $outlook_id_fix = 'auto'; my %config_bool_settings = ( "thread" => \$thread, @@ -305,6 +308,7 @@ my %config_bool_settings = ( "xmailer" => \$use_xmailer, "forbidsendmailvariables" => \$forbid_sendmail_variables, "mailmap" => \$mailmap, + "outlookidfix" => \$outlook_id_fix, ); my %config_settings = ( @@ -551,6 +555,7 @@ my %options = ( "relogin-delay=i" => \$relogin_delay, "git-completion-helper" => \$git_completion_helper, "v=s" => \$reroll_count, + "outlook-id-fix!" => \$outlook_id_fix, ); $rc = GetOptions(%options); @@ -1354,7 +1359,9 @@ sub process_address_list { sub valid_fqdn { my $domain = shift; - return defined $domain && !($^O eq 'darwin' && $domain =~ /\.local$/) && $domain =~ /\./; + my $subdomain = '(?!-)[A-Za-z0-9-]{1,63}(?<!-)'; + return defined $domain && !($^O eq 'darwin' && $domain =~ /\.local$/) + && $domain =~ /^$subdomain(?:\.$subdomain)*$/; } sub maildomain_net { @@ -1386,8 +1393,22 @@ sub maildomain_mta { return $maildomain; } +sub maildomain_hostname_command { + my $maildomain; + + if ($^O eq 'linux' || $^O eq 'darwin') { + my $domain = `(hostname -f) 2>/dev/null`; + if (!$?) { + chomp($domain); + $maildomain = $domain if valid_fqdn($domain); + } + } + return $maildomain; +} + sub maildomain { - return maildomain_net() || maildomain_mta() || 'localhost.localdomain'; + return maildomain_net() || maildomain_mta() || + maildomain_hostname_command || 'localhost.localdomain'; } sub smtp_host_string { @@ -1419,7 +1440,7 @@ sub smtp_auth_maybe { die "invalid smtp auth: '${smtp_auth}'"; } - # TODO: Authentication may fail not because credentials were + # Authentication may fail not because credentials were # invalid but due to other reasons, in which we should not # reject credentials. $auth = Git::credential({ @@ -1431,24 +1452,61 @@ sub smtp_auth_maybe { 'password' => $smtp_authpass }, sub { my $cred = shift; + my $result; + my $error; + + # catch all SMTP auth error in a unified eval block + eval { + if ($smtp_auth) { + my $sasl = Authen::SASL->new( + mechanism => $smtp_auth, + callback => { + user => $cred->{'username'}, + pass => $cred->{'password'}, + authname => $cred->{'username'}, + } + ); + $result = $smtp->auth($sasl); + } else { + $result = $smtp->auth($cred->{'username'}, $cred->{'password'}); + } + 1; # ensure true value is returned if no exception is thrown + } or do { + $error = $@ || 'Unknown error'; + }; + + return ($error + ? handle_smtp_error($error) + : ($result ? 1 : 0)); + }); - if ($smtp_auth) { - my $sasl = Authen::SASL->new( - mechanism => $smtp_auth, - callback => { - user => $cred->{'username'}, - pass => $cred->{'password'}, - authname => $cred->{'username'}, - } - ); + return $auth; +} - return !!$smtp->auth($sasl); +sub handle_smtp_error { + my ($error) = @_; + + # Parse SMTP status code from error message in: + # https://www.rfc-editor.org/rfc/rfc5321.html + if ($error =~ /\b(\d{3})\b/) { + my $status_code = $1; + if ($status_code =~ /^4/) { + # 4yz: Transient Negative Completion reply + warn "SMTP transient error (status code $status_code): $error"; + return 1; + } elsif ($status_code =~ /^5/) { + # 5yz: Permanent Negative Completion reply + warn "SMTP permanent error (status code $status_code): $error"; + return 0; } + # If no recognized status code is found, treat as transient error + warn "SMTP unknown error: $error. Treating as transient failure."; + return 1; + } - return !!$smtp->auth($cred->{'username'}, $cred->{'password'}); - }); - - return $auth; + # If no status code is found, treat as transient error + warn "SMTP generic error: $error"; + return 1; } sub ssl_verify_params { @@ -1537,6 +1595,16 @@ Message-ID: $message_id return ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header); } +sub is_outlook { + my ($host) = @_; + if ($outlook_id_fix eq 'auto') { + $outlook_id_fix = + ($host eq 'smtp.office365.com' || + $host eq 'smtp-mail.outlook.com') ? 1 : 0; + } + return $outlook_id_fix; +} + # Prepares the email, then asks the user what to do. # # If the user chooses to send the email, it's sent and 1 is returned. @@ -1585,8 +1653,18 @@ EOF default => $ask_default); die __("Send this email reply required") unless defined $_; if (/^n/i) { + # If we are skipping a message, we should make sure that + # the next message is treated as the successor to the + # previously sent message, and not the skipped message. + $message_num--; return 0; } elsif (/^e/i) { + # Since the same message will be sent again, we need to + # decrement the message number to the previous message. + # Otherwise, the edited message will be treated as a + # different message sent after the original non-edited + # message. + $message_num--; return -1; } elsif (/^q/i) { cleanup_compose_files(); @@ -1700,6 +1778,23 @@ EOF $smtp->datasend("$line") or die $smtp->message; } $smtp->dataend() or die $smtp->message; + + # Outlook discards the Message-ID header we set while sending the email + # and generates a new random Message-ID. So in order to avoid breaking + # threads, we simply retrieve the Message-ID from the server response + # and assign it to the $message_id variable, which will then be + # assigned to $in_reply_to by the caller when the next message is sent + # as a response to this message. + if (is_outlook($smtp_server)) { + if ($smtp->message =~ /<([^>]+)>/) { + $message_id = "<$1>"; + $header =~ s/^(Message-ID:\s*).*\n/${1}$message_id\n/m; + printf __("Outlook reassigned Message-ID to: %s\n"), $message_id if $smtp->debug; + } else { + warn __("Warning: Could not retrieve Message-ID from server response.\n"); + } + } + $smtp->code =~ /250|200/ or die sprintf(__("Failed to send %s\n"), $subject).$smtp->message; } if ($quiet) { diff --git a/git-zlib.c b/git-zlib.c index 651dd9e07c..df9604910e 100644 --- a/git-zlib.c +++ b/git-zlib.c @@ -45,7 +45,7 @@ static void zlib_pre_call(git_zstream *s) s->z.avail_out = zlib_buf_cap(s->avail_out); } -static void zlib_post_call(git_zstream *s) +static void zlib_post_call(git_zstream *s, int status) { unsigned long bytes_consumed; unsigned long bytes_produced; @@ -54,7 +54,12 @@ static void zlib_post_call(git_zstream *s) bytes_produced = s->z.next_out - s->next_out; if (s->z.total_out != s->total_out + bytes_produced) BUG("total_out mismatch"); - if (s->z.total_in != s->total_in + bytes_consumed) + /* + * zlib does not update total_in when it returns Z_NEED_DICT, + * causing a mismatch here. Skip the sanity check in that case. + */ + if (status != Z_NEED_DICT && + s->z.total_in != s->total_in + bytes_consumed) BUG("total_in mismatch"); s->total_out = s->z.total_out; @@ -72,7 +77,7 @@ void git_inflate_init(git_zstream *strm) zlib_pre_call(strm); status = inflateInit(&strm->z); - zlib_post_call(strm); + zlib_post_call(strm, status); if (status == Z_OK) return; die("inflateInit: %s (%s)", zerr_to_string(status), @@ -90,7 +95,7 @@ void git_inflate_init_gzip_only(git_zstream *strm) zlib_pre_call(strm); status = inflateInit2(&strm->z, windowBits); - zlib_post_call(strm); + zlib_post_call(strm, status); if (status == Z_OK) return; die("inflateInit2: %s (%s)", zerr_to_string(status), @@ -103,7 +108,7 @@ void git_inflate_end(git_zstream *strm) zlib_pre_call(strm); status = inflateEnd(&strm->z); - zlib_post_call(strm); + zlib_post_call(strm, status); if (status == Z_OK) return; error("inflateEnd: %s (%s)", zerr_to_string(status), @@ -122,7 +127,7 @@ int git_inflate(git_zstream *strm, int flush) ? 0 : flush); if (status == Z_MEM_ERROR) die("inflate: out of memory"); - zlib_post_call(strm); + zlib_post_call(strm, status); /* * Let zlib work another round, while we can still @@ -160,7 +165,7 @@ void git_deflate_init(git_zstream *strm, int level) memset(strm, 0, sizeof(*strm)); zlib_pre_call(strm); status = deflateInit(&strm->z, level); - zlib_post_call(strm); + zlib_post_call(strm, status); if (status == Z_OK) return; die("deflateInit: %s (%s)", zerr_to_string(status), @@ -176,7 +181,7 @@ static void do_git_deflate_init(git_zstream *strm, int level, int windowBits) status = deflateInit2(&strm->z, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY); - zlib_post_call(strm); + zlib_post_call(strm, status); if (status == Z_OK) return; die("deflateInit2: %s (%s)", zerr_to_string(status), @@ -207,7 +212,7 @@ int git_deflate_abort(git_zstream *strm) zlib_pre_call(strm); status = deflateEnd(&strm->z); - zlib_post_call(strm); + zlib_post_call(strm, status); return status; } @@ -227,7 +232,7 @@ int git_deflate_end_gently(git_zstream *strm) zlib_pre_call(strm); status = deflateEnd(&strm->z); - zlib_post_call(strm); + zlib_post_call(strm, status); return status; } @@ -244,7 +249,7 @@ int git_deflate(git_zstream *strm, int flush) ? 0 : flush); if (status == Z_MEM_ERROR) die("deflate: out of memory"); - zlib_post_call(strm); + zlib_post_call(strm, status); /* * Let zlib work another round, while we can still diff --git a/git-zlib.h b/git-zlib.h index 1e8d9aabcb..0e66fefa8c 100644 --- a/git-zlib.h +++ b/git-zlib.h @@ -4,7 +4,7 @@ #include "compat/zlib-compat.h" typedef struct git_zstream { - z_stream z; + struct z_stream_s z; unsigned long avail_in; unsigned long avail_out; unsigned long total_in; @@ -462,12 +462,12 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct precompose_argv_prefix(argc, argv, NULL); if (use_pager == -1 && run_setup && !(p->option & DELAY_PAGER_CONFIG)) - use_pager = check_pager_config(the_repository, p->cmd); + use_pager = check_pager_config(repo, p->cmd); if (use_pager == -1 && p->option & USE_PAGER) use_pager = 1; if (run_setup && startup_info->have_repository) /* get_git_dir() may set up repo, avoid that */ - trace_repo_setup(the_repository); + trace_repo_setup(repo); commit_pager_choice(); if (!help && p->option & NEED_WORK_TREE) @@ -541,6 +541,7 @@ static struct cmd_struct commands[] = { { "diff", cmd_diff, NO_PARSEOPT }, { "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "diff-index", cmd_diff_index, RUN_SETUP | NO_PARSEOPT }, + { "diff-pairs", cmd_diff_pairs, RUN_SETUP | NO_PARSEOPT }, { "diff-tree", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT }, { "difftool", cmd_difftool, RUN_SETUP_GENTLY }, { "fast-export", cmd_fast_export, RUN_SETUP }, diff --git a/gitk-git/Makefile b/gitk-git/Makefile index 3a3c56c318..cc32dcab4b 100644 --- a/gitk-git/Makefile +++ b/gitk-git/Makefile @@ -73,7 +73,7 @@ update-po:: $(PO_TEMPLATE) $(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U $p $(PO_TEMPLATE) ; ) $(ALL_MSGFILES): %.msg : %.po @echo Generating catalog $@ - $(MSGFMT) --statistics --tcl $< -l $(basename $(notdir $<)) -d $(dir $@) + $(MSGFMT) --statistics --tcl -l $(basename $(notdir $<)) -d $(dir $@) $< .PHONY: all install uninstall clean update-po .PHONY: FORCE diff --git a/gitk-git/gitk b/gitk-git/gitk index bc9efa1856..19689765cd 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -13,133 +13,102 @@ package require Tk ## ## Enabling platform-specific code paths -proc is_MacOSX {} { - if {[tk windowingsystem] eq {aqua}} { - return 1 - } - return 0 -} - proc is_Windows {} { - if {$::tcl_platform(platform) eq {windows}} { - return 1 - } - return 0 -} - -set _iscygwin {} -proc is_Cygwin {} { - global _iscygwin - if {$_iscygwin eq {}} { - if {[string match "CYGWIN_*" $::tcl_platform(os)]} { - set _iscygwin 1 - } else { - set _iscygwin 0 - } - } - return $_iscygwin + if {$::tcl_platform(platform) eq {windows}} { + return 1 + } + return 0 } ###################################################################### ## ## PATH lookup -set _search_path {} -proc _which {what args} { - global env _search_exe _search_path - - if {$_search_path eq {}} { - if {[is_Cygwin] && [regexp {^(/|\.:)} $env(PATH)]} { - set _search_path [split [exec cygpath \ - --windows \ - --path \ - --absolute \ - $env(PATH)] {;}] - set _search_exe .exe - } elseif {[is_Windows]} { - set gitguidir [file dirname [info script]] - regsub -all ";" $gitguidir "\\;" gitguidir - set env(PATH) "$gitguidir;$env(PATH)" - set _search_path [split $env(PATH) {;}] - # Skip empty `PATH` elements - set _search_path [lsearch -all -inline -not -exact \ - $_search_path ""] - set _search_exe .exe - } else { - set _search_path [split $env(PATH) :] - set _search_exe {} - } - } - - if {[is_Windows] && [lsearch -exact $args -script] >= 0} { - set suffix {} - } else { - set suffix $_search_exe - } - - foreach p $_search_path { - set p [file join $p $what$suffix] - if {[file exists $p]} { - return [file normalize $p] - } - } - return {} -} - -proc sanitize_command_line {command_line from_index} { - set i $from_index - while {$i < [llength $command_line]} { - set cmd [lindex $command_line $i] - if {[file pathtype $cmd] ne "absolute"} { - set fullpath [_which $cmd] - if {$fullpath eq ""} { - throw {NOT-FOUND} "$cmd not found in PATH" - } - lset command_line $i $fullpath - } - - # handle piped commands, e.g. `exec A | B` - for {incr i} {$i < [llength $command_line]} {incr i} { - if {[lindex $command_line $i] eq "|"} { - incr i - break - } - } - } - return $command_line -} - -# Override `exec` to avoid unsafe PATH lookup - -rename exec real_exec - -proc exec {args} { - # skip options - for {set i 0} {$i < [llength $args]} {incr i} { - set arg [lindex $args $i] - if {$arg eq "--"} { - incr i - break - } - if {[string range $arg 0 0] ne "-"} { - break - } - } - set args [sanitize_command_line $args $i] - uplevel 1 real_exec $args -} - -# Override `open` to avoid unsafe PATH lookup - -rename open real_open - -proc open {args} { - set arg0 [lindex $args 0] - if {[string range $arg0 0 0] eq "|"} { - set command_line [string trim [string range $arg0 1 end]] - lset args 0 "| [sanitize_command_line $command_line 0]" - } - uplevel 1 real_open $args +if {[is_Windows]} { + set _search_path {} + proc _which {what args} { + global env _search_path + + if {$_search_path eq {}} { + set gitguidir [file dirname [info script]] + regsub -all ";" $gitguidir "\\;" gitguidir + set env(PATH) "$gitguidir;$env(PATH)" + set _search_path [split $env(PATH) {;}] + # Skip empty `PATH` elements + set _search_path [lsearch -all -inline -not -exact \ + $_search_path ""] + } + + if {[lsearch -exact $args -script] >= 0} { + set suffix {} + } else { + set suffix .exe + } + + foreach p $_search_path { + set p [file join $p $what$suffix] + if {[file exists $p]} { + return [file normalize $p] + } + } + return {} + } + + proc sanitize_command_line {command_line from_index} { + set i $from_index + while {$i < [llength $command_line]} { + set cmd [lindex $command_line $i] + if {[llength [file split $cmd]] < 2} { + set fullpath [_which $cmd] + if {$fullpath eq ""} { + throw {NOT-FOUND} "$cmd not found in PATH" + } + lset command_line $i $fullpath + } + + # handle piped commands, e.g. `exec A | B` + for {incr i} {$i < [llength $command_line]} {incr i} { + if {[lindex $command_line $i] eq "|"} { + incr i + break + } + } + } + return $command_line + } + + # Override `exec` to avoid unsafe PATH lookup + + rename exec real_exec + + proc exec {args} { + # skip options + for {set i 0} {$i < [llength $args]} {incr i} { + set arg [lindex $args $i] + if {$arg eq "--"} { + incr i + break + } + if {[string range $arg 0 0] ne "-"} { + break + } + } + set args [sanitize_command_line $args $i] + uplevel 1 real_exec $args + } + + # Override `open` to avoid unsafe PATH lookup + + rename open real_open + + proc open {args} { + set arg0 [lindex $args 0] + if {[string range $arg0 0 0] eq "|"} { + set command_line [string trim [string range $arg0 1 end]] + lset args 0 "| [sanitize_command_line $command_line 0]" + } + uplevel 1 real_open $args + } } # End of safe PATH lookup stuff @@ -491,11 +460,11 @@ proc parseviewrevs {view revs} { # Escapes a list of filter paths to be passed to git log via stdin. Note that # paths must not be quoted. proc escape_filter_paths {paths} { - set escaped [list] - foreach path $paths { - lappend escaped [string map {\\ \\\\ "\ " "\\\ "} $path] - } - return $escaped + set escaped [list] + foreach path $paths { + lappend escaped [string map {\\ \\\\ "\ " "\\\ "} $path] + } + return $escaped } # Start off a git log process and arrange to read its output @@ -4632,7 +4601,7 @@ proc addviewmenu {n} { .bar.view add radiobutton -label $viewname($n) \ -command [list showview $n] -variable selectedview -value $n #$viewhlmenu add radiobutton -label $viewname($n) \ - # -command [list addvhighlight $n] -variable selectedhlview + # -command [list addvhighlight $n] -variable selectedhlview } proc showview {n} { @@ -7139,7 +7108,7 @@ proc findselectline {l} { # mark the bits of a headline or author that match a find string proc markmatches {canv l str tag matches font row} { - global selectedline + global selectedline foundbgcolor set bbox [$canv bbox $tag] set x0 [lindex $bbox 0] @@ -7153,7 +7122,7 @@ proc markmatches {canv l str tag matches font row} { set xlen [font measure $font [string range $str 0 [expr {$end}]]] set t [$canv create rect [expr {$x0+$xoff}] $y0 \ [expr {$x0+$xlen+2}] $y1 \ - -outline {} -tags [list match$l matches] -fill yellow] + -outline {} -tags [list match$l matches] -fill $foundbgcolor] $canv lower $t if {$row == $selectedline} { $canv raise $t secsel @@ -11767,13 +11736,11 @@ proc prefspage_general {notebook} { grid x $page.tabstopl $page.tabstop -sticky w ${NS}::label $page.wrapcommentl -text [mc "Wrap comment text"] - ${NS}::combobox $page.wrapcomment -values {none char word} -state readonly \ - -textvariable wrapcomment + makedroplist $page.wrapcomment wrapcomment none char word grid x $page.wrapcommentl $page.wrapcomment -sticky w ${NS}::label $page.wrapdefaultl -text [mc "Wrap other text"] - ${NS}::combobox $page.wrapdefault -values {none char word} -state readonly \ - -textvariable wrapdefault + makedroplist $page.wrapdefault wrapdefault none char word grid x $page.wrapdefaultl $page.wrapdefault -sticky w ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \ diff --git a/gitk-git/po/meson.build b/gitk-git/po/meson.build index b1ed019828..c00b3d5c8d 100644 --- a/gitk-git/po/meson.build +++ b/gitk-git/po/meson.build @@ -12,6 +12,7 @@ import('i18n').gettext('gitk', 'pt_pt', 'ru', 'sv', + 'ta', 'vi', 'zh_cn', ], diff --git a/gitk-git/po/ta.po b/gitk-git/po/ta.po new file mode 100644 index 0000000000..0e390c5153 --- /dev/null +++ b/gitk-git/po/ta.po @@ -0,0 +1,1457 @@ +# Translation of gitk +# Copyright (C) 2024-2025 தமிழà¯à®¨à¯‡à®°à®®à¯ +# This file is distributed under the same license as the gitk package. +# தமிழà¯à®¨à¯‡à®°à®®à¯ (TamilNeram.github.io), 2025. +# +# +msgid "" +msgstr "" +"Project-Id-Version: gitk\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-05-07 08:01+0530\n" +"PO-Revision-Date: 2025-05-07 09:17\n" +"Last-Translator: தமிழà¯à®¨à¯‡à®°à®®à¯ (TamilNeram.github.io)\n" +"Language-Team: Tamil\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gitk:274 +msgid "Couldn't get list of unmerged files:" +msgstr "à®’à®°à¯à®™à¯à®•ிணைகà¯à®•பà¯à®ªà®Ÿà®¾à®¤ கோபà¯à®ªà¯à®•ளின௠படà¯à®Ÿà®¿à®¯à®²à¯ˆà®ªà¯ பெற à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ:" + +#: gitk:346 gitk:2565 +msgid "Color words" +msgstr "வணà¯à®£ சொறà¯à®•ளà¯" + +#: gitk:351 gitk:2565 gitk:8476 gitk:8509 +msgid "Markup words" +msgstr "கà¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ சொறà¯à®•ளà¯" + +#: gitk:458 +msgid "Error parsing revisions:" +msgstr "பிழைகளை பாகà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®¤à®²à¯:" + +#: gitk:524 +msgid "Error executing --argscmd command:" +msgstr "--argscmd கடà¯à®Ÿà®³à¯ˆà®¯à¯ˆ இயகà¯à®•à¯à®µà®¤à®¿à®²à¯ பிழை:" + +#: gitk:537 +msgid "No files selected: --merge specified but no files are unmerged." +msgstr "" +"கோபà¯à®ªà¯à®•ள௠எதà¯à®µà¯à®®à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•பà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ: --ஒனà¯à®±à®¿à®£à¯ˆ கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯, " +"ஆனால௠கோபà¯à®ªà¯à®•ள௠எதà¯à®µà¯à®®à¯ அவிழà¯à®•à¯à®•பà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ." + +#: gitk:540 +msgid "" +"No files selected: --merge specified but no unmerged files are within file " +"limit." +msgstr "" +"கோபà¯à®ªà¯à®•ள௠எதà¯à®µà¯à®®à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•பà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ: --ஒனà¯à®±à®¿à®£à¯ˆ கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯, " +"ஆனால௠அவிழà¯à®•à¯à®•பà¯à®ªà®Ÿà®¾à®¤ கோபà¯à®ªà¯à®•ள௠எதà¯à®µà¯à®®à¯ கோபà¯à®ªà¯ வரமà¯à®ªà®¿à®±à¯à®•à¯à®³à¯ இலà¯à®²à¯ˆ." + +#: gitk:565 gitk:720 +msgid "Error executing git log:" +msgstr "அறிவிலி பதிவை இயகà¯à®•à¯à®µà®¤à®¿à®²à¯ பிழை:" + +#: gitk:583 gitk:736 +msgid "Reading" +msgstr "படிதà¯à®¤à®²à¯" + +#: gitk:643 gitk:4736 +msgid "Reading commits..." +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•ளைப௠படிதà¯à®¤à®²à¯..." + +#: gitk:646 gitk:1795 gitk:4739 +msgid "No commits selected" +msgstr "எநà¯à®¤ உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•ளà¯à®®à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•பà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ" + +#: gitk:1603 gitk:4256 gitk:12883 +msgid "Command line" +msgstr "கடà¯à®Ÿà®³à¯ˆ வரி" + +#: gitk:1669 +msgid "Can't parse git log output:" +msgstr "அறிவிலி பதிவ௠வெளியீடà¯à®Ÿà¯ˆ அலச à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯:" + +#: gitk:1898 +msgid "No commit information available" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ செயà¯à®¤à®¿ எதà¯à®µà¯à®®à¯ கிடைகà¯à®•விலà¯à®²à¯ˆ" + +#: gitk:2065 gitk:2094 gitk:4526 gitk:10016 gitk:11626 gitk:11946 +msgid "OK" +msgstr "சரி" + +#: gitk:2096 gitk:4528 gitk:9452 gitk:9531 gitk:9661 gitk:9747 gitk:10018 +#: gitk:11627 gitk:11947 +msgid "Cancel" +msgstr "நீகà¯à®•றலà¯" + +#: gitk:2249 +msgid "&Update" +msgstr "பà¯à®¤à¯à®ªà¯à®ªà®¿à®¤à¯à®¤à®²à¯" + +#: gitk:2250 +msgid "&Reload" +msgstr "மீணà¯à®Ÿà¯à®®à¯ à®à®±à¯à®±à¯" + +#: gitk:2251 +msgid "Reread re&ferences" +msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯à®•ளை மீணà¯à®Ÿà¯à®®à¯ படி" + +#: gitk:2252 +msgid "&List references" +msgstr "படà¯à®Ÿà®¿à®¯à®²à¯ கà¯à®±à®¿à®ªà¯à®ªà¯à®•ளà¯" + +#: gitk:2254 +msgid "Start git &gui" +msgstr "அறிவிலி இடைமà¯à®•தà¯à®¤à¯ˆà®¤à¯ தொடஙà¯à®•à¯" + +#: gitk:2256 +msgid "&Quit" +msgstr "வெளியேறà¯" + +#: gitk:2248 +msgid "&File" +msgstr "கோபà¯à®ªà¯" + +#: gitk:2260 +msgid "&Preferences" +msgstr "விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯‡à®°à¯à®µà¯à®•ளà¯" + +#: gitk:2259 +msgid "&Edit" +msgstr "திரà¯à®¤à¯à®¤à¯" + +#: gitk:2264 +msgid "&New view..." +msgstr "பà¯à®¤à®¿à®¯ பாரà¯à®µà¯ˆ..." + +#: gitk:2265 +msgid "&Edit view..." +msgstr "பாரà¯à®µà¯ˆà®¯à¯ˆà®¤à¯ திரà¯à®¤à¯à®¤à¯..." + +#: gitk:2266 +msgid "&Delete view" +msgstr "பாரà¯à®µà¯ˆà®¯à¯ˆ நீகà¯à®•à¯" + +#: gitk:2268 +msgid "&All files" +msgstr "அனைதà¯à®¤à¯ கோபà¯à®ªà¯à®•ளà¯à®®à¯" + +#: gitk:2263 +msgid "&View" +msgstr "காணà¯à®•" + +#: gitk:2273 gitk:2283 +msgid "&About gitk" +msgstr "அறிவிலிகே பறà¯à®±à®¿" + +#: gitk:2274 gitk:2288 +msgid "&Key bindings" +msgstr "à®®à¯à®•à¯à®•ிய பிணைபà¯à®ªà¯à®•ளà¯" + +#: gitk:2272 gitk:2287 +msgid "&Help" +msgstr "உதவி" + +#: gitk:2365 gitk:8908 +msgid "Commit ID:" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ அடையாளமà¯:" + +#: gitk:2409 +msgid "Row" +msgstr "நிரை" + +#: gitk:2447 +msgid "Find" +msgstr "கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿" + +#: gitk:2475 +msgid "commit" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿" + +#: gitk:2479 gitk:2481 gitk:4898 gitk:4921 gitk:4945 gitk:6966 gitk:7038 +#: gitk:7123 +msgid "containing:" +msgstr "கொணà¯à®Ÿà®¿à®°à¯à®•à¯à®•ிறதà¯:" + +#: gitk:2482 gitk:3737 gitk:3742 gitk:4974 +msgid "touching paths:" +msgstr "தொடà¯à®®à¯ பாதைகளà¯:" + +#: gitk:2483 gitk:4988 +msgid "adding/removing string:" +msgstr "சரதà¯à®¤à¯ˆà®šà¯ சேரà¯à®ªà¯à®ªà®¤à¯/அகறà¯à®±à¯à®µà®¤à¯:" + +#: gitk:2484 gitk:4990 +msgid "changing lines matching:" +msgstr "பொரà¯à®¨à¯à®¤à®•à¯à®•ூடிய வரிகளை மாறà¯à®±à¯à®¤à®²à¯:" + +#: gitk:2493 gitk:2495 gitk:4977 +msgid "Exact" +msgstr "சரியான" + +#: gitk:2495 gitk:5065 gitk:6934 +msgid "IgnCase" +msgstr "வழகà¯à®•à¯à®¤à®µà®¿à®°à¯" + +#: gitk:2495 gitk:4947 gitk:5063 gitk:6930 +msgid "Regexp" +msgstr "வழகà¯à®•வெளி" + +#: gitk:2497 gitk:2498 gitk:5085 gitk:5115 gitk:5122 gitk:7059 gitk:7127 +msgid "All fields" +msgstr "அனைதà¯à®¤à¯ பà¯à®²à®™à¯à®•ளà¯à®®à¯" + +#: gitk:2498 gitk:5082 gitk:5115 gitk:6997 +msgid "Headline" +msgstr "தலைபà¯à®ªà¯" + +#: gitk:2499 gitk:5082 gitk:6997 gitk:7127 gitk:7639 +msgid "Comments" +msgstr "கரà¯à®¤à¯à®¤à¯à®•ளà¯" + +#: gitk:2499 gitk:5082 gitk:5087 gitk:5122 gitk:6997 gitk:7574 gitk:9086 +#: gitk:9101 +msgid "Author" +msgstr "நூலாசிரியரà¯" + +#: gitk:2499 gitk:5082 gitk:6997 gitk:7576 +msgid "Committer" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®ªà®µà®°à¯" + +#: gitk:2533 +msgid "Search" +msgstr "தேடà¯" + +#: gitk:2541 +msgid "Diff" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:2543 +msgid "Old version" +msgstr "பழைய பதிபà¯à®ªà¯" + +#: gitk:2545 +msgid "New version" +msgstr "பà¯à®¤à®¿à®¯ பதிபà¯à®ªà¯" + +#: gitk:2548 +msgid "Lines of context" +msgstr "சூழலின௠வரிகளà¯" + +#: gitk:2558 +msgid "Ignore space change" +msgstr "இடைவெளி மாறà¯à®±à®¤à¯à®¤à¯ˆ பà¯à®±à®•à¯à®•ணி" + +#: gitk:2562 gitk:2564 gitk:8209 gitk:8462 +msgid "Line diff" +msgstr "வரி வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:2637 +msgid "Patch" +msgstr "ஒடà¯à®Ÿà¯" + +#: gitk:2639 +msgid "Tree" +msgstr "மரமà¯" + +#: gitk:2814 gitk:2835 +msgid "Diff this -> selected" +msgstr "இதை வேறà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®™à¯à®•ள௠-> தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯" + +#: gitk:2815 gitk:2836 +msgid "Diff selected -> this" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ -> இதà¯" + +#: gitk:2816 gitk:2837 +msgid "Make patch" +msgstr "ஒடà¯à®Ÿà¯ செயà¯" + +#: gitk:2817 gitk:9510 +msgid "Create tag" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உரà¯à®µà®¾à®•à¯à®•à¯" + +#: gitk:2818 +msgid "Copy commit reference" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ கà¯à®±à®¿à®ªà¯à®ªà¯ நகலெடà¯" + +#: gitk:2819 gitk:9641 +msgid "Write commit to file" +msgstr "கோபà¯à®ªà®¿à®²à¯ உறவை எழà¯à®¤à¯à®™à¯à®•ளà¯" + +#: gitk:2820 +msgid "Create new branch" +msgstr "பà¯à®¤à®¿à®¯ கிளையை உரà¯à®µà®¾à®•à¯à®•à¯" + +#: gitk:2821 +msgid "Cherry-pick this commit" +msgstr "கனி-எட௠இநà¯à®¤ உறà¯à®¤à®¿à®®à¯Šà®´à®¿" + +#: gitk:2822 +msgid "Reset HEAD branch to here" +msgstr "தலை கிளையை இஙà¯à®•ே மீடà¯à®Ÿà®®à¯ˆ" + +#: gitk:2823 +msgid "Mark this commit" +msgstr "இநà¯à®¤ உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à¯ˆà®•௠கà¯à®±à®¿" + +#: gitk:2824 +msgid "Return to mark" +msgstr "மாரà¯à®•à¯à®•à¯à®•à¯à®•à¯à®¤à¯ திரà¯à®®à¯à®ªà¯" + +#: gitk:2825 +msgid "Find descendant of this and mark" +msgstr "இதன௠வழிதà¯à®¤à¯‹à®©à¯à®±à®²à¯ˆà®•௠கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿à®¤à¯à®¤à¯ கà¯à®±à®¿" + +#: gitk:2826 +msgid "Compare with marked commit" +msgstr "கà¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ உறà¯à®¤à®¿à®ªà¯à®ªà®¾à®Ÿà¯à®Ÿà¯à®Ÿà®©à¯ ஒபà¯à®ªà®¿à®Ÿà¯à®•" + +#: gitk:2827 gitk:2838 +msgid "Diff this -> marked commit" +msgstr "இதை வேறà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®™à¯à®•ள௠-> கà¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ உறà¯à®¤à®¿à®®à¯Šà®´à®¿" + +#: gitk:2828 gitk:2839 +msgid "Diff marked commit -> this" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯ கà¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ உறà¯à®¤à®¿à®®à¯Šà®´à®¿ -> இதà¯" + +#: gitk:2829 +msgid "Revert this commit" +msgstr "இநà¯à®¤ உறà¯à®¤à®¿à®ªà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆ மாறà¯à®±à®µà¯à®®à¯" + +#: gitk:2845 +msgid "Check out this branch" +msgstr "இநà¯à®¤ கிளையைப௠பாரà¯à®™à¯à®•ளà¯" + +#: gitk:2846 +msgid "Rename this branch" +msgstr "இநà¯à®¤ கிளையை மறà¯à®ªà¯†à®¯à®°à®¿à®Ÿà¯" + +#: gitk:2847 +msgid "Remove this branch" +msgstr "இநà¯à®¤ கிளையை அகறà¯à®±à¯" + +#: gitk:2848 +msgid "Copy branch name" +msgstr "கிளை பெயரை நகலெடà¯" + +#: gitk:2855 +msgid "Highlight this too" +msgstr "இதை à®®à¯à®©à¯à®©à®¿à®²à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯" + +#: gitk:2856 +msgid "Highlight this only" +msgstr "இதை à®®à¯à®©à¯à®©à®¿à®²à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯" + +#: gitk:2857 +msgid "External diff" +msgstr "வெளிபà¯à®ªà¯à®± வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:2858 +msgid "Blame parent commit" +msgstr "பெறà¯à®±à¯‹à®°à¯ˆ கà¯à®±à¯à®±à®®à¯ சாடà¯à®Ÿà¯" + +#: gitk:2859 +msgid "Copy path" +msgstr "நகல௠பாதை" + +#: gitk:2866 +msgid "Show origin of this line" +msgstr "இநà¯à®¤ வரியின௠தோறà¯à®±à®¤à¯à®¤à¯ˆà®•௠காடà¯à®Ÿà¯" + +#: gitk:2867 +msgid "Run git gui blame on this line" +msgstr "இநà¯à®¤ வரியில௠அறிவிலி இடைமà¯à®•ம௠பழியை இயகà¯à®•à¯" + +#: gitk:3221 +msgid "About gitk" +msgstr "அறிவிலிகே பறà¯à®±à®¿" + +#: gitk:3223 +msgid "" +"\n" +"Gitk - a commit viewer for git\n" +"\n" +"Copyright © 2005-2016 Paul Mackerras\n" +"\n" +"Use and redistribute under the terms of the GNU General Public License" +msgstr "" +"\n" +"அறிவிலிகே - அறிவிலி ஒர௠உறà¯à®¤à®¿à®®à¯Šà®´à®¿ பாரà¯à®µà¯ˆà®¯à®¾à®³à®°à¯ \n" +"\n" +"பதிபà¯à®ªà¯à®°à®¿à®®à¯ˆ © 2005-2016 பால௠மெகà¯à®•ெராச௠\n" +"\n" +"கà¯à®©à¯ பொத௠பொதà¯à®®à®•à¯à®•ள௠உரிமதà¯à®¤à®¿à®©à¯ விதிமà¯à®±à¯ˆà®•ளின௠கீழ௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯ மறà¯à®ªà®•ிரà¯à®µà¯ செயà¯à®¯à®µà¯à®®à¯" + +#: gitk:3231 gitk:3298 gitk:10231 +msgid "Close" +msgstr "மூடà¯" + +#: gitk:3252 +msgid "Gitk key bindings" +msgstr "அறிவிலிகே விசை பிணைபà¯à®ªà¯à®•ளà¯" + +#: gitk:3255 +msgid "Gitk key bindings:" +msgstr "அறிவிலிகே விசை பிணைபà¯à®ªà¯à®•ளà¯:" + +#: gitk:3257 +#, tcl-format +msgid "<%s-Q>\t\tQuit" +msgstr "<%s-Q>\t\tவெளியேறà¯" + +#: gitk:3258 +#, tcl-format +msgid "<%s-W>\t\tClose window" +msgstr "<%s-w>\t\tசாளரதà¯à®¤à¯ˆ மூடà¯" + +#: gitk:3259 +msgid "<Home>\t\tMove to first commit" +msgstr "<வீடà¯> à®®à¯à®¤à®²à¯ உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•à¯à®•௠நகரà¯à®¤à¯à®¤à¯" + +#: gitk:3260 +msgid "<End>\t\tMove to last commit" +msgstr "<à®®à¯à®Ÿà®¿> கடைசி உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•à¯à®•௠நகரà¯à®¤à¯à®¤à¯" + +#: gitk:3261 +msgid "<Up>, p, k\tMove up one commit" +msgstr "<மேலே>, பி, கே\tஒர௠உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à¯ˆ மேலே நகரà¯à®¤à¯à®¤à¯" + +#: gitk:3262 +msgid "<Down>, n, j\tMove down one commit" +msgstr "<கீழà¯>, n, j\tஒர௠உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à¯ˆ கீழே நகரà¯à®¤à¯à®¤à¯" + +#: gitk:3263 +msgid "<Left>, z, h\tGo back in history list" +msgstr "<இடதà¯>, z, h\tவரலாறà¯à®±à¯ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ திரà¯à®®à¯à®ªà®¿à®šà¯ செலà¯" + +#: gitk:3264 +msgid "<Right>, x, l\tGo forward in history list" +msgstr "<வலதà¯>, x, l\tவரலாறà¯à®±à¯ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ à®®à¯à®©à¯à®©à¯‹à®•à¯à®•ி செலà¯" + +#: gitk:3265 +#, tcl-format +msgid "<%s-n>\tGo to n-th parent of current commit in history list" +msgstr "" +"<%s-n> வரலாறà¯à®±à¯ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ தறà¯à®ªà¯‹à®¤à¯ˆà®¯ உறà¯à®¤à®¿à®ªà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®©à¯ n- வத௠பெறà¯à®±à¯‹à®°à®¿à®Ÿà®®à¯ " +"செலà¯" + +#: gitk:3266 +msgid "<PageUp>\tMove up one page in commit list" +msgstr "<பகà¯à®•à®®à¯à®®à¯‡à®²à¯>\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ ஒர௠பகà¯à®•தà¯à®¤à¯ˆ நகரà¯à®¤à¯à®¤à¯" + +#: gitk:3267 +msgid "<PageDown>\tMove down one page in commit list" +msgstr "<பகà¯à®•à®®à¯à®•ீழà¯>\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ ஒர௠பகà¯à®•தà¯à®¤à¯ˆ நகரà¯à®¤à¯à®¤à¯" + +#: gitk:3268 +#, tcl-format +msgid "<%s-Home>\tScroll to top of commit list" +msgstr "<%s-வீடà¯>\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ˆ மேல௠பகà¯à®¤à®¿à®•à¯à®•௠உரà¯à®Ÿà¯à®Ÿà®µà¯à®®à¯" + +#: gitk:3269 +#, tcl-format +msgid "<%s-End>\tScroll to bottom of commit list" +msgstr "<%s-à®®à¯à®Ÿà®¿> உறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à®¿à®©à¯ கீழ௠பகà¯à®¤à®¿à®•à¯à®•௠உரà¯à®Ÿà¯à®Ÿà®µà¯à®®à¯" + +#: gitk:3270 +#, tcl-format +msgid "<%s-Up>\tScroll commit list up one line" +msgstr "<%s-மேலே>\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ˆ ஒர௠வரி மேலே உரà¯à®Ÿà¯à®Ÿà®µà¯à®®à¯" + +#: gitk:3271 +#, tcl-format +msgid "<%s-Down>\tScroll commit list down one line" +msgstr "<%s-கீழà¯>\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ˆ ஒர௠வரி கீழே உரà¯à®Ÿà¯à®Ÿà®µà¯à®®à¯" + +#: gitk:3272 +#, tcl-format +msgid "<%s-PageUp>\tScroll commit list up one page" +msgstr "<%s-பகà¯à®•à®®à¯à®®à¯‡à®²à¯‡>\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ˆ ஒர௠பகà¯à®•ம௠மேலே உரà¯à®Ÿà¯à®Ÿà®µà¯à®®à¯" + +#: gitk:3273 +#, tcl-format +msgid "<%s-PageDown>\tScroll commit list down one page" +msgstr "<%s-பகà¯à®•à®®à¯à®•ீழà¯>\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ˆ ஒர௠பகà¯à®•ம௠கீழே உரà¯à®Ÿà¯à®Ÿà®µà¯à®®à¯" + +#: gitk:3274 +msgid "<Shift-Up>\tFind backwards (upwards, later commits)" +msgstr "<உயரà¯à®¤à¯à®¤à¯-மேலே>\tபினà¯à®©à¯‹à®•à¯à®•ி கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿ (மேலà¯à®¨à¯‹à®•à¯à®•ி, பினà¯à®©à®°à¯ உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•ளà¯)" + +#: gitk:3275 +msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)" +msgstr "" +"<உயரà¯à®¤à¯à®¤à¯-கீழே>\tà®®à¯à®©à¯à®©à¯‹à®•à¯à®•à¯à®•ளைக௠கணà¯à®Ÿà®±à®¿à®¯à®µà¯à®®à¯ (கீழà¯à®¨à¯‹à®•à¯à®•ி, à®®à¯à®¨à¯à®¤à¯ˆà®¯ " +"உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•ளà¯)" + +#: gitk:3276 +msgid "<Delete>, b\tScroll diff view up one page" +msgstr "<நீகà¯à®•à¯>, b\tசà¯à®°à¯à®³à¯ வேறà¯à®ªà®¾à®Ÿà¯ ஒர௠பகà¯à®•தà¯à®¤à¯ˆ மேலே காணà¯à®•" + +#: gitk:3277 +msgid "<Backspace>\tScroll diff view up one page" +msgstr "<பினà¯à®µà¯†à®³à®¿>\tசà¯à®°à¯à®³à¯ வேறà¯à®ªà®¾à®Ÿà¯ ஒர௠பகà¯à®•தà¯à®¤à¯ˆ மேலே காணà¯à®•" + +#: gitk:3278 +msgid "<Space>\t\tScroll diff view down one page" +msgstr "<Space>\t\tசà¯à®°à¯à®³à¯ வேறà¯à®ªà®¾à®Ÿà¯ ஒர௠பகà¯à®•தà¯à®¤à¯ˆà®•௠கீழே காணà¯à®•" + +#: gitk:3279 +msgid "u\t\tScroll diff view up 18 lines" +msgstr "u\t\tசà¯à®°à¯à®³à¯ வேறà¯à®ªà®¾à®Ÿà¯ 18 வரிகளை மேலே காணà¯à®•" + +#: gitk:3280 +msgid "d\t\tScroll diff view down 18 lines" +msgstr "d\t\tசà¯à®°à¯à®³à¯ வேறà¯à®ªà®¾à®Ÿà¯ 18 வரிகளைக௠கீழே காணà¯à®•" + +#: gitk:3281 +#, tcl-format +msgid "<%s-F>\t\tFind" +msgstr "<%s-F>\t\tகணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿" + +#: gitk:3282 +#, tcl-format +msgid "<%s-G>\t\tMove to next find hit" +msgstr "<%s-G>\t\tஅடà¯à®¤à¯à®¤ கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿à®ªà¯à®ªà¯ வெறà¯à®±à®¿à®•à¯à®•௠செலà¯" + +#: gitk:3283 +msgid "<Return>\tMove to next find hit" +msgstr "<திரà¯à®®à¯à®ªà¯>\tஅடà¯à®¤à¯à®¤à®¤à¯ˆà®•௠கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿" + +#: gitk:3284 +msgid "g\t\tGo to commit" +msgstr "g\t\tஉறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•à¯à®•௠செலà¯" + +#: gitk:3285 +msgid "/\t\tFocus the search box" +msgstr "/\t\tதேடல௠பெடà¯à®Ÿà®¿à®¯à®¿à®²à¯ கவனம௠செலà¯à®¤à¯à®¤à¯" + +#: gitk:3286 +msgid "?\t\tMove to previous find hit" +msgstr "?\t\tà®®à¯à®¨à¯à®¤à¯ˆà®¯ கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿à®ªà¯à®ªà¯ வெறà¯à®±à®¿à®•à¯à®•௠செலà¯" + +#: gitk:3287 +msgid "f\t\tScroll diff view to next file" +msgstr "f\t\tஅடà¯à®¤à¯à®¤ கோபà¯à®ªà®¿à®±à¯à®•௠உரà¯à®³à¯ வேறà¯à®ªà®¾à®Ÿà¯ பாரà¯à®µà¯ˆ" + +#: gitk:3288 +#, tcl-format +msgid "<%s-S>\t\tSearch for next hit in diff view" +msgstr "<%s-S>\t\tவேறà¯à®ªà®¾à®Ÿà¯ பாரà¯à®µà¯ˆà®¯à®¿à®²à¯ அடà¯à®¤à¯à®¤ வெறà¯à®±à®¿à®¯à¯ˆà®¤à¯ தேடà¯à®™à¯à®•ளà¯" + +#: gitk:3289 +#, tcl-format +msgid "<%s-R>\t\tSearch for previous hit in diff view" +msgstr "<%s-r> வேறà¯à®ªà®Ÿà¯à®Ÿ பாரà¯à®µà¯ˆà®¯à®¿à®²à¯ à®®à¯à®¨à¯à®¤à¯ˆà®¯ வெறà¯à®±à®¿à®¯à¯ˆà®¤à¯ தேடà¯à®™à¯à®•ளà¯" + +#: gitk:3290 +#, tcl-format +msgid "<%s-KP+>\tIncrease font size" +msgstr "<%s-KP+>\tஎழà¯à®¤à¯à®¤à¯à®°à¯ அளவை அதிகரி" + +#: gitk:3291 +#, tcl-format +msgid "<%s-plus>\tIncrease font size" +msgstr "<%s-plus>\tஎழà¯à®¤à¯à®¤à¯à®°à¯ அளவை அதிகரி" + +#: gitk:3292 +#, tcl-format +msgid "<%s-KP->\tDecrease font size" +msgstr "<%s-KP->\tஎழà¯à®¤à¯à®¤à¯à®°à¯ அளவைக௠கà¯à®±à¯ˆ" + +#: gitk:3293 +#, tcl-format +msgid "<%s-minus>\tDecrease font size" +msgstr "<%s-minus>\tஎழà¯à®¤à¯à®¤à¯à®°à¯ அளவைக௠கà¯à®±à¯ˆ" + +#: gitk:3294 +msgid "<F5>\t\tUpdate" +msgstr "<F5>\t\tபà¯à®¤à¯à®ªà¯à®ªà®¿à®ªà¯à®ªà¯" + +#: gitk:3761 gitk:3770 +#, tcl-format +msgid "Error creating temporary directory %s:" +msgstr "தறà¯à®•ாலிக அடைவ௠%s ஠உரà¯à®µà®¾à®•à¯à®•à¯à®µà®¤à¯ பிழை:" + +#: gitk:3783 +#, tcl-format +msgid "Error getting \"%s\" from %s:" +msgstr "%s இலிரà¯à®¨à¯à®¤à¯ \" %s\" பெறà¯à®µà®¤à¯ பிழை:" + +#: gitk:3846 +msgid "command failed:" +msgstr "கடà¯à®Ÿà®³à¯ˆ தோலà¯à®µà®¿à®¯à¯à®±à¯à®±à®¤à¯:" + +#: gitk:3995 +msgid "No such commit" +msgstr "அதà¯à®¤à®•ைய உறà¯à®¤à®¿à®®à¯Šà®´à®¿ இலà¯à®²à¯ˆ" + +#: gitk:4009 +msgid "git gui blame: command failed:" +msgstr "அறிவிலி இடைமà¯à®• பழி: கடà¯à®Ÿà®³à¯ˆ தோலà¯à®µà®¿à®¯à¯à®±à¯à®±à®¤à¯:" + +#: gitk:4040 +#, tcl-format +msgid "Couldn't read merge head: %s" +msgstr "ஒனà¯à®±à®¿à®£à¯ˆà®ªà¯à®ªà¯ தலையைப௠படிகà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ: %s" + +#: gitk:4048 +#, tcl-format +msgid "Error reading index: %s" +msgstr "பிழை வாசிபà¯à®ªà¯ கà¯à®±à®¿à®¯à¯€à®Ÿà¯: %s" + +#: gitk:4073 +#, tcl-format +msgid "Couldn't start git blame: %s" +msgstr "அறிவிலி பழியைத௠தொடஙà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ: %s" + +#: gitk:4076 gitk:6965 +msgid "Searching" +msgstr "தேடà¯à®•ிறதà¯" + +#: gitk:4108 +#, tcl-format +msgid "Error running git blame: %s" +msgstr "பிழை இயஙà¯à®•à¯à®®à¯ அறிவிலி பழி: %s" + +#: gitk:4136 +#, tcl-format +msgid "That line comes from commit %s, which is not in this view" +msgstr "" +"அநà¯à®¤ வரி உறà¯à®¤à®¿à®®à¯Šà®´à®¿ %s எனà¯à®ªà®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ வரà¯à®•ிறதà¯, இத௠இநà¯à®¤ பாரà¯à®µà¯ˆà®¯à®¿à®²à¯ இலà¯à®²à¯ˆ" + +#: gitk:4150 +msgid "External diff viewer failed:" +msgstr "வெளிபà¯à®ªà¯à®± வேறà¯à®ªà®¾à®Ÿà¯ பாரà¯à®µà¯ˆà®¯à®¾à®³à®°à¯ தோலà¯à®µà®¿à®¯à¯à®±à¯à®±à®¤à¯:" + +#: gitk:4254 +msgid "All files" +msgstr "அனைதà¯à®¤à¯ கோபà¯à®ªà¯à®•ளà¯à®®à¯" + +#: gitk:4278 +msgid "View" +msgstr "காணà¯à®•" + +#: gitk:4281 +msgid "Gitk view definition" +msgstr "அறிவிலிகே பாரà¯à®µà¯ˆ வரையறை" + +#: gitk:4285 +msgid "Remember this view" +msgstr "இநà¯à®¤ பாரà¯à®µà¯ˆà®¯à¯ˆ நினைவில௠கொளà¯à®³à¯à®™à¯à®•ளà¯" + +#: gitk:4286 +msgid "References (space separated list):" +msgstr "கà¯à®±à®¿à®ªà¯à®ªà¯à®•ள௠(இடைவெளி பிரிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿ படà¯à®Ÿà®¿à®¯à®²à¯):" + +#: gitk:4287 +msgid "Branches & tags:" +msgstr "கிளைகள௠மறà¯à®±à¯à®®à¯ கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•ளà¯:" + +#: gitk:4288 +msgid "All refs" +msgstr "அனைதà¯à®¤à¯ கà¯à®±à®¿à®ªà¯à®ªà¯à®•ளà¯" + +#: gitk:4289 +msgid "All (local) branches" +msgstr "அனைதà¯à®¤à¯ (உளà¯à®³à®•) கிளைகளà¯à®®à¯" + +#: gitk:4290 +msgid "All tags" +msgstr "அனைதà¯à®¤à¯ கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•ளà¯à®®à¯" + +#: gitk:4291 +msgid "All remote-tracking branches" +msgstr "அனைதà¯à®¤à¯ தொலை-கணà¯à®•ாணிபà¯à®ªà¯ கிளைகளà¯à®®à¯" + +#: gitk:4292 +msgid "Commit Info (regular expressions):" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ செயà¯à®¤à®¿ (வழகà¯à®•மான வெளிபà¯à®ªà®¾à®Ÿà¯à®•ளà¯):" + +#: gitk:4293 +msgid "Author:" +msgstr "ஆசிரியரà¯:" + +#: gitk:4294 +msgid "Committer:" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®ªà®µà®°à¯:" + +#: gitk:4295 +msgid "Commit Message:" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ செயà¯à®¤à®¿:" + +#: gitk:4296 +msgid "Matches all Commit Info criteria" +msgstr "அனைதà¯à®¤à¯ உறà¯à®¤à®¿à®®à¯Šà®´à®¿ செயà¯à®¤à®¿ அளவà¯à®•ோலà¯à®•ளையà¯à®®à¯ பொரà¯à®¤à¯à®¤à¯à®•ிறதà¯" + +#: gitk:4297 +msgid "Matches no Commit Info criteria" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ செயà¯à®¤à®¿ அளவà¯à®•ோலà¯à®•ளà¯à®Ÿà®©à¯ பொரà¯à®¨à¯à®¤à®µà®¿à®²à¯à®²à¯ˆ" + +#: gitk:4298 +msgid "Changes to Files:" +msgstr "கோபà¯à®ªà¯à®•ளில௠மாறà¯à®±à®™à¯à®•ளà¯:" + +#: gitk:4299 +msgid "Fixed String" +msgstr "நிலையான சரமà¯" + +#: gitk:4300 +msgid "Regular Expression" +msgstr "வழகà¯à®•மான வெளிபà¯à®ªà®¾à®Ÿà¯" + +#: gitk:4301 +msgid "Search string:" +msgstr "தேடல௠சரமà¯:" + +#: gitk:4302 +msgid "" +"Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 " +"15:27:38\"):" +msgstr "" +"உறà¯à®¤à®¿à®®à¯Šà®´à®¿ தேதிகள௠(\"2 வாரஙà¯à®•ளà¯à®•à¯à®•௠மà¯à®©à¯à®ªà¯\", \"2009-01-16 15:27:38\", \"மாரà¯à®šà¯ 17, " +"2009 15:27:38\"):" + +#: gitk:4303 +msgid "Since:" +msgstr "பினà¯à®©à®°à¯:" + +#: gitk:4304 +msgid "Until:" +msgstr "வரை:" + +#: gitk:4305 +msgid "Limit and/or skip a number of revisions (positive integer):" +msgstr "" +"பல திரà¯à®¤à¯à®¤à®™à¯à®•ளை (நேரà¯à®®à®±à¯ˆ à®®à¯à®´à¯ எணà¯) கடà¯à®Ÿà¯à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯ மறà¯à®±à¯à®®à¯/அலà¯à®²à®¤à¯ தவிரà¯:" + +#: gitk:4306 +msgid "Number to show:" +msgstr "காணà¯à®ªà®¿à®•à¯à®• எணà¯:" + +#: gitk:4307 +msgid "Number to skip:" +msgstr "தவிரà¯à®•à¯à®• எணà¯:" + +#: gitk:4308 +msgid "Miscellaneous options:" +msgstr "இதர விரà¯à®ªà¯à®ªà®™à¯à®•ளà¯:" + +#: gitk:4309 +msgid "Strictly sort by date" +msgstr "கணà¯à®Ÿà®¿à®ªà¯à®ªà®¾à®• தேதியினà¯à®ªà®Ÿà®¿ வரிசைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯" + +#: gitk:4310 +msgid "Mark branch sides" +msgstr "கிளை பகà¯à®•à®™à¯à®•ளைக௠கà¯à®±à®¿" + +#: gitk:4311 +msgid "Limit to first parent" +msgstr "à®®à¯à®¤à®²à¯ பெறà¯à®±à¯‹à®°à¯à®•à¯à®•௠வரமà¯à®ªà¯" + +#: gitk:4312 +msgid "Simple history" +msgstr "எளிய வரலாறà¯" + +#: gitk:4313 +msgid "Additional arguments to git log:" +msgstr "அறிவிலி பதிவà¯à®•à¯à®•௠கூடà¯à®¤à®²à¯ வாதஙà¯à®•ளà¯:" + +#: gitk:4314 +msgid "Enter files and directories to include, one per line:" +msgstr "சேரà¯à®•à¯à®• கோபà¯à®ªà¯à®•ள௠மறà¯à®±à¯à®®à¯ கோபà¯à®ªà®•à®™à¯à®•ளை உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯, ஒர௠வரிகà¯à®•௠ஒனà¯à®±à¯:" + +#: gitk:4315 +msgid "Command to generate more commits to include:" +msgstr "சேரà¯à®•à¯à®• கூடà¯à®¤à®²à¯ உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•ளை உரà¯à®µà®¾à®•à¯à®• கடà¯à®Ÿà®³à¯ˆ:" + +#: gitk:4439 +msgid "Gitk: edit view" +msgstr "அறிவிலிகே: திரà¯à®¤à¯à®¤à¯ பாரà¯à®µà¯ˆ" + +#: gitk:4447 +msgid "-- criteria for selecting revisions" +msgstr "-- திரà¯à®¤à¯à®¤à®™à¯à®•ளைத௠தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®ªà¯à®ªà®¤à®±à¯à®•ான அளவà¯à®•ோலà¯à®•ளà¯" + +#: gitk:4452 +msgid "View Name" +msgstr "பெயரைக௠காணà¯à®•" + +#: gitk:4527 +msgid "Apply (F5)" +msgstr "இட௠(F5)" + +#: gitk:4565 +msgid "Error in commit selection arguments:" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ தேரà¯à®µà¯ வாதஙà¯à®•ளில௠பிழை:" + +#: gitk:4620 gitk:4673 gitk:5135 gitk:5149 gitk:6419 gitk:12820 gitk:12821 +msgid "None" +msgstr "எதà¯à®µà¯à®®à®¿à®²à¯à®²à¯ˆ" + +#: gitk:5232 gitk:5237 +msgid "Descendant" +msgstr "வழிதà¯à®¤à¯‹à®©à¯à®±à®²à¯" + +#: gitk:5233 +msgid "Not descendant" +msgstr "வழிதà¯à®¤à¯‹à®©à¯à®±à®²à¯ அலà¯à®²" + +#: gitk:5240 gitk:5245 +msgid "Ancestor" +msgstr "மூதாதையரà¯" + +#: gitk:5241 +msgid "Not ancestor" +msgstr "மூதாதையர௠அலà¯à®²" + +#: gitk:5535 +msgid "Local changes checked in to index but not committed" +msgstr "" +"உளà¯à®³à®• மாறà¯à®±à®™à¯à®•ள௠கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà®¿à®²à¯ சரிபாரà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®©, ஆனால௠உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ" + +#: gitk:5571 +msgid "Local uncommitted changes, not checked in to index" +msgstr "உளà¯à®³à®• உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à®¾à®¤ மாறà¯à®±à®™à¯à®•ளà¯, கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà®¿à®²à¯ சரிபாரà¯à®•à¯à®•பà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ" + +#: gitk:7319 +msgid "Error starting web browser:" +msgstr "வலை உலாவியைத௠தொடஙà¯à®•à¯à®µà®¤à®¿à®²à¯ பிழை:" + +#: gitk:7380 +msgid "and many more" +msgstr "மறà¯à®±à¯à®®à¯ மேலà¯à®®à¯ பல" + +#: gitk:7383 +msgid "many" +msgstr "பல" + +#: gitk:7578 +msgid "Tags:" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•ளà¯:" + +#: gitk:7595 gitk:7601 gitk:9081 +msgid "Parent" +msgstr "பெறà¯à®±à¯‹à®°à¯" + +#: gitk:7606 +msgid "Child" +msgstr "கà¯à®´à®¨à¯à®¤à¯ˆ" + +#: gitk:7615 +msgid "Branch" +msgstr "கிளை" + +#: gitk:7618 +msgid "Follows" +msgstr "பினà¯à®µà®°à¯à®®à®¾à®±à¯" + +#: gitk:7621 +msgid "Precedes" +msgstr "à®®à¯à®©à¯à®©à®¾à®²à¯" + +#: gitk:8216 +#, tcl-format +msgid "Error getting diffs: %s" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯ பெறà¯à®µà®¤à®¿à®²à¯ பிழை: %s" + +#: gitk:8906 +msgid "Goto:" +msgstr "செலà¯:" + +#: gitk:8927 +#, tcl-format +msgid "Short commit ID %s is ambiguous" +msgstr "கà¯à®±à¯à®•ிய உறà¯à®¤à®¿à®®à¯Šà®´à®¿ அடையாளம௠%s தெளிவறà¯à®±à®µà¯ˆ" + +#: gitk:8934 +#, tcl-format +msgid "Revision %s is not known" +msgstr "திரà¯à®¤à¯à®¤à®®à¯ %s தெரியவிலà¯à®²à¯ˆ" + +#: gitk:8944 +#, tcl-format +msgid "Commit ID %s is not known" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ அடையாளம௠%s அறியபà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ" + +#: gitk:8946 +#, tcl-format +msgid "Revision %s is not in the current view" +msgstr "திரà¯à®¤à¯à®¤à®®à¯ %s தறà¯à®ªà¯‹à®¤à¯ˆà®¯ பாரà¯à®µà¯ˆà®¯à®¿à®²à¯ இலà¯à®²à¯ˆ" + +#: gitk:9088 gitk:9103 +msgid "Date" +msgstr "திகதி" + +#: gitk:9091 +msgid "Children" +msgstr "கà¯à®´à®¨à¯à®¤à¯ˆà®•ளà¯" + +#: gitk:9154 +#, tcl-format +msgid "Reset %s branch to here" +msgstr "%s கிளையை இஙà¯à®•ே மீடà¯à®Ÿà®®à¯ˆ" + +#: gitk:9156 +msgid "Detached head: can't reset" +msgstr "பிரிகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿ தலை: மீடà¯à®Ÿà®®à¯ˆà®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯" + +#: gitk:9261 gitk:9267 +msgid "Skipping merge commit " +msgstr "ஒனà¯à®±à®¿à®£à¯ˆ உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à¯ˆ தவரà¯à®•ிறத௠" + +#: gitk:9276 gitk:9281 +msgid "Error getting patch ID for " +msgstr "ஒடà¯à®Ÿà¯ அடையாளதà¯à®¤à¯ˆà®ªà¯ பெறà¯à®µà®¤à®¿à®²à¯ பிழை" + +#: gitk:9277 gitk:9282 +msgid " - stopping\n" +msgstr "- நிறà¯à®¤à¯à®¤à¯à®¤à®²à¯\n" + +#: gitk:9287 gitk:9290 gitk:9298 gitk:9312 gitk:9321 +msgid "Commit " +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿" + +#: gitk:9291 +msgid "" +" is the same patch as\n" +" " +msgstr "அதே ஒடà¯à®Ÿà¯\n" +" " + +#: gitk:9299 +msgid "" +" differs from\n" +" " +msgstr "இரà¯à®¨à¯à®¤à¯ வேறà¯à®ªà®Ÿà¯à®•ிறதà¯\n" +" " + +#: gitk:9301 +msgid "" +"Diff of commits:\n" +"\n" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à®¿à®©à¯ வேறà¯à®ªà®¾à®Ÿà¯:\n" +"\n" + +#: gitk:9313 gitk:9322 +#, tcl-format +msgid " has %s children - stopping\n" +msgstr "%s கà¯à®´à®¨à¯à®¤à¯ˆà®•ள௠உளà¯à®³à®©à®°à¯ - நிறà¯à®¤à¯à®¤à¯à®¤à®²à¯\n" + +#: gitk:9341 +#, tcl-format +msgid "Error writing commit to file: %s" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ கோபà¯à®ªà®¿à®²à¯ எழà¯à®¤à¯à®¤à®²à¯ பிழை: %s" + +#: gitk:9347 +#, tcl-format +msgid "Error diffing commits: %s" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•ள௠வேறà¯à®ªà®¾à®Ÿà¯ பிழை: %s" + +#: gitk:9393 +msgid "Top" +msgstr "மேலே" + +#: gitk:9394 +msgid "From" +msgstr "இரà¯à®¨à¯à®¤à¯" + +#: gitk:9399 +msgid "To" +msgstr "பெறà¯à®¨à®°à¯" + +#: gitk:9423 +msgid "Generate patch" +msgstr "ஒடà¯à®Ÿà¯ˆ உரà¯à®µà®¾à®•à¯à®•à¯" + +#: gitk:9425 +msgid "From:" +msgstr "இரà¯à®¨à¯à®¤à¯:" + +#: gitk:9434 +msgid "To:" +msgstr "இதறà¯à®•à¯:" + +#: gitk:9443 +msgid "Reverse" +msgstr "தலைகீழà¯" + +#: gitk:9445 gitk:9655 +msgid "Output file:" +msgstr "வெளியீடà¯à®Ÿà¯ கோபà¯à®ªà¯:" + +#: gitk:9451 +msgid "Generate" +msgstr "உரà¯à®µà®¾à®•à¯à®•à¯" + +#: gitk:9489 +msgid "Error creating patch:" +msgstr "ஒடà¯à®Ÿà¯ˆ உரà¯à®µà®¾à®•à¯à®•௠பிழை:" + +#: gitk:9512 gitk:9643 gitk:9731 +msgid "ID:" +msgstr "அடையாளமà¯:" + +#: gitk:9521 +msgid "Tag name:" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯ பெயரà¯:" + +#: gitk:9524 +msgid "Tag message is optional" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯ செயà¯à®¤à®¿ விரà¯à®ªà¯à®ªà®®à®¾à®©à®¤à¯" + +#: gitk:9526 +msgid "Tag message:" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯ செயà¯à®¤à®¿:" + +#: gitk:9530 gitk:9701 +msgid "Create" +msgstr "உரà¯à®µà®¾à®•à¯à®•à¯" + +#: gitk:9548 +msgid "No tag name specified" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯ பெயர௠கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ" + +#: gitk:9552 +#, tcl-format +msgid "Tag \"%s\" already exists" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯ \"%s\" à®à®±à¯à®•னவே உளà¯à®³à®¤à¯" + +#: gitk:9562 +msgid "Error creating tag:" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உரà¯à®µà®¾à®•à¯à®•௠பிழை:" + +#: gitk:9652 +msgid "Command:" +msgstr "கடà¯à®Ÿà®³à¯ˆ:" + +#: gitk:9660 +msgid "Write" +msgstr "எழà¯à®¤à¯" + +#: gitk:9678 +msgid "Error writing commit:" +msgstr "பிழை எழà¯à®¤à¯à®¤à®²à¯ உறà¯à®¤à®¿à®®à¯Šà®´à®¿:" + +#: gitk:9700 +msgid "Create branch" +msgstr "கிளையை உரà¯à®µà®¾à®•à¯à®•à¯" + +#: gitk:9716 +#, tcl-format +msgid "Rename branch %s" +msgstr "%s கிளையை மறà¯à®ªà¯†à®¯à®°à®¿à®Ÿà¯" + +#: gitk:9717 +msgid "Rename" +msgstr "மறà¯à®ªà¯†à®¯à®°à®¿à®Ÿà¯" + +#: gitk:9741 +msgid "Name:" +msgstr "பெயரà¯:" + +#: gitk:9765 +msgid "Please specify a name for the new branch" +msgstr "பà¯à®¤à®¿à®¯ கிளைகà¯à®•௠ஒர௠பெயரைக௠கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯" + +#: gitk:9770 +#, tcl-format +msgid "Branch '%s' already exists. Overwrite?" +msgstr "கிளை '%s' à®à®±à¯à®•னவே உளà¯à®³à®¤à¯. மேலெழà¯à®¤à®µà®¾?" + +#: gitk:9814 +msgid "Please specify a new name for the branch" +msgstr "கிளைகà¯à®•௠ஒர௠பà¯à®¤à®¿à®¯ பெயரைக௠கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯" + +#: gitk:9877 +#, tcl-format +msgid "Commit %s is already included in branch %s -- really re-apply it?" +msgstr "" +"உறà¯à®¤à®¿à®®à¯Šà®´à®¿ %s à®à®±à¯à®•னவே கிளை %s சேரà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®©-உணà¯à®®à¯ˆà®¯à®¿à®²à¯ அதை மீணà¯à®Ÿà¯à®®à¯ இடவா?" + +#: gitk:9882 +msgid "Cherry-picking" +msgstr "கனி எடà¯à®•à¯à®•à¯à®®à¯" + +#: gitk:9891 +#, tcl-format +msgid "" +"Cherry-pick failed because of local changes to file '%s'.\n" +"Please commit, reset or stash your changes and try again." +msgstr "" +"'%s' கோபà¯à®ªà®¿à®²à¯ உளà¯à®³à®• மாறà¯à®±à®™à¯à®•ள௠காரணமாக கனி-எட௠தோலà¯à®µà®¿à®¯à®Ÿà¯ˆà®¨à¯à®¤à®¤à¯. \n" +"தயவà¯à®šà¯†à®¯à¯à®¤à¯ உஙà¯à®•ள௠மாறà¯à®±à®™à¯à®•ளைச௠உறà¯à®¤à®¿à®®à¯Šà®´à®¿, மீடà¯à®Ÿà®®à¯ˆ அலà¯à®²à®¤à¯ சேமி பிறக௠மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿." + +#: gitk:9897 +msgid "" +"Cherry-pick failed because of merge conflict.\n" +"Do you wish to run git citool to resolve it?" +msgstr "" +"ஒனà¯à®±à®¿à®£à¯ˆà®•à¯à®•à¯à®®à¯ மோதல௠காரணமாக கனி-எட௠தோலà¯à®µà®¿à®¯à®Ÿà¯ˆà®¨à¯à®¤à®¤à¯. \n" +"அதை தீரà¯à®•à¯à®• அறிவிலி சிà®à®•à®°à¯à®µà®¿à®¯à¯ˆ இயகà¯à®• விரà¯à®®à¯à®ªà¯à®•ிறீரà¯à®•ளா?" + +#: gitk:9913 gitk:9971 +msgid "No changes committed" +msgstr "எநà¯à®¤ மாறà¯à®±à®™à¯à®•ளà¯à®®à¯ உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®¯à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ" + +#: gitk:9940 +#, tcl-format +msgid "Commit %s is not included in branch %s -- really revert it?" +msgstr "" +"உறà¯à®¤à®¿à®®à¯Šà®´à®¿ %s கிளை %s சேரà¯à®•à¯à®•பà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ - உணà¯à®®à¯ˆà®¯à®¿à®²à¯ அதை மீடà¯à®Ÿà¯†à®Ÿà¯à®•à¯à®•வா?" + +#: gitk:9945 +msgid "Reverting" +msgstr "மீடà¯à®Ÿà¯†à®Ÿà¯à®¤à¯à®¤à®²à¯" + +#: gitk:9953 +#, tcl-format +msgid "" +"Revert failed because of local changes to the following files:%s Please " +"commit, reset or stash your changes and try again." +msgstr "" +"பினà¯à®µà®°à¯à®®à¯ கோபà¯à®ªà¯à®•ளில௠உளà¯à®³à®• மாறà¯à®±à®™à¯à®•ள௠காரணமாக மீடà¯à®Ÿà¯†à®Ÿà¯ தோலà¯à®µà®¿à®¯à¯à®±à¯à®±à®¤à¯:%s " +"தயவà¯à®šà¯†à®¯à¯à®¤à¯ உஙà¯à®•ள௠மாறà¯à®±à®™à¯à®•ளைச௠உறà¯à®¤à®¿à®®à¯Šà®´à®¿, மீடà¯à®Ÿà®®à¯ˆ அலà¯à®²à®¤à¯ " +"சேமி மறà¯à®±à¯à®®à¯ மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿." + +#: gitk:9957 +msgid "" +"Revert failed because of merge conflict.\n" +" Do you wish to run git citool to resolve it?" +msgstr "" +"ஒனà¯à®±à®¿à®£à¯ˆà®•à¯à®•à¯à®®à¯ மோதல௠காரணமாக மீடà¯à®Ÿà¯†à®Ÿà¯ தோலà¯à®µà®¿à®¯à®Ÿà¯ˆà®¨à¯à®¤à®¤à¯. \n" +"அதை தீரà¯à®•à¯à®• அறிவிலி சிà®à®•à®°à¯à®µà®¿à®¯à¯ˆ இயகà¯à®• விரà¯à®®à¯à®ªà¯à®•ிறீரà¯à®•ளா?" + +#: gitk:10000 +msgid "Confirm reset" +msgstr "மீடà¯à®Ÿà®®à¯ˆà®ªà¯à®ªà¯ˆ உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯" + +#: gitk:10002 +#, tcl-format +msgid "Reset branch %s to %s?" +msgstr "%s கிளையை %s கà¯à®•௠மீடà¯à®Ÿà®®à¯ˆà®•à¯à®•வா?" + +#: gitk:10004 +msgid "Reset type:" +msgstr "மீடà¯à®Ÿà®®à¯ˆ வகை:" + +#: gitk:10007 +msgid "Soft: Leave working tree and index untouched" +msgstr "" +"மெனà¯à®®à¯ˆ: வேலை செயà¯à®¯à¯à®®à¯ மரம௠மறà¯à®±à¯à®®à¯ கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà¯ˆà®¤à¯ தீணà¯à®Ÿà®¾à®®à®²à¯ விடà¯" + +#: gitk:10010 +msgid "Mixed: Leave working tree untouched, reset index" +msgstr "" +"கலபà¯à®ªà¯: வேலை செயà¯à®¯à¯à®®à¯ மரதà¯à®¤à¯ˆ தீணà¯à®Ÿà®¾à®®à®²à¯ விடà¯, கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà¯ˆ மீடà¯à®Ÿà®®à¯ˆ" + +#: gitk:10013 +msgid "" +"Hard: Reset working tree and index\n" +"(discard ALL local changes)" +msgstr "" +"கடினமà¯: வேலை செயà¯à®¯à¯à®®à¯ மரம௠மறà¯à®±à¯à®®à¯ கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà¯ˆ மீடà¯à®Ÿà®®à¯ˆ \n" +"(அனைதà¯à®¤à¯ உளà¯à®³à®• மாறà¯à®±à®™à¯à®•ளையà¯à®®à¯ நிராகரி)" + +#: gitk:10030 +msgid "Resetting" +msgstr "மீடà¯à®Ÿà®®à¯ˆà®¤à¯à®¤à®²à¯" + +#: gitk:10103 +#, tcl-format +msgid "A local branch named %s exists already" +msgstr "%s எனà¯à®± உளà¯à®³à®• கிளை à®à®±à¯à®•னவே உளà¯à®³à®¤à¯" + +#: gitk:10111 +msgid "Checking out" +msgstr "சரிபாரà¯" + +#: gitk:10170 +msgid "Cannot delete the currently checked-out branch" +msgstr "தறà¯à®ªà¯‹à®¤à¯ சரிபாரà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ கிளையை நீகà¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯" + +#: gitk:10176 +#, tcl-format +msgid "" +"The commits on branch %s aren't on any other branch.\n" +"Really delete branch %s?" +msgstr "" +"கிளை %s மீதான உறà¯à®¤à®¿à®®à¯Šà®´à®¿à®•ள௠வேற௠எநà¯à®¤ கிளையிலà¯à®®à¯ இலà¯à®²à¯ˆ. \n" +"உணà¯à®®à¯ˆà®¯à®¿à®²à¯ கிளை %s நீகà¯à®•வா?" + +#: gitk:10207 +#, tcl-format +msgid "Tags and heads: %s" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•ள௠மறà¯à®±à¯à®®à¯ தலைகளà¯: %s" + +#: gitk:10224 +msgid "Filter" +msgstr "வடிபà¯à®ªà®¿" + +#: gitk:10531 +msgid "" +"Error reading commit topology information; branch and preceding/following " +"tag information will be incomplete." +msgstr "" +"உறà¯à®¤à®¿à®®à¯Šà®´à®¿ இடவியல௠தகவலை படிபà¯à®ªà®¤à®¿à®²à¯ பிழை; கிளை மறà¯à®±à¯à®®à¯ அதறà¯à®•௠" +"à®®à¯à®¨à¯à®¤à¯ˆà®¯/பினà¯à®µà®°à¯à®®à¯ கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯ செயà¯à®¤à®¿ à®®à¯à®´à¯à®®à¯ˆà®¯à®Ÿà¯ˆà®¯à®¾à®¤à¯." + +#: gitk:11508 +msgid "Tag" +msgstr "கà¯à®±à®¿à®šà¯à®šà¯Šà®²à¯" + +#: gitk:11512 +msgid "Id" +msgstr "அடையாளமà¯" + +#: gitk:11595 +msgid "Gitk font chooser" +msgstr "அறிவிலிகே எழà¯à®¤à¯à®¤à¯à®°à¯ தேரà¯à®µà¯" + +#: gitk:11612 +msgid "B" +msgstr "பி" + +#: gitk:11615 +msgid "I" +msgstr "à®" + +#: gitk:11734 +msgid "Commit list display options" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ காடà¯à®šà®¿ விரà¯à®ªà¯à®ªà®™à¯à®•ளà¯" + +#: gitk:11737 +msgid "Maximum graph width (lines)" +msgstr "அதிகபடà¯à®š வரைபட அகலம௠(கோடà¯à®•ளà¯)" + +#: gitk:11741 +#, no-tcl-format +msgid "Maximum graph width (% of pane)" +msgstr "அதிகபடà¯à®š வரைபட அகலம௠(பலகதà¯à®¤à®¿à®©à¯ %)" + +#: gitk:11744 +msgid "Show local changes" +msgstr "உளà¯à®³à®• மாறà¯à®±à®™à¯à®•ளைக௠காடà¯à®Ÿà¯" + +#: gitk:11747 +msgid "Hide remote refs" +msgstr "தொலை கà¯à®±à®¿à®•ளை மறை" + +#: gitk:11751 +msgid "Copy commit ID to clipboard" +msgstr "இடைநிலைபà¯à®ªà®²à®•ைகà¯à®•௠அடையாளதà¯à®¤à¯ˆ நகலெடà¯" + +#: gitk:11755 +msgid "Copy commit ID to X11 selection" +msgstr "உறà¯à®¤à®¿à®®à¯Šà®´à®¿ அடையாளதà¯à®¤à¯ˆ ஃ11 பகà¯à®¤à®¿à®•à¯à®•௠நகலெடà¯" + +#: gitk:11760 +msgid "Length of commit ID to copy" +msgstr "நகலெடà¯à®•à¯à®• உறà¯à®¤à®¿à®®à¯Šà®´à®¿ அடையாளதà¯à®¤à®¿à®©à¯ நீளமà¯" + +#: gitk:11763 +msgid "Diff display options" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯ காடà¯à®šà®¿ விரà¯à®ªà¯à®ªà®™à¯à®•ளà¯" + +#: gitk:11765 +msgid "Tab spacing" +msgstr "தாவல௠இடைவெளி" + +#: gitk:11769 +msgid "Wrap comment text" +msgstr "கரà¯à®¤à¯à®¤à¯ உரையை மடி" + +#: gitk:11774 +msgid "Wrap other text" +msgstr "மறà¯à®± உரையை மடி" + +#: gitk:11779 +msgid "Display nearby tags/heads" +msgstr "à®…à®°à¯à®•ிலà¯à®³à¯à®³ கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•ளà¯/தலைகளைக௠காணà¯à®ªà®¿" + +#: gitk:11782 +msgid "Maximum # tags/heads to show" +msgstr "காணà¯à®ªà®¿à®•à¯à®• அதிகபடà¯à®š # கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•ளà¯/தலைகளà¯" + +#: gitk:11785 +msgid "Limit diffs to listed paths" +msgstr "படà¯à®Ÿà®¿à®¯à®²à®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿ பாதைகளà¯à®•à¯à®•௠வரமà¯à®ªà¯ வேறà¯à®ªà®Ÿà¯à®•ிறதà¯" + +#: gitk:11788 +msgid "Support per-file encodings" +msgstr "ஒர௠கோபà¯à®ªà¯ கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®•ளை ஆதரி" + +#: gitk:11794 gitk:11961 +msgid "External diff tool" +msgstr "வெளிபà¯à®ªà¯à®± வேறà¯à®ªà®¾à®Ÿà¯ கரà¯à®µà®¿" + +#: gitk:11795 +msgid "Choose..." +msgstr "தேரà¯à®µà¯..." + +#: gitk:11802 +msgid "Web browser" +msgstr "வலை உலாவி" + +#: gitk:11807 +msgid "General options" +msgstr "பொத௠விரà¯à®ªà¯à®ªà®™à¯à®•ளà¯" + +#: gitk:11810 +msgid "Use themed widgets" +msgstr "கரà¯à®ªà¯à®ªà¯Šà®°à¯à®³à¯ நிரலà¯à®ªà®²à®•ைகளைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯" + +#: gitk:11812 +msgid "(change requires restart)" +msgstr "(மாறà¯à®±à®¤à¯à®¤à®¿à®±à¯à®•௠மறà¯à®¤à¯Šà®Ÿà®•à¯à®•ம௠தேவை)" + +#: gitk:11814 +msgid "(currently unavailable)" +msgstr "(தறà¯à®ªà¯‹à®¤à¯ கிடைகà¯à®•விலà¯à®²à¯ˆ)" + +#: gitk:11826 +msgid "Colors: press to choose" +msgstr "நிறஙà¯à®•ளà¯: தேரà¯à®µà¯ செயà¯à®¯ à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯" + +#: gitk:11829 +msgid "Interface" +msgstr "இடைமà¯à®•à®®à¯" + +#: gitk:11830 +msgid "interface" +msgstr "இடைமà¯à®•à®®à¯" + +#: gitk:11833 +msgid "Background" +msgstr "பினà¯à®©à®£à®¿" + +#: gitk:11834 gitk:11876 +msgid "background" +msgstr "பினà¯à®©à®£à®¿" + +#: gitk:11837 +msgid "Foreground" +msgstr "à®®à¯à®©à¯à®ªà¯à®±à®®à¯" + +#: gitk:11838 +msgid "foreground" +msgstr "à®®à¯à®©à¯à®ªà¯à®±à®®à¯" + +#: gitk:11841 +msgid "Diff: old lines" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯: பழைய வரிகளà¯" + +#: gitk:11842 +msgid "diff old lines" +msgstr "பழைய வரிகள௠வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:11846 +msgid "Diff: old lines bg" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯: பழைய வரிகள௠பினà¯à®£à®©à®¿" + +#: gitk:11848 +msgid "diff old lines bg" +msgstr "பழைய வரிகள௠பினà¯à®£à®©à®¿ வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:11852 +msgid "Diff: new lines" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯: பà¯à®¤à®¿à®¯ கோடà¯à®•ளà¯" + +#: gitk:11853 +msgid "diff new lines" +msgstr "பà¯à®¤à®¿à®¯ வரிகள௠வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:11857 +msgid "Diff: new lines bg" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯: பà¯à®¤à®¿à®¯ வரிகள௠பினà¯à®£à®©à®¿" + +#: gitk:11859 +msgid "diff new lines bg" +msgstr "பà¯à®¤à®¿à®¯ வரிகளை பினà¯à®£à®©à®¿ வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:11863 +msgid "Diff: hunk header" +msgstr "வேறà¯à®ªà®¾à®Ÿà¯: à®…à®™à¯à®•௠தலைபà¯à®ªà¯" + +#: gitk:11865 +msgid "diff hunk header" +msgstr "à®…à®™à¯à®•௠தலைபà¯à®ªà¯ வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:11869 +msgid "Marked line bg" +msgstr "கà¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ வரி பினà¯à®©à®£à®¿" + +#: gitk:11871 +msgid "marked line background" +msgstr "கà¯à®±à®¿à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ வரி பினà¯à®©à®£à®¿" + +#: gitk:11875 +msgid "Select bg" +msgstr "பினà¯à®©à®£à®¿ தேரà¯à®µà¯" + +#: gitk:11884 +msgid "Fonts: press to choose" +msgstr "எழà¯à®¤à¯à®¤à¯à®°à¯à®•à¯à®•ளà¯: தேரà¯à®µà¯ செயà¯à®¯ à®…à®´à¯à®¤à¯à®¤à¯" + +#: gitk:11886 +msgid "Main font" +msgstr "à®®à¯à®¤à®©à¯à®®à¯ˆà®¯à®¾à®© எழà¯à®¤à¯à®¤à¯à®°à¯" + +#: gitk:11887 +msgid "Diff display font" +msgstr "காடà¯à®šà®¿ எழà¯à®¤à¯à®¤à¯à®°à¯ வேறà¯à®ªà®¾à®Ÿà¯" + +#: gitk:11888 +msgid "User interface font" +msgstr "பயனர௠இடைமà¯à®• எழà¯à®¤à¯à®¤à¯à®°à¯" + +#: gitk:11910 +msgid "Gitk preferences" +msgstr "அறிவிலிகே விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯‡à®°à¯à®µà¯à®•ளà¯" + +#: gitk:11919 +msgid "General" +msgstr "பொதà¯" + +#: gitk:11920 +msgid "Colors" +msgstr "நிறஙà¯à®•ளà¯" + +#: gitk:11921 +msgid "Fonts" +msgstr "எழà¯à®¤à¯à®¤à¯à®°à¯à®•à¯à®•ளà¯" + +#: gitk:11971 +#, tcl-format +msgid "Gitk: choose color for %s" +msgstr "அறிவிலிகே: %s கà¯à®•௠வணà¯à®£à®¤à¯à®¤à¯ˆà®¤à¯ தேரà¯à®µà¯à®šà¯†à®¯à¯à®•" + +#: gitk:12490 +msgid "" +"Sorry, gitk cannot run with this version of Tcl/Tk.\n" +" Gitk requires at least Tcl/Tk 8.4." +msgstr "" +"மனà¯à®©à®¿à®•à¯à®•வà¯à®®à¯, டிசிஎலà¯/டிகேயின௠இநà¯à®¤ பதிபà¯à®ªà¯ˆà®•௠கொணà¯à®Ÿà¯ அறிவிலிகே இயகà¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯. \n" +"அறிவிலிகேவà¯à®•à¯à®•௠கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®šà®®à¯ டிசிஎலà¯/டிகே 8.4 தேவைபà¯à®ªà®Ÿà¯à®•ிறதà¯." + +#: gitk:12711 +msgid "Cannot find a git repository here." +msgstr "இஙà¯à®•ே ஒர௠அறிவிலி களஞà¯à®šà®¿à®¯à®¤à¯à®¤à¯ˆà®•௠கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ." + +#: gitk:12758 +#, tcl-format +msgid "Ambiguous argument '%s': both revision and filename" +msgstr "தெளிவறà¯à®± வாதம௠'%s': திரà¯à®¤à¯à®¤à®®à¯ மறà¯à®±à¯à®®à¯ கோபà¯à®ªà¯ பெயரà¯" + +#: gitk:12770 +msgid "Bad arguments to gitk:" +msgstr "அறிவிலிகேவிறà¯à®•௠மோசமான வாதஙà¯à®•ளà¯:" + +#~ msgid "SHA1 ID:" +#~ msgstr "சா1 அடையாளமà¯:" + +#~ msgid "Auto-select SHA1 (length)" +#~ msgstr "தானாக தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿ சா1 (நீளமà¯)" diff --git a/gitweb/Makefile b/gitweb/Makefile index d5748e9359..26a683d442 100644 --- a/gitweb/Makefile +++ b/gitweb/Makefile @@ -118,7 +118,7 @@ $(MAK_DIR_GITWEB)gitweb.cgi: $(MAK_DIR_GITWEB)gitweb.perl $(MAK_DIR_GITWEB)static/gitweb.js: $(MAK_DIR_GITWEB)generate-gitweb-js.sh $(MAK_DIR_GITWEB)static/gitweb.js: $(addprefix $(MAK_DIR_GITWEB),$(GITWEB_JSLIB_FILES)) $(QUIET_GEN)$(RM) $@ $@+ && \ - $(MAK_DIR_GITWEB)generate-gitweb-js.sh $@+ $^ && \ + $(MAK_DIR_GITWEB)generate-gitweb-js.sh $@+ $(filter %.js,$^) && \ mv $@+ $@ ### Installation rules diff --git a/gitweb/meson.build b/gitweb/meson.build index 89b403dc9d..88a54b4dc9 100644 --- a/gitweb/meson.build +++ b/gitweb/meson.build @@ -1,5 +1,5 @@ gitweb_config = configuration_data() -gitweb_config.set_quoted('PERL_PATH', perl.full_path()) +gitweb_config.set_quoted('PERL_PATH', target_perl.full_path()) gitweb_config.set_quoted('CSSMIN', '') gitweb_config.set_quoted('JSMIN', '') gitweb_config.set_quoted('GIT_BINDIR', get_option('prefix') / get_option('bindir')) @@ -5,7 +5,7 @@ #include "gettext.h" #include "grep.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "pretty.h" #include "userdiff.h" #include "xdiff-interface.h" @@ -1517,7 +1517,7 @@ static int fill_textconv_grep(struct repository *r, fill_filespec(df, gs->identifier, 1, 0100644); break; case GREP_SOURCE_FILE: - fill_filespec(df, null_oid(), 0, 0100644); + fill_filespec(df, null_oid(r->hash_algo), 0, 0100644); break; default: BUG("attempt to textconv something without a path?"); diff --git a/hash.c b/hash.c new file mode 100644 index 0000000000..4a04ecb50e --- /dev/null +++ b/hash.c @@ -0,0 +1,277 @@ +#include "git-compat-util.h" +#include "hash.h" +#include "hex.h" + +static const struct object_id empty_tree_oid = { + .hash = { + 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60, + 0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 + }, + .algo = GIT_HASH_SHA1, +}; +static const struct object_id empty_blob_oid = { + .hash = { + 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b, + 0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 + }, + .algo = GIT_HASH_SHA1, +}; +static const struct object_id null_oid_sha1 = { + .hash = {0}, + .algo = GIT_HASH_SHA1, +}; +static const struct object_id empty_tree_oid_sha256 = { + .hash = { + 0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1, + 0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5, + 0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc, + 0x53, 0x21 + }, + .algo = GIT_HASH_SHA256, +}; +static const struct object_id empty_blob_oid_sha256 = { + .hash = { + 0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2, + 0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43, + 0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72, + 0x18, 0x13 + }, + .algo = GIT_HASH_SHA256, +}; +static const struct object_id null_oid_sha256 = { + .hash = {0}, + .algo = GIT_HASH_SHA256, +}; + +static void git_hash_sha1_init(struct git_hash_ctx *ctx) +{ + ctx->algop = &hash_algos[GIT_HASH_SHA1]; + git_SHA1_Init(&ctx->state.sha1); +} + +static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) +{ + dst->algop = src->algop; + git_SHA1_Clone(&dst->state.sha1, &src->state.sha1); +} + +static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len) +{ + git_SHA1_Update(&ctx->state.sha1, data, len); +} + +static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx) +{ + git_SHA1_Final(hash, &ctx->state.sha1); +} + +static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) +{ + git_SHA1_Final(oid->hash, &ctx->state.sha1); + memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); + oid->algo = GIT_HASH_SHA1; +} + +static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx) +{ + ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]); + git_SHA1_Init_unsafe(&ctx->state.sha1_unsafe); +} + +static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src) +{ + dst->algop = src->algop; + git_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe); +} + +static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data, + size_t len) +{ + git_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len); +} + +static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx) +{ + git_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe); +} + +static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx) +{ + git_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe); + memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); + oid->algo = GIT_HASH_SHA1; +} + +static void git_hash_sha256_init(struct git_hash_ctx *ctx) +{ + ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]); + git_SHA256_Init(&ctx->state.sha256); +} + +static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) +{ + dst->algop = src->algop; + git_SHA256_Clone(&dst->state.sha256, &src->state.sha256); +} + +static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len) +{ + git_SHA256_Update(&ctx->state.sha256, data, len); +} + +static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx) +{ + git_SHA256_Final(hash, &ctx->state.sha256); +} + +static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) +{ + git_SHA256_Final(oid->hash, &ctx->state.sha256); + /* + * This currently does nothing, so the compiler should optimize it out, + * but keep it in case we extend the hash size again. + */ + memset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ); + oid->algo = GIT_HASH_SHA256; +} + +static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED) +{ + BUG("trying to init unknown hash"); +} + +static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED, + const struct git_hash_ctx *src UNUSED) +{ + BUG("trying to clone unknown hash"); +} + +static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED, + const void *data UNUSED, + size_t len UNUSED) +{ + BUG("trying to update unknown hash"); +} + +static void git_hash_unknown_final(unsigned char *hash UNUSED, + struct git_hash_ctx *ctx UNUSED) +{ + BUG("trying to finalize unknown hash"); +} + +static void git_hash_unknown_final_oid(struct object_id *oid UNUSED, + struct git_hash_ctx *ctx UNUSED) +{ + BUG("trying to finalize unknown hash"); +} + +static const struct git_hash_algo sha1_unsafe_algo = { + .name = "sha1", + .format_id = GIT_SHA1_FORMAT_ID, + .rawsz = GIT_SHA1_RAWSZ, + .hexsz = GIT_SHA1_HEXSZ, + .blksz = GIT_SHA1_BLKSZ, + .init_fn = git_hash_sha1_init_unsafe, + .clone_fn = git_hash_sha1_clone_unsafe, + .update_fn = git_hash_sha1_update_unsafe, + .final_fn = git_hash_sha1_final_unsafe, + .final_oid_fn = git_hash_sha1_final_oid_unsafe, + .empty_tree = &empty_tree_oid, + .empty_blob = &empty_blob_oid, + .null_oid = &null_oid_sha1, +}; + +const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { + { + .name = NULL, + .format_id = 0x00000000, + .rawsz = 0, + .hexsz = 0, + .blksz = 0, + .init_fn = git_hash_unknown_init, + .clone_fn = git_hash_unknown_clone, + .update_fn = git_hash_unknown_update, + .final_fn = git_hash_unknown_final, + .final_oid_fn = git_hash_unknown_final_oid, + .empty_tree = NULL, + .empty_blob = NULL, + .null_oid = NULL, + }, + { + .name = "sha1", + .format_id = GIT_SHA1_FORMAT_ID, + .rawsz = GIT_SHA1_RAWSZ, + .hexsz = GIT_SHA1_HEXSZ, + .blksz = GIT_SHA1_BLKSZ, + .init_fn = git_hash_sha1_init, + .clone_fn = git_hash_sha1_clone, + .update_fn = git_hash_sha1_update, + .final_fn = git_hash_sha1_final, + .final_oid_fn = git_hash_sha1_final_oid, + .unsafe = &sha1_unsafe_algo, + .empty_tree = &empty_tree_oid, + .empty_blob = &empty_blob_oid, + .null_oid = &null_oid_sha1, + }, + { + .name = "sha256", + .format_id = GIT_SHA256_FORMAT_ID, + .rawsz = GIT_SHA256_RAWSZ, + .hexsz = GIT_SHA256_HEXSZ, + .blksz = GIT_SHA256_BLKSZ, + .init_fn = git_hash_sha256_init, + .clone_fn = git_hash_sha256_clone, + .update_fn = git_hash_sha256_update, + .final_fn = git_hash_sha256_final, + .final_oid_fn = git_hash_sha256_final_oid, + .empty_tree = &empty_tree_oid_sha256, + .empty_blob = &empty_blob_oid_sha256, + .null_oid = &null_oid_sha256, + } +}; + +const struct object_id *null_oid(const struct git_hash_algo *algop) +{ + return algop->null_oid; +} + +const char *empty_tree_oid_hex(const struct git_hash_algo *algop) +{ + static char buf[GIT_MAX_HEXSZ + 1]; + return oid_to_hex_r(buf, algop->empty_tree); +} + +int hash_algo_by_name(const char *name) +{ + if (!name) + return GIT_HASH_UNKNOWN; + for (size_t i = 1; i < GIT_HASH_NALGOS; i++) + if (!strcmp(name, hash_algos[i].name)) + return i; + return GIT_HASH_UNKNOWN; +} + +int hash_algo_by_id(uint32_t format_id) +{ + for (size_t i = 1; i < GIT_HASH_NALGOS; i++) + if (format_id == hash_algos[i].format_id) + return i; + return GIT_HASH_UNKNOWN; +} + +int hash_algo_by_length(size_t len) +{ + for (size_t i = 1; i < GIT_HASH_NALGOS; i++) + if (len == hash_algos[i].rawsz) + return i; + return GIT_HASH_UNKNOWN; +} + +const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop) +{ + /* If we have a faster "unsafe" implementation, use that. */ + if (algop->unsafe) + return algop->unsafe; + /* Otherwise use the default one. */ + return algop; +} @@ -2,26 +2,32 @@ #define HASH_H #if defined(SHA1_APPLE) +#define SHA1_BACKEND "SHA1_APPLE (No collision detection)" #include <CommonCrypto/CommonDigest.h> #elif defined(SHA1_OPENSSL) +# define SHA1_BACKEND "SHA1_OPENSSL (No collision detection)" # include <openssl/sha.h> # if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3 # define SHA1_NEEDS_CLONE_HELPER # include "sha1/openssl.h" # endif #elif defined(SHA1_DC) +#define SHA1_BACKEND "SHA1_DC" #include "sha1dc_git.h" #else /* SHA1_BLK */ +#define SHA1_BACKEND "SHA1_BLK (No collision detection)" #include "block-sha1/sha1.h" #endif #if defined(SHA1_APPLE_UNSAFE) +# define SHA1_UNSAFE_BACKEND "SHA1_APPLE_UNSAFE" # include <CommonCrypto/CommonDigest.h> # define platform_SHA_CTX_unsafe CC_SHA1_CTX # define platform_SHA1_Init_unsafe CC_SHA1_Init # define platform_SHA1_Update_unsafe CC_SHA1_Update # define platform_SHA1_Final_unsafe CC_SHA1_Final #elif defined(SHA1_OPENSSL_UNSAFE) +# define SHA1_UNSAFE_BACKEND "SHA1_OPENSSL_UNSAFE" # include <openssl/sha.h> # if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3 # define SHA1_NEEDS_CLONE_HELPER_UNSAFE @@ -38,6 +44,7 @@ # define platform_SHA1_Final_unsafe SHA1_Final # endif #elif defined(SHA1_BLK_UNSAFE) +# define SHA1_UNSAFE_BACKEND "SHA1_BLK_UNSAFE" # include "block-sha1/sha1.h" # define platform_SHA_CTX_unsafe blk_SHA_CTX # define platform_SHA1_Init_unsafe blk_SHA1_Init @@ -46,17 +53,21 @@ #endif #if defined(SHA256_NETTLE) +#define SHA256_BACKEND "SHA256_NETTLE" #include "sha256/nettle.h" #elif defined(SHA256_GCRYPT) +#define SHA256_BACKEND "SHA256_GCRYPT" #define SHA256_NEEDS_CLONE_HELPER #include "sha256/gcrypt.h" #elif defined(SHA256_OPENSSL) +# define SHA256_BACKEND "SHA256_OPENSSL" # include <openssl/sha.h> # if defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL >= 3 # define SHA256_NEEDS_CLONE_HELPER # include "sha256/openssl.h" # endif #else +#define SHA256_BACKEND "SHA256_BLK" #include "sha256/block/sha256.h" #endif @@ -193,17 +204,18 @@ struct object_id { int algo; /* XXX requires 4-byte alignment */ }; -#define GET_OID_QUIETLY 01 -#define GET_OID_COMMIT 02 -#define GET_OID_COMMITTISH 04 -#define GET_OID_TREE 010 -#define GET_OID_TREEISH 020 -#define GET_OID_BLOB 040 -#define GET_OID_FOLLOW_SYMLINKS 0100 -#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_QUIETLY 01 +#define GET_OID_COMMIT 02 +#define GET_OID_COMMITTISH 04 +#define GET_OID_TREE 010 +#define GET_OID_TREEISH 020 +#define GET_OID_BLOB 040 +#define GET_OID_FOLLOW_SYMLINKS 0100 +#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_SKIP_AMBIGUITY_CHECK 040000 #define GET_OID_DISAMBIGUATORS \ (GET_OID_COMMIT | GET_OID_COMMITTISH | \ @@ -325,7 +337,7 @@ int hash_algo_by_name(const char *name); /* Identical, except based on the format ID. */ int hash_algo_by_id(uint32_t format_id); /* Identical, except based on the length. */ -int hash_algo_by_length(int len); +int hash_algo_by_length(size_t len); /* Identical, except for a pointer to struct git_hash_algo. */ static inline int hash_algo_by_ptr(const struct git_hash_algo *p) { @@ -340,7 +352,7 @@ static inline int hash_algo_by_ptr(const struct git_hash_algo *p) const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop); -const struct object_id *null_oid(void); +const struct object_id *null_oid(const struct git_hash_algo *algop); static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2, const struct git_hash_algo *algop) { @@ -205,8 +205,9 @@ void hashmap_clear_(struct hashmap *map, ssize_t entry_offset) return; if (entry_offset >= 0) /* called by hashmap_clear_and_free */ free_individual_entries(map, entry_offset); - free(map->table); - memset(map, 0, sizeof(*map)); + FREE_AND_NULL(map->table); + map->tablesize = 0; + map->private_size = 0; } struct hashmap_entry *hashmap_get(const struct hashmap *map, @@ -9,6 +9,7 @@ #include "run-command.h" #include "levenshtein.h" #include "gettext.h" +#include "hash.h" #include "help.h" #include "command-list.h" #include "string-list.h" @@ -213,7 +214,7 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) else if (cmp == 0) { ei++; free(cmds->names[ci++]); - } else if (cmp > 0) + } else ei++; } @@ -803,6 +804,12 @@ void get_version_info(struct strbuf *buf, int show_build_options) #elif defined ZLIB_VERSION strbuf_addf(buf, "zlib: %s\n", ZLIB_VERSION); #endif + strbuf_addf(buf, "SHA-1: %s\n", SHA1_BACKEND); +#if defined SHA1_UNSAFE_BACKEND + strbuf_addf(buf, "non-collision-detecting-SHA-1: %s\n", + SHA1_UNSAFE_BACKEND); +#endif + strbuf_addf(buf, "SHA-256: %s\n", SHA256_BACKEND); } } diff --git a/http-backend.c b/http-backend.c index 50b2858fad..0c575aa88a 100644 --- a/http-backend.c +++ b/http-backend.c @@ -18,7 +18,7 @@ #include "url.h" #include "strvec.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-store.h" #include "protocol.h" #include "date.h" #include "write-or-die.h" diff --git a/http-push.c b/http-push.c index 1b030d96f4..f5a92529a8 100644 --- a/http-push.c +++ b/http-push.c @@ -19,7 +19,8 @@ #include "tree-walk.h" #include "url.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-file.h" +#include "object-store.h" #include "commit-reach.h" #ifdef EXPAT_NEEDS_XMLPARSE_H @@ -194,7 +195,7 @@ static char *xml_entities(const char *s) static void curl_setup_http_get(CURL *curl, const char *url, const char *custom_req) { - curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_null); @@ -204,7 +205,7 @@ static void curl_setup_http(CURL *curl, const char *url, const char *custom_req, struct buffer *buffer, curl_write_callback write_fn) { - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_INFILE, buffer); curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len); @@ -212,9 +213,9 @@ static void curl_setup_http(CURL *curl, const char *url, curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer); curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn); - curl_easy_setopt(curl, CURLOPT_NOBODY, 0); + curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); } static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options) @@ -1445,7 +1446,9 @@ static void one_remote_ref(const char *refname) * Fetch a copy of the object if it doesn't exist locally - it * may be required for updating server info later. */ - if (repo->can_update_info_refs && !repo_has_object_file(the_repository, &ref->old_oid)) { + if (repo->can_update_info_refs && + !has_object(the_repository, &ref->old_oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { obj = lookup_unknown_object(the_repository, &ref->old_oid); fprintf(stderr, " fetch %s for %s\n", oid_to_hex(&ref->old_oid), refname); @@ -1650,14 +1653,14 @@ static int delete_remote_branch(const char *pattern, int force) return error("Remote HEAD symrefs too deep"); if (is_null_oid(&head_oid)) return error("Unable to resolve remote HEAD"); - if (!repo_has_object_file(the_repository, &head_oid)) + if (!has_object(the_repository, &head_oid, HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", oid_to_hex(&head_oid)); /* Remote branch must resolve to a known object */ if (is_null_oid(&remote_ref->old_oid)) return error("Unable to resolve remote branch %s", remote_ref->name); - if (!repo_has_object_file(the_repository, &remote_ref->old_oid)) + if (!has_object(the_repository, &remote_ref->old_oid, HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, oid_to_hex(&remote_ref->old_oid)); /* Remote branch must be an ancestor of remote HEAD */ @@ -1878,7 +1881,8 @@ int cmd_main(int argc, const char **argv) if (!force_all && !is_null_oid(&ref->old_oid) && !ref->force) { - if (!repo_has_object_file(the_repository, &ref->old_oid) || + if (!has_object(the_repository, &ref->old_oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR) || !ref_newer(&ref->peer_ref->new_oid, &ref->old_oid)) { /* diff --git a/http-walker.c b/http-walker.c index 7918ddc096..463f7b119a 100644 --- a/http-walker.c +++ b/http-walker.c @@ -9,7 +9,8 @@ #include "list.h" #include "transport.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-file.h" +#include "object-store.h" struct alt_base { char *base; @@ -137,7 +138,8 @@ static int fill_active_slot(void *data UNUSED) list_for_each_safe(pos, tmp, head) { obj_req = list_entry(pos, struct object_request, node); if (obj_req->state == WAITING) { - if (repo_has_object_file(the_repository, &obj_req->oid)) + if (has_object(the_repository, &obj_req->oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) obj_req->state = COMPLETE; else { start_object_request(obj_req); @@ -495,7 +497,8 @@ static int fetch_object(struct walker *walker, const struct object_id *oid) if (!obj_req) return error("Couldn't find request for %s in the queue", hex); - if (repo_has_object_file(the_repository, &obj_req->oid)) { + if (has_object(the_repository, &obj_req->oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { if (obj_req->req) abort_http_object_request(&obj_req->req); abort_object_request(obj_req); @@ -540,7 +543,7 @@ static int fetch_object(struct walker *walker, const struct object_id *oid) ret = error("File %s has bad hash", hex); } else if (req->rename < 0) { struct strbuf buf = STRBUF_INIT; - loose_object_path(the_repository, &buf, &req->oid); + odb_loose_path(the_repository->objects->odb, &buf, &req->oid); ret = error("unable to write sha1 filename %s", buf.buf); strbuf_release(&buf); } @@ -19,7 +19,7 @@ #include "packfile.h" #include "string-list.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "tempfile.h" static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); @@ -104,6 +104,10 @@ static struct { }; #endif +static long curl_tcp_keepidle = -1; +static long curl_tcp_keepintvl = -1; +static long curl_tcp_keepcnt = -1; + enum proactive_auth { PROACTIVE_AUTH_NONE = 0, PROACTIVE_AUTH_IF_CREDENTIALS, @@ -438,11 +442,11 @@ static int http_options(const char *var, const char *value, return 0; } if (!strcmp("http.lowspeedlimit", var)) { - curl_low_speed_limit = (long)git_config_int(var, value, ctx->kvi); + curl_low_speed_limit = git_config_int(var, value, ctx->kvi); return 0; } if (!strcmp("http.lowspeedtime", var)) { - curl_low_speed_time = (long)git_config_int(var, value, ctx->kvi); + curl_low_speed_time = git_config_int(var, value, ctx->kvi); return 0; } @@ -557,6 +561,19 @@ static int http_options(const char *var, const char *value, return 0; } + if (!strcmp("http.keepaliveidle", var)) { + curl_tcp_keepidle = git_config_int(var, value, ctx->kvi); + return 0; + } + if (!strcmp("http.keepaliveinterval", var)) { + curl_tcp_keepintvl = git_config_int(var, value, ctx->kvi); + return 0; + } + if (!strcmp("http.keepalivecount", var)) { + curl_tcp_keepcnt = git_config_int(var, value, ctx->kvi); + return 0; + } + /* Fall back on the default ones */ return git_default_config(var, value, ctx, data); } @@ -704,11 +721,6 @@ static int has_proxy_cert_password(void) return 1; } -static void set_curl_keepalive(CURL *c) -{ - curl_easy_setopt(c, CURLOPT_TCP_KEEPALIVE, 1); -} - /* Return 1 if redactions have been made, 0 otherwise. */ static int redact_sensitive_header(struct strbuf *header, size_t offset) { @@ -1007,13 +1019,13 @@ static CURL *get_curl_handle(void) die("curl_easy_init failed"); if (!curl_ssl_verify) { - curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0L); } else { /* Verify authenticity of the peer's certificate */ - curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1L); /* The name in the cert must match whom we tried to connect */ - curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2L); } if (curl_http_version) { @@ -1045,7 +1057,7 @@ static CURL *get_curl_handle(void) if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) && !http_schannel_check_revoke) { - curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NO_REVOKE); } if (http_proactive_auth != PROACTIVE_AUTH_NONE) @@ -1105,8 +1117,8 @@ static CURL *get_curl_handle(void) curl_low_speed_time); } - curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20); - curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); + curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20L); + curl_easy_setopt(result, CURLOPT_POSTREDIR, (long)CURL_REDIR_POST_ALL); #ifdef GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR { @@ -1139,7 +1151,7 @@ static CURL *get_curl_handle(void) user_agent ? user_agent : git_user_agent()); if (curl_ftp_no_epsv) - curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0); + curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0L); if (curl_ssl_try) curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY); @@ -1181,18 +1193,18 @@ static CURL *get_curl_handle(void) if (starts_with(curl_http_proxy, "socks5h")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5_HOSTNAME); else if (starts_with(curl_http_proxy, "socks5")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5); else if (starts_with(curl_http_proxy, "socks4a")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4A); else if (starts_with(curl_http_proxy, "socks")) curl_easy_setopt(result, - CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); + CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4); else if (starts_with(curl_http_proxy, "https")) { - curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); + curl_easy_setopt(result, CURLOPT_PROXYTYPE, (long)CURLPROXY_HTTPS); if (http_proxy_ssl_cert) curl_easy_setopt(result, CURLOPT_PROXY_SSLCERT, http_proxy_ssl_cert); @@ -1242,7 +1254,18 @@ static CURL *get_curl_handle(void) } init_curl_proxy_auth(result); - set_curl_keepalive(result); + curl_easy_setopt(result, CURLOPT_TCP_KEEPALIVE, 1L); + + if (curl_tcp_keepidle > -1) + curl_easy_setopt(result, CURLOPT_TCP_KEEPIDLE, + curl_tcp_keepidle); + if (curl_tcp_keepintvl > -1) + curl_easy_setopt(result, CURLOPT_TCP_KEEPINTVL, + curl_tcp_keepintvl); +#ifdef GIT_CURL_HAVE_CURLOPT_TCP_KEEPCNT + if (curl_tcp_keepcnt > -1) + curl_easy_setopt(result, CURLOPT_TCP_KEEPCNT, curl_tcp_keepcnt); +#endif return result; } @@ -1256,10 +1279,30 @@ static void set_from_env(char **var, const char *envname) } } +static void set_long_from_env(long *var, const char *envname) +{ + const char *val = getenv(envname); + if (val) { + long tmp; + char *endp; + int saved_errno = errno; + + errno = 0; + tmp = strtol(val, &endp, 10); + + if (errno) + warning_errno(_("failed to parse %s"), envname); + else if (*endp || endp == val) + warning(_("failed to parse %s"), envname); + else + *var = tmp; + + errno = saved_errno; + } +} + void http_init(struct remote *remote, const char *url, int proactive_auth) { - char *low_speed_limit; - char *low_speed_time; char *normalized_url; struct urlmatch_config config = URLMATCH_CONFIG_INIT; @@ -1338,12 +1381,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) set_from_env(&user_agent, "GIT_HTTP_USER_AGENT"); - low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT"); - if (low_speed_limit) - curl_low_speed_limit = strtol(low_speed_limit, NULL, 10); - low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME"); - if (low_speed_time) - curl_low_speed_time = strtol(low_speed_time, NULL, 10); + set_long_from_env(&curl_low_speed_limit, "GIT_HTTP_LOW_SPEED_LIMIT"); + set_long_from_env(&curl_low_speed_time, "GIT_HTTP_LOW_SPEED_TIME"); if (curl_ssl_verify == -1) curl_ssl_verify = 1; @@ -1370,6 +1409,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) ssl_cert_password_required = 1; } + set_long_from_env(&curl_tcp_keepidle, "GIT_TCP_KEEPIDLE"); + set_long_from_env(&curl_tcp_keepintvl, "GIT_TCP_KEEPINTVL"); + set_long_from_env(&curl_tcp_keepcnt, "GIT_TCP_KEEPCNT"); + curl_default = get_curl_handle(); } @@ -1497,9 +1540,9 @@ struct active_request_slot *get_active_slot(void) 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); + curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0L); + curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1L); curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL); /* @@ -1508,9 +1551,9 @@ struct active_request_slot *get_active_slot(void) * HTTP_FOLLOW_* cases themselves. */ if (http_follow_config == HTTP_FOLLOW_ALWAYS) - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L); else - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0L); curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve); curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods); @@ -2077,12 +2120,12 @@ static int http_request(const char *url, int ret; slot = get_active_slot(); - curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1L); if (!result) { - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1L); } else { - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, result); if (target == HTTP_REQUEST_FILE) { @@ -2108,7 +2151,7 @@ static int http_request(const char *url, strbuf_addstr(&buf, " no-cache"); if (options && options->initial_request && http_follow_config == HTTP_FOLLOW_INITIAL) - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L); headers = curl_slist_append(headers, buf.buf); @@ -2127,7 +2170,7 @@ static int http_request(const char *url, curl_easy_setopt(slot->curl, CURLOPT_URL, url); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(slot->curl, CURLOPT_ENCODING, ""); - curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0L); ret = run_one_slot(slot, &results); @@ -2619,7 +2662,7 @@ struct http_object_request *new_http_object_request(const char *base_url, oidcpy(&freq->oid, oid); freq->localfile = -1; - loose_object_path(the_repository, &filename, oid); + odb_loose_path(the_repository->objects->odb, &filename, oid); strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf); strbuf_addf(&prevfile, "%s.prev", filename.buf); @@ -2707,7 +2750,7 @@ struct http_object_request *new_http_object_request(const char *base_url, freq->headers = object_request_headers(); curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEDATA, freq); - curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0); + curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0L); curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file); curl_easy_setopt(freq->slot->curl, CURLOPT_ERRORBUFFER, freq->errorstr); curl_easy_setopt(freq->slot->curl, CURLOPT_URL, freq->url); @@ -2771,7 +2814,7 @@ int finish_http_object_request(struct http_object_request *freq) unlink_or_warn(freq->tmpfile.buf); return -1; } - loose_object_path(the_repository, &filename, &freq->oid); + odb_loose_path(the_repository->objects->odb, &filename, &freq->oid); freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf); strbuf_release(&filename); @@ -412,6 +412,10 @@ void apply_mailmap_to_header(struct strbuf *buf, const char **header, found_header = 1; buf_offset += endp - line; buf_offset += rewrite_ident_line(person, endp - person, buf, mailmap); + /* Recompute endp after potential buffer reallocation */ + endp = buf->buf + buf_offset; + if (*endp == '\n') + buf_offset++; break; } diff --git a/imap-send.c b/imap-send.c index 6c8f84e836..2e812f5a6e 100644 --- a/imap-send.c +++ b/imap-send.c @@ -324,6 +324,8 @@ static int ssl_socket_connect(struct imap_socket *sock, cert = SSL_get_peer_certificate(sock->ssl); if (!cert) return error("unable to get peer certificate."); + if (SSL_get_verify_result(sock->ssl) != X509_V_OK) + return error("unable to verify peer certificate"); if (verify_hostname(cert, cfg->host) < 0) return -1; } @@ -1418,7 +1420,7 @@ static CURL *setup_curl(struct imap_server_conf *srvc, struct credential *cred) curl_easy_setopt(curl, CURLOPT_URL, path.buf); strbuf_release(&path); - curl_easy_setopt(curl, CURLOPT_PORT, srvc->port); + curl_easy_setopt(curl, CURLOPT_PORT, (long)srvc->port); if (srvc->auth_method) { struct strbuf auth = STRBUF_INIT; @@ -1431,8 +1433,8 @@ static CURL *setup_curl(struct imap_server_conf *srvc, struct credential *cred) if (!srvc->use_ssl) curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, srvc->ssl_verify); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, srvc->ssl_verify); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long)srvc->ssl_verify); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (long)srvc->ssl_verify); curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer); diff --git a/iterator.h b/iterator.h index 0f6900e43a..6b77dcc262 100644 --- a/iterator.h +++ b/iterator.h @@ -12,7 +12,7 @@ #define ITER_OK 0 /* - * The iterator is exhausted and has been freed. + * The iterator is exhausted. */ #define ITER_DONE -1 diff --git a/json-writer.c b/json-writer.c index 8c5187e9fd..34577dc25f 100644 --- a/json-writer.c +++ b/json-writer.c @@ -268,10 +268,6 @@ static void append_sub_jw(struct json_writer *jw, strbuf_addbuf(&jw->json, &value->json); } -/* - * Append existing (properly terminated) JSON sub-data (object or array) - * as-is onto the given JSON data. - */ void jw_object_sub_jw(struct json_writer *jw, const char *key, const struct json_writer *value) { diff --git a/json-writer.h b/json-writer.h index 04413bd1af..8f845d4d29 100644 --- a/json-writer.h +++ b/json-writer.h @@ -28,6 +28,34 @@ * object/array) -or- by building them inline in one pass. This is a * personal style and/or data shape choice. * + * USAGE: + * ====== + * + * - Initialize the json_writer with jw_init. + * + * - Open an object as the main data structure with jw_object_begin. + * Append a key-value pair to it using the jw_object_<type> functions. + * Conclude with jw_end. + * + * - Alternatively, open an array as the main data structure with + * jw_array_begin. Append a value to it using the jw_array_<type> + * functions. Conclude with jw_end. + * + * - Append a new, unterminated array or object to the current + * object using the jw_object_inline_begin_{array, object} functions. + * Similarly, append a new, unterminated array or object to + * the current array using the jw_array_inline_begin_{array, object} + * functions. + * + * - Append other json_writer as a value to the current array or object + * using the jw_{array, object}_sub_jw functions. + * + * - Extend the current array with an null-terminated array of strings + * by using jw_array_argv or with a fixed number of elements of a + * array of string by using jw_array_argc_argv. + * + * - Release the json_writer after using it by calling jw_release. + * * See t/helper/test-json-writer.c for various usage examples. * * LIMITATIONS: @@ -69,42 +97,185 @@ struct json_writer .open_stack = STRBUF_INIT, \ } +/* + * Initialize a json_writer with empty values. + */ void jw_init(struct json_writer *jw); + +/* + * Release the internal buffers of a json_writer. + */ void jw_release(struct json_writer *jw); +/* + * Begin the json_writer using an object as the top-level data structure. If + * pretty is set to 1, the result will be a human-readable and indented JSON, + * and if it is set to 0 the result will be minified single-line JSON. + */ void jw_object_begin(struct json_writer *jw, int pretty); + +/* + * Begin the json_writer using an array as the top-level data structure. If + * pretty is set to 1, the result will be a human-readable and indented JSON, + * and if it is set to 0 the result will be minified single-line JSON. + */ void jw_array_begin(struct json_writer *jw, int pretty); +/* + * Append a string field to the current object of the json_writer, given its key + * and its value. Trigger a BUG when not in an object. + */ void jw_object_string(struct json_writer *jw, const char *key, const char *value); + +/* + * Append an int field to the current object of the json_writer, given its key + * and its value. Trigger a BUG when not in an object. + */ void jw_object_intmax(struct json_writer *jw, const char *key, intmax_t value); + +/* + * Append a double field to the current object of the json_writer, given its key + * and its value. The precision parameter defines the number of significant + * digits, where -1 can be used for maximum precision. Trigger a BUG when not in + * an object. + */ void jw_object_double(struct json_writer *jw, const char *key, int precision, double value); + +/* + * Append a boolean field set to true to the current object of the json_writer, + * given its key. Trigger a BUG when not in an object. + */ void jw_object_true(struct json_writer *jw, const char *key); + +/* + * Append a boolean field set to false to the current object of the json_writer, + * given its key. Trigger a BUG when not in an object. + */ void jw_object_false(struct json_writer *jw, const char *key); + +/* + * Append a boolean field to the current object of the json_writer, given its + * key and its value. Trigger a BUG when not in an object. + */ void jw_object_bool(struct json_writer *jw, const char *key, int value); + +/* + * Append a null field to the current object of the json_writer, given its key. + * Trigger a BUG when not in an object. + */ void jw_object_null(struct json_writer *jw, const char *key); + +/* + * Append a field to the current object of the json_writer, given its key and + * another json_writer that represents its content. Trigger a BUG when not in + * an object. + */ void jw_object_sub_jw(struct json_writer *jw, const char *key, const struct json_writer *value); +/* + * Start an object as the value of a field in the current object of the + * json_writer. Trigger a BUG when not in an object. + */ void jw_object_inline_begin_object(struct json_writer *jw, const char *key); + +/* + * Start an array as the value of a field in the current object of the + * json_writer. Trigger a BUG when not in an object. + */ void jw_object_inline_begin_array(struct json_writer *jw, const char *key); +/* + * Append a string value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_string(struct json_writer *jw, const char *value); + +/* + * Append an int value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_intmax(struct json_writer *jw, intmax_t value); + +/* + * Append a double value to the current array of the json_writer. The precision + * parameter defines the number of significant digits, where -1 can be used for + * maximum precision. Trigger a BUG when not in an array. + */ void jw_array_double(struct json_writer *jw, int precision, double value); + +/* + * Append a true value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_true(struct json_writer *jw); + +/* + * Append a false value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_false(struct json_writer *jw); + +/* + * Append a boolean value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_bool(struct json_writer *jw, int value); + +/* + * Append a null value to the current array of the json_writer. Trigger a BUG + * when not in an array. + */ void jw_array_null(struct json_writer *jw); + +/* + * Append a json_writer as a value to the current array of the + * json_writer. Trigger a BUG when not in an array. + */ void jw_array_sub_jw(struct json_writer *jw, const struct json_writer *value); + +/* + * Append the first argc values from the argv array of strings to the current + * array of the json_writer. Trigger a BUG when not in an array. + * + * This function does not provide safety for cases where the array has less than + * argc values. + */ void jw_array_argc_argv(struct json_writer *jw, int argc, const char **argv); + +/* + * Append a null-terminated array of strings to the current array of the + * json_writer. Trigger a BUG when not in an array. + */ void jw_array_argv(struct json_writer *jw, const char **argv); +/* + * Start an object as a value in the current array of the json_writer. Trigger a + * BUG when not in an array. + */ void jw_array_inline_begin_object(struct json_writer *jw); + +/* + * Start an array as a value in the current array. Trigger a BUG when not in an + * array. + */ void jw_array_inline_begin_array(struct json_writer *jw); +/* + * Return whether the json_writer is terminated. In other words, if the all the + * objects and arrays are already closed. + */ int jw_is_terminated(const struct json_writer *jw); + +/* + * Terminates the current object or array of the json_writer. In other words, + * append a ] if the current array is not closed or } if the current object + * is not closed. + * + * Abort the execution if there's no object or array that can be terminated. + */ void jw_end(struct json_writer *jw); #endif /* JSON_WRITER_H */ @@ -197,10 +197,13 @@ kwsincr (kwset_t kws, char const *text, size_t len) while (link && label != link->label) { links[depth] = link; - if (label < link->label) - dirs[depth++] = L, link = link->llink; - else - dirs[depth++] = R, link = link->rlink; + if (label < link->label) { + dirs[depth++] = L; + link = link->llink; + } else { + dirs[depth++] = R; + link = link->rlink; + } } /* The current character doesn't have an outgoing link at @@ -257,14 +260,14 @@ kwsincr (kwset_t kws, char const *text, size_t len) switch (dirs[depth + 1]) { case L: - r = links[depth], t = r->llink, rl = t->rlink; - t->rlink = r, r->llink = rl; + r = links[depth]; t = r->llink; rl = t->rlink; + t->rlink = r; r->llink = rl; t->balance = r->balance = 0; break; case R: - r = links[depth], l = r->llink, t = l->rlink; - rl = t->rlink, lr = t->llink; - t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl; + r = links[depth]; l = r->llink; t = l->rlink; + rl = t->rlink; lr = t->llink; + t->llink = l; l->rlink = lr; t->rlink = r; r->llink = rl; l->balance = t->balance != 1 ? 0 : -1; r->balance = t->balance != (char) -1 ? 0 : 1; t->balance = 0; @@ -277,14 +280,14 @@ kwsincr (kwset_t kws, char const *text, size_t len) switch (dirs[depth + 1]) { case R: - l = links[depth], t = l->rlink, lr = t->llink; - t->llink = l, l->rlink = lr; + l = links[depth]; t = l->rlink; lr = t->llink; + t->llink = l; l->rlink = lr; t->balance = l->balance = 0; break; case L: - l = links[depth], r = l->rlink, t = r->llink; - lr = t->llink, rl = t->rlink; - t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl; + l = links[depth]; r = l->rlink; t = r->llink; + lr = t->llink; rl = t->rlink; + t->llink = l; l->rlink = lr; t->rlink = r; r->llink = rl; l->balance = t->balance != 1 ? 0 : -1; r->balance = t->balance != (char) -1 ? 0 : 1; t->balance = 0; @@ -567,22 +570,22 @@ bmexec (kwset_t kws, char const *text, size_t size) { while (tp <= ep) { - d = d1[U(tp[-1])], tp += d; - d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])]; tp += d; + d = d1[U(tp[-1])]; tp += d; if (d == 0) goto found; - d = d1[U(tp[-1])], tp += d; - d = d1[U(tp[-1])], tp += d; - d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])]; tp += d; + d = d1[U(tp[-1])]; tp += d; + d = d1[U(tp[-1])]; tp += d; if (d == 0) goto found; - d = d1[U(tp[-1])], tp += d; - d = d1[U(tp[-1])], tp += d; - d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])]; tp += d; + d = d1[U(tp[-1])]; tp += d; + d = d1[U(tp[-1])]; tp += d; if (d == 0) goto found; - d = d1[U(tp[-1])], tp += d; - d = d1[U(tp[-1])], tp += d; + d = d1[U(tp[-1])]; tp += d; + d = d1[U(tp[-1])]; tp += d; } break; found: @@ -649,7 +652,8 @@ cwexec (kwset_t kws, char const *text, size_t len, struct kwsmatch *kwsmatch) mch = NULL; else { - mch = text, accept = kwset->trie; + mch = text; + accept = kwset->trie; goto match; } diff --git a/list-objects-filter.c b/list-objects-filter.c index dc598a081b..78b397bc19 100644 --- a/list-objects-filter.c +++ b/list-objects-filter.c @@ -12,7 +12,7 @@ #include "oidmap.h" #include "oidset.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" /* Remember to update object flag allocation in object.h */ /* @@ -244,7 +244,7 @@ static void filter_trees_free(void *filter_data) { struct filter_trees_depth_data *d = filter_data; if (!d) return; - oidmap_free(&d->seen_at_depth, 1); + oidmap_clear(&d->seen_at_depth, 1); free(d); } diff --git a/list-objects.c b/list-objects.c index 943e62e868..597114281f 100644 --- a/list-objects.c +++ b/list-objects.c @@ -14,7 +14,7 @@ #include "list-objects-filter.h" #include "list-objects-filter-options.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-store.h" #include "trace.h" #include "environment.h" @@ -74,7 +74,8 @@ static void process_blob(struct traversal_context *ctx, * of missing objects. */ if (ctx->revs->exclude_promisor_objects && - !repo_has_object_file(the_repository, &obj->oid) && + !has_object(the_repository, &obj->oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR) && is_promisor_object(ctx->revs->repo, &obj->oid)) return; diff --git a/log-tree.c b/log-tree.c index 8b184d6776..1d05dc1c70 100644 --- a/log-tree.c +++ b/log-tree.c @@ -9,7 +9,7 @@ #include "environment.h" #include "hex.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-file.h" #include "repository.h" #include "tmp-objdir.h" #include "commit.h" @@ -499,7 +499,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, { struct strbuf headers = STRBUF_INIT; const char *name = oid_to_hex(opt->zero_commit ? - null_oid() : &commit->object.oid); + null_oid(the_hash_algo) : &commit->object.oid); *need_8bit_cte_p = 0; /* unknown */ diff --git a/mailinfo.c b/mailinfo.c index 7b001fa5db..ee4597da6b 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -381,12 +381,12 @@ static int is_format_patch_separator(const char *line, int len) return !memcmp(SAMPLE + (cp - line), cp, strlen(SAMPLE) - (cp - line)); } -static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047) +static int decode_q_segment(struct strbuf *out, const struct strbuf *q_seg, + int rfc2047) { const char *in = q_seg->buf; int c; - struct strbuf *out = xmalloc(sizeof(struct strbuf)); - strbuf_init(out, q_seg->len); + strbuf_grow(out, q_seg->len); while ((c = *in++) != 0) { if (c == '=') { @@ -405,16 +405,15 @@ static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047) c = 0x20; strbuf_addch(out, c); } - return out; + return 0; } -static struct strbuf *decode_b_segment(const struct strbuf *b_seg) +static int decode_b_segment(struct strbuf *out, const struct strbuf *b_seg) { /* Decode in..ep, possibly in-place to ot */ int c, pos = 0, acc = 0; const char *in = b_seg->buf; - struct strbuf *out = xmalloc(sizeof(struct strbuf)); - strbuf_init(out, b_seg->len); + strbuf_grow(out, b_seg->len); while ((c = *in++) != 0) { if (c == '+') @@ -447,7 +446,7 @@ static struct strbuf *decode_b_segment(const struct strbuf *b_seg) break; } } - return out; + return 0; } static int convert_to_utf8(struct mailinfo *mi, @@ -475,7 +474,7 @@ static int convert_to_utf8(struct mailinfo *mi, static void decode_header(struct mailinfo *mi, struct strbuf *it) { char *in, *ep, *cp; - struct strbuf outbuf = STRBUF_INIT, *dec; + struct strbuf outbuf = STRBUF_INIT, dec = STRBUF_INIT; struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT; int found_error = 1; /* pessimism */ @@ -530,18 +529,19 @@ static void decode_header(struct mailinfo *mi, struct strbuf *it) default: goto release_return; case 'b': - dec = decode_b_segment(&piecebuf); + if ((found_error = decode_b_segment(&dec, &piecebuf))) + goto release_return; break; case 'q': - dec = decode_q_segment(&piecebuf, 1); + if ((found_error = decode_q_segment(&dec, &piecebuf, 1))) + goto release_return; break; } - if (convert_to_utf8(mi, dec, charset_q.buf)) + if (convert_to_utf8(mi, &dec, charset_q.buf)) goto release_return; - strbuf_addbuf(&outbuf, dec); - strbuf_release(dec); - free(dec); + strbuf_addbuf(&outbuf, &dec); + strbuf_release(&dec); in = ep + 2; } strbuf_addstr(&outbuf, in); @@ -552,6 +552,7 @@ release_return: strbuf_release(&outbuf); strbuf_release(&charset_q); strbuf_release(&piecebuf); + strbuf_release(&dec); if (found_error) mi->input_error = -1; @@ -634,23 +635,22 @@ static int is_inbody_header(const struct mailinfo *mi, static void decode_transfer_encoding(struct mailinfo *mi, struct strbuf *line) { - struct strbuf *ret; + struct strbuf ret = STRBUF_INIT; switch (mi->transfer_encoding) { case TE_QP: - ret = decode_q_segment(line, 0); + decode_q_segment(&ret, line, 0); break; case TE_BASE64: - ret = decode_b_segment(line); + decode_b_segment(&ret, line); break; case TE_DONTCARE: default: return; } strbuf_reset(line); - strbuf_addbuf(line, ret); - strbuf_release(ret); - free(ret); + strbuf_addbuf(line, &ret); + strbuf_release(&ret); } static inline int patchbreak(const struct strbuf *line) @@ -6,7 +6,7 @@ #include "string-list.h" #include "mailmap.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "setup.h" char *git_mailmap_file; diff --git a/match-trees.c b/match-trees.c index ef14ceb594..72922d5d64 100644 --- a/match-trees.c +++ b/match-trees.c @@ -6,7 +6,8 @@ #include "strbuf.h" #include "tree.h" #include "tree-walk.h" -#include "object-store-ll.h" +#include "object-file.h" +#include "object-store.h" #include "repository.h" static int score_missing(unsigned mode) diff --git a/merge-blobs.c b/merge-blobs.c index 0ad0390fea..53f36dbc17 100644 --- a/merge-blobs.c +++ b/merge-blobs.c @@ -4,7 +4,7 @@ #include "merge-ll.h" #include "blob.h" #include "merge-blobs.h" -#include "object-store-ll.h" +#include "object-store.h" static int fill_mmfile_blob(mmfile_t *f, struct blob *obj) { diff --git a/merge-ort-wrappers.c b/merge-ort-wrappers.c index d6f6135996..c54d56b344 100644 --- a/merge-ort-wrappers.c +++ b/merge-ort-wrappers.c @@ -1,9 +1,13 @@ #include "git-compat-util.h" #include "gettext.h" #include "hash.h" +#include "hex.h" +#include "lockfile.h" #include "merge-ort.h" #include "merge-ort-wrappers.h" #include "read-cache-ll.h" +#include "repository.h" +#include "tag.h" #include "tree.h" #include "commit.h" @@ -29,6 +33,7 @@ int merge_ort_nonrecursive(struct merge_options *opt, struct tree *merge_base) { struct merge_result result; + int show_msgs; if (unclean(opt, head)) return -1; @@ -38,9 +43,10 @@ int merge_ort_nonrecursive(struct merge_options *opt, return 1; } + show_msgs = !!opt->verbosity; memset(&result, 0, sizeof(result)); merge_incore_nonrecursive(opt, merge_base, head, merge, &result); - merge_switch_to_result(opt, head, &result, 1, 1); + merge_switch_to_result(opt, head, &result, 1, show_msgs); return result.clean; } @@ -53,14 +59,76 @@ int merge_ort_recursive(struct merge_options *opt, { struct tree *head = repo_get_commit_tree(opt->repo, side1); struct merge_result tmp; + int show_msgs; if (unclean(opt, head)) return -1; + show_msgs = !!opt->verbosity; memset(&tmp, 0, sizeof(tmp)); merge_incore_recursive(opt, merge_bases, side1, side2, &tmp); - merge_switch_to_result(opt, head, &tmp, 1, 1); + merge_switch_to_result(opt, head, &tmp, 1, show_msgs); *result = NULL; return tmp.clean; } + +static struct commit *get_ref(struct repository *repo, + const struct object_id *oid, + const char *name) +{ + struct object *object; + + object = deref_tag(repo, parse_object(repo, oid), + name, strlen(name)); + if (!object) + return NULL; + if (object->type == OBJ_TREE) + return make_virtual_commit(repo, (struct tree*)object, name); + if (object->type != OBJ_COMMIT) + return NULL; + if (repo_parse_commit(repo, (struct commit *)object)) + return NULL; + return (struct commit *)object; +} + +int merge_ort_generic(struct merge_options *opt, + const struct object_id *head, + const struct object_id *merge, + int num_merge_bases, + const struct object_id *merge_bases, + struct commit **result) +{ + int clean; + struct lock_file lock = LOCK_INIT; + struct commit *head_commit = get_ref(opt->repo, head, opt->branch1); + struct commit *next_commit = get_ref(opt->repo, merge, opt->branch2); + struct commit_list *ca = NULL; + + if (merge_bases) { + int i; + for (i = 0; i < num_merge_bases; ++i) { + struct commit *base; + if (!(base = get_ref(opt->repo, &merge_bases[i], + oid_to_hex(&merge_bases[i])))) + return error(_("Could not parse object '%s'"), + oid_to_hex(&merge_bases[i])); + commit_list_insert(base, &ca); + } + } + + repo_hold_locked_index(opt->repo, &lock, LOCK_DIE_ON_ERROR); + clean = merge_ort_recursive(opt, head_commit, next_commit, ca, + result); + free_commit_list(ca); + if (clean < 0) { + rollback_lock_file(&lock); + return clean; + } + + if (write_locked_index(opt->repo->index, &lock, + COMMIT_LOCK | SKIP_IF_UNCHANGED)) + return error(_("Unable to write index.")); + + return clean ? 0 : 1; +} diff --git a/merge-ort-wrappers.h b/merge-ort-wrappers.h index 90af1f69c5..b7e1ced9d7 100644 --- a/merge-ort-wrappers.h +++ b/merge-ort-wrappers.h @@ -1,7 +1,7 @@ #ifndef MERGE_ORT_WRAPPERS_H #define MERGE_ORT_WRAPPERS_H -#include "merge-recursive.h" +#include "merge-ort.h" /* * rename-detecting three-way merge, no recursion. @@ -22,4 +22,16 @@ int merge_ort_recursive(struct merge_options *opt, const struct commit_list *ancestors, struct commit **result); +/* + * rename-detecting three-way merge. num_merge_bases must be at least 1. + * Recursive ancestor consolidation will be performed if num_merge_bases > 1. + * Wrapper mimicking the old merge_recursive_generic() function. + */ +int merge_ort_generic(struct merge_options *opt, + const struct object_id *head, + const struct object_id *merge, + int num_merge_bases, + const struct object_id *merge_bases, + struct commit **result); + #endif diff --git a/merge-ort.c b/merge-ort.c index 46e78c3ffa..47b3d1730e 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -26,6 +26,7 @@ #include "cache-tree.h" #include "commit.h" #include "commit-reach.h" +#include "config.h" #include "diff.h" #include "diffcore.h" #include "dir.h" @@ -36,8 +37,9 @@ #include "merge-ll.h" #include "match-trees.h" #include "mem-pool.h" +#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oid-array.h" #include "path.h" #include "promisor-remote.h" @@ -791,7 +793,7 @@ static void path_msg(struct merge_options *opt, struct strbuf tmp = STRBUF_INIT; /* Sanity checks */ - assert(omittable_hint == + ASSERT(omittable_hint == (!starts_with(type_short_descriptions[type], "CONFLICT") && !starts_with(type_short_descriptions[type], "ERROR")) || type == CONFLICT_DIR_RENAME_SUGGESTED); @@ -1517,8 +1519,8 @@ static int handle_deferred_entries(struct merge_options *opt, struct strintmap copy; /* Loop over the set of paths we need to know rename info for */ - strset_for_each_entry(&renames->relevant_sources[side], - &iter, entry) { + strintmap_for_each_entry(&renames->relevant_sources[side], + &iter, entry) { char *rename_target, *dir, *dir_marker; struct strmap_entry *e; @@ -1642,7 +1644,7 @@ static int handle_deferred_entries(struct merge_options *opt, ci = strmap_get(&opt->priv->paths, path); VERIFY_CI(ci); - assert(renames->deferred[side].trivial_merges_okay && + ASSERT(renames->deferred[side].trivial_merges_okay && !strset_contains(&renames->deferred[side].target_dirs, path)); resolve_trivial_directory_merge(ci, side); @@ -1817,7 +1819,7 @@ static int merge_submodule(struct merge_options *opt, BUG("submodule deleted on one side; this should be handled outside of merge_submodule()"); if ((sub_not_initialized = repo_submodule_init(&subrepo, - opt->repo, path, null_oid()))) { + opt->repo, path, null_oid(the_hash_algo)))) { path_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0, path, NULL, NULL, NULL, _("Failed to merge submodule %s (not checked out)"), @@ -2125,6 +2127,7 @@ static int handle_content_merge(struct merge_options *opt, const struct version_info *b, const char *pathnames[3], const int extra_marker_size, + const int record_object, struct version_info *result) { /* @@ -2199,7 +2202,7 @@ static int handle_content_merge(struct merge_options *opt, two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode)); merge_status = merge_3way(opt, path, - two_way ? null_oid() : &o->oid, + two_way ? null_oid(the_hash_algo) : &o->oid, &a->oid, &b->oid, pathnames, extra_marker_size, &result_buf); @@ -2212,7 +2215,7 @@ static int handle_content_merge(struct merge_options *opt, ret = -1; } - if (!ret && + if (!ret && record_object && write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &result->oid)) { path_msg(opt, ERROR_OBJECT_WRITE_FAILED, 0, @@ -2231,7 +2234,7 @@ static int handle_content_merge(struct merge_options *opt, } else if (S_ISGITLINK(a->mode)) { int two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode)); clean = merge_submodule(opt, pathnames[0], - two_way ? null_oid() : &o->oid, + two_way ? null_oid(the_hash_algo) : &o->oid, &a->oid, &b->oid, &result->oid); if (clean < 0) return -1; @@ -2739,7 +2742,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt, assert(!new_ci->match_mask); new_ci->dirmask = 0; new_ci->stages[1].mode = 0; - oidcpy(&new_ci->stages[1].oid, null_oid()); + oidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo)); /* * Now that we have the file information in new_ci, make sure @@ -2752,7 +2755,7 @@ static void apply_directory_rename_modifications(struct merge_options *opt, continue; /* zero out any entries related to files */ ci->stages[i].mode = 0; - oidcpy(&ci->stages[i].oid, null_oid()); + oidcpy(&ci->stages[i].oid, null_oid(the_hash_algo)); } /* Now we want to focus on new_ci, so reassign ci to it. */ @@ -2895,6 +2898,7 @@ static int process_renames(struct merge_options *opt, struct version_info merged; struct conflict_info *base, *side1, *side2; unsigned was_binary_blob = 0; + const int record_object = true; pathnames[0] = oldpath; pathnames[1] = newpath; @@ -2945,6 +2949,7 @@ static int process_renames(struct merge_options *opt, &side2->stages[2], pathnames, 1 + 2 * opt->priv->call_depth, + record_object, &merged); if (clean_merge < 0) return -1; @@ -3048,7 +3053,8 @@ static int process_renames(struct merge_options *opt, } } - assert(source_deleted || oldinfo->filemask & old_sidemask); + assert(source_deleted || oldinfo->filemask & old_sidemask || + !strcmp(pair->one->path, pair->two->path)); /* Need to check for special types of rename conflicts... */ if (collision && !source_deleted) { @@ -3058,6 +3064,7 @@ static int process_renames(struct merge_options *opt, struct conflict_info *base, *side1, *side2; int clean; + const int record_object = true; pathnames[0] = oldpath; pathnames[other_source_index] = oldpath; @@ -3077,6 +3084,7 @@ static int process_renames(struct merge_options *opt, &side2->stages[2], pathnames, 1 + 2 * opt->priv->call_depth, + record_object, &merged); if (clean < 0) return -1; @@ -3122,7 +3130,7 @@ static int process_renames(struct merge_options *opt, if (type_changed) { /* rename vs. typechange */ /* Mark the original as resolved by removal */ - memcpy(&oldinfo->stages[0].oid, null_oid(), + memcpy(&oldinfo->stages[0].oid, null_oid(the_hash_algo), sizeof(oldinfo->stages[0].oid)); oldinfo->stages[0].mode = 0; oldinfo->filemask &= 0x06; @@ -3404,6 +3412,11 @@ static int collect_renames(struct merge_options *opt, pool_diff_free_filepair(&opt->priv->pool, p); continue; } + if (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_NONE && + p->status == 'R' && 1) { + possibly_cache_new_pair(renames, p, side_index, NULL); + goto skip_directory_renames; + } new_path = check_for_directory_rename(opt, p->two->path, side_index, @@ -3421,11 +3434,12 @@ static int collect_renames(struct merge_options *opt, if (new_path) apply_directory_rename_modifications(opt, p, new_path); +skip_directory_renames: /* * p->score comes back from diffcore_rename_extended() with - * the similarity of the renamed file. The similarity is - * was used to determine that the two files were related - * and are a rename, which we have already used, but beyond + * the similarity of the renamed file. The similarity was + * used to determine that the two files were related and + * are a rename, which we have already used, but beyond * that we have no use for the similarity. So p->score is * now irrelevant. However, process_renames() will need to * know which side of the merge this rename was associated @@ -3448,6 +3462,11 @@ static int detect_and_process_renames(struct merge_options *opt) if (!possible_renames(renames)) goto cleanup; + if (!opt->detect_renames) { + renames->redo_after_renames = 0; + renames->cached_pairs_valid_side = 0; + goto cleanup; + } trace2_region_enter("merge", "regular renames", opt->repo); detection_run |= detect_regular_renames(opt, MERGE_SIDE1); @@ -3917,9 +3936,12 @@ static int write_completed_directory(struct merge_options *opt, * Write out the tree to the git object directory, and also * record the mode and oid in dir_info->result. */ + int record_tree = (!opt->mergeability_only || + opt->priv->call_depth); dir_info->is_null = 0; dir_info->result.mode = S_IFDIR; - if (write_tree(&dir_info->result.oid, &info->versions, offset, + if (record_tree && + write_tree(&dir_info->result.oid, &info->versions, offset, opt->repo->hash_algo->rawsz) < 0) ret = -1; } @@ -3994,7 +4016,7 @@ static int process_entry(struct merge_options *opt, if (ci->filemask & (1 << i)) continue; ci->stages[i].mode = 0; - oidcpy(&ci->stages[i].oid, null_oid()); + oidcpy(&ci->stages[i].oid, null_oid(the_hash_algo)); } } else if (ci->df_conflict && ci->merged.result.mode != 0) { /* @@ -4041,7 +4063,7 @@ static int process_entry(struct merge_options *opt, continue; /* zero out any entries related to directories */ new_ci->stages[i].mode = 0; - oidcpy(&new_ci->stages[i].oid, null_oid()); + oidcpy(&new_ci->stages[i].oid, null_oid(the_hash_algo)); } /* @@ -4163,11 +4185,11 @@ static int process_entry(struct merge_options *opt, new_ci->merged.result.mode = ci->stages[2].mode; oidcpy(&new_ci->merged.result.oid, &ci->stages[2].oid); new_ci->stages[1].mode = 0; - oidcpy(&new_ci->stages[1].oid, null_oid()); + oidcpy(&new_ci->stages[1].oid, null_oid(the_hash_algo)); new_ci->filemask = 5; if ((S_IFMT & b_mode) != (S_IFMT & o_mode)) { new_ci->stages[0].mode = 0; - oidcpy(&new_ci->stages[0].oid, null_oid()); + oidcpy(&new_ci->stages[0].oid, null_oid(the_hash_algo)); new_ci->filemask = 4; } @@ -4175,11 +4197,11 @@ static int process_entry(struct merge_options *opt, ci->merged.result.mode = ci->stages[1].mode; oidcpy(&ci->merged.result.oid, &ci->stages[1].oid); ci->stages[2].mode = 0; - oidcpy(&ci->stages[2].oid, null_oid()); + oidcpy(&ci->stages[2].oid, null_oid(the_hash_algo)); ci->filemask = 3; if ((S_IFMT & a_mode) != (S_IFMT & o_mode)) { ci->stages[0].mode = 0; - oidcpy(&ci->stages[0].oid, null_oid()); + oidcpy(&ci->stages[0].oid, null_oid(the_hash_algo)); ci->filemask = 2; } @@ -4217,10 +4239,13 @@ static int process_entry(struct merge_options *opt, struct version_info *o = &ci->stages[0]; struct version_info *a = &ci->stages[1]; struct version_info *b = &ci->stages[2]; + int record_object = (!opt->mergeability_only || + opt->priv->call_depth); clean_merge = handle_content_merge(opt, path, o, a, b, ci->pathnames, opt->priv->call_depth * 2, + record_object, &merged_file); if (clean_merge < 0) return -1; @@ -4304,7 +4329,7 @@ static int process_entry(struct merge_options *opt, /* Deleted on both sides */ ci->merged.is_null = 1; ci->merged.result.mode = 0; - oidcpy(&ci->merged.result.oid, null_oid()); + oidcpy(&ci->merged.result.oid, null_oid(the_hash_algo)); assert(!ci->df_conflict); ci->merged.clean = !ci->path_conflict; } @@ -4381,6 +4406,8 @@ static int process_entries(struct merge_options *opt, STRING_LIST_INIT_NODUP, NULL, 0 }; int ret = 0; + const int record_tree = (!opt->mergeability_only || + opt->priv->call_depth); trace2_region_enter("merge", "process_entries setup", opt->repo); if (strmap_empty(&opt->priv->paths)) { @@ -4440,6 +4467,12 @@ static int process_entries(struct merge_options *opt, ret = -1; goto cleanup; }; + if (!ci->merged.clean && opt->mergeability_only && + !opt->priv->call_depth) { + ret = 0; + goto cleanup; + } + } } trace2_region_leave("merge", "processing", opt->repo); @@ -4454,7 +4487,8 @@ static int process_entries(struct merge_options *opt, fflush(stdout); BUG("dir_metadata accounting completely off; shouldn't happen"); } - if (write_tree(result_oid, &dir_metadata.versions, 0, + if (record_tree && + write_tree(result_oid, &dir_metadata.versions, 0, opt->repo->hash_algo->rawsz) < 0) ret = -1; cleanup: @@ -4701,6 +4735,8 @@ void merge_display_update_messages(struct merge_options *opt, if (opt->record_conflict_msgs_as_headers) BUG("Either display conflict messages or record them as headers, not both"); + if (opt->mergeability_only) + BUG("Displaying conflict messages incompatible with mergeability-only checks"); trace2_region_enter("merge", "display messages", opt->repo); @@ -4878,9 +4914,9 @@ static inline void set_commit_tree(struct commit *c, struct tree *t) c->maybe_tree = t; } -static struct commit *make_virtual_commit(struct repository *repo, - struct tree *tree, - const char *comment) +struct commit *make_virtual_commit(struct repository *repo, + struct tree *tree, + const char *comment) { struct commit *commit = alloc_commit_node(repo); @@ -4945,9 +4981,6 @@ static void merge_start(struct merge_options *opt, struct merge_result *result) } trace2_region_leave("merge", "sanity checks", opt->repo); - /* Default to histogram diff. Actually, just hardcode it...for now. */ - opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF); - /* Handle attr direction stuff for renormalization */ if (opt->renormalize) git_attr_set_direction(GIT_ATTR_CHECKOUT); @@ -5020,7 +5053,8 @@ static void merge_start(struct merge_options *opt, struct merge_result *result) trace2_region_leave("merge", "allocate/init", opt->repo); } -static void merge_check_renames_reusable(struct merge_result *result, +static void merge_check_renames_reusable(struct merge_options *opt, + struct merge_result *result, struct tree *merge_base, struct tree *side1, struct tree *side2) @@ -5046,6 +5080,26 @@ static void merge_check_renames_reusable(struct merge_result *result, } /* + * Avoid using cached renames when directory rename detection is + * turned off. Cached renames are far less important in that case, + * and they lead to testcases with an interesting intersection of + * effects from relevant renames optimization, trivial directory + * resolution optimization, and cached renames all converging when + * the target of a cached rename is in a directory that + * collect_merge_info() does not recurse into. To avoid such + * problems, simply disable cached renames for this case (similar + * to the rename/rename(1to1) case; see the "disabling the + * optimization" comment near that case). + * + * This could be revisited in the future; see the commit message + * where this comment was added for some possible pointers. + */ + if (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_NONE) { + renames->cached_pairs_valid_side = 0; /* neither side valid */ + return; + } + + /* * Handle other cases; note that merge_trees[0..2] will only * be NULL if opti is, or if all three were manually set to * NULL by e.g. rename/rename(1to1) handling. @@ -5139,10 +5193,12 @@ redo: result->path_messages = &opt->priv->conflicts; 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)); + if (!opt->mergeability_only) { + 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); } @@ -5186,6 +5242,8 @@ static void merge_ort_internal(struct merge_options *opt, ancestor_name = "empty tree"; } else if (merge_bases) { ancestor_name = "merged common ancestors"; + } else if (opt->ancestor) { + ancestor_name = opt->ancestor; } else { strbuf_add_unique_abbrev(&merge_base_abbrev, &merged_merge_bases->object.oid, @@ -5251,7 +5309,7 @@ void merge_incore_nonrecursive(struct merge_options *opt, trace2_region_enter("merge", "merge_start", opt->repo); assert(opt->ancestor != NULL); - merge_check_renames_reusable(result, merge_base, side1, side2); + merge_check_renames_reusable(opt, result, merge_base, side1, side2); merge_start(opt, result); /* * Record the trees used in this merge, so if there's a next merge in @@ -5275,8 +5333,13 @@ void merge_incore_recursive(struct merge_options *opt, { trace2_region_enter("merge", "incore_recursive", opt->repo); - /* We set the ancestor label based on the merge_bases */ - assert(opt->ancestor == NULL); + /* + * We set the ancestor label based on the merge_bases...but we + * allow one exception through so that builtin/am can override + * with its constructed fake ancestor. + */ + assert(opt->ancestor == NULL || + (merge_bases && !merge_bases->next)); trace2_region_enter("merge", "merge_start", opt->repo); merge_start(opt, result); @@ -5285,3 +5348,161 @@ void merge_incore_recursive(struct merge_options *opt, merge_ort_internal(opt, merge_bases, side1, side2, result); trace2_region_leave("merge", "incore_recursive", opt->repo); } + +static void merge_recursive_config(struct merge_options *opt, int ui) +{ + char *value = NULL; + int renormalize = 0; + git_config_get_int("merge.verbosity", &opt->verbosity); + git_config_get_int("diff.renamelimit", &opt->rename_limit); + git_config_get_int("merge.renamelimit", &opt->rename_limit); + git_config_get_bool("merge.renormalize", &renormalize); + opt->renormalize = renormalize; + if (!git_config_get_string("diff.renames", &value)) { + opt->detect_renames = git_config_rename("diff.renames", value); + free(value); + } + if (!git_config_get_string("merge.renames", &value)) { + opt->detect_renames = git_config_rename("merge.renames", value); + free(value); + } + if (!git_config_get_string("merge.directoryrenames", &value)) { + int boolval = git_parse_maybe_bool(value); + if (0 <= boolval) { + opt->detect_directory_renames = boolval ? + MERGE_DIRECTORY_RENAMES_TRUE : + MERGE_DIRECTORY_RENAMES_NONE; + } else if (!strcasecmp(value, "conflict")) { + opt->detect_directory_renames = + MERGE_DIRECTORY_RENAMES_CONFLICT; + } /* avoid erroring on values from future versions of git */ + free(value); + } + if (ui) { + if (!git_config_get_string("diff.algorithm", &value)) { + long diff_algorithm = parse_algorithm_value(value); + if (diff_algorithm < 0) + die(_("unknown value for config '%s': %s"), "diff.algorithm", value); + opt->xdl_opts = (opt->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | diff_algorithm; + free(value); + } + } + git_config(git_xmerge_config, NULL); +} + +static void init_merge_options(struct merge_options *opt, + struct repository *repo, int ui) +{ + const char *merge_verbosity; + memset(opt, 0, sizeof(struct merge_options)); + + opt->repo = repo; + + opt->detect_renames = -1; + opt->detect_directory_renames = MERGE_DIRECTORY_RENAMES_CONFLICT; + opt->rename_limit = -1; + + opt->verbosity = 2; + opt->buffer_output = 1; + strbuf_init(&opt->obuf, 0); + + opt->renormalize = 0; + + opt->conflict_style = -1; + opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF); + + merge_recursive_config(opt, ui); + merge_verbosity = getenv("GIT_MERGE_VERBOSITY"); + if (merge_verbosity) + opt->verbosity = strtol(merge_verbosity, NULL, 10); + if (opt->verbosity >= 5) + opt->buffer_output = 0; +} + +void init_ui_merge_options(struct merge_options *opt, + struct repository *repo) +{ + init_merge_options(opt, repo, 1); +} + +void init_basic_merge_options(struct merge_options *opt, + struct repository *repo) +{ + init_merge_options(opt, repo, 0); +} + +/* + * For now, members of merge_options do not need deep copying, but + * it may change in the future, in which case we would need to update + * this, and also make a matching change to clear_merge_options() to + * release the resources held by a copied instance. + */ +void copy_merge_options(struct merge_options *dst, struct merge_options *src) +{ + *dst = *src; +} + +void clear_merge_options(struct merge_options *opt UNUSED) +{ + ; /* no-op as our copy is shallow right now */ +} + +int parse_merge_opt(struct merge_options *opt, const char *s) +{ + const char *arg; + + if (!s || !*s) + return -1; + if (!strcmp(s, "ours")) + opt->recursive_variant = MERGE_VARIANT_OURS; + else if (!strcmp(s, "theirs")) + opt->recursive_variant = MERGE_VARIANT_THEIRS; + else if (!strcmp(s, "subtree")) + opt->subtree_shift = ""; + else if (skip_prefix(s, "subtree=", &arg)) + opt->subtree_shift = arg; + else if (!strcmp(s, "patience")) + opt->xdl_opts = DIFF_WITH_ALG(opt, PATIENCE_DIFF); + else if (!strcmp(s, "histogram")) + opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF); + else if (skip_prefix(s, "diff-algorithm=", &arg)) { + long value = parse_algorithm_value(arg); + if (value < 0) + return -1; + /* clear out previous settings */ + DIFF_XDL_CLR(opt, NEED_MINIMAL); + opt->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK; + opt->xdl_opts |= value; + } + else if (!strcmp(s, "ignore-space-change")) + DIFF_XDL_SET(opt, IGNORE_WHITESPACE_CHANGE); + else if (!strcmp(s, "ignore-all-space")) + DIFF_XDL_SET(opt, IGNORE_WHITESPACE); + else if (!strcmp(s, "ignore-space-at-eol")) + DIFF_XDL_SET(opt, IGNORE_WHITESPACE_AT_EOL); + else if (!strcmp(s, "ignore-cr-at-eol")) + DIFF_XDL_SET(opt, IGNORE_CR_AT_EOL); + else if (!strcmp(s, "renormalize")) + opt->renormalize = 1; + else if (!strcmp(s, "no-renormalize")) + opt->renormalize = 0; + else if (!strcmp(s, "no-renames")) + opt->detect_renames = 0; + else if (!strcmp(s, "find-renames")) { + opt->detect_renames = 1; + opt->rename_score = 0; + } + else if (skip_prefix(s, "find-renames=", &arg) || + skip_prefix(s, "rename-threshold=", &arg)) { + if ((opt->rename_score = parse_rename_score(&arg)) == -1 || *arg != 0) + return -1; + opt->detect_renames = 1; + } + /* + * Please update $__git_merge_strategy_options in + * git-completion.bash when you add new options + */ + else + return -1; + return 0; +} diff --git a/merge-ort.h b/merge-ort.h index 82f2b3222d..6045579825 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -1,10 +1,11 @@ #ifndef MERGE_ORT_H #define MERGE_ORT_H -#include "merge-recursive.h" #include "hash.h" +#include "strbuf.h" struct commit; +struct commit_list; struct tree; struct strmap; @@ -44,6 +45,57 @@ struct merge_result { unsigned _properly_initialized; }; +struct merge_options_internal; +struct merge_options { + struct repository *repo; + + /* ref names used in console messages and conflict markers */ + const char *ancestor; + const char *branch1; + const char *branch2; + + /* rename related options */ + int detect_renames; + enum { + MERGE_DIRECTORY_RENAMES_NONE = 0, + MERGE_DIRECTORY_RENAMES_CONFLICT = 1, + MERGE_DIRECTORY_RENAMES_TRUE = 2 + } detect_directory_renames; + int rename_limit; + int rename_score; + int show_rename_progress; + + /* xdiff-related options (patience, ignore whitespace, ours/theirs) */ + long xdl_opts; + int conflict_style; + enum { + MERGE_VARIANT_NORMAL = 0, + MERGE_VARIANT_OURS, + MERGE_VARIANT_THEIRS + } recursive_variant; + + /* console output related options */ + int verbosity; + unsigned buffer_output; /* 1: output at end, 2: keep buffered */ + struct strbuf obuf; /* output buffer; if buffer_output == 2, caller + * must handle and call strbuf_release */ + + /* miscellaneous control options */ + const char *subtree_shift; + unsigned renormalize : 1; + unsigned mergeability_only : 1; /* exit early, write fewer objects */ + unsigned record_conflict_msgs_as_headers : 1; + const char *msg_header_prefix; + + /* internal fields used by the implementation */ + struct merge_options_internal *priv; +}; + +/* Mostly internal function also used by merge-ort-wrappers.c */ +struct commit *make_virtual_commit(struct repository *repo, + struct tree *tree, + const char *comment); + /* * rename-detecting three-way merge with recursive ancestor consolidation. * working tree and index are untouched. @@ -114,4 +166,16 @@ void merge_get_conflicted_files(struct merge_result *result, void merge_finalize(struct merge_options *opt, struct merge_result *result); + +/* for use by porcelain commands */ +void init_ui_merge_options(struct merge_options *opt, struct repository *repo); +/* for use by plumbing commands */ +void init_basic_merge_options(struct merge_options *opt, struct repository *repo); + +void copy_merge_options(struct merge_options *dst, struct merge_options *src); +void clear_merge_options(struct merge_options *opt); + +/* parse the option in s and update the relevant field of opt */ +int parse_merge_opt(struct merge_options *opt, const char *s); + #endif diff --git a/merge-recursive.c b/merge-recursive.c deleted file mode 100644 index 884ccf99a5..0000000000 --- a/merge-recursive.c +++ /dev/null @@ -1,4079 +0,0 @@ -/* - * Recursive Merge algorithm stolen from git-merge-recursive.py by - * Fredrik Kuivinen. - * The thieves were Alex Riesen and Johannes Schindelin, in June/July 2006 - */ - -#define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS - -#include "git-compat-util.h" -#include "merge-recursive.h" - -#include "alloc.h" -#include "cache-tree.h" -#include "commit.h" -#include "commit-reach.h" -#include "config.h" -#include "diff.h" -#include "diffcore.h" -#include "dir.h" -#include "environment.h" -#include "gettext.h" -#include "hex.h" -#include "merge-ll.h" -#include "lockfile.h" -#include "match-trees.h" -#include "name-hash.h" -#include "object-file.h" -#include "object-name.h" -#include "object-store-ll.h" -#include "path.h" -#include "repository.h" -#include "revision.h" -#include "sparse-index.h" -#include "string-list.h" -#include "symlinks.h" -#include "tag.h" -#include "tree-walk.h" -#include "unpack-trees.h" -#include "xdiff-interface.h" - -struct merge_options_internal { - int call_depth; - int needed_rename_limit; - struct hashmap current_file_dir_set; - struct string_list df_conflict_file_set; - struct unpack_trees_options unpack_opts; - struct index_state orig_index; -}; - -struct path_hashmap_entry { - struct hashmap_entry e; - char path[FLEX_ARRAY]; -}; - -static int path_hashmap_cmp(const void *cmp_data UNUSED, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, - const void *keydata) -{ - const struct path_hashmap_entry *a, *b; - const char *key = keydata; - - a = container_of(eptr, const struct path_hashmap_entry, e); - b = container_of(entry_or_key, const struct path_hashmap_entry, e); - - return fspathcmp(a->path, key ? key : b->path); -} - -/* - * For dir_rename_entry, directory names are stored as a full path from the - * toplevel of the repository and do not include a trailing '/'. Also: - * - * dir: original name of directory being renamed - * non_unique_new_dir: if true, could not determine new_dir - * new_dir: final name of directory being renamed - * possible_new_dirs: temporary used to help determine new_dir; see comments - * in get_directory_renames() for details - */ -struct dir_rename_entry { - struct hashmap_entry ent; - char *dir; - unsigned non_unique_new_dir:1; - struct strbuf new_dir; - struct string_list possible_new_dirs; -}; - -static struct dir_rename_entry *dir_rename_find_entry(struct hashmap *hashmap, - char *dir) -{ - struct dir_rename_entry key; - - if (!dir) - return NULL; - hashmap_entry_init(&key.ent, strhash(dir)); - key.dir = dir; - return hashmap_get_entry(hashmap, &key, ent, NULL); -} - -static int dir_rename_cmp(const void *cmp_data UNUSED, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, - const void *keydata UNUSED) -{ - const struct dir_rename_entry *e1, *e2; - - e1 = container_of(eptr, const struct dir_rename_entry, ent); - e2 = container_of(entry_or_key, const struct dir_rename_entry, ent); - - return strcmp(e1->dir, e2->dir); -} - -static void dir_rename_init(struct hashmap *map) -{ - hashmap_init(map, dir_rename_cmp, NULL, 0); -} - -static void dir_rename_entry_init(struct dir_rename_entry *entry, - char *directory) -{ - hashmap_entry_init(&entry->ent, strhash(directory)); - entry->dir = directory; - entry->non_unique_new_dir = 0; - strbuf_init(&entry->new_dir, 0); - string_list_init_nodup(&entry->possible_new_dirs); -} - -struct collision_entry { - struct hashmap_entry ent; - char *target_file; - struct string_list source_files; - unsigned reported_already:1; -}; - -static struct collision_entry *collision_find_entry(struct hashmap *hashmap, - char *target_file) -{ - struct collision_entry key; - - hashmap_entry_init(&key.ent, strhash(target_file)); - key.target_file = target_file; - return hashmap_get_entry(hashmap, &key, ent, NULL); -} - -static int collision_cmp(const void *cmp_data UNUSED, - const struct hashmap_entry *eptr, - const struct hashmap_entry *entry_or_key, - const void *keydata UNUSED) -{ - const struct collision_entry *e1, *e2; - - e1 = container_of(eptr, const struct collision_entry, ent); - e2 = container_of(entry_or_key, const struct collision_entry, ent); - - return strcmp(e1->target_file, e2->target_file); -} - -static void collision_init(struct hashmap *map) -{ - hashmap_init(map, collision_cmp, NULL, 0); -} - -static void flush_output(struct merge_options *opt) -{ - if (opt->buffer_output < 2 && opt->obuf.len) { - fputs(opt->obuf.buf, stdout); - strbuf_reset(&opt->obuf); - } -} - -__attribute__((format (printf, 2, 3))) -static int err(struct merge_options *opt, const char *err, ...) -{ - va_list params; - - if (opt->buffer_output < 2) - flush_output(opt); - else { - strbuf_complete(&opt->obuf, '\n'); - strbuf_addstr(&opt->obuf, "error: "); - } - va_start(params, err); - strbuf_vaddf(&opt->obuf, err, params); - va_end(params); - if (opt->buffer_output > 1) - strbuf_addch(&opt->obuf, '\n'); - else { - error("%s", opt->obuf.buf); - strbuf_reset(&opt->obuf); - } - - return -1; -} - -static struct tree *shift_tree_object(struct repository *repo, - struct tree *one, struct tree *two, - const char *subtree_shift) -{ - struct object_id shifted; - - if (!*subtree_shift) { - shift_tree(repo, &one->object.oid, &two->object.oid, &shifted, 0); - } else { - shift_tree_by(repo, &one->object.oid, &two->object.oid, &shifted, - subtree_shift); - } - if (oideq(&two->object.oid, &shifted)) - return two; - return lookup_tree(repo, &shifted); -} - -static inline void set_commit_tree(struct commit *c, struct tree *t) -{ - c->maybe_tree = t; -} - -static struct commit *make_virtual_commit(struct repository *repo, - struct tree *tree, - const char *comment) -{ - struct commit *commit = alloc_commit_node(repo); - - set_merge_remote_desc(commit, comment, (struct object *)commit); - set_commit_tree(commit, tree); - commit->object.parsed = 1; - return commit; -} - -enum rename_type { - RENAME_NORMAL = 0, - RENAME_VIA_DIR, - RENAME_ADD, - RENAME_DELETE, - RENAME_ONE_FILE_TO_ONE, - RENAME_ONE_FILE_TO_TWO, - RENAME_TWO_FILES_TO_ONE -}; - -/* - * Since we want to write the index eventually, we cannot reuse the index - * for these (temporary) data. - */ -struct stage_data { - struct diff_filespec stages[4]; /* mostly for oid & mode; maybe path */ - struct rename_conflict_info *rename_conflict_info; - unsigned processed:1, - rename_conflict_info_owned:1; -}; - -struct rename { - unsigned processed:1; - struct diff_filepair *pair; - const char *branch; /* branch that the rename occurred on */ - /* - * If directory rename detection affected this rename, what was its - * original type ('A' or 'R') and it's original destination before - * the directory rename (otherwise, '\0' and NULL for these two vars). - */ - char dir_rename_original_type; - char *dir_rename_original_dest; - /* - * Purpose of src_entry and dst_entry: - * - * If 'before' is renamed to 'after' then src_entry will contain - * the versions of 'before' from the merge_base, HEAD, and MERGE in - * stages 1, 2, and 3; dst_entry will contain the respective - * versions of 'after' in corresponding locations. Thus, we have a - * total of six modes and oids, though some will be null. (Stage 0 - * is ignored; we're interested in handling conflicts.) - * - * Since we don't turn on break-rewrites by default, neither - * src_entry nor dst_entry can have all three of their stages have - * non-null oids, meaning at most four of the six will be non-null. - * Also, since this is a rename, both src_entry and dst_entry will - * have at least one non-null oid, meaning at least two will be - * non-null. Of the six oids, a typical rename will have three be - * non-null. Only two implies a rename/delete, and four implies a - * rename/add. - */ - struct stage_data *src_entry; - struct stage_data *dst_entry; -}; - -struct rename_conflict_info { - enum rename_type rename_type; - struct rename *ren1; - struct rename *ren2; -}; - -static inline void setup_rename_conflict_info(enum rename_type rename_type, - struct merge_options *opt, - struct rename *ren1, - struct rename *ren2) -{ - struct rename_conflict_info *ci; - - /* - * When we have two renames involved, it's easiest to get the - * correct things into stage 2 and 3, and to make sure that the - * content merge puts HEAD before the other branch if we just - * ensure that branch1 == opt->branch1. So, simply flip arguments - * around if we don't have that. - */ - if (ren2 && ren1->branch != opt->branch1) { - setup_rename_conflict_info(rename_type, opt, ren2, ren1); - return; - } - - CALLOC_ARRAY(ci, 1); - ci->rename_type = rename_type; - ci->ren1 = ren1; - ci->ren2 = ren2; - - ci->ren1->dst_entry->processed = 0; - ci->ren1->dst_entry->rename_conflict_info = ci; - ci->ren1->dst_entry->rename_conflict_info_owned = 1; - if (ren2) { - ci->ren2->dst_entry->rename_conflict_info = ci; - } -} - -static int show(struct merge_options *opt, int v) -{ - return (!opt->priv->call_depth && opt->verbosity >= v) || - opt->verbosity >= 5; -} - -__attribute__((format (printf, 3, 4))) -static void output(struct merge_options *opt, int v, const char *fmt, ...) -{ - va_list ap; - - if (!show(opt, v)) - return; - - strbuf_addchars(&opt->obuf, ' ', opt->priv->call_depth * 2); - - va_start(ap, fmt); - strbuf_vaddf(&opt->obuf, fmt, ap); - va_end(ap); - - strbuf_addch(&opt->obuf, '\n'); - if (!opt->buffer_output) - flush_output(opt); -} - -static void repo_output_commit_title(struct merge_options *opt, - struct repository *repo, - struct commit *commit) -{ - struct merge_remote_desc *desc; - - strbuf_addchars(&opt->obuf, ' ', opt->priv->call_depth * 2); - desc = merge_remote_util(commit); - if (desc) - strbuf_addf(&opt->obuf, "virtual %s\n", desc->name); - else { - strbuf_repo_add_unique_abbrev(&opt->obuf, repo, - &commit->object.oid, - DEFAULT_ABBREV); - strbuf_addch(&opt->obuf, ' '); - if (repo_parse_commit(repo, commit) != 0) - strbuf_addstr(&opt->obuf, _("(bad commit)\n")); - else { - const char *title; - const char *msg = repo_get_commit_buffer(repo, commit, NULL); - int len = find_commit_subject(msg, &title); - if (len) - strbuf_addf(&opt->obuf, "%.*s\n", len, title); - repo_unuse_commit_buffer(repo, commit, msg); - } - } - flush_output(opt); -} - -static void output_commit_title(struct merge_options *opt, struct commit *commit) -{ - repo_output_commit_title(opt, the_repository, commit); -} - -static int add_cacheinfo(struct merge_options *opt, - const struct diff_filespec *blob, - const char *path, int stage, int refresh, int options) -{ - struct index_state *istate = opt->repo->index; - struct cache_entry *ce; - int ret; - - ce = make_cache_entry(istate, blob->mode, &blob->oid, path, stage, 0); - if (!ce) - return err(opt, _("add_cacheinfo failed for path '%s'; merge aborting."), path); - - ret = add_index_entry(istate, ce, options); - if (refresh) { - struct cache_entry *nce; - - nce = refresh_cache_entry(istate, ce, - CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING); - if (!nce) - return err(opt, _("add_cacheinfo failed to refresh for path '%s'; merge aborting."), path); - if (nce != ce) - ret = add_index_entry(istate, nce, options); - } - return ret; -} - -static inline int merge_detect_rename(struct merge_options *opt) -{ - return (opt->detect_renames >= 0) ? opt->detect_renames : 1; -} - -static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree) -{ - 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, - struct tree *common, - struct tree *head, - struct tree *merge) -{ - int rc; - struct tree_desc t[3]; - struct index_state tmp_index = INDEX_STATE_INIT(opt->repo); - - memset(&opt->priv->unpack_opts, 0, sizeof(opt->priv->unpack_opts)); - if (opt->priv->call_depth) - opt->priv->unpack_opts.index_only = 1; - else { - opt->priv->unpack_opts.update = 1; - /* FIXME: should only do this if !overwrite_ignore */ - opt->priv->unpack_opts.preserve_ignored = 0; - } - opt->priv->unpack_opts.merge = 1; - opt->priv->unpack_opts.head_idx = 2; - opt->priv->unpack_opts.fn = threeway_merge; - opt->priv->unpack_opts.src_index = opt->repo->index; - opt->priv->unpack_opts.dst_index = &tmp_index; - opt->priv->unpack_opts.aggressive = !merge_detect_rename(opt); - setup_unpack_trees_porcelain(&opt->priv->unpack_opts, "merge"); - - init_tree_desc_from_tree(t+0, common); - init_tree_desc_from_tree(t+1, head); - init_tree_desc_from_tree(t+2, merge); - - rc = unpack_trees(3, t, &opt->priv->unpack_opts); - cache_tree_free(&opt->repo->index->cache_tree); - - /* - * Update opt->repo->index to match the new results, AFTER saving a - * copy in opt->priv->orig_index. Update src_index to point to the - * saved copy. (verify_uptodate() checks src_index, and the original - * index is the one that had the necessary modification timestamps.) - */ - opt->priv->orig_index = *opt->repo->index; - *opt->repo->index = tmp_index; - opt->priv->unpack_opts.src_index = &opt->priv->orig_index; - - return rc; -} - -static void unpack_trees_finish(struct merge_options *opt) -{ - discard_index(&opt->priv->orig_index); - clear_unpack_trees_porcelain(&opt->priv->unpack_opts); -} - -static int save_files_dirs(const struct object_id *oid UNUSED, - struct strbuf *base, const char *path, - unsigned int mode, void *context) -{ - struct path_hashmap_entry *entry; - int baselen = base->len; - struct merge_options *opt = context; - - strbuf_addstr(base, path); - - FLEX_ALLOC_MEM(entry, path, base->buf, base->len); - hashmap_entry_init(&entry->e, fspathhash(entry->path)); - hashmap_add(&opt->priv->current_file_dir_set, &entry->e); - - strbuf_setlen(base, baselen); - return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0); -} - -static void get_files_dirs(struct merge_options *opt, struct tree *tree) -{ - struct pathspec match_all; - memset(&match_all, 0, sizeof(match_all)); - read_tree(opt->repo, tree, - &match_all, save_files_dirs, opt); -} - -static int get_tree_entry_if_blob(struct repository *r, - const struct object_id *tree, - const char *path, - struct diff_filespec *dfs) -{ - int ret; - - ret = get_tree_entry(r, tree, path, &dfs->oid, &dfs->mode); - if (S_ISDIR(dfs->mode)) { - oidcpy(&dfs->oid, null_oid()); - dfs->mode = 0; - } - return ret; -} - -/* - * Returns an index_entry instance which doesn't have to correspond to - * a real cache entry in Git's index. - */ -static struct stage_data *insert_stage_data(struct repository *r, - const char *path, - struct tree *o, struct tree *a, struct tree *b, - struct string_list *entries) -{ - struct string_list_item *item; - struct stage_data *e = xcalloc(1, sizeof(struct stage_data)); - get_tree_entry_if_blob(r, &o->object.oid, path, &e->stages[1]); - get_tree_entry_if_blob(r, &a->object.oid, path, &e->stages[2]); - get_tree_entry_if_blob(r, &b->object.oid, path, &e->stages[3]); - item = string_list_insert(entries, path); - item->util = e; - return e; -} - -/* - * Create a dictionary mapping file names to stage_data objects. The - * dictionary contains one entry for every path with a non-zero stage entry. - */ -static struct string_list *get_unmerged(struct index_state *istate) -{ - struct string_list *unmerged = xmalloc(sizeof(struct string_list)); - int i; - - string_list_init_dup(unmerged); - - /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(istate); - for (i = 0; i < istate->cache_nr; i++) { - struct string_list_item *item; - struct stage_data *e; - const struct cache_entry *ce = istate->cache[i]; - if (!ce_stage(ce)) - continue; - - item = string_list_lookup(unmerged, ce->name); - if (!item) { - item = string_list_insert(unmerged, ce->name); - item->util = xcalloc(1, sizeof(struct stage_data)); - } - e = item->util; - e->stages[ce_stage(ce)].mode = ce->ce_mode; - oidcpy(&e->stages[ce_stage(ce)].oid, &ce->oid); - } - - return unmerged; -} - -static int string_list_df_name_compare(const char *one, const char *two) -{ - int onelen = strlen(one); - int twolen = strlen(two); - /* - * Here we only care that entries for D/F conflicts are - * adjacent, in particular with the file of the D/F conflict - * appearing before files below the corresponding directory. - * The order of the rest of the list is irrelevant for us. - * - * To achieve this, we sort with df_name_compare and provide - * the mode S_IFDIR so that D/F conflicts will sort correctly. - * We use the mode S_IFDIR for everything else for simplicity, - * since in other cases any changes in their order due to - * sorting cause no problems for us. - */ - int cmp = df_name_compare(one, onelen, S_IFDIR, - two, twolen, S_IFDIR); - /* - * Now that 'foo' and 'foo/bar' compare equal, we have to make sure - * that 'foo' comes before 'foo/bar'. - */ - if (cmp) - return cmp; - return onelen - twolen; -} - -static void record_df_conflict_files(struct merge_options *opt, - struct string_list *entries) -{ - /* If there is a D/F conflict and the file for such a conflict - * currently exists in the working tree, we want to allow it to be - * removed to make room for the corresponding directory if needed. - * The files underneath the directories of such D/F conflicts will - * be processed before the corresponding file involved in the D/F - * conflict. If the D/F directory ends up being removed by the - * merge, then we won't have to touch the D/F file. If the D/F - * directory needs to be written to the working copy, then the D/F - * file will simply be removed (in make_room_for_path()) to make - * room for the necessary paths. Note that if both the directory - * and the file need to be present, then the D/F file will be - * reinstated with a new unique name at the time it is processed. - */ - struct string_list df_sorted_entries = STRING_LIST_INIT_NODUP; - const char *last_file = NULL; - int last_len = 0; - int i; - - /* - * If we're merging merge-bases, we don't want to bother with - * any working directory changes. - */ - if (opt->priv->call_depth) - return; - - /* Ensure D/F conflicts are adjacent in the entries list. */ - for (i = 0; i < entries->nr; i++) { - struct string_list_item *next = &entries->items[i]; - string_list_append(&df_sorted_entries, next->string)->util = - next->util; - } - df_sorted_entries.cmp = string_list_df_name_compare; - string_list_sort(&df_sorted_entries); - - string_list_clear(&opt->priv->df_conflict_file_set, 1); - for (i = 0; i < df_sorted_entries.nr; i++) { - const char *path = df_sorted_entries.items[i].string; - int len = strlen(path); - struct stage_data *e = df_sorted_entries.items[i].util; - - /* - * Check if last_file & path correspond to a D/F conflict; - * i.e. whether path is last_file+'/'+<something>. - * If so, record that it's okay to remove last_file to make - * room for path and friends if needed. - */ - if (last_file && - len > last_len && - memcmp(path, last_file, last_len) == 0 && - path[last_len] == '/') { - string_list_insert(&opt->priv->df_conflict_file_set, last_file); - } - - /* - * Determine whether path could exist as a file in the - * working directory as a possible D/F conflict. This - * will only occur when it exists in stage 2 as a - * file. - */ - if (S_ISREG(e->stages[2].mode) || S_ISLNK(e->stages[2].mode)) { - last_file = path; - last_len = len; - } else { - last_file = NULL; - } - } - string_list_clear(&df_sorted_entries, 0); -} - -static int update_stages(struct merge_options *opt, const char *path, - const struct diff_filespec *o, - const struct diff_filespec *a, - const struct diff_filespec *b) -{ - - /* - * NOTE: It is usually a bad idea to call update_stages on a path - * before calling update_file on that same path, since it can - * sometimes lead to spurious "refusing to lose untracked file..." - * messages from update_file (via make_room_for path via - * would_lose_untracked). Instead, reverse the order of the calls - * (executing update_file first and then update_stages). - */ - int clear = 1; - int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK; - if (clear) - if (remove_file_from_index(opt->repo->index, path)) - return -1; - if (o) - if (add_cacheinfo(opt, o, path, 1, 0, options)) - return -1; - if (a) - if (add_cacheinfo(opt, a, path, 2, 0, options)) - return -1; - if (b) - if (add_cacheinfo(opt, b, path, 3, 0, options)) - return -1; - return 0; -} - -static void update_entry(struct stage_data *entry, - struct diff_filespec *o, - struct diff_filespec *a, - struct diff_filespec *b) -{ - entry->processed = 0; - entry->stages[1].mode = o->mode; - entry->stages[2].mode = a->mode; - entry->stages[3].mode = b->mode; - oidcpy(&entry->stages[1].oid, &o->oid); - oidcpy(&entry->stages[2].oid, &a->oid); - oidcpy(&entry->stages[3].oid, &b->oid); -} - -static int remove_file(struct merge_options *opt, int clean, - const char *path, int no_wd) -{ - int update_cache = opt->priv->call_depth || clean; - int update_working_directory = !opt->priv->call_depth && !no_wd; - - if (update_cache) { - if (remove_file_from_index(opt->repo->index, path)) - return -1; - } - if (update_working_directory) { - if (ignore_case) { - struct cache_entry *ce; - ce = index_file_exists(opt->repo->index, path, strlen(path), - ignore_case); - if (ce && ce_stage(ce) == 0 && strcmp(path, ce->name)) - return 0; - } - if (remove_path(path)) - return -1; - } - return 0; -} - -/* add a string to a strbuf, but converting "/" to "_" */ -static void add_flattened_path(struct strbuf *out, const char *s) -{ - size_t i = out->len; - strbuf_addstr(out, s); - for (; i < out->len; i++) - if (out->buf[i] == '/') - out->buf[i] = '_'; -} - -static char *unique_path(struct merge_options *opt, - const char *path, - const char *branch) -{ - struct path_hashmap_entry *entry; - struct strbuf newpath = STRBUF_INIT; - int suffix = 0; - size_t base_len; - - strbuf_addf(&newpath, "%s~", path); - add_flattened_path(&newpath, branch); - - base_len = newpath.len; - while (hashmap_get_from_hash(&opt->priv->current_file_dir_set, - fspathhash(newpath.buf), newpath.buf) || - (!opt->priv->call_depth && file_exists(newpath.buf))) { - strbuf_setlen(&newpath, base_len); - strbuf_addf(&newpath, "_%d", suffix++); - } - - FLEX_ALLOC_MEM(entry, path, newpath.buf, newpath.len); - hashmap_entry_init(&entry->e, fspathhash(entry->path)); - hashmap_add(&opt->priv->current_file_dir_set, &entry->e); - return strbuf_detach(&newpath, NULL); -} - -/** - * Check whether a directory in the index is in the way of an incoming - * file. Return 1 if so. If check_working_copy is non-zero, also - * check the working directory. If empty_ok is non-zero, also return - * 0 in the case where the working-tree dir exists but is empty. - */ -static int dir_in_way(struct index_state *istate, const char *path, - int check_working_copy, int empty_ok) -{ - int pos; - struct strbuf dirpath = STRBUF_INIT; - struct stat st; - - strbuf_addstr(&dirpath, path); - strbuf_addch(&dirpath, '/'); - - pos = index_name_pos(istate, dirpath.buf, dirpath.len); - - if (pos < 0) - pos = -1 - pos; - if (pos < istate->cache_nr && - !strncmp(dirpath.buf, istate->cache[pos]->name, dirpath.len)) { - strbuf_release(&dirpath); - return 1; - } - - strbuf_release(&dirpath); - return check_working_copy && !lstat(path, &st) && S_ISDIR(st.st_mode) && - !(empty_ok && is_empty_dir(path)) && - !has_symlink_leading_path(path, strlen(path)); -} - -/* - * Returns whether path was tracked in the index before the merge started, - * and its oid and mode match the specified values - */ -static int was_tracked_and_matches(struct merge_options *opt, const char *path, - const struct diff_filespec *blob) -{ - int pos = index_name_pos(&opt->priv->orig_index, path, strlen(path)); - struct cache_entry *ce; - - if (0 > pos) - /* we were not tracking this path before the merge */ - return 0; - - /* See if the file we were tracking before matches */ - ce = opt->priv->orig_index.cache[pos]; - return (oideq(&ce->oid, &blob->oid) && ce->ce_mode == blob->mode); -} - -/* - * Returns whether path was tracked in the index before the merge started - */ -static int was_tracked(struct merge_options *opt, const char *path) -{ - int pos = index_name_pos(&opt->priv->orig_index, path, strlen(path)); - - if (0 <= pos) - /* we were tracking this path before the merge */ - return 1; - - return 0; -} - -static int would_lose_untracked(struct merge_options *opt, const char *path) -{ - struct index_state *istate = opt->repo->index; - - /* - * This may look like it can be simplified to: - * return !was_tracked(opt, path) && file_exists(path) - * but it can't. This function needs to know whether path was in - * the working tree due to EITHER having been tracked in the index - * before the merge OR having been put into the working copy and - * index by unpack_trees(). Due to that either-or requirement, we - * check the current index instead of the original one. - * - * Note that we do not need to worry about merge-recursive itself - * updating the index after unpack_trees() and before calling this - * function, because we strictly require all code paths in - * merge-recursive to update the working tree first and the index - * second. Doing otherwise would break - * update_file()/would_lose_untracked(); see every comment in this - * file which mentions "update_stages". - */ - int pos = index_name_pos(istate, path, strlen(path)); - - if (pos < 0) - pos = -1 - pos; - while (pos < istate->cache_nr && - !strcmp(path, istate->cache[pos]->name)) { - /* - * If stage #0, it is definitely tracked. - * If it has stage #2 then it was tracked - * before this merge started. All other - * cases the path was not tracked. - */ - switch (ce_stage(istate->cache[pos])) { - case 0: - case 2: - return 0; - } - pos++; - } - return file_exists(path); -} - -static int was_dirty(struct merge_options *opt, const char *path) -{ - struct cache_entry *ce; - int dirty = 1; - - if (opt->priv->call_depth || !was_tracked(opt, path)) - return !dirty; - - ce = index_file_exists(opt->priv->unpack_opts.src_index, - path, strlen(path), ignore_case); - dirty = verify_uptodate(ce, &opt->priv->unpack_opts) != 0; - return dirty; -} - -static int make_room_for_path(struct merge_options *opt, const char *path) -{ - int status, i; - const char *msg = _("failed to create path '%s'%s"); - - /* Unlink any D/F conflict files that are in the way */ - for (i = 0; i < opt->priv->df_conflict_file_set.nr; i++) { - const char *df_path = opt->priv->df_conflict_file_set.items[i].string; - size_t pathlen = strlen(path); - size_t df_pathlen = strlen(df_path); - if (df_pathlen < pathlen && - path[df_pathlen] == '/' && - strncmp(path, df_path, df_pathlen) == 0) { - output(opt, 3, - _("Removing %s to make room for subdirectory\n"), - df_path); - unlink(df_path); - unsorted_string_list_delete_item(&opt->priv->df_conflict_file_set, - i, 0); - break; - } - } - - /* Make sure leading directories are created */ - status = safe_create_leading_directories_const(path); - if (status) { - if (status == SCLD_EXISTS) - /* something else exists */ - return err(opt, msg, path, _(": perhaps a D/F conflict?")); - return err(opt, msg, path, ""); - } - - /* - * Do not unlink a file in the work tree if we are not - * tracking it. - */ - if (would_lose_untracked(opt, path)) - return err(opt, _("refusing to lose untracked file at '%s'"), - path); - - /* Successful unlink is good.. */ - if (!unlink(path)) - return 0; - /* .. and so is no existing file */ - if (errno == ENOENT) - return 0; - /* .. but not some other error (who really cares what?) */ - return err(opt, msg, path, _(": perhaps a D/F conflict?")); -} - -static int update_file_flags(struct merge_options *opt, - const struct diff_filespec *contents, - const char *path, - int update_cache, - int update_wd) -{ - int ret = 0; - - if (opt->priv->call_depth) - update_wd = 0; - - if (update_wd) { - enum object_type type; - void *buf; - unsigned long size; - - if (S_ISGITLINK(contents->mode)) { - /* - * We may later decide to recursively descend into - * the submodule directory and update its index - * and/or work tree, but we do not do that now. - */ - update_wd = 0; - goto update_index; - } - - buf = repo_read_object_file(the_repository, &contents->oid, - &type, &size); - if (!buf) { - ret = err(opt, _("cannot read object %s '%s'"), - oid_to_hex(&contents->oid), path); - goto free_buf; - } - if (type != OBJ_BLOB) { - ret = err(opt, _("blob expected for %s '%s'"), - oid_to_hex(&contents->oid), path); - goto free_buf; - } - if (S_ISREG(contents->mode)) { - struct strbuf strbuf = STRBUF_INIT; - if (convert_to_working_tree(opt->repo->index, - path, buf, size, &strbuf, NULL)) { - free(buf); - size = strbuf.len; - buf = strbuf_detach(&strbuf, NULL); - } - } - - if (make_room_for_path(opt, path) < 0) { - update_wd = 0; - goto free_buf; - } - if (S_ISREG(contents->mode) || - (!has_symlinks && S_ISLNK(contents->mode))) { - int fd; - int mode = (contents->mode & 0100 ? 0777 : 0666); - - fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); - if (fd < 0) { - ret = err(opt, _("failed to open '%s': %s"), - path, strerror(errno)); - goto free_buf; - } - write_in_full(fd, buf, size); - close(fd); - } else if (S_ISLNK(contents->mode)) { - char *lnk = xmemdupz(buf, size); - safe_create_leading_directories_const(path); - unlink(path); - if (symlink(lnk, path)) - ret = err(opt, _("failed to symlink '%s': %s"), - path, strerror(errno)); - free(lnk); - } else - ret = err(opt, - _("do not know what to do with %06o %s '%s'"), - contents->mode, oid_to_hex(&contents->oid), path); - free_buf: - free(buf); - } -update_index: - if (!ret && update_cache) { - int refresh = (!opt->priv->call_depth && - contents->mode != S_IFGITLINK); - if (add_cacheinfo(opt, contents, path, 0, refresh, - ADD_CACHE_OK_TO_ADD)) - return -1; - } - return ret; -} - -static int update_file(struct merge_options *opt, - int clean, - const struct diff_filespec *contents, - const char *path) -{ - return update_file_flags(opt, contents, path, - opt->priv->call_depth || clean, !opt->priv->call_depth); -} - -/* Low level file merging, update and removal */ - -struct merge_file_info { - struct diff_filespec blob; /* mostly use oid & mode; sometimes path */ - unsigned clean:1, - merge:1; -}; - -static int merge_3way(struct merge_options *opt, - mmbuffer_t *result_buf, - const struct diff_filespec *o, - const struct diff_filespec *a, - const struct diff_filespec *b, - const char *branch1, - const char *branch2, - const int extra_marker_size) -{ - mmfile_t orig, src1, src2; - 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; - ll_opts.variant = 0; - } else { - switch (opt->recursive_variant) { - case MERGE_VARIANT_OURS: - ll_opts.variant = XDL_MERGE_FAVOR_OURS; - break; - case MERGE_VARIANT_THEIRS: - ll_opts.variant = XDL_MERGE_FAVOR_THEIRS; - break; - default: - ll_opts.variant = 0; - break; - } - } - - assert(a->path && b->path && o->path && opt->ancestor); - if (strcmp(a->path, b->path) || strcmp(a->path, o->path) != 0) { - base = mkpathdup("%s:%s", opt->ancestor, o->path); - name1 = mkpathdup("%s:%s", branch1, a->path); - name2 = mkpathdup("%s:%s", branch2, b->path); - } else { - base = mkpathdup("%s", opt->ancestor); - name1 = mkpathdup("%s", branch1); - name2 = mkpathdup("%s", branch2); - } - - read_mmblob(&orig, &o->oid); - read_mmblob(&src1, &a->oid); - read_mmblob(&src2, &b->oid); - - /* - * FIXME: Using a->path for normalization rules in ll_merge could be - * wrong if we renamed from a->path to b->path. We should use the - * target path for where the file will be written. - */ - merge_status = ll_merge(result_buf, a->path, &orig, base, - &src1, name1, &src2, name2, - opt->repo->index, &ll_opts); - if (merge_status == LL_MERGE_BINARY_CONFLICT) - warning("Cannot merge binary files: %s (%s vs. %s)", - a->path, name1, name2); - - free(base); - free(name1); - free(name2); - free(orig.ptr); - free(src1.ptr); - free(src2.ptr); - return merge_status; -} - -static int find_first_merges(struct repository *repo, - struct object_array *result, const char *path, - struct commit *a, struct commit *b) -{ - int i, j; - struct object_array merges = OBJECT_ARRAY_INIT; - struct commit *commit; - int contains_another; - - char merged_revision[GIT_MAX_HEXSZ + 2]; - const char *rev_args[] = { "rev-list", "--merges", "--ancestry-path", - "--all", merged_revision, NULL }; - struct rev_info revs; - struct setup_revision_opt rev_opts; - - memset(result, 0, sizeof(struct object_array)); - memset(&rev_opts, 0, sizeof(rev_opts)); - - /* get all revisions that merge commit a */ - xsnprintf(merged_revision, sizeof(merged_revision), "^%s", - oid_to_hex(&a->object.oid)); - repo_init_revisions(repo, &revs, NULL); - /* FIXME: can't handle linked worktrees in submodules yet */ - revs.single_worktree = path != NULL; - setup_revisions(ARRAY_SIZE(rev_args)-1, rev_args, &revs, &rev_opts); - - /* save all revisions from the above list that contain b */ - if (prepare_revision_walk(&revs)) - die("revision walk setup failed"); - while ((commit = get_revision(&revs)) != NULL) { - struct object *o = &(commit->object); - 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(); - - /* Now we've got all merges that contain a and b. Prune all - * merges that contain another found merge and save them in - * result. - */ - for (i = 0; i < merges.nr; i++) { - struct commit *m1 = (struct commit *) merges.objects[i].item; - - contains_another = 0; - for (j = 0; j < merges.nr; j++) { - struct commit *m2 = (struct commit *) merges.objects[j].item; - 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; - } - } - } - - if (!contains_another) - add_object_array(merges.objects[i].item, NULL, result); - } - - object_array_clear(&merges); - release_revisions(&revs); - return result->nr; -} - -static void print_commit(struct repository *repo, struct commit *commit) -{ - struct strbuf sb = STRBUF_INIT; - struct pretty_print_context ctx = {0}; - ctx.date_mode.type = DATE_NORMAL; - /* FIXME: Merge this with output_commit_title() */ - assert(!merge_remote_util(commit)); - repo_format_commit_message(repo, commit, " %h: %m %s", &sb, &ctx); - fprintf(stderr, "%s\n", sb.buf); - strbuf_release(&sb); -} - -static int is_valid(const struct diff_filespec *dfs) -{ - return dfs->mode != 0 && !is_null_oid(&dfs->oid); -} - -static int merge_submodule(struct merge_options *opt, - struct object_id *result, const char *path, - const struct object_id *base, const struct object_id *a, - const struct object_id *b) -{ - struct repository subrepo; - int ret = 0, ret2; - struct commit *commit_base, *commit_a, *commit_b; - int parent_count; - struct object_array merges; - - int i; - int search = !opt->priv->call_depth; - - /* store a in result in case we fail */ - /* FIXME: This is the WRONG resolution for the recursive case when - * we need to be careful to avoid accidentally matching either side. - * Should probably use o instead there, much like we do for merging - * binaries. - */ - oidcpy(result, a); - - /* we can not handle deletion conflicts */ - if (is_null_oid(base)) - return 0; - if (is_null_oid(a)) - return 0; - if (is_null_oid(b)) - return 0; - - if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) { - output(opt, 1, _("Failed to merge submodule %s (not checked out)"), path); - return 0; - } - - if (!(commit_base = lookup_commit_reference(&subrepo, base)) || - !(commit_a = lookup_commit_reference(&subrepo, a)) || - !(commit_b = lookup_commit_reference(&subrepo, b))) { - output(opt, 1, _("Failed to merge submodule %s (commits not present)"), path); - goto cleanup; - } - - /* check whether both changes are forward */ - 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 */ - 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); - repo_output_commit_title(opt, &subrepo, commit_b); - } else if (show(opt, 2)) - output(opt, 2, _("Fast-forwarding submodule %s"), path); - else - ; /* no output */ - - ret = 1; - goto cleanup; - } - 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); - repo_output_commit_title(opt, &subrepo, commit_a); - } else if (show(opt, 2)) - output(opt, 2, _("Fast-forwarding submodule %s"), path); - else - ; /* no output */ - - ret = 1; - goto cleanup; - } - - /* - * Case #2: There are one or more merges that contain a and b in - * the submodule. If there is only one, then present it as a - * suggestion to the user, but leave it marked unmerged so the - * user needs to confirm the resolution. - */ - - /* Skip the search if makes no sense to the calling context. */ - if (!search) - goto cleanup; - - /* find commit which merges them */ - 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; - - case 1: - output(opt, 1, _("Failed to merge submodule %s (not fast-forward)"), path); - output(opt, 2, _("Found a possible merge resolution for the submodule:\n")); - print_commit(&subrepo, (struct commit *) merges.objects[0].item); - output(opt, 2, _( - "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"), - oid_to_hex(&merges.objects[0].item->oid), path); - break; - - default: - output(opt, 1, _("Failed to merge submodule %s (multiple merges found)"), path); - for (i = 0; i < merges.nr; i++) - print_commit(&subrepo, (struct commit *) merges.objects[i].item); - } - - object_array_clear(&merges); -cleanup: - repo_clear(&subrepo); - return ret; -} - -static int merge_mode_and_contents(struct merge_options *opt, - const struct diff_filespec *o, - const struct diff_filespec *a, - const struct diff_filespec *b, - const char *filename, - const char *branch1, - const char *branch2, - const int extra_marker_size, - struct merge_file_info *result) -{ - if (opt->branch1 != branch1) { - /* - * It's weird getting a reverse merge with HEAD on the bottom - * side of the conflict markers and the other branch on the - * top. Fix that. - */ - return merge_mode_and_contents(opt, o, b, a, - filename, - branch2, branch1, - extra_marker_size, result); - } - - result->merge = 0; - result->clean = 1; - - if ((S_IFMT & a->mode) != (S_IFMT & b->mode)) { - result->clean = 0; - /* - * FIXME: This is a bad resolution for recursive case; for - * the recursive case we want something that is unlikely to - * accidentally match either side. Also, while it makes - * sense to prefer regular files over symlinks, it doesn't - * make sense to prefer regular files over submodules. - */ - if (S_ISREG(a->mode)) { - result->blob.mode = a->mode; - oidcpy(&result->blob.oid, &a->oid); - } else { - result->blob.mode = b->mode; - oidcpy(&result->blob.oid, &b->oid); - } - } else { - if (!oideq(&a->oid, &o->oid) && !oideq(&b->oid, &o->oid)) - result->merge = 1; - - /* - * Merge modes - */ - if (a->mode == b->mode || a->mode == o->mode) - result->blob.mode = b->mode; - else { - result->blob.mode = a->mode; - if (b->mode != o->mode) { - result->clean = 0; - result->merge = 1; - } - } - - if (oideq(&a->oid, &b->oid) || oideq(&a->oid, &o->oid)) - oidcpy(&result->blob.oid, &b->oid); - else if (oideq(&b->oid, &o->oid)) - oidcpy(&result->blob.oid, &a->oid); - else if (S_ISREG(a->mode)) { - mmbuffer_t result_buf; - int ret = 0, merge_status; - - merge_status = merge_3way(opt, &result_buf, o, a, b, - branch1, branch2, - extra_marker_size); - - if ((merge_status < 0) || !result_buf.ptr) - ret = err(opt, _("failed to execute internal merge")); - - if (!ret && - write_object_file(result_buf.ptr, result_buf.size, - OBJ_BLOB, &result->blob.oid)) - ret = err(opt, _("unable to add %s to database"), - a->path); - - free(result_buf.ptr); - if (ret) - return ret; - /* FIXME: bug, what if modes didn't match? */ - result->clean = (merge_status == 0); - } else if (S_ISGITLINK(a->mode)) { - 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: - oidcpy(&result->blob.oid, &a->oid); - if (!oideq(&a->oid, &b->oid)) - result->clean = 0; - break; - case MERGE_VARIANT_OURS: - oidcpy(&result->blob.oid, &a->oid); - break; - case MERGE_VARIANT_THEIRS: - oidcpy(&result->blob.oid, &b->oid); - break; - } - } else - BUG("unsupported object type in the tree"); - } - - if (result->merge) - output(opt, 2, _("Auto-merging %s"), filename); - - return 0; -} - -static int handle_rename_via_dir(struct merge_options *opt, - struct rename_conflict_info *ci) -{ - /* - * Handle file adds that need to be renamed due to directory rename - * detection. This differs from handle_rename_normal, because - * there is no content merge to do; just move the file into the - * desired final location. - */ - const struct rename *ren = ci->ren1; - const struct diff_filespec *dest = ren->pair->two; - char *file_path = dest->path; - int mark_conflicted = (opt->detect_directory_renames == - MERGE_DIRECTORY_RENAMES_CONFLICT); - assert(ren->dir_rename_original_dest); - - if (!opt->priv->call_depth && would_lose_untracked(opt, dest->path)) { - mark_conflicted = 1; - file_path = unique_path(opt, dest->path, ren->branch); - output(opt, 1, _("Error: Refusing to lose untracked file at %s; " - "writing to %s instead."), - dest->path, file_path); - } - - if (mark_conflicted) { - /* - * Write the file in worktree at file_path. In the index, - * only record the file at dest->path in the appropriate - * higher stage. - */ - if (update_file(opt, 0, dest, file_path)) - return -1; - if (file_path != dest->path) - free(file_path); - if (update_stages(opt, dest->path, NULL, - ren->branch == opt->branch1 ? dest : NULL, - ren->branch == opt->branch1 ? NULL : dest)) - return -1; - return 0; /* not clean, but conflicted */ - } else { - /* Update dest->path both in index and in worktree */ - if (update_file(opt, 1, dest, dest->path)) - return -1; - return 1; /* clean */ - } -} - -static int handle_change_delete(struct merge_options *opt, - const char *path, const char *old_path, - const struct diff_filespec *o, - const struct diff_filespec *changed, - const char *change_branch, - const char *delete_branch, - const char *change, const char *change_past) -{ - char *alt_path = NULL; - const char *update_path = path; - int ret = 0; - - if (dir_in_way(opt->repo->index, path, !opt->priv->call_depth, 0) || - (!opt->priv->call_depth && would_lose_untracked(opt, path))) { - update_path = alt_path = unique_path(opt, path, change_branch); - } - - if (opt->priv->call_depth) { - /* - * We cannot arbitrarily accept either a_sha or b_sha as - * correct; since there is no true "middle point" between - * them, simply reuse the base version for virtual merge base. - */ - ret = remove_file_from_index(opt->repo->index, path); - if (!ret) - ret = update_file(opt, 0, o, update_path); - } else { - /* - * Despite the four nearly duplicate messages and argument - * lists below and the ugliness of the nested if-statements, - * having complete messages makes the job easier for - * translators. - * - * The slight variance among the cases is due to the fact - * that: - * 1) directory/file conflicts (in effect if - * !alt_path) could cause us to need to write the - * file to a different path. - * 2) renames (in effect if !old_path) could mean that - * there are two names for the path that the user - * may know the file by. - */ - if (!alt_path) { - if (!old_path) { - output(opt, 1, _("CONFLICT (%s/delete): %s deleted in %s " - "and %s in %s. Version %s of %s left in tree."), - change, path, delete_branch, change_past, - change_branch, change_branch, path); - } else { - output(opt, 1, _("CONFLICT (%s/delete): %s deleted in %s " - "and %s to %s in %s. Version %s of %s left in tree."), - change, old_path, delete_branch, change_past, path, - change_branch, change_branch, path); - } - } else { - if (!old_path) { - output(opt, 1, _("CONFLICT (%s/delete): %s deleted in %s " - "and %s in %s. Version %s of %s left in tree at %s."), - change, path, delete_branch, change_past, - change_branch, change_branch, path, alt_path); - } else { - output(opt, 1, _("CONFLICT (%s/delete): %s deleted in %s " - "and %s to %s in %s. Version %s of %s left in tree at %s."), - change, old_path, delete_branch, change_past, path, - change_branch, change_branch, path, alt_path); - } - } - /* - * No need to call update_file() on path when change_branch == - * opt->branch1 && !alt_path, since that would needlessly touch - * path. We could call update_file_flags() with update_cache=0 - * and update_wd=0, but that's a no-op. - */ - if (change_branch != opt->branch1 || alt_path) - ret = update_file(opt, 0, changed, update_path); - } - free(alt_path); - - return ret; -} - -static int handle_rename_delete(struct merge_options *opt, - struct rename_conflict_info *ci) -{ - const struct rename *ren = ci->ren1; - const struct diff_filespec *orig = ren->pair->one; - const struct diff_filespec *dest = ren->pair->two; - const char *rename_branch = ren->branch; - const char *delete_branch = (opt->branch1 == ren->branch ? - opt->branch2 : opt->branch1); - - if (handle_change_delete(opt, - opt->priv->call_depth ? orig->path : dest->path, - opt->priv->call_depth ? NULL : orig->path, - orig, dest, - rename_branch, delete_branch, - _("rename"), _("renamed"))) - return -1; - - if (opt->priv->call_depth) - return remove_file_from_index(opt->repo->index, dest->path); - else - return update_stages(opt, dest->path, NULL, - rename_branch == opt->branch1 ? dest : NULL, - rename_branch == opt->branch1 ? NULL : dest); -} - -static int handle_file_collision(struct merge_options *opt, - const char *collide_path, - const char *prev_path1, - const char *prev_path2, - const char *branch1, const char *branch2, - struct diff_filespec *a, - struct diff_filespec *b) -{ - struct merge_file_info mfi; - struct diff_filespec null; - char *alt_path = NULL; - const char *update_path = collide_path; - - /* - * It's easiest to get the correct things into stage 2 and 3, and - * to make sure that the content merge puts HEAD before the other - * branch if we just ensure that branch1 == opt->branch1. So, simply - * flip arguments around if we don't have that. - */ - if (branch1 != opt->branch1) { - return handle_file_collision(opt, collide_path, - prev_path2, prev_path1, - branch2, branch1, - b, a); - } - - /* Remove rename sources if rename/add or rename/rename(2to1) */ - if (prev_path1) - remove_file(opt, 1, prev_path1, - opt->priv->call_depth || would_lose_untracked(opt, prev_path1)); - if (prev_path2) - remove_file(opt, 1, prev_path2, - opt->priv->call_depth || would_lose_untracked(opt, prev_path2)); - - /* - * Remove the collision path, if it wouldn't cause dirty contents - * or an untracked file to get lost. We'll either overwrite with - * merged contents, or just write out to differently named files. - */ - if (was_dirty(opt, collide_path)) { - output(opt, 1, _("Refusing to lose dirty file at %s"), - collide_path); - update_path = alt_path = unique_path(opt, collide_path, "merged"); - } else if (would_lose_untracked(opt, collide_path)) { - /* - * Only way we get here is if both renames were from - * a directory rename AND user had an untracked file - * at the location where both files end up after the - * two directory renames. See testcase 10d of t6043. - */ - output(opt, 1, _("Refusing to lose untracked file at " - "%s, even though it's in the way."), - collide_path); - update_path = alt_path = unique_path(opt, collide_path, "merged"); - } else { - /* - * FIXME: It's possible that the two files are identical - * and that the current working copy happens to match, in - * which case we are unnecessarily touching the working - * tree file. It's not a likely enough scenario that I - * want to code up the checks for it and a better fix is - * available if we restructure how unpack_trees() and - * merge-recursive interoperate anyway, so punting for - * now... - */ - remove_file(opt, 0, collide_path, 0); - } - - /* Store things in diff_filespecs for functions that need it */ - null.path = (char *)collide_path; - oidcpy(&null.oid, null_oid()); - null.mode = 0; - - if (merge_mode_and_contents(opt, &null, a, b, collide_path, - branch1, branch2, opt->priv->call_depth * 2, &mfi)) - return -1; - mfi.clean &= !alt_path; - if (update_file(opt, mfi.clean, &mfi.blob, update_path)) - return -1; - if (!mfi.clean && !opt->priv->call_depth && - update_stages(opt, collide_path, NULL, a, b)) - return -1; - free(alt_path); - /* - * FIXME: If both a & b both started with conflicts (only possible - * if they came from a rename/rename(2to1)), but had IDENTICAL - * contents including those conflicts, then in the next line we claim - * it was clean. If someone cares about this case, we should have the - * caller notify us if we started with conflicts. - */ - return mfi.clean; -} - -static int handle_rename_add(struct merge_options *opt, - struct rename_conflict_info *ci) -{ - /* a was renamed to c, and a separate c was added. */ - struct diff_filespec *a = ci->ren1->pair->one; - struct diff_filespec *c = ci->ren1->pair->two; - char *path = c->path; - char *prev_path_desc; - struct merge_file_info mfi; - - const char *rename_branch = ci->ren1->branch; - const char *add_branch = (opt->branch1 == rename_branch ? - opt->branch2 : opt->branch1); - int other_stage = (ci->ren1->branch == opt->branch1 ? 3 : 2); - - output(opt, 1, _("CONFLICT (rename/add): " - "Rename %s->%s in %s. Added %s in %s"), - a->path, c->path, rename_branch, - c->path, add_branch); - - prev_path_desc = xstrfmt("version of %s from %s", path, a->path); - ci->ren1->src_entry->stages[other_stage].path = a->path; - if (merge_mode_and_contents(opt, a, c, - &ci->ren1->src_entry->stages[other_stage], - prev_path_desc, - opt->branch1, opt->branch2, - 1 + opt->priv->call_depth * 2, &mfi)) - return -1; - free(prev_path_desc); - - ci->ren1->dst_entry->stages[other_stage].path = mfi.blob.path = c->path; - return handle_file_collision(opt, - c->path, a->path, NULL, - rename_branch, add_branch, - &mfi.blob, - &ci->ren1->dst_entry->stages[other_stage]); -} - -static char *find_path_for_conflict(struct merge_options *opt, - const char *path, - const char *branch1, - const char *branch2) -{ - char *new_path = NULL; - if (dir_in_way(opt->repo->index, path, !opt->priv->call_depth, 0)) { - new_path = unique_path(opt, path, branch1); - output(opt, 1, _("%s is a directory in %s adding " - "as %s instead"), - path, branch2, new_path); - } else if (would_lose_untracked(opt, path)) { - new_path = unique_path(opt, path, branch1); - output(opt, 1, _("Refusing to lose untracked file" - " at %s; adding as %s instead"), - path, new_path); - } - - return new_path; -} - -/* - * Toggle the stage number between "ours" and "theirs" (2 and 3). - */ -static inline int flip_stage(int stage) -{ - return (2 + 3) - stage; -} - -static int handle_rename_rename_1to2(struct merge_options *opt, - struct rename_conflict_info *ci) -{ - /* One file was renamed in both branches, but to different names. */ - struct merge_file_info mfi; - struct diff_filespec *add; - struct diff_filespec *o = ci->ren1->pair->one; - struct diff_filespec *a = ci->ren1->pair->two; - struct diff_filespec *b = ci->ren2->pair->two; - char *path_desc; - - output(opt, 1, _("CONFLICT (rename/rename): " - "Rename \"%s\"->\"%s\" in branch \"%s\" " - "rename \"%s\"->\"%s\" in \"%s\"%s"), - o->path, a->path, ci->ren1->branch, - o->path, b->path, ci->ren2->branch, - opt->priv->call_depth ? _(" (left unresolved)") : ""); - - path_desc = xstrfmt("%s and %s, both renamed from %s", - a->path, b->path, o->path); - if (merge_mode_and_contents(opt, o, a, b, path_desc, - ci->ren1->branch, ci->ren2->branch, - opt->priv->call_depth * 2, &mfi)) - return -1; - free(path_desc); - - if (opt->priv->call_depth) - remove_file_from_index(opt->repo->index, o->path); - - /* - * For each destination path, we need to see if there is a - * rename/add collision. If not, we can write the file out - * to the specified location. - */ - add = &ci->ren1->dst_entry->stages[flip_stage(2)]; - if (is_valid(add)) { - add->path = mfi.blob.path = a->path; - if (handle_file_collision(opt, a->path, - NULL, NULL, - ci->ren1->branch, - ci->ren2->branch, - &mfi.blob, add) < 0) - return -1; - } else { - char *new_path = find_path_for_conflict(opt, a->path, - ci->ren1->branch, - ci->ren2->branch); - if (update_file(opt, 0, &mfi.blob, - new_path ? new_path : a->path)) - return -1; - free(new_path); - if (!opt->priv->call_depth && - update_stages(opt, a->path, NULL, a, NULL)) - return -1; - } - - if (!mfi.clean && mfi.blob.mode == a->mode && - oideq(&mfi.blob.oid, &a->oid)) { - /* - * Getting here means we were attempting to merge a binary - * blob. Since we can't merge binaries, the merge algorithm - * just takes one side. But we don't want to copy the - * contents of one side to both paths; we'd rather use the - * original content at the given path for each path. - */ - oidcpy(&mfi.blob.oid, &b->oid); - mfi.blob.mode = b->mode; - } - add = &ci->ren2->dst_entry->stages[flip_stage(3)]; - if (is_valid(add)) { - add->path = mfi.blob.path = b->path; - if (handle_file_collision(opt, b->path, - NULL, NULL, - ci->ren1->branch, - ci->ren2->branch, - add, &mfi.blob) < 0) - return -1; - } else { - char *new_path = find_path_for_conflict(opt, b->path, - ci->ren2->branch, - ci->ren1->branch); - if (update_file(opt, 0, &mfi.blob, - new_path ? new_path : b->path)) - return -1; - free(new_path); - if (!opt->priv->call_depth && - update_stages(opt, b->path, NULL, NULL, b)) - return -1; - } - - return 0; -} - -static int handle_rename_rename_2to1(struct merge_options *opt, - struct rename_conflict_info *ci) -{ - /* Two files, a & b, were renamed to the same thing, c. */ - struct diff_filespec *a = ci->ren1->pair->one; - struct diff_filespec *b = ci->ren2->pair->one; - struct diff_filespec *c1 = ci->ren1->pair->two; - struct diff_filespec *c2 = ci->ren2->pair->two; - char *path = c1->path; /* == c2->path */ - char *path_side_1_desc; - char *path_side_2_desc; - struct merge_file_info mfi_c1; - struct merge_file_info mfi_c2; - int ostage1, ostage2; - - output(opt, 1, _("CONFLICT (rename/rename): " - "Rename %s->%s in %s. " - "Rename %s->%s in %s"), - a->path, c1->path, ci->ren1->branch, - b->path, c2->path, ci->ren2->branch); - - path_side_1_desc = xstrfmt("version of %s from %s", path, a->path); - path_side_2_desc = xstrfmt("version of %s from %s", path, b->path); - ostage1 = ci->ren1->branch == opt->branch1 ? 3 : 2; - ostage2 = flip_stage(ostage1); - ci->ren1->src_entry->stages[ostage1].path = a->path; - ci->ren2->src_entry->stages[ostage2].path = b->path; - if (merge_mode_and_contents(opt, a, c1, - &ci->ren1->src_entry->stages[ostage1], - path_side_1_desc, - opt->branch1, opt->branch2, - 1 + opt->priv->call_depth * 2, &mfi_c1) || - merge_mode_and_contents(opt, b, - &ci->ren2->src_entry->stages[ostage2], - c2, path_side_2_desc, - opt->branch1, opt->branch2, - 1 + opt->priv->call_depth * 2, &mfi_c2)) - return -1; - free(path_side_1_desc); - free(path_side_2_desc); - mfi_c1.blob.path = path; - mfi_c2.blob.path = path; - - return handle_file_collision(opt, path, a->path, b->path, - ci->ren1->branch, ci->ren2->branch, - &mfi_c1.blob, &mfi_c2.blob); -} - -/* - * Get the diff_filepairs changed between o_tree and tree. - */ -static struct diff_queue_struct *get_diffpairs(struct merge_options *opt, - struct tree *o_tree, - struct tree *tree) -{ - struct diff_queue_struct *ret; - struct diff_options opts; - - repo_diff_setup(opt->repo, &opts); - opts.flags.recursive = 1; - opts.flags.rename_empty = 0; - opts.detect_rename = merge_detect_rename(opt); - /* - * We do not have logic to handle the detection of copies. In - * fact, it may not even make sense to add such logic: would we - * really want a change to a base file to be propagated through - * multiple other files by a merge? - */ - if (opts.detect_rename > DIFF_DETECT_RENAME) - opts.detect_rename = DIFF_DETECT_RENAME; - opts.rename_limit = (opt->rename_limit >= 0) ? opt->rename_limit : 7000; - opts.rename_score = opt->rename_score; - opts.show_rename_progress = opt->show_rename_progress; - opts.output_format = DIFF_FORMAT_NO_OUTPUT; - diff_setup_done(&opts); - diff_tree_oid(&o_tree->object.oid, &tree->object.oid, "", &opts); - diffcore_std(&opts); - if (opts.needed_rename_limit > opt->priv->needed_rename_limit) - opt->priv->needed_rename_limit = opts.needed_rename_limit; - - ret = xmalloc(sizeof(*ret)); - *ret = diff_queued_diff; - - opts.output_format = DIFF_FORMAT_NO_OUTPUT; - diff_queued_diff.nr = 0; - diff_queued_diff.queue = NULL; - diff_flush(&opts); - return ret; -} - -static int tree_has_path(struct repository *r, struct tree *tree, - const char *path) -{ - struct object_id hashy; - unsigned short mode_o; - - return !get_tree_entry(r, - &tree->object.oid, path, - &hashy, &mode_o); -} - -/* - * Return a new string that replaces the beginning portion (which matches - * entry->dir), with entry->new_dir. In perl-speak: - * new_path_name = (old_path =~ s/entry->dir/entry->new_dir/); - * NOTE: - * Caller must ensure that old_path starts with entry->dir + '/'. - */ -static char *apply_dir_rename(struct dir_rename_entry *entry, - const char *old_path) -{ - struct strbuf new_path = STRBUF_INIT; - int oldlen, newlen; - - if (entry->non_unique_new_dir) - return NULL; - - oldlen = strlen(entry->dir); - if (entry->new_dir.len == 0) - /* - * If someone renamed/merged a subdirectory into the root - * directory (e.g. 'some/subdir' -> ''), then we want to - * avoid returning - * '' + '/filename' - * as the rename; we need to make old_path + oldlen advance - * past the '/' character. - */ - oldlen++; - newlen = entry->new_dir.len + (strlen(old_path) - oldlen) + 1; - strbuf_grow(&new_path, newlen); - strbuf_addbuf(&new_path, &entry->new_dir); - strbuf_addstr(&new_path, &old_path[oldlen]); - - return strbuf_detach(&new_path, NULL); -} - -static void get_renamed_dir_portion(const char *old_path, const char *new_path, - char **old_dir, char **new_dir) -{ - char *end_of_old, *end_of_new; - - /* Default return values: NULL, meaning no rename */ - *old_dir = NULL; - *new_dir = NULL; - - /* - * For - * "a/b/c/d/e/foo.c" -> "a/b/some/thing/else/e/foo.c" - * the "e/foo.c" part is the same, we just want to know that - * "a/b/c/d" was renamed to "a/b/some/thing/else" - * so, for this example, this function returns "a/b/c/d" in - * *old_dir and "a/b/some/thing/else" in *new_dir. - */ - - /* - * If the basename of the file changed, we don't care. We want - * to know which portion of the directory, if any, changed. - */ - end_of_old = strrchr(old_path, '/'); - end_of_new = strrchr(new_path, '/'); - - /* - * If end_of_old is NULL, old_path wasn't in a directory, so there - * could not be a directory rename (our rule elsewhere that a - * directory which still exists is not considered to have been - * renamed means the root directory can never be renamed -- because - * the root directory always exists). - */ - if (!end_of_old) - return; /* Note: *old_dir and *new_dir are still NULL */ - - /* - * If new_path contains no directory (end_of_new is NULL), then we - * have a rename of old_path's directory to the root directory. - */ - if (!end_of_new) { - *old_dir = xstrndup(old_path, end_of_old - old_path); - *new_dir = xstrdup(""); - return; - } - - /* Find the first non-matching character traversing backwards */ - while (*--end_of_new == *--end_of_old && - end_of_old != old_path && - end_of_new != new_path) - ; /* Do nothing; all in the while loop */ - - /* - * If both got back to the beginning of their strings, then the - * directory didn't change at all, only the basename did. - */ - if (end_of_old == old_path && end_of_new == new_path && - *end_of_old == *end_of_new) - return; /* Note: *old_dir and *new_dir are still NULL */ - - /* - * If end_of_new got back to the beginning of its string, and - * end_of_old got back to the beginning of some subdirectory, then - * we have a rename/merge of a subdirectory into the root, which - * needs slightly special handling. - * - * Note: There is no need to consider the opposite case, with a - * rename/merge of the root directory into some subdirectory - * because as noted above the root directory always exists so it - * cannot be considered to be renamed. - */ - if (end_of_new == new_path && - end_of_old != old_path && end_of_old[-1] == '/') { - *old_dir = xstrndup(old_path, --end_of_old - old_path); - *new_dir = xstrdup(""); - return; - } - - /* - * We've found the first non-matching character in the directory - * paths. That means the current characters we were looking at - * were part of the first non-matching subdir name going back from - * the end of the strings. Get the whole name by advancing both - * end_of_old and end_of_new to the NEXT '/' character. That will - * represent the entire directory rename. - * - * The reason for the increment is cases like - * a/b/star/foo/whatever.c -> a/b/tar/foo/random.c - * After dropping the basename and going back to the first - * non-matching character, we're now comparing: - * a/b/s and a/b/ - * and we want to be comparing: - * a/b/star/ and a/b/tar/ - * but without the pre-increment, the one on the right would stay - * a/b/. - */ - end_of_old = strchr(++end_of_old, '/'); - end_of_new = strchr(++end_of_new, '/'); - - /* Copy the old and new directories into *old_dir and *new_dir. */ - *old_dir = xstrndup(old_path, end_of_old - old_path); - *new_dir = xstrndup(new_path, end_of_new - new_path); -} - -static void remove_hashmap_entries(struct hashmap *dir_renames, - struct string_list *items_to_remove) -{ - int i; - struct dir_rename_entry *entry; - - for (i = 0; i < items_to_remove->nr; i++) { - entry = items_to_remove->items[i].util; - hashmap_remove(dir_renames, &entry->ent, NULL); - } - string_list_clear(items_to_remove, 0); -} - -/* - * See if there is a directory rename for path, and if there are any file - * level conflicts for the renamed location. If there is a rename and - * there are no conflicts, return the new name. Otherwise, return NULL. - */ -static char *handle_path_level_conflicts(struct merge_options *opt, - const char *path, - struct dir_rename_entry *entry, - struct hashmap *collisions, - struct tree *tree) -{ - char *new_path = NULL; - struct collision_entry *collision_ent; - int clean = 1; - struct strbuf collision_paths = STRBUF_INIT; - - /* - * entry has the mapping of old directory name to new directory name - * that we want to apply to path. - */ - new_path = apply_dir_rename(entry, path); - - if (!new_path) { - /* This should only happen when entry->non_unique_new_dir set */ - if (!entry->non_unique_new_dir) - BUG("entry->non_unique_new_dir not set and !new_path"); - output(opt, 1, _("CONFLICT (directory rename split): " - "Unclear where to place %s because directory " - "%s was renamed to multiple other directories, " - "with no destination getting a majority of the " - "files."), - path, entry->dir); - clean = 0; - return NULL; - } - - /* - * The caller needs to have ensured that it has pre-populated - * collisions with all paths that map to new_path. Do a quick check - * to ensure that's the case. - */ - collision_ent = collision_find_entry(collisions, new_path); - if (!collision_ent) - BUG("collision_ent is NULL"); - - /* - * Check for one-sided add/add/.../add conflicts, i.e. - * where implicit renames from the other side doing - * directory rename(s) can affect this side of history - * to put multiple paths into the same location. Warn - * and bail on directory renames for such paths. - */ - if (collision_ent->reported_already) { - clean = 0; - } else if (tree_has_path(opt->repo, tree, new_path)) { - collision_ent->reported_already = 1; - strbuf_add_separated_string_list(&collision_paths, ", ", - &collision_ent->source_files); - output(opt, 1, _("CONFLICT (implicit dir rename): Existing " - "file/dir at %s in the way of implicit " - "directory rename(s) putting the following " - "path(s) there: %s."), - new_path, collision_paths.buf); - clean = 0; - } else if (collision_ent->source_files.nr > 1) { - collision_ent->reported_already = 1; - strbuf_add_separated_string_list(&collision_paths, ", ", - &collision_ent->source_files); - output(opt, 1, _("CONFLICT (implicit dir rename): Cannot map " - "more than one path to %s; implicit directory " - "renames tried to put these paths there: %s"), - new_path, collision_paths.buf); - clean = 0; - } - - /* Free memory we no longer need */ - strbuf_release(&collision_paths); - if (!clean && new_path) { - free(new_path); - return NULL; - } - - return new_path; -} - -/* - * There are a couple things we want to do at the directory level: - * 1. Check for both sides renaming to the same thing, in order to avoid - * implicit renaming of files that should be left in place. (See - * testcase 6b in t6043 for details.) - * 2. Prune directory renames if there are still files left in the - * original directory. These represent a partial directory rename, - * i.e. a rename where only some of the files within the directory - * were renamed elsewhere. (Technically, this could be done earlier - * in get_directory_renames(), except that would prevent us from - * doing the previous check and thus failing testcase 6b.) - * 3. Check for rename/rename(1to2) conflicts (at the directory level). - * In the future, we could potentially record this info as well and - * omit reporting rename/rename(1to2) conflicts for each path within - * the affected directories, thus cleaning up the merge output. - * NOTE: We do NOT check for rename/rename(2to1) conflicts at the - * directory level, because merging directories is fine. If it - * causes conflicts for files within those merged directories, then - * that should be detected at the individual path level. - */ -static void handle_directory_level_conflicts(struct merge_options *opt, - struct hashmap *dir_re_head, - struct tree *head, - struct hashmap *dir_re_merge, - struct tree *merge) -{ - struct hashmap_iter iter; - struct dir_rename_entry *head_ent; - struct dir_rename_entry *merge_ent; - - struct string_list remove_from_head = STRING_LIST_INIT_NODUP; - struct string_list remove_from_merge = STRING_LIST_INIT_NODUP; - - hashmap_for_each_entry(dir_re_head, &iter, head_ent, - ent /* member name */) { - merge_ent = dir_rename_find_entry(dir_re_merge, head_ent->dir); - if (merge_ent && - !head_ent->non_unique_new_dir && - !merge_ent->non_unique_new_dir && - !strbuf_cmp(&head_ent->new_dir, &merge_ent->new_dir)) { - /* 1. Renamed identically; remove it from both sides */ - string_list_append(&remove_from_head, - head_ent->dir)->util = head_ent; - strbuf_release(&head_ent->new_dir); - string_list_append(&remove_from_merge, - merge_ent->dir)->util = merge_ent; - strbuf_release(&merge_ent->new_dir); - } else if (tree_has_path(opt->repo, head, head_ent->dir)) { - /* 2. This wasn't a directory rename after all */ - string_list_append(&remove_from_head, - head_ent->dir)->util = head_ent; - strbuf_release(&head_ent->new_dir); - } - } - - remove_hashmap_entries(dir_re_head, &remove_from_head); - remove_hashmap_entries(dir_re_merge, &remove_from_merge); - - hashmap_for_each_entry(dir_re_merge, &iter, merge_ent, - ent /* member name */) { - head_ent = dir_rename_find_entry(dir_re_head, merge_ent->dir); - if (tree_has_path(opt->repo, merge, merge_ent->dir)) { - /* 2. This wasn't a directory rename after all */ - string_list_append(&remove_from_merge, - merge_ent->dir)->util = merge_ent; - } else if (head_ent && - !head_ent->non_unique_new_dir && - !merge_ent->non_unique_new_dir) { - /* 3. rename/rename(1to2) */ - /* - * We can assume it's not rename/rename(1to1) because - * that was case (1), already checked above. So we - * know that head_ent->new_dir and merge_ent->new_dir - * are different strings. - */ - output(opt, 1, _("CONFLICT (rename/rename): " - "Rename directory %s->%s in %s. " - "Rename directory %s->%s in %s"), - head_ent->dir, head_ent->new_dir.buf, opt->branch1, - head_ent->dir, merge_ent->new_dir.buf, opt->branch2); - string_list_append(&remove_from_head, - head_ent->dir)->util = head_ent; - strbuf_release(&head_ent->new_dir); - string_list_append(&remove_from_merge, - merge_ent->dir)->util = merge_ent; - strbuf_release(&merge_ent->new_dir); - } - } - - remove_hashmap_entries(dir_re_head, &remove_from_head); - remove_hashmap_entries(dir_re_merge, &remove_from_merge); -} - -static struct hashmap *get_directory_renames(struct diff_queue_struct *pairs) -{ - struct hashmap *dir_renames; - struct hashmap_iter iter; - struct dir_rename_entry *entry; - int i; - - /* - * Typically, we think of a directory rename as all files from a - * certain directory being moved to a target directory. However, - * what if someone first moved two files from the original - * directory in one commit, and then renamed the directory - * somewhere else in a later commit? At merge time, we just know - * that files from the original directory went to two different - * places, and that the bulk of them ended up in the same place. - * We want each directory rename to represent where the bulk of the - * files from that directory end up; this function exists to find - * where the bulk of the files went. - * - * The first loop below simply iterates through the list of file - * renames, finding out how often each directory rename pair - * possibility occurs. - */ - dir_renames = xmalloc(sizeof(*dir_renames)); - dir_rename_init(dir_renames); - for (i = 0; i < pairs->nr; ++i) { - struct string_list_item *item; - int *count; - struct diff_filepair *pair = pairs->queue[i]; - char *old_dir, *new_dir; - - /* File not part of directory rename if it wasn't renamed */ - if (pair->status != 'R') - continue; - - get_renamed_dir_portion(pair->one->path, pair->two->path, - &old_dir, &new_dir); - if (!old_dir) - /* Directory didn't change at all; ignore this one. */ - continue; - - entry = dir_rename_find_entry(dir_renames, old_dir); - if (!entry) { - entry = xmalloc(sizeof(*entry)); - dir_rename_entry_init(entry, old_dir); - hashmap_put(dir_renames, &entry->ent); - } else { - free(old_dir); - } - item = string_list_lookup(&entry->possible_new_dirs, new_dir); - if (!item) { - item = string_list_insert(&entry->possible_new_dirs, - new_dir); - item->util = xcalloc(1, sizeof(int)); - } else { - free(new_dir); - } - count = item->util; - *count += 1; - } - - /* - * For each directory with files moved out of it, we find out which - * target directory received the most files so we can declare it to - * be the "winning" target location for the directory rename. This - * winner gets recorded in new_dir. If there is no winner - * (multiple target directories received the same number of files), - * we set non_unique_new_dir. Once we've determined the winner (or - * that there is no winner), we no longer need possible_new_dirs. - */ - hashmap_for_each_entry(dir_renames, &iter, entry, - ent /* member name */) { - int max = 0; - int bad_max = 0; - char *best = NULL; - - for (i = 0; i < entry->possible_new_dirs.nr; i++) { - int *count = entry->possible_new_dirs.items[i].util; - - if (*count == max) - bad_max = max; - else if (*count > max) { - max = *count; - best = entry->possible_new_dirs.items[i].string; - } - } - if (bad_max == max) - entry->non_unique_new_dir = 1; - else { - assert(entry->new_dir.len == 0); - strbuf_addstr(&entry->new_dir, best); - } - /* - * The relevant directory sub-portion of the original full - * filepaths were xstrndup'ed before inserting into - * possible_new_dirs, and instead of manually iterating the - * list and free'ing each, just lie and tell - * possible_new_dirs that it did the strdup'ing so that it - * will free them for us. - */ - entry->possible_new_dirs.strdup_strings = 1; - string_list_clear(&entry->possible_new_dirs, 1); - } - - return dir_renames; -} - -static struct dir_rename_entry *check_dir_renamed(const char *path, - struct hashmap *dir_renames) -{ - char *temp = xstrdup(path); - char *end; - struct dir_rename_entry *entry = NULL; - - while ((end = strrchr(temp, '/'))) { - *end = '\0'; - entry = dir_rename_find_entry(dir_renames, temp); - if (entry) - break; - } - free(temp); - return entry; -} - -static void compute_collisions(struct hashmap *collisions, - struct hashmap *dir_renames, - struct diff_queue_struct *pairs) -{ - int i; - - /* - * Multiple files can be mapped to the same path due to directory - * renames done by the other side of history. Since that other - * side of history could have merged multiple directories into one, - * if our side of history added the same file basename to each of - * those directories, then all N of them would get implicitly - * renamed by the directory rename detection into the same path, - * and we'd get an add/add/.../add conflict, and all those adds - * from *this* side of history. This is not representable in the - * index, and users aren't going to easily be able to make sense of - * it. So we need to provide a good warning about what's - * happening, and fall back to no-directory-rename detection - * behavior for those paths. - * - * See testcases 9e and all of section 5 from t6043 for examples. - */ - collision_init(collisions); - - for (i = 0; i < pairs->nr; ++i) { - struct dir_rename_entry *dir_rename_ent; - struct collision_entry *collision_ent; - char *new_path; - struct diff_filepair *pair = pairs->queue[i]; - - if (pair->status != 'A' && pair->status != 'R') - continue; - dir_rename_ent = check_dir_renamed(pair->two->path, - dir_renames); - if (!dir_rename_ent) - continue; - - new_path = apply_dir_rename(dir_rename_ent, pair->two->path); - if (!new_path) - /* - * dir_rename_ent->non_unique_new_path is true, which - * means there is no directory rename for us to use, - * which means it won't cause us any additional - * collisions. - */ - continue; - collision_ent = collision_find_entry(collisions, new_path); - if (!collision_ent) { - CALLOC_ARRAY(collision_ent, 1); - hashmap_entry_init(&collision_ent->ent, - strhash(new_path)); - hashmap_put(collisions, &collision_ent->ent); - collision_ent->target_file = new_path; - } else { - free(new_path); - } - string_list_insert(&collision_ent->source_files, - pair->two->path); - } -} - -static char *check_for_directory_rename(struct merge_options *opt, - const char *path, - struct tree *tree, - struct hashmap *dir_renames, - struct hashmap *dir_rename_exclusions, - struct hashmap *collisions, - int *clean_merge) -{ - char *new_path = NULL; - struct dir_rename_entry *entry = check_dir_renamed(path, dir_renames); - struct dir_rename_entry *oentry = NULL; - - if (!entry) - return new_path; - - /* - * This next part is a little weird. We do not want to do an - * implicit rename into a directory we renamed on our side, because - * that will result in a spurious rename/rename(1to2) conflict. An - * example: - * Base commit: dumbdir/afile, otherdir/bfile - * Side 1: smrtdir/afile, otherdir/bfile - * Side 2: dumbdir/afile, dumbdir/bfile - * Here, while working on Side 1, we could notice that otherdir was - * renamed/merged to dumbdir, and change the diff_filepair for - * otherdir/bfile into a rename into dumbdir/bfile. However, Side - * 2 will notice the rename from dumbdir to smrtdir, and do the - * transitive rename to move it from dumbdir/bfile to - * smrtdir/bfile. That gives us bfile in dumbdir vs being in - * smrtdir, a rename/rename(1to2) conflict. We really just want - * the file to end up in smrtdir. And the way to achieve that is - * to not let Side1 do the rename to dumbdir, since we know that is - * the source of one of our directory renames. - * - * That's why oentry and dir_rename_exclusions is here. - * - * As it turns out, this also prevents N-way transient rename - * confusion; See testcases 9c and 9d of t6043. - */ - oentry = dir_rename_find_entry(dir_rename_exclusions, entry->new_dir.buf); - if (oentry) { - output(opt, 1, _("WARNING: Avoiding applying %s -> %s rename " - "to %s, because %s itself was renamed."), - entry->dir, entry->new_dir.buf, path, entry->new_dir.buf); - } else { - new_path = handle_path_level_conflicts(opt, path, entry, - collisions, tree); - *clean_merge &= (new_path != NULL); - } - - return new_path; -} - -static void apply_directory_rename_modifications(struct merge_options *opt, - struct diff_filepair *pair, - char *new_path, - struct rename *re, - struct tree *tree, - struct tree *o_tree, - struct tree *a_tree, - struct tree *b_tree, - struct string_list *entries) -{ - struct string_list_item *item; - int stage = (tree == a_tree ? 2 : 3); - int update_wd; - - /* - * In all cases where we can do directory rename detection, - * unpack_trees() will have read pair->two->path into the - * index and the working copy. We need to remove it so that - * we can instead place it at new_path. It is guaranteed to - * not be untracked (unpack_trees() would have errored out - * saying the file would have been overwritten), but it might - * be dirty, though. - */ - update_wd = !was_dirty(opt, pair->two->path); - if (!update_wd) - output(opt, 1, _("Refusing to lose dirty file at %s"), - pair->two->path); - remove_file(opt, 1, pair->two->path, !update_wd); - - /* Find or create a new re->dst_entry */ - item = string_list_lookup(entries, new_path); - if (item) { - /* - * Since we're renaming on this side of history, and it's - * due to a directory rename on the other side of history - * (which we only allow when the directory in question no - * longer exists on the other side of history), the - * original entry for re->dst_entry is no longer - * necessary... - */ - re->dst_entry->processed = 1; - - /* - * ...because we'll be using this new one. - */ - re->dst_entry = item->util; - } else { - /* - * re->dst_entry is for the before-dir-rename path, and we - * need it to hold information for the after-dir-rename - * path. Before creating a new entry, we need to mark the - * old one as unnecessary (...unless it is shared by - * src_entry, i.e. this didn't use to be a rename, in which - * case we can just allow the normal processing to happen - * for it). - */ - if (pair->status == 'R') - re->dst_entry->processed = 1; - - re->dst_entry = insert_stage_data(opt->repo, new_path, - o_tree, a_tree, b_tree, - entries); - item = string_list_insert(entries, new_path); - item->util = re->dst_entry; - } - - /* - * Update the stage_data with the information about the path we are - * moving into place. That slot will be empty and available for us - * to write to because of the collision checks in - * handle_path_level_conflicts(). In other words, - * re->dst_entry->stages[stage].oid will be the null_oid, so it's - * open for us to write to. - * - * It may be tempting to actually update the index at this point as - * well, using update_stages_for_stage_data(), but as per the big - * "NOTE" in update_stages(), doing so will modify the current - * in-memory index which will break calls to would_lose_untracked() - * that we need to make. Instead, we need to just make sure that - * the various handle_rename_*() functions update the index - * explicitly rather than relying on unpack_trees() to have done it. - */ - get_tree_entry(opt->repo, - &tree->object.oid, - pair->two->path, - &re->dst_entry->stages[stage].oid, - &re->dst_entry->stages[stage].mode); - - /* - * Record the original change status (or 'type' of change). If it - * was originally an add ('A'), this lets us differentiate later - * between a RENAME_DELETE conflict and RENAME_VIA_DIR (they - * otherwise look the same). If it was originally a rename ('R'), - * this lets us remember and report accurately about the transitive - * renaming that occurred via the directory rename detection. Also, - * record the original destination name. - */ - re->dir_rename_original_type = pair->status; - re->dir_rename_original_dest = pair->two->path; - - /* - * We don't actually look at pair->status again, but it seems - * pedagogically correct to adjust it. - */ - pair->status = 'R'; - - /* - * Finally, record the new location. - */ - pair->two->path = new_path; -} - -/* - * Get information of all renames which occurred in 'pairs', making use of - * any implicit directory renames inferred from the other side of history. - * We need the three trees in the merge ('o_tree', 'a_tree' and 'b_tree') - * to be able to associate the correct cache entries with the rename - * information; tree is always equal to either a_tree or b_tree. - */ -static struct string_list *get_renames(struct merge_options *opt, - const char *branch, - struct diff_queue_struct *pairs, - struct hashmap *dir_renames, - struct hashmap *dir_rename_exclusions, - struct tree *tree, - struct tree *o_tree, - struct tree *a_tree, - struct tree *b_tree, - struct string_list *entries, - int *clean_merge) -{ - int i; - struct hashmap collisions; - struct hashmap_iter iter; - struct collision_entry *e; - struct string_list *renames; - - compute_collisions(&collisions, dir_renames, pairs); - CALLOC_ARRAY(renames, 1); - - for (i = 0; i < pairs->nr; ++i) { - struct string_list_item *item; - struct rename *re; - struct diff_filepair *pair = pairs->queue[i]; - char *new_path; /* non-NULL only with directory renames */ - - if (pair->status != 'A' && pair->status != 'R') { - diff_free_filepair(pair); - continue; - } - new_path = check_for_directory_rename(opt, pair->two->path, tree, - dir_renames, - dir_rename_exclusions, - &collisions, - clean_merge); - if (pair->status != 'R' && !new_path) { - diff_free_filepair(pair); - continue; - } - - re = xmalloc(sizeof(*re)); - re->processed = 0; - re->pair = pair; - re->branch = branch; - re->dir_rename_original_type = '\0'; - re->dir_rename_original_dest = NULL; - item = string_list_lookup(entries, re->pair->one->path); - if (!item) - re->src_entry = insert_stage_data(opt->repo, - re->pair->one->path, - o_tree, a_tree, b_tree, entries); - else - re->src_entry = item->util; - - item = string_list_lookup(entries, re->pair->two->path); - if (!item) - re->dst_entry = insert_stage_data(opt->repo, - re->pair->two->path, - o_tree, a_tree, b_tree, entries); - else - re->dst_entry = item->util; - item = string_list_insert(renames, pair->one->path); - item->util = re; - if (new_path) - apply_directory_rename_modifications(opt, pair, new_path, - re, tree, o_tree, - a_tree, b_tree, - entries); - } - - hashmap_for_each_entry(&collisions, &iter, e, - ent /* member name */) { - free(e->target_file); - string_list_clear(&e->source_files, 0); - } - hashmap_clear_and_free(&collisions, struct collision_entry, ent); - return renames; -} - -static int process_renames(struct merge_options *opt, - struct string_list *a_renames, - struct string_list *b_renames) -{ - int clean_merge = 1, i, j; - struct string_list a_by_dst = STRING_LIST_INIT_NODUP; - struct string_list b_by_dst = STRING_LIST_INIT_NODUP; - const struct rename *sre; - - /* - * Note that as we build the list, we do not need to check if the - * existing destination path is already in the list, because the - * structure of diffcore_rename guarantees we won't have duplicates. - */ - for (i = 0; i < a_renames->nr; i++) { - sre = a_renames->items[i].util; - string_list_append(&a_by_dst, sre->pair->two->path)->util - = (void *)sre; - } - for (i = 0; i < b_renames->nr; i++) { - sre = b_renames->items[i].util; - string_list_append(&b_by_dst, sre->pair->two->path)->util - = (void *)sre; - } - string_list_sort(&a_by_dst); - string_list_sort(&b_by_dst); - - for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) { - struct string_list *renames1, *renames2Dst; - struct rename *ren1 = NULL, *ren2 = NULL; - const char *ren1_src, *ren1_dst; - struct string_list_item *lookup; - - if (i >= a_renames->nr) { - ren2 = b_renames->items[j++].util; - } else if (j >= b_renames->nr) { - ren1 = a_renames->items[i++].util; - } else { - int compare = strcmp(a_renames->items[i].string, - b_renames->items[j].string); - if (compare <= 0) - ren1 = a_renames->items[i++].util; - if (compare >= 0) - ren2 = b_renames->items[j++].util; - } - - /* TODO: refactor, so that 1/2 are not needed */ - if (ren1) { - renames1 = a_renames; - renames2Dst = &b_by_dst; - } else { - renames1 = b_renames; - renames2Dst = &a_by_dst; - SWAP(ren2, ren1); - } - - if (ren1->processed) - continue; - ren1->processed = 1; - ren1->dst_entry->processed = 1; - /* BUG: We should only mark src_entry as processed if we - * are not dealing with a rename + add-source case. - */ - ren1->src_entry->processed = 1; - - ren1_src = ren1->pair->one->path; - ren1_dst = ren1->pair->two->path; - - if (ren2) { - /* One file renamed on both sides */ - const char *ren2_src = ren2->pair->one->path; - const char *ren2_dst = ren2->pair->two->path; - enum rename_type rename_type; - if (strcmp(ren1_src, ren2_src) != 0) - BUG("ren1_src != ren2_src"); - ren2->dst_entry->processed = 1; - ren2->processed = 1; - if (strcmp(ren1_dst, ren2_dst) != 0) { - rename_type = RENAME_ONE_FILE_TO_TWO; - clean_merge = 0; - } else { - rename_type = RENAME_ONE_FILE_TO_ONE; - /* BUG: We should only remove ren1_src in - * the base stage (think of rename + - * add-source cases). - */ - remove_file(opt, 1, ren1_src, 1); - update_entry(ren1->dst_entry, - ren1->pair->one, - ren1->pair->two, - ren2->pair->two); - } - setup_rename_conflict_info(rename_type, opt, ren1, ren2); - } else if ((lookup = string_list_lookup(renames2Dst, ren1_dst))) { - /* Two different files renamed to the same thing */ - char *ren2_dst; - ren2 = lookup->util; - ren2_dst = ren2->pair->two->path; - if (strcmp(ren1_dst, ren2_dst) != 0) - BUG("ren1_dst != ren2_dst"); - - clean_merge = 0; - ren2->processed = 1; - /* - * BUG: We should only mark src_entry as processed - * if we are not dealing with a rename + add-source - * case. - */ - ren2->src_entry->processed = 1; - - setup_rename_conflict_info(RENAME_TWO_FILES_TO_ONE, - opt, ren1, ren2); - } else { - /* Renamed in 1, maybe changed in 2 */ - /* we only use sha1 and mode of these */ - struct diff_filespec src_other, dst_other; - int try_merge; - - /* - * unpack_trees loads entries from common-commit - * into stage 1, from head-commit into stage 2, and - * from merge-commit into stage 3. We keep track - * of which side corresponds to the rename. - */ - int renamed_stage = a_renames == renames1 ? 2 : 3; - int other_stage = a_renames == renames1 ? 3 : 2; - - /* - * Directory renames have a funny corner case... - */ - int renamed_to_self = !strcmp(ren1_src, ren1_dst); - - /* BUG: We should only remove ren1_src in the base - * stage and in other_stage (think of rename + - * add-source case). - */ - if (!renamed_to_self) - remove_file(opt, 1, ren1_src, - renamed_stage == 2 || - !was_tracked(opt, ren1_src)); - - oidcpy(&src_other.oid, - &ren1->src_entry->stages[other_stage].oid); - src_other.mode = ren1->src_entry->stages[other_stage].mode; - oidcpy(&dst_other.oid, - &ren1->dst_entry->stages[other_stage].oid); - dst_other.mode = ren1->dst_entry->stages[other_stage].mode; - try_merge = 0; - - if (oideq(&src_other.oid, null_oid()) && - ren1->dir_rename_original_type == 'A') { - setup_rename_conflict_info(RENAME_VIA_DIR, - opt, ren1, NULL); - } else if (renamed_to_self) { - setup_rename_conflict_info(RENAME_NORMAL, - opt, ren1, NULL); - } else if (oideq(&src_other.oid, null_oid())) { - setup_rename_conflict_info(RENAME_DELETE, - opt, ren1, NULL); - } else if ((dst_other.mode == ren1->pair->two->mode) && - oideq(&dst_other.oid, &ren1->pair->two->oid)) { - /* - * Added file on the other side identical to - * the file being renamed: clean merge. - * Also, there is no need to overwrite the - * file already in the working copy, so call - * update_file_flags() instead of - * update_file(). - */ - if (update_file_flags(opt, - ren1->pair->two, - ren1_dst, - 1, /* update_cache */ - 0 /* update_wd */)) - clean_merge = -1; - } else if (!oideq(&dst_other.oid, null_oid())) { - /* - * Probably not a clean merge, but it's - * premature to set clean_merge to 0 here, - * because if the rename merges cleanly and - * the merge exactly matches the newly added - * file, then the merge will be clean. - */ - setup_rename_conflict_info(RENAME_ADD, - opt, ren1, NULL); - } else - try_merge = 1; - - if (clean_merge < 0) - goto cleanup_and_return; - if (try_merge) { - struct diff_filespec *o, *a, *b; - src_other.path = (char *)ren1_src; - - o = ren1->pair->one; - if (a_renames == renames1) { - a = ren1->pair->two; - b = &src_other; - } else { - b = ren1->pair->two; - a = &src_other; - } - update_entry(ren1->dst_entry, o, a, b); - setup_rename_conflict_info(RENAME_NORMAL, - opt, ren1, NULL); - } - } - } -cleanup_and_return: - string_list_clear(&a_by_dst, 0); - string_list_clear(&b_by_dst, 0); - - return clean_merge; -} - -struct rename_info { - struct string_list *head_renames; - struct string_list *merge_renames; -}; - -static void initial_cleanup_rename(struct diff_queue_struct *pairs, - struct hashmap *dir_renames) -{ - struct hashmap_iter iter; - struct dir_rename_entry *e; - - hashmap_for_each_entry(dir_renames, &iter, e, - ent /* member name */) { - free(e->dir); - strbuf_release(&e->new_dir); - /* possible_new_dirs already cleared in get_directory_renames */ - } - hashmap_clear_and_free(dir_renames, struct dir_rename_entry, ent); - free(dir_renames); - - free(pairs->queue); - free(pairs); -} - -static int detect_and_process_renames(struct merge_options *opt, - struct tree *common, - struct tree *head, - struct tree *merge, - struct string_list *entries, - struct rename_info *ri) -{ - struct diff_queue_struct *head_pairs, *merge_pairs; - struct hashmap *dir_re_head, *dir_re_merge; - int clean = 1; - - ri->head_renames = NULL; - ri->merge_renames = NULL; - - if (!merge_detect_rename(opt)) - return 1; - - head_pairs = get_diffpairs(opt, common, head); - merge_pairs = get_diffpairs(opt, common, merge); - - if ((opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_TRUE) || - (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_CONFLICT && - !opt->priv->call_depth)) { - dir_re_head = get_directory_renames(head_pairs); - dir_re_merge = get_directory_renames(merge_pairs); - - handle_directory_level_conflicts(opt, - dir_re_head, head, - dir_re_merge, merge); - } else { - dir_re_head = xmalloc(sizeof(*dir_re_head)); - dir_re_merge = xmalloc(sizeof(*dir_re_merge)); - dir_rename_init(dir_re_head); - dir_rename_init(dir_re_merge); - } - - ri->head_renames = get_renames(opt, opt->branch1, head_pairs, - dir_re_merge, dir_re_head, head, - common, head, merge, entries, - &clean); - if (clean < 0) - goto cleanup; - ri->merge_renames = get_renames(opt, opt->branch2, merge_pairs, - dir_re_head, dir_re_merge, merge, - common, head, merge, entries, - &clean); - if (clean < 0) - goto cleanup; - clean &= process_renames(opt, ri->head_renames, ri->merge_renames); - -cleanup: - /* - * Some cleanup is deferred until cleanup_renames() because the - * data structures are still needed and referenced in - * process_entry(). But there are a few things we can free now. - */ - initial_cleanup_rename(head_pairs, dir_re_head); - initial_cleanup_rename(merge_pairs, dir_re_merge); - - return clean; -} - -static void final_cleanup_rename(struct string_list *rename) -{ - const struct rename *re; - int i; - - if (!rename) - return; - - for (i = 0; i < rename->nr; i++) { - re = rename->items[i].util; - diff_free_filepair(re->pair); - if (re->src_entry->rename_conflict_info_owned) - FREE_AND_NULL(re->src_entry->rename_conflict_info); - if (re->dst_entry->rename_conflict_info_owned) - FREE_AND_NULL(re->dst_entry->rename_conflict_info); - } - string_list_clear(rename, 1); - free(rename); -} - -static void final_cleanup_renames(struct rename_info *re_info) -{ - final_cleanup_rename(re_info->head_renames); - final_cleanup_rename(re_info->merge_renames); -} - -static int read_oid_strbuf(struct merge_options *opt, - const struct object_id *oid, - struct strbuf *dst) -{ - void *buf; - enum object_type type; - unsigned long size; - buf = repo_read_object_file(the_repository, oid, &type, &size); - if (!buf) - return err(opt, _("cannot read object %s"), oid_to_hex(oid)); - if (type != OBJ_BLOB) { - free(buf); - return err(opt, _("object %s is not a blob"), oid_to_hex(oid)); - } - strbuf_attach(dst, buf, size, size + 1); - return 0; -} - -static int blob_unchanged(struct merge_options *opt, - const struct diff_filespec *o, - const struct diff_filespec *a, - int renormalize, const char *path) -{ - struct strbuf obuf = STRBUF_INIT; - struct strbuf abuf = STRBUF_INIT; - int ret = 0; /* assume changed for safety */ - struct index_state *idx = opt->repo->index; - - if (a->mode != o->mode) - return 0; - if (oideq(&o->oid, &a->oid)) - return 1; - if (!renormalize) - return 0; - - if (read_oid_strbuf(opt, &o->oid, &obuf) || - read_oid_strbuf(opt, &a->oid, &abuf)) - goto error_return; - /* - * Note: binary | is used so that both renormalizations are - * performed. Comparison can be skipped if both files are - * unchanged since their sha1s have already been compared. - */ - if (renormalize_buffer(idx, path, obuf.buf, obuf.len, &obuf) | - renormalize_buffer(idx, path, abuf.buf, abuf.len, &abuf)) - ret = (obuf.len == abuf.len && !memcmp(obuf.buf, abuf.buf, obuf.len)); - -error_return: - strbuf_release(&obuf); - strbuf_release(&abuf); - return ret; -} - -static int handle_modify_delete(struct merge_options *opt, - const char *path, - const struct diff_filespec *o, - const struct diff_filespec *a, - const struct diff_filespec *b) -{ - const char *modify_branch, *delete_branch; - const struct diff_filespec *changed; - - if (is_valid(a)) { - modify_branch = opt->branch1; - delete_branch = opt->branch2; - changed = a; - } else { - modify_branch = opt->branch2; - delete_branch = opt->branch1; - changed = b; - } - - return handle_change_delete(opt, - path, NULL, - o, changed, - modify_branch, delete_branch, - _("modify"), _("modified")); -} - -static int handle_content_merge(struct merge_file_info *mfi, - struct merge_options *opt, - const char *path, - int is_dirty, - const struct diff_filespec *o, - const struct diff_filespec *a, - const struct diff_filespec *b, - struct rename_conflict_info *ci) -{ - const char *reason = _("content"); - unsigned df_conflict_remains = 0; - - if (!is_valid(o)) - reason = _("add/add"); - - assert(o->path && a->path && b->path); - if (ci && dir_in_way(opt->repo->index, path, !opt->priv->call_depth, - S_ISGITLINK(ci->ren1->pair->two->mode))) - df_conflict_remains = 1; - - if (merge_mode_and_contents(opt, o, a, b, path, - opt->branch1, opt->branch2, - opt->priv->call_depth * 2, mfi)) - return -1; - - /* - * We can skip updating the working tree file iff: - * a) The merge is clean - * b) The merge matches what was in HEAD (content, mode, pathname) - * c) The target path is usable (i.e. not involved in D/F conflict) - */ - if (mfi->clean && was_tracked_and_matches(opt, path, &mfi->blob) && - !df_conflict_remains) { - int pos; - struct cache_entry *ce; - - output(opt, 3, _("Skipped %s (merged same as existing)"), path); - if (add_cacheinfo(opt, &mfi->blob, path, - 0, (!opt->priv->call_depth && !is_dirty), 0)) - return -1; - /* - * However, add_cacheinfo() will delete the old cache entry - * and add a new one. We need to copy over any skip_worktree - * flag to avoid making the file appear as if it were - * deleted by the user. - */ - pos = index_name_pos(&opt->priv->orig_index, path, strlen(path)); - ce = opt->priv->orig_index.cache[pos]; - if (ce_skip_worktree(ce)) { - pos = index_name_pos(opt->repo->index, path, strlen(path)); - ce = opt->repo->index->cache[pos]; - ce->ce_flags |= CE_SKIP_WORKTREE; - } - return mfi->clean; - } - - if (!mfi->clean) { - if (S_ISGITLINK(mfi->blob.mode)) - reason = _("submodule"); - output(opt, 1, _("CONFLICT (%s): Merge conflict in %s"), - reason, path); - if (ci && !df_conflict_remains) - if (update_stages(opt, path, o, a, b)) - return -1; - } - - if (df_conflict_remains || is_dirty) { - char *new_path; - if (opt->priv->call_depth) { - remove_file_from_index(opt->repo->index, path); - } else { - if (!mfi->clean) { - if (update_stages(opt, path, o, a, b)) - return -1; - } else { - int file_from_stage2 = was_tracked(opt, path); - - if (update_stages(opt, path, NULL, - file_from_stage2 ? &mfi->blob : NULL, - file_from_stage2 ? NULL : &mfi->blob)) - return -1; - } - - } - new_path = unique_path(opt, path, ci->ren1->branch); - if (is_dirty) { - output(opt, 1, _("Refusing to lose dirty file at %s"), - path); - } - output(opt, 1, _("Adding as %s instead"), new_path); - if (update_file(opt, 0, &mfi->blob, new_path)) { - free(new_path); - return -1; - } - free(new_path); - mfi->clean = 0; - } else if (update_file(opt, mfi->clean, &mfi->blob, path)) - return -1; - return !is_dirty && mfi->clean; -} - -static int handle_rename_normal(struct merge_options *opt, - const char *path, - const struct diff_filespec *o, - const struct diff_filespec *a, - const struct diff_filespec *b, - struct rename_conflict_info *ci) -{ - struct rename *ren = ci->ren1; - struct merge_file_info mfi; - int clean; - - /* Merge the content and write it out */ - clean = handle_content_merge(&mfi, opt, path, was_dirty(opt, path), - o, a, b, ci); - - if (clean && - opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_CONFLICT && - ren->dir_rename_original_dest) { - if (update_stages(opt, path, - &mfi.blob, &mfi.blob, &mfi.blob)) - return -1; - clean = 0; /* not clean, but conflicted */ - } - return clean; -} - -static void dir_rename_warning(const char *msg, - int is_add, - int clean, - struct merge_options *opt, - struct rename *ren) -{ - const char *other_branch; - other_branch = (ren->branch == opt->branch1 ? - opt->branch2 : opt->branch1); - if (is_add) { - output(opt, clean ? 2 : 1, msg, - ren->pair->one->path, ren->branch, - other_branch, ren->pair->two->path); - return; - } - output(opt, clean ? 2 : 1, msg, - ren->pair->one->path, ren->dir_rename_original_dest, ren->branch, - other_branch, ren->pair->two->path); -} -static int warn_about_dir_renamed_entries(struct merge_options *opt, - struct rename *ren) -{ - const char *msg; - int clean = 1, is_add; - - if (!ren) - return clean; - - /* Return early if ren was not affected/created by a directory rename */ - if (!ren->dir_rename_original_dest) - return clean; - - /* Sanity checks */ - assert(opt->detect_directory_renames > MERGE_DIRECTORY_RENAMES_NONE); - assert(ren->dir_rename_original_type == 'A' || - ren->dir_rename_original_type == 'R'); - - /* Check whether to treat directory renames as a conflict */ - clean = (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_TRUE); - - is_add = (ren->dir_rename_original_type == 'A'); - if (ren->dir_rename_original_type == 'A' && clean) { - msg = _("Path updated: %s added in %s inside a " - "directory that was renamed in %s; moving it to %s."); - } else if (ren->dir_rename_original_type == 'A' && !clean) { - msg = _("CONFLICT (file location): %s added in %s " - "inside a directory that was renamed in %s, " - "suggesting it should perhaps be moved to %s."); - } else if (ren->dir_rename_original_type == 'R' && clean) { - msg = _("Path updated: %s renamed to %s in %s, inside a " - "directory that was renamed in %s; moving it to %s."); - } else if (ren->dir_rename_original_type == 'R' && !clean) { - msg = _("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."); - } else { - BUG("Impossible dir_rename_original_type/clean combination"); - } - dir_rename_warning(msg, is_add, clean, opt, ren); - - return clean; -} - -/* Per entry merge function */ -static int process_entry(struct merge_options *opt, - const char *path, struct stage_data *entry) -{ - int clean_merge = 1; - int normalize = opt->renormalize; - - struct diff_filespec *o = &entry->stages[1]; - struct diff_filespec *a = &entry->stages[2]; - struct diff_filespec *b = &entry->stages[3]; - int o_valid = is_valid(o); - int a_valid = is_valid(a); - int b_valid = is_valid(b); - o->path = a->path = b->path = (char*)path; - - entry->processed = 1; - if (entry->rename_conflict_info) { - struct rename_conflict_info *ci = entry->rename_conflict_info; - struct diff_filespec *temp; - int path_clean; - - path_clean = warn_about_dir_renamed_entries(opt, ci->ren1); - path_clean &= warn_about_dir_renamed_entries(opt, ci->ren2); - - /* - * For cases with a single rename, {o,a,b}->path have all been - * set to the rename target path; we need to set two of these - * back to the rename source. - * For rename/rename conflicts, we'll manually fix paths below. - */ - temp = (opt->branch1 == ci->ren1->branch) ? b : a; - o->path = temp->path = ci->ren1->pair->one->path; - if (ci->ren2) { - assert(opt->branch1 == ci->ren1->branch); - } - - switch (ci->rename_type) { - case RENAME_NORMAL: - case RENAME_ONE_FILE_TO_ONE: - clean_merge = handle_rename_normal(opt, path, o, a, b, - ci); - break; - case RENAME_VIA_DIR: - clean_merge = handle_rename_via_dir(opt, ci); - break; - case RENAME_ADD: - /* - * Probably unclean merge, but if the renamed file - * merges cleanly and the result can then be - * two-way merged cleanly with the added file, I - * guess it's a clean merge? - */ - clean_merge = handle_rename_add(opt, ci); - break; - case RENAME_DELETE: - clean_merge = 0; - if (handle_rename_delete(opt, ci)) - clean_merge = -1; - break; - case RENAME_ONE_FILE_TO_TWO: - /* - * Manually fix up paths; note: - * ren[12]->pair->one->path are equal. - */ - o->path = ci->ren1->pair->one->path; - a->path = ci->ren1->pair->two->path; - b->path = ci->ren2->pair->two->path; - - clean_merge = 0; - if (handle_rename_rename_1to2(opt, ci)) - clean_merge = -1; - break; - case RENAME_TWO_FILES_TO_ONE: - /* - * Manually fix up paths; note, - * ren[12]->pair->two->path are actually equal. - */ - o->path = NULL; - a->path = ci->ren1->pair->two->path; - b->path = ci->ren2->pair->two->path; - - /* - * Probably unclean merge, but if the two renamed - * files merge cleanly and the two resulting files - * can then be two-way merged cleanly, I guess it's - * a clean merge? - */ - clean_merge = handle_rename_rename_2to1(opt, ci); - break; - default: - entry->processed = 0; - break; - } - if (path_clean < clean_merge) - clean_merge = path_clean; - } else if (o_valid && (!a_valid || !b_valid)) { - /* Case A: Deleted in one */ - if ((!a_valid && !b_valid) || - (!b_valid && blob_unchanged(opt, o, a, normalize, path)) || - (!a_valid && blob_unchanged(opt, o, b, normalize, path))) { - /* Deleted in both or deleted in one and - * unchanged in the other */ - if (a_valid) - output(opt, 2, _("Removing %s"), path); - /* do not touch working file if it did not exist */ - remove_file(opt, 1, path, !a_valid); - } else { - /* Modify/delete; deleted side may have put a directory in the way */ - clean_merge = 0; - if (handle_modify_delete(opt, path, o, a, b)) - clean_merge = -1; - } - } else if ((!o_valid && a_valid && !b_valid) || - (!o_valid && !a_valid && b_valid)) { - /* Case B: Added in one. */ - /* [nothing|directory] -> ([nothing|directory], file) */ - - const char *add_branch; - const char *other_branch; - const char *conf; - const struct diff_filespec *contents; - - if (a_valid) { - add_branch = opt->branch1; - other_branch = opt->branch2; - contents = a; - conf = _("file/directory"); - } else { - add_branch = opt->branch2; - other_branch = opt->branch1; - contents = b; - conf = _("directory/file"); - } - if (dir_in_way(opt->repo->index, path, - !opt->priv->call_depth && !S_ISGITLINK(a->mode), - 0)) { - char *new_path = unique_path(opt, path, add_branch); - clean_merge = 0; - output(opt, 1, _("CONFLICT (%s): There is a directory with name %s in %s. " - "Adding %s as %s"), - conf, path, other_branch, path, new_path); - if (update_file(opt, 0, contents, new_path)) - clean_merge = -1; - else if (opt->priv->call_depth) - remove_file_from_index(opt->repo->index, path); - free(new_path); - } else { - output(opt, 2, _("Adding %s"), path); - /* do not overwrite file if already present */ - if (update_file_flags(opt, contents, path, 1, !a_valid)) - clean_merge = -1; - } - } else if (a_valid && b_valid) { - if (!o_valid) { - /* Case C: Added in both (check for same permissions) */ - output(opt, 1, - _("CONFLICT (add/add): Merge conflict in %s"), - path); - clean_merge = handle_file_collision(opt, - path, NULL, NULL, - opt->branch1, - opt->branch2, - a, b); - } else { - /* case D: Modified in both, but differently. */ - struct merge_file_info mfi; - int is_dirty = 0; /* unpack_trees would have bailed if dirty */ - clean_merge = handle_content_merge(&mfi, opt, path, - is_dirty, - o, a, b, NULL); - } - } else if (!o_valid && !a_valid && !b_valid) { - /* - * this entry was deleted altogether. a_mode == 0 means - * we had that path and want to actively remove it. - */ - remove_file(opt, 1, path, !a->mode); - } else - BUG("fatal merge failure, shouldn't happen."); - - return clean_merge; -} - -static int merge_trees_internal(struct merge_options *opt, - struct tree *head, - struct tree *merge, - struct tree *merge_base, - struct tree **result) -{ - struct index_state *istate = opt->repo->index; - int code, clean; - - if (opt->subtree_shift) { - merge = shift_tree_object(opt->repo, head, merge, - opt->subtree_shift); - merge_base = shift_tree_object(opt->repo, head, merge_base, - opt->subtree_shift); - } - - if (oideq(&merge_base->object.oid, &merge->object.oid)) { - output(opt, 0, _("Already up to date.")); - *result = head; - return 1; - } - - code = unpack_trees_start(opt, merge_base, head, merge); - - if (code != 0) { - if (show(opt, 4) || opt->priv->call_depth) - err(opt, _("merging of trees %s and %s failed"), - oid_to_hex(&head->object.oid), - oid_to_hex(&merge->object.oid)); - unpack_trees_finish(opt); - return -1; - } - - if (unmerged_index(istate)) { - struct string_list *entries; - struct rename_info re_info; - int i; - /* - * Only need the hashmap while processing entries, so - * initialize it here and free it when we are done running - * through the entries. Keeping it in the merge_options as - * opposed to decaring a local hashmap is for convenience - * so that we don't have to pass it to around. - */ - hashmap_init(&opt->priv->current_file_dir_set, path_hashmap_cmp, - NULL, 512); - get_files_dirs(opt, head); - get_files_dirs(opt, merge); - - entries = get_unmerged(opt->repo->index); - clean = detect_and_process_renames(opt, merge_base, head, merge, - entries, &re_info); - record_df_conflict_files(opt, entries); - if (clean < 0) - goto cleanup; - for (i = entries->nr-1; 0 <= i; i--) { - const char *path = entries->items[i].string; - struct stage_data *e = entries->items[i].util; - if (!e->processed) { - int ret = process_entry(opt, path, e); - if (!ret) - clean = 0; - else if (ret < 0) { - clean = ret; - goto cleanup; - } - } - } - for (i = 0; i < entries->nr; i++) { - struct stage_data *e = entries->items[i].util; - if (!e->processed) - BUG("unprocessed path??? %s", - entries->items[i].string); - } - - cleanup: - final_cleanup_renames(&re_info); - - string_list_clear(entries, 1); - free(entries); - - hashmap_clear_and_free(&opt->priv->current_file_dir_set, - struct path_hashmap_entry, e); - - if (clean < 0) { - unpack_trees_finish(opt); - return clean; - } - } - else - clean = 1; - - unpack_trees_finish(opt); - - if (opt->priv->call_depth && - !(*result = write_in_core_index_as_tree(opt->repo))) - return -1; - - return clean; -} - -/* - * Merge the commits h1 and h2, returning a flag (int) indicating the - * cleanness of the merge. Also, if opt->priv->call_depth, create a - * virtual commit and write its location to *result. - */ -static int merge_recursive_internal(struct merge_options *opt, - struct commit *h1, - struct commit *h2, - const struct commit_list *_merge_bases, - struct commit **result) -{ - struct commit_list *merge_bases = copy_commit_list(_merge_bases); - struct commit_list *iter; - struct commit *merged_merge_bases; - struct tree *result_tree; - const char *ancestor_name; - struct strbuf merge_base_abbrev = STRBUF_INIT; - int ret; - - if (show(opt, 4)) { - output(opt, 4, _("Merging:")); - output_commit_title(opt, h1); - output_commit_title(opt, h2); - } - - if (!merge_bases) { - if (repo_get_merge_bases(the_repository, h1, h2, - &merge_bases) < 0) { - ret = -1; - goto out; - } - merge_bases = reverse_commit_list(merge_bases); - } - - if (show(opt, 5)) { - unsigned cnt = commit_list_count(merge_bases); - - output(opt, 5, Q_("found %u common ancestor:", - "found %u common ancestors:", cnt), cnt); - for (iter = merge_bases; iter; iter = iter->next) - output_commit_title(opt, iter->item); - } - - merged_merge_bases = pop_commit(&merge_bases); - if (!merged_merge_bases) { - /* if there is no common ancestor, use an empty tree */ - struct tree *tree; - - tree = lookup_tree(opt->repo, opt->repo->hash_algo->empty_tree); - merged_merge_bases = make_virtual_commit(opt->repo, tree, - "ancestor"); - ancestor_name = "empty tree"; - } else if (opt->ancestor && !opt->priv->call_depth) { - ancestor_name = opt->ancestor; - } else if (merge_bases) { - ancestor_name = "merged common ancestors"; - } else { - strbuf_add_unique_abbrev(&merge_base_abbrev, - &merged_merge_bases->object.oid, - DEFAULT_ABBREV); - ancestor_name = merge_base_abbrev.buf; - } - - for (iter = merge_bases; iter; iter = iter->next) { - const char *saved_b1, *saved_b2; - opt->priv->call_depth++; - /* - * When the merge fails, the result contains files - * with conflict markers. The cleanness flag is - * ignored (unless indicating an error), it was never - * actually used, as result of merge_trees has always - * overwritten it: the committed "conflicts" were - * already resolved. - */ - discard_index(opt->repo->index); - saved_b1 = opt->branch1; - saved_b2 = opt->branch2; - opt->branch1 = "Temporary merge branch 1"; - opt->branch2 = "Temporary merge branch 2"; - if (merge_recursive_internal(opt, merged_merge_bases, iter->item, - NULL, &merged_merge_bases) < 0) { - ret = -1; - goto out; - } - opt->branch1 = saved_b1; - opt->branch2 = saved_b2; - opt->priv->call_depth--; - - if (!merged_merge_bases) { - ret = err(opt, _("merge returned no commit")); - goto out; - } - } - - /* - * FIXME: Since merge_recursive_internal() is only ever called by - * places that ensure the index is loaded first - * (e.g. builtin/merge.c, rebase/sequencer, etc.), in the common - * case where the merge base was unique that means when we get here - * we immediately discard the index and re-read it, which is a - * complete waste of time. We should only be discarding and - * re-reading if we were forced to recurse. - */ - discard_index(opt->repo->index); - if (!opt->priv->call_depth) - repo_read_index(opt->repo); - - opt->ancestor = ancestor_name; - ret = merge_trees_internal(opt, - repo_get_commit_tree(opt->repo, h1), - repo_get_commit_tree(opt->repo, h2), - repo_get_commit_tree(opt->repo, - merged_merge_bases), - &result_tree); - opt->ancestor = NULL; /* avoid accidental re-use of opt->ancestor */ - if (ret < 0) { - flush_output(opt); - goto out; - } - - if (opt->priv->call_depth) { - *result = make_virtual_commit(opt->repo, result_tree, - "merged tree"); - commit_list_insert(h1, &(*result)->parents); - commit_list_insert(h2, &(*result)->parents->next); - } - -out: - strbuf_release(&merge_base_abbrev); - free_commit_list(merge_bases); - return ret; -} - -static int merge_start(struct merge_options *opt, struct tree *head) -{ - struct strbuf sb = STRBUF_INIT; - - /* Sanity checks on opt */ - assert(opt->repo); - - assert(opt->branch1 && opt->branch2); - - assert(opt->detect_renames >= -1 && - opt->detect_renames <= DIFF_DETECT_COPY); - assert(opt->detect_directory_renames >= MERGE_DIRECTORY_RENAMES_NONE && - opt->detect_directory_renames <= MERGE_DIRECTORY_RENAMES_TRUE); - assert(opt->rename_limit >= -1); - assert(opt->rename_score >= 0 && opt->rename_score <= MAX_SCORE); - assert(opt->show_rename_progress >= 0 && opt->show_rename_progress <= 1); - - assert(opt->xdl_opts >= 0); - assert(opt->recursive_variant >= MERGE_VARIANT_NORMAL && - opt->recursive_variant <= MERGE_VARIANT_THEIRS); - - assert(opt->verbosity >= 0 && opt->verbosity <= 5); - assert(opt->buffer_output <= 2); - assert(opt->obuf.len == 0); - - assert(opt->priv == NULL); - - /* Not supported; option specific to merge-ort */ - assert(!opt->record_conflict_msgs_as_headers); - assert(!opt->msg_header_prefix); - - /* Sanity check on repo state; index must match head */ - if (repo_index_has_changes(opt->repo, head, &sb)) { - err(opt, _("Your local changes to the following files would be overwritten by merge:\n %s"), - sb.buf); - strbuf_release(&sb); - return -1; - } - - CALLOC_ARRAY(opt->priv, 1); - string_list_init_dup(&opt->priv->df_conflict_file_set); - return 0; -} - -static void merge_finalize(struct merge_options *opt) -{ - flush_output(opt); - if (!opt->priv->call_depth && opt->buffer_output < 2) - strbuf_release(&opt->obuf); - if (show(opt, 2)) - diff_warn_rename_limit("merge.renamelimit", - opt->priv->needed_rename_limit, 0); - hashmap_clear_and_free(&opt->priv->current_file_dir_set, - struct path_hashmap_entry, e); - string_list_clear(&opt->priv->df_conflict_file_set, 0); - FREE_AND_NULL(opt->priv); -} - -int merge_trees(struct merge_options *opt, - struct tree *head, - struct tree *merge, - struct tree *merge_base) -{ - int clean; - struct tree *ignored; - - assert(opt->ancestor != NULL); - - if (merge_start(opt, head)) - return -1; - clean = merge_trees_internal(opt, head, merge, merge_base, &ignored); - merge_finalize(opt); - - return clean; -} - -int merge_recursive(struct merge_options *opt, - struct commit *h1, - struct commit *h2, - const struct commit_list *merge_bases, - struct commit **result) -{ - int clean; - - assert(opt->ancestor == NULL || - !strcmp(opt->ancestor, "constructed merge base")); - - prepare_repo_settings(opt->repo); - opt->repo->settings.command_requires_full_index = 1; - - if (merge_start(opt, repo_get_commit_tree(opt->repo, h1))) - return -1; - clean = merge_recursive_internal(opt, h1, h2, merge_bases, result); - merge_finalize(opt); - - return clean; -} - -static struct commit *get_ref(struct repository *repo, - const struct object_id *oid, - const char *name) -{ - struct object *object; - - object = deref_tag(repo, parse_object(repo, oid), - name, strlen(name)); - if (!object) - return NULL; - if (object->type == OBJ_TREE) - return make_virtual_commit(repo, (struct tree*)object, name); - if (object->type != OBJ_COMMIT) - return NULL; - if (repo_parse_commit(repo, (struct commit *)object)) - return NULL; - return (struct commit *)object; -} - -int merge_recursive_generic(struct merge_options *opt, - const struct object_id *head, - const struct object_id *merge, - int num_merge_bases, - const struct object_id *merge_bases, - struct commit **result) -{ - int clean; - struct lock_file lock = LOCK_INIT; - struct commit *head_commit = get_ref(opt->repo, head, opt->branch1); - struct commit *next_commit = get_ref(opt->repo, merge, opt->branch2); - struct commit_list *ca = NULL; - - if (merge_bases) { - int i; - for (i = 0; i < num_merge_bases; ++i) { - struct commit *base; - if (!(base = get_ref(opt->repo, &merge_bases[i], - oid_to_hex(&merge_bases[i])))) - return err(opt, _("Could not parse object '%s'"), - oid_to_hex(&merge_bases[i])); - commit_list_insert(base, &ca); - } - if (num_merge_bases == 1) - opt->ancestor = "constructed merge base"; - } - - repo_hold_locked_index(opt->repo, &lock, LOCK_DIE_ON_ERROR); - clean = merge_recursive(opt, head_commit, next_commit, ca, - result); - free_commit_list(ca); - if (clean < 0) { - rollback_lock_file(&lock); - return clean; - } - - if (write_locked_index(opt->repo->index, &lock, - COMMIT_LOCK | SKIP_IF_UNCHANGED)) - return err(opt, _("Unable to write index.")); - - return clean ? 0 : 1; -} - -static void merge_recursive_config(struct merge_options *opt, int ui) -{ - char *value = NULL; - int renormalize = 0; - git_config_get_int("merge.verbosity", &opt->verbosity); - git_config_get_int("diff.renamelimit", &opt->rename_limit); - git_config_get_int("merge.renamelimit", &opt->rename_limit); - git_config_get_bool("merge.renormalize", &renormalize); - opt->renormalize = renormalize; - if (!git_config_get_string("diff.renames", &value)) { - opt->detect_renames = git_config_rename("diff.renames", value); - free(value); - } - if (!git_config_get_string("merge.renames", &value)) { - opt->detect_renames = git_config_rename("merge.renames", value); - free(value); - } - if (!git_config_get_string("merge.directoryrenames", &value)) { - int boolval = git_parse_maybe_bool(value); - if (0 <= boolval) { - opt->detect_directory_renames = boolval ? - MERGE_DIRECTORY_RENAMES_TRUE : - MERGE_DIRECTORY_RENAMES_NONE; - } else if (!strcasecmp(value, "conflict")) { - opt->detect_directory_renames = - MERGE_DIRECTORY_RENAMES_CONFLICT; - } /* avoid erroring on values from future versions of git */ - free(value); - } - if (ui) { - if (!git_config_get_string("diff.algorithm", &value)) { - long diff_algorithm = parse_algorithm_value(value); - if (diff_algorithm < 0) - die(_("unknown value for config '%s': %s"), "diff.algorithm", value); - opt->xdl_opts = (opt->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | diff_algorithm; - free(value); - } - } - git_config(git_xmerge_config, NULL); -} - -static void init_merge_options(struct merge_options *opt, - struct repository *repo, int ui) -{ - const char *merge_verbosity; - memset(opt, 0, sizeof(struct merge_options)); - - opt->repo = repo; - - opt->detect_renames = -1; - opt->detect_directory_renames = MERGE_DIRECTORY_RENAMES_CONFLICT; - opt->rename_limit = -1; - - opt->verbosity = 2; - opt->buffer_output = 1; - strbuf_init(&opt->obuf, 0); - - opt->renormalize = 0; - - opt->conflict_style = -1; - - merge_recursive_config(opt, ui); - merge_verbosity = getenv("GIT_MERGE_VERBOSITY"); - if (merge_verbosity) - opt->verbosity = strtol(merge_verbosity, NULL, 10); - if (opt->verbosity >= 5) - opt->buffer_output = 0; -} - -void init_ui_merge_options(struct merge_options *opt, - struct repository *repo) -{ - init_merge_options(opt, repo, 1); -} - -void init_basic_merge_options(struct merge_options *opt, - struct repository *repo) -{ - init_merge_options(opt, repo, 0); -} - -/* - * For now, members of merge_options do not need deep copying, but - * it may change in the future, in which case we would need to update - * this, and also make a matching change to clear_merge_options() to - * release the resources held by a copied instance. - */ -void copy_merge_options(struct merge_options *dst, struct merge_options *src) -{ - *dst = *src; -} - -void clear_merge_options(struct merge_options *opt UNUSED) -{ - ; /* no-op as our copy is shallow right now */ -} - -int parse_merge_opt(struct merge_options *opt, const char *s) -{ - const char *arg; - - if (!s || !*s) - return -1; - if (!strcmp(s, "ours")) - opt->recursive_variant = MERGE_VARIANT_OURS; - else if (!strcmp(s, "theirs")) - opt->recursive_variant = MERGE_VARIANT_THEIRS; - else if (!strcmp(s, "subtree")) - opt->subtree_shift = ""; - else if (skip_prefix(s, "subtree=", &arg)) - opt->subtree_shift = arg; - else if (!strcmp(s, "patience")) - opt->xdl_opts = DIFF_WITH_ALG(opt, PATIENCE_DIFF); - else if (!strcmp(s, "histogram")) - opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF); - else if (skip_prefix(s, "diff-algorithm=", &arg)) { - long value = parse_algorithm_value(arg); - if (value < 0) - return -1; - /* clear out previous settings */ - DIFF_XDL_CLR(opt, NEED_MINIMAL); - opt->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK; - opt->xdl_opts |= value; - } - else if (!strcmp(s, "ignore-space-change")) - DIFF_XDL_SET(opt, IGNORE_WHITESPACE_CHANGE); - else if (!strcmp(s, "ignore-all-space")) - DIFF_XDL_SET(opt, IGNORE_WHITESPACE); - else if (!strcmp(s, "ignore-space-at-eol")) - DIFF_XDL_SET(opt, IGNORE_WHITESPACE_AT_EOL); - else if (!strcmp(s, "ignore-cr-at-eol")) - DIFF_XDL_SET(opt, IGNORE_CR_AT_EOL); - else if (!strcmp(s, "renormalize")) - opt->renormalize = 1; - else if (!strcmp(s, "no-renormalize")) - opt->renormalize = 0; - else if (!strcmp(s, "no-renames")) - opt->detect_renames = 0; - else if (!strcmp(s, "find-renames")) { - opt->detect_renames = 1; - opt->rename_score = 0; - } - else if (skip_prefix(s, "find-renames=", &arg) || - skip_prefix(s, "rename-threshold=", &arg)) { - if ((opt->rename_score = parse_rename_score(&arg)) == -1 || *arg != 0) - return -1; - opt->detect_renames = 1; - } - /* - * Please update $__git_merge_strategy_options in - * git-completion.bash when you add new options - */ - else - return -1; - return 0; -} diff --git a/merge-recursive.h b/merge-recursive.h deleted file mode 100644 index 0b91f28f90..0000000000 --- a/merge-recursive.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef MERGE_RECURSIVE_H -#define MERGE_RECURSIVE_H - -#include "strbuf.h" - -struct commit; -struct commit_list; -struct object_id; -struct repository; -struct tree; - -struct merge_options_internal; -struct merge_options { - struct repository *repo; - - /* ref names used in console messages and conflict markers */ - const char *ancestor; - const char *branch1; - const char *branch2; - - /* rename related options */ - int detect_renames; - enum { - MERGE_DIRECTORY_RENAMES_NONE = 0, - MERGE_DIRECTORY_RENAMES_CONFLICT = 1, - MERGE_DIRECTORY_RENAMES_TRUE = 2 - } detect_directory_renames; - int rename_limit; - int rename_score; - int show_rename_progress; - - /* xdiff-related options (patience, ignore whitespace, ours/theirs) */ - long xdl_opts; - int conflict_style; - enum { - MERGE_VARIANT_NORMAL = 0, - MERGE_VARIANT_OURS, - MERGE_VARIANT_THEIRS - } recursive_variant; - - /* console output related options */ - int verbosity; - unsigned buffer_output; /* 1: output at end, 2: keep buffered */ - struct strbuf obuf; /* output buffer; if buffer_output == 2, caller - * must handle and call strbuf_release */ - - /* miscellaneous control options */ - const char *subtree_shift; - unsigned renormalize : 1; - unsigned record_conflict_msgs_as_headers : 1; - const char *msg_header_prefix; - - /* internal fields used by the implementation */ - struct merge_options_internal *priv; -}; - -/* for use by porcelain commands */ -void init_ui_merge_options(struct merge_options *opt, struct repository *repo); -/* for use by plumbing commands */ -void init_basic_merge_options(struct merge_options *opt, struct repository *repo); - -void copy_merge_options(struct merge_options *dst, struct merge_options *src); -void clear_merge_options(struct merge_options *opt); - -/* parse the option in s and update the relevant field of opt */ -int parse_merge_opt(struct merge_options *opt, const char *s); - -/* - * RETURN VALUES: All the merge_* functions below return a value as follows: - * > 0 Merge was clean - * = 0 Merge had conflicts - * < 0 Merge hit an unexpected and unrecoverable problem (e.g. disk - * full) and aborted merge part-way through. - */ - -/* - * rename-detecting three-way merge, no recursion. - * - * Outputs: - * - See RETURN VALUES above - * - opt->repo->index has the new index - * - new index NOT written to disk - * - The working tree is updated with results of the merge - */ -int merge_trees(struct merge_options *opt, - struct tree *head, - struct tree *merge, - struct tree *merge_base); - -/* - * merge_recursive is like merge_trees() but with recursive ancestor - * consolidation. - * - * NOTE: empirically, about a decade ago it was determined that with more - * than two merge bases, optimal behavior was found when the - * merge_bases were passed in the order of oldest commit to newest - * commit. Also, merge_bases will be consumed (emptied) so make a - * copy if you need it. - * - * Outputs: - * - See RETURN VALUES above - * - *result is treated as scratch space for temporary recursive merges - * - opt->repo->index has the new index - * - new index NOT written to disk - * - The working tree is updated with results of the merge - */ -int merge_recursive(struct merge_options *opt, - struct commit *h1, - struct commit *h2, - const struct commit_list *merge_bases, - struct commit **result); - -/* - * merge_recursive_generic can operate on trees instead of commits, by - * wrapping the trees into virtual commits, and calling merge_recursive(). - * It also writes out the in-memory index to disk if the merge is successful. - * - * Outputs: - * - See RETURN VALUES above - * - *result is treated as scratch space for temporary recursive merges - * - opt->repo->index has the new index - * - new index also written to $GIT_INDEX_FILE on disk - * - The working tree is updated with results of the merge - */ -int merge_recursive_generic(struct merge_options *opt, - const struct object_id *head, - const struct object_id *merge, - int num_merge_bases, - const struct object_id *merge_bases, - struct commit **result); - -#endif diff --git a/mergetools/vimdiff b/mergetools/vimdiff index ffc9be86c8..fca1044f65 100644 --- a/mergetools/vimdiff +++ b/mergetools/vimdiff @@ -274,8 +274,8 @@ gen_cmd () { # definition. # # The syntax of the "layout definitions" is explained in "Documentation/ - # mergetools/vimdiff.txt" but you can already intuitively understand how - # it works by knowing that... + # mergetools/vimdiff.adoc" but you can already intuitively understand + # how it works by knowing that... # # * "+" means "a new vim tab" # * "/" means "a new vim horizontal split" @@ -305,6 +305,9 @@ gen_cmd () { elif echo "$LAYOUT" | grep @BASE >/dev/null then FINAL_TARGET="BASE" + elif echo "$LAYOUT" | grep @REMOTE >/dev/null + then + FINAL_TARGET="REMOTE" else FINAL_TARGET="MERGED" fi @@ -529,7 +532,7 @@ run_unit_tests () { # Function to make sure that we don't break anything when modifying this # script. - NUMBER_OF_TEST_CASES=16 + NUMBER_OF_TEST_CASES=19 TEST_CASE_01="(LOCAL,BASE,REMOTE)/MERGED" # default behaviour TEST_CASE_02="@LOCAL,REMOTE" # when using vimdiff1 @@ -547,6 +550,9 @@ run_unit_tests () { TEST_CASE_14="BASE,REMOTE+BASE,LOCAL" TEST_CASE_15=" (( (LOCAL , BASE , REMOTE) / MERGED)) +(BASE) , LOCAL+ BASE , REMOTE+ (((LOCAL / BASE / REMOTE)) , MERGED ) " TEST_CASE_16="LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE + (LOCAL / BASE / REMOTE),MERGED" + TEST_CASE_17="(LOCAL,@BASE,REMOTE)/MERGED" + TEST_CASE_18="LOCAL,@REMOTE" + TEST_CASE_19="@REMOTE" EXPECTED_CMD_01="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | execute 'tabdo windo diffthis' | tabfirst\"" EXPECTED_CMD_02="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 1b | wincmd l | 3b | execute 'tabdo windo diffthis' | tabfirst\"" @@ -564,6 +570,9 @@ run_unit_tests () { EXPECTED_CMD_14="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 2b | wincmd l | 3b | tabnew | leftabove vertical split | 2b | wincmd l | 1b | execute 'tabdo windo diffthis' | tabfirst\"" EXPECTED_CMD_15="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnew | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" EXPECTED_CMD_16="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnew | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | execute 'tabdo windo diffthis' | tabfirst\"" + EXPECTED_CMD_17="-c \"set hidden diffopt-=hiddenoff | echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | execute 'tabdo windo diffthis' | tabfirst\"" + EXPECTED_CMD_18="-c \"set hidden diffopt-=hiddenoff | echo | leftabove vertical split | 1b | wincmd l | 3b | execute 'tabdo windo diffthis' | tabfirst\"" + EXPECTED_CMD_19="-c \"set hidden diffopt-=hiddenoff | echo | silent execute 'bufdo diffthis' | 3b | execute 'tabdo windo diffthis' | tabfirst\"" EXPECTED_TARGET_01="MERGED" EXPECTED_TARGET_02="LOCAL" @@ -581,6 +590,9 @@ run_unit_tests () { EXPECTED_TARGET_14="MERGED" EXPECTED_TARGET_15="MERGED" EXPECTED_TARGET_16="MERGED" + EXPECTED_TARGET_17="BASE" + EXPECTED_TARGET_18="REMOTE" + EXPECTED_TARGET_19="REMOTE" at_least_one_ko="false" diff --git a/meson.build b/meson.build index efe2871c9d..7fea4a34d6 100644 --- a/meson.build +++ b/meson.build @@ -70,9 +70,15 @@ # # Execute single test interactively such that features like `debug ()` work. # $ meson test -i --test-args='-ix' t1400-update-ref # -# Test execution is parallelized by default and scales with the number of -# processor cores available. You can change the number of processes by passing -# the `-jN` flag to `meson test`. +# # Execute all benchmarks. +# $ meson test -i --benchmark +# +# # Execute single benchmark. +# $ meson test -i --benchmark p0000-* +# +# Test execution (but not benchmark execution) is parallelized by default and +# scales with the number of processor cores available. You can change the +# number of processes by passing the `-jN` flag to `meson test`. # # 4. Install the Git distribution. Again, this can be done via Meson, Ninja or # Samurai: @@ -155,6 +161,37 @@ # These machine files can be passed to `meson setup` via the `--native-file` # option. # +# Cross compilation +# ================= +# +# Machine files can also be used in the context of cross-compilation to +# describe the target machine as well as the cross-compiler toolchain that +# shall be used. An example machine file could look like the following: +# +# [binaries] +# c = 'x86_64-w64-mingw32-gcc' +# cpp = 'x86_64-w64-mingw32-g++' +# ar = 'x86_64-w64-mingw32-ar' +# windres = 'x86_64-w64-mingw32-windres' +# strip = 'x86_64-w64-mingw32-strip' +# exe_wrapper = 'wine64' +# sh = 'C:/Program Files/Git for Windows/usr/bin/sh.exe' +# +# [host_machine] +# system = 'windows' +# cpu_family = 'x86_64' +# cpu = 'x86_64' +# endian = 'little' +# +# These machine files can be passed to `meson setup` via the `--cross-file` +# option. +# +# Note that next to the cross-compiler toolchain, the `[binaries]` section is +# also used to locate a couple of binaries that will be built into Git. This +# includes `sh`, `python` and `perl`, so when cross-compiling Git you likely +# want to set these binary paths in addition to the cross-compiler toolchain +# binaries. +# # Subproject wrappers # =================== # @@ -173,19 +210,17 @@ project('git', 'c', # The version is only of cosmetic nature, so if we cannot find a shell yet we # simply don't set up a version at all. This may be the case for example on # Windows systems, where we first have to bootstrap the host environment. - version: find_program('sh', required: false).found() ? run_command( + version: find_program('sh', native: true, required: false).found() ? run_command( 'GIT-VERSION-GEN', meson.current_source_dir(), '--format=@GIT_VERSION@', capture: true, check: true, ).stdout().strip() : 'unknown', - default_options: [ - # Git requires C99 with GNU extensions, which of course isn't supported by - # MSVC. Funny enough, C99 doesn't work with MSVC either, as it has only - # learned to define __STDC_VERSION__ with C11 and later. We thus require - # GNU C99 and fall back to C11. Meson only learned to handle the fallback - # with version 1.3.0, so on older versions we use GNU C99 unconditionally. - 'c_std=' + (meson.version().version_compare('>=1.3.0') ? 'gnu99,c11' : 'gnu99'), - ], + # Git requires C99 with GNU extensions, which of course isn't supported by + # MSVC. Funny enough, C99 doesn't work with MSVC either, as it has only + # learned to define __STDC_VERSION__ with C11 and later. We thus require + # GNU C99 and fall back to C11. Meson only learned to handle the fallback + # with version 1.3.0, so on older versions we use GNU C99 unconditionally. + default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'], ) fs = import('fs') @@ -198,16 +233,23 @@ elif host_machine.system() == 'windows' program_path = [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] endif -cygpath = find_program('cygpath', dirs: program_path, required: false) -diff = find_program('diff', dirs: program_path) -git = find_program('git', dirs: program_path, required: false) -sed = find_program('sed', dirs: program_path) -shell = find_program('sh', dirs: program_path) -tar = find_program('tar', dirs: program_path) +cygpath = find_program('cygpath', dirs: program_path, native: true, required: false) +diff = find_program('diff', dirs: program_path, native: true) +git = find_program('git', dirs: program_path, native: true, required: false) +sed = find_program('sed', dirs: program_path, native: true) +shell = find_program('sh', dirs: program_path, native: true) +tar = find_program('tar', dirs: program_path, native: true) +time = find_program('time', dirs: program_path, required: get_option('benchmarks')) + +# Detect the target shell that is used by Git at runtime. Note that we prefer +# "/bin/sh" over a PATH-based lookup, which provides a working shell on most +# supported systems. This path is also the default shell path used by our +# Makefile. This lookup can be overridden via `program_path`. +target_shell = find_program('sh', dirs: program_path + [ '/bin' ], native: false) # Sanity-check that programs required for the build exist. foreach tool : ['cat', 'cut', 'grep', 'sort', 'tr', 'uname'] - find_program(tool, dirs: program_path) + find_program(tool, dirs: program_path, native: true) endforeach script_environment = environment() @@ -263,7 +305,9 @@ libgit_sources = [ 'common-init.c', 'compat/nonblock.c', 'compat/obstack.c', + 'compat/open.c', 'compat/terminal.c', + 'compiler-tricks/not-constant.c', 'config.c', 'connect.c', 'connected.c', @@ -310,6 +354,7 @@ libgit_sources = [ 'graph.c', 'grep.c', 'hash-lookup.c', + 'hash.c', 'hashmap.c', 'help.c', 'hex.c', @@ -337,7 +382,6 @@ libgit_sources = [ 'merge-ll.c', 'merge-ort.c', 'merge-ort-wrappers.c', - 'merge-recursive.c', 'merge.c', 'midx.c', 'midx-write.c', @@ -352,6 +396,7 @@ libgit_sources = [ 'object-file-convert.c', 'object-file.c', 'object-name.c', + 'object-store.c', 'object.c', 'oid-array.c', 'oidmap.c', @@ -410,10 +455,10 @@ libgit_sources = [ 'reftable/iter.c', 'reftable/merged.c', 'reftable/pq.c', - 'reftable/reader.c', 'reftable/record.c', 'reftable/stack.c', 'reftable/system.c', + 'reftable/table.c', 'reftable/tree.c', 'reftable/writer.c', 'remote.c', @@ -540,6 +585,7 @@ builtin_sources = [ 'builtin/diagnose.c', 'builtin/diff-files.c', 'builtin/diff-index.c', + 'builtin/diff-pairs.c', 'builtin/diff-tree.c', 'builtin/diff.c', 'builtin/difftool.c', @@ -581,7 +627,6 @@ builtin_sources = [ 'builtin/name-rev.c', 'builtin/notes.c', 'builtin/pack-objects.c', - 'builtin/pack-redundant.c', 'builtin/pack-refs.c', 'builtin/patch-id.c', 'builtin/prune-packed.c', @@ -632,6 +677,32 @@ builtin_sources = [ 'builtin/write-tree.c', ] +third_party_excludes = [ + ':!contrib', + ':!compat/inet_ntop.c', + ':!compat/inet_pton.c', + ':!compat/nedmalloc', + ':!compat/obstack.*', + ':!compat/poll', + ':!compat/regex', + ':!sha1collisiondetection', + ':!sha1dc', + ':!t/unit-tests/clar', + ':!t/t[0-9][0-9][0-9][0-9]*', + ':!xdiff', +] + +headers_to_check = [] +if git.found() and fs.exists(meson.project_source_root() / '.git') + foreach header : run_command(git, '-C', meson.project_source_root(), 'ls-files', '--deduplicate', '*.h', third_party_excludes, check: true).stdout().split() + headers_to_check += header + endforeach +endif + +if not get_option('breaking_changes') + builtin_sources += 'builtin/pack-redundant.c' +endif + builtin_sources += custom_target( output: 'config-list.h', command: [ @@ -659,24 +730,18 @@ builtin_sources += custom_target( # build options to our tests. build_options_config = configuration_data() build_options_config.set('GIT_INTEROP_MAKE_OPTS', '') -build_options_config.set('GIT_PERF_LARGE_REPO', '') +build_options_config.set_quoted('GIT_PERF_LARGE_REPO', get_option('benchmark_large_repo')) build_options_config.set('GIT_PERF_MAKE_COMMAND', '') build_options_config.set('GIT_PERF_MAKE_OPTS', '') -build_options_config.set('GIT_PERF_REPEAT_COUNT', '') -build_options_config.set('GIT_PERF_REPO', '') +build_options_config.set_quoted('GIT_PERF_REPEAT_COUNT', get_option('benchmark_repeat_count').to_string()) +build_options_config.set_quoted('GIT_PERF_REPO', get_option('benchmark_repo')) build_options_config.set('GIT_TEST_CMP_USE_COPIED_CONTEXT', '') build_options_config.set('GIT_TEST_INDEX_VERSION', '') build_options_config.set('GIT_TEST_OPTS', '') build_options_config.set('GIT_TEST_PERL_FATAL_WARNINGS', '') build_options_config.set_quoted('GIT_TEST_UTF8_LOCALE', get_option('test_utf8_locale')) build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) -build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) - -if get_option('breaking_changes') - build_options_config.set('WITH_BREAKING_CHANGES', 'YesPlease') -else - build_options_config.set('WITH_BREAKING_CHANGES', '') -endif +build_options_config.set_quoted('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) if get_option('sane_tool_path').length() != 0 sane_tool_path = (host_machine.system() == 'windows' ? ';' : ':').join(get_option('sane_tool_path')) @@ -693,12 +758,7 @@ endif # These variables are used for building libgit.a. libgit_c_args = [ '-DBINDIR="' + get_option('bindir') + '"', - '-DDEFAULT_EDITOR="' + get_option('default_editor') + '"', '-DDEFAULT_GIT_TEMPLATE_DIR="' + get_option('datadir') / 'git-core/templates' + '"', - '-DDEFAULT_HELP_FORMAT="' + get_option('default_help_format') + '"', - '-DDEFAULT_PAGER="' + get_option('default_pager') + '"', - '-DETC_GITATTRIBUTES="' + get_option('gitattributes') + '"', - '-DETC_GITCONFIG="' + get_option('gitconfig') + '"', '-DFALLBACK_RUNTIME_PREFIX="' + get_option('prefix') + '"', '-DGIT_HOST_CPU="' + host_machine.cpu_family() + '"', '-DGIT_HTML_PATH="' + get_option('datadir') / 'doc/git-doc"', @@ -706,8 +766,45 @@ libgit_c_args = [ '-DGIT_LOCALE_PATH="' + get_option('localedir') + '"', '-DGIT_MAN_PATH="' + get_option('mandir') + '"', '-DPAGER_ENV="' + get_option('pager_environment') + '"', - '-DSHELL_PATH="' + fs.as_posix(shell.full_path()) + '"', + '-DSHELL_PATH="' + fs.as_posix(target_shell.full_path()) + '"', ] + +system_attributes = get_option('gitattributes') +if system_attributes != '' + libgit_c_args += '-DETC_GITATTRIBUTES="' + system_attributes + '"' +else + libgit_c_args += '-DETC_GITATTRIBUTES="' + get_option('sysconfdir') / 'gitattributes"' +endif + +system_config = get_option('gitconfig') +if system_config != '' + libgit_c_args += '-DETC_GITCONFIG="' + system_config + '"' +else + libgit_c_args += '-DETC_GITCONFIG="' + get_option('sysconfdir') / 'gitconfig"' +endif + +editor_opt = get_option('default_editor') +if editor_opt != '' and editor_opt != 'vi' + libgit_c_args += '-DDEFAULT_EDITOR="' + editor_opt + '"' +endif + +pager_opt = get_option('default_pager') +if pager_opt != '' and pager_opt != 'less' + libgit_c_args += '-DDEFAULT_PAGER="' + pager_opt + '"' +endif + +help_format_opt = get_option('default_help_format') +if help_format_opt == 'platform' + if host_machine.system() == 'windows' + help_format_opt = 'html' + else + help_format_opt = 'man' + endif +endif +if help_format_opt != 'man' + libgit_c_args += '-DDEFAULT_HELP_FORMAT="' + help_format_opt + '"' +endif + libgit_include_directories = [ '.' ] libgit_dependencies = [ ] @@ -715,12 +812,14 @@ libgit_dependencies = [ ] # Makefile. if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argument_syntax() == 'gcc' foreach cflag : [ + '-Wcomma', '-Wdeclaration-after-statement', '-Wformat-security', '-Wold-style-definition', '-Woverflow', '-Wpointer-arith', '-Wstrict-prototypes', + '-Wunreachable-code', '-Wunused', '-Wvla', '-Wwrite-strings', @@ -739,6 +838,13 @@ if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argum endforeach endif +if get_option('breaking_changes') + build_options_config.set('WITH_BREAKING_CHANGES', 'YesPlease') + libgit_c_args += '-DWITH_BREAKING_CHANGES' +else + build_options_config.set('WITH_BREAKING_CHANGES', '') +endif + if get_option('b_sanitize').contains('address') build_options_config.set('SANITIZE_ADDRESS', 'YesCompiledWithIt') else @@ -761,6 +867,7 @@ endif build_options_config.set_quoted('X', executable_suffix) python = import('python').find_installation('python3', required: get_option('python')) +target_python = find_program('python3', native: false, required: python.found()) if python.found() build_options_config.set('NO_PYTHON', '') else @@ -772,7 +879,7 @@ endif # features. It is optional if you want to neither execute tests nor use any of # these optional features. perl_required = get_option('perl') -if get_option('tests') or get_option('gitweb').enabled() or 'netrc' in get_option('credential_helpers') +if get_option('benchmarks').enabled() or get_option('gitweb').enabled() or 'netrc' in get_option('credential_helpers') perl_required = true endif @@ -790,9 +897,11 @@ endif # which we can do starting with Meson 1.5.0 and newer, or we have to # match against the minor version. if meson.version().version_compare('>=1.5.0') - perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=5.26.0', version_argument: '-V:version') + perl = find_program('perl', dirs: program_path, native: true, required: perl_required, version: '>=5.26.0', version_argument: '-V:version') + target_perl = find_program('perl', dirs: program_path, native: false, required: perl.found(), version: '>=5.26.0', version_argument: '-V:version') else - perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=26') + perl = find_program('perl', dirs: program_path, native: true, required: perl_required, version: '>=26') + target_perl = find_program('perl', dirs: program_path, native: false, required: perl.found(), version: '>=26') endif perl_features_enabled = perl.found() and get_option('perl').allowed() if perl_features_enabled @@ -843,7 +952,7 @@ else build_options_config.set('NO_PTHREADS', '1') endif -msgfmt = find_program('msgfmt', dirs: program_path, required: false) +msgfmt = find_program('msgfmt', dirs: program_path, native: true, required: false) gettext_option = get_option('gettext').disable_auto_if(not msgfmt.found()) if not msgfmt.found() and gettext_option.enabled() error('Internationalization via libintl requires msgfmt') @@ -966,7 +1075,6 @@ if curl.found() # Most executables don't have to link against libcurl, but we still need its # include directories so that we can resolve LIBCURL_VERSION in "help.c". libgit_dependencies += curl.partial_dependency(includes: true) - libgit_c_args += '-DCURL_DISABLE_TYPECHECK' build_options_config.set('NO_CURL', '') else libgit_c_args += '-DNO_CURL' @@ -1014,10 +1122,6 @@ if compiler.has_header('alloca.h') libgit_c_args += '-DHAVE_ALLOCA_H' endif -if compiler.has_header('sys/sysinfo.h') - libgit_c_args += '-DHAVE_SYSINFO' -endif - # Windows has libgen.h and a basename implementation, but we still need our own # implementation to threat things like drive prefixes specially. if host_machine.system() == 'windows' or not compiler.has_header('libgen.h') @@ -1040,18 +1144,22 @@ if host_machine.system() == 'windows' networking_dependencies += winsock endif else - libresolv = compiler.find_library('resolv', required: false) - if libresolv.found() - networking_dependencies += libresolv - endif + networking_dependencies += [ + compiler.find_library('nsl', required: false), + compiler.find_library('resolv', required: false), + compiler.find_library('socket', required: false), + ] endif libgit_dependencies += networking_dependencies -foreach symbol : ['inet_ntop', 'inet_pton', 'strerror'] - if not compiler.has_function(symbol, dependencies: networking_dependencies) - libgit_c_args += '-DNO_' + symbol.to_upper() - endif -endforeach +if host_machine.system() != 'windows' + foreach symbol : ['inet_ntop', 'inet_pton', 'hstrerror'] + if not compiler.has_function(symbol, dependencies: networking_dependencies) + libgit_c_args += '-DNO_' + symbol.to_upper() + libgit_sources += 'compat/' + symbol + '.c' + endif + endforeach +endif has_ipv6 = compiler.has_function('getaddrinfo', dependencies: networking_dependencies) if not has_ipv6 @@ -1089,11 +1197,6 @@ else build_options_config.set('NO_UNIX_SOCKETS', '1') endif -if not compiler.has_function('pread') - libgit_c_args += '-DNO_PREAD' - libgit_sources += 'compat/pread.c' -endif - if host_machine.system() == 'darwin' libgit_sources += 'compat/precompose_utf8.c' libgit_c_args += '-DPRECOMPOSE_UNICODE' @@ -1107,7 +1210,6 @@ if host_machine.system() == 'cygwin' ] elif host_machine.system() == 'windows' libgit_sources += [ - 'compat/mingw.c', 'compat/winansi.c', 'compat/win32/dirent.c', 'compat/win32/flush.c', @@ -1134,6 +1236,9 @@ elif host_machine.system() == 'windows' libgit_include_directories += 'compat/win32' if compiler.get_id() == 'msvc' libgit_include_directories += 'compat/vcbuild/include' + libgit_sources += 'compat/msvc.c' + else + libgit_sources += 'compat/mingw.c' endif endif @@ -1226,6 +1331,10 @@ if host_machine.system() != 'windows' endif endif +if compiler.has_member('struct sysinfo', 'totalram', prefix: '#include <sys/sysinfo.h>') + libgit_c_args += '-DHAVE_SYSINFO' +endif + if compiler.has_member('struct stat', 'st_mtimespec.tv_nsec', prefix: '#include <sys/stat.h>') libgit_c_args += '-DUSE_ST_TIMESPEC' elif not compiler.has_member('struct stat', 'st_mtim.tv_nsec', prefix: '#include <sys/stat.h>') @@ -1244,23 +1353,41 @@ if not compiler.has_member('struct passwd', 'pw_gecos', prefix: '#include <pwd.h libgit_c_args += '-DNO_GECOS_IN_PWENT' endif -if compiler.has_function('sync_file_range') - libgit_c_args += '-DHAVE_SYNC_FILE_RANGE' -endif +checkfuncs = { + 'strcasestr' : ['strcasestr.c'], + 'memmem' : ['memmem.c'], + 'strlcpy' : ['strlcpy.c'], + 'strtoull' : [], + 'setenv' : ['setenv.c'], + 'mkdtemp' : ['mkdtemp.c'], + 'initgroups' : [], + 'strtoumax' : ['strtoumax.c', 'strtoimax.c'], + 'pread' : ['pread.c'], +} -if not compiler.has_function('strcasestr') - libgit_c_args += '-DNO_STRCASESTR' - libgit_sources += 'compat/strcasestr.c' +if host_machine.system() == 'windows' + libgit_c_args += '-DUSE_WIN32_MMAP' +else + checkfuncs += { + 'mmap' : ['mmap.c'], + # provided by compat/mingw.c. + 'unsetenv' : ['unsetenv.c'], + # provided by compat/mingw.c. + 'getpagesize' : [], + } endif -if not compiler.has_function('memmem') - libgit_c_args += '-DNO_MEMMEM' - libgit_sources += 'compat/memmem.c' -endif +foreach func, impls : checkfuncs + if not compiler.has_function(func) + libgit_c_args += '-DNO_' + func.to_upper() + foreach impl : impls + libgit_sources += 'compat/' + impl + endforeach + endif +endforeach -if not compiler.has_function('strlcpy') - libgit_c_args += '-DNO_STRLCPY' - libgit_sources += 'compat/strlcpy.c' +if compiler.has_function('sync_file_range') + libgit_c_args += '-DHAVE_SYNC_FILE_RANGE' endif if not compiler.has_function('strdup') @@ -1268,53 +1395,15 @@ if not compiler.has_function('strdup') libgit_sources += 'compat/strdup.c' endif -if not compiler.has_function('strtoumax') - libgit_c_args += '-DNO_STRTOUMAX' - libgit_sources += [ - 'compat/strtoumax.c', - 'compat/strtoimax.c', - ] -endif - -if not compiler.has_function('strtoull') - libgit_c_args += '-DNO_STRTOULL' -endif - -if not compiler.has_function('setenv') - libgit_c_args += '-DNO_SETENV' - libgit_sources += 'compat/setenv.c' -endif - if not compiler.has_function('qsort') libgit_c_args += '-DINTERNAL_QSORT' endif libgit_sources += 'compat/qsort_s.c' -# unsetenv is provided by compat/mingw.c. -if host_machine.system() != 'windows' and not compiler.has_function('unsetenv') - libgit_c_args += '-DNO_UNSETENV' - libgit_sources += 'compat/unsetenv.c' -endif - -if not compiler.has_function('mkdtemp') - libgit_c_args += '-DNO_MKDTEMP' - libgit_sources += 'compat/mkdtemp.c' -endif - -if not compiler.has_function('initgroups') - libgit_c_args += '-DNO_INITGROUPS' -endif - if compiler.has_function('getdelim') libgit_c_args += '-DHAVE_GETDELIM' endif -if host_machine.system() == 'windows' - libgit_c_args += '-DUSE_WIN32_MMAP' -elif not compiler.has_function('mmap') - libgit_c_args += '-DNO_MMAP' - libgit_sources += 'compat/mmap.c' -endif if compiler.has_function('clock_gettime') libgit_c_args += '-DHAVE_CLOCK_GETTIME' @@ -1505,10 +1594,19 @@ else error('Unsupported CSPRNG backend: ' + csprng_backend) endif +git_exec_path = 'libexec/git-core' +libexec = get_option('libexecdir') +if libexec != 'libexec' and libexec != '.' + git_exec_path = libexec +endif + if get_option('runtime_prefix') libgit_c_args += '-DRUNTIME_PREFIX' build_options_config.set('RUNTIME_PREFIX', 'true') - git_exec_path = get_option('libexecdir') / 'git-core' + + if git_exec_path.startswith('/') + error('runtime_prefix requires a relative libexecdir not:', libexec) + endif if compiler.has_header('mach-o/dyld.h') libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH' @@ -1545,7 +1643,6 @@ if get_option('runtime_prefix') endif else build_options_config.set('RUNTIME_PREFIX', 'false') - git_exec_path = get_option('prefix') / get_option('libexecdir') / 'git-core' endif libgit_c_args += '-DGIT_EXEC_PATH="' + git_exec_path + '"' @@ -1686,7 +1783,7 @@ bin_wrappers += executable('scalar', install_dir: get_option('libexecdir') / 'git-core', ) -if get_option('curl').enabled() +if curl.found() libgit_curl = declare_dependency( sources: [ 'http.c', @@ -1825,14 +1922,19 @@ if perl_features_enabled perl_header_template = 'perl/header_templates/runtime_prefix.template.pl' endif + perllibdir = get_option('perllibdir') + if perllibdir == '' + perllibdir = get_option('datadir') / 'perl5' + endif + perl_header = configure_file( input: perl_header_template, output: 'GIT-PERL-HEADER', configuration: { 'GITEXECDIR_REL': get_option('libexecdir') / 'git-core', - 'PERLLIBDIR_REL': get_option('datadir') / 'perl5', + 'PERLLIBDIR_REL': perllibdir, 'LOCALEDIR_REL': get_option('datadir') / 'locale', - 'INSTLIBDIR': get_option('datadir') / 'perl5', + 'INSTLIBDIR': perllibdir, 'PATHSEP': pathsep, }, ) @@ -1952,6 +2054,18 @@ subdir('templates') # can properly set up test dependencies. The bin-wrappers themselves are set up # at configuration time, so these are fine. if get_option('tests') + test_kwargs = { + 'timeout': 0, + } + + # The TAP protocol was already understood by previous versions of Meson, but + # it was incompatible with the `meson test --interactive` flag. + if meson.version().version_compare('>=1.8.0') + test_kwargs += { + 'protocol': 'tap', + } + endif + subdir('t') endif @@ -1966,6 +2080,70 @@ endif subdir('contrib') +exclude_from_check_headers = [ + 'compat/', + 'unicode-width.h', +] + +if sha1_backend != 'openssl' + exclude_from_check_headers += 'sha1/openssl.h' +endif +if sha256_backend != 'openssl' + exclude_from_check_headers += 'sha256/openssl.h' +endif +if sha256_backend != 'nettle' + exclude_from_check_headers += 'sha256/nettle.h' +endif +if sha256_backend != 'gcrypt' + exclude_from_check_headers += 'sha256/gcrypt.h' +endif + +if headers_to_check.length() != 0 and compiler.get_argument_syntax() == 'gcc' + hco_targets = [] + foreach h : headers_to_check + skip_header = false + foreach exclude : exclude_from_check_headers + if h.startswith(exclude) + skip_header = true + break + endif + endforeach + + if skip_header + continue + endif + + hcc = custom_target( + input: h, + output: h.underscorify() + 'cc', + command: [ + shell, + '-c', + 'echo \'#include "git-compat-util.h"\' > @OUTPUT@ && echo \'#include "' + h + '"\' >> @OUTPUT@' + ] + ) + + hco = custom_target( + input: hcc, + output: fs.replace_suffix(h.underscorify(), '.hco'), + command: [ + compiler.cmd_array(), + libgit_c_args, + '-I', meson.project_source_root(), + '-I', meson.project_source_root() / 't/unit-tests', + '-o', '/dev/null', + '-c', '-xc', + '@INPUT@' + ] + ) + hco_targets += hco + endforeach + + # TODO: deprecate 'hdr-check' in lieu of 'check-headers' in Git 2.51+ + hdr_check = alias_target('hdr-check', hco_targets) + alias_target('check-headers', hdr_check) +endif + foreach key, value : { 'DIFF': diff.full_path(), 'GIT_SOURCE_DIR': meson.project_source_root(), @@ -1974,9 +2152,9 @@ foreach key, value : { 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', 'PAGER_ENV': get_option('pager_environment'), - 'PERL_PATH': perl.found() ? perl.full_path() : '', - 'PYTHON_PATH': python.found () ? python.full_path() : '', - 'SHELL_PATH': shell.full_path(), + 'PERL_PATH': target_perl.found() ? target_perl.full_path() : '', + 'PYTHON_PATH': target_python.found () ? target_python.full_path() : '', + 'SHELL_PATH': target_shell.full_path(), 'TAR': tar.full_path(), 'TEST_OUTPUT_DIRECTORY': test_output_directory, 'TEST_SHELL_PATH': shell.full_path(), @@ -2015,6 +2193,7 @@ meson.add_dist_script( ) summary({ + 'benchmarks': get_option('tests') and perl.found() and time.found(), 'curl': curl.found(), 'expat': expat.found(), 'gettext': intl.found(), @@ -2034,3 +2213,9 @@ summary({ 'sha256': sha256_backend, 'zlib': zlib_backend, }, section: 'Backends') + +summary({ + 'perl': target_perl, + 'python': target_python, + 'shell': target_shell, +}, section: 'Runtime executable paths') diff --git a/meson_options.txt b/meson_options.txt index 78d172a740..e7f768df24 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,12 +1,16 @@ +# Configuration for Git installation +option('perllibdir', type: 'string', value: '', + description: 'Directory to install perl lib to. Defaults to <datadir>/perl5') + # Configuration for how Git behaves at runtime. option('default_pager', type: 'string', value: 'less', description: 'Fall-back pager.') option('default_editor', type: 'string', value: 'vi', description: 'Fall-back editor.') -option('gitconfig', type: 'string', value: '/etc/gitconfig', - description: 'Path to the global git configuration file.') -option('gitattributes', type: 'string', value: '/etc/gitattributes', - description: 'Path to the global git attributes file.') +option('gitconfig', type: 'string', + description: 'Path to the global git configuration file. (default: etc/gitconfig)') +option('gitattributes', type: 'string', + description: 'Path to the global git attributes file. (default: etc/gitattributes)') option('pager_environment', type: 'string', value: 'LESS=FRX LV=-c', description: 'Environment used when spawning the pager') option('perl_cpan_fallback', type: 'boolean', value: true, @@ -95,12 +99,20 @@ option('highlight_bin', type: 'string', value: 'highlight') # Documentation. option('docs', type: 'array', choices: ['man', 'html'], value: [], description: 'Which documenattion formats to build and install.') -option('default_help_format', type: 'combo', choices: ['man', 'html'], value: 'man', +option('default_help_format', type: 'combo', choices: ['man', 'html', 'platform'], value: 'platform', description: 'Default format used when executing git-help(1).') option('docs_backend', type: 'combo', choices: ['asciidoc', 'asciidoctor', 'auto'], value: 'auto', description: 'Which backend to use to generate documentation.') # Testing. +option('benchmarks', type: 'feature', value: 'auto', + description: 'Enable benchmarks. This requires Perl and GNU time.') +option('benchmark_repo', type: 'string', value: '', + description: 'Repository to copy for the performance tests. Should be at least the size of the Git repository.') +option('benchmark_large_repo', type: 'string', value: '', + description: 'Large repository to copy for the performance tests. Should be at least the size of the Linux repository.') +option('benchmark_repeat_count', type: 'integer', value: 3, + description: 'Number of times a test should be repeated for best-of-N measurements.') option('coccinelle', type: 'feature', value: 'auto', description: 'Provide a coccicheck target that generates a Coccinelle patch.') option('tests', type: 'boolean', value: true, diff --git a/midx-write.c b/midx-write.c index 48d6558253..ba4a94950a 100644 --- a/midx-write.c +++ b/midx-write.c @@ -647,18 +647,24 @@ static uint32_t *midx_pack_order(struct write_midx_context *ctx) return pack_order; } -static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash, - struct write_midx_context *ctx) +static void write_midx_reverse_index(struct write_midx_context *ctx, + const char *object_dir, + unsigned char *midx_hash) { struct strbuf buf = STRBUF_INIT; char *tmp_file; trace2_region_enter("midx", "write_midx_reverse_index", ctx->repo); - strbuf_addf(&buf, "%s-%s.rev", midx_name, hash_to_hex_algop(midx_hash, - ctx->repo->hash_algo)); + if (ctx->incremental) + get_split_midx_filename_ext(ctx->repo->hash_algo, &buf, + object_dir, midx_hash, + MIDX_EXT_REV); + else + get_midx_filename_ext(ctx->repo->hash_algo, &buf, object_dir, + midx_hash, MIDX_EXT_REV); - tmp_file = write_rev_file_order(ctx->repo->hash_algo, NULL, ctx->pack_order, + tmp_file = write_rev_file_order(ctx->repo, NULL, ctx->pack_order, ctx->entries_nr, midx_hash, WRITE_REV); if (finalize_object_file(tmp_file, buf.buf)) @@ -708,7 +714,7 @@ static int add_ref_to_pending(const char *refname, const char *referent UNUSED, if (!peel_iterated_oid(revs->repo, oid, &peeled)) oid = &peeled; - object = parse_object_or_die(oid, refname); + object = parse_object_or_die(revs->repo, oid, refname); if (object->type != OBJ_COMMIT) return 0; @@ -768,7 +774,7 @@ static int read_refs_snapshot(const char *refs_snapshot, if (*end) die(_("malformed line: %s"), buf.buf); - object = parse_object_or_die(&oid, NULL); + object = parse_object_or_die(revs->repo, &oid, NULL); if (preferred) object->flags |= NEEDS_BITMAP; @@ -829,22 +835,29 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr return cb.commits; } -static int write_midx_bitmap(struct repository *r, const char *midx_name, +static int write_midx_bitmap(struct write_midx_context *ctx, + const char *object_dir, 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 bitmap_writer writer; struct pack_idx_entry **index; - char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name, - hash_to_hex_algop(midx_hash, r->hash_algo)); + struct strbuf bitmap_name = STRBUF_INIT; + + trace2_region_enter("midx", "write_midx_bitmap", ctx->repo); - trace2_region_enter("midx", "write_midx_bitmap", r); + if (ctx->incremental) + get_split_midx_filename_ext(ctx->repo->hash_algo, &bitmap_name, + object_dir, midx_hash, + MIDX_EXT_BITMAP); + else + get_midx_filename_ext(ctx->repo->hash_algo, &bitmap_name, + object_dir, midx_hash, MIDX_EXT_BITMAP); if (flags & MIDX_WRITE_BITMAP_HASH_CACHE) options |= BITMAP_OPT_HASH_CACHE; @@ -861,7 +874,8 @@ static int write_midx_bitmap(struct repository *r, const char *midx_name, for (i = 0; i < pdata->nr_objects; i++) index[i] = &pdata->objects[i].idx; - bitmap_writer_init(&writer, r, pdata); + bitmap_writer_init(&writer, ctx->repo, pdata, + ctx->incremental ? ctx->base_midx : NULL); bitmap_writer_show_progress(&writer, flags & MIDX_PROGRESS); bitmap_writer_build_type_index(&writer, index); @@ -879,7 +893,7 @@ static int write_midx_bitmap(struct repository *r, const char *midx_name, * bitmap_writer_finish(). */ for (i = 0; i < pdata->nr_objects; i++) - index[pack_order[i]] = &pdata->objects[i].idx; + index[ctx->pack_order[i]] = &pdata->objects[i].idx; bitmap_writer_select_commits(&writer, commits, commits_nr); ret = bitmap_writer_build(&writer); @@ -887,14 +901,14 @@ static int write_midx_bitmap(struct repository *r, const char *midx_name, goto cleanup; bitmap_writer_set_checksum(&writer, midx_hash); - bitmap_writer_finish(&writer, index, bitmap_name, options); + bitmap_writer_finish(&writer, index, bitmap_name.buf, options); cleanup: free(index); - free(bitmap_name); + strbuf_release(&bitmap_name); bitmap_writer_free(&writer); - trace2_region_leave("midx", "write_midx_bitmap", r); + trace2_region_leave("midx", "write_midx_bitmap", ctx->repo); return ret; } @@ -1077,8 +1091,6 @@ static int write_midx_internal(struct repository *r, const char *object_dir, ctx.repo = r; ctx.incremental = !!(flags & MIDX_WRITE_INCREMENTAL); - if (ctx.incremental && (flags & MIDX_WRITE_BITMAP)) - die(_("cannot write incremental MIDX with bitmap")); if (ctx.incremental) strbuf_addf(&midx_name, @@ -1086,7 +1098,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir, object_dir); else get_midx_filename(r->hash_algo, &midx_name, object_dir); - if (safe_create_leading_directories(midx_name.buf)) + if (safe_create_leading_directories(r, midx_name.buf)) die_errno(_("unable to create leading directories of %s"), midx_name.buf); @@ -1119,6 +1131,13 @@ static int write_midx_internal(struct repository *r, const char *object_dir, if (ctx.incremental) { struct multi_pack_index *m = ctx.base_midx; while (m) { + if (flags & MIDX_WRITE_BITMAP && load_midx_revindex(m)) { + error(_("could not load reverse index for MIDX %s"), + hash_to_hex_algop(get_midx_checksum(m), + m->repo->hash_algo)); + result = 1; + goto cleanup; + } ctx.num_multi_pack_indexes_before++; m = m->base_midx; } @@ -1342,10 +1361,12 @@ static int write_midx_internal(struct repository *r, const char *object_dir, return -1; } - f = hashfd(get_tempfile_fd(incr), get_tempfile_path(incr)); + f = hashfd(r->hash_algo, get_tempfile_fd(incr), + get_tempfile_path(incr)); } else { hold_lock_file_for_update(&lk, midx_name.buf, LOCK_DIE_ON_ERROR); - f = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk)); + f = hashfd(r->hash_algo, get_lock_file_fd(&lk), + get_lock_file_path(&lk)); } cf = init_chunkfile(f); @@ -1387,7 +1408,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir, 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); + write_midx_reverse_index(&ctx, object_dir, midx_hash); if (flags & MIDX_WRITE_BITMAP) { struct packing_data pdata; @@ -1410,8 +1431,8 @@ static int write_midx_internal(struct repository *r, const char *object_dir, FREE_AND_NULL(ctx.entries); ctx.entries_nr = 0; - if (write_midx_bitmap(r, midx_name.buf, midx_hash, &pdata, - commits, commits_nr, ctx.pack_order, + if (write_midx_bitmap(&ctx, object_dir, + midx_hash, &pdata, commits, commits_nr, flags) < 0) { error(_("could not write multi-pack bitmap")); result = 1; @@ -1545,7 +1566,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla _("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); + uint32_t pack_int_id = nth_midxed_pack_int_id(m, i); count[pack_int_id]++; display_progress(progress, i + 1); } @@ -1676,21 +1697,31 @@ static void fill_included_packs_batch(struct repository *r, 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; + uint32_t pack_int_id = pack_info[i].pack_int_id; struct packed_git *p = m->packs[pack_int_id]; - size_t expected_size; + uint64_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); + /* + * Use shifted integer arithmetic to calculate the + * expected pack size to ~4 significant digits without + * overflow for packsizes less that 1PB. + */ + expected_size = (uint64_t)pack_info[i].referenced_objects << 14; expected_size /= p->num_objects; + expected_size = u64_mult(expected_size, p->pack_size); + expected_size = u64_add(expected_size, 1u << 13) >> 14; if (expected_size >= batch_size) continue; - total_size += expected_size; + if (unsigned_add_overflows(total_size, (size_t)expected_size)) + total_size = SIZE_MAX; + else + total_size += expected_size; + include_pack[pack_int_id] = 1; } @@ -5,7 +5,6 @@ #include "dir.h" #include "hex.h" #include "packfile.h" -#include "object-file.h" #include "hash-lookup.h" #include "midx.h" #include "progress.h" @@ -14,6 +13,8 @@ #include "pack-bitmap.h" #include "pack-revindex.h" +#define MIDX_PACK_ERROR ((void *)(intptr_t)-1) + int midx_checksum_valid(struct multi_pack_index *m); void clear_midx_files_ext(const char *object_dir, const char *ext, const char *keep_hash); @@ -406,7 +407,7 @@ void close_midx(struct multi_pack_index *m) munmap((unsigned char *)m->data, m->data_len); for (i = 0; i < m->num_packs; i++) { - if (m->packs[i]) + if (m->packs[i] && m->packs[i] != MIDX_PACK_ERROR) m->packs[i]->multi_pack_index = 0; } FREE_AND_NULL(m->packs); @@ -459,6 +460,8 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, pack_int_id = midx_for_pack(&m, pack_int_id); + if (m->packs[pack_int_id] == MIDX_PACK_ERROR) + return 1; if (m->packs[pack_int_id]) return 0; @@ -483,8 +486,10 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, strbuf_release(&pack_name); strbuf_release(&key); - if (!p) + if (!p) { + m->packs[pack_int_id] = MIDX_PACK_ERROR; return 1; + } p->multi_pack_index = 1; m->packs[pack_int_id] = p; @@ -496,6 +501,8 @@ struct packed_git *nth_midxed_pack(struct multi_pack_index *m, uint32_t pack_int_id) { uint32_t local_pack_int_id = midx_for_pack(&m, pack_int_id); + if (m->packs[local_pack_int_id] == MIDX_PACK_ERROR) + return NULL; return m->packs[local_pack_int_id]; } @@ -747,7 +754,8 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i int midx_checksum_valid(struct multi_pack_index *m) { - return hashfile_checksum_valid(m->data, m->data_len); + return hashfile_checksum_valid(m->repo->hash_algo, + m->data, m->data_len); } struct clear_midx_data { diff --git a/name-hash.c b/name-hash.c index d66de1cdfd..b91e276267 100644 --- a/name-hash.c +++ b/name-hash.c @@ -492,8 +492,10 @@ static void *lazy_name_thread_proc(void *_data) for (k = 0; k < d->istate->cache_nr; k++) { struct cache_entry *ce_k = d->istate->cache[k]; ce_k->ce_flags |= CE_HASHED; - hashmap_entry_init(&ce_k->ent, d->lazy_entries[k].hash_name); - hashmap_add(&d->istate->name_hash, &ce_k->ent); + if (!S_ISSPARSEDIR(ce_k->ce_mode)) { + hashmap_entry_init(&ce_k->ent, d->lazy_entries[k].hash_name); + hashmap_add(&d->istate->name_hash, &ce_k->ent); + } } return NULL; diff --git a/notes-cache.c b/notes-cache.c index ecfdf6e43b..150241b15e 100644 --- a/notes-cache.c +++ b/notes-cache.c @@ -2,7 +2,8 @@ #include "git-compat-util.h" #include "notes-cache.h" -#include "object-store-ll.h" +#include "object-file.h" +#include "object-store.h" #include "pretty.h" #include "repository.h" #include "commit.h" diff --git a/notes-merge.c b/notes-merge.c index 67a472020d..dae8e6a281 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -8,7 +8,7 @@ #include "refs.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "repository.h" #include "diff.h" @@ -296,7 +296,7 @@ static void check_notes_merge_worktree(struct notes_merge_options *o) "(%s exists)."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*")); } - if (safe_create_leading_directories_const(repo_git_path_replace(the_repository, &buf, + if (safe_create_leading_directories_const(the_repository, repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE "/.test"))) die_errno("unable to create directory %s", repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)); @@ -314,7 +314,7 @@ static void write_buf_to_worktree(const struct object_id *obj, { int fd; char *path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj)); - if (safe_create_leading_directories_const(path)) + if (safe_create_leading_directories_const(the_repository, path)) die_errno("unable to create directory for '%s'", path); fd = xopen(path, O_WRONLY | O_EXCL | O_CREAT, 0666); @@ -617,7 +617,7 @@ int notes_merge(struct notes_merge_options *o, if (repo_get_merge_bases(the_repository, local, remote, &bases) < 0) exit(128); if (!bases) { - base_oid = null_oid(); + base_oid = null_oid(the_hash_algo); base_tree_oid = the_hash_algo->empty_tree; if (o->verbosity >= 4) printf("No merge base found; doing history-less merge\n"); @@ -729,7 +729,7 @@ int notes_merge_commit(struct notes_merge_options *o, /* write file as blob, and add to partial_tree */ if (stat(path.buf, &st)) die_errno("Failed to stat '%s'", path.buf); - if (index_path(o->repo->index, &blob_oid, path.buf, &st, HASH_WRITE_OBJECT)) + if (index_path(o->repo->index, &blob_oid, path.buf, &st, INDEX_WRITE_OBJECT)) die("Failed to write blob object from '%s'", path.buf); if (add_note(partial_tree, &obj_oid, &blob_oid, NULL)) die("Failed to add resolved note '%s' to notes tree", @@ -6,8 +6,9 @@ #include "environment.h" #include "hex.h" #include "notes.h" +#include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "utf8.h" #include "strbuf.h" #include "tree-walk.h" @@ -793,7 +794,8 @@ static int prune_notes_helper(const struct object_id *object_oid, struct note_delete_list **l = (struct note_delete_list **) cb_data; struct note_delete_list *n; - if (repo_has_object_file(the_repository, object_oid)) + if (has_object(the_repository, object_oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return 0; /* nothing to do for this note */ /* failed to find object => prune this note */ @@ -1353,7 +1355,7 @@ int copy_note(struct notes_tree *t, if (note) return add_note(t, to_obj, note, combine_notes); else if (existing_note) - return add_note(t, to_obj, null_oid(), combine_notes); + return add_note(t, to_obj, null_oid(the_hash_algo), combine_notes); return 0; } diff --git a/object-file-convert.c b/object-file-convert.c index eba71955cf..7ab875afe6 100644 --- a/object-file-convert.c +++ b/object-file-convert.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -63,7 +62,8 @@ static int decode_tree_entry_raw(struct object_id *oid, const char **path, return 0; } -static int convert_tree_object(struct strbuf *out, +static int convert_tree_object(struct repository *repo, + struct strbuf *out, const struct git_hash_algo *from, const struct git_hash_algo *to, const char *buffer, size_t size) @@ -78,7 +78,7 @@ static int convert_tree_object(struct strbuf *out, 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)) + if (repo_oid_to_algop(repo, &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); @@ -88,7 +88,8 @@ static int convert_tree_object(struct strbuf *out, return 0; } -static int convert_tag_object(struct strbuf *out, +static int convert_tag_object(struct repository *repo, + struct strbuf *out, const struct git_hash_algo *from, const struct git_hash_algo *to, const char *buffer, size_t size) @@ -105,7 +106,7 @@ static int convert_tag_object(struct strbuf *out, 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)) + if (repo_oid_to_algop(repo, &oid, to, &mapped_oid)) return error("unable to map tree %s in tag object", oid_to_hex(&oid)); size -= ((p + 1) - buffer); @@ -139,7 +140,8 @@ static int convert_tag_object(struct strbuf *out, return 0; } -static int convert_commit_object(struct strbuf *out, +static int convert_commit_object(struct repository *repo, + struct strbuf *out, const struct git_hash_algo *from, const struct git_hash_algo *to, const char *buffer, size_t size) @@ -165,7 +167,7 @@ static int convert_commit_object(struct strbuf *out, (p != eol)) return error(_("bad %s in commit"), "tree"); - if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid)) + if (repo_oid_to_algop(repo, &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)); @@ -177,7 +179,7 @@ static int convert_commit_object(struct strbuf *out, (p != eol)) return error(_("bad %s in commit"), "parent"); - if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid)) + if (repo_oid_to_algop(repo, &oid, to, &mapped_oid)) return error(_("unable to map %s %s in commit object"), "parent", oid_to_hex(&oid)); @@ -202,7 +204,7 @@ static int convert_commit_object(struct strbuf *out, } /* Compute the new tag object */ - if (convert_tag_object(&new_tag, from, to, tag.buf, tag.len)) { + if (convert_tag_object(repo, &new_tag, from, to, tag.buf, tag.len)) { strbuf_release(&tag); strbuf_release(&new_tag); return -1; @@ -241,7 +243,8 @@ static int convert_commit_object(struct strbuf *out, return 0; } -int convert_object_file(struct strbuf *outbuf, +int convert_object_file(struct repository *repo, + struct strbuf *outbuf, const struct git_hash_algo *from, const struct git_hash_algo *to, const void *buf, size_t len, @@ -256,13 +259,13 @@ int convert_object_file(struct strbuf *outbuf, switch (type) { case OBJ_COMMIT: - ret = convert_commit_object(outbuf, from, to, buf, len); + ret = convert_commit_object(repo, outbuf, from, to, buf, len); break; case OBJ_TREE: - ret = convert_tree_object(outbuf, from, to, buf, len); + ret = convert_tree_object(repo, outbuf, from, to, buf, len); break; case OBJ_TAG: - ret = convert_tag_object(outbuf, from, to, buf, len); + ret = convert_tag_object(repo, outbuf, from, to, buf, len); break; default: /* Not implemented yet, so fail. */ diff --git a/object-file-convert.h b/object-file-convert.h index a4f802aa8e..9b3cc5e533 100644 --- a/object-file-convert.h +++ b/object-file-convert.h @@ -14,7 +14,8 @@ int repo_oid_to_algop(struct repository *repo, const struct object_id *src, * 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, +int convert_object_file(struct repository *repo, + struct strbuf *outbuf, const struct git_hash_algo *from, const struct git_hash_algo *to, const void *buf, size_t len, diff --git a/object-file.c b/object-file.c index 726e41a047..1ac04c2891 100644 --- a/object-file.c +++ b/object-file.c @@ -11,502 +11,37 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" -#include "abspath.h" -#include "config.h" +#include "bulk-checkin.h" #include "convert.h" +#include "dir.h" #include "environment.h" +#include "fsck.h" #include "gettext.h" #include "hex.h" -#include "string-list.h" -#include "lockfile.h" -#include "pack.h" -#include "commit.h" -#include "run-command.h" -#include "refs.h" -#include "bulk-checkin.h" -#include "repository.h" -#include "replace-object.h" -#include "streaming.h" -#include "dir.h" -#include "list.h" -#include "quote.h" -#include "packfile.h" +#include "loose.h" +#include "object-file-convert.h" #include "object-file.h" #include "object-store.h" #include "oidtree.h" +#include "pack.h" +#include "packfile.h" #include "path.h" -#include "promisor-remote.h" #include "setup.h" -#include "submodule.h" -#include "fsck.h" -#include "loose.h" -#include "object-file-convert.h" +#include "streaming.h" /* The maximum size for an object header. */ #define MAX_HEADER_LEN 32 -static const struct object_id empty_tree_oid = { - .hash = { - 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60, - 0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 - }, - .algo = GIT_HASH_SHA1, -}; -static const struct object_id empty_blob_oid = { - .hash = { - 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b, - 0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 - }, - .algo = GIT_HASH_SHA1, -}; -static const struct object_id null_oid_sha1 = { - .hash = {0}, - .algo = GIT_HASH_SHA1, -}; -static const struct object_id empty_tree_oid_sha256 = { - .hash = { - 0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1, - 0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5, - 0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc, - 0x53, 0x21 - }, - .algo = GIT_HASH_SHA256, -}; -static const struct object_id empty_blob_oid_sha256 = { - .hash = { - 0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2, - 0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43, - 0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72, - 0x18, 0x13 - }, - .algo = GIT_HASH_SHA256, -}; -static const struct object_id null_oid_sha256 = { - .hash = {0}, - .algo = GIT_HASH_SHA256, -}; - -static void git_hash_sha1_init(struct git_hash_ctx *ctx) -{ - ctx->algop = &hash_algos[GIT_HASH_SHA1]; - git_SHA1_Init(&ctx->state.sha1); -} - -static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) -{ - dst->algop = src->algop; - git_SHA1_Clone(&dst->state.sha1, &src->state.sha1); -} - -static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len) -{ - git_SHA1_Update(&ctx->state.sha1, data, len); -} - -static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx) -{ - git_SHA1_Final(hash, &ctx->state.sha1); -} - -static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) -{ - git_SHA1_Final(oid->hash, &ctx->state.sha1); - memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); - oid->algo = GIT_HASH_SHA1; -} - -static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx) -{ - ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]); - git_SHA1_Init_unsafe(&ctx->state.sha1_unsafe); -} - -static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src) -{ - dst->algop = src->algop; - git_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe); -} - -static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data, - size_t len) -{ - git_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len); -} - -static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx) -{ - git_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe); -} - -static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx) -{ - git_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe); - memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); - oid->algo = GIT_HASH_SHA1; -} - -static void git_hash_sha256_init(struct git_hash_ctx *ctx) -{ - ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]); - git_SHA256_Init(&ctx->state.sha256); -} - -static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) -{ - dst->algop = src->algop; - git_SHA256_Clone(&dst->state.sha256, &src->state.sha256); -} - -static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len) -{ - git_SHA256_Update(&ctx->state.sha256, data, len); -} - -static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx) -{ - git_SHA256_Final(hash, &ctx->state.sha256); -} - -static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) -{ - git_SHA256_Final(oid->hash, &ctx->state.sha256); - /* - * This currently does nothing, so the compiler should optimize it out, - * but keep it in case we extend the hash size again. - */ - memset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ); - oid->algo = GIT_HASH_SHA256; -} - -static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED) -{ - BUG("trying to init unknown hash"); -} - -static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED, - const struct git_hash_ctx *src UNUSED) -{ - BUG("trying to clone unknown hash"); -} - -static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED, - const void *data UNUSED, - size_t len UNUSED) -{ - BUG("trying to update unknown hash"); -} - -static void git_hash_unknown_final(unsigned char *hash UNUSED, - struct git_hash_ctx *ctx UNUSED) -{ - BUG("trying to finalize unknown hash"); -} - -static void git_hash_unknown_final_oid(struct object_id *oid UNUSED, - struct git_hash_ctx *ctx UNUSED) -{ - BUG("trying to finalize unknown hash"); -} - -static const struct git_hash_algo sha1_unsafe_algo = { - .name = "sha1", - .format_id = GIT_SHA1_FORMAT_ID, - .rawsz = GIT_SHA1_RAWSZ, - .hexsz = GIT_SHA1_HEXSZ, - .blksz = GIT_SHA1_BLKSZ, - .init_fn = git_hash_sha1_init_unsafe, - .clone_fn = git_hash_sha1_clone_unsafe, - .update_fn = git_hash_sha1_update_unsafe, - .final_fn = git_hash_sha1_final_unsafe, - .final_oid_fn = git_hash_sha1_final_oid_unsafe, - .empty_tree = &empty_tree_oid, - .empty_blob = &empty_blob_oid, - .null_oid = &null_oid_sha1, -}; - -const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { - { - .name = NULL, - .format_id = 0x00000000, - .rawsz = 0, - .hexsz = 0, - .blksz = 0, - .init_fn = git_hash_unknown_init, - .clone_fn = git_hash_unknown_clone, - .update_fn = git_hash_unknown_update, - .final_fn = git_hash_unknown_final, - .final_oid_fn = git_hash_unknown_final_oid, - .empty_tree = NULL, - .empty_blob = NULL, - .null_oid = NULL, - }, - { - .name = "sha1", - .format_id = GIT_SHA1_FORMAT_ID, - .rawsz = GIT_SHA1_RAWSZ, - .hexsz = GIT_SHA1_HEXSZ, - .blksz = GIT_SHA1_BLKSZ, - .init_fn = git_hash_sha1_init, - .clone_fn = git_hash_sha1_clone, - .update_fn = git_hash_sha1_update, - .final_fn = git_hash_sha1_final, - .final_oid_fn = git_hash_sha1_final_oid, - .unsafe = &sha1_unsafe_algo, - .empty_tree = &empty_tree_oid, - .empty_blob = &empty_blob_oid, - .null_oid = &null_oid_sha1, - }, - { - .name = "sha256", - .format_id = GIT_SHA256_FORMAT_ID, - .rawsz = GIT_SHA256_RAWSZ, - .hexsz = GIT_SHA256_HEXSZ, - .blksz = GIT_SHA256_BLKSZ, - .init_fn = git_hash_sha256_init, - .clone_fn = git_hash_sha256_clone, - .update_fn = git_hash_sha256_update, - .final_fn = git_hash_sha256_final, - .final_oid_fn = git_hash_sha256_final_oid, - .empty_tree = &empty_tree_oid_sha256, - .empty_blob = &empty_blob_oid_sha256, - .null_oid = &null_oid_sha256, - } -}; - -const struct object_id *null_oid(void) -{ - return the_hash_algo->null_oid; -} - -const char *empty_tree_oid_hex(const struct git_hash_algo *algop) -{ - static char buf[GIT_MAX_HEXSZ + 1]; - return oid_to_hex_r(buf, algop->empty_tree); -} - -int hash_algo_by_name(const char *name) -{ - int i; - if (!name) - return GIT_HASH_UNKNOWN; - for (i = 1; i < GIT_HASH_NALGOS; i++) - if (!strcmp(name, hash_algos[i].name)) - return i; - return GIT_HASH_UNKNOWN; -} - -int hash_algo_by_id(uint32_t format_id) -{ - int i; - for (i = 1; i < GIT_HASH_NALGOS; i++) - if (format_id == hash_algos[i].format_id) - return i; - return GIT_HASH_UNKNOWN; -} - -int hash_algo_by_length(int len) -{ - int i; - for (i = 1; i < GIT_HASH_NALGOS; i++) - if (len == hash_algos[i].rawsz) - return i; - return GIT_HASH_UNKNOWN; -} - -const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop) -{ - /* If we have a faster "unsafe" implementation, use that. */ - if (algop->unsafe) - return algop->unsafe; - /* Otherwise use the default one. */ - return algop; -} - -/* - * This is meant to hold a *small* number of objects that you would - * want repo_read_object_file() to be able to return, but yet you do not want - * to write them into the object store (e.g. a browse-only - * application). - */ -static struct cached_object_entry { - struct object_id oid; - struct cached_object { - enum object_type type; - const void *buf; - unsigned long size; - } value; -} *cached_objects; -static int cached_object_nr, cached_object_alloc; - -static const struct cached_object *find_cached_object(const struct object_id *oid) -{ - static const struct cached_object empty_tree = { - .type = OBJ_TREE, - .buf = "", - }; - int i; - const struct cached_object_entry *co = cached_objects; - - for (i = 0; i < cached_object_nr; i++, co++) { - if (oideq(&co->oid, oid)) - return &co->value; - } - if (oideq(oid, the_hash_algo->empty_tree)) - return &empty_tree; - return NULL; -} - - static int get_conv_flags(unsigned flags) { - if (flags & HASH_RENORMALIZE) + if (flags & INDEX_RENORMALIZE) return CONV_EOL_RENORMALIZE; - else if (flags & HASH_WRITE_OBJECT) + else if (flags & INDEX_WRITE_OBJECT) return global_conv_flags_eol | CONV_WRITE_OBJECT; else return 0; } - -int mkdir_in_gitdir(const char *path) -{ - if (mkdir(path, 0777)) { - int saved_errno = errno; - struct stat st; - struct strbuf sb = STRBUF_INIT; - - if (errno != EEXIST) - return -1; - /* - * Are we looking at a path in a symlinked worktree - * whose original repository does not yet have it? - * e.g. .git/rr-cache pointing at its original - * repository in which the user hasn't performed any - * conflict resolution yet? - */ - if (lstat(path, &st) || !S_ISLNK(st.st_mode) || - strbuf_readlink(&sb, path, st.st_size) || - !is_absolute_path(sb.buf) || - mkdir(sb.buf, 0777)) { - strbuf_release(&sb); - errno = saved_errno; - return -1; - } - strbuf_release(&sb); - } - return adjust_shared_perm(the_repository, path); -} - -static enum scld_error safe_create_leading_directories_1(char *path, int share) -{ - char *next_component = path + offset_1st_component(path); - enum scld_error ret = SCLD_OK; - - while (ret == SCLD_OK && next_component) { - struct stat st; - char *slash = next_component, slash_character; - - while (*slash && !is_dir_sep(*slash)) - slash++; - - if (!*slash) - break; - - next_component = slash + 1; - while (is_dir_sep(*next_component)) - next_component++; - if (!*next_component) - break; - - slash_character = *slash; - *slash = '\0'; - if (!stat(path, &st)) { - /* path exists */ - if (!S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - ret = SCLD_EXISTS; - } - } else if (mkdir(path, 0777)) { - if (errno == EEXIST && - !stat(path, &st) && S_ISDIR(st.st_mode)) - ; /* somebody created it since we checked */ - else if (errno == ENOENT) - /* - * Either mkdir() failed because - * somebody just pruned the containing - * directory, or stat() failed because - * the file that was in our way was - * just removed. Either way, inform - * the caller that it might be worth - * trying again: - */ - ret = SCLD_VANISHED; - else - ret = SCLD_FAILED; - } else if (share && adjust_shared_perm(the_repository, path)) { - ret = SCLD_PERMS; - } - *slash = slash_character; - } - return ret; -} - -enum scld_error safe_create_leading_directories(char *path) -{ - return safe_create_leading_directories_1(path, 1); -} - -enum scld_error safe_create_leading_directories_no_share(char *path) -{ - return safe_create_leading_directories_1(path, 0); -} - -enum scld_error safe_create_leading_directories_const(const char *path) -{ - int save_errno; - /* path points to cache entries, so xstrdup before messing with it */ - char *buf = xstrdup(path); - enum scld_error result = safe_create_leading_directories(buf); - - save_errno = errno; - free(buf); - errno = save_errno; - return result; -} - -int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) -{ - int fd; - /* - * we let the umask do its job, don't try to be more - * restrictive except to remove write permission. - */ - int mode = 0444; - repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); - fd = git_mkstemp_mode(temp_filename->buf, mode); - if (0 <= fd) - return fd; - - /* slow path */ - /* some mkstemp implementations erase temp_filename on failure */ - repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); - safe_create_leading_directories(temp_filename->buf); - return xmkstemp_mode(temp_filename->buf, mode); -} - -int odb_pack_keep(const char *name) -{ - int fd; - - fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600); - if (0 <= fd) - return fd; - - /* slow path */ - safe_create_leading_directories_const(name); - return open(name, O_RDWR|O_CREAT|O_EXCL, 0600); -} - static void fill_loose_path(struct strbuf *buf, const struct object_id *oid) { int i; @@ -520,9 +55,9 @@ static void fill_loose_path(struct strbuf *buf, const struct object_id *oid) } } -static const char *odb_loose_path(struct object_directory *odb, - struct strbuf *buf, - const struct object_id *oid) +const char *odb_loose_path(struct object_directory *odb, + struct strbuf *buf, + const struct object_id *oid) { strbuf_reset(buf); strbuf_addstr(buf, odb->path); @@ -531,513 +66,6 @@ static const char *odb_loose_path(struct object_directory *odb, return buf->buf; } -const char *loose_object_path(struct repository *r, struct strbuf *buf, - const struct object_id *oid) -{ - return odb_loose_path(r->objects->odb, buf, oid); -} - -/* - * Return non-zero iff the path is usable as an alternate object database. - */ -static int alt_odb_usable(struct raw_object_store *o, - struct strbuf *path, - const char *normalized_objdir, khiter_t *pos) -{ - int r; - - /* Detect cases where alternate disappeared */ - if (!is_directory(path->buf)) { - error(_("object directory %s does not exist; " - "check .git/objects/info/alternates"), - path->buf); - return 0; - } - - /* - * Prevent the common mistake of listing the same - * thing twice, or object directory itself. - */ - if (!o->odb_by_path) { - khiter_t p; - - o->odb_by_path = kh_init_odb_path_map(); - assert(!o->odb->next); - p = kh_put_odb_path_map(o->odb_by_path, o->odb->path, &r); - assert(r == 1); /* never used */ - kh_value(o->odb_by_path, p) = o->odb; - } - if (fspatheq(path->buf, normalized_objdir)) - return 0; - *pos = kh_put_odb_path_map(o->odb_by_path, path->buf, &r); - /* r: 0 = exists, 1 = never used, 2 = deleted */ - return r == 0 ? 0 : 1; -} - -/* - * Prepare alternate object database registry. - * - * The variable alt_odb_list points at the list of struct - * object_directory. The elements on this list come from - * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT - * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates, - * whose contents is similar to that environment variable but can be - * LF separated. Its base points at a statically allocated buffer that - * contains "/the/directory/corresponding/to/.git/objects/...", while - * its name points just after the slash at the end of ".git/objects/" - * in the example above, and has enough space to hold all hex characters - * of the object ID, an extra slash for the first level indirection, and - * the terminating NUL. - */ -static void read_info_alternates(struct repository *r, - const char *relative_base, - int depth); -static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry, - const char *relative_base, int depth, const char *normalized_objdir) -{ - struct object_directory *ent; - struct strbuf pathbuf = STRBUF_INIT; - struct strbuf tmp = STRBUF_INIT; - khiter_t pos; - int ret = -1; - - if (!is_absolute_path(entry->buf) && relative_base) { - strbuf_realpath(&pathbuf, relative_base, 1); - strbuf_addch(&pathbuf, '/'); - } - strbuf_addbuf(&pathbuf, entry); - - if (!strbuf_realpath(&tmp, pathbuf.buf, 0)) { - error(_("unable to normalize alternate object path: %s"), - pathbuf.buf); - goto error; - } - strbuf_swap(&pathbuf, &tmp); - - /* - * The trailing slash after the directory name is given by - * this function at the end. Remove duplicates. - */ - while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/') - strbuf_setlen(&pathbuf, pathbuf.len - 1); - - if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos)) - goto error; - - CALLOC_ARRAY(ent, 1); - /* pathbuf.buf is already in r->objects->odb_by_path */ - ent->path = strbuf_detach(&pathbuf, NULL); - - /* add the alternate entry */ - *r->objects->odb_tail = ent; - r->objects->odb_tail = &(ent->next); - ent->next = NULL; - assert(r->objects->odb_by_path); - kh_value(r->objects->odb_by_path, pos) = ent; - - /* recursively add alternates */ - read_info_alternates(r, ent->path, depth + 1); - ret = 0; - error: - strbuf_release(&tmp); - strbuf_release(&pathbuf); - return ret; -} - -static const char *parse_alt_odb_entry(const char *string, - int sep, - struct strbuf *out) -{ - const char *end; - - strbuf_reset(out); - - if (*string == '#') { - /* comment; consume up to next separator */ - end = strchrnul(string, sep); - } else if (*string == '"' && !unquote_c_style(out, string, &end)) { - /* - * quoted path; unquote_c_style has copied the - * data for us and set "end". Broken quoting (e.g., - * an entry that doesn't end with a quote) falls - * back to the unquoted case below. - */ - } else { - /* normal, unquoted path */ - end = strchrnul(string, sep); - strbuf_add(out, string, end - string); - } - - if (*end) - end++; - return end; -} - -static void link_alt_odb_entries(struct repository *r, const char *alt, - int sep, const char *relative_base, int depth) -{ - struct strbuf objdirbuf = STRBUF_INIT; - struct strbuf entry = STRBUF_INIT; - - if (!alt || !*alt) - return; - - if (depth > 5) { - error(_("%s: ignoring alternate object stores, nesting too deep"), - relative_base); - return; - } - - strbuf_realpath(&objdirbuf, r->objects->odb->path, 1); - - while (*alt) { - alt = parse_alt_odb_entry(alt, sep, &entry); - if (!entry.len) - continue; - link_alt_odb_entry(r, &entry, - relative_base, depth, objdirbuf.buf); - } - strbuf_release(&entry); - strbuf_release(&objdirbuf); -} - -static void read_info_alternates(struct repository *r, - const char *relative_base, - int depth) -{ - char *path; - struct strbuf buf = STRBUF_INIT; - - path = xstrfmt("%s/info/alternates", relative_base); - if (strbuf_read_file(&buf, path, 1024) < 0) { - warn_on_fopen_errors(path); - free(path); - return; - } - - link_alt_odb_entries(r, buf.buf, '\n', relative_base, depth); - strbuf_release(&buf); - free(path); -} - -void add_to_alternates_file(const char *reference) -{ - struct lock_file lock = LOCK_INIT; - char *alts = repo_git_path(the_repository, "objects/info/alternates"); - FILE *in, *out; - int found = 0; - - hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR); - out = fdopen_lock_file(&lock, "w"); - if (!out) - die_errno(_("unable to fdopen alternates lockfile")); - - in = fopen(alts, "r"); - if (in) { - struct strbuf line = STRBUF_INIT; - - while (strbuf_getline(&line, in) != EOF) { - if (!strcmp(reference, line.buf)) { - found = 1; - break; - } - fprintf_or_die(out, "%s\n", line.buf); - } - - strbuf_release(&line); - fclose(in); - } - else if (errno != ENOENT) - die_errno(_("unable to read alternates file")); - - if (found) { - rollback_lock_file(&lock); - } else { - fprintf_or_die(out, "%s\n", reference); - if (commit_lock_file(&lock)) - die_errno(_("unable to move new alternates file into place")); - if (the_repository->objects->loaded_alternates) - link_alt_odb_entries(the_repository, reference, - '\n', NULL, 0); - } - free(alts); -} - -void add_to_alternates_memory(const char *reference) -{ - /* - * Make sure alternates are initialized, or else our entry may be - * overwritten when they are. - */ - prepare_alt_odb(the_repository); - - link_alt_odb_entries(the_repository, reference, - '\n', NULL, 0); -} - -struct object_directory *set_temporary_primary_odb(const char *dir, int will_destroy) -{ - struct object_directory *new_odb; - - /* - * Make sure alternates are initialized, or else our entry may be - * overwritten when they are. - */ - prepare_alt_odb(the_repository); - - /* - * Make a new primary odb and link the old primary ODB in as an - * alternate - */ - new_odb = xcalloc(1, sizeof(*new_odb)); - new_odb->path = xstrdup(dir); - - /* - * Disable ref updates while a temporary odb is active, since - * the objects in the database may roll back. - */ - new_odb->disable_ref_updates = 1; - new_odb->will_destroy = will_destroy; - new_odb->next = the_repository->objects->odb; - the_repository->objects->odb = new_odb; - return new_odb->next; -} - -void restore_primary_odb(struct object_directory *restore_odb, const char *old_path) -{ - struct object_directory *cur_odb = the_repository->objects->odb; - - if (strcmp(old_path, cur_odb->path)) - BUG("expected %s as primary object store; found %s", - old_path, cur_odb->path); - - if (cur_odb->next != restore_odb) - BUG("we expect the old primary object store to be the first alternate"); - - the_repository->objects->odb = restore_odb; - free_object_directory(cur_odb); -} - -/* - * Compute the exact path an alternate is at and returns it. In case of - * error NULL is returned and the human readable error is added to `err` - * `path` may be relative and should point to $GIT_DIR. - * `err` must not be null. - */ -char *compute_alternate_path(const char *path, struct strbuf *err) -{ - char *ref_git = NULL; - const char *repo; - int seen_error = 0; - - ref_git = real_pathdup(path, 0); - if (!ref_git) { - seen_error = 1; - strbuf_addf(err, _("path '%s' does not exist"), path); - goto out; - } - - repo = read_gitfile(ref_git); - if (!repo) - repo = read_gitfile(mkpath("%s/.git", ref_git)); - if (repo) { - free(ref_git); - ref_git = xstrdup(repo); - } - - if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { - char *ref_git_git = mkpathdup("%s/.git", ref_git); - free(ref_git); - ref_git = ref_git_git; - } else if (!is_directory(mkpath("%s/objects", ref_git))) { - struct strbuf sb = STRBUF_INIT; - seen_error = 1; - if (get_common_dir(&sb, ref_git)) { - strbuf_addf(err, - _("reference repository '%s' as a linked " - "checkout is not supported yet."), - path); - goto out; - } - - strbuf_addf(err, _("reference repository '%s' is not a " - "local repository."), path); - goto out; - } - - if (!access(mkpath("%s/shallow", ref_git), F_OK)) { - strbuf_addf(err, _("reference repository '%s' is shallow"), - path); - seen_error = 1; - goto out; - } - - if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) { - strbuf_addf(err, - _("reference repository '%s' is grafted"), - path); - seen_error = 1; - goto out; - } - -out: - if (seen_error) { - FREE_AND_NULL(ref_git); - } - - return ref_git; -} - -struct object_directory *find_odb(struct repository *r, const char *obj_dir) -{ - struct object_directory *odb; - char *obj_dir_real = real_pathdup(obj_dir, 1); - struct strbuf odb_path_real = STRBUF_INIT; - - prepare_alt_odb(r); - for (odb = r->objects->odb; odb; odb = odb->next) { - strbuf_realpath(&odb_path_real, odb->path, 1); - if (!strcmp(obj_dir_real, odb_path_real.buf)) - break; - } - - free(obj_dir_real); - strbuf_release(&odb_path_real); - - if (!odb) - die(_("could not find object directory matching %s"), obj_dir); - return odb; -} - -static void fill_alternate_refs_command(struct child_process *cmd, - const char *repo_path) -{ - const char *value; - - if (!git_config_get_value("core.alternateRefsCommand", &value)) { - cmd->use_shell = 1; - - strvec_push(&cmd->args, value); - strvec_push(&cmd->args, repo_path); - } else { - cmd->git_cmd = 1; - - strvec_pushf(&cmd->args, "--git-dir=%s", repo_path); - strvec_push(&cmd->args, "for-each-ref"); - strvec_push(&cmd->args, "--format=%(objectname)"); - - if (!git_config_get_value("core.alternateRefsPrefixes", &value)) { - strvec_push(&cmd->args, "--"); - strvec_split(&cmd->args, value); - } - } - - strvec_pushv(&cmd->env, (const char **)local_repo_env); - cmd->out = -1; -} - -static void read_alternate_refs(const char *path, - alternate_ref_fn *cb, - void *data) -{ - struct child_process cmd = CHILD_PROCESS_INIT; - struct strbuf line = STRBUF_INIT; - FILE *fh; - - fill_alternate_refs_command(&cmd, path); - - if (start_command(&cmd)) - return; - - fh = xfdopen(cmd.out, "r"); - while (strbuf_getline_lf(&line, fh) != EOF) { - struct object_id oid; - const char *p; - - if (parse_oid_hex(line.buf, &oid, &p) || *p) { - warning(_("invalid line while parsing alternate refs: %s"), - line.buf); - break; - } - - cb(&oid, data); - } - - fclose(fh); - finish_command(&cmd); - strbuf_release(&line); -} - -struct alternate_refs_data { - alternate_ref_fn *fn; - void *data; -}; - -static int refs_from_alternate_cb(struct object_directory *e, - void *data) -{ - struct strbuf path = STRBUF_INIT; - size_t base_len; - struct alternate_refs_data *cb = data; - - if (!strbuf_realpath(&path, e->path, 0)) - goto out; - if (!strbuf_strip_suffix(&path, "/objects")) - goto out; - base_len = path.len; - - /* Is this a git repository with refs? */ - strbuf_addstr(&path, "/refs"); - if (!is_directory(path.buf)) - goto out; - strbuf_setlen(&path, base_len); - - read_alternate_refs(path.buf, cb->fn, cb->data); - -out: - strbuf_release(&path); - return 0; -} - -void for_each_alternate_ref(alternate_ref_fn fn, void *data) -{ - struct alternate_refs_data cb; - cb.fn = fn; - cb.data = data; - foreach_alt_odb(refs_from_alternate_cb, &cb); -} - -int foreach_alt_odb(alt_odb_fn fn, void *cb) -{ - struct object_directory *ent; - int r = 0; - - prepare_alt_odb(the_repository); - for (ent = the_repository->objects->odb->next; ent; ent = ent->next) { - r = fn(ent, cb); - if (r) - break; - } - return r; -} - -void prepare_alt_odb(struct repository *r) -{ - if (r->objects->loaded_alternates) - return; - - link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0); - - read_info_alternates(r, r->objects->odb->path, 0); - r->objects->loaded_alternates = 1; -} - -int has_alt_odb(struct repository *r) -{ - prepare_alt_odb(r); - return !!r->objects->odb->next; -} - /* Returns 1 if we have successfully freshened the file, 0 otherwise. */ static int freshen_file(const char *fn) { @@ -1102,60 +130,6 @@ int has_loose_object(const struct object_id *oid) return check_and_freshen(oid, 0); } -static void mmap_limit_check(size_t length) -{ - static size_t limit = 0; - if (!limit) { - limit = git_env_ulong("GIT_MMAP_LIMIT", 0); - if (!limit) - limit = SIZE_MAX; - } - if (length > limit) - die(_("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX), - (uintmax_t)length, (uintmax_t)limit); -} - -void *xmmap_gently(void *start, size_t length, - int prot, int flags, int fd, off_t offset) -{ - void *ret; - - mmap_limit_check(length); - ret = mmap(start, length, prot, flags, fd, offset); - if (ret == MAP_FAILED && !length) - ret = NULL; - return ret; -} - -const char *mmap_os_err(void) -{ - static const char blank[] = ""; -#if defined(__linux__) - if (errno == ENOMEM) { - /* this continues an existing error message: */ - static const char enomem[] = -", check sys.vm.max_map_count and/or RLIMIT_DATA"; - return enomem; - } -#endif /* OS-specific bits */ - return blank; -} - -void *xmmap(void *start, size_t length, - int prot, int flags, int fd, off_t offset) -{ - void *ret = xmmap_gently(start, length, prot, flags, fd, offset); - if (ret == MAP_FAILED) - die_errno(_("mmap failed%s"), mmap_os_err()); - return ret; -} - -static int format_object_header_literally(char *str, size_t size, - const char *type, size_t objsize) -{ - return xsnprintf(str, size, "%s %"PRIuMAX, type, (uintmax_t)objsize) + 1; -} - int format_object_header(char *str, size_t size, enum object_type type, size_t objsize) { @@ -1164,7 +138,7 @@ int format_object_header(char *str, size_t size, enum object_type type, if (!name) BUG("could not get a type name for 'enum object_type' value %d", type); - return format_object_header_literally(str, size, name, objsize); + return xsnprintf(str, size, "%s %"PRIuMAX, name, (uintmax_t)objsize) + 1; } int check_object_signature(struct repository *r, const struct object_id *oid, @@ -1217,33 +191,6 @@ int stream_object_signature(struct repository *r, const struct object_id *oid) return !oideq(oid, &real_oid) ? -1 : 0; } -int git_open_cloexec(const char *name, int flags) -{ - int fd; - static int o_cloexec = O_CLOEXEC; - - fd = open(name, flags | o_cloexec); - if ((o_cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) { - /* Try again w/o O_CLOEXEC: the kernel might not support it */ - o_cloexec &= ~O_CLOEXEC; - fd = open(name, flags | o_cloexec); - } - -#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) - { - static int fd_cloexec = FD_CLOEXEC; - - if (!o_cloexec && 0 <= fd && fd_cloexec) { - /* Opened w/o O_CLOEXEC? try with fcntl(2) to add it */ - int flags = fcntl(fd, F_GETFD); - if (fcntl(fd, F_SETFD, flags | fd_cloexec)) - fd_cloexec = 0; - } - } -#endif - return fd; -} - /* * Find "oid" as a loose object in the local repository or in an alternate. * Returns 0 on success, negative on failure. @@ -1346,8 +293,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, - unsigned long bufsiz, - struct strbuf *header) + unsigned long bufsiz) { int status; @@ -1362,7 +308,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, obj_read_unlock(); status = git_inflate(stream, 0); obj_read_lock(); - if (status < Z_OK) + if (status != Z_OK && status != Z_STREAM_END) return ULHR_BAD; /* @@ -1372,32 +318,8 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, return ULHR_OK; /* - * We have a header longer than MAX_HEADER_LEN. The "header" - * here is only non-NULL when we run "cat-file - * --allow-unknown-type". - */ - if (!header) - return ULHR_TOO_LONG; - - /* - * buffer[0..bufsiz] was not large enough. Copy the partial - * result out to header, and then append the result of further - * reading the stream. + * We have a header longer than MAX_HEADER_LEN. */ - strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer); - stream->next_out = buffer; - stream->avail_out = bufsiz; - - do { - obj_read_unlock(); - status = git_inflate(stream, 0); - obj_read_lock(); - strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer); - if (memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer)) - return 0; - stream->next_out = buffer; - stream->avail_out = bufsiz; - } while (status != Z_STREAM_END); return ULHR_TOO_LONG; } @@ -1437,18 +359,17 @@ static void *unpack_loose_rest(git_zstream *stream, obj_read_lock(); } } - if (status == Z_STREAM_END && !stream->avail_in) { - git_inflate_end(stream); - return buf; - } - if (status < 0) + if (status != Z_STREAM_END) { error(_("corrupt loose object '%s'"), oid_to_hex(oid)); - else if (stream->avail_in) + FREE_AND_NULL(buf); + } else if (stream->avail_in) { error(_("garbage at end of loose object '%s'"), oid_to_hex(oid)); - free(buf); - return NULL; + FREE_AND_NULL(buf); + } + + return buf; } /* @@ -1476,8 +397,6 @@ int parse_loose_header(const char *hdr, struct object_info *oi) } type = type_from_string_gently(type_buf, type_len, 1); - if (oi->type_name) - strbuf_add(oi->type_name, type_buf, type_len); if (oi->typep) *oi->typep = type; @@ -1514,9 +433,9 @@ int parse_loose_header(const char *hdr, struct object_info *oi) return 0; } -static int loose_object_info(struct repository *r, - const struct object_id *oid, - struct object_info *oi, int flags) +int loose_object_info(struct repository *r, + const struct object_id *oid, + struct object_info *oi, int flags) { int status = 0; int fd; @@ -1525,10 +444,8 @@ static int loose_object_info(struct repository *r, void *map; git_zstream stream; char hdr[MAX_HEADER_LEN]; - struct strbuf hdrbuf = STRBUF_INIT; unsigned long size_scratch; enum object_type type_scratch; - int allow_unknown = flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE; if (oi->delta_base_oid) oidclr(oi->delta_base_oid, the_repository->hash_algo); @@ -1541,7 +458,7 @@ static int loose_object_info(struct repository *r, * return value implicitly indicates whether the * object even exists. */ - if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) { + if (!oi->typep && !oi->sizep && !oi->contentp) { struct stat st; if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK)) return quick_has_loose(r, oid) ? 0 : -1; @@ -1570,12 +487,11 @@ static int loose_object_info(struct repository *r, if (oi->disk_sizep) *oi->disk_sizep = mapsize; - switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr), - allow_unknown ? &hdrbuf : NULL)) { + switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) { case ULHR_OK: - if (parse_loose_header(hdrbuf.len ? hdrbuf.buf : hdr, oi) < 0) + if (parse_loose_header(hdr, oi) < 0) status = error(_("unable to parse %s header"), oid_to_hex(oid)); - else if (!allow_unknown && *oi->typep < 0) + else if (*oi->typep < 0) die(_("invalid object type")); if (!oi->contentp) @@ -1600,357 +516,17 @@ static int loose_object_info(struct repository *r, die(_("loose object %s (stored in %s) is corrupt"), oid_to_hex(oid), path); - git_inflate_end(&stream); cleanup: + git_inflate_end(&stream); munmap(map, mapsize); if (oi->sizep == &size_scratch) oi->sizep = NULL; - strbuf_release(&hdrbuf); if (oi->typep == &type_scratch) oi->typep = NULL; oi->whence = OI_LOOSE; return status; } -int obj_read_use_lock = 0; -pthread_mutex_t obj_read_mutex; - -void enable_obj_read_lock(void) -{ - if (obj_read_use_lock) - return; - - obj_read_use_lock = 1; - init_recursive_mutex(&obj_read_mutex); -} - -void disable_obj_read_lock(void) -{ - if (!obj_read_use_lock) - return; - - obj_read_use_lock = 0; - pthread_mutex_destroy(&obj_read_mutex); -} - -int fetch_if_missing = 1; - -static int do_oid_object_info_extended(struct repository *r, - const struct object_id *oid, - struct object_info *oi, unsigned flags) -{ - static struct object_info blank_oi = OBJECT_INFO_INIT; - const struct cached_object *co; - struct pack_entry e; - int rtype; - const struct object_id *real = oid; - int already_retried = 0; - - - if (flags & OBJECT_INFO_LOOKUP_REPLACE) - real = lookup_replace_object(r, oid); - - if (is_null_oid(real)) - return -1; - - if (!oi) - oi = &blank_oi; - - co = find_cached_object(real); - if (co) { - if (oi->typep) - *(oi->typep) = co->type; - if (oi->sizep) - *(oi->sizep) = co->size; - if (oi->disk_sizep) - *(oi->disk_sizep) = 0; - if (oi->delta_base_oid) - oidclr(oi->delta_base_oid, the_repository->hash_algo); - if (oi->type_name) - strbuf_addstr(oi->type_name, type_name(co->type)); - if (oi->contentp) - *oi->contentp = xmemdupz(co->buf, co->size); - oi->whence = OI_CACHED; - return 0; - } - - while (1) { - if (find_pack_entry(r, real, &e)) - break; - - /* Most likely it's a loose object. */ - if (!loose_object_info(r, real, oi, flags)) - return 0; - - /* Not a loose object; someone else may have just packed it. */ - if (!(flags & OBJECT_INFO_QUICK)) { - reprepare_packed_git(r); - if (find_pack_entry(r, real, &e)) - break; - } - - /* - * If r is the_repository, this might be an attempt at - * accessing a submodule object as if it were in the_repository - * (having called add_submodule_odb() on that submodule's ODB). - * If any such ODBs exist, register them and try again. - */ - if (r == the_repository && - register_all_submodule_odb_as_alternates()) - /* We added some alternates; retry */ - continue; - - /* Check if it is a missing object */ - if (fetch_if_missing && repo_has_promisor_remote(r) && - !already_retried && - !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) { - promisor_remote_get_direct(r, real, 1); - already_retried = 1; - continue; - } - - if (flags & OBJECT_INFO_DIE_IF_CORRUPT) { - const struct packed_git *p; - if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid)) - die(_("replacement %s not found for %s"), - oid_to_hex(real), oid_to_hex(oid)); - if ((p = has_packed_and_bad(r, real))) - die(_("packed object %s (stored in %s) is corrupt"), - oid_to_hex(real), p->pack_name); - } - return -1; - } - - if (oi == &blank_oi) - /* - * We know that the caller doesn't actually need the - * information below, so return early. - */ - return 0; - rtype = packed_object_info(r, e.p, e.offset, oi); - if (rtype < 0) { - mark_bad_packed_object(e.p, real); - return do_oid_object_info_extended(r, real, oi, 0); - } else if (oi->whence == OI_PACKED) { - oi->u.packed.offset = e.offset; - oi->u.packed.pack = e.p; - oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA || - rtype == OBJ_OFS_DELTA); - } - - 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); - free(content); - if (ret == -1) - return -1; - 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(); - return ret; -} - - -/* returns enum object_type or negative */ -int oid_object_info(struct repository *r, - const struct object_id *oid, - unsigned long *sizep) -{ - enum object_type type; - struct object_info oi = OBJECT_INFO_INIT; - - oi.typep = &type; - oi.sizep = sizep; - if (oid_object_info_extended(r, oid, &oi, - OBJECT_INFO_LOOKUP_REPLACE) < 0) - return -1; - return type; -} - -int pretend_object_file(void *buf, unsigned long len, enum object_type type, - struct object_id *oid) -{ - struct cached_object_entry *co; - char *co_buf; - - hash_object_file(the_hash_algo, buf, len, type, oid); - if (repo_has_object_file_with_flags(the_repository, oid, OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT) || - find_cached_object(oid)) - return 0; - ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc); - co = &cached_objects[cached_object_nr++]; - co->value.size = len; - co->value.type = type; - co_buf = xmalloc(len); - memcpy(co_buf, buf, len); - co->value.buf = co_buf; - oidcpy(&co->oid, oid); - return 0; -} - -/* - * This function dies on corrupt objects; the callers who want to - * deal with them should arrange to call oid_object_info_extended() and give - * error messages themselves. - */ -void *repo_read_object_file(struct repository *r, - const struct object_id *oid, - enum object_type *type, - unsigned long *size) -{ - struct object_info oi = OBJECT_INFO_INIT; - unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE; - void *data; - - oi.typep = type; - oi.sizep = size; - oi.contentp = &data; - if (oid_object_info_extended(r, oid, &oi, flags)) - return NULL; - - return data; -} - -void *read_object_with_reference(struct repository *r, - const struct object_id *oid, - enum object_type required_type, - unsigned long *size, - struct object_id *actual_oid_return) -{ - enum object_type type; - void *buffer; - unsigned long isize; - struct object_id actual_oid; - - oidcpy(&actual_oid, oid); - while (1) { - int ref_length = -1; - const char *ref_type = NULL; - - buffer = repo_read_object_file(r, &actual_oid, &type, &isize); - if (!buffer) - return NULL; - if (type == required_type) { - *size = isize; - if (actual_oid_return) - oidcpy(actual_oid_return, &actual_oid); - return buffer; - } - /* Handle references */ - else if (type == OBJ_COMMIT) - ref_type = "tree "; - else if (type == OBJ_TAG) - ref_type = "object "; - else { - free(buffer); - return NULL; - } - ref_length = strlen(ref_type); - - if (ref_length + the_hash_algo->hexsz > isize || - memcmp(buffer, ref_type, ref_length) || - get_oid_hex((char *) buffer + ref_length, &actual_oid)) { - free(buffer); - return NULL; - } - free(buffer); - /* Now we have the ID of the referred-to object in - * actual_oid. Check again. */ - } -} - static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c, const void *buf, unsigned long len, struct object_id *oid, @@ -1976,17 +552,6 @@ static void write_object_file_prepare(const struct git_hash_algo *algo, hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); } -static void write_object_file_prepare_literally(const struct git_hash_algo *algo, - const void *buf, unsigned long len, - const char *type, struct object_id *oid, - char *hdr, int *hdrlen) -{ - struct git_hash_ctx c; - - *hdrlen = format_object_header_literally(hdr, *hdrlen, type, len); - hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); -} - #define CHECK_COLLISION_DEST_VANISHED -2 static int check_collision(const char *source, const char *dest) @@ -2116,21 +681,14 @@ out: return 0; } -static void hash_object_file_literally(const struct git_hash_algo *algo, - const void *buf, unsigned long len, - const char *type, struct object_id *oid) -{ - char hdr[MAX_HEADER_LEN]; - int hdrlen = sizeof(hdr); - - write_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen); -} - void hash_object_file(const struct git_hash_algo *algo, const void *buf, unsigned long len, enum object_type type, struct object_id *oid) { - hash_object_file_literally(algo, buf, len, type_name(type), oid); + char hdr[MAX_HEADER_LEN]; + int hdrlen = sizeof(hdr); + + write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); } /* Finalize a file on disk, and close it. */ @@ -2222,7 +780,7 @@ static int start_loose_object_common(struct strbuf *tmp_file, fd = create_tmpfile(tmp_file, filename); if (fd < 0) { - if (flags & HASH_SILENT) + if (flags & WRITE_OBJECT_FILE_SILENT) return -1; else if (errno == EACCES) return error(_("insufficient permission for adding " @@ -2318,7 +876,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr, if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT)) prepare_loose_object_bulk_checkin(); - loose_object_path(the_repository, &filename, oid); + odb_loose_path(the_repository->objects->odb, &filename, oid); fd = start_loose_object_common(&tmp_file, filename.buf, flags, &stream, compressed, sizeof(compressed), @@ -2354,7 +912,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr, utb.actime = mtime; utb.modtime = mtime; if (utime(tmp_file.buf, &utb) < 0 && - !(flags & HASH_SILENT)) + !(flags & WRITE_OBJECT_FILE_SILENT)) warning_errno(_("failed utime() on %s"), tmp_file.buf); } @@ -2465,7 +1023,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, goto cleanup; } - loose_object_path(the_repository, &filename, oid); + odb_loose_path(the_repository->objects->odb, &filename, oid); /* We finally know the object path, and create the missing dir. */ dirlen = directory_size(filename.buf); @@ -2473,7 +1031,8 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, struct strbuf dir = STRBUF_INIT; strbuf_add(&dir, filename.buf, dirlen); - if (mkdir_in_gitdir(dir.buf) && errno != EEXIST) { + if (safe_create_dir_in_gitdir(the_repository, dir.buf) && + errno != EEXIST) { err = error_errno(_("unable to create directory %s"), dir.buf); strbuf_release(&dir); goto cleanup; @@ -2510,7 +1069,7 @@ int write_object_file_flags(const void *buf, unsigned long len, hash_object_file(compat, buf, len, type, &compat_oid); else { struct strbuf converted = STRBUF_INIT; - convert_object_file(&converted, algo, compat, + convert_object_file(the_repository, &converted, algo, compat, buf, len, type, 0); hash_object_file(compat, converted.buf, converted.len, type, &compat_oid); @@ -2531,52 +1090,6 @@ int write_object_file_flags(const void *buf, unsigned long len, return 0; } -int write_object_file_literally(const void *buf, unsigned long len, - const char *type, struct object_id *oid, - 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; - header = xmalloc(hdrlen); - write_object_file_prepare_literally(the_hash_algo, buf, len, type, - oid, header, &hdrlen); - - if (!(flags & HASH_WRITE_OBJECT)) - goto cleanup; - 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); - return status; -} - int force_object_loose(const struct object_id *oid, time_t mtime) { struct repository *repo = the_repository; @@ -2611,32 +1124,6 @@ int force_object_loose(const struct object_id *oid, time_t mtime) return ret; } -int has_object(struct repository *r, const struct object_id *oid, - unsigned flags) -{ - int quick = !(flags & HAS_OBJECT_RECHECK_PACKED); - unsigned object_info_flags = OBJECT_INFO_SKIP_FETCH_OBJECT | - (quick ? OBJECT_INFO_QUICK : 0); - - if (!startup_info->have_repository) - return 0; - return oid_object_info_extended(r, oid, NULL, object_info_flags) >= 0; -} - -int repo_has_object_file_with_flags(struct repository *r, - const struct object_id *oid, int flags) -{ - if (!startup_info->have_repository) - return 0; - return oid_object_info_extended(r, oid, NULL, flags) >= 0; -} - -int repo_has_object_file(struct repository *r, - const struct object_id *oid) -{ - return repo_has_object_file_with_flags(r, oid, 0); -} - /* * We can't use the normal fsck_error_function() for index_mem(), * because we don't yet have a valid oid for it to report. Instead, @@ -2661,7 +1148,7 @@ static int index_mem(struct index_state *istate, { struct strbuf nbuf = STRBUF_INIT; int ret = 0; - int write_object = flags & HASH_WRITE_OBJECT; + int write_object = flags & INDEX_WRITE_OBJECT; if (!type) type = OBJ_BLOB; @@ -2676,12 +1163,12 @@ static int index_mem(struct index_state *istate, size = nbuf.len; } } - if (flags & HASH_FORMAT_CHECK) { + if (flags & INDEX_FORMAT_CHECK) { struct fsck_options opts = FSCK_OPTIONS_DEFAULT; opts.strict = 1; opts.error_func = hash_format_check_report; - if (fsck_buffer(null_oid(), type, buf, size, &opts)) + if (fsck_buffer(null_oid(the_hash_algo), type, buf, size, &opts)) die(_("refusing to create malformed object")); fsck_finish(&opts); } @@ -2702,11 +1189,11 @@ static int index_stream_convert_blob(struct index_state *istate, unsigned flags) { int ret = 0; - const int write_object = flags & HASH_WRITE_OBJECT; + const int write_object = flags & INDEX_WRITE_OBJECT; struct strbuf sbuf = STRBUF_INIT; assert(path); - assert(would_convert_to_git_filter_fd(istate, path)); + ASSERT(would_convert_to_git_filter_fd(istate, path)); convert_to_git_filter_fd(istate, path, fd, &sbuf, get_conv_flags(flags)); @@ -2767,28 +1254,6 @@ static int index_core(struct index_state *istate, return ret; } -/* - * This creates one packfile per large blob unless bulk-checkin - * machinery is "plugged". - * - * This also bypasses the usual "convert-to-git" dance, and that is on - * purpose. We could write a streaming version of the converting - * functions and insert that before feeding the data to fast-import - * (or equivalent in-core API described above). However, that is - * somewhat complicated, as we do not know the size of the filter - * result, which we need to know beforehand when writing a git object. - * Since the primary motivation for trying to stream from the working - * tree file and to avoid mmaping it in core is to deal with large - * binary blobs, they generally do not want to get any conversion, and - * callers should avoid this code path when filters are requested. - */ -static int index_blob_stream(struct object_id *oid, int fd, size_t size, - const char *path, - unsigned flags) -{ - return index_blob_bulk_checkin(oid, fd, size, path, flags); -} - int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags) @@ -2803,13 +1268,14 @@ int index_fd(struct index_state *istate, struct object_id *oid, ret = index_stream_convert_blob(istate, oid, fd, path, flags); else if (!S_ISREG(st->st_mode)) ret = index_pipe(istate, oid, fd, type, path, flags); - else if (st->st_size <= big_file_threshold || type != OBJ_BLOB || + else if (st->st_size <= repo_settings_get_big_file_threshold(the_repository) || + type != OBJ_BLOB || (path && would_convert_to_git(istate, path))) ret = index_core(istate, oid, fd, xsize_t(st->st_size), type, path, flags); else - ret = index_blob_stream(oid, fd, xsize_t(st->st_size), path, - flags); + ret = index_blob_bulk_checkin(oid, fd, xsize_t(st->st_size), path, + flags); close(fd); return ret; } @@ -2833,7 +1299,7 @@ int index_path(struct index_state *istate, struct object_id *oid, case S_IFLNK: if (strbuf_readlink(&sb, path, st->st_size)) return error_errno("readlink(\"%s\")", path); - if (!(flags & HASH_WRITE_OBJECT)) + if (!(flags & INDEX_WRITE_OBJECT)) hash_object_file(the_hash_algo, sb.buf, sb.len, OBJ_BLOB, oid); else if (write_object_file(sb.buf, sb.len, OBJ_BLOB, oid)) @@ -2863,16 +1329,6 @@ int read_pack_header(int fd, struct pack_header *header) return 0; } -void assert_oid_type(const struct object_id *oid, enum object_type expect) -{ - enum object_type type = oid_object_info(the_repository, oid, NULL); - if (type < 0) - die(_("%s is not a valid object"), oid_to_hex(oid)); - if (type != expect) - die(_("%s is not a valid '%s' object"), oid_to_hex(oid), - type_name(expect)); -} - int for_each_file_in_obj_subdir(unsigned int subdir_nr, struct strbuf *path, each_loose_object_fn obj_cb, @@ -3080,7 +1536,6 @@ static int check_stream_oid(git_zstream *stream, git_hash_update(&c, buf, stream->next_out - buf); total_read += stream->next_out - buf; } - git_inflate_end(stream); if (status != Z_STREAM_END) { error(_("corrupt loose object '%s'"), oid_to_hex(expected_oid)); @@ -3124,38 +1579,43 @@ int read_loose_object(const char *path, goto out; } - if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr), - NULL) != ULHR_OK) { + if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr)) != ULHR_OK) { error(_("unable to unpack header of %s"), path); - git_inflate_end(&stream); - goto out; + goto out_inflate; } if (parse_loose_header(hdr, oi) < 0) { error(_("unable to parse header of %s"), path); - git_inflate_end(&stream); - goto out; + goto out_inflate; + } + + if (*oi->typep < 0) { + error(_("unable to parse type from header '%s' of %s"), + hdr, path); + goto out_inflate; } - if (*oi->typep == OBJ_BLOB && *size > big_file_threshold) { + if (*oi->typep == OBJ_BLOB && + *size > repo_settings_get_big_file_threshold(the_repository)) { if (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0) - goto out; + goto out_inflate; } else { *contents = unpack_loose_rest(&stream, hdr, *size, expected_oid); if (!*contents) { error(_("unable to unpack contents of %s"), path); - git_inflate_end(&stream); - goto out; + goto out_inflate; } - hash_object_file_literally(the_repository->hash_algo, - *contents, *size, - oi->type_name->buf, real_oid); + hash_object_file(the_repository->hash_algo, + *contents, *size, + *oi->typep, real_oid); if (!oideq(expected_oid, real_oid)) - goto out; + goto out_inflate; } ret = 0; /* everything checks out */ +out_inflate: + git_inflate_end(&stream); out: if (map) munmap(map, mapsize); diff --git a/object-file.h b/object-file.h index 81b30d269c..6f41142452 100644 --- a/object-file.h +++ b/object-file.h @@ -3,6 +3,7 @@ #include "git-zlib.h" #include "object.h" +#include "object-store.h" struct index_state; @@ -14,50 +15,113 @@ struct index_state; */ extern int fetch_if_missing; -#define HASH_WRITE_OBJECT 1 -#define HASH_FORMAT_CHECK 2 -#define HASH_RENORMALIZE 4 -#define HASH_SILENT 8 +enum { + INDEX_WRITE_OBJECT = (1 << 0), + INDEX_FORMAT_CHECK = (1 << 1), + INDEX_RENORMALIZE = (1 << 2), +}; + int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags); int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags); +struct object_directory; + +/* + * Populate and return the loose object cache array corresponding to the + * given object ID. + */ +struct oidtree *odb_loose_cache(struct object_directory *odb, + const struct object_id *oid); + +/* Empty the loose object cache for the specified object directory. */ +void odb_clear_loose_cache(struct object_directory *odb); + +/* + * Put in `buf` the name of the file in the local object database that + * would be used to store a loose object with the specified oid. + */ +const char *odb_loose_path(struct object_directory *odb, + struct strbuf *buf, + const struct object_id *oid); + /* - * Create the directory containing the named path, using care to be - * somewhat safe against races. Return one of the scld_error values to - * indicate success/failure. On error, set errno to describe the - * problem. + * Return true iff an alternate object database has a loose object + * with the specified name. This function does not respect replace + * references. + */ +int has_loose_object_nonlocal(const struct object_id *); + +int has_loose_object(const struct object_id *); + +void *map_loose_object(struct repository *r, const struct object_id *oid, + unsigned long *size); + +/* + * Iterate over the files in the loose-object parts of the object + * directory "path", triggering the following callbacks: + * + * - loose_object is called for each loose object we find. + * + * - loose_cruft is called for any files that do not appear to be + * loose objects. Note that we only look in the loose object + * directories "objects/[0-9a-f]{2}/", so we will not report + * "objects/foobar" as cruft. + * + * - loose_subdir is called for each top-level hashed subdirectory + * of the object directory (e.g., "$OBJDIR/f0"). It is called + * after the objects in the directory are processed. * - * SCLD_VANISHED indicates that one of the ancestor directories of the - * path existed at one point during the function call and then - * suddenly vanished, probably because another process pruned the - * directory while we were working. To be robust against this kind of - * race, callers might want to try invoking the function again when it - * returns SCLD_VANISHED. + * Any callback that is NULL will be ignored. Callbacks returning non-zero + * will end the iteration. * - * safe_create_leading_directories() temporarily changes path while it - * is working but restores it before returning. - * safe_create_leading_directories_const() doesn't modify path, even - * temporarily. Both these variants adjust the permissions of the - * created directories to honor core.sharedRepository, so they are best - * suited for files inside the git dir. For working tree files, use - * safe_create_leading_directories_no_share() instead, as it ignores - * the core.sharedRepository setting. + * In the "buf" variant, "path" is a strbuf which will also be used as a + * scratch buffer, but restored to its original contents before + * the function returns. */ -enum scld_error { - SCLD_OK = 0, - SCLD_FAILED = -1, - SCLD_PERMS = -2, - SCLD_EXISTS = -3, - SCLD_VANISHED = -4 -}; -enum scld_error safe_create_leading_directories(char *path); -enum scld_error safe_create_leading_directories_const(const char *path); -enum scld_error safe_create_leading_directories_no_share(char *path); +typedef int each_loose_object_fn(const struct object_id *oid, + const char *path, + void *data); +typedef int each_loose_cruft_fn(const char *basename, + const char *path, + void *data); +typedef int each_loose_subdir_fn(unsigned int nr, + const char *path, + void *data); +int for_each_file_in_obj_subdir(unsigned int subdir_nr, + struct strbuf *path, + each_loose_object_fn obj_cb, + each_loose_cruft_fn cruft_cb, + each_loose_subdir_fn subdir_cb, + void *data); +int for_each_loose_file_in_objdir(const char *path, + each_loose_object_fn obj_cb, + each_loose_cruft_fn cruft_cb, + each_loose_subdir_fn subdir_cb, + void *data); +int for_each_loose_file_in_objdir_buf(struct strbuf *path, + each_loose_object_fn obj_cb, + each_loose_cruft_fn cruft_cb, + each_loose_subdir_fn subdir_cb, + void *data); -int mkdir_in_gitdir(const char *path); +/* + * Iterate over all accessible loose objects without respect to + * reachability. By default, this includes both local and alternate objects. + * The order in which objects are visited is unspecified. + * + * Any flags specific to packs are ignored. + */ +int for_each_loose_object(each_loose_object_fn, void *, + enum for_each_object_flags flags); -int git_open_cloexec(const char *name, int flags); -#define git_open(name) git_open_cloexec(name, O_RDONLY) + +/** + * format_object_header() is a thin wrapper around s xsnprintf() that + * writes the initial "<type> <obj-len>" part of the loose object + * header. It returns the size that snprintf() returns + 1. + */ +int format_object_header(char *str, size_t size, enum object_type type, + size_t objsize); /** * unpack_loose_header() initializes the data stream needed to unpack @@ -69,12 +133,7 @@ int git_open_cloexec(const char *name, int flags); * - ULHR_BAD on error * - ULHR_TOO_LONG if the header was too long * - * It will only parse up to MAX_HEADER_LEN bytes unless an optional - * "hdrbuf" argument is non-NULL. This is intended for use with - * OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error) - * reporting. The full header will be extracted to "hdrbuf" for use - * with parse_loose_header(), ULHR_TOO_LONG will still be returned - * from this function to indicate that the header was too long. + * It will only parse up to MAX_HEADER_LEN bytes. */ enum unpack_loose_header_result { ULHR_OK, @@ -85,8 +144,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, - unsigned long bufsiz, - struct strbuf *hdrbuf); + unsigned long bufsiz); /** * parse_loose_header() parses the starting "<type> <len>\0" of an @@ -99,6 +157,41 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream, struct object_info; int parse_loose_header(const char *hdr, struct object_info *oi); +enum { + /* + * By default, `write_object_file()` does not actually write + * anything into the object store, but only computes the object ID. + * This flag changes that so that the object will be written as a loose + * object and persisted. + */ + WRITE_OBJECT_FILE_PERSIST = (1 << 0), + + /* + * Do not print an error in case something gose wrong. + */ + WRITE_OBJECT_FILE_SILENT = (1 << 1), +}; + +int write_object_file_flags(const void *buf, unsigned long len, + enum object_type type, struct object_id *oid, + struct object_id *compat_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, NULL, 0); +} + +struct input_stream { + const void *(*read)(struct input_stream *, unsigned long *len); + void *data; + int is_finished; +}; + +int stream_loose_object(struct input_stream *in_stream, size_t len, + struct object_id *oid); + +int force_object_loose(const struct object_id *oid, time_t mtime); + /** * With in-core object data in "buf", rehash it to make sure the * object name actually matches "oid" to detect object corruption. @@ -117,6 +210,10 @@ int check_object_signature(struct repository *r, const struct object_id *oid, */ int stream_object_signature(struct repository *r, const struct object_id *oid); +int loose_object_info(struct repository *r, + const struct object_id *oid, + struct object_info *oi, int flags); + enum finalize_object_file_flags { FOF_SKIP_COLLISION_CHECK = 1, }; @@ -125,13 +222,25 @@ int finalize_object_file(const char *tmpfile, const char *filename); int finalize_object_file_flags(const char *tmpfile, const char *filename, enum finalize_object_file_flags flags); +void hash_object_file(const struct git_hash_algo *algo, const void *buf, + unsigned long len, enum object_type type, + struct object_id *oid); + /* Helper to check and "touch" a file */ int check_and_freshen_file(const char *fn, int freshen); -void *read_object_with_reference(struct repository *r, - const struct object_id *oid, - enum object_type required_type, - unsigned long *size, - struct object_id *oid_ret); +/* + * Open the loose object at path, check its hash, and return the contents, + * use the "oi" argument to assert things about the object, or e.g. populate its + * type, and size. If the object is a blob, then "contents" may return NULL, + * to allow streaming of large blobs. + * + * Returns 0 on success, negative on error (details may be written to stderr). + */ +int read_loose_object(const char *path, + const struct object_id *expected_oid, + struct object_id *real_oid, + void **contents, + struct object_info *oi); #endif /* OBJECT_FILE_H */ diff --git a/object-name.c b/object-name.c index 76749fbfe6..9288b2dd24 100644 --- a/object-name.c +++ b/object-name.c @@ -19,7 +19,7 @@ #include "oidtree.h" #include "packfile.h" #include "pretty.h" -#include "object-store-ll.h" +#include "object-file.h" #include "read-cache-ll.h" #include "repo-settings.h" #include "repository.h" @@ -961,7 +961,9 @@ static int get_oid_basic(struct repository *r, const char *str, int len, int fatal = !(flags & GET_OID_QUIETLY); if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) { - if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) { + if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) && + repo_settings_get_warn_ambiguous_refs(r) && + warn_on_object_refname_ambiguity) { refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0); if (refs_found > 0) { warning(warn_msg, len, str); @@ -1794,18 +1796,20 @@ void object_context_release(struct object_context *ctx) strbuf_release(&ctx->symlink_path); } -/* - * This is like "get_oid_basic()", except it allows "object ID expressions", - * notably "xyz^" for "parent of xyz" - */ -int repo_get_oid(struct repository *r, const char *name, struct object_id *oid) +int repo_get_oid_with_flags(struct repository *r, const char *name, + struct object_id *oid, unsigned flags) { struct object_context unused; - int ret = get_oid_with_context(r, name, 0, oid, &unused); + int ret = get_oid_with_context(r, name, flags, oid, &unused); object_context_release(&unused); return ret; } +int repo_get_oid(struct repository *r, const char *name, struct object_id *oid) +{ + return repo_get_oid_with_flags(r, name, oid, 0); +} + /* * This returns a non-zero value if the string (built using printf * format and the given arguments) is not a valid object. diff --git a/object-name.h b/object-name.h index 8dba4a47a4..cda4934cd5 100644 --- a/object-name.h +++ b/object-name.h @@ -51,6 +51,12 @@ void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo, void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid, int abbrev_len); +/* + * This is like "get_oid_basic()", except it allows "object ID expressions", + * notably "xyz^" for "parent of xyz". Accepts GET_OID_* flags. + */ +int repo_get_oid_with_flags(struct repository *r, const char *str, + struct object_id *oid, unsigned flags); int repo_get_oid(struct repository *r, const char *str, struct object_id *oid); __attribute__((format (printf, 2, 3))) int get_oidf(struct object_id *oid, const char *fmt, ...); diff --git a/object-store-ll.h b/object-store-ll.h deleted file mode 100644 index cd3bd5bd99..0000000000 --- a/object-store-ll.h +++ /dev/null @@ -1,556 +0,0 @@ -#ifndef OBJECT_STORE_LL_H -#define OBJECT_STORE_LL_H - -#include "hashmap.h" -#include "object.h" -#include "list.h" -#include "thread-utils.h" -#include "oidset.h" - -struct oidmap; -struct oidtree; -struct strbuf; -struct repository; - -struct object_directory { - struct object_directory *next; - - /* - * Used to store the results of readdir(3) calls when we are OK - * sacrificing accuracy due to races for speed. That includes - * object existence with OBJECT_INFO_QUICK, as well as - * our search for unique abbreviated hashes. Don't use it for tasks - * requiring greater accuracy! - * - * Be sure to call odb_load_loose_cache() before using. - */ - 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 - * might be discarded on rollback. - */ - int disable_ref_updates; - - /* - * This object store is ephemeral, so there is no need to fsync. - */ - int will_destroy; - - /* - * Path to the alternative object store. If this is a relative path, - * it is relative to the current working directory. - */ - char *path; -}; - -struct input_stream { - const void *(*read)(struct input_stream *, unsigned long *len); - void *data; - int is_finished; -}; - -void prepare_alt_odb(struct repository *r); -int has_alt_odb(struct repository *r); -char *compute_alternate_path(const char *path, struct strbuf *err); -struct object_directory *find_odb(struct repository *r, const char *obj_dir); -typedef int alt_odb_fn(struct object_directory *, void *); -int foreach_alt_odb(alt_odb_fn, void*); -typedef void alternate_ref_fn(const struct object_id *oid, void *); -void for_each_alternate_ref(alternate_ref_fn, void *); - -/* - * Add the directory to the on-disk alternates file; the new entry will also - * take effect in the current process. - */ -void add_to_alternates_file(const char *dir); - -/* - * Add the directory to the in-memory list of alternates (along with any - * recursive alternates it points to), but do not modify the on-disk alternates - * file. - */ -void add_to_alternates_memory(const char *dir); - -/* - * Replace the current writable object directory with the specified temporary - * object directory; returns the former primary object directory. - */ -struct object_directory *set_temporary_primary_odb(const char *dir, int will_destroy); - -/* - * Restore a previous ODB replaced by set_temporary_main_odb. - */ -void restore_primary_odb(struct object_directory *restore_odb, const char *old_path); - -/* - * Populate and return the loose object cache array corresponding to the - * given object ID. - */ -struct oidtree *odb_loose_cache(struct object_directory *odb, - const struct object_id *oid); - -/* Empty the loose object cache for the specified object directory. */ -void odb_clear_loose_cache(struct object_directory *odb); - -/* Clear and free the specified object directory */ -void free_object_directory(struct object_directory *odb); - -struct packed_git { - struct hashmap_entry packmap_ent; - struct packed_git *next; - struct list_head mru; - struct pack_window *windows; - off_t pack_size; - const void *index_data; - size_t index_size; - uint32_t num_objects; - size_t crc_offset; - struct oidset bad_objects; - int index_version; - time_t mtime; - int pack_fd; - int index; /* for builtin/pack-objects.c */ - unsigned pack_local:1, - pack_keep:1, - pack_keep_in_core:1, - freshened:1, - do_not_close:1, - pack_promisor:1, - multi_pack_index:1, - is_cruft:1; - unsigned char hash[GIT_MAX_RAWSZ]; - struct revindex_entry *revindex; - const uint32_t *revindex_data; - const uint32_t *revindex_map; - size_t revindex_size; - /* - * mtimes_map points at the beginning of the memory mapped region of - * this pack's corresponding .mtimes file, and mtimes_size is the size - * of that .mtimes file - */ - const uint32_t *mtimes_map; - size_t mtimes_size; - - /* repo denotes the repository this packfile belongs to */ - struct repository *repo; - - /* something like ".git/objects/pack/xxxxx.pack" */ - char pack_name[FLEX_ARRAY]; /* more */ -}; - -struct multi_pack_index; - -static inline int pack_map_entry_cmp(const void *cmp_data UNUSED, - const struct hashmap_entry *entry, - const struct hashmap_entry *entry2, - const void *keydata) -{ - const char *key = keydata; - const struct packed_git *pg1, *pg2; - - pg1 = container_of(entry, const struct packed_git, packmap_ent); - pg2 = container_of(entry2, const struct packed_git, packmap_ent); - - return strcmp(pg1->pack_name, key ? key : pg2->pack_name); -} - -struct raw_object_store { - /* - * Set of all object directories; the main directory is first (and - * cannot be NULL after initialization). Subsequent directories are - * alternates. - */ - struct object_directory *odb; - struct object_directory **odb_tail; - struct kh_odb_path_map *odb_by_path; - - int loaded_alternates; - - /* - * A list of alternate object directories loaded from the environment; - * this should not generally need to be accessed directly, but will - * populate the "odb" list when prepare_alt_odb() is run. - */ - char *alternate_db; - - /* - * Objects that should be substituted by other objects - * (see git-replace(1)). - */ - struct oidmap *replace_map; - unsigned replace_map_initialized : 1; - pthread_mutex_t replace_mutex; /* protect object replace functions */ - - struct commit_graph *commit_graph; - unsigned commit_graph_attempted : 1; /* if loading has been attempted */ - - /* - * private data - * - * should only be accessed directly by packfile.c and midx.c - */ - struct multi_pack_index *multi_pack_index; - - /* - * private data - * - * should only be accessed directly by packfile.c - */ - - struct packed_git *packed_git; - /* A most-recently-used ordered version of the packed_git list. */ - struct list_head packed_git_mru; - - struct { - struct packed_git **packs; - unsigned flags; - } kept_pack_cache; - - /* - * A map of packfiles to packed_git structs for tracking which - * packs have been loaded already. - */ - struct hashmap pack_map; - - /* - * A fast, rough count of the number of objects in the repository. - * These two fields are not meant for direct access. Use - * repo_approximate_object_count() instead. - */ - unsigned long approximate_object_count; - unsigned approximate_object_count_valid : 1; - - /* - * Whether packed_git has already been populated with this repository's - * packs. - */ - unsigned packed_git_initialized : 1; -}; - -struct raw_object_store *raw_object_store_new(void); -void raw_object_store_clear(struct raw_object_store *o); - -/* - * Create a temporary file rooted in the object database directory, or - * die on failure. The filename is taken from "pattern", which should have the - * usual "XXXXXX" trailer, and the resulting filename is written into the - * "template" buffer. Returns the open descriptor. - */ -int odb_mkstemp(struct strbuf *temp_filename, const char *pattern); - -/* - * Create a pack .keep file named "name" (which should generally be the output - * of odb_pack_name). Returns a file descriptor opened for writing, or -1 on - * error. - */ -int odb_pack_keep(const char *name); - -/* - * Put in `buf` the name of the file in the local object database that - * would be used to store a loose object with the specified oid. - */ -const char *loose_object_path(struct repository *r, struct strbuf *buf, - const struct object_id *oid); - -void *map_loose_object(struct repository *r, const struct object_id *oid, - unsigned long *size); - -void *repo_read_object_file(struct repository *r, - const struct object_id *oid, - enum object_type *type, - unsigned long *size); - -/* Read and unpack an object file into memory, write memory to an object file */ -int oid_object_info(struct repository *r, const struct object_id *, unsigned long *); - -void hash_object_file(const struct git_hash_algo *algo, const void *buf, - unsigned long len, enum object_type type, - struct object_id *oid); - -int write_object_file_flags(const void *buf, unsigned long len, - enum object_type type, struct object_id *oid, - 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, NULL, 0); -} - -int write_object_file_literally(const void *buf, unsigned long len, - const char *type, struct object_id *oid, - unsigned flags); -int stream_loose_object(struct input_stream *in_stream, size_t len, - struct object_id *oid); - -/* - * Add an object file to the in-memory object store, without writing it - * to disk. - * - * Callers are responsible for calling write_object_file to record the - * object in persistent storage before writing any other new objects - * that reference it. - */ -int pretend_object_file(void *, unsigned long, enum object_type, - struct object_id *oid); - -int force_object_loose(const struct object_id *oid, time_t mtime); - -struct object_info { - /* Request */ - enum object_type *typep; - unsigned long *sizep; - off_t *disk_sizep; - struct object_id *delta_base_oid; - struct strbuf *type_name; - void **contentp; - - /* Response */ - enum { - OI_CACHED, - OI_LOOSE, - OI_PACKED, - OI_DBCACHED - } whence; - union { - /* - * struct { - * ... Nothing to expose in this case - * } cached; - * struct { - * ... Nothing to expose in this case - * } loose; - */ - struct { - struct packed_git *pack; - off_t offset; - unsigned int is_delta; - } packed; - } u; -}; - -/* - * Initializer for a "struct object_info" that wants no items. You may - * also memset() the memory to all-zeroes. - */ -#define OBJECT_INFO_INIT { 0 } - -/* Invoke lookup_replace_object() on the given hash */ -#define OBJECT_INFO_LOOKUP_REPLACE 1 -/* Allow reading from a loose object file of unknown/bogus type */ -#define OBJECT_INFO_ALLOW_UNKNOWN_TYPE 2 -/* Do not retry packed storage after checking packed and loose storage */ -#define OBJECT_INFO_QUICK 8 -/* - * Do not attempt to fetch the object if missing (even if fetch_is_missing is - * nonzero). - */ -#define OBJECT_INFO_SKIP_FETCH_OBJECT 16 -/* - * This is meant for bulk prefetching of missing blobs in a partial - * clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK - */ -#define OBJECT_INFO_FOR_PREFETCH (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK) - -/* Die if object corruption (not just an object being missing) was detected. */ -#define OBJECT_INFO_DIE_IF_CORRUPT 32 - -int oid_object_info_extended(struct repository *r, - const struct object_id *, - struct object_info *, unsigned flags); - -/* - * Open the loose object at path, check its hash, and return the contents, - * use the "oi" argument to assert things about the object, or e.g. populate its - * type, and size. If the object is a blob, then "contents" may return NULL, - * to allow streaming of large blobs. - * - * Returns 0 on success, negative on error (details may be written to stderr). - */ -int read_loose_object(const char *path, - const struct object_id *expected_oid, - struct object_id *real_oid, - void **contents, - struct object_info *oi); - -/* Retry packed storage after checking packed and loose storage */ -#define HAS_OBJECT_RECHECK_PACKED 1 - -/* - * Returns 1 if the object exists. This function will not lazily fetch objects - * in a partial clone. - */ -int has_object(struct repository *r, const struct object_id *oid, - unsigned flags); - -/* - * These macros and functions are deprecated. If checking existence for an - * object that is likely to be missing and/or whose absence is relatively - * inconsequential (or is consequential but the caller is prepared to handle - * it), use has_object(), which has better defaults (no lazy fetch in a partial - * clone and no rechecking of packed storage). In the unlikely event that a - * caller needs to assert existence of an object that it fully expects to - * exist, and wants to trigger a lazy fetch in a partial clone, use - * oid_object_info_extended() with a NULL struct object_info. - * - * These functions can be removed once all callers have migrated to - * has_object() and/or oid_object_info_extended(). - */ -int repo_has_object_file(struct repository *r, const struct object_id *oid); -int repo_has_object_file_with_flags(struct repository *r, - const struct object_id *oid, int flags); - -/* - * Return true iff an alternate object database has a loose object - * with the specified name. This function does not respect replace - * references. - */ -int has_loose_object_nonlocal(const struct object_id *); - -int has_loose_object(const struct object_id *); - -/** - * format_object_header() is a thin wrapper around s xsnprintf() that - * writes the initial "<type> <obj-len>" part of the loose object - * header. It returns the size that snprintf() returns + 1. - */ -int format_object_header(char *str, size_t size, enum object_type type, - size_t objsize); - -void assert_oid_type(const struct object_id *oid, enum object_type expect); - -/* - * Enabling the object read lock allows multiple threads to safely call the - * following functions in parallel: repo_read_object_file(), - * read_object_with_reference(), oid_object_info() and oid_object_info_extended(). - * - * obj_read_lock() and obj_read_unlock() may also be used to protect other - * section which cannot execute in parallel with object reading. Since the used - * lock is a recursive mutex, these sections can even contain calls to object - * reading functions. However, beware that in these cases zlib inflation won't - * be performed in parallel, losing performance. - * - * TODO: oid_object_info_extended()'s call stack has a recursive behavior. If - * any of its callees end up calling it, this recursive call won't benefit from - * parallel inflation. - */ -void enable_obj_read_lock(void); -void disable_obj_read_lock(void); - -extern int obj_read_use_lock; -extern pthread_mutex_t obj_read_mutex; - -static inline void obj_read_lock(void) -{ - if(obj_read_use_lock) - pthread_mutex_lock(&obj_read_mutex); -} - -static inline void obj_read_unlock(void) -{ - if(obj_read_use_lock) - pthread_mutex_unlock(&obj_read_mutex); -} - -/* - * Iterate over the files in the loose-object parts of the object - * directory "path", triggering the following callbacks: - * - * - loose_object is called for each loose object we find. - * - * - loose_cruft is called for any files that do not appear to be - * loose objects. Note that we only look in the loose object - * directories "objects/[0-9a-f]{2}/", so we will not report - * "objects/foobar" as cruft. - * - * - loose_subdir is called for each top-level hashed subdirectory - * of the object directory (e.g., "$OBJDIR/f0"). It is called - * after the objects in the directory are processed. - * - * Any callback that is NULL will be ignored. Callbacks returning non-zero - * will end the iteration. - * - * In the "buf" variant, "path" is a strbuf which will also be used as a - * scratch buffer, but restored to its original contents before - * the function returns. - */ -typedef int each_loose_object_fn(const struct object_id *oid, - const char *path, - void *data); -typedef int each_loose_cruft_fn(const char *basename, - const char *path, - void *data); -typedef int each_loose_subdir_fn(unsigned int nr, - const char *path, - void *data); -int for_each_file_in_obj_subdir(unsigned int subdir_nr, - struct strbuf *path, - each_loose_object_fn obj_cb, - each_loose_cruft_fn cruft_cb, - each_loose_subdir_fn subdir_cb, - void *data); -int for_each_loose_file_in_objdir(const char *path, - each_loose_object_fn obj_cb, - each_loose_cruft_fn cruft_cb, - each_loose_subdir_fn subdir_cb, - void *data); -int for_each_loose_file_in_objdir_buf(struct strbuf *path, - each_loose_object_fn obj_cb, - each_loose_cruft_fn cruft_cb, - each_loose_subdir_fn subdir_cb, - void *data); - -/* Flags for for_each_*_object() below. */ -enum for_each_object_flags { - /* Iterate only over local objects, not alternates. */ - FOR_EACH_OBJECT_LOCAL_ONLY = (1<<0), - - /* Only iterate over packs obtained from the promisor remote. */ - FOR_EACH_OBJECT_PROMISOR_ONLY = (1<<1), - - /* - * Visit objects within a pack in packfile order rather than .idx order - */ - FOR_EACH_OBJECT_PACK_ORDER = (1<<2), - - /* Only iterate over packs that are not marked as kept in-core. */ - FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS = (1<<3), - - /* Only iterate over packs that do not have .keep files. */ - FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS = (1<<4), -}; - -/* - * Iterate over all accessible loose objects without respect to - * reachability. By default, this includes both local and alternate objects. - * The order in which objects are visited is unspecified. - * - * Any flags specific to packs are ignored. - */ -int for_each_loose_object(each_loose_object_fn, void *, - enum for_each_object_flags flags); - -/* - * Iterate over all accessible packed objects without respect to reachability. - * By default, this includes both local and alternate packs. - * - * Note that some objects may appear twice if they are found in multiple packs. - * Each pack is visited in an unspecified order. By default, objects within a - * pack are visited in pack-idx order (i.e., sorted by oid). - */ -typedef int each_packed_object_fn(const struct object_id *oid, - struct packed_git *pack, - uint32_t pos, - void *data); -int for_each_object_in_pack(struct packed_git *p, - each_packed_object_fn, void *data, - enum for_each_object_flags flags); -int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, - void *data, enum for_each_object_flags flags); - -#endif /* OBJECT_STORE_LL_H */ diff --git a/object-store.c b/object-store.c new file mode 100644 index 0000000000..58cde0313a --- /dev/null +++ b/object-store.c @@ -0,0 +1,1010 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "git-compat-util.h" +#include "abspath.h" +#include "commit-graph.h" +#include "config.h" +#include "dir.h" +#include "environment.h" +#include "gettext.h" +#include "hex.h" +#include "khash.h" +#include "lockfile.h" +#include "loose.h" +#include "object-file-convert.h" +#include "object-file.h" +#include "object-store.h" +#include "packfile.h" +#include "path.h" +#include "promisor-remote.h" +#include "quote.h" +#include "replace-object.h" +#include "run-command.h" +#include "setup.h" +#include "strbuf.h" +#include "strvec.h" +#include "submodule.h" +#include "write-or-die.h" + +KHASH_INIT(odb_path_map, const char * /* key: odb_path */, + struct object_directory *, 1, fspathhash, fspatheq) + +/* + * This is meant to hold a *small* number of objects that you would + * want repo_read_object_file() to be able to return, but yet you do not want + * to write them into the object store (e.g. a browse-only + * application). + */ +struct cached_object_entry { + struct object_id oid; + struct cached_object { + enum object_type type; + const void *buf; + unsigned long size; + } value; +}; + +static const struct cached_object *find_cached_object(struct raw_object_store *object_store, + const struct object_id *oid) +{ + static const struct cached_object empty_tree = { + .type = OBJ_TREE, + .buf = "", + }; + const struct cached_object_entry *co = object_store->cached_objects; + + for (size_t i = 0; i < object_store->cached_object_nr; i++, co++) + if (oideq(&co->oid, oid)) + return &co->value; + + if (oid->algo && oideq(oid, hash_algos[oid->algo].empty_tree)) + return &empty_tree; + + return NULL; +} + +int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) +{ + int fd; + /* + * we let the umask do its job, don't try to be more + * restrictive except to remove write permission. + */ + int mode = 0444; + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); + fd = git_mkstemp_mode(temp_filename->buf, mode); + if (0 <= fd) + return fd; + + /* slow path */ + /* some mkstemp implementations erase temp_filename on failure */ + repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern); + safe_create_leading_directories(the_repository, temp_filename->buf); + return xmkstemp_mode(temp_filename->buf, mode); +} + +/* + * Return non-zero iff the path is usable as an alternate object database. + */ +static int alt_odb_usable(struct raw_object_store *o, + struct strbuf *path, + const char *normalized_objdir, khiter_t *pos) +{ + int r; + + /* Detect cases where alternate disappeared */ + if (!is_directory(path->buf)) { + error(_("object directory %s does not exist; " + "check .git/objects/info/alternates"), + path->buf); + return 0; + } + + /* + * Prevent the common mistake of listing the same + * thing twice, or object directory itself. + */ + if (!o->odb_by_path) { + khiter_t p; + + o->odb_by_path = kh_init_odb_path_map(); + assert(!o->odb->next); + p = kh_put_odb_path_map(o->odb_by_path, o->odb->path, &r); + assert(r == 1); /* never used */ + kh_value(o->odb_by_path, p) = o->odb; + } + if (fspatheq(path->buf, normalized_objdir)) + return 0; + *pos = kh_put_odb_path_map(o->odb_by_path, path->buf, &r); + /* r: 0 = exists, 1 = never used, 2 = deleted */ + return r == 0 ? 0 : 1; +} + +/* + * Prepare alternate object database registry. + * + * The variable alt_odb_list points at the list of struct + * object_directory. The elements on this list come from + * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT + * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates, + * whose contents is similar to that environment variable but can be + * LF separated. Its base points at a statically allocated buffer that + * contains "/the/directory/corresponding/to/.git/objects/...", while + * its name points just after the slash at the end of ".git/objects/" + * in the example above, and has enough space to hold all hex characters + * of the object ID, an extra slash for the first level indirection, and + * the terminating NUL. + */ +static void read_info_alternates(struct repository *r, + const char *relative_base, + int depth); +static int link_alt_odb_entry(struct repository *r, const struct strbuf *entry, + const char *relative_base, int depth, const char *normalized_objdir) +{ + struct object_directory *ent; + struct strbuf pathbuf = STRBUF_INIT; + struct strbuf tmp = STRBUF_INIT; + khiter_t pos; + int ret = -1; + + if (!is_absolute_path(entry->buf) && relative_base) { + strbuf_realpath(&pathbuf, relative_base, 1); + strbuf_addch(&pathbuf, '/'); + } + strbuf_addbuf(&pathbuf, entry); + + if (!strbuf_realpath(&tmp, pathbuf.buf, 0)) { + error(_("unable to normalize alternate object path: %s"), + pathbuf.buf); + goto error; + } + strbuf_swap(&pathbuf, &tmp); + + /* + * The trailing slash after the directory name is given by + * this function at the end. Remove duplicates. + */ + while (pathbuf.len && pathbuf.buf[pathbuf.len - 1] == '/') + strbuf_setlen(&pathbuf, pathbuf.len - 1); + + if (!alt_odb_usable(r->objects, &pathbuf, normalized_objdir, &pos)) + goto error; + + CALLOC_ARRAY(ent, 1); + /* pathbuf.buf is already in r->objects->odb_by_path */ + ent->path = strbuf_detach(&pathbuf, NULL); + + /* add the alternate entry */ + *r->objects->odb_tail = ent; + r->objects->odb_tail = &(ent->next); + ent->next = NULL; + assert(r->objects->odb_by_path); + kh_value(r->objects->odb_by_path, pos) = ent; + + /* recursively add alternates */ + read_info_alternates(r, ent->path, depth + 1); + ret = 0; + error: + strbuf_release(&tmp); + strbuf_release(&pathbuf); + return ret; +} + +static const char *parse_alt_odb_entry(const char *string, + int sep, + struct strbuf *out) +{ + const char *end; + + strbuf_reset(out); + + if (*string == '#') { + /* comment; consume up to next separator */ + end = strchrnul(string, sep); + } else if (*string == '"' && !unquote_c_style(out, string, &end)) { + /* + * quoted path; unquote_c_style has copied the + * data for us and set "end". Broken quoting (e.g., + * an entry that doesn't end with a quote) falls + * back to the unquoted case below. + */ + } else { + /* normal, unquoted path */ + end = strchrnul(string, sep); + strbuf_add(out, string, end - string); + } + + if (*end) + end++; + return end; +} + +static void link_alt_odb_entries(struct repository *r, const char *alt, + int sep, const char *relative_base, int depth) +{ + struct strbuf objdirbuf = STRBUF_INIT; + struct strbuf entry = STRBUF_INIT; + + if (!alt || !*alt) + return; + + if (depth > 5) { + error(_("%s: ignoring alternate object stores, nesting too deep"), + relative_base); + return; + } + + strbuf_realpath(&objdirbuf, r->objects->odb->path, 1); + + while (*alt) { + alt = parse_alt_odb_entry(alt, sep, &entry); + if (!entry.len) + continue; + link_alt_odb_entry(r, &entry, + relative_base, depth, objdirbuf.buf); + } + strbuf_release(&entry); + strbuf_release(&objdirbuf); +} + +static void read_info_alternates(struct repository *r, + const char *relative_base, + int depth) +{ + char *path; + struct strbuf buf = STRBUF_INIT; + + path = xstrfmt("%s/info/alternates", relative_base); + if (strbuf_read_file(&buf, path, 1024) < 0) { + warn_on_fopen_errors(path); + free(path); + return; + } + + link_alt_odb_entries(r, buf.buf, '\n', relative_base, depth); + strbuf_release(&buf); + free(path); +} + +void add_to_alternates_file(const char *reference) +{ + struct lock_file lock = LOCK_INIT; + char *alts = repo_git_path(the_repository, "objects/info/alternates"); + FILE *in, *out; + int found = 0; + + hold_lock_file_for_update(&lock, alts, LOCK_DIE_ON_ERROR); + out = fdopen_lock_file(&lock, "w"); + if (!out) + die_errno(_("unable to fdopen alternates lockfile")); + + in = fopen(alts, "r"); + if (in) { + struct strbuf line = STRBUF_INIT; + + while (strbuf_getline(&line, in) != EOF) { + if (!strcmp(reference, line.buf)) { + found = 1; + break; + } + fprintf_or_die(out, "%s\n", line.buf); + } + + strbuf_release(&line); + fclose(in); + } + else if (errno != ENOENT) + die_errno(_("unable to read alternates file")); + + if (found) { + rollback_lock_file(&lock); + } else { + fprintf_or_die(out, "%s\n", reference); + if (commit_lock_file(&lock)) + die_errno(_("unable to move new alternates file into place")); + if (the_repository->objects->loaded_alternates) + link_alt_odb_entries(the_repository, reference, + '\n', NULL, 0); + } + free(alts); +} + +void add_to_alternates_memory(const char *reference) +{ + /* + * Make sure alternates are initialized, or else our entry may be + * overwritten when they are. + */ + prepare_alt_odb(the_repository); + + link_alt_odb_entries(the_repository, reference, + '\n', NULL, 0); +} + +struct object_directory *set_temporary_primary_odb(const char *dir, int will_destroy) +{ + struct object_directory *new_odb; + + /* + * Make sure alternates are initialized, or else our entry may be + * overwritten when they are. + */ + prepare_alt_odb(the_repository); + + /* + * Make a new primary odb and link the old primary ODB in as an + * alternate + */ + new_odb = xcalloc(1, sizeof(*new_odb)); + new_odb->path = xstrdup(dir); + + /* + * Disable ref updates while a temporary odb is active, since + * the objects in the database may roll back. + */ + new_odb->disable_ref_updates = 1; + new_odb->will_destroy = will_destroy; + new_odb->next = the_repository->objects->odb; + the_repository->objects->odb = new_odb; + return new_odb->next; +} + +static 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); +} + +void restore_primary_odb(struct object_directory *restore_odb, const char *old_path) +{ + struct object_directory *cur_odb = the_repository->objects->odb; + + if (strcmp(old_path, cur_odb->path)) + BUG("expected %s as primary object store; found %s", + old_path, cur_odb->path); + + if (cur_odb->next != restore_odb) + BUG("we expect the old primary object store to be the first alternate"); + + the_repository->objects->odb = restore_odb; + free_object_directory(cur_odb); +} + +/* + * Compute the exact path an alternate is at and returns it. In case of + * error NULL is returned and the human readable error is added to `err` + * `path` may be relative and should point to $GIT_DIR. + * `err` must not be null. + */ +char *compute_alternate_path(const char *path, struct strbuf *err) +{ + char *ref_git = NULL; + const char *repo; + int seen_error = 0; + + ref_git = real_pathdup(path, 0); + if (!ref_git) { + seen_error = 1; + strbuf_addf(err, _("path '%s' does not exist"), path); + goto out; + } + + repo = read_gitfile(ref_git); + if (!repo) + repo = read_gitfile(mkpath("%s/.git", ref_git)); + if (repo) { + free(ref_git); + ref_git = xstrdup(repo); + } + + if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { + char *ref_git_git = mkpathdup("%s/.git", ref_git); + free(ref_git); + ref_git = ref_git_git; + } else if (!is_directory(mkpath("%s/objects", ref_git))) { + struct strbuf sb = STRBUF_INIT; + seen_error = 1; + if (get_common_dir(&sb, ref_git)) { + strbuf_addf(err, + _("reference repository '%s' as a linked " + "checkout is not supported yet."), + path); + goto out; + } + + strbuf_addf(err, _("reference repository '%s' is not a " + "local repository."), path); + goto out; + } + + if (!access(mkpath("%s/shallow", ref_git), F_OK)) { + strbuf_addf(err, _("reference repository '%s' is shallow"), + path); + seen_error = 1; + goto out; + } + + if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) { + strbuf_addf(err, + _("reference repository '%s' is grafted"), + path); + seen_error = 1; + goto out; + } + +out: + if (seen_error) { + FREE_AND_NULL(ref_git); + } + + return ref_git; +} + +struct object_directory *find_odb(struct repository *r, const char *obj_dir) +{ + struct object_directory *odb; + char *obj_dir_real = real_pathdup(obj_dir, 1); + struct strbuf odb_path_real = STRBUF_INIT; + + prepare_alt_odb(r); + for (odb = r->objects->odb; odb; odb = odb->next) { + strbuf_realpath(&odb_path_real, odb->path, 1); + if (!strcmp(obj_dir_real, odb_path_real.buf)) + break; + } + + free(obj_dir_real); + strbuf_release(&odb_path_real); + + if (!odb) + die(_("could not find object directory matching %s"), obj_dir); + return odb; +} + +static void fill_alternate_refs_command(struct child_process *cmd, + const char *repo_path) +{ + const char *value; + + if (!git_config_get_value("core.alternateRefsCommand", &value)) { + cmd->use_shell = 1; + + strvec_push(&cmd->args, value); + strvec_push(&cmd->args, repo_path); + } else { + cmd->git_cmd = 1; + + strvec_pushf(&cmd->args, "--git-dir=%s", repo_path); + strvec_push(&cmd->args, "for-each-ref"); + strvec_push(&cmd->args, "--format=%(objectname)"); + + if (!git_config_get_value("core.alternateRefsPrefixes", &value)) { + strvec_push(&cmd->args, "--"); + strvec_split(&cmd->args, value); + } + } + + strvec_pushv(&cmd->env, (const char **)local_repo_env); + cmd->out = -1; +} + +static void read_alternate_refs(const char *path, + alternate_ref_fn *cb, + void *data) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + struct strbuf line = STRBUF_INIT; + FILE *fh; + + fill_alternate_refs_command(&cmd, path); + + if (start_command(&cmd)) + return; + + fh = xfdopen(cmd.out, "r"); + while (strbuf_getline_lf(&line, fh) != EOF) { + struct object_id oid; + const char *p; + + if (parse_oid_hex(line.buf, &oid, &p) || *p) { + warning(_("invalid line while parsing alternate refs: %s"), + line.buf); + break; + } + + cb(&oid, data); + } + + fclose(fh); + finish_command(&cmd); + strbuf_release(&line); +} + +struct alternate_refs_data { + alternate_ref_fn *fn; + void *data; +}; + +static int refs_from_alternate_cb(struct object_directory *e, + void *data) +{ + struct strbuf path = STRBUF_INIT; + size_t base_len; + struct alternate_refs_data *cb = data; + + if (!strbuf_realpath(&path, e->path, 0)) + goto out; + if (!strbuf_strip_suffix(&path, "/objects")) + goto out; + base_len = path.len; + + /* Is this a git repository with refs? */ + strbuf_addstr(&path, "/refs"); + if (!is_directory(path.buf)) + goto out; + strbuf_setlen(&path, base_len); + + read_alternate_refs(path.buf, cb->fn, cb->data); + +out: + strbuf_release(&path); + return 0; +} + +void for_each_alternate_ref(alternate_ref_fn fn, void *data) +{ + struct alternate_refs_data cb; + cb.fn = fn; + cb.data = data; + foreach_alt_odb(refs_from_alternate_cb, &cb); +} + +int foreach_alt_odb(alt_odb_fn fn, void *cb) +{ + struct object_directory *ent; + int r = 0; + + prepare_alt_odb(the_repository); + for (ent = the_repository->objects->odb->next; ent; ent = ent->next) { + r = fn(ent, cb); + if (r) + break; + } + return r; +} + +void prepare_alt_odb(struct repository *r) +{ + if (r->objects->loaded_alternates) + return; + + link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0); + + read_info_alternates(r, r->objects->odb->path, 0); + r->objects->loaded_alternates = 1; +} + +int has_alt_odb(struct repository *r) +{ + prepare_alt_odb(r); + return !!r->objects->odb->next; +} + +int obj_read_use_lock = 0; +pthread_mutex_t obj_read_mutex; + +void enable_obj_read_lock(void) +{ + if (obj_read_use_lock) + return; + + obj_read_use_lock = 1; + init_recursive_mutex(&obj_read_mutex); +} + +void disable_obj_read_lock(void) +{ + if (!obj_read_use_lock) + return; + + obj_read_use_lock = 0; + pthread_mutex_destroy(&obj_read_mutex); +} + +int fetch_if_missing = 1; + +static int do_oid_object_info_extended(struct repository *r, + const struct object_id *oid, + struct object_info *oi, unsigned flags) +{ + static struct object_info blank_oi = OBJECT_INFO_INIT; + const struct cached_object *co; + struct pack_entry e; + int rtype; + const struct object_id *real = oid; + int already_retried = 0; + + + if (flags & OBJECT_INFO_LOOKUP_REPLACE) + real = lookup_replace_object(r, oid); + + if (is_null_oid(real)) + return -1; + + if (!oi) + oi = &blank_oi; + + co = find_cached_object(r->objects, real); + if (co) { + if (oi->typep) + *(oi->typep) = co->type; + if (oi->sizep) + *(oi->sizep) = co->size; + if (oi->disk_sizep) + *(oi->disk_sizep) = 0; + if (oi->delta_base_oid) + oidclr(oi->delta_base_oid, the_repository->hash_algo); + if (oi->contentp) + *oi->contentp = xmemdupz(co->buf, co->size); + oi->whence = OI_CACHED; + return 0; + } + + while (1) { + if (find_pack_entry(r, real, &e)) + break; + + /* Most likely it's a loose object. */ + if (!loose_object_info(r, real, oi, flags)) + return 0; + + /* Not a loose object; someone else may have just packed it. */ + if (!(flags & OBJECT_INFO_QUICK)) { + reprepare_packed_git(r); + if (find_pack_entry(r, real, &e)) + break; + } + + /* + * If r is the_repository, this might be an attempt at + * accessing a submodule object as if it were in the_repository + * (having called add_submodule_odb() on that submodule's ODB). + * If any such ODBs exist, register them and try again. + */ + if (r == the_repository && + register_all_submodule_odb_as_alternates()) + /* We added some alternates; retry */ + continue; + + /* Check if it is a missing object */ + if (fetch_if_missing && repo_has_promisor_remote(r) && + !already_retried && + !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) { + promisor_remote_get_direct(r, real, 1); + already_retried = 1; + continue; + } + + if (flags & OBJECT_INFO_DIE_IF_CORRUPT) { + const struct packed_git *p; + if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid)) + die(_("replacement %s not found for %s"), + oid_to_hex(real), oid_to_hex(oid)); + if ((p = has_packed_and_bad(r, real))) + die(_("packed object %s (stored in %s) is corrupt"), + oid_to_hex(real), p->pack_name); + } + return -1; + } + + if (oi == &blank_oi) + /* + * We know that the caller doesn't actually need the + * information below, so return early. + */ + return 0; + rtype = packed_object_info(r, e.p, e.offset, oi); + if (rtype < 0) { + mark_bad_packed_object(e.p, real); + return do_oid_object_info_extended(r, real, oi, 0); + } else if (oi->whence == OI_PACKED) { + oi->u.packed.offset = e.offset; + oi->u.packed.pack = e.p; + oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA || + rtype == OBJ_OFS_DELTA); + } + + 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; + enum object_type type; + 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.typep = &type; + } + 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; + + if (type != OBJ_BLOB) { + ret = convert_object_file(the_repository, &outbuf, + the_hash_algo, input_algo, + content, size, type, !do_die); + free(content); + if (ret == -1) + return -1; + 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->typep) + *input_oi->typep = type; + } + 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(); + return ret; +} + + +/* returns enum object_type or negative */ +int oid_object_info(struct repository *r, + const struct object_id *oid, + unsigned long *sizep) +{ + enum object_type type; + struct object_info oi = OBJECT_INFO_INIT; + + oi.typep = &type; + oi.sizep = sizep; + if (oid_object_info_extended(r, oid, &oi, + OBJECT_INFO_LOOKUP_REPLACE) < 0) + return -1; + return type; +} + +int pretend_object_file(struct repository *repo, + void *buf, unsigned long len, enum object_type type, + struct object_id *oid) +{ + struct cached_object_entry *co; + char *co_buf; + + hash_object_file(repo->hash_algo, buf, len, type, oid); + if (has_object(repo, oid, 0) || + find_cached_object(repo->objects, oid)) + return 0; + + ALLOC_GROW(repo->objects->cached_objects, + repo->objects->cached_object_nr + 1, repo->objects->cached_object_alloc); + co = &repo->objects->cached_objects[repo->objects->cached_object_nr++]; + co->value.size = len; + co->value.type = type; + co_buf = xmalloc(len); + memcpy(co_buf, buf, len); + co->value.buf = co_buf; + oidcpy(&co->oid, oid); + return 0; +} + +/* + * This function dies on corrupt objects; the callers who want to + * deal with them should arrange to call oid_object_info_extended() and give + * error messages themselves. + */ +void *repo_read_object_file(struct repository *r, + const struct object_id *oid, + enum object_type *type, + unsigned long *size) +{ + struct object_info oi = OBJECT_INFO_INIT; + unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE; + void *data; + + oi.typep = type; + oi.sizep = size; + oi.contentp = &data; + if (oid_object_info_extended(r, oid, &oi, flags)) + return NULL; + + return data; +} + +void *read_object_with_reference(struct repository *r, + const struct object_id *oid, + enum object_type required_type, + unsigned long *size, + struct object_id *actual_oid_return) +{ + enum object_type type; + void *buffer; + unsigned long isize; + struct object_id actual_oid; + + oidcpy(&actual_oid, oid); + while (1) { + int ref_length = -1; + const char *ref_type = NULL; + + buffer = repo_read_object_file(r, &actual_oid, &type, &isize); + if (!buffer) + return NULL; + if (type == required_type) { + *size = isize; + if (actual_oid_return) + oidcpy(actual_oid_return, &actual_oid); + return buffer; + } + /* Handle references */ + else if (type == OBJ_COMMIT) + ref_type = "tree "; + else if (type == OBJ_TAG) + ref_type = "object "; + else { + free(buffer); + return NULL; + } + ref_length = strlen(ref_type); + + if (ref_length + the_hash_algo->hexsz > isize || + memcmp(buffer, ref_type, ref_length) || + get_oid_hex((char *) buffer + ref_length, &actual_oid)) { + free(buffer); + return NULL; + } + free(buffer); + /* Now we have the ID of the referred-to object in + * actual_oid. Check again. */ + } +} + +int has_object(struct repository *r, const struct object_id *oid, + unsigned flags) +{ + unsigned object_info_flags = 0; + + if (!startup_info->have_repository) + return 0; + if (!(flags & HAS_OBJECT_RECHECK_PACKED)) + object_info_flags |= OBJECT_INFO_QUICK; + if (!(flags & HAS_OBJECT_FETCH_PROMISOR)) + object_info_flags |= OBJECT_INFO_SKIP_FETCH_OBJECT; + + return oid_object_info_extended(r, oid, NULL, object_info_flags) >= 0; +} + +void assert_oid_type(const struct object_id *oid, enum object_type expect) +{ + enum object_type type = oid_object_info(the_repository, oid, NULL); + if (type < 0) + die(_("%s is not a valid object"), oid_to_hex(oid)); + if (type != expect) + die(_("%s is not a valid '%s' object"), oid_to_hex(oid), + type_name(expect)); +} + +struct raw_object_store *raw_object_store_new(void) +{ + struct raw_object_store *o = xmalloc(sizeof(*o)); + + memset(o, 0, sizeof(*o)); + INIT_LIST_HEAD(&o->packed_git_mru); + hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0); + pthread_mutex_init(&o->replace_mutex, NULL); + return o; +} + +static void free_object_directories(struct raw_object_store *o) +{ + while (o->odb) { + struct object_directory *next; + + next = o->odb->next; + free_object_directory(o->odb); + o->odb = next; + } + kh_destroy_odb_path_map(o->odb_by_path); + o->odb_by_path = NULL; +} + +void raw_object_store_clear(struct raw_object_store *o) +{ + FREE_AND_NULL(o->alternate_db); + + oidmap_clear(&o->replace_map, 1); + pthread_mutex_destroy(&o->replace_mutex); + + free_commit_graph(o->commit_graph); + o->commit_graph = NULL; + o->commit_graph_attempted = 0; + + free_object_directories(o); + o->odb_tail = NULL; + o->loaded_alternates = 0; + + for (size_t i = 0; i < o->cached_object_nr; i++) + free((char *) o->cached_objects[i].value.buf); + FREE_AND_NULL(o->cached_objects); + + INIT_LIST_HEAD(&o->packed_git_mru); + close_object_store(o); + + /* + * `close_object_store()` only closes the packfiles, but doesn't free + * them. We thus have to do this manually. + */ + for (struct packed_git *p = o->packed_git, *next; p; p = next) { + next = p->next; + free(p); + } + o->packed_git = NULL; + + hashmap_clear(&o->pack_map); +} diff --git a/object-store.h b/object-store.h index 1b3e3d7d01..c589008535 100644 --- a/object-store.h +++ b/object-store.h @@ -1,11 +1,338 @@ #ifndef OBJECT_STORE_H #define OBJECT_STORE_H -#include "khash.h" -#include "dir.h" -#include "object-store-ll.h" +#include "hashmap.h" +#include "object.h" +#include "list.h" +#include "oidset.h" +#include "oidmap.h" +#include "thread-utils.h" -KHASH_INIT(odb_path_map, const char * /* key: odb_path */, - struct object_directory *, 1, fspathhash, fspatheq) +struct oidmap; +struct oidtree; +struct strbuf; +struct repository; + +struct object_directory { + struct object_directory *next; + + /* + * Used to store the results of readdir(3) calls when we are OK + * sacrificing accuracy due to races for speed. That includes + * object existence with OBJECT_INFO_QUICK, as well as + * our search for unique abbreviated hashes. Don't use it for tasks + * requiring greater accuracy! + * + * Be sure to call odb_load_loose_cache() before using. + */ + 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 + * might be discarded on rollback. + */ + int disable_ref_updates; + + /* + * This object store is ephemeral, so there is no need to fsync. + */ + int will_destroy; + + /* + * Path to the alternative object store. If this is a relative path, + * it is relative to the current working directory. + */ + char *path; +}; + +void prepare_alt_odb(struct repository *r); +int has_alt_odb(struct repository *r); +char *compute_alternate_path(const char *path, struct strbuf *err); +struct object_directory *find_odb(struct repository *r, const char *obj_dir); +typedef int alt_odb_fn(struct object_directory *, void *); +int foreach_alt_odb(alt_odb_fn, void*); +typedef void alternate_ref_fn(const struct object_id *oid, void *); +void for_each_alternate_ref(alternate_ref_fn, void *); + +/* + * Add the directory to the on-disk alternates file; the new entry will also + * take effect in the current process. + */ +void add_to_alternates_file(const char *dir); + +/* + * Add the directory to the in-memory list of alternates (along with any + * recursive alternates it points to), but do not modify the on-disk alternates + * file. + */ +void add_to_alternates_memory(const char *dir); + +/* + * Replace the current writable object directory with the specified temporary + * object directory; returns the former primary object directory. + */ +struct object_directory *set_temporary_primary_odb(const char *dir, int will_destroy); + +/* + * Restore a previous ODB replaced by set_temporary_main_odb. + */ +void restore_primary_odb(struct object_directory *restore_odb, const char *old_path); + +struct packed_git; +struct multi_pack_index; +struct cached_object_entry; + +struct raw_object_store { + /* + * Set of all object directories; the main directory is first (and + * cannot be NULL after initialization). Subsequent directories are + * alternates. + */ + struct object_directory *odb; + struct object_directory **odb_tail; + struct kh_odb_path_map *odb_by_path; + + int loaded_alternates; + + /* + * A list of alternate object directories loaded from the environment; + * this should not generally need to be accessed directly, but will + * populate the "odb" list when prepare_alt_odb() is run. + */ + char *alternate_db; + + /* + * Objects that should be substituted by other objects + * (see git-replace(1)). + */ + struct oidmap replace_map; + unsigned replace_map_initialized : 1; + pthread_mutex_t replace_mutex; /* protect object replace functions */ + + struct commit_graph *commit_graph; + unsigned commit_graph_attempted : 1; /* if loading has been attempted */ + + /* + * private data + * + * should only be accessed directly by packfile.c and midx.c + */ + struct multi_pack_index *multi_pack_index; + + /* + * private data + * + * should only be accessed directly by packfile.c + */ + + struct packed_git *packed_git; + /* A most-recently-used ordered version of the packed_git list. */ + struct list_head packed_git_mru; + + struct { + struct packed_git **packs; + unsigned flags; + } kept_pack_cache; + + /* + * This is meant to hold a *small* number of objects that you would + * want repo_read_object_file() to be able to return, but yet you do not want + * to write them into the object store (e.g. a browse-only + * application). + */ + struct cached_object_entry *cached_objects; + size_t cached_object_nr, cached_object_alloc; + + /* + * A map of packfiles to packed_git structs for tracking which + * packs have been loaded already. + */ + struct hashmap pack_map; + + /* + * A fast, rough count of the number of objects in the repository. + * These two fields are not meant for direct access. Use + * repo_approximate_object_count() instead. + */ + unsigned long approximate_object_count; + unsigned approximate_object_count_valid : 1; + + /* + * Whether packed_git has already been populated with this repository's + * packs. + */ + unsigned packed_git_initialized : 1; +}; + +struct raw_object_store *raw_object_store_new(void); +void raw_object_store_clear(struct raw_object_store *o); + +/* + * Create a temporary file rooted in the object database directory, or + * die on failure. The filename is taken from "pattern", which should have the + * usual "XXXXXX" trailer, and the resulting filename is written into the + * "template" buffer. Returns the open descriptor. + */ +int odb_mkstemp(struct strbuf *temp_filename, const char *pattern); + +void *repo_read_object_file(struct repository *r, + const struct object_id *oid, + enum object_type *type, + unsigned long *size); + +/* Read and unpack an object file into memory, write memory to an object file */ +int oid_object_info(struct repository *r, const struct object_id *, unsigned long *); + +/* + * Add an object file to the in-memory object store, without writing it + * to disk. + * + * Callers are responsible for calling write_object_file to record the + * object in persistent storage before writing any other new objects + * that reference it. + */ +int pretend_object_file(struct repository *repo, + void *buf, unsigned long len, enum object_type type, + struct object_id *oid); + +struct object_info { + /* Request */ + enum object_type *typep; + unsigned long *sizep; + off_t *disk_sizep; + struct object_id *delta_base_oid; + void **contentp; + + /* Response */ + enum { + OI_CACHED, + OI_LOOSE, + OI_PACKED, + OI_DBCACHED + } whence; + union { + /* + * struct { + * ... Nothing to expose in this case + * } cached; + * struct { + * ... Nothing to expose in this case + * } loose; + */ + struct { + struct packed_git *pack; + off_t offset; + unsigned int is_delta; + } packed; + } u; +}; + +/* + * Initializer for a "struct object_info" that wants no items. You may + * also memset() the memory to all-zeroes. + */ +#define OBJECT_INFO_INIT { 0 } + +/* Invoke lookup_replace_object() on the given hash */ +#define OBJECT_INFO_LOOKUP_REPLACE 1 +/* Do not retry packed storage after checking packed and loose storage */ +#define OBJECT_INFO_QUICK 8 +/* + * Do not attempt to fetch the object if missing (even if fetch_is_missing is + * nonzero). + */ +#define OBJECT_INFO_SKIP_FETCH_OBJECT 16 +/* + * This is meant for bulk prefetching of missing blobs in a partial + * clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK + */ +#define OBJECT_INFO_FOR_PREFETCH (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK) + +/* Die if object corruption (not just an object being missing) was detected. */ +#define OBJECT_INFO_DIE_IF_CORRUPT 32 + +int oid_object_info_extended(struct repository *r, + const struct object_id *, + struct object_info *, unsigned flags); + +enum { + /* Retry packed storage after checking packed and loose storage */ + HAS_OBJECT_RECHECK_PACKED = (1 << 0), + /* Allow fetching the object in case the repository has a promisor remote. */ + HAS_OBJECT_FETCH_PROMISOR = (1 << 1), +}; + +/* + * Returns 1 if the object exists. This function will not lazily fetch objects + * in a partial clone by default. + */ +int has_object(struct repository *r, const struct object_id *oid, + unsigned flags); + +void assert_oid_type(const struct object_id *oid, enum object_type expect); + +/* + * Enabling the object read lock allows multiple threads to safely call the + * following functions in parallel: repo_read_object_file(), + * read_object_with_reference(), oid_object_info() and oid_object_info_extended(). + * + * obj_read_lock() and obj_read_unlock() may also be used to protect other + * section which cannot execute in parallel with object reading. Since the used + * lock is a recursive mutex, these sections can even contain calls to object + * reading functions. However, beware that in these cases zlib inflation won't + * be performed in parallel, losing performance. + * + * TODO: oid_object_info_extended()'s call stack has a recursive behavior. If + * any of its callees end up calling it, this recursive call won't benefit from + * parallel inflation. + */ +void enable_obj_read_lock(void); +void disable_obj_read_lock(void); + +extern int obj_read_use_lock; +extern pthread_mutex_t obj_read_mutex; + +static inline void obj_read_lock(void) +{ + if(obj_read_use_lock) + pthread_mutex_lock(&obj_read_mutex); +} + +static inline void obj_read_unlock(void) +{ + if(obj_read_use_lock) + pthread_mutex_unlock(&obj_read_mutex); +} +/* Flags for for_each_*_object(). */ +enum for_each_object_flags { + /* Iterate only over local objects, not alternates. */ + FOR_EACH_OBJECT_LOCAL_ONLY = (1<<0), + + /* Only iterate over packs obtained from the promisor remote. */ + FOR_EACH_OBJECT_PROMISOR_ONLY = (1<<1), + + /* + * Visit objects within a pack in packfile order rather than .idx order + */ + FOR_EACH_OBJECT_PACK_ORDER = (1<<2), + + /* Only iterate over packs that are not marked as kept in-core. */ + FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS = (1<<3), + + /* Only iterate over packs that do not have .keep files. */ + FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS = (1<<4), +}; + + +void *read_object_with_reference(struct repository *r, + const struct object_id *oid, + enum object_type required_type, + unsigned long *size, + struct object_id *oid_ret); #endif /* OBJECT_STORE_H */ @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -7,25 +6,23 @@ #include "object.h" #include "replace-object.h" #include "object-file.h" -#include "object-store.h" #include "blob.h" #include "statinfo.h" #include "tree.h" #include "commit.h" #include "tag.h" #include "alloc.h" -#include "packfile.h" #include "commit-graph.h" -#include "loose.h" -unsigned int get_max_object_index(void) +unsigned int get_max_object_index(const struct repository *repo) { - return the_repository->parsed_objects->obj_hash_size; + return repo->parsed_objects->obj_hash_size; } -struct object *get_indexed_object(unsigned int idx) +struct object *get_indexed_object(const struct repository *repo, + unsigned int idx) { - return the_repository->parsed_objects->obj_hash[idx]; + return repo->parsed_objects->obj_hash[idx]; } static const char *object_type_strings[] = { @@ -283,10 +280,11 @@ struct object *parse_object_buffer(struct repository *r, const struct object_id return obj; } -struct object *parse_object_or_die(const struct object_id *oid, +struct object *parse_object_or_die(struct repository *repo, + const struct object_id *oid, const char *name) { - struct object *o = parse_object(the_repository, oid); + struct object *o = parse_object(repo, oid); if (o) return o; @@ -491,45 +489,12 @@ void object_array_clear(struct object_array *array) array->nr = array->alloc = 0; } -/* - * Return true if array already contains an entry. - */ -static int contains_object(struct object_array *array, - const struct object *item, const char *name) -{ - unsigned nr = array->nr, i; - struct object_array_entry *object = array->objects; - - for (i = 0; i < nr; i++, object++) - if (item == object->item && !strcmp(object->name, name)) - return 1; - return 0; -} - -void object_array_remove_duplicates(struct object_array *array) -{ - unsigned nr = array->nr, src; - struct object_array_entry *objects = array->objects; - - array->nr = 0; - for (src = 0; src < nr; src++) { - if (!contains_object(array, objects[src].item, - objects[src].name)) { - if (src != array->nr) - objects[array->nr] = objects[src]; - array->nr++; - } else { - object_array_release_entry(&objects[src]); - } - } -} - -void clear_object_flags(unsigned flags) +void clear_object_flags(struct repository *repo, unsigned flags) { int i; - for (i=0; i < the_repository->parsed_objects->obj_hash_size; i++) { - struct object *obj = the_repository->parsed_objects->obj_hash[i]; + for (i = 0; i < repo->parsed_objects->obj_hash_size; i++) { + struct object *obj = repo->parsed_objects->obj_hash[i]; if (obj) obj->flags &= ~flags; } @@ -566,70 +531,6 @@ struct parsed_object_pool *parsed_object_pool_new(struct repository *repo) return o; } -struct raw_object_store *raw_object_store_new(void) -{ - struct raw_object_store *o = xmalloc(sizeof(*o)); - - memset(o, 0, sizeof(*o)); - INIT_LIST_HEAD(&o->packed_git_mru); - hashmap_init(&o->pack_map, pack_map_entry_cmp, NULL, 0); - pthread_mutex_init(&o->replace_mutex, NULL); - return o; -} - -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); -} - -static void free_object_directories(struct raw_object_store *o) -{ - while (o->odb) { - struct object_directory *next; - - next = o->odb->next; - free_object_directory(o->odb); - o->odb = next; - } - kh_destroy_odb_path_map(o->odb_by_path); - o->odb_by_path = NULL; -} - -void raw_object_store_clear(struct raw_object_store *o) -{ - FREE_AND_NULL(o->alternate_db); - - oidmap_free(o->replace_map, 1); - FREE_AND_NULL(o->replace_map); - pthread_mutex_destroy(&o->replace_mutex); - - free_commit_graph(o->commit_graph); - o->commit_graph = NULL; - o->commit_graph_attempted = 0; - - free_object_directories(o); - o->odb_tail = NULL; - o->loaded_alternates = 0; - - INIT_LIST_HEAD(&o->packed_git_mru); - close_object_store(o); - - /* - * `close_object_store()` only closes the packfiles, but doesn't free - * them. We thus have to do this manually. - */ - for (struct packed_git *p = o->packed_git, *next; p; p = next) { - next = p->next; - free(p); - } - o->packed_git = NULL; - - hashmap_clear(&o->pack_map); -} - void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o) { for (int i = 0; i < o->grafts_nr; i++) { @@ -169,12 +169,13 @@ int type_from_string_gently(const char *str, ssize_t, int gentle); /* * Return the current number of buckets in the object hashmap. */ -unsigned int get_max_object_index(void); +unsigned int get_max_object_index(const struct repository *repo); /* * Return the object from the specified bucket in the object hashmap. */ -struct object *get_indexed_object(unsigned int); +struct object *get_indexed_object(const struct repository *repo, + unsigned int); /* * This can be used to see if we have heard of the object before, but @@ -231,7 +232,8 @@ struct object *parse_object_with_flags(struct repository *r, * "name" parameter is not NULL, it is included in the error message * (otherwise, the hex object ID is given). */ -struct object *parse_object_or_die(const struct object_id *oid, const char *name); +struct object *parse_object_or_die(struct repository *repo, const struct object_id *oid, + const char *name); /* Given the result of read_sha1_file(), returns the object after * parsing it. eaten_p indicates if the object has a borrowed copy @@ -325,18 +327,12 @@ void object_array_filter(struct object_array *array, object_array_each_func_t want, void *cb_data); /* - * Remove from array all but the first entry with a given name. - * Warning: this function uses an O(N^2) algorithm. - */ -void object_array_remove_duplicates(struct object_array *array); - -/* * Remove any objects from the array, freeing all used memory; afterwards * the array is ready to store more objects with add_object_array(). */ void object_array_clear(struct object_array *array); -void clear_object_flags(unsigned flags); +void clear_object_flags(struct repository *repo, unsigned flags); /* * Clear the specified object flags from all in-core commit objects from @@ -22,7 +22,7 @@ void oidmap_init(struct oidmap *map, size_t initial_size) hashmap_init(&map->map, oidmap_neq, NULL, initial_size); } -void oidmap_free(struct oidmap *map, int free_entries) +void oidmap_clear(struct oidmap *map, int free_entries) { if (!map) return; @@ -36,12 +36,13 @@ struct oidmap { void oidmap_init(struct oidmap *map, size_t initial_size); /* - * Frees an oidmap structure and allocated memory. + * Clear an oidmap, freeing any allocated memory. The map is empty and + * can be reused without another explicit init. * * If `free_entries` is true, each oidmap_entry in the map is freed as well * using stdlibs free(). */ -void oidmap_free(struct oidmap *map, int free_entries); +void oidmap_clear(struct oidmap *map, int free_entries); /* * Returns the oidmap entry for the specified oid, or NULL if not found. @@ -66,6 +67,10 @@ void *oidmap_put(struct oidmap *map, void *entry); */ void *oidmap_remove(struct oidmap *map, const struct object_id *key); +static inline unsigned int oidmap_get_size(struct oidmap *map) +{ + return hashmap_get_size(&map->map); +} struct oidmap_iter { struct hashmap_iter h_iter; diff --git a/oss-fuzz/fuzz-pack-idx.c b/oss-fuzz/fuzz-pack-idx.c index 3e190214d1..609a343ee3 100644 --- a/oss-fuzz/fuzz-pack-idx.c +++ b/oss-fuzz/fuzz-pack-idx.c @@ -1,5 +1,5 @@ #include "git-compat-util.h" -#include "object-store-ll.h" +#include "object-store.h" #include "packfile.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 34e86d4994..56960e6ad7 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -1,11 +1,10 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "environment.h" #include "gettext.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "diff.h" #include "revision.h" @@ -26,6 +25,8 @@ #include "alloc.h" #include "refs.h" #include "strmap.h" +#include "midx.h" +#include "pack-revindex.h" struct bitmapped_commit { struct commit *commit; @@ -43,14 +44,17 @@ static inline int bitmap_writer_nr_selected_commits(struct bitmap_writer *writer } void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r, - struct packing_data *pdata) + struct packing_data *pdata, + struct multi_pack_index *midx) { memset(writer, 0, sizeof(struct bitmap_writer)); if (writer->bitmaps) BUG("bitmap writer already initialized"); + writer->repo = r; writer->bitmaps = kh_init_oid_map(); writer->pseudo_merge_commits = kh_init_oid_map(); writer->to_pack = pdata; + writer->midx = midx; string_list_init_dup(&writer->pseudo_merge_groups); @@ -113,6 +117,11 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer, struct pack_idx_entry **index) { uint32_t i; + uint32_t base_objects = 0; + + if (writer->midx) + base_objects = writer->midx->num_objects + + writer->midx->num_objects_in_base; writer->commits = ewah_new(); writer->trees = ewah_new(); @@ -142,19 +151,19 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer, switch (real_type) { case OBJ_COMMIT: - ewah_set(writer->commits, i); + ewah_set(writer->commits, i + base_objects); break; case OBJ_TREE: - ewah_set(writer->trees, i); + ewah_set(writer->trees, i + base_objects); break; case OBJ_BLOB: - ewah_set(writer->blobs, i); + ewah_set(writer->blobs, i + base_objects); break; case OBJ_TAG: - ewah_set(writer->tags, i); + ewah_set(writer->tags, i + base_objects); break; default: @@ -207,19 +216,37 @@ void bitmap_writer_push_commit(struct bitmap_writer *writer, static uint32_t find_object_pos(struct bitmap_writer *writer, const struct object_id *oid, int *found) { - struct object_entry *entry = packlist_find(writer->to_pack, oid); + struct object_entry *entry; + + entry = packlist_find(writer->to_pack, oid); + if (entry) { + uint32_t base_objects = 0; + if (writer->midx) + base_objects = writer->midx->num_objects + + writer->midx->num_objects_in_base; - if (!entry) { if (found) - *found = 0; - warning("Failed to write bitmap index. Packfile doesn't have full closure " - "(object %s is missing)", oid_to_hex(oid)); - return 0; + *found = 1; + return oe_in_pack_pos(writer->to_pack, entry) + base_objects; + } else if (writer->midx) { + uint32_t at, pos; + + if (!bsearch_midx(oid, writer->midx, &at)) + goto missing; + if (midx_to_pack_pos(writer->midx, at, &pos) < 0) + goto missing; + + if (found) + *found = 1; + return pos; } +missing: if (found) - *found = 1; - return oe_in_pack_pos(writer->to_pack, entry); + *found = 0; + warning("Failed to write bitmap index. Packfile doesn't have full closure " + "(object %s is missing)", oid_to_hex(oid)); + return 0; } static void compute_xor_offsets(struct bitmap_writer *writer) @@ -415,9 +442,9 @@ next: bb->commits[bb->commits_nr++] = r->item; } - trace2_data_intmax("pack-bitmap-write", the_repository, + trace2_data_intmax("pack-bitmap-write", writer->repo, "num_selected_commits", writer->selected_nr); - trace2_data_intmax("pack-bitmap-write", the_repository, + trace2_data_intmax("pack-bitmap-write", writer->repo, "num_maximal_commits", num_maximal); release_revisions(&revs); @@ -460,7 +487,7 @@ static int fill_bitmap_tree(struct bitmap_writer *writer, switch (object_type(entry.mode)) { case OBJ_TREE: if (fill_bitmap_tree(writer, bitmap, - lookup_tree(the_repository, &entry.oid)) < 0) + lookup_tree(writer->repo, &entry.oid)) < 0) return -1; break; case OBJ_BLOB: @@ -536,7 +563,7 @@ static int fill_bitmap_commit(struct bitmap_writer *writer, return -1; bitmap_set(ent->bitmap, pos); prio_queue_put(tree_queue, - repo_get_commit_tree(the_repository, c)); + repo_get_commit_tree(writer->repo, c)); } for (p = c->parents; p; p = p->next) { @@ -586,15 +613,15 @@ int bitmap_writer_build(struct bitmap_writer *writer) struct prio_queue queue = { compare_commits_by_gen_then_commit_date }; struct prio_queue tree_queue = { NULL }; struct bitmap_index *old_bitmap; - uint32_t *mapping; + uint32_t *mapping = NULL; int closed = 1; /* until proven otherwise */ if (writer->show_progress) - writer->progress = start_progress(the_repository, + writer->progress = start_progress(writer->repo, "Building bitmaps", writer->selected_nr); trace2_region_enter("pack-bitmap-write", "building_bitmaps_total", - the_repository); + writer->repo); old_bitmap = prepare_bitmap_git(writer->to_pack->repo); if (old_bitmap) @@ -645,10 +672,10 @@ int bitmap_writer_build(struct bitmap_writer *writer) free(mapping); trace2_region_leave("pack-bitmap-write", "building_bitmaps_total", - the_repository); - trace2_data_intmax("pack-bitmap-write", the_repository, + writer->repo); + trace2_data_intmax("pack-bitmap-write", writer->repo, "building_bitmaps_reused", reused_bitmaps_nr); - trace2_data_intmax("pack-bitmap-write", the_repository, + trace2_data_intmax("pack-bitmap-write", writer->repo, "building_bitmaps_pseudo_merge_reused", reused_pseudo_merge_bitmaps_nr); @@ -711,7 +738,7 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer, } if (writer->show_progress) - writer->progress = start_progress(the_repository, + writer->progress = start_progress(writer->repo, "Selecting bitmap commits", 0); for (;;) { @@ -960,7 +987,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f, for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) table_inv[table[i]] = i; - trace2_region_enter("pack-bitmap-write", "writing_lookup_table", the_repository); + trace2_region_enter("pack-bitmap-write", "writing_lookup_table", writer->repo); for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) { struct bitmapped_commit *selected = &writer->selected[table[i]]; uint32_t xor_offset = selected->xor_offset; @@ -987,7 +1014,7 @@ static void write_lookup_table(struct bitmap_writer *writer, struct hashfile *f, hashwrite_be64(f, (uint64_t)offsets[table[i]]); hashwrite_be32(f, xor_row); } - trace2_region_leave("pack-bitmap-write", "writing_lookup_table", the_repository); + trace2_region_leave("pack-bitmap-write", "writing_lookup_table", writer->repo); free(table); free(table_inv); @@ -1008,7 +1035,7 @@ static void write_hash_cache(struct hashfile *f, void bitmap_writer_set_checksum(struct bitmap_writer *writer, const unsigned char *sha1) { - hashcpy(writer->pack_checksum, sha1, the_repository->hash_algo); + hashcpy(writer->pack_checksum, sha1, writer->repo->hash_algo); } void bitmap_writer_finish(struct bitmap_writer *writer, @@ -1021,7 +1048,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer, struct strbuf tmp_file = STRBUF_INIT; struct hashfile *f; off_t *offsets = NULL; - uint32_t i; + uint32_t i, base_objects; struct bitmap_disk_header header; @@ -1030,15 +1057,15 @@ void bitmap_writer_finish(struct bitmap_writer *writer, if (writer->pseudo_merges_nr) options |= BITMAP_OPT_PSEUDO_MERGES; - f = hashfd(fd, tmp_file.buf); + f = hashfd(writer->repo->hash_algo, fd, tmp_file.buf); memcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE)); header.version = htons(default_version); header.options = htons(flags | options); header.entry_count = htonl(bitmap_writer_nr_selected_commits(writer)); - hashcpy(header.checksum, writer->pack_checksum, the_repository->hash_algo); + hashcpy(header.checksum, writer->pack_checksum, writer->repo->hash_algo); - hashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz); + hashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + writer->repo->hash_algo->rawsz); dump_bitmap(f, writer->commits); dump_bitmap(f, writer->trees); dump_bitmap(f, writer->blobs); @@ -1047,6 +1074,12 @@ void bitmap_writer_finish(struct bitmap_writer *writer, if (options & BITMAP_OPT_LOOKUP_TABLE) CALLOC_ARRAY(offsets, writer->to_pack->nr_objects); + if (writer->midx) + base_objects = writer->midx->num_objects + + writer->midx->num_objects_in_base; + else + base_objects = 0; + for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) { struct bitmapped_commit *stored = &writer->selected[i]; int commit_pos = oid_pos(&stored->commit->object.oid, index, @@ -1054,8 +1087,8 @@ void bitmap_writer_finish(struct bitmap_writer *writer, oid_access); if (commit_pos < 0) - BUG(_("trying to write commit not in index")); - stored->commit_pos = commit_pos; + BUG("trying to write commit not in index"); + stored->commit_pos = commit_pos + base_objects; } write_selected_commits_v1(writer, f, offsets); @@ -1072,7 +1105,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer, finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); - if (adjust_shared_perm(the_repository, tmp_file.buf)) + if (adjust_shared_perm(writer->repo, tmp_file.buf)) die_errno("unable to make temporary bitmap file readable"); if (rename(tmp_file.buf, filename)) diff --git a/pack-bitmap.c b/pack-bitmap.c index 6406953d32..8727f316de 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -17,8 +17,7 @@ #include "packfile.h" #include "repository.h" #include "trace2.h" -#include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "list-objects-filter-options.h" #include "midx.h" #include "config.h" @@ -54,6 +53,16 @@ struct bitmap_index { struct packed_git *pack; struct multi_pack_index *midx; + /* + * If using a multi-pack index chain, 'base' points to the + * bitmap index corresponding to this bitmap's midx->base_midx. + * + * base_nr indicates how many layers precede this one, and is + * zero when base is NULL. + */ + struct bitmap_index *base; + uint32_t base_nr; + /* mmapped buffer of the whole bitmap index */ unsigned char *map; size_t map_size; /* size of the mmaped buffer */ @@ -71,6 +80,23 @@ struct bitmap_index { struct ewah_bitmap *blobs; struct ewah_bitmap *tags; + /* + * Type index arrays when this bitmap is associated with an + * incremental multi-pack index chain. + * + * If n is the number of unique layers in the MIDX chain, then + * commits_all[n-1] is this structs 'commits' field, + * commits_all[n-2] is the commits field of this bitmap's + * 'base', and so on. + * + * When associated either with a non-incremental MIDX or a + * single packfile, these arrays each contain a single element. + */ + struct ewah_bitmap **commits_all; + struct ewah_bitmap **trees_all; + struct ewah_bitmap **blobs_all; + struct ewah_bitmap **tags_all; + /* Map from object ID -> `stored_bitmap` for all the bitmapped commits */ kh_oid_map_t *bitmaps; @@ -170,6 +196,15 @@ static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index) return read_bitmap(index->map, index->map_size, &index->map_pos); } +static uint32_t bitmap_num_objects_total(struct bitmap_index *index) +{ + if (index->midx) { + struct multi_pack_index *m = index->midx; + return m->num_objects + m->num_objects_in_base; + } + return index->pack->num_objects; +} + static uint32_t bitmap_num_objects(struct bitmap_index *index) { if (index->midx) @@ -353,10 +388,6 @@ static int load_bitmap_entries_v1(struct bitmap_index *index) return error(_("corrupt ewah bitmap: commit index %u out of range"), (unsigned)commit_idx_pos); - bitmap = read_bitmap_1(index); - if (!bitmap) - return -1; - if (xor_offset > MAX_XOR_OFFSET || xor_offset > i) return error(_("corrupted bitmap pack index")); @@ -367,6 +398,10 @@ static int load_bitmap_entries_v1(struct bitmap_index *index) return error(_("invalid XOR offset in bitmap pack index")); } + bitmap = read_bitmap_1(index); + if (!bitmap) + return -1; + recent_bitmaps[i % MAX_XOR_OFFSET] = store_bitmap( index, bitmap, &oid, xor_bitmap, flags); } @@ -377,8 +412,15 @@ static int load_bitmap_entries_v1(struct bitmap_index *index) char *midx_bitmap_filename(struct multi_pack_index *midx) { struct strbuf buf = STRBUF_INIT; - get_midx_filename_ext(midx->repo->hash_algo, &buf, midx->object_dir, - get_midx_checksum(midx), MIDX_EXT_BITMAP); + if (midx->has_chain) + get_split_midx_filename_ext(midx->repo->hash_algo, &buf, + midx->object_dir, + get_midx_checksum(midx), + MIDX_EXT_BITMAP); + else + get_midx_filename_ext(midx->repo->hash_algo, &buf, + midx->object_dir, get_midx_checksum(midx), + MIDX_EXT_BITMAP); return strbuf_detach(&buf, NULL); } @@ -445,16 +487,21 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git, goto cleanup; } - for (i = 0; i < bitmap_git->midx->num_packs; i++) { - if (prepare_midx_pack(bitmap_repo(bitmap_git), - bitmap_git->midx, - i)) { + for (i = 0; i < bitmap_git->midx->num_packs + bitmap_git->midx->num_packs_in_base; i++) { + if (prepare_midx_pack(bitmap_repo(bitmap_git), bitmap_git->midx, i)) { warning(_("could not open pack %s"), bitmap_git->midx->pack_names[i]); goto cleanup; } } + if (midx->base_midx) { + bitmap_git->base = prepare_midx_bitmap_git(midx->base_midx); + bitmap_git->base_nr = bitmap_git->base->base_nr + 1; + } else { + bitmap_git->base_nr = 0; + } + return 0; cleanup: @@ -506,6 +553,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git bitmap_git->map_size = xsize_t(st.st_size); bitmap_git->map = xmmap(NULL, bitmap_git->map_size, PROT_READ, MAP_PRIVATE, fd, 0); bitmap_git->map_pos = 0; + bitmap_git->base_nr = 0; close(fd); if (load_bitmap_header(bitmap_git) < 0) { @@ -525,8 +573,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_git) { if (bitmap_is_midx(bitmap_git)) { - uint32_t i; - int ret; + struct multi_pack_index *m; /* * The multi-pack-index's .rev file is already loaded via @@ -535,17 +582,47 @@ static int load_reverse_index(struct repository *r, struct bitmap_index *bitmap_ * But we still need to open the individual pack .rev files, * since we will need to make use of them in pack-objects. */ - for (i = 0; i < bitmap_git->midx->num_packs; i++) { - ret = load_pack_revindex(r, bitmap_git->midx->packs[i]); - if (ret) - return ret; + for (m = bitmap_git->midx; m; m = m->base_midx) { + uint32_t i; + int ret; + + for (i = 0; i < m->num_packs; i++) { + ret = load_pack_revindex(r, m->packs[i]); + if (ret) + return ret; + } } return 0; } return load_pack_revindex(r, bitmap_git->pack); } -static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git) +static void load_all_type_bitmaps(struct bitmap_index *bitmap_git) +{ + struct bitmap_index *curr = bitmap_git; + size_t i = bitmap_git->base_nr; + + ALLOC_ARRAY(bitmap_git->commits_all, bitmap_git->base_nr + 1); + ALLOC_ARRAY(bitmap_git->trees_all, bitmap_git->base_nr + 1); + ALLOC_ARRAY(bitmap_git->blobs_all, bitmap_git->base_nr + 1); + ALLOC_ARRAY(bitmap_git->tags_all, bitmap_git->base_nr + 1); + + while (curr) { + bitmap_git->commits_all[i] = curr->commits; + bitmap_git->trees_all[i] = curr->trees; + bitmap_git->blobs_all[i] = curr->blobs; + bitmap_git->tags_all[i] = curr->tags; + + curr = curr->base; + if (curr && !i) + BUG("unexpected number of bitmap layers, expected %"PRIu32, + bitmap_git->base_nr + 1); + i -= 1; + } +} + +static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git, + int recursing) { assert(bitmap_git->map); @@ -564,6 +641,16 @@ static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git) if (!bitmap_git->table_lookup && load_bitmap_entries_v1(bitmap_git) < 0) goto failed; + if (bitmap_git->base) { + if (!bitmap_is_midx(bitmap_git)) + BUG("non-MIDX bitmap has non-NULL base bitmap index"); + if (load_bitmap(r, bitmap_git->base, 1) < 0) + goto failed; + } + + if (!recursing) + load_all_type_bitmaps(bitmap_git); + return 0; failed: @@ -639,7 +726,7 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r) { struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git)); - if (!open_bitmap(r, bitmap_git) && !load_bitmap(r, bitmap_git)) + if (!open_bitmap(r, bitmap_git) && !load_bitmap(r, bitmap_git, 0)) return bitmap_git; free_bitmap_index(bitmap_git); @@ -648,16 +735,30 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r) struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx) { - struct repository *r = midx->repo; struct bitmap_index *bitmap_git = xcalloc(1, sizeof(*bitmap_git)); - if (!open_midx_bitmap_1(bitmap_git, midx) && !load_bitmap(r, bitmap_git)) + if (!open_midx_bitmap_1(bitmap_git, midx)) return bitmap_git; free_bitmap_index(bitmap_git); return NULL; } +int bitmap_index_contains_pack(struct bitmap_index *bitmap, struct packed_git *pack) +{ + for (; bitmap; bitmap = bitmap->base) { + if (bitmap_is_midx(bitmap)) { + for (size_t i = 0; i < bitmap->midx->num_packs; i++) + if (bitmap->midx->packs[i] == pack) + return 1; + } else if (bitmap->pack == pack) { + return 1; + } + } + + return 0; +} + struct include_data { struct bitmap_index *bitmap_git; struct bitmap *base; @@ -896,26 +997,42 @@ corrupt: return NULL; } -struct ewah_bitmap *bitmap_for_commit(struct bitmap_index *bitmap_git, - struct commit *commit) +static struct ewah_bitmap *find_bitmap_for_commit(struct bitmap_index *bitmap_git, + struct commit *commit, + struct bitmap_index **found) { - khiter_t hash_pos = kh_get_oid_map(bitmap_git->bitmaps, - commit->object.oid); + khiter_t hash_pos; + if (!bitmap_git) + return NULL; + + hash_pos = kh_get_oid_map(bitmap_git->bitmaps, commit->object.oid); if (hash_pos >= kh_end(bitmap_git->bitmaps)) { struct stored_bitmap *bitmap = NULL; if (!bitmap_git->table_lookup) - return NULL; + return find_bitmap_for_commit(bitmap_git->base, commit, + found); /* this is a fairly hot codepath - no trace2_region please */ /* NEEDSWORK: cache misses aren't recorded */ bitmap = lazy_bitmap_for_commit(bitmap_git, commit); if (!bitmap) - return NULL; + return find_bitmap_for_commit(bitmap_git->base, commit, + found); + if (found) + *found = bitmap_git; return lookup_stored_bitmap(bitmap); } + if (found) + *found = bitmap_git; return lookup_stored_bitmap(kh_value(bitmap_git->bitmaps, hash_pos)); } +struct ewah_bitmap *bitmap_for_commit(struct bitmap_index *bitmap_git, + struct commit *commit) +{ + return find_bitmap_for_commit(bitmap_git, commit, NULL); +} + static inline int bitmap_position_extended(struct bitmap_index *bitmap_git, const struct object_id *oid) { @@ -924,7 +1041,7 @@ static inline int bitmap_position_extended(struct bitmap_index *bitmap_git, if (pos < kh_end(positions)) { int bitmap_pos = kh_value(positions, pos); - return bitmap_pos + bitmap_num_objects(bitmap_git); + return bitmap_pos + bitmap_num_objects_total(bitmap_git); } return -1; @@ -992,7 +1109,7 @@ static int ext_index_add_object(struct bitmap_index *bitmap_git, bitmap_pos = kh_value(eindex->positions, hash_pos); } - return bitmap_pos + bitmap_num_objects(bitmap_git); + return bitmap_pos + bitmap_num_objects_total(bitmap_git); } struct bitmap_show_data { @@ -1024,10 +1141,15 @@ static unsigned apply_pseudo_merges_for_commit_1(struct bitmap_index *bitmap_git struct commit *commit, uint32_t commit_pos) { - int ret; + struct bitmap_index *curr = bitmap_git; + int ret = 0; - ret = apply_pseudo_merges_for_commit(&bitmap_git->pseudo_merges, - result, commit, commit_pos); + while (curr) { + ret += apply_pseudo_merges_for_commit(&curr->pseudo_merges, + result, commit, + commit_pos); + curr = curr->base; + } if (ret) pseudo_merges_satisfied_nr += ret; @@ -1241,8 +1363,8 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, bitmap_set(roots_bitmap, pos); } - if (!cascade_pseudo_merges_1(bitmap_git, cb.base, roots_bitmap)) - bitmap_free(roots_bitmap); + cascade_pseudo_merges_1(bitmap_git, cb.base, roots_bitmap); + bitmap_free(roots_bitmap); } /* @@ -1301,7 +1423,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git, revs->tag_objects = tmp_tags; reset_revision_walk(); - clear_object_flags(UNINTERESTING); + clear_object_flags(repo, UNINTERESTING); /* * Then add the boundary commit(s) as fill-in traversal tips. @@ -1342,11 +1464,17 @@ struct ewah_bitmap *pseudo_merge_bitmap_for_commit(struct bitmap_index *bitmap_g if (pos < 0 || pos >= bitmap_num_objects(bitmap_git)) goto done; + /* + * Use bitmap-relative positions instead of offsetting + * by bitmap_git->num_objects_in_base because we use + * this to find a match in pseudo_merge_for_parents(), + * and pseudo-merge groups cannot span multiple bitmap + * layers. + */ bitmap_set(parents, pos); } - match = pseudo_merge_for_parents(&bitmap_git->pseudo_merges, - parents); + match = pseudo_merge_for_parents(&bitmap_git->pseudo_merges, parents); done: bitmap_free(parents); @@ -1500,7 +1628,9 @@ static void show_extended_objects(struct bitmap_index *bitmap_git, for (i = 0; i < eindex->count; ++i) { struct object *obj; - if (!bitmap_get(objects, st_add(bitmap_num_objects(bitmap_git), i))) + if (!bitmap_get(objects, + st_add(bitmap_num_objects_total(bitmap_git), + i))) continue; obj = eindex->objects[i]; @@ -1509,29 +1639,33 @@ static void show_extended_objects(struct bitmap_index *bitmap_git, (obj->type == OBJ_TAG && !revs->tag_objects)) continue; - show_reach(&obj->oid, obj->type, 0, eindex->hashes[i], NULL, 0); + show_reach(&obj->oid, obj->type, 0, eindex->hashes[i], NULL, 0, NULL); } } -static void init_type_iterator(struct ewah_iterator *it, +static void init_type_iterator(struct ewah_or_iterator *it, struct bitmap_index *bitmap_git, enum object_type type) { switch (type) { case OBJ_COMMIT: - ewah_iterator_init(it, bitmap_git->commits); + ewah_or_iterator_init(it, bitmap_git->commits_all, + bitmap_git->base_nr + 1); break; case OBJ_TREE: - ewah_iterator_init(it, bitmap_git->trees); + ewah_or_iterator_init(it, bitmap_git->trees_all, + bitmap_git->base_nr + 1); break; case OBJ_BLOB: - ewah_iterator_init(it, bitmap_git->blobs); + ewah_or_iterator_init(it, bitmap_git->blobs_all, + bitmap_git->base_nr + 1); break; case OBJ_TAG: - ewah_iterator_init(it, bitmap_git->tags); + ewah_or_iterator_init(it, bitmap_git->tags_all, + bitmap_git->base_nr + 1); break; default: @@ -1542,21 +1676,21 @@ static void init_type_iterator(struct ewah_iterator *it, static void show_objects_for_type( struct bitmap_index *bitmap_git, + struct bitmap *objects, enum object_type object_type, - show_reachable_fn show_reach) + show_reachable_fn show_reach, + void *payload) { size_t i = 0; uint32_t offset; - struct ewah_iterator it; + struct ewah_or_iterator it; eword_t filter; - struct bitmap *objects = bitmap_git->result; - init_type_iterator(&it, bitmap_git, object_type); for (i = 0; i < objects->word_alloc && - ewah_iterator_next(&filter, &it); i++) { + ewah_or_iterator_next(&filter, &it); i++) { eword_t word = objects->words[i] & filter; size_t pos = (i * BITS_IN_EWORD); @@ -1583,7 +1717,7 @@ static void show_objects_for_type( nth_midxed_object_oid(&oid, m, index_pos); pack_id = nth_midxed_pack_int_id(m, index_pos); - pack = bitmap_git->midx->packs[pack_id]; + pack = nth_midxed_pack(bitmap_git->midx, pack_id); } else { index_pos = pack_pos_to_index(bitmap_git->pack, pos + offset); ofs = pack_pos_to_offset(bitmap_git->pack, pos + offset); @@ -1595,9 +1729,11 @@ static void show_objects_for_type( if (bitmap_git->hashes) hash = get_be32(bitmap_git->hashes + index_pos); - show_reach(&oid, object_type, 0, hash, pack, ofs); + show_reach(&oid, object_type, 0, hash, pack, ofs, payload); } } + + ewah_or_iterator_release(&it); } static int in_bitmapped_pack(struct bitmap_index *bitmap_git, @@ -1649,7 +1785,7 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git, { struct eindex *eindex = &bitmap_git->ext_index; struct bitmap *tips; - struct ewah_iterator it; + struct ewah_or_iterator it; eword_t mask; uint32_t i; @@ -1666,7 +1802,7 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git, * packfile. */ for (i = 0, init_type_iterator(&it, bitmap_git, type); - i < to_filter->word_alloc && ewah_iterator_next(&mask, &it); + i < to_filter->word_alloc && ewah_or_iterator_next(&mask, &it); i++) { if (i < tips->word_alloc) mask &= ~tips->words[i]; @@ -1679,13 +1815,14 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git, * them individually. */ for (i = 0; i < eindex->count; i++) { - size_t pos = st_add(i, bitmap_num_objects(bitmap_git)); + size_t pos = st_add(i, bitmap_num_objects_total(bitmap_git)); if (eindex->objects[i]->type == type && bitmap_get(to_filter, pos) && !bitmap_get(tips, pos)) bitmap_unset(to_filter, pos); } + ewah_or_iterator_release(&it); bitmap_free(tips); } @@ -1705,7 +1842,7 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git, oi.sizep = &size; - if (pos < bitmap_num_objects(bitmap_git)) { + if (pos < bitmap_num_objects_total(bitmap_git)) { struct packed_git *pack; off_t ofs; @@ -1713,7 +1850,7 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git, uint32_t midx_pos = pack_pos_to_midx(bitmap_git->midx, pos); uint32_t pack_id = nth_midxed_pack_int_id(bitmap_git->midx, midx_pos); - pack = bitmap_git->midx->packs[pack_id]; + pack = nth_midxed_pack(bitmap_git->midx, pack_id); ofs = nth_midxed_offset(bitmap_git->midx, midx_pos); } else { pack = bitmap_git->pack; @@ -1728,8 +1865,9 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git, die(_("unable to get size of %s"), oid_to_hex(&oid)); } } else { + size_t eindex_pos = pos - bitmap_num_objects_total(bitmap_git); struct eindex *eindex = &bitmap_git->ext_index; - struct object *obj = eindex->objects[pos - bitmap_num_objects(bitmap_git)]; + struct object *obj = eindex->objects[eindex_pos]; if (oid_object_info_extended(bitmap_repo(bitmap_git), &obj->oid, &oi, 0) < 0) die(_("unable to get size of %s"), oid_to_hex(&obj->oid)); @@ -1745,14 +1883,14 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git, { struct eindex *eindex = &bitmap_git->ext_index; struct bitmap *tips; - struct ewah_iterator it; + struct ewah_or_iterator it; eword_t mask; uint32_t i; tips = find_tip_objects(bitmap_git, tip_objects, OBJ_BLOB); for (i = 0, init_type_iterator(&it, bitmap_git, OBJ_BLOB); - i < to_filter->word_alloc && ewah_iterator_next(&mask, &it); + i < to_filter->word_alloc && ewah_or_iterator_next(&mask, &it); i++) { eword_t word = to_filter->words[i] & mask; unsigned offset; @@ -1780,6 +1918,7 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git, bitmap_unset(to_filter, pos); } + ewah_or_iterator_release(&it); bitmap_free(tips); } @@ -1882,7 +2021,7 @@ static void filter_packed_objects_from_bitmap(struct bitmap_index *bitmap_git, uint32_t objects_nr; size_t i, pos; - objects_nr = bitmap_num_objects(bitmap_git); + objects_nr = bitmap_num_objects_total(bitmap_git); pos = objects_nr / BITS_IN_EWORD; if (pos > result->word_alloc) @@ -1899,6 +2038,50 @@ static void filter_packed_objects_from_bitmap(struct bitmap_index *bitmap_git, } } +int for_each_bitmapped_object(struct bitmap_index *bitmap_git, + struct list_objects_filter_options *filter, + show_reachable_fn show_reach, + void *payload) +{ + struct bitmap *filtered_bitmap = NULL; + uint32_t objects_nr; + size_t full_word_count; + int ret; + + if (!can_filter_bitmap(filter)) { + ret = -1; + goto out; + } + + objects_nr = bitmap_num_objects(bitmap_git); + full_word_count = objects_nr / BITS_IN_EWORD; + + /* We start from the all-1 bitmap and then filter down from there. */ + filtered_bitmap = bitmap_word_alloc(full_word_count + !!(objects_nr % BITS_IN_EWORD)); + memset(filtered_bitmap->words, 0xff, full_word_count * sizeof(*filtered_bitmap->words)); + for (size_t i = full_word_count * BITS_IN_EWORD; i < objects_nr; i++) + bitmap_set(filtered_bitmap, i); + + if (filter_bitmap(bitmap_git, NULL, filtered_bitmap, filter) < 0) { + ret = -1; + goto out; + } + + show_objects_for_type(bitmap_git, filtered_bitmap, + OBJ_COMMIT, show_reach, payload); + show_objects_for_type(bitmap_git, filtered_bitmap, + OBJ_TREE, show_reach, payload); + show_objects_for_type(bitmap_git, filtered_bitmap, + OBJ_BLOB, show_reach, payload); + show_objects_for_type(bitmap_git, filtered_bitmap, + OBJ_TAG, show_reach, payload); + + ret = 0; +out: + bitmap_free(filtered_bitmap); + return ret; +} + struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs, int filter_provided_objects) { @@ -1935,7 +2118,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs, struct object *object = revs->pending.objects[i].item; if (object->type == OBJ_NONE) - parse_object_or_die(&object->oid, NULL); + parse_object_or_die(revs->repo, &object->oid, NULL); while (object->type == OBJ_TAG) { struct tag *tag = (struct tag *) object; @@ -1945,7 +2128,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs, else object_list_insert(object, &wants); - object = parse_object_or_die(get_tagged_oid(tag), NULL); + object = parse_object_or_die(revs->repo, get_tagged_oid(tag), NULL); object->flags |= (tag->object.flags & UNINTERESTING); } @@ -1980,7 +2163,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs, * from disk. this is the point of no return; after this the rev_list * becomes invalidated and we must perform the revwalk through bitmaps */ - if (load_bitmap(revs->repo, bitmap_git) < 0) + if (load_bitmap(revs->repo, bitmap_git, 0) < 0) goto cleanup; if (!use_boundary_traversal) @@ -2281,7 +2464,8 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git, multi_pack_reuse = 0; if (multi_pack_reuse) { - for (i = 0; i < bitmap_git->midx->num_packs; i++) { + struct multi_pack_index *m = bitmap_git->midx; + for (i = 0; i < m->num_packs + m->num_packs_in_base; i++) { struct bitmapped_pack pack; if (nth_bitmapped_pack(r, bitmap_git->midx, &pack, i) < 0) { warning(_("unable to load pack: '%s', disabling pack-reuse"), @@ -2307,14 +2491,18 @@ void reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git, uint32_t pack_int_id; if (bitmap_is_midx(bitmap_git)) { + struct multi_pack_index *m = bitmap_git->midx; uint32_t preferred_pack_pos; - if (midx_preferred_pack(bitmap_git->midx, &preferred_pack_pos) < 0) { + while (m->base_midx) + m = m->base_midx; + + if (midx_preferred_pack(m, &preferred_pack_pos) < 0) { warning(_("unable to compute preferred pack, disabling pack-reuse")); return; } - pack = bitmap_git->midx->packs[preferred_pack_pos]; + pack = nth_midxed_pack(m, preferred_pack_pos); pack_int_id = preferred_pack_pos; } else { pack = bitmap_git->pack; @@ -2388,13 +2576,17 @@ void traverse_bitmap_commit_list(struct bitmap_index *bitmap_git, { assert(bitmap_git->result); - show_objects_for_type(bitmap_git, OBJ_COMMIT, show_reachable); + show_objects_for_type(bitmap_git, bitmap_git->result, + OBJ_COMMIT, show_reachable, NULL); if (revs->tree_objects) - show_objects_for_type(bitmap_git, OBJ_TREE, show_reachable); + show_objects_for_type(bitmap_git, bitmap_git->result, + OBJ_TREE, show_reachable, NULL); if (revs->blob_objects) - show_objects_for_type(bitmap_git, OBJ_BLOB, show_reachable); + show_objects_for_type(bitmap_git, bitmap_git->result, + OBJ_BLOB, show_reachable, NULL); if (revs->tag_objects) - show_objects_for_type(bitmap_git, OBJ_TAG, show_reachable); + show_objects_for_type(bitmap_git, bitmap_git->result, + OBJ_TAG, show_reachable, NULL); show_extended_objects(bitmap_git, revs, show_reachable); } @@ -2406,12 +2598,12 @@ static uint32_t count_object_type(struct bitmap_index *bitmap_git, struct eindex *eindex = &bitmap_git->ext_index; uint32_t i = 0, count = 0; - struct ewah_iterator it; + struct ewah_or_iterator it; eword_t filter; init_type_iterator(&it, bitmap_git, type); - while (i < objects->word_alloc && ewah_iterator_next(&filter, &it)) { + while (i < objects->word_alloc && ewah_or_iterator_next(&filter, &it)) { eword_t word = objects->words[i++] & filter; count += ewah_bit_popcount64(word); } @@ -2419,10 +2611,12 @@ static uint32_t count_object_type(struct bitmap_index *bitmap_git, for (i = 0; i < eindex->count; ++i) { if (eindex->objects[i]->type == type && bitmap_get(objects, - st_add(bitmap_num_objects(bitmap_git), i))) + st_add(bitmap_num_objects_total(bitmap_git), i))) count++; } + ewah_or_iterator_release(&it); + return count; } @@ -2454,6 +2648,8 @@ struct bitmap_test_data { struct bitmap *tags; struct progress *prg; size_t seen; + + struct bitmap_test_data *base_tdata; }; static void test_bitmap_type(struct bitmap_test_data *tdata, @@ -2462,6 +2658,11 @@ static void test_bitmap_type(struct bitmap_test_data *tdata, enum object_type bitmap_type = OBJ_NONE; int bitmaps_nr = 0; + if (bitmap_is_midx(tdata->bitmap_git)) { + while (pos < tdata->bitmap_git->midx->num_objects_in_base) + tdata = tdata->base_tdata; + } + if (bitmap_get(tdata->commits, pos)) { bitmap_type = OBJ_COMMIT; bitmaps_nr++; @@ -2525,13 +2726,57 @@ static void test_show_commit(struct commit *commit, void *data) display_progress(tdata->prg, ++tdata->seen); } +static uint32_t bitmap_total_entry_count(struct bitmap_index *bitmap_git) +{ + uint32_t total = 0; + do { + total = st_add(total, bitmap_git->entry_count); + bitmap_git = bitmap_git->base; + } while (bitmap_git); + + return total; +} + +static void bitmap_test_data_prepare(struct bitmap_test_data *tdata, + struct bitmap_index *bitmap_git) +{ + memset(tdata, 0, sizeof(struct bitmap_test_data)); + + tdata->bitmap_git = bitmap_git; + tdata->base = bitmap_new(); + tdata->commits = ewah_to_bitmap(bitmap_git->commits); + tdata->trees = ewah_to_bitmap(bitmap_git->trees); + tdata->blobs = ewah_to_bitmap(bitmap_git->blobs); + tdata->tags = ewah_to_bitmap(bitmap_git->tags); + + if (bitmap_git->base) { + tdata->base_tdata = xmalloc(sizeof(struct bitmap_test_data)); + bitmap_test_data_prepare(tdata->base_tdata, bitmap_git->base); + } +} + +static void bitmap_test_data_release(struct bitmap_test_data *tdata) +{ + if (!tdata) + return; + + bitmap_test_data_release(tdata->base_tdata); + free(tdata->base_tdata); + + bitmap_free(tdata->base); + bitmap_free(tdata->commits); + bitmap_free(tdata->trees); + bitmap_free(tdata->blobs); + bitmap_free(tdata->tags); +} + void test_bitmap_walk(struct rev_info *revs) { struct object *root; struct bitmap *result = NULL; size_t result_popcnt; struct bitmap_test_data tdata; - struct bitmap_index *bitmap_git; + struct bitmap_index *bitmap_git, *found; struct ewah_bitmap *bm; if (!(bitmap_git = prepare_bitmap_git(revs->repo))) @@ -2540,17 +2785,28 @@ void test_bitmap_walk(struct rev_info *revs) if (revs->pending.nr != 1) die(_("you must specify exactly one commit to test")); - fprintf_ln(stderr, "Bitmap v%d test (%d entries%s)", + fprintf_ln(stderr, "Bitmap v%d test (%d entries%s, %d total)", bitmap_git->version, bitmap_git->entry_count, - bitmap_git->table_lookup ? "" : " loaded"); + bitmap_git->table_lookup ? "" : " loaded", + bitmap_total_entry_count(bitmap_git)); root = revs->pending.objects[0].item; - bm = bitmap_for_commit(bitmap_git, (struct commit *)root); + bm = find_bitmap_for_commit(bitmap_git, (struct commit *)root, &found); if (bm) { fprintf_ln(stderr, "Found bitmap for '%s'. %d bits / %08x checksum", - oid_to_hex(&root->oid), (int)bm->bit_size, ewah_checksum(bm)); + oid_to_hex(&root->oid), + (int)bm->bit_size, ewah_checksum(bm)); + + if (bitmap_is_midx(found)) + fprintf_ln(stderr, "Located via MIDX '%s'.", + hash_to_hex_algop(get_midx_checksum(found->midx), + revs->repo->hash_algo)); + else + fprintf_ln(stderr, "Located via pack '%s'.", + hash_to_hex_algop(found->pack->hash, + revs->repo->hash_algo)); result = ewah_to_bitmap(bm); } @@ -2567,16 +2823,10 @@ void test_bitmap_walk(struct rev_info *revs) if (prepare_revision_walk(revs)) die(_("revision walk setup failed")); - tdata.bitmap_git = bitmap_git; - tdata.base = bitmap_new(); - tdata.commits = ewah_to_bitmap(bitmap_git->commits); - tdata.trees = ewah_to_bitmap(bitmap_git->trees); - tdata.blobs = ewah_to_bitmap(bitmap_git->blobs); - tdata.tags = ewah_to_bitmap(bitmap_git->tags); + bitmap_test_data_prepare(&tdata, bitmap_git); tdata.prg = start_progress(revs->repo, "Verifying bitmap entries", result_popcnt); - tdata.seen = 0; traverse_commit_list(revs, &test_show_commit, &test_show_object, &tdata); @@ -2588,11 +2838,7 @@ void test_bitmap_walk(struct rev_info *revs) die(_("mismatch in bitmap results")); bitmap_free(result); - bitmap_free(tdata.base); - bitmap_free(tdata.commits); - bitmap_free(tdata.trees); - bitmap_free(tdata.blobs); - bitmap_free(tdata.tags); + bitmap_test_data_release(&tdata); free_bitmap_index(bitmap_git); } @@ -2820,7 +3066,7 @@ uint32_t *create_bitmap_mapping(struct bitmap_index *bitmap_git, BUG("rebuild_existing_bitmaps: missing required rev-cache " "extension"); - num_objects = bitmap_num_objects(bitmap_git); + num_objects = bitmap_num_objects_total(bitmap_git); CALLOC_ARRAY(reposition, num_objects); for (i = 0; i < num_objects; ++i) { @@ -2856,6 +3102,10 @@ void free_bitmap_index(struct bitmap_index *b) ewah_pool_free(b->trees); ewah_pool_free(b->blobs); ewah_pool_free(b->tags); + free(b->commits_all); + free(b->trees_all); + free(b->blobs_all); + free(b->tags_all); if (b->bitmaps) { struct stored_bitmap *sb; kh_foreach_value(b->bitmaps, sb, { @@ -2883,6 +3133,7 @@ void free_bitmap_index(struct bitmap_index *b) close_midx_revindex(b->midx); } free_pseudo_merge_map(&b->pseudo_merges); + free_bitmap_index(b->base); free(b); } @@ -2898,13 +3149,13 @@ static off_t get_disk_usage_for_type(struct bitmap_index *bitmap_git, { struct bitmap *result = bitmap_git->result; off_t total = 0; - struct ewah_iterator it; + struct ewah_or_iterator it; eword_t filter; size_t i; init_type_iterator(&it, bitmap_git, object_type); for (i = 0; i < result->word_alloc && - ewah_iterator_next(&filter, &it); i++) { + ewah_or_iterator_next(&filter, &it); i++) { eword_t word = result->words[i] & filter; size_t base = (i * BITS_IN_EWORD); unsigned offset; @@ -2924,7 +3175,7 @@ static off_t get_disk_usage_for_type(struct bitmap_index *bitmap_git, off_t offset = nth_midxed_offset(bitmap_git->midx, midx_pos); uint32_t pack_id = nth_midxed_pack_int_id(bitmap_git->midx, midx_pos); - struct packed_git *pack = bitmap_git->midx->packs[pack_id]; + struct packed_git *pack = nth_midxed_pack(bitmap_git->midx, pack_id); if (offset_to_pack_pos(pack, offset, &pack_pos) < 0) { struct object_id oid; @@ -2945,6 +3196,8 @@ static off_t get_disk_usage_for_type(struct bitmap_index *bitmap_git, } } + ewah_or_iterator_release(&it); + return total; } @@ -2963,7 +3216,8 @@ static off_t get_disk_usage_for_extended(struct bitmap_index *bitmap_git) struct object *obj = eindex->objects[i]; if (!bitmap_get(result, - st_add(bitmap_num_objects(bitmap_git), i))) + st_add(bitmap_num_objects_total(bitmap_git), + i))) continue; if (oid_object_info_extended(bitmap_repo(bitmap_git), &obj->oid, @@ -3024,7 +3278,8 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname) return 0; } -static int verify_bitmap_file(const char *name) +static int verify_bitmap_file(const struct git_hash_algo *algop, + const char *name) { struct stat st; unsigned char *data; @@ -3040,7 +3295,7 @@ static int verify_bitmap_file(const char *name) data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); - if (!hashfile_checksum_valid(data, st.st_size)) + if (!hashfile_checksum_valid(algop, data, st.st_size)) res = error(_("bitmap file '%s' has invalid checksum"), name); @@ -3055,14 +3310,14 @@ int verify_bitmap_files(struct repository *r) for (struct multi_pack_index *m = get_multi_pack_index(r); m; m = m->next) { char *midx_bitmap_name = midx_bitmap_filename(m); - res |= verify_bitmap_file(midx_bitmap_name); + res |= verify_bitmap_file(r->hash_algo, midx_bitmap_name); free(midx_bitmap_name); } for (struct packed_git *p = get_all_packs(r); p; p = p->next) { char *pack_bitmap_name = pack_bitmap_filename(p); - res |= verify_bitmap_file(pack_bitmap_name); + res |= verify_bitmap_file(r->hash_algo, pack_bitmap_name); free(pack_bitmap_name); } diff --git a/pack-bitmap.h b/pack-bitmap.h index d7f4b8b8e9..382d39499a 100644 --- a/pack-bitmap.h +++ b/pack-bitmap.h @@ -50,7 +50,8 @@ typedef int (*show_reachable_fn)( int flags, uint32_t hash, struct packed_git *found_pack, - off_t found_offset); + off_t found_offset, + void *payload); struct bitmap_index; @@ -66,6 +67,13 @@ struct bitmapped_pack { struct bitmap_index *prepare_bitmap_git(struct repository *r); struct bitmap_index *prepare_midx_bitmap_git(struct multi_pack_index *midx); + +/* + * Given a bitmap index, determine whether it contains the pack either directly + * or via the multi-pack-index. + */ +int bitmap_index_contains_pack(struct bitmap_index *bitmap, struct packed_git *pack); + void count_bitmap_commit_list(struct bitmap_index *, uint32_t *commits, uint32_t *trees, uint32_t *blobs, uint32_t *tags); void traverse_bitmap_commit_list(struct bitmap_index *, @@ -78,6 +86,18 @@ int test_bitmap_pseudo_merges(struct repository *r); int test_bitmap_pseudo_merge_commits(struct repository *r, uint32_t n); int test_bitmap_pseudo_merge_objects(struct repository *r, uint32_t n); +struct list_objects_filter_options; + +/* + * Filter bitmapped objects and iterate through all resulting objects, + * executing `show_reach` for each of them. Returns `-1` in case the filter is + * not supported, `0` otherwise. + */ +int for_each_bitmapped_object(struct bitmap_index *bitmap_git, + struct list_objects_filter_options *filter, + show_reachable_fn show_reach, + void *payload); + #define GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL \ "GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL" @@ -104,6 +124,7 @@ int bitmap_has_oid_in_uninteresting(struct bitmap_index *, const struct object_i off_t get_disk_usage_from_bitmap(struct bitmap_index *, struct rev_info *); struct bitmap_writer { + struct repository *repo; struct ewah_bitmap *commits; struct ewah_bitmap *trees; struct ewah_bitmap *blobs; @@ -111,6 +132,7 @@ struct bitmap_writer { kh_oid_map_t *bitmaps; struct packing_data *to_pack; + struct multi_pack_index *midx; /* if appending to a MIDX chain */ struct bitmapped_commit *selected; unsigned int selected_nr, selected_alloc; @@ -125,7 +147,8 @@ struct bitmap_writer { }; void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r, - struct packing_data *pdata); + struct packing_data *pdata, + struct multi_pack_index *midx); void bitmap_writer_show_progress(struct bitmap_writer *writer, int show); void bitmap_writer_set_checksum(struct bitmap_writer *writer, const unsigned char *sha1); diff --git a/pack-check.c b/pack-check.c index d0aeb5ec41..874897d6cb 100644 --- a/pack-check.c +++ b/pack-check.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -9,7 +8,7 @@ #include "progress.h" #include "packfile.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" struct idx_entry { off_t offset; @@ -44,7 +43,7 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, } while (len); index_crc = p->index_data; - index_crc += 2 + 256 + (size_t)p->num_objects * (the_hash_algo->rawsz/4) + nr; + index_crc += 2 + 256 + (size_t)p->num_objects * (p->repo->hash_algo->rawsz/4) + nr; return data_crc != ntohl(*index_crc); } @@ -81,11 +80,11 @@ static int verify_packfile(struct repository *r, } while (offset < pack_sig_ofs); git_hash_final(hash, &ctx); pack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL); - if (!hasheq(hash, pack_sig, the_repository->hash_algo)) + if (!hasheq(hash, pack_sig, r->hash_algo)) err = error("%s pack checksum mismatch", p->pack_name); if (!hasheq(index_base + index_size - r->hash_algo->hexsz, pack_sig, - the_repository->hash_algo)) + r->hash_algo)) err = error("%s pack checksum does not match its index", p->pack_name); unuse_pack(w_curs); @@ -131,7 +130,8 @@ static int verify_packfile(struct repository *r, type = unpack_object_header(p, w_curs, &curpos, &size); unuse_pack(w_curs); - if (type == OBJ_BLOB && big_file_threshold <= size) { + if (type == OBJ_BLOB && + repo_settings_get_big_file_threshold(r) <= size) { /* * Let stream_object_signature() check it with * the streaming interface; no point slurping @@ -180,7 +180,7 @@ int verify_pack_index(struct packed_git *p) return error("packfile %s index not opened", p->pack_name); /* Verify SHA1 sum of the index file */ - if (!hashfile_checksum_valid(p->index_data, p->index_size)) + if (!hashfile_checksum_valid(p->repo->hash_algo, p->index_data, p->index_size)) err = error("Packfile index for %s hash mismatch", p->pack_name); return err; diff --git a/pack-mtimes.c b/pack-mtimes.c index cdf30b8d2b..20900ca88d 100644 --- a/pack-mtimes.c +++ b/pack-mtimes.c @@ -1,8 +1,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "pack-mtimes.h" -#include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "packfile.h" #include "strbuf.h" diff --git a/pack-objects.h b/pack-objects.h index d73e3843c9..b1c3e702f4 100644 --- a/pack-objects.h +++ b/pack-objects.h @@ -1,9 +1,10 @@ #ifndef PACK_OBJECTS_H #define PACK_OBJECTS_H -#include "object-store-ll.h" +#include "object-store.h" #include "thread-utils.h" #include "pack.h" +#include "packfile.h" struct repository; @@ -119,11 +120,23 @@ struct object_entry { unsigned ext_base:1; /* delta_idx points outside packlist */ }; +/** + * A packing region is a section of the packing_data.objects array + * as given by a starting index and a number of elements. + */ +struct packing_region { + size_t start; + size_t nr; +}; + struct packing_data { struct repository *repo; struct object_entry *objects; uint32_t nr_objects, nr_alloc; + struct packing_region *regions; + size_t nr_regions, nr_regions_alloc; + int32_t *index; uint32_t index_size; diff --git a/pack-revindex.c b/pack-revindex.c index d3832478d9..ffcde48870 100644 --- a/pack-revindex.c +++ b/pack-revindex.c @@ -1,14 +1,12 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "gettext.h" #include "pack-revindex.h" -#include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "packfile.h" #include "strbuf.h" #include "trace2.h" #include "parse.h" +#include "repository.h" #include "midx.h" #include "csum-file.h" @@ -137,7 +135,7 @@ static void create_pack_revindex(struct packed_git *p) const unsigned num_ent = p->num_objects; unsigned i; const char *index = p->index_data; - const unsigned hashsz = the_hash_algo->rawsz; + const unsigned hashsz = p->repo->hash_algo->rawsz; ALLOC_ARRAY(p->revindex, num_ent + 1); index += 4 * 256; @@ -193,7 +191,11 @@ static char *pack_revindex_filename(struct packed_git *p) } #define RIDX_HEADER_SIZE (12) -#define RIDX_MIN_SIZE (RIDX_HEADER_SIZE + (2 * the_hash_algo->rawsz)) + +static size_t ridx_min_size(const struct git_hash_algo *algo) +{ + return RIDX_HEADER_SIZE + (2 * algo->rawsz); +} struct revindex_header { uint32_t signature; @@ -201,7 +203,8 @@ struct revindex_header { uint32_t hash_id; }; -static int load_revindex_from_disk(char *revindex_name, +static int load_revindex_from_disk(const struct git_hash_algo *algo, + char *revindex_name, uint32_t num_objects, const uint32_t **data_p, size_t *len_p) { @@ -228,12 +231,12 @@ static int load_revindex_from_disk(char *revindex_name, revindex_size = xsize_t(st.st_size); - if (revindex_size < RIDX_MIN_SIZE) { + if (revindex_size < ridx_min_size(algo)) { ret = error(_("reverse-index file %s is too small"), revindex_name); goto cleanup; } - if (revindex_size - RIDX_MIN_SIZE != st_mult(sizeof(uint32_t), num_objects)) { + if (revindex_size - ridx_min_size(algo) != st_mult(sizeof(uint32_t), num_objects)) { ret = error(_("reverse-index file %s is corrupt"), revindex_name); goto cleanup; } @@ -279,7 +282,8 @@ int load_pack_revindex_from_disk(struct packed_git *p) revindex_name = pack_revindex_filename(p); - ret = load_revindex_from_disk(revindex_name, + ret = load_revindex_from_disk(p->repo->hash_algo, + revindex_name, p->num_objects, &p->revindex_map, &p->revindex_size); @@ -322,7 +326,8 @@ int verify_pack_revindex(struct packed_git *p) if (!p->revindex_map || !p->revindex_data) return res; - if (!hashfile_checksum_valid((const unsigned char *)p->revindex_map, p->revindex_size)) { + if (!hashfile_checksum_valid(p->repo->hash_algo, + (const unsigned char *)p->revindex_map, p->revindex_size)) { error(_("invalid checksum")); res = -1; } @@ -374,19 +379,26 @@ int load_midx_revindex(struct multi_pack_index *m) * not want to accidentally call munmap() in the middle of the * MIDX. */ - trace2_data_string("load_midx_revindex", the_repository, + trace2_data_string("load_midx_revindex", m->repo, "source", "midx"); m->revindex_data = (const uint32_t *)m->chunk_revindex; return 0; } - trace2_data_string("load_midx_revindex", the_repository, + trace2_data_string("load_midx_revindex", m->repo, "source", "rev"); - get_midx_filename_ext(m->repo->hash_algo, &revindex_name, m->object_dir, - get_midx_checksum(m), MIDX_EXT_REV); + if (m->has_chain) + get_split_midx_filename_ext(m->repo->hash_algo, &revindex_name, + m->object_dir, get_midx_checksum(m), + MIDX_EXT_REV); + else + get_midx_filename_ext(m->repo->hash_algo, &revindex_name, + m->object_dir, get_midx_checksum(m), + MIDX_EXT_REV); - ret = load_revindex_from_disk(revindex_name.buf, + ret = load_revindex_from_disk(m->repo->hash_algo, + revindex_name.buf, m->num_objects, &m->revindex_map, &m->revindex_len); @@ -418,7 +430,7 @@ int offset_to_pack_pos(struct packed_git *p, off_t ofs, uint32_t *pos) { unsigned lo, hi; - if (load_pack_revindex(the_repository, p) < 0) + if (load_pack_revindex(p->repo, p) < 0) return -1; lo = 0; @@ -464,18 +476,22 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos) if (p->revindex) return p->revindex[pos].offset; else if (pos == p->num_objects) - return p->pack_size - the_hash_algo->rawsz; + return p->pack_size - p->repo->hash_algo->rawsz; else return nth_packed_object_offset(p, pack_pos_to_index(p, pos)); } uint32_t pack_pos_to_midx(struct multi_pack_index *m, uint32_t pos) { + while (m && pos < m->num_objects_in_base) + m = m->base_midx; + if (!m) + BUG("NULL multi-pack-index for object position: %"PRIu32, pos); if (!m->revindex_data) BUG("pack_pos_to_midx: reverse index not yet loaded"); - if (m->num_objects <= pos) + if (m->num_objects + m->num_objects_in_base <= pos) BUG("pack_pos_to_midx: out-of-bounds object at %"PRIu32, pos); - return get_be32(m->revindex_data + pos); + return get_be32(m->revindex_data + pos - m->num_objects_in_base); } struct midx_pack_key { @@ -491,7 +507,8 @@ static int midx_pack_order_cmp(const void *va, const void *vb) const struct midx_pack_key *key = va; struct multi_pack_index *midx = key->midx; - uint32_t versus = pack_pos_to_midx(midx, (uint32_t*)vb - (const uint32_t *)midx->revindex_data); + size_t pos = (uint32_t *)vb - (const uint32_t *)midx->revindex_data; + uint32_t versus = pack_pos_to_midx(midx, pos + midx->num_objects_in_base); uint32_t versus_pack = nth_midxed_pack_int_id(midx, versus); off_t versus_offset; @@ -529,9 +546,9 @@ static int midx_key_to_pack_pos(struct multi_pack_index *m, { uint32_t *found; - if (key->pack >= m->num_packs) + if (key->pack >= m->num_packs + m->num_packs_in_base) BUG("MIDX pack lookup out of bounds (%"PRIu32" >= %"PRIu32")", - key->pack, m->num_packs); + key->pack, m->num_packs + m->num_packs_in_base); /* * The preferred pack sorts first, so determine its identifier by * looking at the first object in pseudo-pack order. @@ -551,7 +568,8 @@ static int midx_key_to_pack_pos(struct multi_pack_index *m, if (!found) return -1; - *pos = found - m->revindex_data; + *pos = (found - m->revindex_data) + m->num_objects_in_base; + return 0; } @@ -559,9 +577,13 @@ int midx_to_pack_pos(struct multi_pack_index *m, uint32_t at, uint32_t *pos) { struct midx_pack_key key; + while (m && at < m->num_objects_in_base) + m = m->base_midx; + if (!m) + BUG("NULL multi-pack-index for object position: %"PRIu32, at); if (!m->revindex_data) BUG("midx_to_pack_pos: reverse index not yet loaded"); - if (m->num_objects <= at) + if (m->num_objects + m->num_objects_in_base <= at) BUG("midx_to_pack_pos: out-of-bounds object at %"PRIu32, at); key.pack = nth_midxed_pack_int_id(m, at); diff --git a/pack-write.c b/pack-write.c index 823e40b42f..6b06315f80 100644 --- a/pack-write.c +++ b/pack-write.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "environment.h" #include "gettext.h" @@ -56,7 +54,7 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts) * The *sha1 contains the pack content SHA1 hash. * The objects array passed in will be sorted by SHA1 on exit. */ -const char *write_idx_file(const struct git_hash_algo *hash_algo, +const char *write_idx_file(struct repository *repo, const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *opts, const unsigned char *sha1) @@ -82,7 +80,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo, if (opts->flags & WRITE_IDX_VERIFY) { assert(index_name); - f = hashfd_check(index_name); + f = hashfd_check(repo->hash_algo, index_name); } else { if (!index_name) { struct strbuf tmp_file = STRBUF_INIT; @@ -92,7 +90,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo, unlink(index_name); fd = xopen(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600); } - f = hashfd(fd, index_name); + f = hashfd(repo->hash_algo, fd, index_name); } /* if last object's offset is >= 2^31 we should use index V2 */ @@ -131,7 +129,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo, struct pack_idx_entry *obj = *list++; if (index_version < 2) hashwrite_be32(f, obj->offset); - hashwrite(f, obj->oid.hash, hash_algo->rawsz); + hashwrite(f, obj->oid.hash, repo->hash_algo->rawsz); if ((opts->flags & WRITE_IDX_STRICT) && (i && oideq(&list[-2]->oid, &obj->oid))) die("The same object %s appears twice in the pack", @@ -173,7 +171,7 @@ const char *write_idx_file(const struct git_hash_algo *hash_algo, } } - hashwrite(f, sha1, hash_algo->rawsz); + hashwrite(f, sha1, repo->hash_algo->rawsz); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_CLOSE | ((opts->flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC)); @@ -217,7 +215,7 @@ static void write_rev_trailer(const struct git_hash_algo *hash_algo, hashwrite(f, hash, hash_algo->rawsz); } -char *write_rev_file(const struct git_hash_algo *hash_algo, +char *write_rev_file(struct repository *repo, const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, @@ -236,7 +234,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo, pack_order[i] = i; QSORT_S(pack_order, nr_objects, pack_order_cmp, objects); - ret = write_rev_file_order(hash_algo, rev_name, pack_order, nr_objects, + ret = write_rev_file_order(repo, rev_name, pack_order, nr_objects, hash, flags); free(pack_order); @@ -244,7 +242,7 @@ char *write_rev_file(const struct git_hash_algo *hash_algo, return ret; } -char *write_rev_file_order(const struct git_hash_algo *hash_algo, +char *write_rev_file_order(struct repository *repo, const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, @@ -268,7 +266,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo, fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600); path = xstrdup(rev_name); } - f = hashfd(fd, path); + f = hashfd(repo->hash_algo, fd, path); } else if (flags & WRITE_REV_VERIFY) { struct stat statbuf; if (stat(rev_name, &statbuf)) { @@ -278,18 +276,18 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo, } else die_errno(_("could not stat: %s"), rev_name); } - f = hashfd_check(rev_name); + f = hashfd_check(repo->hash_algo, rev_name); path = xstrdup(rev_name); } else { return NULL; } - write_rev_header(hash_algo, f); + write_rev_header(repo->hash_algo, f); write_rev_index_positions(f, pack_order, nr_objects); - write_rev_trailer(hash_algo, f, hash); + write_rev_trailer(repo->hash_algo, f, hash); - if (adjust_shared_perm(the_repository, path) < 0) + if (adjust_shared_perm(repo, path) < 0) die(_("failed to make %s readable"), path); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -330,7 +328,7 @@ static void write_mtimes_trailer(const struct git_hash_algo *hash_algo, hashwrite(f, hash, hash_algo->rawsz); } -static char *write_mtimes_file(const struct git_hash_algo *hash_algo, +static char *write_mtimes_file(struct repository *repo, struct packing_data *to_pack, struct pack_idx_entry **objects, uint32_t nr_objects, @@ -346,13 +344,13 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo, fd = odb_mkstemp(&tmp_file, "pack/tmp_mtimes_XXXXXX"); mtimes_name = strbuf_detach(&tmp_file, NULL); - f = hashfd(fd, mtimes_name); + f = hashfd(repo->hash_algo, fd, mtimes_name); - write_mtimes_header(hash_algo, f); + write_mtimes_header(repo->hash_algo, f); write_mtimes_objects(f, to_pack, objects, nr_objects); - write_mtimes_trailer(hash_algo, f, hash); + write_mtimes_trailer(repo->hash_algo, f, hash); - if (adjust_shared_perm(the_repository, mtimes_name) < 0) + if (adjust_shared_perm(repo, mtimes_name) < 0) die(_("failed to make %s readable"), mtimes_name); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -527,14 +525,15 @@ int encode_in_pack_object_header(unsigned char *hdr, int hdr_len, return n; } -struct hashfile *create_tmp_packfile(char **pack_tmp_name) +struct hashfile *create_tmp_packfile(struct repository *repo, + char **pack_tmp_name) { struct strbuf tmpname = STRBUF_INIT; int fd; fd = odb_mkstemp(&tmpname, "pack/tmp_pack_XXXXXX"); *pack_tmp_name = strbuf_detach(&tmpname, NULL); - return hashfd(fd, *pack_tmp_name); + return hashfd(repo->hash_algo, fd, *pack_tmp_name); } static void rename_tmp_packfile(struct strbuf *name_prefix, const char *source, @@ -555,7 +554,7 @@ void rename_tmp_packfile_idx(struct strbuf *name_buffer, rename_tmp_packfile(name_buffer, *idx_tmp_name, "idx"); } -void stage_tmp_packfiles(const struct git_hash_algo *hash_algo, +void stage_tmp_packfiles(struct repository *repo, struct strbuf *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, @@ -568,19 +567,19 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo, char *rev_tmp_name = NULL; char *mtimes_tmp_name = NULL; - if (adjust_shared_perm(the_repository, pack_tmp_name)) + if (adjust_shared_perm(repo, pack_tmp_name)) die_errno("unable to make temporary pack file readable"); - *idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list, + *idx_tmp_name = (char *)write_idx_file(repo, NULL, written_list, nr_written, pack_idx_opts, hash); - if (adjust_shared_perm(the_repository, *idx_tmp_name)) + if (adjust_shared_perm(repo, *idx_tmp_name)) die_errno("unable to make temporary index file readable"); - rev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written, + rev_tmp_name = write_rev_file(repo, NULL, written_list, nr_written, hash, pack_idx_opts->flags); if (pack_idx_opts->flags & WRITE_MTIMES) { - mtimes_tmp_name = write_mtimes_file(hash_algo, to_pack, + mtimes_tmp_name = write_mtimes_file(repo, to_pack, written_list, nr_written, hash); } @@ -87,7 +87,7 @@ struct progress; /* Note, the data argument could be NULL if object type is blob */ typedef int (*verify_fn)(const struct object_id *, enum object_type, unsigned long, void*, int*); -const char *write_idx_file(const struct git_hash_algo *hash_algo, +const char *write_idx_file(struct repository *repo, const char *index_name, struct pack_idx_entry **objects, int nr_objects, @@ -106,13 +106,13 @@ struct ref; void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought); -char *write_rev_file(const struct git_hash_algo *hash_algo, +char *write_rev_file(struct repository *repo, const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags); -char *write_rev_file_order(const struct git_hash_algo *hash_algo, +char *write_rev_file_order(struct repository *repo, const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, @@ -134,8 +134,9 @@ int read_pack_header(int fd, struct pack_header *); struct packing_data; -struct hashfile *create_tmp_packfile(char **pack_tmp_name); -void stage_tmp_packfiles(const struct git_hash_algo *hash_algo, +struct hashfile *create_tmp_packfile(struct repository *repo, + char **pack_tmp_name); +void stage_tmp_packfiles(struct repository *repo, struct strbuf *name_buffer, const char *pack_tmp_name, struct pack_idx_entry **written_list, diff --git a/packfile.c b/packfile.c index 2d80d80cb3..70c7208f02 100644 --- a/packfile.c +++ b/packfile.c @@ -19,11 +19,12 @@ #include "tree-walk.h" #include "tree.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "midx.h" #include "commit-graph.h" #include "pack-revindex.h" #include "promisor-remote.h" +#include "pack-mtimes.h" char *odb_pack_name(struct repository *r, struct strbuf *buf, const unsigned char *hash, const char *ext) @@ -736,6 +737,17 @@ struct packed_git *add_packed_git(struct repository *r, const char *path, p = alloc_packed_git(r, alloc); memcpy(p->pack_name, path, path_len); + /* + * Note that we have to check auxiliary data structures before we check + * for the ".pack" file to exist to avoid races with a packfile that is + * in the process of being deleted. The ".pack" file is unlinked before + * its auxiliary data structures, so we know that we either get a + * consistent snapshot of all data structures or that we'll fail to + * stat(3p) the packfile itself and thus return `NULL`. + * + * As such, we cannot bail out before the access(3p) calls in case the + * packfile doesn't exist without doing two stat(3p) calls for it. + */ xsnprintf(p->pack_name + path_len, alloc - path_len, ".keep"); if (!access(p->pack_name, F_OK)) p->pack_keep = 1; @@ -1597,17 +1609,12 @@ int packed_object_info(struct repository *r, struct packed_git *p, *oi->disk_sizep = pack_pos_to_offset(p, pos + 1) - obj_offset; } - if (oi->typep || oi->type_name) { + if (oi->typep) { enum object_type ptot; ptot = packed_to_object_type(r, p, obj_offset, type, &w_curs, curpos); if (oi->typep) *oi->typep = ptot; - if (oi->type_name) { - const char *tn = type_name(ptot); - if (tn) - strbuf_addstr(oi->type_name, tn); - } if (ptot < 0) { type = OBJ_BAD; goto out; @@ -2107,7 +2114,7 @@ static void maybe_invalidate_kept_pack_cache(struct repository *r, r->objects->kept_pack_cache.flags = 0; } -static struct packed_git **kept_pack_cache(struct repository *r, unsigned flags) +struct packed_git **kept_pack_cache(struct repository *r, unsigned flags) { maybe_invalidate_kept_pack_cache(r, flags); diff --git a/packfile.h b/packfile.h index 00ada7a938..3a3c77cf05 100644 --- a/packfile.h +++ b/packfile.h @@ -1,13 +1,71 @@ #ifndef PACKFILE_H #define PACKFILE_H +#include "list.h" #include "object.h" +#include "object-store.h" #include "oidset.h" /* in object-store.h */ -struct packed_git; struct object_info; +struct packed_git { + struct hashmap_entry packmap_ent; + struct packed_git *next; + struct list_head mru; + struct pack_window *windows; + off_t pack_size; + const void *index_data; + size_t index_size; + uint32_t num_objects; + size_t crc_offset; + struct oidset bad_objects; + int index_version; + time_t mtime; + int pack_fd; + int index; /* for builtin/pack-objects.c */ + unsigned pack_local:1, + pack_keep:1, + pack_keep_in_core:1, + freshened:1, + do_not_close:1, + pack_promisor:1, + multi_pack_index:1, + is_cruft:1; + unsigned char hash[GIT_MAX_RAWSZ]; + struct revindex_entry *revindex; + const uint32_t *revindex_data; + const uint32_t *revindex_map; + size_t revindex_size; + /* + * mtimes_map points at the beginning of the memory mapped region of + * this pack's corresponding .mtimes file, and mtimes_size is the size + * of that .mtimes file + */ + const uint32_t *mtimes_map; + size_t mtimes_size; + + /* repo denotes the repository this packfile belongs to */ + struct repository *repo; + + /* something like ".git/objects/pack/xxxxx.pack" */ + char pack_name[FLEX_ARRAY]; /* more */ +}; + +static inline int pack_map_entry_cmp(const void *cmp_data UNUSED, + const struct hashmap_entry *entry, + const struct hashmap_entry *entry2, + const void *keydata) +{ + const char *key = keydata; + const struct packed_git *pg1, *pg2; + + pg1 = container_of(entry, const struct packed_git, packmap_ent); + pg2 = container_of(entry2, const struct packed_git, packmap_ent); + + return strcmp(pg1->pack_name, key ? key : pg2->pack_name); +} + struct pack_window { struct pack_window *next; unsigned char *base; @@ -60,6 +118,24 @@ void for_each_file_in_pack_dir(const char *objdir, each_file_in_pack_dir_fn fn, void *data); +/* + * Iterate over all accessible packed objects without respect to reachability. + * By default, this includes both local and alternate packs. + * + * Note that some objects may appear twice if they are found in multiple packs. + * Each pack is visited in an unspecified order. By default, objects within a + * pack are visited in pack-idx order (i.e., sorted by oid). + */ +typedef int each_packed_object_fn(const struct object_id *oid, + struct packed_git *pack, + uint32_t pos, + void *data); +int for_each_object_in_pack(struct packed_git *p, + each_packed_object_fn, void *data, + enum for_each_object_flags flags); +int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, + void *data, enum for_each_object_flags flags); + /* A hook to report invalid files in pack directory */ #define PACKDIR_FILE_PACK 1 #define PACKDIR_FILE_IDX 2 @@ -197,6 +273,8 @@ int has_object_pack(struct repository *r, const struct object_id *oid); int has_object_kept_pack(struct repository *r, const struct object_id *oid, unsigned flags); +struct packed_git **kept_pack_cache(struct repository *r, unsigned flags); + /* * Return 1 if an object in a promisor packfile is or refers to the given * object, 0 otherwise. diff --git a/parallel-checkout.c b/parallel-checkout.c index 7cc6b30528..57c2dcaa8f 100644 --- a/parallel-checkout.c +++ b/parallel-checkout.c @@ -277,7 +277,7 @@ static int write_pc_item_to_fd(struct parallel_checkout_item *pc_item, int fd, ssize_t wrote; /* Sanity check */ - assert(is_eligible_for_parallel_checkout(pc_item->ce, &pc_item->ca)); + ASSERT(is_eligible_for_parallel_checkout(pc_item->ce, &pc_item->ca)); filter = get_stream_filter_ca(&pc_item->ca, &pc_item->ce->oid); if (filter) { diff --git a/parse-options-cb.c b/parse-options-cb.c index 166d35e0eb..50c8afe412 100644 --- a/parse-options-cb.c +++ b/parse-options-cb.c @@ -145,7 +145,7 @@ int parse_opt_object_id(const struct option *opt, const char *arg, int unset) struct object_id *target = opt->value; if (unset) { - oidcpy(target, null_oid()); + oidcpy(target, null_oid(the_hash_algo)); return 0; } if (!arg) diff --git a/parse-options.c b/parse-options.c index 35fbb3b0d6..a9a39ecaef 100644 --- a/parse-options.c +++ b/parse-options.c @@ -73,7 +73,7 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p, enum opt_parsed flags, const char **argp) { - const char *s, *arg; + const char *arg; const int unset = flags & OPT_UNSET; int err; @@ -172,41 +172,93 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p, return (*opt->ll_callback)(p, opt, p_arg, p_unset); } case OPTION_INTEGER: + { + intmax_t upper_bound = INTMAX_MAX >> (bitsizeof(intmax_t) - CHAR_BIT * opt->precision); + intmax_t lower_bound = -upper_bound - 1; + intmax_t value; + if (unset) { - *(int *)opt->value = 0; - return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { - *(int *)opt->value = opt->defval; - return 0; - } - if (get_arg(p, opt, flags, &arg)) + value = 0; + } else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + value = opt->defval; + } else if (get_arg(p, opt, flags, &arg)) { return -1; - if (!*arg) + } else if (!*arg) { return error(_("%s expects a numerical value"), optname(opt, flags)); - *(int *)opt->value = strtol(arg, (char **)&s, 10); - if (*s) - return error(_("%s expects a numerical value"), + } else if (!git_parse_signed(arg, &value, upper_bound)) { + if (errno == ERANGE) + return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"), + arg, optname(opt, flags), lower_bound, upper_bound); + + return error(_("%s expects an integer value with an optional k/m/g suffix"), optname(opt, flags)); - return 0; + } - case OPTION_MAGNITUDE: - if (unset) { - *(unsigned long *)opt->value = 0; + if (value < lower_bound) + return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"), + arg, optname(opt, flags), (intmax_t)lower_bound, (intmax_t)upper_bound); + + switch (opt->precision) { + case 1: + *(int8_t *)opt->value = value; return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { - *(unsigned long *)opt->value = opt->defval; + case 2: + *(int16_t *)opt->value = value; + return 0; + case 4: + *(int32_t *)opt->value = value; return 0; + case 8: + *(int64_t *)opt->value = value; + return 0; + default: + BUG("invalid precision for option %s", + optname(opt, flags)); } - if (get_arg(p, opt, flags, &arg)) + } + case OPTION_UNSIGNED: + { + uintmax_t upper_bound = UINTMAX_MAX >> (bitsizeof(uintmax_t) - CHAR_BIT * opt->precision); + uintmax_t value; + + if (unset) { + value = 0; + } else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + value = opt->defval; + } else if (get_arg(p, opt, flags, &arg)) { return -1; - if (!git_parse_ulong(arg, opt->value)) + } else if (!*arg) { + return error(_("%s expects a numerical value"), + optname(opt, flags)); + } else if (!git_parse_unsigned(arg, &value, upper_bound)) { + if (errno == ERANGE) + return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"), + arg, optname(opt, flags), (uintmax_t) 0, upper_bound); + return error(_("%s expects a non-negative integer value" " with an optional k/m/g suffix"), optname(opt, flags)); - return 0; + } + + switch (opt->precision) { + case 1: + *(uint8_t *)opt->value = value; + return 0; + case 2: + *(uint16_t *)opt->value = value; + return 0; + case 4: + *(uint32_t *)opt->value = value; + return 0; + case 8: + *(uint64_t *)opt->value = value; + return 0; + default: + BUG("invalid precision for option %s", + optname(opt, flags)); + } + } default: BUG("opt->type %d should not happen", opt->type); @@ -656,7 +708,7 @@ static void show_negated_gitcomp(const struct option *opts, int show_all, case OPTION_STRING: case OPTION_FILENAME: case OPTION_INTEGER: - case OPTION_MAGNITUDE: + case OPTION_UNSIGNED: case OPTION_CALLBACK: case OPTION_BIT: case OPTION_NEGBIT: @@ -708,7 +760,7 @@ static int show_gitcomp(const struct option *opts, int show_all) case OPTION_STRING: case OPTION_FILENAME: case OPTION_INTEGER: - case OPTION_MAGNITUDE: + case OPTION_UNSIGNED: case OPTION_CALLBACK: if (opts->flags & PARSE_OPT_NOARG) break; diff --git a/parse-options.h b/parse-options.h index 997ffbee80..91c3e3c29b 100644 --- a/parse-options.h +++ b/parse-options.h @@ -25,7 +25,7 @@ enum parse_opt_type { /* options with arguments (usually) */ OPTION_STRING, OPTION_INTEGER, - OPTION_MAGNITUDE, + OPTION_UNSIGNED, OPTION_CALLBACK, OPTION_LOWLEVEL_CALLBACK, OPTION_FILENAME @@ -92,6 +92,10 @@ typedef int parse_opt_subcommand_fn(int argc, const char **argv, * `value`:: * stores pointers to the values to be filled. * + * `precision`:: + * precision of the integer pointed to by `value` in number of bytes. Should + * typically be its `sizeof()`. + * * `argh`:: * token to explain the kind of argument this option wants. Does not * begin in capital letter, and does not end with a full stop. @@ -151,6 +155,7 @@ struct option { int short_name; const char *long_name; void *value; + size_t precision; const char *argh; const char *help; @@ -213,7 +218,8 @@ struct option { .type = OPTION_INTEGER, \ .short_name = (s), \ .long_name = (l), \ - .value = (v), \ + .value = (v) + BARF_UNLESS_SIGNED(*(v)), \ + .precision = sizeof(*v), \ .argh = N_("n"), \ .help = (h), \ .flags = (f), \ @@ -270,11 +276,12 @@ struct option { #define OPT_CMDMODE(s, l, v, h, i) OPT_CMDMODE_F(s, l, v, h, i, 0) #define OPT_INTEGER(s, l, v, h) OPT_INTEGER_F(s, l, v, h, 0) -#define OPT_MAGNITUDE(s, l, v, h) { \ - .type = OPTION_MAGNITUDE, \ +#define OPT_UNSIGNED(s, l, v, h) { \ + .type = OPTION_UNSIGNED, \ .short_name = (s), \ .long_name = (l), \ - .value = (v), \ + .value = (v) + BARF_UNLESS_UNSIGNED(*(v)), \ + .precision = sizeof(*v), \ .argh = N_("n"), \ .help = (h), \ .flags = PARSE_OPT_NONEG, \ @@ -38,7 +38,7 @@ int git_parse_signed(const char *value, intmax_t *ret, intmax_t max) errno = EINVAL; return 0; } - if ((val < 0 && -max / factor > val) || + if ((val < 0 && (-max - 1) / factor > val) || (val > 0 && max / factor < val)) { errno = ERANGE; return 0; @@ -51,7 +51,7 @@ int git_parse_signed(const char *value, intmax_t *ret, intmax_t max) return 0; } -static int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max) +int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max) { if (value && *value) { char *end; @@ -2,6 +2,7 @@ #define PARSE_H int git_parse_signed(const char *value, intmax_t *ret, intmax_t max); +int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max); int git_parse_ssize_t(const char *, ssize_t *); int git_parse_ulong(const char *, unsigned long *); int git_parse_int(const char *value, int *ret); diff --git a/path-walk.c b/path-walk.c index 341bdd2ba4..2d4ddbadd5 100644 --- a/path-walk.c +++ b/path-walk.c @@ -503,7 +503,11 @@ int walk_objects_by_path(struct path_walk_info *info) if (prepare_revision_walk(info->revs)) die(_("failed to setup revision walk")); - /* Walk trees to mark them as UNINTERESTING. */ + /* + * Walk trees to mark them as UNINTERESTING. + * This is particularly important when 'edge_aggressive' is set. + */ + info->revs->edge_hint_aggressive = info->edge_aggressive; edge_repo = info->revs->repo; edge_tree_list = root_tree_list; mark_edges_uninteresting(info->revs, show_edge, diff --git a/path-walk.h b/path-walk.h index 473ee9d361..5ef5a8440e 100644 --- a/path-walk.h +++ b/path-walk.h @@ -51,6 +51,13 @@ struct path_walk_info { int prune_all_uninteresting; /** + * When 'edge_aggressive' is set, then the revision walk will use + * the '--object-edge-aggressive' option to mark even more objects + * as uninteresting. + */ + int edge_aggressive; + + /** * Specify a sparse-checkout definition to match our paths to. Do not * walk outside of this sparse definition. If the patterns are in * cone mode, then the search may prune directories that are outside @@ -15,7 +15,7 @@ #include "submodule-config.h" #include "path.h" #include "packfile.h" -#include "object-store-ll.h" +#include "object-store.h" #include "lockfile.h" #include "exec-cmd.h" @@ -902,6 +902,129 @@ void safe_create_dir(struct repository *repo, const char *dir, int share) die(_("Could not make %s writable by group"), dir); } +int safe_create_dir_in_gitdir(struct repository *repo, const char *path) +{ + if (mkdir(path, 0777)) { + int saved_errno = errno; + struct stat st; + struct strbuf sb = STRBUF_INIT; + + if (errno != EEXIST) + return -1; + /* + * Are we looking at a path in a symlinked worktree + * whose original repository does not yet have it? + * e.g. .git/rr-cache pointing at its original + * repository in which the user hasn't performed any + * conflict resolution yet? + */ + if (lstat(path, &st) || !S_ISLNK(st.st_mode) || + strbuf_readlink(&sb, path, st.st_size) || + !is_absolute_path(sb.buf) || + mkdir(sb.buf, 0777)) { + strbuf_release(&sb); + errno = saved_errno; + return -1; + } + strbuf_release(&sb); + } + return adjust_shared_perm(repo, path); +} + +static enum scld_error safe_create_leading_directories_1(struct repository *repo, + char *path) +{ + char *next_component = path + offset_1st_component(path); + enum scld_error ret = SCLD_OK; + + while (ret == SCLD_OK && next_component) { + struct stat st; + char *slash = next_component, slash_character; + + while (*slash && !is_dir_sep(*slash)) + slash++; + + if (!*slash) + break; + + next_component = slash + 1; + while (is_dir_sep(*next_component)) + next_component++; + if (!*next_component) + break; + + slash_character = *slash; + *slash = '\0'; + if (!stat(path, &st)) { + /* path exists */ + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + ret = SCLD_EXISTS; + } + } else if (mkdir(path, 0777)) { + if (errno == EEXIST && + !stat(path, &st) && S_ISDIR(st.st_mode)) + ; /* somebody created it since we checked */ + else if (errno == ENOENT) + /* + * Either mkdir() failed because + * somebody just pruned the containing + * directory, or stat() failed because + * the file that was in our way was + * just removed. Either way, inform + * the caller that it might be worth + * trying again: + */ + ret = SCLD_VANISHED; + else + ret = SCLD_FAILED; + } else if (repo && adjust_shared_perm(repo, path)) { + ret = SCLD_PERMS; + } + *slash = slash_character; + } + return ret; +} + +enum scld_error safe_create_leading_directories(struct repository *repo, + char *path) +{ + return safe_create_leading_directories_1(repo, path); +} + +enum scld_error safe_create_leading_directories_no_share(char *path) +{ + return safe_create_leading_directories_1(NULL, path); +} + +enum scld_error safe_create_leading_directories_const(struct repository *repo, + const char *path) +{ + int save_errno; + /* path points to cache entries, so xstrdup before messing with it */ + char *buf = xstrdup(path); + enum scld_error result = safe_create_leading_directories(repo, buf); + + save_errno = errno; + free(buf); + errno = save_errno; + return result; +} + +int safe_create_file_with_leading_directories(struct repository *repo, + const char *path) +{ + int fd; + + fd = open(path, O_RDWR|O_CREAT|O_EXCL, 0600); + if (0 <= fd) + return fd; + + /* slow path */ + safe_create_leading_directories_const(repo, path); + return open(path, O_RDWR|O_CREAT|O_EXCL, 0600); +} + static int have_same_root(const char *path1, const char *path2) { int is_abs1, is_abs2; @@ -221,6 +221,58 @@ char *xdg_cache_home(const char *filename); */ void safe_create_dir(struct repository *repo, const char *dir, int share); +/* + * Similar to `safe_create_dir()`, but with two differences: + * + * - It knows to resolve gitlink files for symlinked worktrees. + * + * - It always adjusts shared permissions. + * + * Returns a negative erorr code on error, 0 on success. + */ +int safe_create_dir_in_gitdir(struct repository *repo, const char *path); + +/* + * Create the directory containing the named path, using care to be + * somewhat safe against races. Return one of the scld_error values to + * indicate success/failure. On error, set errno to describe the + * problem. + * + * SCLD_VANISHED indicates that one of the ancestor directories of the + * path existed at one point during the function call and then + * suddenly vanished, probably because another process pruned the + * directory while we were working. To be robust against this kind of + * race, callers might want to try invoking the function again when it + * returns SCLD_VANISHED. + * + * safe_create_leading_directories() temporarily changes path while it + * is working but restores it before returning. + * safe_create_leading_directories_const() doesn't modify path, even + * temporarily. Both these variants adjust the permissions of the + * created directories to honor core.sharedRepository, so they are best + * suited for files inside the git dir. For working tree files, use + * safe_create_leading_directories_no_share() instead, as it ignores + * the core.sharedRepository setting. + */ +enum scld_error { + SCLD_OK = 0, + SCLD_FAILED = -1, + SCLD_PERMS = -2, + SCLD_EXISTS = -3, + SCLD_VANISHED = -4 +}; +enum scld_error safe_create_leading_directories(struct repository *repo, char *path); +enum scld_error safe_create_leading_directories_const(struct repository *repo, + const char *path); +enum scld_error safe_create_leading_directories_no_share(char *path); + +/* + * Create a file, potentially creating its leading directories in case they + * don't exist. Returns the return value of the open(3p) call. + */ +int safe_create_file_with_leading_directories(struct repository *repo, + const char *path); + # ifdef USE_THE_REPOSITORY_VARIABLE # include "strbuf.h" # include "repository.h" diff --git a/pathspec.c b/pathspec.c index 89663645e1..a3ddd701c7 100644 --- a/pathspec.c +++ b/pathspec.c @@ -1,5 +1,4 @@ #define USE_THE_REPOSITORY_VARIABLE -#define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" #include "abspath.h" @@ -35,7 +34,7 @@ void add_pathspec_matches_against_index(const struct pathspec *pathspec, char *seen, enum ps_skip_worktree_action sw_action) { - int num_unmatched = 0, i; + int num_unmatched = 0; /* * Since we are walking the index as if we were walking the directory, @@ -43,12 +42,12 @@ void add_pathspec_matches_against_index(const struct pathspec *pathspec, * mistakenly think that the user gave a pathspec that did not match * anything. */ - for (i = 0; i < pathspec->nr; i++) + for (int i = 0; i < pathspec->nr; i++) if (!seen[i]) num_unmatched++; if (!num_unmatched) return; - for (i = 0; i < istate->cache_nr; i++) { + for (unsigned int i = 0; i < istate->cache_nr; i++) { const struct cache_entry *ce = istate->cache[i]; if (sw_action == PS_IGNORE_SKIP_WORKTREE && (ce_skip_worktree(ce) || !path_in_sparse_checkout(ce->name, istate))) @@ -78,7 +77,7 @@ char *find_pathspecs_matching_skip_worktree(const struct pathspec *pathspec) { struct index_state *istate = the_repository->index; char *seen = xcalloc(pathspec->nr, 1); - int i; + unsigned int i; for (i = 0; i < istate->cache_nr; i++) { struct cache_entry *ce = istate->cache[i]; @@ -130,7 +129,7 @@ static void prefix_magic(struct strbuf *sb, int prefixlen, if (element[1] != '(') { /* Process an element in shorthand form (e.g. ":!/<match>") */ strbuf_addstr(sb, ":("); - for (int i = 0; i < ARRAY_SIZE(pathspec_magic); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(pathspec_magic); i++) { if ((magic & pathspec_magic[i].bit) && pathspec_magic[i].mnemonic) { if (sb->buf[sb->len - 1] != '(') @@ -341,7 +340,7 @@ static const char *parse_long_magic(unsigned *magic, int *prefix_len, for (pos = elem + 2; *pos && *pos != ')'; pos = nextat) { size_t len = strcspn_escaped(pos, ",)"); - int i; + unsigned int i; if (pos[len] == ',') nextat = pos + len + 1; /* handle ',' */ @@ -354,7 +353,7 @@ static const char *parse_long_magic(unsigned *magic, int *prefix_len, if (starts_with(pos, "prefix:")) { char *endptr; *prefix_len = strtol(pos + 7, &endptr, 10); - if (endptr - pos != len) + if ((size_t)(endptr - pos) != len) die(_("invalid parameter for pathspec magic 'prefix'")); continue; } @@ -400,7 +399,7 @@ static const char *parse_short_magic(unsigned *magic, const char *elem) for (pos = elem + 1; *pos && *pos != ':'; pos++) { char ch = *pos; - int i; + unsigned int i; /* Special case alias for '!' */ if (ch == '^') { @@ -493,7 +492,7 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags, if (!match) { const char *hint_path; - if (!have_git_dir()) + if ((flags & PATHSPEC_NO_REPOSITORY) || !have_git_dir()) die(_("'%s' is outside the directory tree"), copyfrom); hint_path = repo_get_work_tree(the_repository); @@ -564,7 +563,7 @@ static int pathspec_item_cmp(const void *a_, const void *b_) void pathspec_magic_names(unsigned magic, struct strbuf *out) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) { const struct pathspec_magic *m = pathspec_magic + i; if (!(magic & m->bit)) @@ -615,6 +614,10 @@ void parse_pathspec(struct pathspec *pathspec, (flags & PATHSPEC_PREFER_FULL)) BUG("PATHSPEC_PREFER_CWD and PATHSPEC_PREFER_FULL are incompatible"); + if ((flags & PATHSPEC_NO_REPOSITORY) && + (~magic_mask & (PATHSPEC_ATTR | PATHSPEC_FROMTOP))) + BUG("PATHSPEC_NO_REPOSITORY is incompatible with PATHSPEC_ATTR and PATHSPEC_FROMTOP"); + /* No arguments with prefix -> prefix pathspec */ if (!entry) { if (flags & PATHSPEC_PREFER_FULL) @@ -803,8 +806,8 @@ int match_pathspec_attrs(struct index_state *istate, int pathspec_needs_expanded_index(struct index_state *istate, const struct pathspec *pathspec) { - unsigned int i, pos; - int res = 0; + unsigned int pos; + int i, res = 0; char *skip_worktree_seen = NULL; /* @@ -845,7 +848,8 @@ int pathspec_needs_expanded_index(struct index_state *istate, * - not-in-cone/bar*: may need expanded index * - **.c: may need expanded index */ - if (strspn(item.original + item.nowildcard_len, "*") == item.len - item.nowildcard_len && + if (strspn(item.original + item.nowildcard_len, "*") == + (unsigned int)(item.len - item.nowildcard_len) && path_in_cone_mode_sparse_checkout(item.original, istate)) continue; @@ -860,8 +864,10 @@ int pathspec_needs_expanded_index(struct index_state *istate, * directory name and the sparse directory is the first * component of the pathspec, need to expand the index. */ - if (item.nowildcard_len > ce_namelen(ce) && - !strncmp(item.original, ce->name, ce_namelen(ce))) { + if ((unsigned int)item.nowildcard_len > + ce_namelen(ce) && + !strncmp(item.original, ce->name, + ce_namelen(ce))) { res = 1; break; } diff --git a/pathspec.h b/pathspec.h index de537cff3c..5e3a6f1fe7 100644 --- a/pathspec.h +++ b/pathspec.h @@ -76,6 +76,11 @@ struct pathspec { * allowed, then it will automatically set for every pathspec. */ #define PATHSPEC_LITERAL_PATH (1<<6) +/* + * For git diff --no-index, indicate that we are operating without + * a repository or index. + */ +#define PATHSPEC_NO_REPOSITORY (1<<7) /** * Given command line arguments and a prefix, convert the input to @@ -184,6 +189,12 @@ int match_pathspec(struct index_state *istate, const char *name, int namelen, int prefix, char *seen, int is_dir); +/* Set both DO_MATCH_DIRECTORY and DO_MATCH_LEADING_PATHSPEC if is_dir true */ +int match_leading_pathspec(struct index_state *istate, + const struct pathspec *ps, + const char *name, int namelen, + int prefix, char *seen, int is_dir); + /* * Determine whether a pathspec will match only entire index entries (non-sparse * files and/or entire sparse directories). If the pathspec has the potential to diff --git a/perl/FromCPAN/Mail/meson.build b/perl/FromCPAN/Mail/meson.build index b4ff2fc0b2..467507c5e6 100644 --- a/perl/FromCPAN/Mail/meson.build +++ b/perl/FromCPAN/Mail/meson.build @@ -3,6 +3,6 @@ test_dependencies += custom_target( output: 'Address.pm', command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5/FromCPAN/Mail', + install_dir: perllibdir / 'FromCPAN/Mail', depends: [git_version_file], ) diff --git a/perl/FromCPAN/meson.build b/perl/FromCPAN/meson.build index 1f9ea6ce8e..720c60283d 100644 --- a/perl/FromCPAN/meson.build +++ b/perl/FromCPAN/meson.build @@ -3,7 +3,7 @@ test_dependencies += custom_target( output: 'Error.pm', command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5/FromCPAN', + install_dir: perllibdir / 'FromCPAN', depends: [git_version_file], ) diff --git a/perl/Git/LoadCPAN/Mail/meson.build b/perl/Git/LoadCPAN/Mail/meson.build index 89cde56be8..05a5770560 100644 --- a/perl/Git/LoadCPAN/Mail/meson.build +++ b/perl/Git/LoadCPAN/Mail/meson.build @@ -3,6 +3,6 @@ test_dependencies += custom_target( output: 'Address.pm', command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5/Git/LoadCPAN/Mail', + install_dir: perllibdir / 'Git/LoadCPAN/Mail', depends: [git_version_file], ) diff --git a/perl/Git/LoadCPAN/meson.build b/perl/Git/LoadCPAN/meson.build index 1ee915c650..b975d49726 100644 --- a/perl/Git/LoadCPAN/meson.build +++ b/perl/Git/LoadCPAN/meson.build @@ -3,7 +3,7 @@ test_dependencies += custom_target( output: 'Error.pm', command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5/Git/LoadCPAN', + install_dir: perllibdir / 'Git/LoadCPAN', depends: [git_version_file], ) diff --git a/perl/Git/SVN/Memoize/meson.build b/perl/Git/SVN/Memoize/meson.build index 233ec670d7..d6209dc3bf 100644 --- a/perl/Git/SVN/Memoize/meson.build +++ b/perl/Git/SVN/Memoize/meson.build @@ -3,6 +3,6 @@ test_dependencies += custom_target( output: 'YAML.pm', command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5/Git/SVN', + install_dir: perllibdir / 'Git/SVN/Memoize', depends: [git_version_file], ) diff --git a/perl/Git/SVN/meson.build b/perl/Git/SVN/meson.build index 44abaf42b7..8858985fe8 100644 --- a/perl/Git/SVN/meson.build +++ b/perl/Git/SVN/meson.build @@ -13,7 +13,7 @@ foreach source : [ output: source, command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5/Git/SVN', + install_dir: perllibdir / 'Git/SVN', depends: [git_version_file], ) endforeach diff --git a/perl/Git/meson.build b/perl/Git/meson.build index b21fa5591e..a61b7b1f4a 100644 --- a/perl/Git/meson.build +++ b/perl/Git/meson.build @@ -10,7 +10,7 @@ foreach source : [ output: source, command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5/Git', + install_dir: perllibdir / 'Git', depends: [git_version_file], ) endforeach diff --git a/perl/meson.build b/perl/meson.build index 2d4ab1c4a9..3c66b007ea 100644 --- a/perl/meson.build +++ b/perl/meson.build @@ -3,7 +3,7 @@ test_dependencies += custom_target( output: 'Git.pm', command: generate_perl_command, install: true, - install_dir: get_option('datadir') / 'perl5', + install_dir: perllibdir, depends: [git_version_file], ) @@ -29,6 +29,10 @@ Repository: https://github.com/jnavila/git Leader: Jean-Noël Avila <jn.avila@free.fr> Members: Sébastien Helleu <flashcode@flashtux.org> +Language: ga (Irish) +Repository: https://github.com/aindriu80/git-po +Members: Aindriú Mac Giolla Eoin <aindriu80@gmail.com> + Language: id (Indonesian) Repository: https://github.com/bagasme/git-po Leader: Bagas Sanjaya <bagasdotme@gmail.com> @@ -234,6 +234,10 @@ # acquire lock придобивам ключалка # detached отделѐн, неÑвързан # revision walk обхождане на верÑиите +# exit code изходен код +# score оценка за Ñъвпадение +# raw необработен +# # # ------------------------ # „$var“ - може да не Ñработва за shell има gettext и eval_gettext - проверка - намират Ñе леÑно по „$ @@ -262,8 +266,8 @@ msgid "" msgstr "" "Project-Id-Version: git 2.48\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-03-05 22:57+0000\n" -"PO-Revision-Date: 2025-03-06 09:15+0100\n" +"POT-Creation-Date: 2025-05-29 13:50+0200\n" +"PO-Revision-Date: 2025-05-29 20:25+0200\n" "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n" "Language-Team: Bulgarian <dict@fsa-bg.org>\n" "Language: bg\n" @@ -1807,7 +1811,7 @@ msgstr "„stat“ не може да Ñе изпълни върху „%s“" #, c-format msgid "unable to read %s" -msgstr "обектът „%s“ не може да бъде прочетен" +msgstr "обектът „%s“ не може да Ñе прочете" #, c-format msgid "Badly quoted content in file '%s': %s" @@ -2163,7 +2167,7 @@ msgid "update tracked files" msgstr "обновÑване на Ñледените файлове" msgid "renormalize EOL of tracked files (implies -u)" -msgstr "уеднаквÑване на знаците за край на файл (включва опциÑта „-u“)" +msgstr "уеднаквÑване на знаците за край на ред (включва опциÑта „-u“)" msgid "record only the fact that the path will be added later" msgstr "отбелÑзване Ñамо на факта, че пътÑÑ‚ ще Ñе добави по-къÑно" @@ -2739,11 +2743,11 @@ msgstr "Ðеправилен аргумент на функциÑта „bisect_ #, c-format msgid "couldn't get the oid of the rev '%s'" -msgstr "идентификаторът на обект на верÑÐ¸Ñ â€ž%s“ не може да бъде получен" +msgstr "идентификаторът на обект на верÑÐ¸Ñ â€ž%s“ не може да Ñе получи" #, c-format msgid "couldn't open the file '%s'" -msgstr "файлът „%s“ не може да бъде отворен" +msgstr "файлът „%s“ не може да Ñе отвори" #, c-format msgid "Invalid command: you're currently in a %s/%s bisect" @@ -2879,8 +2883,7 @@ msgstr "" #, c-format msgid "cannot read file '%s' for replaying" msgstr "" -"файлът „%s“ не може да бъде прочетен, за да Ñе изпълнÑÑ‚ командите от него " -"наново" +"файлът „%s“ не може да Ñе прочете, за да Ñе изпълнÑÑ‚ командите от него наново" #, c-format msgid "running %s\n" @@ -2905,7 +2908,7 @@ msgstr "" #, c-format msgid "cannot open file '%s' for writing" -msgstr "файлът „%s“ не може да бъде отворен за запиÑ" +msgstr "файлът „%s“ не може да Ñе отвори за запиÑ" msgid "bisect run cannot continue any more" msgstr "двоичното търÑене не може да продължи" @@ -2964,7 +2967,7 @@ msgstr "трÑбва да завършва Ñ Ñ†Ð²ÑÑ‚" #, c-format msgid "cannot find revision %s to ignore" -msgstr "верÑиÑта за преÑкачане „%s“ не може да бъде открита" +msgstr "верÑиÑта за преÑкачане „%s“ липÑва" msgid "show blame entries as we find them, incrementally" msgstr "извеждане на авторÑтвото Ñ Ð½Ð°Ð¼Ð¸Ñ€Ð°Ð½ÐµÑ‚Ð¾ му, поÑледователно" @@ -2986,7 +2989,7 @@ msgid "force progress reporting" msgstr "извеждане на напредъка" msgid "show output score for blame entries" -msgstr "извеждане на допълнителна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° определÑнето на авторÑтвото" +msgstr "извеждане на оценка за Ñъвпадение при определÑне на авторÑтвото" msgid "show original filename (Default: auto)" msgstr "" @@ -3054,7 +3057,7 @@ msgid "use <file>'s contents as the final image" msgstr "използване на Ñъдържанието на ФÐЙЛа като крайно положение" msgid "score" -msgstr "напаÑване на редовете" +msgstr "оценка за Ñъвпадение" msgid "find line copies within and across files" msgstr "" @@ -3175,7 +3178,7 @@ msgid "" "branch '%s' not found.\n" "Did you forget --remote?" msgstr "" -"клонът „%s“ не може да бъде открит.\n" +"клонът „%s“ липÑва.\n" "Пробвахте ли опциÑта „--remote“?" #, c-format @@ -3191,7 +3194,7 @@ msgid "Deleted branch %s (was %s).\n" msgstr "Изтрит клон „%s“ (той Ñочеше към „%s“).\n" msgid "unable to parse format string" -msgstr "форматиращиÑÑ‚ низ не може да бъде анализиран: %s" +msgstr "форматиращиÑÑ‚ низ не може да Ñе анализира: %s" msgid "could not resolve HEAD" msgstr "подаването, Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“, не може да Ñе уÑтанови" @@ -3596,7 +3599,7 @@ msgstr "Разпакетиране на пратки от обекти" #, c-format msgid "cannot read object %s '%s'" -msgstr "обектът „%s“ (%s) не може да бъде прочетен" +msgstr "обектът „%s“ (%s) не може да Ñе прочете" msgid "flush is only for --buffer mode" msgstr "изчиÑтването на буферите (flush) Ñе ползва Ñамо за „--buffer“" @@ -3622,11 +3625,8 @@ msgstr "може да укажете Ñамо една пакетна Ð¾Ð¿Ñ†Ð¸Ñ msgid "git cat-file <type> <object>" msgstr "git cat-file ВИД ОБЕКТ" -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e|-p) ОБЕКТ" - -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t|-s) [--allow-unknown-type] ОБЕКТ" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e|-p|-t|-s) ОБЕКТ" msgid "" "git cat-file (--textconv | --filters)\n" @@ -3665,9 +3665,6 @@ msgstr "" msgid "show object size" msgstr "извеждане на размера на обект" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "позволÑване на опциите „-s“ и „-t“ да работÑÑ‚ Ñ Ð¿Ð¾Ð²Ñ€ÐµÐ´ÐµÐ½Ð¸ обекти" - msgid "use mail map file" msgstr "" "използване на файл за ÑъответÑтвиÑта на имената и адреÑите на е-поща " @@ -3730,6 +3727,13 @@ msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "" "опциите „--textconv“/„--filters“ изиÑкват ПЪТ, а пакетниÑÑ‚ режим (batch) не" +msgid "objects filter only supported in batch mode" +msgstr "филтрирането на обекти е възможно Ñамо в пакетен режим" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "филтрирането на обекти не Ñе поддържа: „%s“" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "„%s=<%s>“ изиÑква „%s“ или „%s“" @@ -3911,11 +3915,11 @@ msgstr "нÑÐºÐ¾Ñ Ð¾Ñ‚ необходимите верÑии липÑва в п #, c-format msgid "path '%s': cannot merge" -msgstr "пътÑÑ‚ „%s“ не може да бъде ÑлÑн" +msgstr "пътÑÑ‚ „%s“ не може да Ñе Ñлее" #, c-format msgid "Unable to add merge result for '%s'" -msgstr "Резултатът за „%s“ не може да бъде ÑлÑн" +msgstr "Резултатът за „%s“ не може да Ñе Ñлее" #, c-format msgid "Recreated %d merge conflict" @@ -3966,7 +3970,7 @@ msgstr "пътÑÑ‚ „%s“ не е ÑлÑÑ‚" #, c-format msgid "unable to read tree (%s)" -msgstr "дървото не може да бъде прочетено (%s)" +msgstr "дървото не може да Ñе прочете (%s)" msgid "you need to resolve your current index first" msgstr "първо трÑбва да коригирате индекÑа Ñи" @@ -3988,7 +3992,7 @@ msgid "HEAD is now at" msgstr "УказателÑÑ‚ „HEAD“ в момента Ñочи към" msgid "unable to update HEAD" -msgstr "УказателÑÑ‚ „HEAD“ не може да бъде обновен" +msgstr "УказателÑÑ‚ „HEAD“ не може да Ñе обнови" #, c-format msgid "Reset branch '%s'\n" @@ -4262,7 +4266,7 @@ msgstr "липÑва име на клон, използвайте опциÑта #, c-format msgid "could not resolve %s" -msgstr "„%s“ не може да бъде проÑледен" +msgstr "„%s“ не може да Ñе проÑледи" msgid "invalid path specification" msgstr "указан е неправилен път" @@ -4345,7 +4349,7 @@ msgstr "Изтриване на „%s“\n" #, c-format msgid "Would remove %s\n" -msgstr "Файлът „%s“ ще бъде изтрит\n" +msgstr "Файлът „%s“ ще Ñе изтрие\n" #, c-format msgid "Skipping repository %s\n" @@ -4353,21 +4357,21 @@ msgstr "ПреÑкачане на хранилището „%s“\n" #, c-format msgid "Would skip repository %s\n" -msgstr "Хранилището „%s“ ще бъде преÑкочено\n" +msgstr "Хранилището „%s“ ще Ñе преÑкочи\n" #, c-format msgid "failed to remove %s" -msgstr "файлът „%s“ не може да бъде изтрит" +msgstr "файлът „%s“ не може да Ñе изтрие" #, c-format msgid "could not lstat %s\n" msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „lstat“ за „%s“\n" msgid "Refusing to remove current working directory\n" -msgstr "Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да бъде изтрита\n" +msgstr "Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да Ñе изтрие\n" msgid "Would refuse to remove current working directory\n" -msgstr "Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да бъде изтрита\n" +msgstr "Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да Ñе изтрие\n" #, c-format msgid "" @@ -4440,8 +4444,8 @@ msgstr "" msgid "Would remove the following item:" msgid_plural "Would remove the following items:" -msgstr[0] "СледниÑÑ‚ обект ще бъде изтрит:" -msgstr[1] "Следните обекти ще бъдат изтрити:" +msgstr[0] "СледниÑÑ‚ обект ще Ñе изтрие:" +msgstr[1] "Следните обекти ще Ñе изтриÑÑ‚:" msgid "No more files to clean, exiting." msgstr "Файловете за изчиÑтване Ñвършиха. Изход от програмата." @@ -4482,7 +4486,7 @@ msgstr "" #, c-format msgid "failed to stat '%s'" -msgstr "не може да бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" +msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" #, c-format msgid "%s exists and is not a directory" @@ -4515,11 +4519,11 @@ msgstr "твърдата връзка е различна от източникР#, c-format msgid "failed to create link '%s'" -msgstr "връзката „%s“ не може да бъде Ñъздадена" +msgstr "връзката „%s“ не може да Ñе Ñъздаде" #, c-format msgid "failed to copy file to '%s'" -msgstr "файлът не може да бъде копиран като „%s“" +msgstr "файлът не може да Ñе копира като „%s“" #, c-format msgid "failed to iterate over '%s'" @@ -4546,7 +4550,7 @@ msgstr "отдалеченото хранилище не изпрати вÑич #, c-format msgid "unable to update %s" -msgstr "обектът „%s“ не може да бъде обновен" +msgstr "обектът „%s“ не може да Ñе обнови" msgid "failed to initialize sparse-checkout" msgstr "чаÑтичното изтеглÑне не може да Ñе инициализира" @@ -4557,7 +4561,7 @@ msgstr "" "ÑъщеÑтвува. ИзтеглÑне не може да Ñе извърши" msgid "unable to checkout working tree" -msgstr "работното дърво не може да бъде подготвено" +msgstr "работното дърво не може да Ñе подготви" msgid "unable to write parameters to config file" msgstr "наÑтройките не може да бъдат запиÑани в ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»" @@ -4566,7 +4570,7 @@ msgid "cannot repack to clean up" msgstr "не може да Ñе извърши пакетиране за изчиÑтване на файловете" msgid "cannot unlink temporary alternates file" -msgstr "временниÑÑ‚ файл за алтернативни обекти не може да бъде изтрит" +msgstr "временниÑÑ‚ файл за алтернативни обекти не може да Ñе изтрие" msgid "don't clone shallow repository" msgstr "без клониране на плитко хранилище" @@ -4730,7 +4734,7 @@ msgstr "родителÑките директории на „%s“ не можР#, c-format msgid "could not create work tree dir '%s'" -msgstr "работното дърво в „%s“ не може да бъде Ñъздадено." +msgstr "работното дърво в „%s“ не може да Ñе Ñъздаде." #, c-format msgid "Cloning into bare repository '%s'...\n" @@ -5070,22 +5074,22 @@ msgid "updating files failed" msgstr "неуÑпешно обновÑване на файловете" msgid "failed to unpack HEAD tree object" -msgstr "върховото дърво (HEAD tree object) не може да бъде извадено от пакет" +msgstr "върховото дърво (HEAD tree object) не може да Ñе извади от пакет" msgid "No paths with --include/--only does not make sense." msgstr "опциите „--include“ и „--only“ изиÑкват аргументи." msgid "unable to create temporary index" -msgstr "временниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде Ñъздаден" +msgstr "временниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе Ñъздаде" msgid "interactive add failed" msgstr "неуÑпешно интерактивно добавÑне" msgid "unable to update temporary index" -msgstr "временниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде обновен" +msgstr "временниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе обнови" msgid "Failed to update main cache tree" -msgstr "Кешът за обектите-дървета не може да бъде обновен" +msgstr "Кешът за обектите-дървета не може да Ñе обнови" msgid "cannot do a partial commit during a merge." msgstr "по време на Ñливане не може да Ñе извърши чаÑтично подаване." @@ -5097,10 +5101,10 @@ msgid "cannot do a partial commit during a rebase." msgstr "по време на пребазиране не може да Ñе извърши чаÑтично подаване." msgid "cannot read the index" -msgstr "индекÑÑŠÑ‚ не може да бъде прочетен" +msgstr "индекÑÑŠÑ‚ не може да Ñе прочете" msgid "unable to write temporary index file" -msgstr "временниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде запиÑан" +msgstr "временниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе запише" #, c-format msgid "commit '%s' lacks author header" @@ -5126,7 +5130,7 @@ msgstr "" #, c-format msgid "could not lookup commit '%s'" -msgstr "Ñледното подаване не може да бъде открито: %s" +msgstr "Ñледното подаване липÑва: %s" #, c-format msgid "(reading log message from standard input)\n" @@ -5137,24 +5141,24 @@ msgstr "Ñъобщението за подаване не бе прочетенР#, c-format msgid "could not read log file '%s'" -msgstr "файлът ÑÑŠÑ Ñъобщението за подаване „%s“ не може да бъде прочетен" +msgstr "файлът ÑÑŠÑ Ñъобщението за подаване „%s“ не може да Ñе прочете" #, c-format msgid "options '%s' and '%s:%s' cannot be used together" msgstr "опциите „--%s“ и „--%s:%s“ Ñа неÑъвмеÑтими" msgid "could not read SQUASH_MSG" -msgstr "Ñъобщението за вкарване SQUASH_MSG не може да бъде прочетено" +msgstr "Ñъобщението за вкарване SQUASH_MSG не може да Ñе прочете" msgid "could not read MERGE_MSG" -msgstr "Ñъобщението за Ñливане MERGE_MSG не може да бъде прочетено" +msgstr "Ñъобщението за Ñливане MERGE_MSG не може да Ñе прочете" #, c-format msgid "could not open '%s'" msgstr "„%s“ не може да Ñе отвори" msgid "could not write commit template" -msgstr "шаблонът за подаване не може да бъде запазен" +msgstr "шаблонът за подаване не може да Ñе запази" #, c-format msgid "" @@ -5231,7 +5235,7 @@ msgid "%sCommitter: %.*s <%.*s>" msgstr "%sПодаващ: %.*s <%.*s>" msgid "Cannot read index" -msgstr "ИндекÑÑŠÑ‚ не може да бъде прочетен" +msgstr "ИндекÑÑŠÑ‚ не може да Ñе прочете" msgid "unable to pass trailers to --trailers" msgstr "епилогът не може да Ñе подаде на „--trailers“" @@ -5275,7 +5279,7 @@ msgid "reword option of '%s' and '%s' cannot be used together" msgstr "опциите „%s“ и „%s“ Ñа неÑъвмеÑтими" msgid "You have nothing to amend." -msgstr "ÐÑма какво да бъде поправено." +msgstr "ÐÑма какво да Ñе поправи." msgid "You are in the middle of a merge -- cannot amend." msgstr "Ð’ момента Ñе извършва Ñливане, не може да поправÑте." @@ -5471,18 +5475,18 @@ msgid "ok to record a change with an empty message" msgstr "позволÑване на Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ñ Ð¿Ñ€Ð°Ð·Ð½Ð¸ ÑъобщениÑ" msgid "could not parse HEAD commit" -msgstr "върховото подаване „HEAD“ не може да бъде прочетено" +msgstr "върховото подаване „HEAD“ не може да Ñе прочете" #, c-format msgid "Corrupt MERGE_HEAD file (%s)" msgstr "Повреден файл за върха за Ñливането „MERGE_HEAD“ (%s)" msgid "could not read MERGE_MODE" -msgstr "режимът на Ñливане „MERGE_MODE“ не може да бъде прочетен" +msgstr "режимът на Ñливане „MERGE_MODE“ не може да Ñе прочете" #, c-format msgid "could not read commit message: %s" -msgstr "Ñъобщението за подаване не може да бъде прочетено: %s" +msgstr "Ñъобщението за подаване не може да Ñе прочете: %s" #, c-format msgid "Aborting commit due to empty commit message.\n" @@ -5723,7 +5727,7 @@ msgstr "при търÑене да Ñе уважат и директивите Ð #, c-format msgid "unable to read config file '%s'" -msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде прочетен" +msgstr "конфигурационниÑÑ‚ файл „%s“ не може да Ñе прочете" msgid "error processing config file(s)" msgstr "грешка при обработката на конфигурационен файл" @@ -5804,7 +5808,7 @@ msgstr "не Ñе поддържа редактиране на обекти-BLOB #, c-format msgid "cannot create configuration file %s" -msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде Ñъздаден" +msgstr "конфигурационниÑÑ‚ файл „%s“ не може да Ñе Ñъздаде" msgid "Action" msgstr "ДейÑтвие" @@ -6042,7 +6046,7 @@ msgstr "" "добавÑне на такъв МÐРКЕРна Ñчупеното работно дърво (Ñтандартно е „-broken“)" msgid "No names found, cannot describe anything." -msgstr "Ðе Ñа открити имена — нищо не може да бъде опиÑано." +msgstr "Ðе Ñа открити имена — нищо не може да Ñе опише." #, c-format msgid "option '%s' and commit-ishes cannot be used together" @@ -6064,6 +6068,51 @@ msgstr "укажете ÑуфикÑа на файла във формат за â msgid "specify the content of the diagnostic archive" msgstr "указване на Ñъдържанието на диагноÑÑ‚Ð¸Ñ‡Ð½Ð¸Ñ Ð°Ñ€Ñ…Ð¸Ð²" +#, c-format +msgid "unable to parse mode: %s" +msgstr "режимът не може да Ñе анализира: %s" + +#, c-format +msgid "unable to parse object id: %s" +msgstr "идентификаторът на обекта не може да Ñе анализира: %s" + +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [ОПЦИЯ_ЗÐ_Ð ÐЗЛИКИ…]" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "непознат аргумент: %s" + +msgid "working without -z is not supported" +msgstr "опциÑта „-z“ е задължителна" + +msgid "pathspec arguments not supported" +msgstr "не Ñе поддържат опции за пътища" + +msgid "revision arguments not allowed" +msgstr "не Ñе поддържат опции за верÑии" + +msgid "invalid raw diff input" +msgstr "неправилен необработен вход за разлики" + +msgid "tree objects not supported" +msgstr "не Ñе поддържат обекти-дървета" + +msgid "got EOF while reading path" +msgstr "край на файл (EOF) при изчитане на път" + +msgid "got EOF while reading destination path" +msgstr "край на файл (EOF) при изчитане на Ñ†ÐµÐ»ÐµÐ²Ð¸Ñ Ð¿ÑŠÑ‚" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "" +"оценката за Ñъвпадение при преименуване/копиране не може да Ñе анализира: %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "непознато ÑÑŠÑтоÑние на разлика: %c" + msgid "--merge-base only works with two commits" msgstr "опциÑта „--merge-base“ изиÑква точно две подаваниÑ" @@ -6106,15 +6155,15 @@ msgstr "git difftool [ОПЦИЯ…] [ПОДÐÐ’ÐÐЕ [ПОДÐÐ’ÐÐЕ]] [[--] #, c-format msgid "could not read symlink %s" -msgstr "Ñимволната връзка „%s“ не може да бъде прочетена" +msgstr "Ñимволната връзка „%s“ не може да Ñе прочете" #, c-format msgid "could not read symlink file %s" -msgstr "файлът, Ñочен от Ñимволната връзка „%s“, не може да бъде прочетен" +msgstr "файлът, Ñочен от Ñимволната връзка „%s“, не може да Ñе прочете" #, c-format msgid "could not read object %s for symlink %s" -msgstr "обектът „%s“ за Ñимволната връзка „%s“ не може да бъде прочетен" +msgstr "обектът „%s“ за Ñимволната връзка „%s“ не може да Ñе прочете" msgid "" "combined diff formats ('-c' and '--cc') are not supported in\n" @@ -6206,8 +6255,11 @@ msgstr "Съобщение за напредъка на вÑеки такъв Б msgid "select handling of signed tags" msgstr "Как да Ñе обработват подпиÑаните етикети" +msgid "select handling of signed commits" +msgstr "как да Ñе обработват подпиÑаните подаваниÑ" + msgid "select handling of tags that tag filtered objects" -msgstr "Как да Ñе обработват етикетите на филтрираните обекти" +msgstr "как да Ñе обработват етикетите на филтрираните обекти" msgid "select handling of commit messages in an alternate encoding" msgstr "" @@ -6304,7 +6356,7 @@ msgid "fetch.parallel cannot be negative" msgstr "опциÑта „fetch.parallel“ трÑбва да е неотрицателна" msgid "couldn't find remote ref HEAD" -msgstr "указателÑÑ‚ „HEAD“ в отдалеченото хранилище не може да бъде открит" +msgstr "указателÑÑ‚ „HEAD“ в отдалеченото хранилище липÑва" #, c-format msgid "From %.*s\n" @@ -6327,10 +6379,10 @@ msgid "[tag update]" msgstr "[обновÑване на етикетите]" msgid "unable to update local ref" -msgstr "локален указател не може да бъде обновен" +msgstr "локален указател не може да Ñе обнови" msgid "would clobber existing tag" -msgstr "ÑъщеÑтвуващ етикет ще бъде презапиÑан" +msgstr "ще Ñе презапише ÑъщеÑтвуващ етикет" msgid "[new tag]" msgstr "[нов етикет]" @@ -6349,7 +6401,7 @@ msgstr "ÑъщинÑко Ñливане" #, c-format msgid "cannot open '%s'" -msgstr "„%s“ не може да бъде отворен" +msgstr "„%s“ не може да Ñе отвори" msgid "" "fetch normally indicates which branches had a forced update,\n" @@ -6531,7 +6583,7 @@ msgstr "брой подмодули доÑтавени паралелно" msgid "modify the refspec to place all refs within refs/prefetch/" msgstr "" -"промÑна на указателÑ, така че и той, както оÑтаналите, да бъде в „refs/" +"промÑна на указателÑ, така че и той, както оÑтаналите, да е в „refs/" "prefetch/“" msgid "prune remote-tracking branches no longer on remote" @@ -6866,10 +6918,6 @@ msgid "%s: object corrupt or missing: %s" msgstr "%s: развален или липÑващ обект: %s" #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: обектът е непознат вид „%s“: %s" - -#, c-format msgid "%s: object could not be parsed: %s" msgstr "„%s“: не може да Ñе анализира: „%s“" @@ -6920,22 +6968,25 @@ msgstr "„%s“: неправилен указател за отмÑна на Ñ #, c-format msgid "unable to load rev-index for pack '%s'" -msgstr "обратниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° пакета „%s“ не може да бъде зареден" +msgstr "обратниÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ð° пакета „%s“ не може да Ñе зареди" #, c-format msgid "invalid rev-index for pack '%s'" msgstr "неправилен обратен Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° пакета „%s“" +msgid "Checking ref database" +msgstr "Проверка на базата от данни Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸Ñ‚Ðµ" + 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>...]" +" [--[no-]name-objects] [--[no-]references] [<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] [ОБЕКТ…]" +" [--[no-]name-objects] [--[no-]references] [ОБЕКТ…]" msgid "show unreachable objects" msgstr "показване на недоÑтижимите обекти" @@ -6973,6 +7024,9 @@ msgstr "показване на напредъка" msgid "show verbose names for reachable objects" msgstr "показване на подробни имена на доÑтижимите обекти" +msgid "check reference database consistency" +msgstr "проверка на валидноÑтта на базата от данни Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸" + msgid "Checking objects" msgstr "Проверка на обектите" @@ -7008,7 +7062,7 @@ msgstr "fsmonitor-daemon не наблюдава „%s“\n" #, c-format msgid "could not create fsmonitor cookie '%s'" -msgstr "биÑквитката за fsmonitor „%s“ не може да бъде Ñъздадена" +msgstr "биÑквитката за fsmonitor „%s“ не може да Ñе Ñъздаде" #, c-format msgid "fsmonitor: cookie_result '%d' != SEEN" @@ -7187,19 +7241,19 @@ msgid "unrecognized --schedule argument '%s'" msgstr "непознат аргумент към „--schedule“: %s" msgid "failed to write commit-graph" -msgstr "графът Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да бъде запиÑан" +msgstr "графът Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да Ñе запише" msgid "failed to prefetch remotes" msgstr "неуÑпешно предварително доÑтавÑне на отдалечените клони" msgid "failed to start 'git pack-objects' process" -msgstr "процеÑÑŠÑ‚ за командата „git pack-objects“ не може да бъде Ñтартиран" +msgstr "процеÑÑŠÑ‚ за командата „git pack-objects“ не може да Ñе Ñтартира" msgid "failed to finish 'git pack-objects' process" msgstr "процеÑÑŠÑ‚ за командата „git pack-objects“ не може да завърши" msgid "failed to write multi-pack-index" -msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде запиÑан" +msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да Ñе запише" msgid "'git multi-pack-index expire' failed" msgstr "неуÑпешно изпълнение на „git multi-pack-index expire“" @@ -7258,7 +7312,7 @@ msgid "unable to add '%s' value of '%s'" msgstr "неуÑпешно добавÑне на ÑтойноÑÑ‚ на „%s“ за „%s“" msgid "return success even if repository was not registered" -msgstr "уÑпешно завършване, дори ако хранилището не бъде региÑтрирано" +msgstr "уÑпешно завършване, дори ако хранилището не Ñе региÑтрира" #, c-format msgid "unable to unset '%s' value of '%s'" @@ -7341,7 +7395,7 @@ msgid "" "then try again. If it still fails, a git-maintenance(1) process may have\n" "crashed in this repository earlier: remove the file manually to continue." msgstr "" -"Файлът-ключалка „%s.lock“ не може да бъде Ñъздаден: %s\n" +"Файлът-ключалка „%s.lock“ не може да Ñе Ñъздаде: %s\n" "\n" "Изглежда, че и друг Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð° git-maintenance(1) е пуÑнат в това\n" "хранилище. Уверете Ñе, че вÑички подобни процеÑи Ñа Ñпрени и опитайте\n" @@ -7392,7 +7446,7 @@ msgstr "липÑва поддръжка за нишки. „%s“ ще Ñе Ð¿Ñ #, c-format msgid "unable to read tree %s" -msgstr "дървото не може да бъде прочетено: %s" +msgstr "дървото не може да Ñе прочете: %s" #, c-format msgid "unable to grep from object of type %s" @@ -7562,7 +7616,7 @@ msgstr "опциите „--no-index“ и „--untracked“ Ñа неÑъвме #, c-format msgid "unable to resolve revision: %s" -msgstr "верÑиÑта „%s“ не може бъде открита" +msgstr "верÑиÑта „%s“ не може Ñе открие" msgid "--untracked not supported with --recurse-submodules" msgstr "опциите „--untracked“ и „--recurse-submodules“ Ñа неÑъвмеÑтими" @@ -7758,7 +7812,7 @@ msgstr[0] "не може да Ñе запълни %d байт" msgstr[1] "не може да Ñе запълнÑÑ‚ %d байта" msgid "early EOF" -msgstr "неочакван край на файл" +msgstr "неочакван край на файл (EOF)" msgid "read error on input" msgstr "грешка при четене на входните данни" @@ -7799,7 +7853,7 @@ msgid "unknown object type %d" msgstr "непознат вид обект %d" msgid "cannot pread pack file" -msgstr "пакетниÑÑ‚ файл не може да бъде прочетен" +msgstr "пакетниÑÑ‚ файл не може да Ñе прочете" #, c-format msgid "premature end of pack file, %<PRIuMAX> byte missing" @@ -7817,11 +7871,11 @@ msgstr "" #, c-format msgid "cannot read existing object info %s" -msgstr "ÑъщеÑтвуващиÑÑ‚ обект в „%s“ не може да бъде прочетен" +msgstr "ÑъщеÑтвуващиÑÑ‚ обект в „%s“ не може да Ñе прочете" #, c-format msgid "cannot read existing object %s" -msgstr "ÑъщеÑтвуващиÑÑ‚ обект „%s“ не може да бъде прочетен" +msgstr "ÑъщеÑтвуващиÑÑ‚ обект „%s“ не може да Ñе прочете" #, c-format msgid "invalid blob object %s" @@ -7835,7 +7889,7 @@ msgid "Not all child objects of %s are reachable" msgstr "ÐÑкои обекти, наÑледници на „%s“, не може да бъдат доÑтигнати" msgid "failed to apply delta" -msgstr "разликата не може да бъде приложена" +msgstr "разликата не може да Ñе приложи" msgid "Receiving objects" msgstr "Получаване на обекти" @@ -7916,11 +7970,11 @@ msgstr "неправилна ÑтойноÑÑ‚: „pack.indexVersion=%<PRIu32>“ #, c-format msgid "Cannot open existing pack file '%s'" -msgstr "СъщеÑтвуващиÑÑ‚ пакетен файл „%s“ не може да бъде отворен" +msgstr "СъщеÑтвуващиÑÑ‚ пакетен файл „%s“ не може да Ñе отвори" #, c-format msgid "Cannot open existing pack idx file for '%s'" -msgstr "СъщеÑтвуващиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» „%s“ не може да бъде отворен" +msgstr "СъщеÑтвуващиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» „%s“ не може да Ñе отвори" #, c-format msgid "non delta: %d object" @@ -7996,8 +8050,7 @@ msgstr "права̀" msgid "specify that the git repository is to be shared amongst several users" msgstr "" -"указване, че хранилището на Git ще бъде Ñподелено от повече от един " -"потребител" +"указване, че хранилището на Git ще Ñе ÑÐ¿Ð¾Ð´ÐµÐ»Ñ Ð¾Ñ‚ повече от един потребител" msgid "override the name of the initial branch" msgstr "задаване на името на Ð¿ÑŠÑ€Ð²Ð¾Ð½Ð°Ñ‡Ð°Ð»Ð½Ð¸Ñ ÐºÐ»Ð¾Ð½" @@ -8010,7 +8063,7 @@ msgstr "указване на алгоритъм за контролна ÑумР#, c-format msgid "cannot mkdir %s" -msgstr "директориÑта „%s“ не може да бъде Ñъздадена" +msgstr "директориÑта „%s“ не може да Ñе Ñъздаде" #, c-format msgid "cannot chdir to %s" @@ -8057,7 +8110,7 @@ msgstr "временниÑÑ‚ файл не може да Ñе отвори" #, c-format msgid "could not read input file '%s'" -msgstr "входниÑÑ‚ файл „%s“ не може да бъде прочетен" +msgstr "входниÑÑ‚ файл „%s“ не може да Ñе прочете" msgid "could not read from stdin" msgstr "от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не може да Ñе чете" @@ -8145,10 +8198,6 @@ msgstr "" "проÑледÑване на еволюциÑта на диапазона от редове ÐÐЧÐЛО,КРÐЙ или :ФУÐКЦИЯта " "във ФÐЙЛа" -#, c-format -msgid "unrecognized argument: %s" -msgstr "непознат аргумент: %s" - msgid "-L<range>:<file> cannot be used with pathspec" msgstr "опциÑта „-LДИÐПÐЗОÐ:ФÐЙЛ“ не може да Ñе ползва Ñ Ð¿ÑŠÑ‚" @@ -8162,7 +8211,7 @@ msgstr "git show %s: повреден файл" #, c-format msgid "could not read object %s" -msgstr "обектът не може да бъде прочетен: %s" +msgstr "обектът не може да Ñе прочете: %s" #, c-format msgid "unknown type: %d" @@ -8177,7 +8226,7 @@ msgstr "не е зададена ÑтойноÑÑ‚ на „format.headers“" #, c-format msgid "cannot open patch file %s" -msgstr "файлът-кръпка „%s“ не може да бъде отворен" +msgstr "файлът-кръпка „%s“ не може да Ñе отвори" msgid "need exactly one range" msgstr "трÑбва да зададете точно един диапазон" @@ -8187,7 +8236,7 @@ msgstr "не е диапазон" #, c-format msgid "unable to read branch description file '%s'" -msgstr "файлът Ñ Ð¾Ð¿Ð¸Ñанието на клона „%s“ не може да бъде прочетен" +msgstr "файлът Ñ Ð¾Ð¿Ð¸Ñанието на клона „%s“ не може да Ñе прочете" msgid "cover letter needs email format" msgstr "придружаващото пиÑмо трÑбва да е форматирано като е-пиÑмо" @@ -8214,20 +8263,20 @@ msgid "failed to resolve '%s' as a valid ref" msgstr "„%s“ не е указател или не Ñочи към нищо" msgid "could not find exact merge base" -msgstr "точната база за Ñливане не може да бъде открита" +msgstr "точната база за Ñливане не може да Ñе открие" msgid "" "failed to get upstream, if you want to record base commit automatically,\n" "please use git branch --set-upstream-to to track a remote branch.\n" "Or you could specify base commit by --base=<base-commit-id> manually" msgstr "" -"ÑледениÑÑ‚ клон не може да бъде уÑтановен. Ðко иÑкате ръчно да го\n" +"ÑледениÑÑ‚ клон не може да Ñе уÑтанови. Ðко иÑкате ръчно да го\n" "зададете, използвайте „git branch --set-upstream-to“.\n" "Може ръчно да зададете базово подаване чрез „--" "base=<ИДЕÐТИФИКÐТОР_ÐÐ_БÐЗОВО_ПОДÐÐ’ÐÐЕ>“." msgid "failed to find exact merge base" -msgstr "точната база при Ñливане не може да бъде открита" +msgstr "точната база при Ñливане не може да Ñе определи" msgid "base commit should be the ancestor of revision list" msgstr "базовото подаване трÑбва да е предшеÑтвеникът на ÑпиÑъка Ñ Ð²ÐµÑ€Ñиите" @@ -8236,7 +8285,7 @@ msgid "base commit shouldn't be in revision list" msgstr "базовото подаване не може да е в ÑпиÑъка Ñ Ð²ÐµÑ€Ñиите" msgid "cannot get patch id" -msgstr "идентификаторът на кръпката не може да бъде получен" +msgstr "идентификаторът на кръпката не може да Ñе получи" msgid "failed to infer range-diff origin of current series" msgstr "" @@ -8424,7 +8473,7 @@ msgstr "опциÑта „--remerge-diff“ е неÑъвмеÑтима Ñ Ð³ÐµÐ #, c-format msgid "could not create directory '%s'" -msgstr "ДиректориÑта „%s“ не може да бъде Ñъздадена" +msgstr "ДиректориÑта „%s“ не може да Ñе Ñъздаде" msgid "--interdiff requires --cover-letter or single patch" msgstr "" @@ -8450,7 +8499,7 @@ msgstr "Диапазонна разлика ÑпрÑмо v%d:" #, c-format msgid "unable to read signature file '%s'" -msgstr "файлът „%s“ Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñ Ð½Ðµ може да бъде прочетен" +msgstr "файлът „%s“ Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñ Ð½Ðµ може да Ñе прочете" msgid "Generating patches" msgstr "Създаване на кръпки" @@ -8787,7 +8836,7 @@ msgstr "поддържа Ñе Ñамо Ñливане на точно две Ð¸Ñ #, c-format msgid "could not resolve ref '%s'" -msgstr "указателÑÑ‚ „%s“ не може да бъде проÑледен" +msgstr "указателÑÑ‚ „%s“ не може да Ñе проÑледи" #, c-format msgid "Merging %s with %s\n" @@ -8821,6 +8870,9 @@ msgstr "Ñамо тривиално Ñливане" msgid "also show informational/conflict messages" msgstr "показване и информационните ÑъобщениÑ, и тези при конфликт" +msgid "suppress all output; only exit status wanted" +msgstr "без извеждане на информациÑ, получаване Ñамо на изходен код" + msgid "list filenames without modes/oids/stages" msgstr "" "извеждане на имената на файлове без режими/идентификатори на обекти/етапи" @@ -8952,12 +9004,11 @@ msgstr "Вече е обновено." #, c-format msgid "Squash commit -- not updating HEAD\n" -msgstr "Вкарано подаване — указателÑÑ‚ „HEAD“ нÑма да бъде обновен\n" +msgstr "Вкарано подаване — указателÑÑ‚ „HEAD“ нÑма да Ñе обнови\n" #, c-format msgid "No merge message -- not updating HEAD\n" -msgstr "" -"ЛипÑва Ñъобщение при подаване — указателÑÑ‚ „HEAD“ нÑма да бъде обновен\n" +msgstr "ЛипÑва Ñъобщение при подаване — указателÑÑ‚ „HEAD“ нÑма да Ñе обнови\n" #, c-format msgid "'%s' does not point to a commit" @@ -8968,14 +9019,14 @@ msgid "Bad branch.%s.mergeoptions string: %s" msgstr "Ðеправилен низ за наÑтройката „branch.%s.mergeoptions“: „%s“" msgid "Unable to write index." -msgstr "ИндекÑÑŠÑ‚ не може да бъде прочетен" +msgstr "ИндекÑÑŠÑ‚ не може да Ñе прочете" msgid "Not handling anything other than two heads merge." msgstr "Поддържа Ñе Ñамо Ñливане на точно две иÑтории." #, c-format msgid "unable to write %s" -msgstr "„%s“ не може да бъде запиÑан" +msgstr "„%s“ не може да Ñе запише" #, c-format msgid "Could not read from '%s'" @@ -8984,8 +9035,8 @@ msgstr "От „%s“ не може да Ñе чете" #, c-format msgid "Not committing merge; use 'git commit' to complete the merge.\n" msgstr "" -"Сливането нÑма да бъде подадено. За завършването му и подаването му " -"използвайте командата „git commit“.\n" +"Сливането нÑма да Ñе подаде. За завършването му и подаването му използвайте " +"командата „git commit“.\n" msgid "" "Please enter a commit message to explain why this merge is necessary,\n" @@ -9163,7 +9214,7 @@ msgstr "%d (FSCK_IGNORE?) никога не трÑбва да задейÑтва #, c-format msgid "could not read tagged object '%s'" -msgstr "обектът Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ не може да бъде прочетен: %s" +msgstr "обектът Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ не може да Ñе прочете: %s" #, c-format msgid "object '%s' tagged as '%s', but is a '%s' type" @@ -9176,7 +9227,7 @@ msgid "tag on stdin did not refer to a valid object" msgstr "етикетът на ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не Ñочи към правилен обект" msgid "unable to write tag file" -msgstr "файлът за етикета не може да бъде запазен" +msgstr "файлът за етикета не може да Ñе запази" msgid "input is NUL terminated" msgstr "входните запиÑи Ñа разделени Ñ Ð½ÑƒÐ»ÐµÐ²Ð¸Ñ Ð·Ð½Ð°Ðº „NUL“" @@ -9239,8 +9290,11 @@ msgstr "" "при препакетиране пакетните файлове, които Ñа Ñ Ð¿Ð¾-малък от този размер, да " "Ñе обединÑват в пакети Ñ Ð¿Ð¾-голÑм от този размер" -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [ОПЦИЯ…] ОБЕКТ… ЦЕЛ" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] ОБЕКТ… ЦЕЛ" + +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] ОБЕКТ… ЦЕЛЕВÐ_ДИРЕКТОРИЯ" #, c-format msgid "Directory %s is in index and no submodule?" @@ -9311,6 +9365,12 @@ msgid "%s, source=%s, destination=%s" msgstr "%s, обект: „%s“, цел: „%s“" #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "" +"невъзможно е да Ñе премеÑÑ‚ÑÑ‚ едновременно и „%s“, и родителÑката Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ " +"„%s“" + +#, c-format msgid "Renaming %s to %s\n" msgstr "Преименуване на „%s“ на „%s“\n" @@ -9455,7 +9515,7 @@ msgid "please supply the note contents using either -m or -F option" msgstr "задайте Ñъдържанието на бележката Ñ Ð½ÑÐºÐ¾Ñ Ð¾Ñ‚ опциите „-m“ или „-F“" msgid "unable to write note object" -msgstr "обектът-бележка не може да бъде запиÑан" +msgstr "обектът-бележка не може да Ñе запише" #, c-format msgid "the note contents have been left in %s" @@ -9463,7 +9523,7 @@ msgstr "Ñъдържанието на бележката е във файла †#, c-format msgid "could not open or read '%s'" -msgstr "файлът „%s“ не може да бъде отворен или прочетен" +msgstr "файлът „%s“ не може да Ñе отвори или прочете" #, c-format msgid "failed to resolve '%s' as a valid ref." @@ -9471,7 +9531,7 @@ msgstr "не може да Ñе открие към какво Ñочи „%s“ #, c-format msgid "failed to read object '%s'." -msgstr "обектът „%s“ не може да бъде прочетен." +msgstr "обектът „%s“ не може да Ñе прочете." #, c-format msgid "cannot read note data from non-blob object '%s'." @@ -9575,16 +9635,16 @@ msgstr "" "C“.\n" msgid "failed to delete ref NOTES_MERGE_PARTIAL" -msgstr "указателÑÑ‚ „NOTES_MERGE_PARTIAL“ не може да бъде изтрит" +msgstr "указателÑÑ‚ „NOTES_MERGE_PARTIAL“ не може да Ñе изтрие" msgid "failed to delete ref NOTES_MERGE_REF" -msgstr "указателÑÑ‚ „NOTES_MERGE_REF“ не може да бъде изтрит" +msgstr "указателÑÑ‚ „NOTES_MERGE_REF“ не може да Ñе изтрие" msgid "failed to remove 'git notes merge' worktree" -msgstr "работната Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ð° „git notes merge“ не може да бъде изтрита" +msgstr "работната Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ð° „git notes merge“ не може да Ñе изтрие" msgid "failed to read ref NOTES_MERGE_PARTIAL" -msgstr "указателÑÑ‚ „NOTES_MERGE_PARTIAL“ не може да бъде прочетен" +msgstr "указателÑÑ‚ „NOTES_MERGE_PARTIAL“ не може да Ñе прочете" msgid "could not find commit from NOTES_MERGE_PARTIAL." msgstr "подаването от „NOTES_MERGE_PARTIAL“ не може да Ñе открие." @@ -9741,7 +9801,7 @@ msgstr "ЗапиÑване на обектите" #, c-format msgid "failed to stat %s" -msgstr "не може да бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" +msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“" #, c-format msgid "failed utime() on %s" @@ -9772,11 +9832,11 @@ msgstr "ПреброÑване на обектите" #, c-format msgid "unable to get size of %s" -msgstr "размерът на „%s“ не може да бъде получен" +msgstr "размерът на „%s“ не може да Ñе получи" #, c-format msgid "unable to parse object header of %s" -msgstr "заглавната чаÑÑ‚ на „%s“ не може да бъде анализирана" +msgstr "заглавната чаÑÑ‚ на „%s“ не може да Ñе анализира" #, c-format msgid "object %s cannot be read" @@ -9801,7 +9861,7 @@ msgstr "" #, c-format msgid "unable to get type of object %s" -msgstr "видът на обекта „%s“ не може да бъде определен" +msgstr "видът на обекта „%s“ не може да Ñе определи" msgid "Compressing objects" msgstr "КомпреÑиране на обектите" @@ -9831,7 +9891,7 @@ msgstr "" #, c-format msgid "could not get type of object %s in pack %s" -msgstr "видът на обекта „%s“ в пакет „%s“ не може да бъде определен" +msgstr "видът на обекта „%s“ в пакет „%s“ не може да Ñе определи" #, c-format msgid "could not find pack '%s'" @@ -9839,7 +9899,7 @@ msgstr "пакетът „%s“ не може да Ñе открие" #, c-format msgid "packfile %s cannot be accessed" -msgstr "пакетниÑÑ‚ файл „%s“ не може да бъде доÑтъпен" +msgstr "пакетниÑÑ‚ файл „%s“ не може да Ñе доÑтъпи" msgid "Enumerating cruft objects" msgstr "ИзброÑване на ненужните обекти" @@ -9872,14 +9932,14 @@ msgstr "" "заредÑÑ‚" msgid "cannot open pack index" -msgstr "индекÑÑŠÑ‚ на Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» не може да бъде отворен" +msgstr "индекÑÑŠÑ‚ на Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» не може да Ñе отвори" #, c-format msgid "loose object at %s could not be examined" -msgstr "непакетираниÑÑ‚ обект в „%s“ не може да бъде анализиран" +msgstr "непакетираниÑÑ‚ обект в „%s“ не може да Ñе анализира" msgid "unable to force loose object" -msgstr "оÑтаването на обекта непакетиран не може да бъде наложено" +msgstr "оÑтаването на обекта непакетиран не може да Ñе наложи" #, c-format msgid "not a rev '%s'" @@ -10272,6 +10332,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "недоÑтъпно подаване: %s" +#, c-format +msgid "invalid refspec '%s'" +msgstr "неправилен указател: „%s“" + msgid "ignoring --verify-signatures for rebase" msgstr "без „--verify-signatures“ при пребазиране" @@ -10330,7 +10394,7 @@ msgid "" "$ git reset --hard\n" "to recover." msgstr "" -"Работното ви копие не може да бъде превъртÑно.\n" +"Работното ви копие не може да Ñе превърти.\n" "След като запазите вÑичко необходимо поÑочено от командата:\n" " git diff %s\n" "изпълнете:\n" @@ -10806,7 +10870,7 @@ msgstr "неправилната ÑтойноÑÑ‚ на „allow_rerere_autoupdat #, c-format msgid "could not remove '%s'" -msgstr "„%s“ не може да бъде изтрит" +msgstr "„%s“ не може да Ñе изтрие" #, c-format msgid "" @@ -11047,7 +11111,7 @@ msgstr "" "ОпциÑта „--edit-todo“ е доÑтъпна Ñамо по време на интерактивно пребазиране." msgid "Cannot read HEAD" -msgstr "УказателÑÑ‚ „HEAD“ не може да бъде прочетен" +msgstr "УказателÑÑ‚ „HEAD“ не може да Ñе прочете" msgid "" "You must edit all merge conflicts and then\n" @@ -11125,7 +11189,7 @@ msgid "No such ref: %s" msgstr "Такъв указател нÑма: %s" msgid "Could not resolve HEAD to a commit" -msgstr "Подаването, Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“, не може да бъде открито" +msgstr "ЛипÑва подаването, Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“" #, c-format msgid "'%s': need exactly one merge base with branch" @@ -11265,6 +11329,9 @@ msgstr "" msgid "git reflog exists <ref>" msgstr "git reflog exists УКÐЗÐТЕЛ" +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktree]|УКÐЗÐТЕЛ…]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "неправилно времево клеймо „%s“ подадено към „--%s“" @@ -11318,8 +11385,8 @@ msgid "Marking reachable objects..." msgstr "ОтбелÑзване на доÑтижимите обекти…" #, c-format -msgid "%s points nowhere!" -msgstr "„%s“ не Ñочи наникъде!" +msgid "reflog could not be found: '%s'" +msgstr "журналът Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸ липÑва: „%s“" msgid "no reflog specified to delete" msgstr "не е указан журнал Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð·Ð° изтриване" @@ -11328,6 +11395,15 @@ msgstr "не е указан журнал Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð·Ð° изтриРmsgid "invalid ref format: %s" msgstr "неправилен формат на указател: %s" +msgid "drop the reflogs of all references" +msgstr "изтриване на вÑички журнали Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸" + +msgid "drop reflogs from the current worktree only" +msgstr "изтриване на журнала Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸ Ñамо в текущото работно дърво" + +msgid "references specified along with --all" +msgstr "указателите Ñе задават Ñ Ð¾Ð¿Ñ†Ð¸Ñта „--all“" + msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=ФОРМÐТ [--no-reflog] [--dry-run]" @@ -11470,7 +11546,7 @@ msgstr "вече ÑъщеÑтвува отдалечено хранилище Ñ #, c-format msgid "Could not setup master '%s'" -msgstr "ОÑновниÑÑ‚ клон „%s“ не може да бъде наÑтроен" +msgstr "ОÑновниÑÑ‚ клон „%s“ не може да Ñе наÑтрои" #, c-format msgid "more than one %s" @@ -11514,7 +11590,7 @@ msgstr "ÐÑма отдалечено хранилище на име „%s“" #, c-format msgid "Could not rename config section '%s' to '%s'" -msgstr "Разделът „%s“ в наÑтройките не може да бъде преименуван на „%s“" +msgstr "Разделът „%s“ в наÑтройките не може да Ñе преименува на „%s“" #, c-format msgid "" @@ -11552,7 +11628,7 @@ msgstr[1] "" #, c-format msgid "Could not remove config section '%s'" -msgstr "Разделът „%s“ в наÑтройките не може да бъде изтрит" +msgstr "Разделът „%s“ в наÑтройките не може да Ñе изтрие" #, c-format msgid " new (next fetch will store in remotes/%s)" @@ -11734,7 +11810,7 @@ msgstr "" #, c-format msgid "Could not delete %s" -msgstr "„%s“ не може да бъде изтрит" +msgstr "„%s“ не може да Ñе изтрие" #, c-format msgid "Not a valid ref: %s" @@ -11762,7 +11838,7 @@ msgstr "адреÑ: %s" #, c-format msgid " * [would prune] %s" -msgstr " â— [ще бъде окаÑтрено] %s" +msgstr " â— [ще Ñе окаÑтри] %s" #, c-format msgid " * [pruned] %s" @@ -11863,7 +11939,7 @@ msgstr "пакет „%s“ е твърде голÑм за Ñвиване" #, c-format msgid "could not open tempfile %s for writing" -msgstr "временниÑÑ‚ файл „%s“ не може да бъде отворен за запиÑ" +msgstr "временниÑÑ‚ файл „%s“ не може да Ñе отвори за запиÑ" msgid "could not close refs snapshot tempfile" msgstr "временниÑÑ‚ файл ÑÑŠÑ Ñнимка на указателите не може да Ñе затвори" @@ -11896,6 +11972,11 @@ msgid "with --cruft, expire objects older than this" msgstr "" "Ñ Ð¾Ð¿Ñ†Ð¸Ñта „--cruft“: обÑвÑване на обектите по-Ñтари от това ВРЕМЕ за оÑтарели" +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "" +"Ñ Ð¾Ð¿Ñ†Ð¸Ñта „--cruft“: препакетиране Ñамо на пакетите за ненужни обекти, които " +"Ñа Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€ под този" + msgid "remove redundant packs, and run git-prune-packed" msgstr "" "премахване на ненужните пакетирани файлове и изпълнение на командата „git-" @@ -12015,7 +12096,7 @@ msgstr "" #, c-format msgid "replace ref '%s' not found" -msgstr "указателÑÑ‚ за замÑна „%s“ не може да бъде открит" +msgstr "указателÑÑ‚ за замÑна „%s“ липÑва" #, c-format msgid "Deleted replace ref '%s'" @@ -12041,14 +12122,14 @@ msgstr "" #, c-format msgid "unable to open %s for writing" -msgstr "„%s“ не може да бъде отворен за запиÑ" +msgstr "„%s“ не може да Ñе отвори за запиÑ" msgid "cat-file reported failure" msgstr "изпълнението на „cat-file“ завърши Ñ Ð³Ñ€ÐµÑˆÐºÐ°" #, c-format msgid "unable to open %s for reading" -msgstr "„%s“ не може да бъде отворен за четене" +msgstr "„%s“ не може да Ñе отвори за четене" msgid "unable to spawn mktree" msgstr "не може да Ñе Ñъздаде Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð·Ð° „mktree“" @@ -12067,7 +12148,7 @@ msgid "unable to fstat %s" msgstr "„fstat“ не може да Ñе изпълни върху „%s“" msgid "unable to write object to database" -msgstr "обектът не може да бъде запиÑан в базата от данни" +msgstr "обектът не може да Ñе запише в базата от данни" #, c-format msgid "unable to get object type for %s" @@ -12105,11 +12186,11 @@ msgid "the original commit '%s' has a gpg signature" msgstr "първоначалното подаване „%s“ е Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñ Ð½Ð° GPG" msgid "the signature will be removed in the replacement commit!" -msgstr "ПодпиÑÑŠÑ‚ ще бъде премахнат в заменÑщото подаване!" +msgstr "ПодпиÑÑŠÑ‚ ще Ñе премахне в заменÑщото подаване!" #, c-format msgid "could not write replacement commit for: '%s'" -msgstr "заменÑщото подаване за „%s“ не може да бъде запиÑано" +msgstr "заменÑщото подаване за „%s“ не може да Ñе запише" #, c-format msgid "graft for '%s' unnecessary" @@ -12294,11 +12375,11 @@ msgid "You do not have a valid HEAD." msgstr "УказателÑÑ‚ „HEAD“ е повреден." msgid "Failed to find tree of HEAD." -msgstr "Дървото, Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“, не може да бъде открито." +msgstr "Дървото, Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“, не може да Ñе открие." #, c-format msgid "Failed to find tree of %s." -msgstr "Дървото, Ñочено от „%s“, не може да бъде открито." +msgstr "Дървото, Ñочено от „%s“, не може да Ñе открие." #, c-format msgid "HEAD is now at %s" @@ -12364,19 +12445,22 @@ msgstr "" #, c-format msgid "Could not reset index file to revision '%s'." -msgstr "ИндекÑÑŠÑ‚ не може да бъде занулен към верÑÐ¸Ñ â€ž%s“." +msgstr "ИндекÑÑŠÑ‚ не може да Ñе занули към верÑÐ¸Ñ â€ž%s“." msgid "Could not write new index file." -msgstr "ÐовиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде запиÑан." +msgstr "ÐовиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе запише." #, c-format msgid "unable to get disk usage of %s" -msgstr "използваното мÑÑто за „%s“ не може да бъде получено" +msgstr "използваното мÑÑто за „%s“ не може да Ñе получи" #, c-format msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "неправилна ÑтойноÑÑ‚ за „%s“: „%s“, единÑтвениÑÑ‚ позволен формат е „%s“" +msgid "-z option used with unsupported option" +msgstr "неподдържана ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ñ Ð¾Ð¿Ñ†Ð¸Ñта „-z“" + msgid "rev-list does not support display of notes" msgstr "командата „rev-list“ не поддържа извеждането на бележки" @@ -12463,7 +12547,7 @@ msgid "this operation must be run in a work tree" msgstr "тази команда трÑбва да Ñе изпълни в работно дърво" msgid "Could not read the index" -msgstr "ИндекÑÑŠÑ‚ не може да бъде прочетен" +msgstr "ИндекÑÑŠÑ‚ не може да Ñе прочете" #, c-format msgid "unknown mode for --show-object-format: %s" @@ -12787,8 +12871,8 @@ msgstr "опциÑта „--reflog“ изиÑква точно едно име #, c-format msgid "only %d entry can be shown at one time." msgid_plural "only %d entries can be shown at one time." -msgstr[0] "Ñамо %d Ð·Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да бъде показан наведнъж." -msgstr[1] "Ñамо %d запиÑа може да бъде показани наведнъж." +msgstr[0] "Ñамо %d Ð·Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да Ñе покаже наведнъж." +msgstr[1] "Ñамо %d запиÑа може да Ñе покажат наведнъж." #, c-format msgid "no such ref %s" @@ -12898,14 +12982,14 @@ msgstr "" #, c-format msgid "failed to remove directory '%s'" -msgstr "директориÑта „%s“ не може да бъде изтрита" +msgstr "директориÑта „%s“ не може да Ñе изтрие" msgid "failed to create directory for sparse-checkout file" -msgstr "директориÑта за чаÑтично изтеглÑне „%s“ не може да бъде Ñъздадена" +msgstr "директориÑта за чаÑтично изтеглÑне „%s“ не може да Ñе Ñъздаде" #, c-format msgid "unable to fdopen %s" -msgstr "обектът „%s“ не може да бъде отворен Ñ â€žfdopen“" +msgstr "обектът „%s“ не може да Ñе отвори Ñ â€žfdopen“" msgid "failed to initialize worktree config" msgstr "наÑтройките на работното дърво не може да Ñе инициализират" @@ -12933,7 +13017,7 @@ msgstr "пътÑÑ‚ „%s“ не може да Ñе нормализира" #, c-format msgid "unable to unquote C-style string '%s'" -msgstr "цитирането на низ, форматиран за C — „%s“ не може да бъде изчиÑтено" +msgstr "цитирането на низ, форматиран за C — „%s“ не може да Ñе изчиÑти" msgid "unable to load existing sparse-checkout patterns" msgstr "шаблоните за чаÑтично изтеглÑне не може да Ñе заредÑÑ‚" @@ -13119,7 +13203,7 @@ msgstr "" "index“." msgid "could not save index tree" -msgstr "дървото Ñочено от индекÑа не може да бъде запазено" +msgstr "дървото Ñочено от индекÑа не може да Ñе запази" #, c-format msgid "Merging %s with %s" @@ -13140,7 +13224,7 @@ msgstr "Изтрито: „%s“ (%s)" #, c-format msgid "%s: Could not drop stash entry" -msgstr "Скатаното „%s“ не може да бъде изтрито" +msgstr "Скатаното „%s“ не може да Ñе изтрие" #, c-format msgid "'%s' is not a stash reference" @@ -13153,10 +13237,10 @@ msgid "No branch name specified" msgstr "Ðе е указано име на клон" msgid "failed to parse tree" -msgstr "дървото не може да бъде анализирано" +msgstr "дървото не може да Ñе анализира" msgid "failed to unpack trees" -msgstr "дървото не може да бъде разпакетирано" +msgstr "дървото не може да Ñе разпакетира" msgid "include untracked files in the stash" msgstr "Ñкатаване и на неÑледените файлове" @@ -13166,7 +13250,7 @@ msgstr "извеждане Ñамо на неÑледените файлове Ð #, c-format msgid "Cannot update %s with %s" -msgstr "УказателÑÑ‚ „%s“ не може да бъде обновен да Ñочи към „%s“" +msgstr "УказателÑÑ‚ „%s“ не може да Ñе обнови да Ñочи към „%s“" msgid "stash message" msgstr "Ñъобщение при Ñкатаване" @@ -13184,19 +13268,19 @@ msgid "You do not have the initial commit yet" msgstr "Ð’Ñе още липÑва първоначално подаване" msgid "Cannot save the current index state" -msgstr "СъÑтоÑнието на Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде запазено" +msgstr "СъÑтоÑнието на Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе запази" msgid "Cannot save the untracked files" msgstr "ÐеÑледените файлове не може да Ñе запазÑÑ‚" msgid "Cannot save the current worktree state" -msgstr "СъÑтоÑнието на работното дърво не може да бъде запазено" +msgstr "СъÑтоÑнието на работното дърво не може да Ñе запази" msgid "Cannot save the current staged state" -msgstr "СъÑтоÑнието на Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде запазено" +msgstr "СъÑтоÑнието на Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе запази" msgid "Cannot record working tree state" -msgstr "СъÑтоÑнието на работното дърво не може да бъде запазено" +msgstr "СъÑтоÑнието на работното дърво не може да Ñе запази" msgid "Can't use --patch and --include-untracked or --all at the same time" msgstr "опциÑта „--patch“ е неÑъвмеÑтима Ñ â€ž--include-untracked“ и „--all“" @@ -13216,7 +13300,7 @@ msgid "Cannot initialize stash" msgstr "Скатаването не може да Ñтартира" msgid "Cannot save the current status" -msgstr "Текущото ÑÑŠÑтоÑние не може да бъде запазено" +msgstr "Текущото ÑÑŠÑтоÑние не може да Ñе запази" #, c-format msgid "Saved working directory and index state %s" @@ -13329,7 +13413,7 @@ msgstr "Във файла „.gitmodules“ липÑва Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð· #, c-format msgid "could not resolve HEAD ref inside the submodule '%s'" -msgstr "указателÑÑ‚ Ñочен от „HEAD“ в подмодула „%s“ не може да бъде открит" +msgstr "указателÑÑ‚ Ñочен от „HEAD“ в подмодула „%s“ липÑва" #, c-format msgid "failed to recurse into submodule '%s'" @@ -13400,7 +13484,7 @@ msgstr "неуÑпешно региÑтриране на Ð°Ð´Ñ€ÐµÑ Ð·Ð° Ð¿ÑŠÑ‚Ñ #, c-format msgid "failed to update remote for submodule '%s'" -msgstr "отдалечениÑÑ‚ Ð°Ð´Ñ€ÐµÑ Ð½Ð° подмодула „%s“ не може да бъде променен" +msgstr "отдалечениÑÑ‚ Ð°Ð´Ñ€ÐµÑ Ð½Ð° подмодула „%s“ не може да Ñе промени" msgid "suppress output of synchronizing submodule url" msgstr "без извеждане на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸ Ñинхронизирането на подмодул" @@ -13432,11 +13516,11 @@ msgstr "ДиректориÑта „%s“ е изчиÑтена\n" #, c-format msgid "Could not remove submodule work tree '%s'\n" msgstr "" -"ДиректориÑта към работното дърво на подмодула „%s“ не може да бъде изтрита\n" +"ДиректориÑта към работното дърво на подмодула „%s“ не може да Ñе изтрие\n" #, c-format msgid "could not create empty submodule directory %s" -msgstr "празната Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° подмодула „%s“ не може да бъде Ñъздадена" +msgstr "празната Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° подмодула „%s“ не може да Ñе Ñъздаде" #, c-format msgid "Submodule '%s' (%s) unregistered for path '%s'\n" @@ -13501,7 +13585,7 @@ msgstr "ÐеуÑпешно клониране на адреÑа „%s“ в пъ #, c-format msgid "could not get submodule directory for '%s'" -msgstr "директориÑта на подмодула „%s“ не може да бъде получена" +msgstr "директориÑта на подмодула „%s“ не може да Ñе получи" msgid "alternative anchor for relative paths" msgstr "Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° определÑнето на отноÑителните пътища" @@ -13726,7 +13810,7 @@ msgid "force creation" msgstr "принудително Ñъздаване" msgid "show whether the branch would be created" -msgstr "извеждане дали клонът ще бъде Ñъздаден" +msgstr "извеждане дали клонът ще Ñе Ñъздаде" msgid "" "git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--" @@ -13775,7 +13859,7 @@ msgstr "Ðктивиране на локалното хранилище за пР#, c-format msgid "unable to checkout submodule '%s'" -msgstr "Подмодулът „%s“ не може да бъде изтеглен" +msgstr "Подмодулът „%s“ не може да Ñе изтегли" msgid "please make sure that the .gitmodules file is in the working tree" msgstr "файлът „.gitmodules“ трÑбва да е в работното дърво" @@ -13924,7 +14008,7 @@ msgstr "" "изтриете вие.\n" msgid "unable to sign the tag" -msgstr "етикетът не може да бъде подпиÑан" +msgstr "етикетът не може да Ñе подпише" #, c-format msgid "" @@ -14047,15 +14131,15 @@ msgstr "Разпакетиране на обектите" #, c-format msgid "failed to create directory %s" -msgstr "директориÑта „%s“ не може да бъде Ñъздадена" +msgstr "директориÑта „%s“ не може да Ñе Ñъздаде" #, c-format msgid "failed to delete file %s" -msgstr "файлът „%s“ не може да бъде изтрит" +msgstr "файлът „%s“ не може да Ñе изтрие" #, c-format msgid "failed to delete directory %s" -msgstr "директориÑта „%s“ не може да бъде изтрита" +msgstr "директориÑта „%s“ не може да Ñе изтрие" #, c-format msgid "Testing mtime in '%s' " @@ -14098,8 +14182,7 @@ msgid "git update-index [<options>] [--] [<file>...]" msgstr "git update-index [ОПЦИЯ…] [--] [ФÐЙЛ…]" msgid "continue refresh even when index needs update" -msgstr "" -"продължаване Ñ Ð¾Ð±Ð½Ð¾Ð²Ñването, дори когато индекÑÑŠÑ‚ трÑбва да бъде обновен" +msgstr "продължаване Ñ Ð¾Ð±Ð½Ð¾Ð²Ñването, дори когато индекÑÑŠÑ‚ трÑбва да Ñе обнови" msgid "refresh: ignore submodules" msgstr "подмодулите да Ñе игнорират при обновÑването" @@ -14283,8 +14366,8 @@ msgstr "" "git update-ref [ОПЦИЯ…] ИМЕ_ÐÐ_УКÐЗÐТЕЛ ÐОВ_ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ " "[СТÐÐ _ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ]" -msgid "git update-ref [<options>] --stdin [-z]" -msgstr "git update-ref [ОПЦИЯ…] --stdin [-z]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [ОПЦИЯ…] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "изтриване на указателÑ" @@ -14300,6 +14383,9 @@ msgstr "" msgid "read updates from stdin" msgstr "изчитане на указателите от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´" +msgid "batch reference updates" +msgstr "пакетно обновÑване на указатели" + msgid "update the info files from scratch" msgstr "обновÑване на информационните файлове от нулата" @@ -14458,7 +14544,7 @@ msgstr "„%s“ не може да Ñе изчиÑти в „%s“" #, c-format msgid "could not create directory of '%s'" -msgstr "директориÑта „%s“ не може да бъде Ñъздадена" +msgstr "директориÑта „%s“ не може да Ñе Ñъздаде" msgid "initializing" msgstr "инициализациÑ" @@ -14616,8 +14702,7 @@ msgstr "" #, c-format msgid "validation failed, cannot move working tree: %s" -msgstr "" -"проверките Ñа неуÑпешни, работното дърво не може да бъде премеÑтено: %s" +msgstr "проверките Ñа неуÑпешни, работното дърво не може да Ñе премеÑти: %s" #, c-format msgid "failed to move '%s' to '%s'" @@ -14659,7 +14744,7 @@ msgstr "" #, c-format msgid "validation failed, cannot remove working tree: %s" -msgstr "проверките Ñа неуÑпешни, работното дърво не може да бъде изтрито: %s" +msgstr "проверките Ñа неуÑпешни, работното дърво не може да Ñе изтрие: %s" #, c-format msgid "repair: %s: %s" @@ -14792,7 +14877,7 @@ msgid "unable to dup bundle descriptor" msgstr "неуÑпешно дублиране на деÑкриптора на пратката Ñ â€ždup“" msgid "Could not spawn pack-objects" -msgstr "Командата „git pack-objects“ не може да бъде Ñтартирана" +msgstr "Командата „git pack-objects“ не може да Ñе Ñтартира" msgid "pack-objects died" msgstr "Командата „git pack-objects“ не завърши уÑпешно" @@ -14815,7 +14900,7 @@ msgstr "Създаването на празна пратка е невъзмоР#, c-format msgid "cannot create '%s'" -msgstr "файлът „%s“ не може да бъде Ñъздаден" +msgstr "файлът „%s“ не може да Ñе Ñъздаде" msgid "index-pack died" msgstr "командата „git index-pack“ не завърши уÑпешно" @@ -15001,6 +15086,9 @@ msgstr "СравнÑване на файлове от работното дърРmsgid "Compare a tree to the working tree or index" msgstr "СравнÑване на обекти-дърво Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð½Ð¾Ñ‚Ð¾ дърво и индекÑа" +msgid "Compare the content and mode of provided blob pairs" +msgstr "СравнÑване на Ñъдържанието и режимите на двойките обекти-BLOB" + msgid "Compares the content and mode of blobs found via two tree objects" msgstr "" "СравнÑване на Ñъдържанието и права̀та за доÑтъп на обектите-BLOB чрез два " @@ -15543,7 +15631,7 @@ msgstr "" #, c-format msgid "could not find commit %s" -msgstr "подаването „%s“ не може да бъде открито" +msgstr "подаването „%s“ липÑва" msgid "commit-graph requires overflow generation data but has none" msgstr "" @@ -15603,7 +15691,7 @@ msgstr "" "правилниÑÑ‚ брой на идентификаторите в оÑÐ½Ð¾Ð²Ð½Ð¸Ñ Ð³Ñ€Ð°Ñ„ не може да Ñе запише" msgid "unable to create temporary graph layer" -msgstr "не може да бъде Ñъздаден временен Ñлой за гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта" +msgstr "не може да Ñе Ñъздаде временен Ñлой за гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта" #, c-format msgid "unable to adjust shared permissions for '%s'" @@ -15619,10 +15707,10 @@ msgid "unable to open commit-graph chain file" msgstr "файлът Ñ Ð²ÐµÑ€Ð¸Ð³Ð°Ñ‚Ð° на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да Ñе отвори" msgid "failed to rename base commit-graph file" -msgstr "оÑновниÑÑ‚ файл на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да бъде преименуван" +msgstr "оÑновниÑÑ‚ файл на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да Ñе преименува" msgid "failed to rename temporary commit-graph file" -msgstr "временниÑÑ‚ файл на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да бъде преименуван" +msgstr "временниÑÑ‚ файл на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да Ñе преименува" #, c-format msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits" @@ -15723,7 +15811,7 @@ msgstr "Проверка на подаваниÑта в гра̀фа" #, c-format msgid "could not parse commit %s" -msgstr "подаването „%s“ не може да бъде анализирано" +msgstr "подаването „%s“ не може да Ñе анализира" #, c-format msgid "%s %s is not a commit!" @@ -15892,7 +15980,7 @@ msgstr "неуÑпешно изпълнение на closedir(„%s“)" #, c-format msgid "[GLE %ld] unable to open for read '%ls'" msgstr "" -"файлът „%2$ls“ не може да бъде отворен за четене [поÑледна грешка в нишката: " +"файлът „%2$ls“ не може да Ñе отвори за четене [поÑледна грешка в нишката: " "GLE=%1$ld]" #, c-format @@ -15903,11 +15991,11 @@ msgstr "" #, c-format msgid "failed to copy SID (%ld)" -msgstr "идентификаторът за ÑигурноÑÑ‚ (SID=%ld) не може да бъде копиран" +msgstr "идентификаторът за ÑигурноÑÑ‚ (SID=%ld) не може да Ñе копира" #, c-format msgid "failed to get owner for '%s' (%ld)" -msgstr "притежателÑÑ‚ на „%s“ (%ld) не може да бъде получен" +msgstr "притежателÑÑ‚ на „%s“ (%ld) не може да Ñе получи" msgid "memory exhausted" msgstr "паметта е изчерпана" @@ -15967,10 +16055,10 @@ msgid "No previous regular expression" msgstr "ÐÑма предхождащ регулÑрен израз" msgid "could not send IPC command" -msgstr "командата за ÐºÐ¾Ð¼ÑƒÐ½Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ процеÑи не може да бъде пратена" +msgstr "командата за ÐºÐ¾Ð¼ÑƒÐ½Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ процеÑи не може да Ñе прати" msgid "could not read IPC response" -msgstr "отговорът за комуникациÑта между процеÑи не може да бъде прочетен" +msgstr "отговорът за комуникациÑта между процеÑи не може да Ñе прочете" #, c-format msgid "could not start accept_thread '%s'" @@ -16021,7 +16109,7 @@ msgstr "" #, c-format msgid "could not expand include path '%s'" -msgstr "пътÑÑ‚ за вмъкване „%s“не може да бъде разширен" +msgstr "пътÑÑ‚ за вмъкване „%s“ не може да Ñе разшири" msgid "relative config includes must come from files" msgstr "отноÑителните Ð²Ð¼ÑŠÐºÐ²Ð°Ð½Ð¸Ñ Ð½Ð° конфигурации трÑбва да идват от файлове" @@ -16163,7 +16251,7 @@ msgstr "неправилна булева ÑтойноÑÑ‚ „%s“ за „%s†#, c-format msgid "failed to expand user dir in: '%s'" -msgstr "домашната папка на Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ Ð½Ðµ може да бъде открита: „%s“" +msgstr "домашната папка на Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ Ð»Ð¸Ð¿Ñва: „%s“" #, c-format msgid "'%s' for '%s' is not a valid timestamp" @@ -16222,7 +16310,7 @@ msgstr "указателÑÑ‚ „%s“ не Ñочи към обект-BLOB" #, c-format msgid "unable to resolve config blob '%s'" -msgstr "обектът-BLOB „%s“ Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¸ не може да бъде открит" +msgstr "обектът-BLOB „%s“ Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¸ липÑва" msgid "unable to parse command-line config" msgstr "неправилни наÑтройки от ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¸Ñ Ñ€ÐµÐ´" @@ -16258,7 +16346,7 @@ msgstr "зададени Ñа нÑколко ÑтойноÑти за „%s“" #, c-format msgid "failed to write new configuration file %s" -msgstr "новиÑÑ‚ конфигурационен файл „%s“ не може да бъде запазен" +msgstr "новиÑÑ‚ конфигурационен файл „%s“ не може да Ñе запази" #, c-format msgid "no multi-line comment allowed: '%s'" @@ -16266,7 +16354,7 @@ msgstr "коментари на повече от един ред не Ñа по #, c-format msgid "could not lock config file %s" -msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде заключен" +msgstr "конфигурационниÑÑ‚ файл „%s“ не може да Ñе заключи" #, c-format msgid "opening %s" @@ -16290,7 +16378,7 @@ msgstr "неуÑпешна ÑмÑна на права̀ Ñ â€žchmod“ Ð²ÑŠÑ€Ñ…Ñ #, c-format msgid "could not write config file %s" -msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде запиÑан" +msgstr "конфигурационниÑÑ‚ файл „%s“ не може да Ñе запише" #, c-format msgid "could not set '%s' to '%s'" @@ -16462,13 +16550,13 @@ msgid "unable to fork" msgstr "неуÑпешно Ñъздаване на процеÑ" msgid "Could not run 'git rev-list'" -msgstr "Командата „git rev-list“ не може да бъде изпълнена." +msgstr "Командата „git rev-list“ не може да Ñе изпълни." msgid "failed write to rev-list" msgstr "неуÑпешен Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° ÑпиÑъка Ñ Ð²ÐµÑ€Ñиите" msgid "failed to close rev-list's stdin" -msgstr "ÑтандартниÑÑ‚ вход на ÑпиÑъка Ñ Ð²ÐµÑ€Ñиите не може да бъде затворен" +msgstr "ÑтандартниÑÑ‚ вход на ÑпиÑъка Ñ Ð²ÐµÑ€Ñиите не може да Ñе затвори" #, c-format msgid "illegal crlf_action %d" @@ -16542,7 +16630,7 @@ msgstr "неуÑпешно Ñъздаване на Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð·Ð° външеР#, c-format msgid "cannot feed the input to external filter '%s'" -msgstr "входът не може да бъде подаден на Ð²ÑŠÐ½ÑˆÐ½Ð¸Ñ Ñ„Ð¸Ð»Ñ‚ÑŠÑ€ „%s“" +msgstr "входът не може да Ñе подаде на Ð²ÑŠÐ½ÑˆÐ½Ð¸Ñ Ñ„Ð¸Ð»Ñ‚ÑŠÑ€ „%s“" #, c-format msgid "external filter '%s' failed %d" @@ -16689,7 +16777,7 @@ msgstr "неправилен обект-дърво: %s" #, c-format msgid "failed to load island regex for '%s': %s" -msgstr "регулÑрниÑÑ‚ израз на групата за „%s“, не може да бъде зареден: „%s“" +msgstr "регулÑрниÑÑ‚ израз на групата за „%s“, не може да Ñе зареди: „%s“" #, c-format msgid "island regex from config has too many capture groups (max=%d)" @@ -16711,7 +16799,7 @@ msgstr "директориÑта „%s“ липÑва и не може да ÑÐ #, c-format msgid "could not open directory '%s'" -msgstr "директориÑта „%s“ не може да бъде отворена" +msgstr "директориÑта „%s“ не може да Ñе отвори" #, c-format msgid "skipping '%s', which is neither file nor directory" @@ -16722,7 +16810,7 @@ msgstr "ÑтандартниÑÑ‚ изход не може да Ñе дублир #, c-format msgid "could not add directory '%s' to archiver" -msgstr "директориÑта „%s“ не може да бъде добавена към архива" +msgstr "директориÑта „%s“ не може да Ñе добави към архива" msgid "failed to write archive" msgstr "неуÑпешен Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° архива" @@ -16731,7 +16819,7 @@ msgid "--merge-base does not work with ranges" msgstr "опциÑта „--merge-base“ не работи Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð¸" msgid "unable to get HEAD" -msgstr "УказателÑÑ‚ „HEAD“ не може да бъде получен" +msgstr "УказателÑÑ‚ „HEAD“ не може да Ñе получи" msgid "no merge base found" msgstr "липÑва база за Ñливане" @@ -16914,7 +17002,7 @@ msgid "generate diffs with <n> lines context" msgstr "файловете Ñ Ñ€Ð°Ð·Ð»Ð¸ÐºÐ¸ да Ñа Ñ ÐºÐ¾Ð½Ñ‚ÐµÐºÑÑ‚ Ñ Ñ‚Ð°ÐºÑŠÐ² БРОЙ редове" msgid "generate the diff in raw format" -msgstr "файловете Ñ Ñ€Ð°Ð·Ð»Ð¸ÐºÐ¸ да Ñа в Ñуров формат" +msgstr "файловете Ñ Ñ€Ð°Ð·Ð»Ð¸ÐºÐ¸ да Ñа в необработен формат" msgid "synonym for '-p --raw'" msgstr "пÑевдоним на „-p --raw“" @@ -17266,7 +17354,7 @@ msgstr "задайте променливата „%s“ да е поне %d и #, c-format msgid "failed to read orderfile '%s'" -msgstr "файлът Ñ Ð¿Ð¾Ð´Ñ€ÐµÐ´Ð±Ð°Ñ‚Ð° на ÑъответÑтвиÑта „%s“ не може да бъде прочетен" +msgstr "файлът Ñ Ð¿Ð¾Ð´Ñ€ÐµÐ´Ð±Ð°Ñ‚Ð° на ÑъответÑтвиÑта „%s“ не може да Ñе прочете" msgid "Performing inexact rename detection" msgstr "ТърÑене на Ð¿Ñ€ÐµÐ¸Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð¸Ñ Ð½Ð° обекти Ñъчетани Ñ Ð¿Ñ€Ð¾Ð¼ÐµÌ€Ð½Ð¸" @@ -17311,7 +17399,7 @@ msgid "" "No directory name could be guessed.\n" "Please specify a directory on the command line" msgstr "" -"Името на директориÑта не може да бъде отгатнато.\n" +"Името на директориÑта не може да Ñе отгатне.\n" "Задайте директориÑта изрично на ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¸Ñ Ñ€ÐµÐ´" #, c-format @@ -17523,7 +17611,7 @@ msgstr "грешка при обработка на потвърждениÑта #. #, c-format msgid "expected packfile to be sent after '%s'" -msgstr "очаква Ñе пакетниÑÑ‚ файл да бъде изпратен Ñлед „%s“" +msgstr "очаква Ñе пакетниÑÑ‚ файл да Ñе изпрати Ñлед „%s“" #. TRANSLATORS: The parameter will be 'ready', a protocol #. keyword. @@ -17552,7 +17640,7 @@ msgid "git fetch-pack: expected response end packet" msgstr "git fetch-pack: очаква Ñе пакет за край на отговора" msgid "no matching remote head" -msgstr "не може да бъде открит подходÑщ връх от отдалеченото хранилище" +msgstr "липÑва подходÑщ връх от отдалеченото хранилище" msgid "unexpected 'ready' from remote" msgstr "неочаквано ÑÑŠÑтоÑние за готовноÑÑ‚ от отдалечено хранилище" @@ -17754,7 +17842,7 @@ msgstr "лош/неÑъвмеÑтим Ð¿Ð¾Ð´Ð¿Ð¸Ñ â€ž%s“" #, c-format msgid "failed to get the ssh fingerprint for key '%s'" -msgstr "отпечатъкът по ssh на ключа „%s“ не може да бъде получен" +msgstr "отпечатъкът по ssh на ключа „%s“ не може да Ñе получи" msgid "" "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured" @@ -17818,7 +17906,7 @@ msgstr "" #, c-format msgid "'%s': unable to read %s" -msgstr "„%s“: файлът Ñочен от „%s“ не може да бъде прочетен" +msgstr "„%s“: файлът Ñочен от „%s“ не може да Ñе прочете" #, c-format msgid "'%s': short read" @@ -17903,7 +17991,7 @@ msgid "" "able to execute it. Maybe git-%s is broken?" msgstr "" "Изглежда, че „%s“ е команда на git, но Ñ‚Ñ Ð½Ðµ може да\n" -"бъде изпълнена. ВероÑтно пакетът „git-%s“ е повреден." +"Ñе изпълни. ВероÑтно пакетът „git-%s“ е повреден." #, c-format msgid "git: '%s' is not a git command. See 'git --help'." @@ -17995,6 +18083,10 @@ msgid "Unknown value for http.proactiveauth" msgstr "Ðепозната ÑтойноÑÑ‚ за „http.proactiveauth“" #, c-format +msgid "failed to parse %s" +msgstr "„%s“ не може да Ñе анализира" + +#, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Ðеподдържана Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° SSL „%s“. Поддържат Ñе:" @@ -18064,15 +18156,14 @@ msgstr "липÑва Ð°Ð´Ñ€ÐµÑ Ð·Ð° е-поща, а автоматичното #, c-format msgid "unable to auto-detect email address (got '%s')" msgstr "" -"адреÑÑŠÑ‚ за е-поща не може да бъде отгатнат (най-доброто предположение бе " -"„%s“)" +"адреÑÑŠÑ‚ за е-поща не може да Ñе отгатне (най-доброто предположение бе „%s“)" msgid "no name was given and auto-detection is disabled" msgstr "липÑва име, а автоматичното отгатване е изключено" #, c-format msgid "unable to auto-detect name (got '%s')" -msgstr "името не може да бъде отгатнато (най-доброто предположение бе „%s“)" +msgstr "името не може да Ñе отгатне (най-доброто предположение бе „%s“)" #, c-format msgid "empty ident name (for <%s>) not allowed" @@ -18148,7 +18239,7 @@ msgid "" "may have crashed in this repository earlier:\n" "remove the file manually to continue." msgstr "" -"Файлът-ключалка „%s.lock“ не може да бъде Ñъздаден: %s\n" +"Файлът-ключалка „%s.lock“ не може да Ñе Ñъздаде: %s\n" "\n" "Изглежда, че и друг Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð° git е пуÑнат в това хранилище, напр.\n" "редактор, Ñтартиран Ñ â€žgit commit“. Уверете Ñе, че вÑички подобни\n" @@ -18158,10 +18249,10 @@ msgstr "" #, c-format msgid "Unable to create '%s.lock': %s" -msgstr "Файлът-ключалка „%s.lock“ не може да бъде Ñъздаден: %s" +msgstr "Файлът-ключалка „%s.lock“ не може да Ñе Ñъздаде: %s" msgid "unable to create temporary object directory" -msgstr "не може да бъде Ñъздадена Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° временни обекти" +msgstr "не може да Ñе Ñъздаде Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° временни обекти" #, c-format msgid "could not write loose object index %s" @@ -18190,6 +18281,10 @@ msgid "invalid marker-size '%s', expecting an integer" msgstr "неправилен размер на маркер: „%s“, изиÑква Ñе цÑло чиÑло" #, c-format +msgid "Could not parse object '%s'" +msgstr "ÐеуÑпешен анализ на обекта „%s“" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (не е изтеглен)" @@ -18208,7 +18303,7 @@ msgstr "ГРЕШКÐ: неуÑпешно Ñливане на подмодула #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" -"Подмодулът „%s“ не може да бъде ÑлÑÑ‚ (базата за Ñливане не предшеÑтва " +"Подмодулът „%s“ не може да Ñе Ñлее (базата за Ñливане не предшеÑтва " "подаваниÑта)" #, c-format @@ -18433,292 +18528,23 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "неуÑпешно Ñъбиране на информациÑта за Ñливането на „%s“, „%s“ и „%s“" -msgid "(bad commit)\n" -msgstr "(лошо подаване)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "" -"неуÑпешно изпълнение на „add_cacheinfo“ за Ð¿ÑŠÑ‚Ñ â€ž%s“. Сливането е " -"преуÑтановено." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "" -"неуÑпешно изпълнение на „add_cacheinfo“ за обновÑването на Ð¿ÑŠÑ‚Ñ â€ž%s“. " -"Сливането е преуÑтановено." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "грешка при Ñъздаването на Ð¿ÑŠÑ‚Ñ â€ž%s“%s" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Изтриване на „%s“, за да Ñе оÑвободи мÑÑто за поддиректориÑ\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": възможно е да има конфликт директориÑ/файл." - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "" -"преуÑтановÑване на дейÑтвието, за да не Ñе изтрие неÑледениÑÑ‚ файл „%s“" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "обектът „%s“ (%s) Ñе очакваше да е BLOB, а не е" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "„%s“ не може да Ñе отвори: %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "неуÑпешно Ñъздаване на Ñимволната връзка „%s“: %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "" -"не е ÑÑно какво да Ñе прави Ñ Ð¾Ð±ÐµÐºÑ‚Ð° „%2$s“ (%3$s) Ñ Ð¿Ñ€Ð°Ð²Ð°Ì€ за доÑтъп „%1$06o“" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (хранилището е Ñ Ð³Ñ€ÐµÑˆÐºÐ¸)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "Превъртане на подмодула „%s“ до Ñледното подаване:" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "Превъртане на подмодула „%s“" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"ÐеуÑпешно Ñливане на подмодула „%s“ (липÑва Ñливането, което Ñе предшеÑтва " -"от подаваниÑта)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (не е превъртане)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "" -"Открито е Ñливане, което може да решава проблема ÑÑŠÑ Ñливането на " -"подмодула:\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" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"Това приема предложеното.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (открити Ñа множеÑтво ÑливаниÑ)" - -msgid "failed to execute internal merge" -msgstr "неуÑпешно вътрешно Ñливане" - -#, c-format -msgid "unable to add %s to database" -msgstr "„%s“ не може да Ñе добави в базата от данни" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "Грешка: за да не Ñе изтрие неÑледениÑÑ‚ файл „%s“, Ñе запиÑва в „%s“." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"КОÐФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ в %s. ВерÑÐ¸Ñ %s на „%s“ " -"е оÑтавена в дървото." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"КОÐФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ е преименуван на „%s“ в " -"%s. ВерÑÐ¸Ñ %s на „%s“ е оÑтавена в дървото." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"КОÐФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ в %s. ВерÑÐ¸Ñ %s на „%s“ " -"е оÑтавена в дървото: %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"КОÐФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ е преименуван на „%s“ в " -"%s. ВерÑÐ¸Ñ %s на „%s“ е оÑтавена в дървото: %s." - -msgid "rename" -msgstr "преименуване" - -msgid "renamed" -msgstr "преименуван" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "ПреуÑтановÑване на дейÑтвието, за да не Ñе изгуби променениÑÑ‚ „%s“" - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "" -"Отказ да Ñе загуби неÑледениÑÑ‚ файл „%s“, защото е на мÑÑто, където пречи." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"КОÐФЛИКТ (преименуване/добавÑне): „%s“ е преименуван на „%s“ в клон „%s“, а " -"„%s“ е добавен в „%s“" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "„%s“ е Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð² „%s“, затова Ñе Ð´Ð¾Ð±Ð°Ð²Ñ ÐºÐ°Ñ‚Ð¾ „%s“" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "" -"ПреуÑтановÑване на дейÑтвието, за да не Ñе изгуби неÑледениÑÑ‚ файл „%s“. " -"ВмеÑто него Ñе Ð´Ð¾Ð±Ð°Ð²Ñ â€ž%s“" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"КОÐФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " -"„%s“, а „%s“ е преименуван на „%s“ в „%s“/%s." - -msgid " (left unresolved)" -msgstr " (некоригиран конфликт)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"КОÐФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " -"„%s“, а „%s“ е преименуван на „%s“ в „%s“" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"КОÐФЛИКТ (раздвоÑване при преименуване на директориÑ): Ðе е ÑÑно къде да Ñе " -"поÑтави „%s“, защото нÑколко нови директории поделÑÑ‚ Ñъдържанието на " -"Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ â€ž%s“, като Ð½Ð¸ÐºÐ¾Ñ Ð½Ðµ Ñъдържа мнозинÑтво от файловете Ñ." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"КОÐФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " -"„%s“, а „%s“ е преименуван на „%s“ в „%s“" - -#, c-format -msgid "cannot read object %s" -msgstr "обектът „%s“ не може да Ñе прочете" - -#, c-format -msgid "object %s is not a blob" -msgstr "обектът „%s“ не е BLOB" - -msgid "modify" -msgstr "промÑна" - -msgid "modified" -msgstr "променен" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "ПреÑкачане на „%s“ (ÑлетиÑÑ‚ резултат е идентичен ÑÑŠÑ ÑегашниÑ)" - -#, c-format -msgid "Adding as %s instead" -msgstr "ДобавÑне като „%s“" - -#, c-format -msgid "Removing %s" -msgstr "Изтриване на „%s“" - -msgid "file/directory" -msgstr "файл/директориÑ" - -msgid "directory/file" -msgstr "директориÑ/файл" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"КОÐФЛИКТ (%s): СъщеÑтвува Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ð° име „%s“ в „%s“. ДобавÑне на „%s“ " -"като „%s“" - -#, c-format -msgid "Adding %s" -msgstr "ДобавÑне на „%s“" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "КОÐФЛИКТ (добавÑне/добавÑне): Конфликт при Ñливане на „%s“" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "неуÑпешно Ñливане на дърветата „%s“ и „%s“" - -msgid "Merging:" -msgstr "Сливане:" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "открит е %u общ предшеÑтвеник:" -msgstr[1] "открити Ñа %u общи предшеÑтвеници:" - -msgid "merge returned no commit" -msgstr "Ñливането не върна подаване" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "ÐеуÑпешен анализ на обекта „%s“" - msgid "failed to read the cache" -msgstr "кешът не може да бъде прочетен" +msgstr "кешът не може да Ñе прочете" #, c-format msgid "failed to add packfile '%s'" -msgstr "пакетниÑÑ‚ файл „%s“ не може да бъде добавен" +msgstr "пакетниÑÑ‚ файл „%s“ не може да Ñе добави" #, c-format msgid "failed to open pack-index '%s'" -msgstr "индекÑÑŠÑ‚ за пакети „%s“ не може да бъде отворен" +msgstr "индекÑÑŠÑ‚ за пакети „%s“ не може да Ñе отвори" #, c-format msgid "failed to locate object %d in packfile" msgstr "обект %d в Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» липÑва" msgid "cannot store reverse index file" -msgstr "файлът за индекÑа не може да бъде Ñъхранен" +msgstr "файлът за индекÑа не може да Ñе Ñъхрани" #, c-format msgid "could not parse line: %s" @@ -18741,17 +18567,17 @@ msgstr "не може да Ñе Ñъздаде връзка „%s“, коÑто #, c-format msgid "failed to clear multi-pack-index at %s" -msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде изчиÑтен при „%s“" - -msgid "cannot write incremental MIDX with bitmap" -msgstr "" -"нараÑтващиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети Ñ Ð±Ð¸Ñ‚Ð¾Ð²Ð° маÑка не може да Ñе запише" +msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да Ñе изчиÑти при „%s“" msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "" "индекÑÑŠÑ‚ за множеÑтво пакети Ñе преÑкача, защото Ñумата за проверка не " "Ñъвпада" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "файлът Ñ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети „%s“ не може да Ñе зареди" + msgid "Adding packfiles to multi-pack-index" msgstr "ДобавÑне на пакетни файлове към Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети" @@ -18776,14 +18602,13 @@ msgid "no pack files to index." msgstr "нÑма пакетни файлове за индекÑиране" msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "" -"многопакетната битова маÑка без никакви обекти не може да бъде запазена" +msgstr "многопакетната битова маÑка без никакви обекти не може да Ñе запази" msgid "unable to create temporary MIDX layer" msgstr "не може да Ñе Ñъздаде временен Ñлой за индекÑа за множеÑтво пакети" msgid "could not write multi-pack bitmap" -msgstr "многопакетната битова маÑка не може да бъде запазена" +msgstr "многопакетната битова маÑка не може да Ñе запази" msgid "unable to open multi-pack-index chain file" msgstr "файлът Ñ Ð²ÐµÑ€Ð¸Ð³Ð°Ñ‚Ð° на гра̀фа Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта не може да Ñе отвори" @@ -18809,10 +18634,10 @@ msgid "cannot repack an incremental multi-pack-index" msgstr "нараÑтващиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети не може да Ñе препакетира" msgid "could not start pack-objects" -msgstr "командата „pack-objects“ не може да бъде Ñтартирана" +msgstr "командата „pack-objects“ не може да Ñе Ñтартира" msgid "could not finish pack-objects" -msgstr "командата „pack-objects“ не може да бъде завършена" +msgstr "командата „pack-objects“ не може да завърши" msgid "multi-pack-index OID fanout is of the wrong size" msgstr "" @@ -18929,8 +18754,7 @@ msgstr "" msgid "multi-pack-index file exists, but failed to parse" msgstr "" -"файлът Ñ Ð¸Ð½Ð´ÐµÐºÑа за множеÑтво пакети ÑъщеÑтвува, но не може да бъде " -"анализиран" +"файлът Ñ Ð¸Ð½Ð´ÐµÐºÑа за множеÑтво пакети ÑъщеÑтвува, но не може да Ñе анализира" msgid "incorrect checksum" msgstr "неправилна Ñума за проверка" @@ -18959,11 +18783,11 @@ msgstr "Проверка на отмеÑтването на обекти" #, c-format msgid "failed to load pack entry for oid[%d] = %s" -msgstr "запиÑÑŠÑ‚ в пакета за обекта oid[%d] = %s не може да бъде зареден" +msgstr "запиÑÑŠÑ‚ в пакета за обекта oid[%d] = %s не може да Ñе зареди" #, c-format msgid "failed to load pack-index for packfile %s" -msgstr "индекÑÑŠÑ‚ на пакета „%s“ не може да бъде зареден" +msgstr "индекÑÑŠÑ‚ на пакета „%s“ не може да Ñе зареди" #, c-format msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" @@ -19004,7 +18828,7 @@ msgstr "" msgid "Cannot commit uninitialized/unreferenced notes tree" msgstr "" -"Ðеинициализирано или нереферирано дърво за бележки не може да бъде подадено" +"Ðеинициализирано или нереферирано дърво за бележки не може да Ñе подаде" #, c-format msgid "Bad notes.rewriteMode value: '%s'" @@ -19043,68 +18867,6 @@ 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“" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "алтернативниÑÑ‚ път към обекти не може да бъде нормализиран: „%s“" - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "" -"%s: алтернативните хранилища за обекти Ñе пренебрегват поради прекалено " -"дълбоко влагане" - -msgid "unable to fdopen alternates lockfile" -msgstr "заключващиÑÑ‚ файл за алтернативите не може да Ñе отвори Ñ â€žfdopen“" - -msgid "unable to read alternates file" -msgstr "файлът Ñ Ð°Ð»Ñ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð¸Ñ‚Ðµ не може да бъде прочетен" - -msgid "unable to move new alternates file into place" -msgstr "новиÑÑ‚ файл Ñ Ð°Ð»Ñ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð¸Ñ‚Ðµ не може да бъде премеÑтен на мÑÑтото му" - -#, c-format -msgid "path '%s' does not exist" -msgstr "пътÑÑ‚ „%s“ не ÑъщеÑтвува." - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "вÑе още не Ñе поддържа еталонно хранилище „%s“ като Ñвързано." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "еталонното хранилище „%s“ не е локално" - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "еталонното хранилище „%s“ е плитко" - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "еталонното хранилище „%s“ е Ñ Ð¿Ñ€Ð¸Ñаждане" - -#, c-format -msgid "could not find object directory matching %s" -msgstr "директориÑта Ñ Ð¾Ð±ÐµÐºÑ‚Ð¸, коÑто Ð¾Ñ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° „%s“, не може да бъде открита" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "неправилен ред при анализа на алтернативните указатели: „%s“" - -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "" -"неуÑпешен опит за „mmap“ %<PRIuMAX>, което е над позволеното %<PRIuMAX>" - -#, c-format -msgid "mmap failed%s" -msgstr "неуÑпешно изпълнение на „mmap“%s" - -#, c-format msgid "object file %s is empty" msgstr "файлът Ñ Ð¾Ð±ÐµÐºÑ‚Ð¸Ñ‚Ðµ „%s“ е празен" @@ -19122,14 +18884,14 @@ msgstr "непакетираниÑÑ‚ обект „%s“ не може да Ñе #, c-format msgid "unable to parse %s header" -msgstr "заглавната чаÑÑ‚ на „%s“ не може да бъде анализирана" +msgstr "заглавната чаÑÑ‚ на „%s“ не може да Ñе анализира" msgid "invalid object type" msgstr "неправилен вид обект" #, c-format msgid "unable to unpack %s header" -msgstr "заглавната чаÑÑ‚ на „%s“ не може да бъде разпакетирана" +msgstr "заглавната чаÑÑ‚ на „%s“ не може да Ñе разпакетира" #, c-format msgid "header for %s too long, exceeds %d bytes" @@ -19140,20 +18902,8 @@ msgid "loose object %s (stored in %s) is corrupt" msgstr "непакетираниÑÑ‚ обект „%s“ (в „%s“) е повреден" #, c-format -msgid "replacement %s not found for %s" -msgstr "замеÑтителÑÑ‚ „%s“ на „%s“ не може да бъде открит" - -#, c-format -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 open %s" -msgstr "обектът „%s“ не може да бъде отворен" +msgstr "обектът „%s“ не може да Ñе отвори" #, c-format msgid "files '%s' and '%s' differ in contents" @@ -19161,11 +18911,11 @@ msgstr "Ñъдържанието на файловете „%s“ и „%s“ е #, c-format msgid "unable to write file %s" -msgstr "файлът „%s“ не може да бъде запиÑан" +msgstr "файлът „%s“ не може да Ñе запише" #, c-format msgid "unable to write repeatedly vanishing file %s" -msgstr "ÑмалÑващиÑÑ‚ Ñе файл „%s“ не може да бъде запиÑван" +msgstr "ÑмалÑващиÑÑ‚ Ñе файл „%s“ не може да Ñе запише" #, c-format msgid "unable to set permission to '%s'" @@ -19180,7 +18930,7 @@ msgstr "" "нÑма права̀ за добавÑне на обект към базата от данни на хранилището „%s“" msgid "unable to create temporary file" -msgstr "не може да бъде Ñъздаден временен файл" +msgstr "не може да Ñе Ñъздаде временен файл" msgid "unable to write loose object file" msgstr "грешка при запиÑа на файла Ñ Ð½ÐµÐ¿Ð°ÐºÐµÑ‚Ð¸Ñ€Ð°Ð½ обект" @@ -19211,7 +18961,7 @@ msgstr "неуÑпешно изпълнение на „deflateEnd“ върху #, c-format msgid "unable to create directory %s" -msgstr "директориÑта „%s“ не може да бъде Ñъздадена" +msgstr "директориÑта „%s“ не може да Ñе Ñъздаде" #, c-format msgid "cannot read object for %s" @@ -19245,10 +18995,6 @@ msgid "%s: unsupported file type" msgstr "неподдържан вид файл: „%s“" #, c-format -msgid "%s is not a valid '%s' object" -msgstr "„%s“ е неправилен обект от вид „%s“" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "неправилна контролна Ñума за „%s“ (трÑбва да е %s)" @@ -19258,15 +19004,20 @@ msgstr "неуÑпешно изпълнение на „mmap“ върху „%s #, c-format msgid "unable to unpack header of %s" -msgstr "заглавната чаÑÑ‚ на „%s“ не може да бъде разпакетирана" +msgstr "заглавната чаÑÑ‚ на „%s“ не може да Ñе разпакетира" #, c-format msgid "unable to parse header of %s" -msgstr "заглавната чаÑÑ‚ на „%s“ не може да бъде анализирана" +msgstr "заглавната чаÑÑ‚ на „%s“ не може да Ñе анализира" + +#, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "" +"заглавната чаÑÑ‚ „%s“ на %s не може да Ñе анализира, за да Ñе определи видът" #, c-format msgid "unable to unpack contents of %s" -msgstr "Ñъдържанието на „%s“ не може да бъде разпакетирано" +msgstr "Ñъдържанието не може да Ñе разпакетира: „%s“" #. TRANSLATORS: This is a line of ambiguous object #. output shown when we cannot look up or parse the @@ -19423,6 +19174,75 @@ msgid "invalid object name '%.*s'." msgstr "неправилно име на обект: „%.*s“" #, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "" +"директориÑта за обекти „%s“ не ÑъщеÑтвува, проверете „.git/objects/info/" +"alternates“" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "алтернативниÑÑ‚ път към обекти не може да Ñе нормализира: „%s“" + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "" +"%s: алтернативните хранилища за обекти Ñе пренебрегват поради прекалено " +"дълбоко влагане" + +msgid "unable to fdopen alternates lockfile" +msgstr "заключващиÑÑ‚ файл за алтернативите не може да Ñе отвори Ñ â€žfdopen“" + +msgid "unable to read alternates file" +msgstr "файлът Ñ Ð°Ð»Ñ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð¸Ñ‚Ðµ не може да Ñе прочете" + +msgid "unable to move new alternates file into place" +msgstr "новиÑÑ‚ файл Ñ Ð°Ð»Ñ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð¸Ñ‚Ðµ не може да Ñе премеÑти на мÑÑтото Ñи" + +#, c-format +msgid "path '%s' does not exist" +msgstr "пътÑÑ‚ „%s“ не ÑъщеÑтвува." + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "вÑе още не Ñе поддържа еталонно хранилище „%s“ като Ñвързано." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "еталонното хранилище „%s“ не е локално" + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "еталонното хранилище „%s“ е плитко" + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "еталонното хранилище „%s“ е Ñ Ð¿Ñ€Ð¸Ñаждане" + +#, c-format +msgid "could not find object directory matching %s" +msgstr "директориÑта Ñ Ð¾Ð±ÐµÐºÑ‚Ð¸, коÑто Ð¾Ñ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° „%s“, не може да Ñе открие" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "неправилен ред при анализа на алтернативните указатели: „%s“" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "замеÑтителÑÑ‚ „%s“ на „%s“ липÑва" + +#, c-format +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 "%s is not a valid '%s' object" +msgstr "„%s“ е неправилен обект от вид „%s“" + +#, c-format msgid "invalid object type \"%s\"" msgstr "неправилен вид обект: „%s“" @@ -19436,7 +19256,7 @@ msgstr "обектът „%s“ е непознат вид: %d" #, c-format msgid "unable to parse object: %s" -msgstr "обектът „%s“ не може да бъде анализиран" +msgstr "обектът „%s“ не може да Ñе анализира" #, c-format msgid "hash mismatch %s" @@ -19603,7 +19423,7 @@ msgstr "„%s“ липÑва в пакет „%s“ при отмеÑтване #, c-format msgid "unable to get disk usage of '%s'" -msgstr "използваното мÑÑто за Ñъхранение на „%s“ не може да бъде получено" +msgstr "използваното мÑÑто за Ñъхранение на „%s“ не може да Ñе получи" #, c-format msgid "bitmap file '%s' has invalid checksum" @@ -19736,6 +19556,14 @@ msgid "%s isn't available" msgstr "опциÑта „%s“ не е налична" #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "ÑтойноÑтта %s за „%s“ е извън диапазона [%<PRIdMAX>,%<PRIdMAX>]" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "„%s“ очаква цÑло чиÑло, евентуално ÑÑŠÑ ÑÑƒÑ„Ð¸ÐºÑ â€žk“/„m“/„g“" + +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "" "„%s“ очаква неотрицателно цÑло чиÑло, евентуално ÑÑŠÑ ÑÑƒÑ„Ð¸ÐºÑ â€žk“/„m“/„g“" @@ -19896,10 +19724,6 @@ msgid "bad boolean environment value '%s' for '%s'" msgstr "неправилна булева ÑтойноÑÑ‚ „%s“ за „%s“" #, c-format -msgid "failed to parse %s" -msgstr "„%s“ не може да бъде анализиран" - -#, c-format msgid "failed to walk children of tree %s: not found" msgstr "неуÑпешно обхождане на дъщерните елементи на дървото „%s“: то липÑва" @@ -20064,8 +19888,12 @@ msgid "could not fetch %s from promisor remote" msgstr "„%s“ не може да Ñе доÑтави от гарантиращото хранилище" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "има хранилище Ñ Ð¸Ð¼Ðµ „%s“, но адреÑÑŠÑ‚ му Ñочи към „%s“, а не към „%s“" +msgid "no or empty URL advertised for remote '%s'" +msgstr "липÑващ или празен Ð°Ð´Ñ€ÐµÑ Ð·Ð° отдалечено хранилище „%s“" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "има хранилище Ñ Ð¸Ð¼Ðµ „%s“, но адреÑÑŠÑ‚ му е „%s“, а не „%s“" #, c-format msgid "unknown '%s' value for '%s' config option" @@ -20088,7 +19916,7 @@ msgstr "Изтриване на повтарÑщите Ñе обекти" #, c-format msgid "failed to load pseudo-merge regex for %s: '%s'" msgstr "" -"регулÑрниÑÑ‚ израз за пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ð·Ð° „%s“, не може да бъде зареден: „%s“" +"регулÑрниÑÑ‚ израз за пÑевдо ÑÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ Ð·Ð° „%s“, не може да Ñе зареди: „%s“" #, c-format msgid "%s must be non-negative, using default" @@ -20154,7 +19982,7 @@ msgstr "" #, c-format msgid "could not parse commit '%s'" -msgstr "подаването „%s“ не може да бъде анализирано" +msgstr "подаването „%s“ не може да Ñе анализира" #, c-format msgid "" @@ -20173,7 +20001,7 @@ msgstr "неуÑпешно търÑене на разлика" #, c-format msgid "could not parse log for '%s'" -msgstr "журналът Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта на „%s“ не може да бъде анализиран" +msgstr "журналът Ñ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñта на „%s“ не може да Ñе анализира" #, c-format msgid "invalid extra cruft tip: '%s'" @@ -20185,7 +20013,7 @@ msgstr "допълнителните Ñкорошни обекти не може #, c-format msgid "will not add file alias '%s' ('%s' already exists in index)" msgstr "" -"нÑма да бъде добавен пÑевдоним за файл „%s“ („%s“ вече ÑъщеÑтвува в индекÑа)" +"нÑма да Ñе добави пÑевдоним за файл „%s“ („%s“ вече ÑъщеÑтвува в индекÑа)" msgid "cannot create an empty blob in the object database" msgstr "в базата от данни за обектите не може да Ñе Ñъздаде празен обект-BLOB" @@ -20198,7 +20026,7 @@ msgstr "" #, c-format msgid "unable to index file '%s'" -msgstr "файлът „%s“ не може да бъде индекÑиран" +msgstr "файлът „%s“ не може да Ñе индекÑира" #, c-format msgid "unable to add '%s' to index" @@ -20319,7 +20147,7 @@ msgid "cannot write split index for a sparse index" msgstr "не може да Ñе запише разделѐн, чаÑтичен индекÑ" msgid "failed to convert to a sparse-index" -msgstr "индекÑÑŠÑ‚ не може да бъде превърнат в чаÑтичен" +msgstr "индекÑÑŠÑ‚ не може да Ñе превърне в чаÑтичен" #, c-format msgid "unable to open git dir: %s" @@ -20438,7 +20266,7 @@ msgid "" "If you remove a line here THAT COMMIT WILL BE LOST.\n" msgstr "" "\n" -"Ðко изтриете ред, ÑъответÑтващото му подаване ще бъде ИЗТРИТО.\n" +"Ðко изтриете ред, ÑъответÑтващото му подаване ще Ñе ИЗТРИЕ.\n" msgid "" "\n" @@ -20460,7 +20288,7 @@ msgid "" "\n" msgstr "" "\n" -"Ðко изтриете вÑичко, пребазирането ще бъде преуÑтановено.\n" +"Ðко изтриете вÑичко, пребазирането ще Ñе преуÑтанови.\n" "\n" #, c-format @@ -20745,7 +20573,7 @@ msgstr "" #, c-format msgid "could not retrieve `%s`" -msgstr "„%s“ не може да бъде получен" +msgstr "„%s“ не може да Ñе получи" #, c-format msgid "invalid branch name: %s = %s" @@ -20812,7 +20640,7 @@ msgstr "невъзможно е едновременно да Ñе Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ #, c-format msgid "could not delete reference %s: %s" -msgstr "УказателÑÑ‚ „%s“ не може да бъде изтрит: %s" +msgstr "УказателÑÑ‚ „%s“ не може да Ñе изтрие: %s" #, c-format msgid "could not delete references: %s" @@ -20843,12 +20671,16 @@ msgstr "файлът Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» „%s“ не може да Ñе про #, c-format msgid "cannot open directory %s" -msgstr "директориÑта „%s“ не може да бъде отворена" +msgstr "директориÑта „%s“ не може да Ñе отвори" msgid "Checking references consistency" msgstr "Проверка на валидноÑтта на указателите" #, c-format +msgid "unable to open '%s'" +msgstr "„%s“ не може да Ñе отвори" + +#, c-format msgid "refname is dangerous: %s" msgstr "опаÑно име на указател: %s" @@ -20914,17 +20746,13 @@ msgstr "Ñтекът не може да Ñе Ñвие: %s" #, c-format msgid "refname %s not found" -msgstr "името на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€ž%s“ не може да бъде открито" +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“" - -#, c-format msgid "pattern '%s' has no '*'" msgstr "шаблонът „%s“ не Ñъдържа „*“" @@ -21003,13 +20831,12 @@ msgstr "толкова големи изтлаÑÐºÐ²Ð°Ð½Ð¸Ñ Ð½Ðµ може да #, c-format msgid "cannot deflate request; zlib deflate error %d" msgstr "" -"заÑвката не може да бъде декомпреÑирана, грешка от „zlib“ при " -"декомпреÑиране: %d" +"заÑвката не може да Ñе декомпреÑира, грешка от „zlib“ при декомпреÑиране: %d" #, c-format msgid "cannot deflate request; zlib end error %d" msgstr "" -"заÑвката не може да бъде декомпреÑирана; грешка от „zlib“ при завършване: %d<" +"заÑвката не може да Ñе декомпреÑира; грешка от „zlib“ при завършване: %d" #, c-format msgid "%d bytes of length header were received" @@ -21071,8 +20898,7 @@ msgid "" "If you cannot, please let us know why you still need to use it by\n" "sending an e-mail to <git@vger.kernel.org>." msgstr "" -"изчитането на отдалеченото хранилище от „%s/%s“ предÑтои да бъде " -"премахнато.\n" +"изчитането на отдалеченото хранилище от „%s/%s“ предÑтои да Ñе премахне.\n" "Ðко вÑе още ползвате директориÑта „remotes/“, препоръчваме да Ñ Ð¼Ð¸Ð³Ñ€Ð¸Ñ€Ð°Ñ‚Ðµ\n" "към ÑледÑщи директории на база наÑтройки чрез командата:\n" "\n" @@ -21244,7 +21070,7 @@ msgstr "проÑтото (simple) изтлаÑкване не ÑъответÑÑ‚ #, c-format msgid "couldn't find remote ref %s" -msgstr "отдалечениÑÑ‚ указател „%s“ не може да бъде открит" +msgstr "отдалечениÑÑ‚ указател „%s“ липÑва" #, c-format msgid "* Ignoring funny ref '%s' locally" @@ -21282,8 +21108,8 @@ msgstr " (публикувайте локалните промѐни чрез 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] "Клонът ви е Ñ %2$d подаване зад „%1$s“ и може да бъде превъртÑн.\n" -msgstr[1] "Клонът ви е Ñ %2$d Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð´ „%1$s“ и може да бъде превъртÑн.\n" +msgstr[0] "Клонът ви е Ñ %2$d подаване зад „%1$s“ и може да Ñе превърти.\n" +msgstr[1] "Клонът ви е Ñ %2$d Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð´ „%1$s“ и може да Ñе превърти.\n" msgid " (use \"git pull\" to update your local branch)\n" msgstr " (обновете Ð»Ð¾ÐºÐ°Ð»Ð½Ð¸Ñ Ñи клон чрез „git pull“)\n" @@ -21308,7 +21134,7 @@ msgstr " (Ñлейте Ð¾Ñ‚Ð´Ð°Ð»ÐµÑ‡ÐµÐ½Ð¸Ñ ÐºÐ»Ð¾Ð½ в Ð»Ð¾ÐºÐ°Ð»Ð½Ð¸Ñ Ñ‡Ñ€ #, c-format msgid "cannot parse expected object name '%s'" -msgstr "очакваното име на обект „%s“ не може да бъде анализирано" +msgstr "очакваното име на обект „%s“ не може да Ñе анализира" #, c-format msgid "cannot strip one component off url '%s'" @@ -21330,7 +21156,7 @@ msgid "corrupt MERGE_RR" msgstr "повреден „MERGE_RR“ (Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° коригиране на конфликт)" msgid "unable to write rerere record" -msgstr "приложеното коригиране на конфликт не може да бъде запиÑано" +msgstr "приложеното коригиране на конфликт не може да Ñе запише" #, c-format msgid "there were errors while writing '%s' (%s)" @@ -21400,7 +21226,7 @@ msgstr "не може да Ñе определи към какво да Ñочи #, c-format msgid "failed to find tree of %s" -msgstr "дървото, Ñочено от „%s“, не може да бъде открито" +msgstr "дървото, Ñочено от „%s“, не може да Ñе открие" #, c-format msgid "unsupported section for hidden refs: %s" @@ -21428,7 +21254,7 @@ msgstr "" #, c-format msgid "could not get commit for --ancestry-path argument %s" -msgstr "подаването „%s“ към опциÑта „--ancestry-path“ не може да бъде получено" +msgstr "подаването „%s“ към опциÑта „--ancestry-path“ не може да Ñе получи" msgid "--unpacked=<packfile> no longer supported" msgstr "опциÑта „--unpacked=ПÐКЕТЕÐ_ФÐЙЛ“ вече не Ñе поддържа" @@ -21483,11 +21309,11 @@ msgstr "Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ може да Ñе зачиÑли" msgid "could not set recommended config" msgstr "препоръчаните наÑтройки не може да Ñе зададат" -msgid "could not turn on maintenance" -msgstr "задачите по поддръжка не може да Ñе включат" +msgid "could not toggle maintenance" +msgstr "режимът на задачите по поддръжка не може да Ñе превключи" msgid "could not start the FSMonitor daemon" -msgstr "фоновиÑÑ‚ Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð° FSMonitor не може да бъде ÑпрÑн" +msgstr "фоновиÑÑ‚ Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð° FSMonitor не може да Ñе Ñпре" msgid "could not turn off maintenance" msgstr "задачите по поддръжка не може да Ñе изключат" @@ -21508,13 +21334,13 @@ msgid "failed to get default branch name" msgstr "неуÑпешно получаване на името на ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ ÐºÐ»Ð¾Ð½" msgid "failed to unregister repository" -msgstr "хранилището не може да бъде отчиÑлено" +msgstr "хранилището не може да Ñе отчиÑли" msgid "failed to stop the FSMonitor daemon" -msgstr "фоновиÑÑ‚ Ð¿Ñ€Ð¾Ñ†ÐµÑ FSMonitor не може да бъде ÑпрÑн" +msgstr "фоновиÑÑ‚ Ð¿Ñ€Ð¾Ñ†ÐµÑ FSMonitor не може да Ñе Ñпре" msgid "failed to delete enlistment directory" -msgstr "зачиÑлената Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ може да бъде изтрита" +msgstr "зачиÑлената Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ може да Ñе изтрие" msgid "branch to checkout after clone" msgstr "към кой клон да Ñе премине Ñлед клониране" @@ -21531,12 +21357,16 @@ msgstr "Ñъздаване на хранилище в Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ â€žsr msgid "specify if tags should be fetched during clone" msgstr "указва дали етикетите да Ñе доÑтавÑÑ‚ при клониране" +msgid "specify if background maintenance should be enabled" +msgstr "дали на заден фон да Ñе изпълнÑват задачи за поддръжката" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch ОСÐОВЕÐ_КЛОÐ] [--full-clone]\n" -" [--[no-]src] [--[no-]tags] ÐДРЕС [ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" +" [--[no-]src] [--[no-]tags] [--[no-]maintenance] ÐДРЕС " +"[ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -21548,7 +21378,7 @@ msgstr "директориÑта „%s“ вече ÑъщеÑтвува" #, c-format msgid "failed to get default branch for '%s'" -msgstr "оÑновниÑÑ‚ клон на „%s“ не може да бъде получен" +msgstr "оÑновниÑÑ‚ клон на „%s“ не може да Ñе получи" #, c-format msgid "could not configure remote in '%s'" @@ -21574,19 +21404,33 @@ msgstr "scalar diagnose [ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" msgid "`scalar list` does not take arguments" msgstr "„scalar list“ не приема аргументи" -msgid "scalar register [<enlistment>]" -msgstr "scalar register [ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" msgid "reconfigure all registered enlistments" msgstr "пренаÑтройване на вÑички зачиÑлени директории" -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all|ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" +msgid "(enable|disable|keep)" +msgstr "(enable=включване|disable=изключване|keep=запазване)" + +msgid "signal how to adjust background maintenance" +msgstr "как да Ñе промени поддръжката на заден фон" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all|" +"ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ]" msgid "--all or <enlistment>, but not both" msgstr "опциÑта „--all“ и указването на зачиÑлена Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ Ñа ÑъвмеÑтими" #, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "непознат режим за „--maintenance“: „%s“" + +#, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "оÑтарÑлото Ñкаларно хранилище (scalar.repo) „%s“ не може да Ñе изтрие" @@ -21633,7 +21477,7 @@ msgid "scalar delete <enlistment>" msgstr "scalar delete ЗÐЧИСЛЕÐÐ_ДИРЕКТОРИЯ" msgid "refusing to delete current working directory" -msgstr "текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да бъде изтрита" +msgstr "текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да Ñе изтрие" msgid "include Git version" msgstr "включване и на верÑиÑта на git" @@ -21670,15 +21514,14 @@ msgstr "" #, c-format msgid "unable to parse remote unpack status: %s" -msgstr "" -"ÑÑŠÑтоÑнието от отдалеченото разпакетиране не може да бъде анализирано: %s" +msgstr "ÑÑŠÑтоÑнието от отдалеченото разпакетиране не може да Ñе анализира: %s" #, c-format msgid "remote unpack failed: %s" msgstr "неуÑпешно отдалечено разпакетиране: %s" msgid "failed to sign the push certificate" -msgstr "Ñертификатът за изтлаÑкване не може да бъде подпиÑан" +msgstr "Ñертификатът за изтлаÑкване не може да Ñе подпише" msgid "send-pack: unable to fork off fetch subprocess" msgstr "send-pack: неуÑпешно Ñъздаване на процеÑ" @@ -21712,7 +21555,7 @@ msgstr "неÑъщеÑтвуващ режим на изчиÑтване „%s“ #, c-format msgid "could not delete '%s'" -msgstr "„%s“ не може да бъде изтрит" +msgstr "„%s“ не може да Ñе изтрие" msgid "revert" msgstr "отмÑна" @@ -21826,13 +21669,13 @@ msgstr "подайте или Ñкатайте промѐните, за да Ð #. #, c-format msgid "%s: Unable to write new index file" -msgstr "%s: новиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде запазен" +msgstr "%s: новиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе запази" msgid "unable to update cache tree" -msgstr "кешът на обектите-дървета не може да бъде обновен" +msgstr "кешът на обектите-дървета не може да Ñе обнови" msgid "could not resolve HEAD commit" -msgstr "подаването, Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“, не може да бъде открито" +msgstr "подаването, Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“, липÑва" #, c-format msgid "no key present in '%.*s'" @@ -21840,7 +21683,7 @@ msgstr "в „%.*s“ нÑма ключове" #, c-format msgid "unable to dequote value of '%s'" -msgstr "цитирането на ÑтойноÑтта на „%s“ не може да бъде изчиÑтено" +msgstr "цитирането на ÑтойноÑтта на „%s“ не може да Ñе изчиÑти" msgid "'GIT_AUTHOR_NAME' already given" msgstr "наÑтройката за автор „GIT_AUTHOR_NAME“ вече е зададена" @@ -21949,15 +21792,13 @@ msgstr "" " git commit --amend --reset-author\n" msgid "couldn't look up newly created commit" -msgstr "току що Ñъздаденото подаване не може да бъде открито" +msgstr "току що Ñъздаденото подаване липÑва" msgid "could not parse newly created commit" -msgstr "току що Ñъздаденото подаване не може да бъде анализирано" +msgstr "току що Ñъздаденото подаване не може да Ñе анализира" msgid "unable to resolve HEAD after creating commit" -msgstr "" -"ÑÑŠÑтоÑнието Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ не може да бъде открито Ñлед " -"подаването" +msgstr "ÑÑŠÑтоÑнието Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ липÑва Ñлед подаването" msgid "detached HEAD" msgstr "неÑвързан връх „HEAD“" @@ -21966,18 +21807,18 @@ msgid " (root-commit)" msgstr " (начално подаване)" msgid "could not parse HEAD" -msgstr "указателÑÑ‚ „HEAD“ не може да бъде анализиран" +msgstr "указателÑÑ‚ „HEAD“ не може да Ñе анализира" #, c-format msgid "HEAD %s is not a commit!" msgstr "указателÑÑ‚ „HEAD“ „%s“ Ñочи към нещо, което не е подаване!" msgid "unable to parse commit author" -msgstr "авторът на подаването не може да бъде анализиран" +msgstr "авторът на подаването не може да Ñе анализира" #, c-format msgid "unable to read commit message from '%s'" -msgstr "Ñъобщението за подаване не може да бъде прочетено от „%s“" +msgstr "Ñъобщението за подаване не може да Ñе прочете от „%s“" #, c-format msgid "invalid author identity '%s'" @@ -21992,7 +21833,7 @@ msgstr "„%s“ не може да Ñе обнови" #, c-format msgid "could not parse parent commit %s" -msgstr "родителÑкото подаване „%s“ не може да бъде анализирано" +msgstr "родителÑкото подаване „%s“ не може да Ñе анализира" #, c-format msgid "unknown command: %d" @@ -22006,11 +21847,11 @@ msgid "This is the commit message #%d:" msgstr "Това е Ñъобщение при подаване â„–%d:" msgid "The 1st commit message will be skipped:" -msgstr "Съобщението при подаване â„–1 ще бъде преÑкочено:" +msgstr "Съобщението при подаване â„–1 ще Ñе преÑкочи:" #, c-format msgid "The commit message #%d will be skipped:" -msgstr "Съобщението при подаване â„–%d ще бъде преÑкочено:" +msgstr "Съобщението при подаване â„–%d ще Ñе преÑкочи:" #, c-format msgid "This is a combination of %d commits." @@ -22027,12 +21868,11 @@ msgid "could not read HEAD" msgstr "указателÑÑ‚ „HEAD“ не може да Ñе прочете" msgid "could not read HEAD's commit message" -msgstr "" -"Ñъобщението за подаване към ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ не може да бъде прочетено: %s" +msgstr "Ñъобщението за подаване към ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ не може да Ñе прочете: %s" #, c-format msgid "could not read commit message of %s" -msgstr "Ñъобщението за подаване към „%s“ не може да бъде прочетено" +msgstr "Ñъобщението за подаване към „%s“ не може да Ñе прочете" msgid "your index file is unmerged." msgstr "индекÑÑŠÑ‚ не е ÑлÑÑ‚." @@ -22060,11 +21900,11 @@ msgstr "%s: неразпозната ÑтойноÑÑ‚ за родителÑÐºÐ¾Ñ #, c-format msgid "could not revert %s... %s" -msgstr "подаването „%s“… не може да бъде отменено: „%s“" +msgstr "подаването „%s“… не може да Ñе отменени: „%s“" #, c-format msgid "could not apply %s... %s" -msgstr "подаването „%s“… не може да бъде приложено: „%s“" +msgstr "подаването „%s“… не може да Ñе приложи: „%s“" #, c-format msgid "dropping %s %s -- patch contents already upstream\n" @@ -22211,24 +22051,23 @@ msgstr "използвайте „git cherry-pick (--continue|%s--abort|--quit)â #, c-format msgid "could not create sequencer directory '%s'" msgstr "" -"директориÑта за определÑнето на поÑледователноÑтта „%s“ не може да бъде " -"Ñъздадена" +"директориÑта за определÑнето на поÑледователноÑтта „%s“ не може да Ñе Ñъздаде" msgid "no cherry-pick or revert in progress" msgstr "" "в момента не Ñе извършва отбиране на Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ пребазиране на клона" msgid "cannot resolve HEAD" -msgstr "Подаването Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ не може да бъде открито" +msgstr "Подаването Ñочено от ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ липÑва" msgid "cannot abort from a branch yet to be born" msgstr "" -"дейÑтвието не може да бъде преуÑтановено, когато Ñте на клон, който тепърва " -"предÑтои да бъде Ñъздаден" +"дейÑтвието не може да Ñе преуÑтанови, когато Ñте на клон, който тепърва " +"предÑтои да Ñе Ñъздаде" #, c-format msgid "cannot read '%s': %s" -msgstr "„%s“ не може да бъде прочетен: %s" +msgstr "„%s“ не може да Ñе прочете: %s" msgid "unexpected end of file" msgstr "неочакван край на файл" @@ -22266,10 +22105,10 @@ msgstr "" " git %s --continue" msgid "cannot read HEAD" -msgstr "указателÑÑ‚ „HEAD“ не може да бъде прочетен" +msgstr "указателÑÑ‚ „HEAD“ не може да Ñе прочете" msgid "could not write commit message file" -msgstr "файлът ÑÑŠÑ Ñъобщението за подаване не може да бъде запиÑан" +msgstr "файлът ÑÑŠÑ Ñъобщението за подаване не може да Ñе запише" #, c-format msgid "" @@ -22291,7 +22130,7 @@ msgstr "" #, c-format msgid "Could not apply %s... %.*s" -msgstr "Подаването „%s“… не може да бъде приложено: „%.*s“" +msgstr "Подаването „%s“… не може да Ñе приложи: „%.*s“" #, c-format msgid "Could not merge %.*s" @@ -22340,7 +22179,7 @@ msgstr "неправилно име на етикет: „%.*s“" #, c-format msgid "could not resolve '%s'" -msgstr "„%s“ не може да бъде открит" +msgstr "„%s“ липÑва" msgid "writing fake root commit" msgstr "запазване на фалшиво начално подаване" @@ -22364,14 +22203,14 @@ msgstr "върху начално подаване не може да Ñе изР#, c-format msgid "could not get commit message of '%s'" -msgstr "Ñъобщението за подаване към „%s“ не може да бъде получено" +msgstr "Ñъобщението за подаване към „%s“ не може да Ñе получи" #, c-format msgid "could not even attempt to merge '%.*s'" msgstr "Ñливането на „%.*s“ не може даже да започне" msgid "merge: Unable to write new index file" -msgstr "Ñливане: новиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да бъде запазен" +msgstr "Ñливане: новиÑÑ‚ Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе запази" #, c-format msgid "" @@ -22405,7 +22244,7 @@ msgstr "Ðеочакван резултат при Ñкатаване: „%s“" #, c-format msgid "Could not create directory for '%s'" -msgstr "ДиректориÑта за „%s“ не може да бъде Ñъздадена" +msgstr "ДиректориÑта за „%s“ не може да Ñе Ñъздаде" #, c-format msgid "Created autostash: %s\n" @@ -22420,7 +22259,7 @@ msgstr "Ðвтоматично Ñкатаното е приложено.\n" #, c-format msgid "cannot store %s" -msgstr "„%s“ не може да бъде запазен" +msgstr "„%s“ не може да Ñе запази" #, c-format msgid "" @@ -22464,7 +22303,7 @@ msgid "" " git rebase --edit-todo\n" " git rebase --continue\n" msgstr "" -"Следната запланувана команда не може да бъде изпълнена:\n" +"Следната запланувана команда не може да Ñе изпълни:\n" "\n" " %.*s\n" "\n" @@ -22495,7 +22334,7 @@ msgstr "указателÑÑ‚ за „onto“ не може да Ñе Ð¿Ñ€Ð¾Ñ‡ÐµÑ #, c-format msgid "could not update HEAD to %s" -msgstr "„HEAD“ не може да бъде обновен до „%s“" +msgstr "„HEAD“ не може да Ñе обнови до „%s“" #, c-format msgid "Successfully rebased and updated %s.\n" @@ -22526,10 +22365,10 @@ msgstr "" #, c-format msgid "could not write file: '%s'" -msgstr "файлът „%s“ не може да бъде запиÑан" +msgstr "файлът „%s“ не може да Ñе запише" msgid "could not remove CHERRY_PICK_HEAD" -msgstr "указателÑÑ‚ „CHERRY_PICK_HEAD“ не може да бъде изтрит" +msgstr "указателÑÑ‚ „CHERRY_PICK_HEAD“ не може да Ñе изтрие" msgid "could not commit staged changes." msgstr "промѐните в индекÑа не може да бъдат подадени." @@ -22543,7 +22382,7 @@ msgid "%s: bad revision" msgstr "%s: неправилна верÑиÑ" msgid "can't revert as initial commit" -msgstr "първоначалното подаване не може да бъде отменено" +msgstr "първоначалното подаване не може да Ñе отмени" #, c-format msgid "skipped previously applied commit %s" @@ -22676,7 +22515,7 @@ msgstr "процеÑÑŠÑ‚ не може да Ñе върне към предишР#, c-format msgid "failed to stat '%*s%s%s'" -msgstr "не може да бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%*s%s%s“" +msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%*s%s%s“" #, c-format msgid "safe.directory '%s' not absolute" @@ -22695,7 +22534,7 @@ msgstr "" " git config --global --add safe.directory %s" msgid "Unable to read current working directory" -msgstr "Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ може да бъде прочетена" +msgstr "Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ може да Ñе прочете" #, c-format msgid "cannot change to '%s'" @@ -22743,11 +22582,11 @@ msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „st #, c-format msgid "cannot opendir '%s'" -msgstr "директориÑта „%s“ не може да бъде отворена" +msgstr "директориÑта „%s“ не може да Ñе отвори" #, c-format msgid "cannot readlink '%s'" -msgstr "връзката „%s“ не може да бъде прочетена" +msgstr "връзката „%s“ не може да Ñе прочете" #, c-format msgid "cannot symlink '%s' '%s'" @@ -22897,7 +22736,7 @@ msgstr "" #, c-format msgid "Could not update .gitmodules entry %s" -msgstr "ЗапиÑÑŠÑ‚ „%s“ във файла „.gitmodules“ не може да бъде променен" +msgstr "ЗапиÑÑŠÑ‚ „%s“ във файла „.gitmodules“ не може да Ñе промени" msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" msgstr "" @@ -22910,7 +22749,7 @@ msgstr "Във файла „.gitmodules“ липÑва раздел за Ð´Ð¸Ñ #, c-format msgid "Could not remove .gitmodules entry for %s" -msgstr "ЗапиÑÑŠÑ‚ „%s“ във файла „.gitmodules“ не може да бъде изтрит" +msgstr "ЗапиÑÑŠÑ‚ „%s“ във файла „.gitmodules“ не може да Ñе изтрие" msgid "staging updated .gitmodules failed" msgstr "неуÑпешно добавÑне на Ð¿Ñ€Ð¾Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð» „.gitmodules“ в индекÑа" @@ -22957,7 +22796,7 @@ msgstr "ИзтлаÑкване на подмодула „%s“\n" #, c-format msgid "Unable to push submodule '%s'\n" -msgstr "Подмодулът „%s“ не може да бъде изтлаÑкан\n" +msgstr "Подмодулът „%s“ не може да Ñе изтлаÑка\n" #, c-format msgid "Fetching submodule %s%s\n" @@ -22965,11 +22804,11 @@ msgstr "ДоÑтавÑне на подмодула „%s%s“\n" #, c-format msgid "Could not access submodule '%s'\n" -msgstr "Подмодулът „%s“ не може да бъде доÑтъпен\n" +msgstr "Подмодулът „%s“ не може да Ñе доÑтъпи\n" #, c-format msgid "Could not access submodule '%s' at commit %s\n" -msgstr "Подмодулът „%s“ не може да бъде доÑтъпен при подаване %s\n" +msgstr "Подмодулът „%s“ не може да Ñе доÑтъпи при подаване %s\n" #, c-format msgid "Fetching submodule %s%s at commit %s\n" @@ -23045,7 +22884,7 @@ msgstr "" #, c-format msgid "could not lookup name for submodule '%s'" -msgstr "името на подмодула „%s“ не може да бъде намерено" +msgstr "името на подмодула „%s“ не може да Ñе намери" #, c-format msgid "refusing to move '%s' into an existing git dir" @@ -23070,7 +22909,7 @@ msgstr "„ls-tree“ завърши Ñ Ð½ÐµÐ¾Ñ‡Ð°ÐºÐ²Ð°Ð½ изходен код #, c-format msgid "failed to lstat '%s'" -msgstr "не може да бъде получена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „lstat“ за „%s“" +msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „lstat“ за „%s“" msgid "no remote configured to get bundle URIs from" msgstr "не е наÑтроено отдалечено хранилище за ÑпиÑъците Ñ Ð°Ð´Ñ€ÐµÑи на пратки" @@ -23089,6 +22928,9 @@ msgstr "" "какъв брой запиÑи в кеша на обектите-дървета да Ñе отбележат като невалидни " "(Ñтандартно е 0)" +msgid "the number of objects to write" +msgstr "брой запиÑани обекти" + msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk ОПЦИЯ… -- ОПЦИЯ_ЗÐ_ВЕРСИИ…" @@ -23219,7 +23061,7 @@ msgstr "неуÑпешен пълен Ð·Ð°Ð¿Ð¸Ñ ÐºÑŠÐ¼ наÑрещната пР#, c-format msgid "unable to find remote helper for '%s'" -msgstr "наÑрещната помощна програма за „%s“ не може да бъде открита" +msgstr "наÑрещната помощна програма за „%s“ липÑва" msgid "can't dup helper output fd" msgstr "" @@ -23332,7 +23174,7 @@ msgid "" "Perhaps you should specify a branch.\n" msgstr "" "ÐÑма общи указатели, не Ñа указани никакви указатели —\n" -"нищо нÑма да бъде направено. Пробвайте да укажете клон.\n" +"нищо нÑма да Ñе направи. Пробвайте да укажете клон.\n" #, c-format msgid "unsupported object format '%s'" @@ -23379,7 +23221,7 @@ msgstr "Клонът „%s“ ще Ñледи „%s“ от „%s“\n" #, c-format msgid "could not read bundle '%s'" -msgstr "пратката на git „%s“ не може да бъде прочетена" +msgstr "пратката на git „%s“ не може да Ñе прочете" #, c-format msgid "transport: invalid depth option '%s'" @@ -23530,7 +23372,7 @@ msgid "" "Refusing to remove the current working directory:\n" "%s" msgstr "" -"Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да бъде изтрита:\n" +"Текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ñма да Ñе изтрие:\n" "%s" #, c-format @@ -23640,7 +23482,7 @@ msgid "" "Cannot update submodule:\n" "%s" msgstr "" -"Подмодулът не може да бъде обновен:\n" +"Подмодулът не може да Ñе обнови:\n" "„%s“" #, c-format @@ -23815,7 +23657,7 @@ msgstr "файлът „gitdir“ не ÑъщеÑтвува" #, c-format msgid "unable to read gitdir file (%s)" -msgstr "файлът „gitdir“ не може да бъде прочетен (%s)" +msgstr "файлът „gitdir“ не може да Ñе прочете (%s)" #, c-format msgid "short read (expected %<PRIuMAX> bytes, read %<PRIuMAX>)" @@ -23854,11 +23696,11 @@ msgstr "променливата на Ñредата „%s“ не може да #, c-format msgid "unable to create '%s'" -msgstr "пакетниÑÑ‚ файл „%s“ не може да бъде Ñъздаден" +msgstr "пакетниÑÑ‚ файл „%s“ не може да Ñе Ñъздаде" #, c-format msgid "could not open '%s' for reading and writing" -msgstr "„%s“ не може да бъде отворен и за четене, и за запиÑ" +msgstr "„%s“ не може да Ñе отвори и за четене, и за запиÑ" #, c-format msgid "unable to access '%s'" @@ -23870,6 +23712,15 @@ msgstr "текущата работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ðµ недоÑтъп msgid "unable to get random bytes" msgstr "не може да Ñе получат Ñлучайни байтове" +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "" +"неуÑпешен опит за „mmap“ %<PRIuMAX>, което е над позволеното %<PRIuMAX>" + +#, c-format +msgid "mmap failed%s" +msgstr "неуÑпешно изпълнение на „mmap“%s" + msgid "Unmerged paths:" msgstr "ÐеÑлети пътища:" @@ -24001,7 +23852,7 @@ msgid "" "Everything below it will be ignored." msgstr "" "Ðе променÑйте и не изтривайте Ð³Ð¾Ñ€Ð½Ð¸Ñ Ñ€ÐµÐ´.\n" -"Ð’Ñичко отдолу ще бъде изтрито." +"Ð’Ñичко отдолу ще Ñе изтрие." #, c-format msgid "" @@ -24639,8 +24490,15 @@ msgstr "" "използвайте опциÑта: „--smtp-debug“." #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook промени „Message-ID“ да е: %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "ПРЕДУПРЕЖДЕÐИЕ: в отговора на Ñървъра липÑва „Message-ID“.\n" + +#, perl-format msgid "Failed to send %s\n" -msgstr "„%s“ не може да бъде изпратен\n" +msgstr "„%s“ не може да Ñе изпрати\n" #, perl-format msgid "Dry-Sent %s" @@ -24664,7 +24522,7 @@ msgstr "Резултат: уÑпех" #, perl-format msgid "can't open file %s" -msgstr "файлът „%s“ не може да бъде отворен" +msgstr "файлът „%s“ не може да Ñе отвори" #, perl-format msgid "(mbox) Adding cc: %s from line '%s'\n" @@ -24684,7 +24542,7 @@ msgstr "(Ñ‚Ñло) ДобавÑне на „Ñк: %s“ от ред „%s“\n" #, perl-format msgid "(%s) Could not execute '%s'" -msgstr "(%s) Ðе може да бъде Ñе изпълни „%s“" +msgstr "(%s) Ðе може да Ñе изпълни „%s“" #, perl-format msgid "(%s) Malformed output from '%s'" @@ -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: 2025-03-06 18:29+0100\n" -"PO-Revision-Date: 2025-03-07 17:28+0100\n" +"POT-Creation-Date: 2025-05-27 22:57+0000\n" +"PO-Revision-Date: 2025-05-31 18:38+0200\n" "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n" "Language-Team: German\n" "Language: de\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -"X-Generator: Poedit 3.4.4\n" +"X-Generator: Poedit 3.6\n" #, c-format msgid "Huh (%s)?" @@ -379,8 +379,8 @@ msgstr "Ergänzung im Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? " #, c-format msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " msgstr "" -"Diesen Patch-Block im Index und Arbeitsverzeichnis verwerfen [y,n,q,a," -"d%s,?]? " +"Diesen Patch-Block im Index und Arbeitsverzeichnis verwerfen " +"[y,n,q,a,d%s,?]? " msgid "" "y - discard this hunk from index and worktree\n" @@ -411,8 +411,8 @@ msgstr "Ergänzung auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d%s,?]? " #, c-format msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " msgstr "" -"Diesen Patch-Block auf Index und Arbeitsverzeichnis anwenden [y,n,q,a," -"d%s,?]? " +"Diesen Patch-Block auf Index und Arbeitsverzeichnis anwenden " +"[y,n,q,a,d%s,?]? " msgid "" "y - apply this hunk to index and worktree\n" @@ -1746,10 +1746,12 @@ msgstr "" msgid "not tracking: ambiguous information for ref '%s'" msgstr "kein Tracking: mehrdeutige Informationen für Referenz '%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 @@ -3096,11 +3098,11 @@ msgid "HEAD not found below refs/heads!" msgstr "HEAD wurde nicht unter \"refs/heads\" gefunden!" msgid "" -"branch with --recurse-submodules can only be used if submodule." -"propagateBranches is enabled" +"branch with --recurse-submodules can only be used if " +"submodule.propagateBranches is enabled" msgstr "" -"Branch mit --recurse-submodules kann nur genutzt werden, wenn submodule." -"propagateBranches aktiviert ist" +"Branch mit --recurse-submodules kann nur genutzt werden, wenn " +"submodule.propagateBranches aktiviert ist" msgid "--recurse-submodules can only be used to create branches" msgstr "--recurse-submodules kann nur genutzt werden, um Branches zu erstellen" @@ -3355,11 +3357,8 @@ msgstr "Nur eine Batch-Option erlaubt." msgid "git cat-file <type> <object>" msgstr "git cat-file <Typ> <Objekt>" -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e | -p) <Objekt>" - -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t | -s) [--allow-unknown-type] <Objekt>" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <Objekt>" msgid "" "git cat-file (--textconv | --filters)\n" @@ -3398,9 +3397,6 @@ msgstr "zeige Objekt-Typ (eines von 'blob', 'tree', 'commit', 'tag', ...)" msgid "show object size" msgstr "Objektgröße anzeigen" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "-s und -t mit beschädigten Objekten erlauben" - msgid "use mail map file" msgstr "\"mailmap\"-Datei verwenden" @@ -3460,6 +3456,13 @@ msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "" "nutzen Sie einen <Pfad> für (--textconv | --filters); Nicht mit 'batch'" +msgid "objects filter only supported in batch mode" +msgstr "Objektfilter werden nur im Batch-Modus unterstützt" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "Objektfilter nicht unterstützt: '%s'" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "'%s=<%s>' benötigt '%s' oder '%s'" @@ -5785,6 +5788,50 @@ msgstr "Dateiendung im strftime-Format für den Dateinamen angeben" msgid "specify the content of the diagnostic archive" msgstr "den Inhalt des Diagnosearchivs angeben" +#, c-format +msgid "unable to parse mode: %s" +msgstr "Konnte Modus '%s' nicht parsen." + +#, c-format +msgid "unable to parse object id: %s" +msgstr "Konnte Objekt-ID '%s' nicht parsen." + +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<Diff-Optionen>]" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "nicht erkanntes Argument: %s" + +msgid "working without -z is not supported" +msgstr "Arbeiten ohne -z wird nicht unterstützt" + +msgid "pathspec arguments not supported" +msgstr "Pfadspezifikationen als Argumente werden nicht unterstützt" + +msgid "revision arguments not allowed" +msgstr "Commits als Argumente werden nicht unterstützt" + +msgid "invalid raw diff input" +msgstr "ungültige Raw-Diff-Eingabe" + +msgid "tree objects not supported" +msgstr "Tree-Objekte werden nicht unterstützt" + +msgid "got EOF while reading path" +msgstr "EOF beim Lesen des Pfads" + +msgid "got EOF while reading destination path" +msgstr "EOF beim Lesen des Zielpfads" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "Konnte Umbenennen/Kopieren-Punktzahl nicht parsen: %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "unbekannter Diff-Status: %c" + msgid "--merge-base only works with two commits" msgstr "--merge-base funktioniert nur mit zwei Commits" @@ -5927,6 +5974,9 @@ msgstr "Fortschritt nach <n> Objekten anzeigen" msgid "select handling of signed tags" msgstr "Behandlung von signierten Tags wählen" +msgid "select handling of signed commits" +msgstr "Behandlung von signierten Commits wählen" + msgid "select handling of tags that tag filtered objects" msgstr "Behandlung von Tags wählen, die gefilterte Objekte markieren" @@ -6367,8 +6417,8 @@ msgid "protocol does not support --negotiate-only, exiting" msgstr "Protokoll unterstützt --negotiate-only nicht, beende" msgid "" -"--filter can only be used with the remote configured in extensions." -"partialclone" +"--filter can only be used with the remote configured in " +"extensions.partialclone" msgstr "" "--filter kann nur mit den Remote-Repositories verwendet werden,\n" "die in extensions.partialclone konfiguriert sind" @@ -6589,10 +6639,6 @@ msgid "%s: object corrupt or missing: %s" msgstr "%s: Objekt fehlerhaft oder nicht vorhanden: %s" #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: Objekt hat einen unbekannten Typ '%s': %s" - -#, c-format msgid "%s: object could not be parsed: %s" msgstr "%s: Objekt konnte nicht geparst werden: %s" @@ -6649,16 +6695,19 @@ msgstr "rev-Index für Pack-Datei '%s' kann nicht geladen werden" msgid "invalid rev-index for pack '%s'" msgstr "ungültiger Rev-Index für Pack-Datei '%s'" +msgid "Checking ref database" +msgstr "Referenzdatenbank überprüfen" + 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>...]" +" [--[no-]name-objects] [--[no-]references] [<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] [<Objekt>...]" +" [--[no-]name-objects] [--[no-]references] [<Objekt>...]" msgid "show unreachable objects" msgstr "unerreichbare Objekte anzeigen" @@ -6696,6 +6745,9 @@ msgstr "Fortschrittsanzeige anzeigen" msgid "show verbose names for reachable objects" msgstr "ausführliche Namen für erreichbare Objekte anzeigen" +msgid "check reference database consistency" +msgstr "Konsistenz der Referenzdatenbank überprüfen" + msgid "Checking objects" msgstr "Prüfe Objekte" @@ -7104,6 +7156,7 @@ msgstr "grep: Fehler beim Erzeugen eines Thread: %s" msgid "invalid number of threads specified (%d) for %s" msgstr "ungültige Anzahl von Threads (%d) für %s angegeben" +#. #-#-#-#-# grep.c.po #-#-#-#-# #. TRANSLATORS: %s is the configuration #. variable for tweaking threads, currently #. grep.threads @@ -7861,10 +7914,6 @@ msgstr "" "Entwicklung der Zeilen vom Bereich <Start>,<Ende> oder Funktion :" "<Funktionsname> in <Datei> verfolgen" -#, c-format -msgid "unrecognized argument: %s" -msgstr "nicht erkanntes Argument: %s" - msgid "-L<range>:<file> cannot be used with pathspec" msgstr "-L<Bereich>:<Datei> kann nicht mit Pfadspezifikation verwendet werden" @@ -8527,6 +8576,9 @@ msgstr "nur einen trivialen Merge durchführen" msgid "also show informational/conflict messages" msgstr "auch Informations-/Konfliktmeldungen anzeigen" +msgid "suppress all output; only exit status wanted" +msgstr "alle Ausgaben unterdrücken; nur Exit-Status verwenden" + msgid "list filenames without modes/oids/stages" msgstr "Dateinamen ohne Modi/Oids/Stufen auflisten" @@ -8941,8 +8993,11 @@ msgstr "" "während des Umpackens, sammle Paket-Dateien von geringerer Größe in einen " "Stapel, welcher größer ist als diese Größe" -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<Optionen>] <Quelle>... <Ziel>" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <Quelle> <Ziel>" + +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] <Quelle>... <Zielverzeichnis>" #, c-format msgid "Directory %s is in index and no submodule?" @@ -9014,6 +9069,12 @@ msgid "%s, source=%s, destination=%s" msgstr "%s, Quelle=%s, Ziel=%s" #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "" +"kann nicht sowohl '%s' als auch das übergeordnete Verzeichnis '%s' " +"verschieben" + +#, c-format msgid "Renaming %s to %s\n" msgstr "Benenne %s nach %s um\n" @@ -9971,6 +10032,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "Konnte nicht auf Commit '%s' zugreifen." +#, c-format +msgid "invalid refspec '%s'" +msgstr "ungültige Refspec '%s'" + msgid "ignoring --verify-signatures for rebase" msgstr "Ignoriere --verify-signatures für Rebase" @@ -10971,6 +11036,9 @@ msgstr "" msgid "git reflog exists <ref>" msgstr "git reflog exists <Referenz>" +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktree] | <Referenzen>...]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "ungültiger Zeitstempel '%s' für '--%s'" @@ -11022,8 +11090,8 @@ msgid "Marking reachable objects..." msgstr "Markiere nicht erreichbare Objekte..." #, c-format -msgid "%s points nowhere!" -msgstr "%s zeigt auf nichts!" +msgid "reflog could not be found: '%s'" +msgstr "Reflog konnte nicht gefunden werden: '%s'" msgid "no reflog specified to delete" msgstr "Kein Reflog zum Löschen angegeben." @@ -11032,6 +11100,15 @@ msgstr "Kein Reflog zum Löschen angegeben." msgid "invalid ref format: %s" msgstr "Ungültiges Format für Referenzen: %s" +msgid "drop the reflogs of all references" +msgstr "die Reflogs aller Referenzen löschen" + +msgid "drop reflogs from the current worktree only" +msgstr "nur Reflogs aus dem aktuellen Arbeitsverzeichnis löschen" + +msgid "references specified along with --all" +msgstr "Referenzen, die zusammen mit --all angegeben werden" + msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=<Format> [--no-reflog] [--dry-run]" @@ -11594,6 +11671,10 @@ msgstr "Datumsangabe" msgid "with --cruft, expire objects older than this" msgstr "mit --cruft, Objekte verfallen lassen, die älter sind als das" +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "" +"mit --cruft, nur Cruft-Pakete umpacken, die kleiner als dieser Wert sind" + msgid "remove redundant packs, and run git-prune-packed" msgstr "redundante Pakete entfernen und \"git-prune-packed\" ausführen" @@ -12077,6 +12158,9 @@ msgstr "konnte Festplattennutzung von %s nicht bekommen" msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "ungültiger Wert für '%s': '%s', das einzig zulässige Format ist '%s'" +msgid "-z option used with unsupported option" +msgstr "Die Option -z wird mit nicht unterstützter Option verwendet." + msgid "rev-list does not support display of notes" msgstr "rev-list unterstützt keine Anzeige von Notizen" @@ -13995,8 +14079,8 @@ msgstr "git update-ref [<Optionen>] -d <Referenzname> [<alte-oid>]" 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]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<Optionen>] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "diese Referenz löschen" @@ -14010,6 +14094,9 @@ msgstr "Standard-Eingabe hat durch NUL-Zeichen abgeschlossene Argumente" msgid "read updates from stdin" msgstr "Aktualisierungen von der Standard-Eingabe lesen" +msgid "batch reference updates" +msgstr "Batch-Referenz-Updates" + msgid "update the info files from scratch" msgstr "die Informationsdateien von Grund auf aktualisieren" @@ -14724,6 +14811,9 @@ msgstr "Dateien von dem Arbeitsverzeichnis und dem Index vergleichen" msgid "Compare a tree to the working tree or index" msgstr "ein Verzeichnis von dem Arbeitsverzeichnis und dem Index vergleichen" +msgid "Compare the content and mode of provided blob pairs" +msgstr "Inhalt und Modus der bereitgestellten Blobpaare vergleichen" + msgid "Compares the content and mode of blobs found via two tree objects" msgstr "" "den Inhalt und Modus von Blobs aus zwei Verzeichnisobjekten vergleichen" @@ -15380,8 +15470,8 @@ msgid "" "attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " "(%d) is not supported" msgstr "" -"versuche, einen Commit-Graphen zu schreiben, aber 'commitGraph." -"changedPathsVersion' (%d) wird nicht unterstützt" +"versuche, einen Commit-Graphen zu schreiben, aber " +"'commitGraph.changedPathsVersion' (%d) wird nicht unterstützt" msgid "too many commits to write graph" msgstr "zu viele Commits zum Schreiben des Graphen" @@ -17682,6 +17772,10 @@ msgid "Unknown value for http.proactiveauth" msgstr "Unbekannter Wert für http.proactiveauth" #, c-format +msgid "failed to parse %s" +msgstr "Fehler beim Parsen von %s." + +#, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Nicht unterstütztes SSL-Backend '%s'. Unterstützte SSL-Backends:" @@ -17872,6 +17966,10 @@ msgid "invalid marker-size '%s', expecting an integer" msgstr "ungültige marker-size '%s', ganze Zahl erwartet" #, c-format +msgid "Could not parse object '%s'" +msgstr "Konnte Objekt '%s' nicht parsen." + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Fehler beim Merge von Submodul %s (nicht ausgecheckt)." @@ -18124,276 +18222,6 @@ msgid "collecting merge info failed for trees %s, %s, %s" msgstr "" "Sammeln von Merge-Informationen für die Referenzen %s, %s, %s fehlgeschlagen" -msgid "(bad commit)\n" -msgstr "(ungültiger Commit)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "add_cacheinfo für Pfad '%s' fehlgeschlagen; Merge wird abgebrochen." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "" -"add_cacheinfo zur Aktualisierung für Pfad '%s' fehlgeschlagen;\n" -"Merge wird abgebrochen." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "Fehler beim Erstellen des Pfades '%s'%s" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Entferne %s, um Platz für Unterverzeichnis zu schaffen\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": vielleicht ein Verzeichnis/Datei-Konflikt?" - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "verweigere, da unversionierte Dateien in '%s' verloren gehen würden" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "Blob erwartet für %s '%s'" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "Fehler beim Öffnen von '%s': %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "Fehler beim Erstellen einer symbolischen Verknüpfung für '%s': %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "weiß nicht was mit %06o %s '%s' zu machen ist" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "" -"Submodul %s konnte nicht zusammengeführt werden (Repository beschädigt)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "Spule Submodul %s zu dem folgenden Commit vor:" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "Spule Submodul %s vor" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"Fehler beim Merge von Submodule %s (dem Merge nachfolgende Commits nicht " -"gefunden)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Fehler beim Merge von Submodul %s (kein Vorspulen)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Mögliche Auflösung des Merges für Submodul gefunden:\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 "" -"Falls das korrekt ist, fügen Sie es einfach der Staging-Area, zum Beispiel " -"mit:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"hinzu, um diesen Vorschlag zu akzeptieren.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "Fehler beim Merge von Submodul %s (mehrere Merges gefunden)" - -msgid "failed to execute internal merge" -msgstr "Fehler bei Ausführung des internen Merges" - -#, c-format -msgid "unable to add %s to database" -msgstr "konnte %s nicht zur Datenbank hinzufügen" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "" -"Fehler: Verweigere unversionierte Datei bei %s zu verlieren;\n" -"schreibe stattdessen nach %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde " -"im Arbeitsbereich gelassen." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s nach %s in %s. Stand %s von " -"%s wurde im Arbeitsbereich gelassen." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde " -"im Arbeitsbereich bei %s gelassen." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s nach %s in %s. Stand %s von " -"%s wurde im Arbeitsbereich bei %s gelassen." - -msgid "rename" -msgstr "umbenennen" - -msgid "renamed" -msgstr "umbenannt" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "Verweigere geänderte Datei bei %s zu verlieren." - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "" -"Verweigere unversionierte Datei bei %s zu verlieren, auch wenn diese im Weg " -"ist." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"KONFLIKT (umbenennen/hinzufügen): Benenne um %s->%s in %s. %s hinzugefügt in " -"%s" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s ist ein Verzeichnis in %s, füge es stattdessen als %s hinzu" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "" -"Verweigere unversionierte Datei bei %s zu verlieren; füge stattdessen %s " -"hinzu" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"KONFLIKT (umbenennen/umbenennen): Benenne um \"%s\"->\"%s\" in Branch \"%s\" " -"und \"%s\"->\"%s\" in Branch \"%s\"%s" - -msgid " (left unresolved)" -msgstr " (bleibt unaufgelöst)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"KONFLIKT (umbenennen/umbenennen): Benenne um %s->%s in %s. Benenne um %s->%s " -"in %s" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"KONFLIKT (Aufteilung Verzeichnisumbenennung): Unklar, wo %s zu platzieren " -"ist,\n" -"weil Verzeichnis %s zu mehreren anderen Verzeichnissen umbenannt wurde, " -"wobei\n" -"keines dieser Ziele die Mehrheit der Dateien erhielt." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"KONFLIKT (umbenennen/umbenennen): Benenne Verzeichnis um %s->%s in %s.\n" -"Benenne Verzeichnis um %s->%s in %s" - -#, c-format -msgid "cannot read object %s" -msgstr "kann Objekt %s nicht lesen" - -#, c-format -msgid "object %s is not a blob" -msgstr "Objekt %s ist kein Blob" - -msgid "modify" -msgstr "ändern" - -msgid "modified" -msgstr "geändert" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "%s ausgelassen (Ergebnis des Merges existiert bereits)" - -#, c-format -msgid "Adding as %s instead" -msgstr "Füge stattdessen als %s hinzu" - -#, c-format -msgid "Removing %s" -msgstr "Entferne %s" - -msgid "file/directory" -msgstr "Datei/Verzeichnis" - -msgid "directory/file" -msgstr "Verzeichnis/Datei" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"KONFLIKT (%s): Es existiert bereits ein Verzeichnis %s in %s. Füge %s als %s " -"hinzu." - -#, c-format -msgid "Adding %s" -msgstr "Füge %s hinzu" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "KONFLIKT (hinzufügen/hinzufügen): Merge-Konflikt in %s" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "Zusammenführen der \"Tree\"-Objekte %s und %s fehlgeschlagen" - -msgid "Merging:" -msgstr "Merge:" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "%u gemeinsamen Vorgänger-Commit gefunden" -msgstr[1] "%u gemeinsame Vorgänger-Commits gefunden" - -msgid "merge returned no commit" -msgstr "Merge hat keinen Commit zurückgegeben" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "Konnte Objekt '%s' nicht parsen." - msgid "failed to read the cache" msgstr "Lesen des Zwischenspeichers fehlgeschlagen" @@ -18435,13 +18263,14 @@ msgstr "kann '%s' nicht mit '%s' verknüpfen" msgid "failed to clear multi-pack-index at %s" msgstr "Fehler beim Löschen des Multi-Pack-Index bei %s" -msgid "cannot write incremental MIDX with bitmap" -msgstr "kann kein inkrementelles MIDX mit Bitmap schreiben" - msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "" "ignoriere existierenden Multi-Pack-Index; Prüfsumme stimmt nicht überein" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "konnte den umgekehrten Index für MIDX %s nicht laden" + msgid "Adding packfiles to multi-pack-index" msgstr "Packdateien zum Multi-Pack-Index hinzufügen" @@ -18704,69 +18533,6 @@ 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 "" -"Objektverzeichnis %s existiert nicht; prüfe .git/objects/info/alternates" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "Konnte alternativen Objektpfad '%s' nicht normalisieren." - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s: ignoriere alternative Objektspeicher - Verschachtelung zu tief" - -msgid "unable to fdopen alternates lockfile" -msgstr "Konnte fdopen nicht auf Lock-Datei für \"alternates\" aufrufen." - -msgid "unable to read alternates file" -msgstr "Konnte \"alternates\"-Datei nicht lesen." - -msgid "unable to move new alternates file into place" -msgstr "Konnte neue \"alternates\"-Datei nicht übernehmen." - -#, c-format -msgid "path '%s' does not exist" -msgstr "Pfad '%s' existiert nicht" - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "" -"Referenziertes Repository '%s' wird noch nicht als verknüpftes\n" -"Arbeitsverzeichnis unterstützt." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "Referenziertes Repository '%s' ist kein lokales Repository." - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "" -"Referenziertes Repository '%s' hat eine unvollständige Historie (shallow)." - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "" -"Referenziertes Repository '%s' ist mit künstlichen Vorgängern (\"grafts\") " -"eingehängt." - -#, c-format -msgid "could not find object directory matching %s" -msgstr "konnte Objekt-Verzeichnis nicht finden, dass '%s' entsprechen soll" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "Ungültige Zeile beim Parsen alternativer Referenzen: %s" - -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "Versuche mmap %<PRIuMAX> über Limit %<PRIuMAX>." - -#, c-format -msgid "mmap failed%s" -msgstr "mmap fehlgeschlagen%s" - -#, c-format msgid "object file %s is empty" msgstr "Objektdatei %s ist leer." @@ -18802,18 +18568,6 @@ msgid "loose object %s (stored in %s) is corrupt" msgstr "Loses Objekt %s (gespeichert in %s) ist beschädigt." #, c-format -msgid "replacement %s not found for %s" -msgstr "Ersetzung %s für %s nicht gefunden." - -#, c-format -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 open %s" msgstr "kann %s nicht öffnen" @@ -18908,10 +18662,6 @@ msgid "%s: unsupported file type" msgstr "%s: nicht unterstützte Dateiart" #, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s ist kein gültiges '%s' Objekt" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "Hash für %s stimmt nicht überein (%s erwartet)." @@ -18928,6 +18678,10 @@ msgid "unable to parse header of %s" msgstr "Konnte Kopfbereich von %s nicht parsen." #, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "Konnte den Typ aus der Kopfzeile '%s' von %s nicht parsen." + +#, c-format msgid "unable to unpack contents of %s" msgstr "Konnte Inhalt von %s nicht entpacken." @@ -19088,6 +18842,77 @@ msgid "invalid object name '%.*s'." msgstr "ungültiger Objektname '%.*s'." #, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "" +"Objektverzeichnis %s existiert nicht; prüfe .git/objects/info/alternates" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "Konnte alternativen Objektpfad '%s' nicht normalisieren." + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s: ignoriere alternative Objektspeicher - Verschachtelung zu tief" + +msgid "unable to fdopen alternates lockfile" +msgstr "Konnte fdopen nicht auf Lock-Datei für \"alternates\" aufrufen." + +msgid "unable to read alternates file" +msgstr "Konnte \"alternates\"-Datei nicht lesen." + +msgid "unable to move new alternates file into place" +msgstr "Konnte neue \"alternates\"-Datei nicht übernehmen." + +#, c-format +msgid "path '%s' does not exist" +msgstr "Pfad '%s' existiert nicht" + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "" +"Referenziertes Repository '%s' wird noch nicht als verknüpftes\n" +"Arbeitsverzeichnis unterstützt." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "Referenziertes Repository '%s' ist kein lokales Repository." + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "" +"Referenziertes Repository '%s' hat eine unvollständige Historie (shallow)." + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "" +"Referenziertes Repository '%s' ist mit künstlichen Vorgängern (\"grafts\") " +"eingehängt." + +#, c-format +msgid "could not find object directory matching %s" +msgstr "konnte Objekt-Verzeichnis nicht finden, dass '%s' entsprechen soll" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "Ungültige Zeile beim Parsen alternativer Referenzen: %s" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "Ersetzung %s für %s nicht gefunden." + +#, c-format +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 "%s is not a valid '%s' object" +msgstr "%s ist kein gültiges '%s' Objekt" + +#, c-format msgid "invalid object type \"%s\"" msgstr "Ungültiger Objekttyp \"%s\"" @@ -19371,6 +19196,14 @@ msgid "%s isn't available" msgstr "%s ist nicht verfügbar." #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "Wert %s für %s nicht im Bereich [%<PRIdMAX>,%<PRIdMAX>]" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s erwartet einen ganzzahligen Wert mit einem optionalen k/m/g-Suffix" + +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "" "%s erwartet einen nicht-negativen Integer-Wert mit einem optionalen k/m/g " @@ -19532,10 +19365,6 @@ msgid "bad boolean environment value '%s' for '%s'" msgstr "falscher boolescher Wert von Umgebungsvariable '%s' für '%s'" #, c-format -msgid "failed to parse %s" -msgstr "Fehler beim Parsen von %s." - -#, c-format msgid "failed to walk children of tree %s: not found" msgstr "Fehlen beim Durchlaufen der Kinder von Baum %s: nicht gefunden" @@ -19701,7 +19530,11 @@ msgid "could not fetch %s from promisor remote" msgstr "konnte %s nicht von Promisor-Remote abrufen" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgid "no or empty URL advertised for remote '%s'" +msgstr "keine oder leere URL für Remote-Repository '%s' angegeben" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" msgstr "" "bekanntes Remote-Repository mit dem Namen '%s', aber mit der URL '%s' statt " "'%s'" @@ -20482,6 +20315,10 @@ msgid "Checking references consistency" msgstr "Überprüfung der Konsistenz der Referenzen" #, c-format +msgid "unable to open '%s'" +msgstr "konnte '%s' nicht öffnen" + +#, c-format msgid "refname is dangerous: %s" msgstr "Referenzname ist gefährlich: %s" @@ -20552,10 +20389,6 @@ msgstr "" "unterstützt" #, c-format -msgid "invalid refspec '%s'" -msgstr "ungültige Refspec '%s'" - -#, c-format msgid "pattern '%s' has no '*'" msgstr "Muster '%s' hat keinen '*'" @@ -21108,8 +20941,8 @@ msgstr "konnte keine Eintragung hinzufügen" msgid "could not set recommended config" msgstr "konnte die empfohlene Konfiguration nicht setzen" -msgid "could not turn on maintenance" -msgstr "konnte die Wartung nicht einschalten" +msgid "could not toggle maintenance" +msgstr "konnte die Wartung nicht umschalten" msgid "could not start the FSMonitor daemon" msgstr "konnte den FSMonitor-Daemon nicht starten" @@ -21156,12 +20989,15 @@ msgstr "Repository im Verzeichnis 'src' erstellen" msgid "specify if tags should be fetched during clone" msgstr "Angabe, ob Tags während des Klonens abgerufen werden sollen" +msgid "specify if background maintenance should be enabled" +msgstr "angeben, ob die Hintergrundwartung aktiviert werden soll" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <Haupt-Branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <URL> [<Eintragung>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <URL> [<Eintragung>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -21199,19 +21035,33 @@ msgstr "scalar diagnose [<Eintragung>]" msgid "`scalar list` does not take arguments" msgstr "`scalar list` akzeptiert keine Argumente" -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<Eintragung>]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [<Eintragung>]" msgid "reconfigure all registered enlistments" msgstr "alle registrierten Eintragungen neu konfigurieren" -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all | <Eintragung>]" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +msgid "signal how to adjust background maintenance" +msgstr "Angabe, wie die Hintergrundwartung einzustellen ist" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<Eintragung>]" msgid "--all or <enlistment>, but not both" msgstr "--all oder <Eintragung>, aber nicht beides" #, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "unbekannter Modus für die Option --maintenance: %s" + +#, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "konnte veraltetes scalar.repo '%s' nicht entfernen" @@ -22669,6 +22519,9 @@ msgstr "" "Anzahl der Einträge im Cache-Verzeichnis, die ungültig gemacht werden sollen " "(Standardwert 0)" +msgid "the number of objects to write" +msgstr "die Anzahl der zu schreibenden Objekte" + msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk <Optionen> -- <Commit-Optionen>" @@ -23460,6 +23313,14 @@ msgstr "konnte aktuelles Arbeitsverzeichnis nicht bekommen" msgid "unable to get random bytes" msgstr "konnte keine Zufallsbytes abrufen" +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "Versuche mmap %<PRIuMAX> über Limit %<PRIuMAX>." + +#, c-format +msgid "mmap failed%s" +msgstr "mmap fehlgeschlagen%s" + msgid "Unmerged paths:" msgstr "Nicht zusammengeführte Pfade:" @@ -24270,6 +24131,14 @@ msgstr "" "und benutzen Sie --smtp-debug." #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook hat die Message-ID neu zugewiesen: %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "" +"Warnung: Message-ID konnte nicht aus der Serverantwort abgerufen werden.\n" + +#, perl-format msgid "Failed to send %s\n" msgstr "Fehler beim Senden %s\n" @@ -87,8 +87,8 @@ msgid "" msgstr "" "Project-Id-Version: git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-03-05 22:57+0000\n" -"PO-Revision-Date: 2025-03-06 16:46+0100\n" +"POT-Creation-Date: 2025-05-27 22:57+0000\n" +"PO-Revision-Date: 2025-05-29 12:54+0200\n" "Last-Translator: Cédric Malard <c.malard-git@valdun.net>\n" "Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n" "Language: fr\n" @@ -3405,11 +3405,8 @@ msgstr "une seule option de traitement ne peut être spécifiée à la fois" msgid "git cat-file <type> <object>" msgstr "git cat-file <type> <objet>" -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e | -p) <objet>" - -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t | -s) [--allow-unknown-type] <objet>" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <objet>" msgid "" "git cat-file (--textconv | --filters)\n" @@ -3447,9 +3444,6 @@ msgstr "montrer le type de l'objet (parmi 'blob', 'tree', 'commit', 'tag' ...)" msgid "show object size" msgstr "afficher la taille de l'objet" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "autoriser -s et -t à travailler sur des objets cassés/corrompus" - msgid "use mail map file" msgstr "utiliser le fichier de correspondance de mail" @@ -3508,6 +3502,13 @@ msgstr "" "utiliser un <chemin> spécifique pour (--textconv | --filters); pas pour les " "lots" +msgid "objects filter only supported in batch mode" +msgstr "le filtre d'objets n'est pris en charge qu'en mode par lots" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "filtre d'objets non pris en charge : '%s'" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "'%s=<%s>' a besoin de '%s' ou '%s'" @@ -5811,6 +5812,50 @@ msgstr "spécifier une suffixe au format strftime pour le nom de fichier" msgid "specify the content of the diagnostic archive" msgstr "spécifier le contenu de l'archive de diagnostique" +#, c-format +msgid "unable to parse mode: %s" +msgstr "impossible d'analyser le mode : %s" + +#, c-format +msgid "unable to parse object id: %s" +msgstr "impossible d'analyser l'id de l'objet : %s" + +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<options-de-diff>]" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "argument non reconnu : %s" + +msgid "working without -z is not supported" +msgstr "l'invocation sans -z n'est pas supportée" + +msgid "pathspec arguments not supported" +msgstr "les arguments de spécificateurs de chemin ne sont pas pris en charge" + +msgid "revision arguments not allowed" +msgstr "les arguments de type révision ne sont pas pris en charge" + +msgid "invalid raw diff input" +msgstr "entrée de diff brut invalide" + +msgid "tree objects not supported" +msgstr "les objets arbres ne sont pas supportés" + +msgid "got EOF while reading path" +msgstr "EOF rencontré lors de la lecture du chemin" + +msgid "got EOF while reading destination path" +msgstr "EOF rencontré lors de la lecture du chemin destination" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "impossible d'analyser le score de renommage/copie : %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "statut de diff inconnu : %c" + msgid "--merge-base only works with two commits" msgstr "--merge-base ne fonctionne qu'avec deux commits" @@ -5952,6 +5997,9 @@ msgstr "afficher la progression après <n> objets" msgid "select handling of signed tags" msgstr "sélectionner la gestion des étiquettes signées" +msgid "select handling of signed commits" +msgstr "sélectionner la gestion des commits signés" + msgid "select handling of tags that tag filtered objects" msgstr "" "sélectionner la gestion des étiquettes qui pointent sur des objets filtrés" @@ -6605,10 +6653,6 @@ msgid "%s: object corrupt or missing: %s" msgstr "%s : objet corrompu ou manquant : %s" #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s : l'objet a un type '%s' inconnu : %s" - -#, c-format msgid "%s: object could not be parsed: %s" msgstr "%s : impossible d'analyser : %s" @@ -6665,16 +6709,19 @@ msgstr "impossible de charger le rev-index pour le paquet '%s'" msgid "invalid rev-index for pack '%s'" msgstr "rev-index invalide pour le paquet '%s'" +msgid "Checking ref database" +msgstr "Vérification de la base de données des réferences" + 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>...]" +" [--[no-]name-objects] [--[no-]references] [<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] [<objec>...]" +" [--[no-]name-objects] [--[no-]references] [<objet>...]" msgid "show unreachable objects" msgstr "afficher les objets inaccessibles" @@ -6713,6 +6760,9 @@ msgstr "afficher la progression" msgid "show verbose names for reachable objects" msgstr "afficher les noms étendus pour les objets inaccessibles" +msgid "check reference database consistency" +msgstr "vérifier la cohérence de la base de données des références" + msgid "Checking objects" msgstr "Vérification des objets" @@ -7877,10 +7927,6 @@ msgstr "" "tracer l'évolution d'une plage <début>,<fin> ou d'une fonction <nom-de-" "fonction> dans <fichier>" -#, c-format -msgid "unrecognized argument: %s" -msgstr "argument non reconnu : %s" - msgid "-L<range>:<file> cannot be used with pathspec" msgstr "" "-L<plage>:<fichier> ne peut pas être utilisé avec une spécificateur de chemin" @@ -8550,6 +8596,9 @@ msgstr "faire seulement une fusion triviale" msgid "also show informational/conflict messages" msgstr "afficher aussi les messages d'information/de conflit" +msgid "suppress all output; only exit status wanted" +msgstr "supprimer toutes les sorties ; seul le statut de sortie est rendu" + msgid "list filenames without modes/oids/stages" msgstr "lister les noms de fichier sans modes/oids/indexation" @@ -8961,8 +9010,11 @@ msgstr "" "pendant le repaquetage, collecter les fichiers paquet de plus petite taille " "dans un lot plus grand que cette taille" -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<options>] <source>... <destination>" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <source> <destination>" + +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] <source>... <répertoire-de-destination>" #, c-format msgid "Directory %s is in index and no submodule?" @@ -9033,6 +9085,10 @@ msgid "%s, source=%s, destination=%s" msgstr "%s, source=%s, destination=%s" #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "Impossible de déplacer à la fois '%s' et son répertoire parent '%s'" + +#, c-format msgid "Renaming %s to %s\n" msgstr "Renommage de %s en %s\n" @@ -9975,6 +10031,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "impossible d'accéder le commit %s" +#, c-format +msgid "invalid refspec '%s'" +msgstr "spécificateur de réference invalide : '%s'" + msgid "ignoring --verify-signatures for rebase" msgstr "--verify-signatures est ignoré pour un rebasage" @@ -10957,6 +11017,9 @@ msgstr "" msgid "git reflog exists <ref>" msgstr "git reflog exists <référence>" +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktree] | <réf>...]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "horodatage invalide '%s' fourni à '--%s'" @@ -11008,8 +11071,8 @@ msgid "Marking reachable objects..." msgstr "Marquage des objets inaccessibles..." #, c-format -msgid "%s points nowhere!" -msgstr "%s ne pointe nulle part !" +msgid "reflog could not be found: '%s'" +msgstr "impossible de trouver le journal de références : '%s'" msgid "no reflog specified to delete" msgstr "pas de journal de références à supprimer spécifié" @@ -11018,6 +11081,15 @@ msgstr "pas de journal de références à supprimer spécifié" msgid "invalid ref format: %s" msgstr "format de référence invalide : %s" +msgid "drop the reflogs of all references" +msgstr "abandonner les reflogs de toutes les références" + +msgid "drop reflogs from the current worktree only" +msgstr "abandonner les reflogs de l'arbre-de-travail actuel uniquement" + +msgid "references specified along with --all" +msgstr "références spécifiées en même temps que --all" + msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" @@ -11581,7 +11653,10 @@ msgid "approxidate" msgstr "date approximative" msgid "with --cruft, expire objects older than this" -msgstr "avec --cruft, faire expirer les objets plus vieux que celui-ci" +msgstr "avec --cruft, faire expirer les objets plus vieux que ceci" + +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "avec --cruft, ne réempaqueter que les objets plus petits que ceci" msgid "remove redundant packs, and run git-prune-packed" msgstr "supprimer les paquets redondants et lancer git-prune-packed" @@ -12064,6 +12139,9 @@ msgstr "impossible de récupérer l'utilisation du disque de %s" msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "valeur invalide pour '%s' : '%s', le seul format permis est '%s'" +msgid "-z option used with unsupported option" +msgstr "option -z utilisée avec une option non supportée" + msgid "rev-list does not support display of notes" msgstr "rev-list ne supporte l'affichage des notes" @@ -13970,8 +14048,8 @@ msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" msgstr "" "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]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<options>] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "supprimer la référence" @@ -13985,6 +14063,9 @@ msgstr "l'entrée standard a des arguments qui se terminent par NUL" msgid "read updates from stdin" msgstr "lire les mises à jour depuis l'entrée standard" +msgid "batch reference updates" +msgstr "traiter les mises à jour par lot" + msgid "update the info files from scratch" msgstr "mettre à jour les fichiers d'information à partir de zéro" @@ -14690,6 +14771,9 @@ msgstr "Compare des fichiers de l'arbre de travail et de l'index" msgid "Compare a tree to the working tree or index" msgstr "Comparer un arbre avec l'arbre de travail ou l'index" +msgid "Compare the content and mode of provided blob pairs" +msgstr "Compare le contenu et le mode des paires de blobs fournies" + msgid "Compares the content and mode of blobs found via two tree objects" msgstr "Compare le contenu et le mode des blobs trouvés via deux objets arbre" @@ -17679,6 +17763,10 @@ msgid "Unknown value for http.proactiveauth" msgstr "valeur inconnue pour http.proactiveauth" #, c-format +msgid "failed to parse %s" +msgstr "échec de l'analyse de %s" + +#, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Dorsale SSL '%s' non supportée. Dorsales SSL supportées :" @@ -17871,6 +17959,10 @@ msgid "invalid marker-size '%s', expecting an integer" msgstr "taille de marqueur invalide '%s', entier attendu" #, c-format +msgid "Could not parse object '%s'" +msgstr "Impossible d'analyser l'objet '%s'" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Échec de la fusion du sous-module %s (non extrait)" @@ -18119,264 +18211,6 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "échec de collecte l'information de fusion pour les arbres %s, %s, %s" -msgid "(bad commit)\n" -msgstr "(mauvais commit)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "impossible de créer le chemin '%s' %s" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Suppression de %s pour faire de la place pour le sous-répertoire\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": peut-être un conflit D/F ?" - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "refus de perdre le fichier non suivi '%s'" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "blob attendu pour %s '%s'" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "échec à l'ouverture de '%s' : %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "échec à la création du lien symbolique '%s' : %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "ne sait pas traiter %06o %s '%s'" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Échec de la fusion du sous-module %s (dépôt corrompu)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "Avance rapide du sous-module %s au commit suivant :" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "Avance rapide du sous-module %s" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"Échec de fusion du sous-module %s (fusion suivant les commits non trouvée)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Échec de fusion du sous-module %s (pas en avance rapide)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Résolution possible de fusion trouvée pour le sous-module :\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 "" -"Si c'est correct, ajoutez le simplement à l'index\n" -"en utilisant par exemple :\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"qui acceptera cette suggestion.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "Échec de fusion du sous-module %s (plusieurs fusions trouvées)" - -msgid "failed to execute internal merge" -msgstr "échec à l'exécution de la fusion interne" - -#, c-format -msgid "unable to add %s to database" -msgstr "impossible d'ajouter %s à la base de données" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "" -"Erreur : refus de perdre le fichier non suivi %s ; écriture dans %s à la " -"place." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s de " -"%s laissée dans l'arbre." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. Version " -"%s de %s laissée dans l'arbre." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s de " -"%s laissée dans l'arbre dans le fichier %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. Version " -"%s de %s laissée dans l'arbre dans le fichier %s." - -msgid "rename" -msgstr "renommage" - -msgid "renamed" -msgstr "renommé" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "Refus de perdre le fichier modifié %s" - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "Refus de perdre le fichier non suivi %s, même s'il gêne." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"CONFLIT (renommage/ajout) : Renommage de %s->%s dans %s. %s ajouté dans %s" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s est un répertoire dans %s ajouté plutôt comme %s" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "Refus de perdre le fichier non suivi %s ; ajout comme %s à la place" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"CONFLIT (renommage/renommage) : Renommage de \"%s\"->\"%s\" dans la branche " -"\"%s\" et renommage \"%s\"->\"%s\" dans \"%s\"%s" - -msgid " (left unresolved)" -msgstr " (laissé non résolu)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"CONFLIT (renommage/renommage) : renommage '%s'->'%s' dans %s. Renommage '%s'-" -">'%s' dans %s" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"CONFLIT (renommage de répertoire coupé) : la place de %s n'est pas claire " -"parce que le répertoire %s a été renommé en plusieurs autres répertoires, " -"sans aucune destination récupérant la majorité des fichiers." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"CONFLIT (renommage/renommage) : renommage du répertoire %s->%s dans %s. " -"Renommage de répertoire %s->%s dans %s" - -#, c-format -msgid "cannot read object %s" -msgstr "impossible de lire l'objet %s" - -#, c-format -msgid "object %s is not a blob" -msgstr "l'objet %s n'est pas un blob" - -msgid "modify" -msgstr "modification" - -msgid "modified" -msgstr "modifié" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "%s sauté (fusion identique à l'existant)" - -#, c-format -msgid "Adding as %s instead" -msgstr "Ajout plutôt comme %s" - -#, c-format -msgid "Removing %s" -msgstr "Suppression de %s" - -msgid "file/directory" -msgstr "fichier/répertoire" - -msgid "directory/file" -msgstr "répertoire/fichier" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"CONFLIT (%s) : Il y a un répertoire nommé %s dans %s. Ajout de %s comme %s" - -#, c-format -msgid "Adding %s" -msgstr "Ajout de %s" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "CONFLIT (ajout/ajout) : Conflit de fusion dans %s" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "échec de fusion des arbres %s et %s" - -msgid "Merging:" -msgstr "Fusion :" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "%u ancêtre commun trouvé :" -msgstr[1] "%u ancêtres communs trouvés :" - -msgid "merge returned no commit" -msgstr "la fusion n'a pas retourné de commit" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "Impossible d'analyser l'objet '%s'" - msgid "failed to read the cache" msgstr "impossible de lire le cache" @@ -18418,13 +18252,14 @@ msgstr "impossible de lier '%s' à '%s'" msgid "failed to clear multi-pack-index at %s" msgstr "échec du nettoyage de l'index de multi-paquet à %s" -msgid "cannot write incremental MIDX with bitmap" -msgstr "impossible d'écrire un MIDX incrémental avec des bitmap" - msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "" "index multi-paquet existant ignoré ; non-concordance de la somme de contrôle" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "impossible de charger l'index inversé pour le MIDX %s" + msgid "Adding packfiles to multi-pack-index" msgstr "Ajout de fichiers paquet à un index multi-paquet" @@ -18692,66 +18527,6 @@ 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 "" -"le répertoire objet %s n'existe pas ; vérifiez .git/objects/info/alternates" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "impossible de normaliser le chemin d'objet alternatif : %s" - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s : magasins d'objets alternatifs ignorés, récursion trop profonde" - -msgid "unable to fdopen alternates lockfile" -msgstr "impossible d'ouvrir (fdopen) le fichier verrou des alternatives" - -msgid "unable to read alternates file" -msgstr "lecture du fichier d'alternatives impossible" - -msgid "unable to move new alternates file into place" -msgstr "impossible de déplacer le nouveau fichier d'alternative" - -#, c-format -msgid "path '%s' does not exist" -msgstr "le chemin '%s' n'existe pas" - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "" -"extraire le dépôt de référence '%s' comme une extraction liée n'est pas " -"encore supporté." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "le dépôt de référence '%s' n'est pas un dépôt local." - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "le dépôt de référence '%s' est superficiel" - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "le dépôt de référence '%s' est greffé" - -#, c-format -msgid "could not find object directory matching %s" -msgstr "impossible de trouver le répertoire objet correspondant à %s" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "ligne invalide pendant l'analyse des refs alternatives : %s" - -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "essai de mmap %<PRIuMAX> au delà de la limite %<PRIuMAX>" - -#, c-format -msgid "mmap failed%s" -msgstr "échec de mmap%s" - -#, c-format msgid "object file %s is empty" msgstr "le fichier objet %s est vide" @@ -18787,18 +18562,6 @@ msgid "loose object %s (stored in %s) is corrupt" msgstr "l'objet libre %s (stocké dans %s) est corrompu" #, c-format -msgid "replacement %s not found for %s" -msgstr "remplacement %s non trouvé pour %s" - -#, c-format -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 open %s" msgstr "impossible d'ouvrir %s" @@ -18892,10 +18655,6 @@ msgid "%s: unsupported file type" msgstr "%s : type de fichier non supporté" #, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s n'est pas un objet '%s' valide" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "incohérence de hachage pour %s (%s attendu)" @@ -18912,6 +18671,10 @@ msgid "unable to parse header of %s" msgstr "impossible d'analyser l'entête de %s" #, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "impossible d'analyser le type depuis l'entête '%s' de '%s'" + +#, c-format msgid "unable to unpack contents of %s" msgstr "impossible de dépaqueter le contenu de %s" @@ -19072,6 +18835,74 @@ msgid "invalid object name '%.*s'." msgstr "nom d'objet invalide : '%.*s'." #, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "" +"le répertoire objet %s n'existe pas ; vérifiez .git/objects/info/alternates" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "impossible de normaliser le chemin d'objet alternatif : %s" + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s : magasins d'objets alternatifs ignorés, récursion trop profonde" + +msgid "unable to fdopen alternates lockfile" +msgstr "impossible d'ouvrir (fdopen) le fichier verrou des alternatives" + +msgid "unable to read alternates file" +msgstr "lecture du fichier d'alternatives impossible" + +msgid "unable to move new alternates file into place" +msgstr "impossible de déplacer le nouveau fichier d'alternative" + +#, c-format +msgid "path '%s' does not exist" +msgstr "le chemin '%s' n'existe pas" + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "" +"extraire le dépôt de référence '%s' comme une extraction liée n'est pas " +"encore supporté." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "le dépôt de référence '%s' n'est pas un dépôt local." + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "le dépôt de référence '%s' est superficiel" + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "le dépôt de référence '%s' est greffé" + +#, c-format +msgid "could not find object directory matching %s" +msgstr "impossible de trouver le répertoire objet correspondant à %s" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "ligne invalide pendant l'analyse des refs alternatives : %s" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "remplacement %s non trouvé pour %s" + +#, c-format +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 "%s is not a valid '%s' object" +msgstr "%s n'est pas un objet '%s' valide" + +#, c-format msgid "invalid object type \"%s\"" msgstr "type d'objet invalide \"%s\"" @@ -19356,8 +19187,17 @@ msgid "%s isn't available" msgstr "%s n'est pas disponible" #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "valeur %s pour %s pas dans la plage [%<PRIdMAX>,%<PRIdMAX>]" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s attend une valeur entière avec un suffixe k/m/g optionnel" + +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" -msgstr "%s attend une valeur entière non négative avec une suffixe k/m/g" +msgstr "" +"%s attend une valeur entière non négative avec un suffixe k/m/g optionnel" #, c-format msgid "ambiguous option: %s (could be --%s%s or --%s%s)" @@ -19515,10 +19355,6 @@ msgid "bad boolean environment value '%s' for '%s'" msgstr "valeur booléenne d'environnement invalide '%s' pour '%s'" #, c-format -msgid "failed to parse %s" -msgstr "échec de l'analyse de %s" - -#, c-format msgid "failed to walk children of tree %s: not found" msgstr "échec de parcours des enfants de l'arbre %s : non trouvé" @@ -19691,8 +19527,12 @@ msgid "could not fetch %s from promisor remote" msgstr "impossible de récupérer %s depuis le distant de prometteur" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "distant connu nommé '%s' mais avec l'url '%s' au lieu de '%s'" +msgid "no or empty URL advertised for remote '%s'" +msgstr "URL manquante ou vide annoncée pour le distant '%s'" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "distant connu nommé '%s' mais avec l'URL '%s' au lieu de '%s'" #, c-format msgid "unknown '%s' value for '%s' config option" @@ -20466,6 +20306,10 @@ msgid "Checking references consistency" msgstr "Vérification de la cohérence des références" #, c-format +msgid "unable to open '%s'" +msgstr "impossible d'ouvrir '%s'" + +#, c-format msgid "refname is dangerous: %s" msgstr "le nom de réference est dangereux : %s" @@ -20539,10 +20383,6 @@ 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'" - -#, c-format msgid "pattern '%s' has no '*'" msgstr "la valeur '%s' du motif n'a pas de '*'" @@ -21097,7 +20937,7 @@ msgstr "impossible d'ajouter l'enrôlement" msgid "could not set recommended config" msgstr "impossible de réglér la configuration recommandée" -msgid "could not turn on maintenance" +msgid "could not toggle maintenance" msgstr "impossible d'activer la maintenance" msgid "could not start the FSMonitor daemon" @@ -21146,13 +20986,16 @@ msgid "specify if tags should be fetched during clone" msgstr "" "spécifier si les étiquettes devraient être récupérées pendant le clonage" +msgid "specify if background maintenance should be enabled" +msgstr "spécifier si la maintenance en tâche de fond doit être activée" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <branche-principale>] [--full-" "clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enrôlement>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enrôlement>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -21190,19 +21033,33 @@ msgstr "scalar diagnose [<enrôlement>]" msgid "`scalar list` does not take arguments" msgstr "`scalar list` n'accepte pas d'argument" -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<enrôlement>]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [<enrôlement>]" msgid "reconfigure all registered enlistments" msgstr "reconfigurer tous les enrôlements enregistrés" -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scala reconfigure [--all|<enrôlement>]" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +msgid "signal how to adjust background maintenance" +msgstr "signaler comment ajuster la maintenance en tâche de fond" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enrôlement>]" msgid "--all or <enlistment>, but not both" msgstr "--all ou <enrôlement>, mais pas les deux" #, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "mode inconnu pour l'option --maintenance : %s" + +#, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "impossible de supprimé le scalar.repo obsolète '%s'" @@ -22652,6 +22509,9 @@ msgstr "effacer l'arbre de cache avant chaque itération" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "nombre d'entrées dans l'arbre de cache à invalider (par défaut, 0)" +msgid "the number of objects to write" +msgstr "le nombre d'objets à écrire" + msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk <options> -- <options-de-révision>" @@ -23445,6 +23305,14 @@ msgstr "impossible d'accéder au répertoire de travail courant" msgid "unable to get random bytes" msgstr "impossible d'acquérir des octets aléatoires" +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "essai de mmap %<PRIuMAX> au delà de la limite %<PRIuMAX>" + +#, c-format +msgid "mmap failed%s" +msgstr "échec de mmap%s" + msgid "Unmerged paths:" msgstr "Chemins non fusionnés :" @@ -24203,6 +24071,15 @@ msgstr "" "debug." #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook a réassigné le Message-ID à  : %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "" +"Avertissement : Impossible de récupérer le Message-ID dans la réponse du " +"serveur.\n" + +#, perl-format msgid "Failed to send %s\n" msgstr "Échec de l'envoi de %s\n" @@ -24299,6 +24176,278 @@ 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 "git cat-file (-t | -s) [--allow-unknown-type] <object>" +#~ msgstr "git cat-file (-t | -s) [--allow-unknown-type] <objet>" + +#~ msgid "allow -s and -t to work with broken/corrupt objects" +#~ msgstr "autoriser -s et -t à travailler sur des objets cassés/corrompus" + +#, c-format +#~ msgid "%s: object is of unknown type '%s': %s" +#~ msgstr "%s : l'objet a un type '%s' inconnu : %s" + +#, c-format +#~ msgid "%s points nowhere!" +#~ msgstr "%s ne pointe nulle part !" + +#~ msgid "(bad commit)\n" +#~ msgstr "(mauvais commit)\n" + +#, c-format +#~ msgid "add_cacheinfo failed for path '%s'; merge aborting." +#~ msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." + +#, c-format +#~ msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." +#~ msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." + +#, c-format +#~ msgid "failed to create path '%s'%s" +#~ msgstr "impossible de créer le chemin '%s' %s" + +#, c-format +#~ msgid "Removing %s to make room for subdirectory\n" +#~ msgstr "Suppression de %s pour faire de la place pour le sous-répertoire\n" + +#~ msgid ": perhaps a D/F conflict?" +#~ msgstr ": peut-être un conflit D/F ?" + +#, c-format +#~ msgid "refusing to lose untracked file at '%s'" +#~ msgstr "refus de perdre le fichier non suivi '%s'" + +#, c-format +#~ msgid "blob expected for %s '%s'" +#~ msgstr "blob attendu pour %s '%s'" + +#, c-format +#~ msgid "failed to open '%s': %s" +#~ msgstr "échec à l'ouverture de '%s' : %s" + +#, c-format +#~ msgid "failed to symlink '%s': %s" +#~ msgstr "échec à la création du lien symbolique '%s' : %s" + +#, c-format +#~ msgid "do not know what to do with %06o %s '%s'" +#~ msgstr "ne sait pas traiter %06o %s '%s'" + +#, c-format +#~ msgid "Failed to merge submodule %s (repository corrupt)" +#~ msgstr "Échec de la fusion du sous-module %s (dépôt corrompu)" + +#, c-format +#~ msgid "Fast-forwarding submodule %s to the following commit:" +#~ msgstr "Avance rapide du sous-module %s au commit suivant :" + +#, c-format +#~ msgid "Fast-forwarding submodule %s" +#~ msgstr "Avance rapide du sous-module %s" + +#, c-format +#~ msgid "Failed to merge submodule %s (merge following commits not found)" +#~ msgstr "" +#~ "Échec de fusion du sous-module %s (fusion suivant les commits non trouvée)" + +#, c-format +#~ msgid "Failed to merge submodule %s (not fast-forward)" +#~ msgstr "Échec de fusion du sous-module %s (pas en avance rapide)" + +#~ msgid "Found a possible merge resolution for the submodule:\n" +#~ msgstr "Résolution possible de fusion trouvée pour le sous-module :\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 "" +#~ "Si c'est correct, ajoutez le simplement à l'index\n" +#~ "en utilisant par exemple :\n" +#~ "\n" +#~ " git update-index --cacheinfo 160000 %s \"%s\"\n" +#~ "\n" +#~ "qui acceptera cette suggestion.\n" + +#, c-format +#~ msgid "Failed to merge submodule %s (multiple merges found)" +#~ msgstr "Échec de fusion du sous-module %s (plusieurs fusions trouvées)" + +#~ msgid "failed to execute internal merge" +#~ msgstr "échec à l'exécution de la fusion interne" + +#, c-format +#~ msgid "unable to add %s to database" +#~ msgstr "impossible d'ajouter %s à la base de données" + +#, c-format +#~ msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." +#~ msgstr "" +#~ "Erreur : refus de perdre le fichier non suivi %s ; écriture dans %s à la " +#~ "place." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s " +#~ "left in tree." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s " +#~ "de %s laissée dans l'arbre." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of " +#~ "%s left in tree." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. " +#~ "Version %s de %s laissée dans l'arbre." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s " +#~ "left in tree at %s." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s " +#~ "de %s laissée dans l'arbre dans le fichier %s." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of " +#~ "%s left in tree at %s." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. " +#~ "Version %s de %s laissée dans l'arbre dans le fichier %s." + +#~ msgid "rename" +#~ msgstr "renommage" + +#~ msgid "renamed" +#~ msgstr "renommé" + +#, c-format +#~ msgid "Refusing to lose dirty file at %s" +#~ msgstr "Refus de perdre le fichier modifié %s" + +#, c-format +#~ msgid "Refusing to lose untracked file at %s, even though it's in the way." +#~ msgstr "Refus de perdre le fichier non suivi %s, même s'il gêne." + +#, c-format +#~ msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" +#~ msgstr "" +#~ "CONFLIT (renommage/ajout) : Renommage de %s->%s dans %s. %s ajouté dans %s" + +#, c-format +#~ msgid "%s is a directory in %s adding as %s instead" +#~ msgstr "%s est un répertoire dans %s ajouté plutôt comme %s" + +#, c-format +#~ msgid "Refusing to lose untracked file at %s; adding as %s instead" +#~ msgstr "Refus de perdre le fichier non suivi %s ; ajout comme %s à la place" + +#, c-format +#~ msgid "" +#~ "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " +#~ "\"%s\"->\"%s\" in \"%s\"%s" +#~ msgstr "" +#~ "CONFLIT (renommage/renommage) : Renommage de \"%s\"->\"%s\" dans la " +#~ "branche \"%s\" et renommage \"%s\"->\"%s\" dans \"%s\"%s" + +#~ msgid " (left unresolved)" +#~ msgstr " (laissé non résolu)" + +#, c-format +#~ msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" +#~ msgstr "" +#~ "CONFLIT (renommage/renommage) : renommage '%s'->'%s' dans %s. Renommage " +#~ "'%s'->'%s' dans %s" + +#, c-format +#~ msgid "" +#~ "CONFLICT (directory rename split): Unclear where to place %s because " +#~ "directory %s was renamed to multiple other directories, with no " +#~ "destination getting a majority of the files." +#~ msgstr "" +#~ "CONFLIT (renommage de répertoire coupé) : la place de %s n'est pas claire " +#~ "parce que le répertoire %s a été renommé en plusieurs autres répertoires, " +#~ "sans aucune destination récupérant la majorité des fichiers." + +#, c-format +#~ msgid "" +#~ "CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory " +#~ "%s->%s in %s" +#~ msgstr "" +#~ "CONFLIT (renommage/renommage) : renommage du répertoire %s->%s dans %s. " +#~ "Renommage de répertoire %s->%s dans %s" + +#, c-format +#~ msgid "cannot read object %s" +#~ msgstr "impossible de lire l'objet %s" + +#, c-format +#~ msgid "object %s is not a blob" +#~ msgstr "l'objet %s n'est pas un blob" + +#~ msgid "modify" +#~ msgstr "modification" + +#~ msgid "modified" +#~ msgstr "modifié" + +#, c-format +#~ msgid "Skipped %s (merged same as existing)" +#~ msgstr "%s sauté (fusion identique à l'existant)" + +#, c-format +#~ msgid "Adding as %s instead" +#~ msgstr "Ajout plutôt comme %s" + +#, c-format +#~ msgid "Removing %s" +#~ msgstr "Suppression de %s" + +#~ msgid "file/directory" +#~ msgstr "fichier/répertoire" + +#~ msgid "directory/file" +#~ msgstr "répertoire/fichier" + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" +#~ msgstr "" +#~ "CONFLIT (%s) : Il y a un répertoire nommé %s dans %s. Ajout de %s comme %s" + +#, c-format +#~ msgid "Adding %s" +#~ msgstr "Ajout de %s" + +#, c-format +#~ msgid "CONFLICT (add/add): Merge conflict in %s" +#~ msgstr "CONFLIT (ajout/ajout) : Conflit de fusion dans %s" + +#, c-format +#~ msgid "merging of trees %s and %s failed" +#~ msgstr "échec de fusion des arbres %s et %s" + +#~ msgid "Merging:" +#~ msgstr "Fusion :" + +#, c-format +#~ msgid "found %u common ancestor:" +#~ msgid_plural "found %u common ancestors:" +#~ msgstr[0] "%u ancêtre commun trouvé :" +#~ msgstr[1] "%u ancêtres communs trouvés :" + +#~ msgid "merge returned no commit" +#~ msgstr "la fusion n'a pas retourné de commit" + +#~ msgid "cannot write incremental MIDX with bitmap" +#~ msgstr "impossible d'écrire un MIDX incrémental avec des bitmap" + #, c-format #~ msgid "Could not find remote branch %s to clone." #~ msgstr "Impossible de trouver la branche distante '%s' à cloner." @@ -24307,9 +24456,6 @@ msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " #~ msgid "merging cannot continue; got unclean result of %d" #~ msgstr "la fusion ne peut pas continuer ; résultat non propre retourné %d" -#~ msgid "git repack [<options>]" -#~ msgstr "git repack [<options>]" - #~ msgid "--onto and --advance are incompatible" #~ msgstr "--onto et --advance sont incompatibles" diff --git a/po/ga.po b/po/ga.po new file mode 100644 index 0000000000..c03f63756e --- /dev/null +++ b/po/ga.po @@ -0,0 +1,29758 @@ +# Irish translations for Git package. +# Copyright (C) 2025 THE Git'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Git package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: Git\n" +"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" +"POT-Creation-Date: 2025-05-29 09:16+0100\n" +"PO-Revision-Date: 2025-05-29 10:10+0100\n" +"Last-Translator: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>\n" +"Language-Team: none\n" +"Language: ga\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n" +"X-Generator: Poedit 3.4.4\n" + +#: add-interactive.c +#, c-format +msgid "Huh (%s)?" +msgstr "Huh (%s)?" + +#: add-interactive.c builtin/merge.c builtin/rebase.c reset.c sequencer.c +msgid "could not read index" +msgstr "nà raibh in ann innéacs a léamh" + +#: add-interactive.c +msgid "binary" +msgstr "dénártha" + +#: add-interactive.c +msgid "nothing" +msgstr "rud ar bith" + +#: add-interactive.c +msgid "unchanged" +msgstr "gan athrú" + +#: add-interactive.c +msgid "Update" +msgstr "Nuashonraigh" + +#: add-interactive.c +#, c-format +msgid "could not stage '%s'" +msgstr "nà fhéadfaà '%s' a chéim" + +#: add-interactive.c builtin/stash.c reset.c sequencer.c +msgid "could not write index" +msgstr "nà fhéadfadh innéacs a scrÃobh" + +#: add-interactive.c +#, c-format +msgid "updated %d path\n" +msgid_plural "updated %d paths\n" +msgstr[0] "nuashonraithe %d cosán\n" +msgstr[1] "nuashonraÃodh %d cosán\n" +msgstr[2] "nuashonraÃodh %d cosán\n" + +#: add-interactive.c +#, c-format +msgid "note: %s is untracked now.\n" +msgstr "nótaÃ: Tá %s dÃrianaithe anois.\n" + +#: add-interactive.c apply.c builtin/checkout.c builtin/reset.c +#, c-format +msgid "make_cache_entry failed for path '%s'" +msgstr "theip ar make_cache_entry le haghaidh cosán '%s'" + +#: add-interactive.c +msgid "Revert" +msgstr "Aisghabháil" + +#: add-interactive.c +msgid "Could not parse HEAD^{tree}" +msgstr "Nà raibh sé in ann HEAD ^ {tree} a pharsáil" + +#: add-interactive.c +#, c-format +msgid "reverted %d path\n" +msgid_plural "reverted %d paths\n" +msgstr[0] "cosán %d aisiompaithe\n" +msgstr[1] "%d cosán aisiompaithe\n" +msgstr[2] "%d cosán aisiompaithe\n" + +#: add-interactive.c +#, c-format +msgid "No untracked files.\n" +msgstr "Gan aon chomhaid neamhrianaithe.\n" + +#: add-interactive.c +msgid "Add untracked" +msgstr "Cuir neamh-rianaithe leis" + +#: add-interactive.c +#, c-format +msgid "added %d path\n" +msgid_plural "added %d paths\n" +msgstr[0] "cuireadh %d cosán leis\n" +msgstr[1] "%d cosán curtha leis\n" +msgstr[2] "%d cosán curtha leis\n" + +#: add-interactive.c +#, c-format +msgid "ignoring unmerged: %s" +msgstr "ag neamhaird a dhéanamh de neamhchumasctha: %s" + +#: add-interactive.c +#, c-format +msgid "Only binary files changed.\n" +msgstr "NÃor athraigh ach comhaid dénártha.\n" + +#: add-interactive.c +#, c-format +msgid "No changes.\n" +msgstr "Gan aon athruithe.\n" + +#: add-interactive.c +msgid "Patch update" +msgstr "Nuashonrú paiste" + +#: add-interactive.c +msgid "Review diff" +msgstr "Athbhreithniú diff" + +#: add-interactive.c +msgid "show paths with changes" +msgstr "taispeáin cosáin le hathruithe" + +#: add-interactive.c +msgid "add working tree state to the staged set of changes" +msgstr "cuir stát crann oibre leis an tsraith athruithe céimeádta" + +#: add-interactive.c +msgid "revert staged set of changes back to the HEAD version" +msgstr "tacar athruithe céime a chur ar ais chuig an leagan HEAD" + +#: add-interactive.c +msgid "pick hunks and update selectively" +msgstr "roghnaigh hunks agus nuashonraigh go roghnach" + +#: add-interactive.c +msgid "view diff between HEAD and index" +msgstr "féach ar an difrÃocht idir HEAD agus innéacs" + +#: add-interactive.c +msgid "add contents of untracked files to the staged set of changes" +msgstr "cuir ábhar comhaid neamhrianaithe leis an tacar athruithe céimeádta" + +#: add-interactive.c +msgid "Prompt help:" +msgstr "Cabhair pras:" + +#: add-interactive.c +msgid "select a single item" +msgstr "roghnaigh mÃr amháin" + +#: add-interactive.c +msgid "select a range of items" +msgstr "roghnaigh raon earraÃ" + +#: add-interactive.c +msgid "select multiple ranges" +msgstr "roghnaigh raonta iomadúla" + +#: add-interactive.c +msgid "select item based on unique prefix" +msgstr "roghnaigh mÃr bunaithe ar réimÃr uathúil" + +#: add-interactive.c +msgid "unselect specified items" +msgstr "mÃreanna sonraithe dÃroghnaigh" + +#: add-interactive.c +msgid "choose all items" +msgstr "roghnaigh gach earra" + +#: add-interactive.c +msgid "(empty) finish selecting" +msgstr "(folamh) crÃochnaigh a roghnú" + +#: add-interactive.c +msgid "select a numbered item" +msgstr "roghnaigh mÃr uimhrithe" + +#: add-interactive.c +msgid "(empty) select nothing" +msgstr "(folamh) roghnaigh aon rud" + +#: add-interactive.c builtin/clean.c +msgid "*** Commands ***" +msgstr "*** Orduithe ***" + +#: add-interactive.c builtin/clean.c +msgid "What now" +msgstr "Cad anois" + +#: add-interactive.c +msgid "staged" +msgstr "stáitse" + +#: add-interactive.c +msgid "unstaged" +msgstr "gan stáitse" + +#: add-interactive.c apply.c builtin/am.c builtin/bugreport.c builtin/clone.c +#: builtin/diagnose.c builtin/fetch.c builtin/hook.c builtin/merge.c +#: builtin/pull.c builtin/submodule--helper.c +msgid "path" +msgstr "cosán" + +#: add-interactive.c +msgid "could not refresh index" +msgstr "nà fhéadfadh innéacs a athnuachan" + +#: add-interactive.c builtin/clean.c +#, c-format +msgid "Bye.\n" +msgstr "Slán..\n" + +#: add-patch.c +#, c-format +msgid "Stage mode change [y,n,q,a,d%s,?]? " +msgstr "Athrú modh stáitse [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stage deletion [y,n,q,a,d%s,?]? " +msgstr "Scriosadh céime [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stage addition [y,n,q,a,d%s,?]? " +msgstr "Breiseán céime [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stage this hunk [y,n,q,a,d%s,?]? " +msgstr "Cuir an pÃosa seo ar stáitse [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"staging." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh stáitsithe." + +#: add-patch.c +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\n" +msgstr "" +"y - céim an hunk seo\n" +"n - ná déan an hunk seo a chéile\n" +"q - scor; ná déan an hunk seo ná aon cheann de na cinn atá fágtha a chéile\n" +"a - céim an hunk seo agus gach hunc ina dhiaidh sin sa chomhad\n" +"d - ná déan an hunk seo ná aon cheann de na hunks nÃos déanaà sa chomhad a " +"chéile\n" + +#: add-patch.c +#, c-format +msgid "Stash mode change [y,n,q,a,d%s,?]? " +msgstr "Athrú modh stash [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stash deletion [y,n,q,a,d%s,?]? " +msgstr "Scriosadh staise [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stash addition [y,n,q,a,d%s,?]? " +msgstr "Breiseán stash [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stash this hunk [y,n,q,a,d%s,?]? " +msgstr "An bhfuil an carachtar seo [y,n,q,a,d%s,?] i bhfolach? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"stashing." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh stórála." + +#: add-patch.c +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\n" +msgstr "" +"y - stash an hunk seo\n" +"n - ná déan an hunk seo a stóráil\n" +"q - scor; ná déan an hunk seo ná aon cheann de na cinn atá fágtha a stóráil\n" +"a - stóráil an hunk seo agus gach hunk ina dhiaidh sin sa chomhad\n" +"d - ná déan an hunk seo ná aon cheann de na hunks nÃos déanaà sa chomhad a " +"stóráil\n" + +#: add-patch.c +#, c-format +msgid "Unstage mode change [y,n,q,a,d%s,?]? " +msgstr "Athrú ar mhodh gan stáitse [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Unstage deletion [y,n,q,a,d%s,?]? " +msgstr "Scriosadh gan stáitse [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Unstage addition [y,n,q,a,d%s,?]? " +msgstr "Breiseán gan stáitse [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Unstage this hunk [y,n,q,a,d%s,?]? " +msgstr "DÃ-stáitseáil an pÃosa beag seo den stáitse [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"unstaging." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh dÃstáisithe." + +#: add-patch.c +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\n" +msgstr "" +"y - déan an hunk seo a dhÃchur\n" +"n - ná déan an hunk seo a dhÃchur\n" +"q - scor; ná déan an hunk seo nó aon cheann de na cinn atá fágtha a dhÃchur\n" +"a - déan an hunk seo a dhÃchur agus gach hunk ina dhiaidh sin sa chomhad\n" +"d - ná déan an hunk seo nó aon cheann de na huncanna nÃos déanaà sa chomhad " +"a dhÃchur\n" + +#: add-patch.c +#, c-format +msgid "Apply mode change to index [y,n,q,a,d%s,?]? " +msgstr "Cuir athrú mód i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply deletion to index [y,n,q,a,d%s,?]? " +msgstr "Cuir scriosadh i bhfeidhm ar innéacs [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply addition to index [y,n,q,a,d%s,?]? " +msgstr "Cuir an breiseán i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply this hunk to index [y,n,q,a,d%s,?]? " +msgstr "Cuir an pÃosa seo i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"applying." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh iarratas a dhéanamh." + +#: add-patch.c +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\n" +msgstr "" +"y - cuir an hunk seo i bhfeidhm ar innéacs\n" +"n - ná cuir an hunk seo i bhfeidhm ar innéacs\n" +"q - scor; ná cuir an hunk seo ná aon cheann de na cinn atá fágtha i " +"bhfeidhm\n" +"a - cuir an hunk seo agus gach hunk nÃos déanaà i bhfeidhm sa chomhad\n" +"d - ná cuir an hunk seo ná aon cheann de na hunks nÃos déanaà sa chomhad i " +"bhfeidhm\n" + +#: add-patch.c +#, c-format +msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? " +msgstr "Athrú modh a dhiúscairt ó chrann oibre [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? " +msgstr "An scriosadh ón gcrann oibre [y,n,q,a,d%s,?] a sheachaint? " + +#: add-patch.c +#, c-format +msgid "Discard addition from worktree [y,n,q,a,d%s,?]? " +msgstr "Scrios an breiseán ón gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? " +msgstr "" +"An bhfuil an pÃosa beag seo le fáil réidh ón gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"discarding." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach lena dhiúscairt." + +#: add-patch.c +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\n" +msgstr "" +"y - caitheamh an bonc seo ón gcrann oibre\n" +"n - ná caitheamh an hunk seo ón gcrann oibre\n" +"q - scor; ná caith an hunk seo ná aon cheann de na cinn atá fágtha\n" +"a - caith an hunk seo agus gach hunc ina dhiaidh sin sa chomhad\n" +"d - ná caith an hunk seo ná aon cheann de na huncanna nÃos déanaà sa " +"chomhad\n" + +#: add-patch.c +#, c-format +msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Athrú modh a dhiúscairt ó innéacs agus crann oibre [y, n, q, a, d %s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"An scriosadh ón innéacs agus ón gcrann oibre [y,n,q,a,d%s,?] a dhÃbirt? " + +#: add-patch.c +#, c-format +msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? " +msgstr "Caitheamh breisiú ó innéacs agus crann oibre [y, n, q, a, d %s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"An bhfuil an pÃosa beag seo le fáil réidh ón innéacs agus ón gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"y - discard this hunk from index and worktree\n" +"n - do not discard this hunk from index and worktree\n" +"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\n" +msgstr "" +"y - caitheamh an hunk seo ón innéacs agus ón gcrann oibre\n" +"n - ná caith an hunk seo ón innéacs agus ón gcrann oibre\n" +"q - scor; ná caith an hunk seo ná aon cheann de na cinn atá fágtha\n" +"a - caith an hunk seo agus gach hunc ina dhiaidh sin sa chomhad\n" +"d - ná caith an hunk seo ná aon cheann de na huncanna nÃos déanaà sa " +"chomhad\n" + +#: add-patch.c +#, c-format +msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir athrú mód i bhfeidhm ar an innéacs agus ar an gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir scriosadh i bhfeidhm ar innéacs agus crann oibre [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir an breiseán i bhfeidhm ar an innéacs agus ar an gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir an pÃosa seo i bhfeidhm ar an innéacs agus ar an gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"y - apply this hunk to index and worktree\n" +"n - do not apply this hunk to index and worktree\n" +"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\n" +msgstr "" +"y - cuir an hunk seo i bhfeidhm ar innéacs agus ar chrann oibre\n" +"n - ná cuir an hunk seo i bhfeidhm ar innéacs agus crann oibre\n" +"q - scor; ná cuir an hunk seo ná aon cheann de na cinn atá fágtha i " +"bhfeidhm\n" +"a - cuir an hunk seo agus gach hunk nÃos déanaà i bhfeidhm sa chomhad\n" +"d - ná cuir an hunk seo ná aon cheann de na hunks nÃos déanaà sa chomhad i " +"bhfeidhm\n" + +#: add-patch.c +#, c-format +msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir athrú mód i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir scriosadh i bhfeidhm ar chrann oibre [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply addition to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir an breiseán i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir an pÃosa seo i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"y - apply this hunk to worktree\n" +"n - do not apply this hunk to worktree\n" +"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\n" +msgstr "" +"y - cuir an hunk seo i bhfeidhm ar chrann oibre\n" +"n - ná cuir an hunk seo i bhfeidhm ar chrann oibre\n" +"q - scor; ná cuir an hunk seo ná aon cheann de na cinn atá fágtha i " +"bhfeidhm\n" +"a - cuir an hunk seo agus gach hunk nÃos déanaà i bhfeidhm sa chomhad\n" +"d - ná cuir an hunk seo ná aon cheann de na hunks nÃos déanaà sa chomhad i " +"bhfeidhm\n" + +#: add-patch.c +#, c-format +msgid "could not parse hunk header '%.*s'" +msgstr "nÃorbh fhéidir ceanntásc an bhlúire '%.*s' a pharsáil" + +#: add-patch.c +msgid "could not parse diff" +msgstr "nà raibh sé in ann difrÃocht a pharsáil" + +#: add-patch.c +msgid "could not parse colored diff" +msgstr "nà raibh sé in ann difrÃocht daite a pháirseáil" + +#: add-patch.c +#, c-format +msgid "failed to run '%s'" +msgstr "theip ar '%s' a reáchtáil" + +#: add-patch.c +msgid "mismatched output from interactive.diffFilter" +msgstr "aschur mÃ-mheaitseáilte ó interactive.diffFilter" + +#: add-patch.c +msgid "" +"Your filter must maintain a one-to-one correspondence\n" +"between its input and output lines." +msgstr "" +"Caithfidh do scagaire comhfhreagras duine le duine a choinneáil\n" +"idir a lÃnte ionchuir agus aschuir." + +#: add-patch.c +#, c-format +msgid "" +"expected context line #%d in\n" +"%.*s" +msgstr "" +"lÃne comhthéacs a bhfuil súil leo #%d i\n" +"%.*s" + +#: add-patch.c +#, c-format +msgid "" +"hunks do not overlap:\n" +"%.*s\n" +"\tdoes not end with:\n" +"%.*s" +msgstr "" +"nà fhorluÃonn hunks:\n" +"%.*s\n" +" nà chrÃochnaÃonn sé le:\n" +"%.*s" + +#: add-patch.c +msgid "Manual hunk edit mode -- see bottom for a quick guide.\n" +msgstr "" +"Modh eagarthóireachta hunk láimhe - féach an bun le haghaidh treoir thapa.\n" + +#: add-patch.c +#, c-format +msgid "" +"---\n" +"To remove '%c' lines, make them ' ' lines (context).\n" +"To remove '%c' lines, delete them.\n" +"Lines starting with %s will be removed.\n" +msgstr "" +"---\n" +"Chun lÃnte '%c' a bhaint, déan lÃnte '' iad (comhthéacs).\n" +"Chun lÃnte '%c' a bhaint, scrios iad.\n" +"Bainfear lÃnte a thosaÃonn le %s.\n" + +#: add-patch.c +msgid "" +"If it does not apply cleanly, you will be given an opportunity to\n" +"edit again. If all lines of the hunk are removed, then the edit is\n" +"aborted and the hunk is left unchanged.\n" +msgstr "" +"Mura bhfuil feidhm aige go glan, tabharfar deis duit\n" +"cuir in eagar arÃs. Má bhaintear gach lÃne den hunk, ansin is é an t-" +"eagarthóireacht\n" +"cuireadh isteach agus fágtar an hunk gan athrú.\n" + +#: add-patch.c +msgid "could not parse hunk header" +msgstr "nà fhéadfaà ceanntásc hunk a pháirseáil" + +#: add-patch.c +msgid "'git apply --cached' failed" +msgstr "Theip ar 'git apply --cached'" + +#. 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. +#. +#: add-patch.c +msgid "" +"Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? " +msgstr "" +"Nà bhaineann do chuid eagraithe. Cuir in eagar arÃs (ag rá \"nÃl\" cuirtear " +"i leataobh é!) [y/n]? " + +#: add-patch.c +msgid "The selected hunks do not apply to the index!" +msgstr "Nà bhaineann na hunks roghnaithe leis an innéacs!" + +#: add-patch.c +msgid "Apply them to the worktree anyway? " +msgstr "An gcuirfidh tú i bhfeidhm iad ar an gcrann oibre ar aon nós? " + +#: add-patch.c +msgid "Nothing was applied.\n" +msgstr "Nà chuirtear aon rud i bhfeidhm.\n" + +#: add-patch.c +msgid "" +"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" +"g - select a hunk to go to\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, 'P' to use the pager\n" +"? - print help\n" +msgstr "" +"j - fág an hunk seo gan chinneadh, féach an chéad hunk neamhchinnte eile\n" +"J - fág an hunk seo gan chinneadh, féach an chéad hunk eile\n" +"k - fág an hunk seo gan chinneadh, féach an hunk neamhchinnte roimhe seo\n" +"K - fág an hunk seo gan chinneadh, féach an hunk roimhe seo\n" +"g - roghnaigh hunk le dul chuig\n" +"/- cuardaigh hunk a mheaitseann leis an regex a thugtar\n" +"s - roinn an hunk reatha ina huncanna nÃos lú\n" +"e - cuir an hunk reatha in eagar de láimh\n" +"p - priontáil an hunk reatha, 'P' chun an pager a úsáid\n" +"? - cabhair priontála\n" + +#: add-patch.c +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "NÃl súil leis ach litir amháin, fuair '%s'" + +#: add-patch.c +msgid "No previous hunk" +msgstr "NÃl aon hunk roimhe seo" + +#: add-patch.c +msgid "No next hunk" +msgstr "NÃl aon chéad hunk eile" + +#: add-patch.c +msgid "No other hunks to goto" +msgstr "NÃl aon ghuncanna eile le dul" + +#: add-patch.c +msgid "go to which hunk (<ret> to see more)? " +msgstr "téigh chuig cén hunk (<ret> le tuilleadh a fheiceáil)? " + +#: add-patch.c +msgid "go to which hunk? " +msgstr "téigh chuig cén hunk? " + +#: add-patch.c +#, c-format +msgid "Invalid number: '%s'" +msgstr "Uimhir neamhbhailÃ: '%s'" + +#: add-patch.c +#, c-format +msgid "Sorry, only %d hunk available." +msgid_plural "Sorry, only %d hunks available." +msgstr[0] "Tá brón orm, nÃl ach %d pÃosa ar fáil." +msgstr[1] "Tá brón orm, nÃl ach %d hunks ar fáil." +msgstr[2] "Tá brón orm, nÃl ach %d hunks ar fáil." + +#: add-patch.c +msgid "No other hunks to search" +msgstr "NÃl aon ghuncanna eile le cuardach" + +#: add-patch.c +msgid "search for regex? " +msgstr "cuardach a dhéanamh ar regex? " + +#: add-patch.c +#, c-format +msgid "Malformed search regexp %s: %s" +msgstr "Regexp cuardaigh mÃfheidhmithe %s: %s" + +#: add-patch.c +msgid "No hunk matches the given pattern" +msgstr "NÃl aon hunk ag teacht leis an bpatrún tugtha" + +#: add-patch.c +msgid "Sorry, cannot split this hunk" +msgstr "Tá brón orainn, nà féidir an hunk seo a roinnt" + +#: add-patch.c +#, c-format +msgid "Split into %d hunks." +msgstr "Roinn ina %d hunks." + +#: add-patch.c +msgid "Sorry, cannot edit this hunk" +msgstr "Tá brón orainn, nà féidir an hunk seo a chur in eagar" + +#: add-patch.c +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Ordú anaithnid '%s' (bain úsáid as '?' le haghaidh cabhair)" + +#: add-patch.c +msgid "'git apply' failed" +msgstr "Theip ar 'git apply'" + +#: add-patch.c +msgid "No changes." +msgstr "Gan aon athruithe." + +#: add-patch.c +msgid "Only binary files changed." +msgstr "NÃor athraigh ach comhaid dénártha." + +#: advice.c +#, c-format +msgid "" +"\n" +"Disable this message with \"git config set advice.%s false\"" +msgstr "" +"\n" +"DÃchumasaigh an teachtaireacht seo le \"git config set advice.%s false\"" + +#: advice.c +#, c-format +msgid "%shint:%s%.*s%s\n" +msgstr "%sleid:%s%.*s%s\n" + +#: advice.c +msgid "Cherry-picking is not possible because you have unmerged files." +msgstr "" +"Nà féidir piocadh silÃnà toisc go bhfuil comhaid neamh-chumasaithe agat." + +#: advice.c +msgid "Committing is not possible because you have unmerged files." +msgstr "" +"Nà féidir tiomantas a dhéanamh toisc go bhfuil comhaid neamh-" +"chomhcheangailte agat." + +#: advice.c +msgid "Merging is not possible because you have unmerged files." +msgstr "" +"Nà féidir cumasc a dhéanamh toisc go bhfuil comhaid neamh-chumasaithe agat." + +#: advice.c +msgid "Pulling is not possible because you have unmerged files." +msgstr "" +"Nà féidir tarraingt a tharraingt toisc go bhfuil comhaid neamh-chumasaithe " +"agat." + +#: advice.c +msgid "Reverting is not possible because you have unmerged files." +msgstr "" +"Nà féidir aisiompú toisc go bhfuil comhaid neamh-chomhcheangailte agat." + +#: advice.c +msgid "Rebasing is not possible because you have unmerged files." +msgstr "" +"Nà féidir athbhunú a dhéanamh toisc go bhfuil comhaid neamh-chumasaithe agat." + +#: advice.c +msgid "" +"Fix them up in the work tree, and then use 'git add/rm <file>'\n" +"as appropriate to mark resolution and make a commit." +msgstr "" +"<file>Socraigh iad sa chrann oibre, agus ansin bain úsáid as 'git add/rm '\n" +"de réir mar is cuà chun réiteach a mharcáil agus tiomantas a dhéanamh." + +#: advice.c +msgid "Exiting because of an unresolved conflict." +msgstr "Ag imeacht mar gheall ar choimhlint neamhréitithe." + +#: advice.c builtin/merge.c +msgid "You have not concluded your merge (MERGE_HEAD exists)." +msgstr "NÃor thug tú do chumasc i gcrÃch (MERGE_HEAD ann)." + +#: advice.c +msgid "Please, commit your changes before merging." +msgstr "Déan d'athruithe a dhéanamh le do thoil sula ndéanann tú cumasc." + +#: advice.c +msgid "Exiting because of unfinished merge." +msgstr "Ag imeacht mar gheall ar chumasc crÃochnaithe." + +#: advice.c +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 "" +"Nà féidir brainsà éagsúla a chur ar aghaidh go tapa, nà mór duit:\n" +"\n" +" git merge --no-ff\n" +"\n" +"nó:\n" +"\n" +" git rebase\n" + +#: advice.c +msgid "Not possible to fast-forward, aborting." +msgstr "Nà féidir dul ar aghaidh go tapa, ag cur isteach." + +#: advice.c +#, c-format +msgid "" +"The following paths and/or pathspecs matched paths that exist\n" +"outside of your sparse-checkout definition, so will not be\n" +"updated in the index:\n" +msgstr "" +"Meaitseáil na cosáin agus/nó na cosáin seo a leanas cosáin ann\n" +"lasmuigh de do shainmhÃniú seiceála neamhchoitianta, mar sin nà bheidh\n" +"nuashonraithe san innéacs:\n" + +#: advice.c +msgid "" +"If you intend to update such entries, try one of the following:\n" +"* Use the --sparse option.\n" +"* Disable or modify the sparsity rules." +msgstr "" +"Má tá sé ar intinn agat iontrálacha den sórt sin a nuashonrú, bain triail as " +"ceann amháin de\n" +"* Úsáid an rogha --sparse.\n" +"* DÃchumasaigh nó modhnaigh na rialacha neamhghnách." + +#: advice.c +#, c-format +msgid "" +"Note: switching to '%s'.\n" +"\n" +"You are in 'detached HEAD' state. You can look around, make experimental\n" +"changes and commit them, and you can discard any commits you make in this\n" +"state without impacting any branches by switching back to a branch.\n" +"\n" +"If you want to create a new branch to retain commits you create, you may\n" +"do so (now or later) by using -c with the switch command. Example:\n" +"\n" +" git switch -c <new-branch-name>\n" +"\n" +"Or undo this operation with:\n" +"\n" +" git switch -\n" +"\n" +"Turn off this advice by setting config variable advice.detachedHead to " +"false\n" +"\n" +msgstr "" +"Nóta: ag aistriú go '%s'.\n" +"\n" +"Tá tú i stát 'CEANN scoite'. Is féidir leat breathnú timpeall, turgnamhach a " +"dhéanamh\n" +"athruithe agus iad a dhéanamh, agus féadfaidh tú aon gealltanais a dhéanann " +"tú san áireamh a dhiúscairt\n" +"stáit gan dul i bhfeidhm ar aon bhrainsà trà aistriú ar ais chuig brainse.\n" +"\n" +"Más mian leat brainse nua a chruthú chun gealltanais a chruthaÃonn tú a " +"choinneáil, féadfaidh tú\n" +"déan amhlaidh (anois nó nÃos déanaÃ) trà úsáid a bhaint as -c leis an ordú " +"lasc. Sampla:\n" +"\n" +" git switch -c <new-branch-name>\n" +"\n" +"Nó cealaigh an oibrÃocht seo le:\n" +"\n" +" git switch -c <new-branch-name>\n" +"\n" +"Múch an chomhairle seo trà chomhairle athróg advice.detachedHead a shocrú go " +"false\n" +"\n" + +#: advice.c +#, 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 "" +"Tá na cosáin seo a leanas bogadh taobh amuigh den\n" +"sainmhÃniú seiceála neamhchoitianta ach nÃl siad neamhchoitiúil mar gheall " +"ar an\n" +"modhnuithe.\n" + +#: advice.c +msgid "" +"To correct the sparsity of these paths, do the following:\n" +"* Use \"git add --sparse <paths>\" to update the index\n" +"* Use \"git sparse-checkout reapply\" to apply the sparsity rules" +msgstr "" +"Chun neamhghnáth na gcosáin seo a cheartú, déan an méid seo a leanas:\n" +"* Úsáid “git add --sparse<paths>\" chun an t-innéacs a nuashonrú\n" +"* Úsáid “git sparse-checkout reapply†chun na rialacha neamhchoitianta a " +"chur i bhfeidhm" + +#: alias.c +msgid "cmdline ends with \\" +msgstr "crÃochnaÃonn cmdline le \\" + +#: alias.c +msgid "unclosed quote" +msgstr "luachan neamhdhúnadh" + +#: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c +#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c +msgid "too many arguments" +msgstr "an iomarca argóintÃ" + +#: apply.c +#, c-format +msgid "unrecognized whitespace option '%s'" +msgstr "rogha spás bán gan aithint '%s'" + +#: apply.c +#, c-format +msgid "unrecognized whitespace ignore option '%s'" +msgstr "neamhaird ar spás bán gan aithint neamhaird ar rogha '%s'" + +#: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c +#: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c +#: builtin/describe.c builtin/diff-tree.c builtin/difftool.c +#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c +#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c +#: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c +#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-parse.c +#: builtin/show-branch.c builtin/stash.c builtin/submodule--helper.c +#: builtin/tag.c builtin/worktree.c parse-options.c range-diff.c revision.c +#, c-format +msgid "options '%s' and '%s' cannot be used together" +msgstr "nà féidir roghanna '%s' agus '%s' a úsáid le chéile" + +#: apply.c +#, c-format +msgid "'%s' outside a repository" +msgstr "'%s' lasmuigh de stór" + +#: apply.c +msgid "failed to read patch" +msgstr "theip ar phaiste a léamh" + +#: apply.c +msgid "patch too large" +msgstr "paiste ró-mhór" + +#: apply.c +#, c-format +msgid "Cannot prepare timestamp regexp %s" +msgstr "Nà féidir regexp %s aimstampa a ullmhú" + +#: apply.c +#, c-format +msgid "regexec returned %d for input: %s" +msgstr "d'fhill regexec %d le haghaidh ionchur: %s" + +#: apply.c +#, c-format +msgid "unable to find filename in patch at line %d" +msgstr "nà féidir ainm comhaid a aimsiú i bpaiste ag an lÃne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d" +msgstr "git apply: bad git-diff - ag súil le /dev/null, fuair %s ar lÃne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - inconsistent new filename on line %d" +msgstr "" +"git apply: bad git-diff - ainm comhaid nua neamhchomhsheasmhach ar lÃne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - inconsistent old filename on line %d" +msgstr "git apply: bad git-diff - sean-ainm comhaid neamhréireach ar lÃne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - expected /dev/null on line %d" +msgstr "git apply: bad git-diff - súil leis /dev/null ar lÃne %d" + +#: apply.c +#, c-format +msgid "invalid mode on line %d: %s" +msgstr "modh neamhbhailà ar lÃne %d: %s" + +#: apply.c +#, c-format +msgid "inconsistent header lines %d and %d" +msgstr "lÃnte ceanntásc neamhchomhsheasmhach %d agus %d" + +#: apply.c +#, c-format +msgid "" +"git diff header lacks filename information when removing %d leading pathname " +"component (line %d)" +msgid_plural "" +"git diff header lacks filename information when removing %d leading pathname " +"components (line %d)" +msgstr[0] "" +"tá easpa eolais ainm comhaid ar cheanntásc git diff nuair a bhaintear %d " +"comhpháirt ainm cosáin tosaigh (lÃne %d)" +msgstr[1] "" +"tá easpa eolais ainm comhaid ar cheanntásc git diff agus %d comhpháirteanna " +"ainm cosáin tosaigh á mbaint (lÃne %d)" +msgstr[2] "" +"tá easpa eolais ainm comhaid ar cheanntásc git diff agus %d comhpháirteanna " +"ainm cosáin tosaigh á mbaint (lÃne %d)" + +#: apply.c +#, c-format +msgid "git diff header lacks filename information (line %d)" +msgstr "tá easpa eolais ainm comhaid ar cheanntásc git diff (lÃne %d)" + +#: apply.c +#, c-format +msgid "recount: unexpected line: %.*s" +msgstr "atháireamh: lÃne gan choinne: %.*s" + +#: apply.c +#, c-format +msgid "patch fragment without header at line %d: %.*s" +msgstr "blúirt paiste gan ceanntásc ag an lÃne %d: %.*s" + +#: apply.c +msgid "new file depends on old contents" +msgstr "braitheann comhad nua ar shean-ábhar" + +#: apply.c +msgid "deleted file still has contents" +msgstr "tá ábhar fós ag comhad scriosta" + +#: apply.c +#, c-format +msgid "corrupt patch at line %d" +msgstr "paiste truaillithe ag lÃne %d" + +#: apply.c +#, c-format +msgid "new file %s depends on old contents" +msgstr "braitheann an comhad nua %s ar an seanábhar" + +#: apply.c +#, c-format +msgid "deleted file %s still has contents" +msgstr "tá ábhar fós ag comhad scriosta %s" + +#: apply.c +#, c-format +msgid "** warning: file %s becomes empty but is not deleted" +msgstr "** rabhadh: éirÃonn comhad %s folamh ach nà scriostar é" + +#: apply.c +#, c-format +msgid "corrupt binary patch at line %d: %.*s" +msgstr "paiste dénártha truaillithe ag lÃne %d: %.*s" + +#: apply.c +#, c-format +msgid "unrecognized binary patch at line %d" +msgstr "paiste dénártha gan aithint ag an lÃne %d" + +#: apply.c +#, c-format +msgid "patch with only garbage at line %d" +msgstr "paiste gan ach truflais ag an lÃne %d" + +#: apply.c +#, c-format +msgid "unable to read symlink %s" +msgstr "nach féidir nasc simtéarach %s a léamh" + +#: apply.c +#, c-format +msgid "unable to open or read %s" +msgstr "nach féidir %s a oscailt nó a léamh" + +#: apply.c +#, c-format +msgid "invalid start of line: '%c'" +msgstr "tús neamhbhailà na lÃne: '%c'" + +#: apply.c +#, c-format +msgid "Hunk #%d succeeded at %d (offset %d line)." +msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." +msgstr[0] "D'éirigh le hunk #%d ag %d (lÃne fhritháireamh %d)." +msgstr[1] "D'éirigh le hunk #%d ag %d (%d lÃne curtha as feidhm)." +msgstr[2] "D'éirigh le hunk #%d ag %d (%d lÃne curtha as feidhm)." + +#: apply.c +#, c-format +msgid "Context reduced to (%ld/%ld) to apply fragment at %d" +msgstr "Laghdaithe comhthéacs go (%ld/%ld) chun blúire a chur i bhfeidhm ag %d" + +#: apply.c +#, c-format +msgid "" +"while searching for:\n" +"%.*s" +msgstr "" +"agus tú ag cuardach:\n" +"%.*s" + +#: apply.c +#, c-format +msgid "missing binary patch data for '%s'" +msgstr "sonraà paiste dénártha in easnamh do '%s'" + +#: apply.c +#, c-format +msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'" +msgstr "" +"nà féidir paiste dénártha a chur i bhfeidhm ar ais gan an hunk droim ar ais " +"chuig '%s'" + +#: apply.c +#, c-format +msgid "cannot apply binary patch to '%s' without full index line" +msgstr "" +"nà féidir paiste dénártha a chur i bhfeidhm ar '%s' gan lÃne innéacs iomlán" + +#: apply.c +#, c-format +msgid "" +"the patch applies to '%s' (%s), which does not match the current contents." +msgstr "" +"baineann an paiste le '%s' (%s), nach bhfuil comhoiriúnach leis an ábhar " +"reatha." + +#: apply.c +#, c-format +msgid "the patch applies to an empty '%s' but it is not empty" +msgstr "baineann an paiste le '%s' folamh ach nÃl sé folamh" + +#: apply.c +#, c-format +msgid "the necessary postimage %s for '%s' cannot be read" +msgstr "nà féidir an post riachtanach %s le haghaidh '%s' a léamh" + +#: apply.c +#, c-format +msgid "binary patch does not apply to '%s'" +msgstr "nà bhaineann paiste dénártha le '%s'" + +#: apply.c +#, c-format +msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" +msgstr "" +"cruthaÃonn paiste dénártha chuig '%s' toradh mÃcheart (ag súil le %s, fuair " +"%s)" + +#: apply.c +#, c-format +msgid "patch failed: %s:%ld" +msgstr "theip ar phaiste: %s: %ld" + +#: apply.c builtin/mv.c +#, c-format +msgid "cannot checkout %s" +msgstr "nà féidir %s a sheiceáil" + +#: apply.c midx.c pack-mtimes.c pack-revindex.c setup.c +#, c-format +msgid "failed to read %s" +msgstr "theip ar %s a léamh" + +#: apply.c +#, c-format +msgid "reading from '%s' beyond a symbolic link" +msgstr "léamh ó '%s' nÃos faide ná nasc siombalach" + +#: apply.c +#, c-format +msgid "path %s has been renamed/deleted" +msgstr "tá conair %s athainmnithe/scriosta" + +#: apply.c +#, c-format +msgid "%s: does not exist in index" +msgstr "%s: nÃl ann san innéacs" + +#: apply.c +#, c-format +msgid "%s: does not match index" +msgstr "%s: nà mheaitseálann innéacs" + +#: apply.c +msgid "repository lacks the necessary blob to perform 3-way merge." +msgstr "nÃl an blob riachtanach ag stór chun cumasc trà bhealach a dhéanamh." + +#: apply.c +#, c-format +msgid "Performing three-way merge...\n" +msgstr "Cumaisc trà bhealach a dhéanamh...\n" + +#: apply.c +#, c-format +msgid "cannot read the current contents of '%s'" +msgstr "nà féidir ábhar reatha '%s' a léamh" + +#: apply.c +#, c-format +msgid "Failed to perform three-way merge...\n" +msgstr "Theip ar chumasc trà bhealach a dhéanamh...\n" + +#: apply.c +#, c-format +msgid "Applied patch to '%s' with conflicts.\n" +msgstr "Paiste cuireadh i bhfeidhm ar '%s' le coinbhleachtaÃ.\n" + +#: apply.c +#, c-format +msgid "Applied patch to '%s' cleanly.\n" +msgstr "Cuireadh paiste i bhfeidhm go '%s' go glan.\n" + +#: apply.c +#, c-format +msgid "Falling back to direct application...\n" +msgstr "Ag titim ar ais chuig feidhmchlár dÃreach...\n" + +#: apply.c +msgid "removal patch leaves file contents" +msgstr "fágann paiste bainte ábhar an chomhaid" + +#: apply.c +#, c-format +msgid "%s: wrong type" +msgstr "%s: cineál mÃcheart" + +#: apply.c +#, c-format +msgid "%s has type %o, expected %o" +msgstr "%s tá cineál %o air, ach bhÃothas ag súil le %o" + +#: apply.c read-cache.c +#, c-format +msgid "invalid path '%s'" +msgstr "cosán neamhbhailà '%s'" + +#: apply.c +#, c-format +msgid "%s: already exists in index" +msgstr "%s: ann cheana féin san innéacs" + +#: apply.c +#, c-format +msgid "%s: already exists in working directory" +msgstr "%s: ann cheana féin san eolaire oibre" + +#: apply.c +#, c-format +msgid "new mode (%o) of %s does not match old mode (%o)" +msgstr "nà mheaitseálann modh nua (%o) de %s sean-mhodh (%o)" + +#: apply.c +#, c-format +msgid "new mode (%o) of %s does not match old mode (%o) of %s" +msgstr "nà mheaitseálann modh nua (%o) de %s sean-mhodh (%o) de %s" + +#: apply.c +#, c-format +msgid "affected file '%s' is beyond a symbolic link" +msgstr "tá an comhad tionchair '%s' nÃos faide ná nasc siombalach" + +#: apply.c +#, c-format +msgid "%s: patch does not apply" +msgstr "%s: nÃl paiste i bhfeidhm" + +#: apply.c +#, c-format +msgid "Checking patch %s..." +msgstr "Seiceáil paiste %s..." + +#: apply.c +#, c-format +msgid "sha1 information is lacking or useless for submodule %s" +msgstr "tá faisnéis sha1 easpa nó gan úsáid le haghaidh fo-mhodúl %s" + +#: apply.c +#, c-format +msgid "mode change for %s, which is not in current HEAD" +msgstr "athrú modh do %s, nach bhfuil i HEAD reatha" + +#: apply.c +#, c-format +msgid "sha1 information is lacking or useless (%s)." +msgstr "tá faisnéis sha1 easpa nó gan úsáid (%s)." + +#: apply.c +#, c-format +msgid "could not add %s to temporary index" +msgstr "nà fhéadfaà %s a chur le hinnéacs sealadach" + +#: apply.c +#, c-format +msgid "could not write temporary index to %s" +msgstr "nà fhéadfaà innéacs sealadach a scrÃobh chuig %s" + +#: apply.c +#, c-format +msgid "unable to remove %s from index" +msgstr "nach féidir %s a bhaint as innéacs" + +#: apply.c +#, c-format +msgid "corrupt patch for submodule %s" +msgstr "paiste truaillithe do fho-mhodúl %s" + +#: apply.c +#, c-format +msgid "unable to stat newly created file '%s'" +msgstr "nach féidir an comhad nua-chruthaithe '%s' a stáil" + +#: apply.c +#, c-format +msgid "unable to create backing store for newly created file %s" +msgstr "nach féidir stór tacaÃochta a chruthú do chomhad nua-chruthaithe %s" + +#: apply.c +#, c-format +msgid "unable to add cache entry for %s" +msgstr "nach féidir iontráil taisce a chur le haghaidh %s" + +#: apply.c builtin/bisect.c builtin/gc.c +#, c-format +msgid "failed to write to '%s'" +msgstr "theip ar scrÃobh chuig '%s'" + +#: apply.c +#, c-format +msgid "closing file '%s'" +msgstr "comhad dúnadh '%s'" + +#: apply.c +#, c-format +msgid "unable to write file '%s' mode %o" +msgstr "nà féidir an comhad '%s' modh %o a scrÃobh" + +#: apply.c +#, c-format +msgid "Applied patch %s cleanly." +msgstr "Cuireadh paiste %s i bhfeidhm go glan." + +#: apply.c +msgid "internal error" +msgstr "earráid inmheánach" + +#: apply.c +#, c-format +msgid "Applying patch %%s with %d reject..." +msgid_plural "Applying patch %%s with %d rejects..." +msgstr[0] "Ag cur paiste %%s i bhfeidhm le %d diúltú..." +msgstr[1] "Ag cur paiste %%s i bhfeidhm le %d diúltuithe..." +msgstr[2] "Ag cur paiste %%s i bhfeidhm le %d diúltuithe..." + +#: apply.c +#, c-format +msgid "cannot open %s" +msgstr "nà féidir %s a oscailt" + +#: apply.c rerere.c +#, c-format +msgid "cannot unlink '%s'" +msgstr "nà féidir '%s' a dhÃnascadh" + +#: apply.c +#, c-format +msgid "Hunk #%d applied cleanly." +msgstr "Cuireadh Hunk #%d i bhfeidhm go glan." + +#: apply.c +#, c-format +msgid "Rejected hunk #%d." +msgstr "Hunk diúltaithe #%d." + +#: apply.c +#, c-format +msgid "Skipped patch '%s'." +msgstr "Paiste scipeáilte '%s'." + +#: apply.c +msgid "No valid patches in input (allow with \"--allow-empty\")" +msgstr "NÃl aon paistà bailà san ionchur (cead le “--allow-emptyâ€)" + +#: apply.c t/helper/test-cache-tree.c +msgid "unable to read index file" +msgstr "in ann comhad innéacs a léamh" + +#: apply.c +#, c-format +msgid "can't open patch '%s': %s" +msgstr "nà féidir paiste '%s' a oscailt: %s" + +#: apply.c +#, c-format +msgid "squelched %d whitespace error" +msgid_plural "squelched %d whitespace errors" +msgstr[0] "earráid spás bán %d múchta" +msgstr[1] "%d earráid spás bán múchta" +msgstr[2] "%d earráid spás bán múchta" + +#: apply.c +#, c-format +msgid "%d line adds whitespace errors." +msgid_plural "%d lines add whitespace errors." +msgstr[0] "Cuireann %d lÃne earráidà spás bán leis." +msgstr[1] "Cuireann %d lÃne earráidà spás bán leis." +msgstr[2] "Cuireann %d lÃne earráidà spás bán leis." + +#: apply.c +#, c-format +msgid "%d line applied after fixing whitespace errors." +msgid_plural "%d lines applied after fixing whitespace errors." +msgstr[0] "%d lÃne curtha i bhfeidhm tar éis earráidà spás bán a shocrú." +msgstr[1] "%d lÃne curtha i bhfeidhm tar éis earráidà spás bán a shocrú." +msgstr[2] "%d lÃne curtha i bhfeidhm tar éis earráidà spás bán a shocrú." + +#: apply.c builtin/mv.c builtin/rm.c +msgid "Unable to write new index file" +msgstr "Nà féidir comhad innéacs nua a scrÃobh" + +#: apply.c +msgid "don't apply changes matching the given path" +msgstr "ná cuir athruithe a mheaitseáil leis an gcosán tugtha" + +#: apply.c +msgid "apply changes matching the given path" +msgstr "athruithe a chur i bhfeidhm a mheaitseálann" + +#: apply.c builtin/am.c +msgid "num" +msgstr "uimhir" + +#: apply.c +msgid "remove <num> leading slashes from traditional diff paths" +msgstr "bain <num>slascanna ceannródaÃocha ó chosáin difriúla traidisiúnta" + +#: apply.c +msgid "ignore additions made by the patch" +msgstr "neamhaird a dhéanamh ar bhreiseanna a dhéanann an" + +#: apply.c +msgid "instead of applying the patch, output diffstat for the input" +msgstr "in ionad an paiste a chur i bhfeidhm, diffstat aschuir don ionchur" + +#: apply.c +msgid "show number of added and deleted lines in decimal notation" +msgstr "lÃon na lÃnte breise agus scriosta a thaispeáint i nótaà deachúil" + +#: apply.c +msgid "instead of applying the patch, output a summary for the input" +msgstr "in ionad an paiste a chur i bhfeidhm, aschur achoimre don ionchur" + +#: apply.c +msgid "instead of applying the patch, see if the patch is applicable" +msgstr "" +"in ionad an paiste a chur i bhfeidhm, féach an bhfuil an paiste infheidhme" + +#: apply.c +msgid "make sure the patch is applicable to the current index" +msgstr "" +"déan cinnte go bhfuil an paiste infheidhme maidir leis an innéacs reatha" + +#: apply.c +msgid "mark new files with `git add --intent-to-add`" +msgstr "comhad nua a mharcáil le `git add --intent-to-add`" + +#: apply.c +msgid "apply a patch without touching the working tree" +msgstr "cuir paiste i bhfeidhm gan teagmháil leis an gcrann oibre" + +#: apply.c +msgid "accept a patch that touches outside the working area" +msgstr "glacadh le paiste a théann lasmuigh den limistéar oibre" + +#: apply.c +msgid "also apply the patch (use with --stat/--summary/--check)" +msgstr "" +"cuir an paiste i bhfeidhm freisin (bain úsáid le --stat/--summary/--check)" + +#: apply.c +msgid "attempt three-way merge, fall back on normal patch if that fails" +msgstr "" +"iarracht a dhéanamh cumasc trà bhealach, titim ar ais ar ghnáthphaiste má " +"theipeann" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use our version" +msgstr "le haghaidh coimhlintÃ, bain úsáid as ár leagan" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use their version" +msgstr "le haghaidh coimhlintÃ, bain úsáid as a leagan" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use a union version" +msgstr "le haghaidh coimhlintÃ, bain úsáid as leagan aontais" + +#: apply.c +msgid "build a temporary index based on embedded index information" +msgstr "innéacs sealadach a thógáil bunaithe ar eolas innéacs leabaithe" + +#: apply.c builtin/checkout-index.c +msgid "paths are separated with NUL character" +msgstr "tá cosáin scartha le carachtar NUL" + +#: apply.c +msgid "ensure at least <n> lines of context match" +msgstr "a chinntiú go mbe <n>adh lÃnte comhthéacsa" + +#: apply.c builtin/am.c builtin/interpret-trailers.c builtin/pack-objects.c +#: builtin/rebase.c +msgid "action" +msgstr "gnÃomh" + +#: apply.c +msgid "detect new or modified lines that have whitespace errors" +msgstr "lÃnte nua nó modhnaithe a bhrath a bhfuil earráidà spás bán acu" + +#: apply.c +msgid "ignore changes in whitespace when finding context" +msgstr "neamhaird a dhéanamh ar athruithe ar spás bán agus comhthéacs á" + +#: apply.c +msgid "apply the patch in reverse" +msgstr "cuir an paiste i bhfeidhm ar ais" + +#: apply.c +msgid "don't expect at least one line of context" +msgstr "ná bà ag súil le lÃne comhthéacs amháin ar a laghad" + +#: apply.c +msgid "leave the rejected hunks in corresponding *.rej files" +msgstr "fág na hunks diúltaithe i gcomhaide*.rej comhfhreagracha" + +#: apply.c +msgid "allow overlapping hunks" +msgstr "cead a cheadú do na huncanna" + +#: apply.c +msgid "tolerate incorrectly detected missing new-line at the end of file" +msgstr "" +"glacadh le lÃne nua atá in easnamh a bhraitear go mÃcheart ag deireadh an " +"chomhaid" + +#: apply.c +msgid "do not trust the line counts in the hunk headers" +msgstr "ná bÃodh muinÃn agat as na comhaireamh lÃne sna ceanntásca hunk" + +#: apply.c builtin/am.c +msgid "root" +msgstr "fréamh" + +#: apply.c +msgid "prepend <root> to all filenames" +msgstr "cuireadh <root>i bhfeidhm ar gach ainm comhaid" + +#: apply.c +msgid "don't return error for empty patches" +msgstr "ná tabhair earráid ar ais le haghaidh paistà folamh" + +#: apply.c +msgid "--ours, --theirs, and --union require --3way" +msgstr "ÉilÃonn --ours, --theirs, agus --union --3way" + +#: archive-tar.c archive-zip.c +#, c-format +msgid "cannot stream blob %s" +msgstr "nà féidir le blob %s a shruthlú" + +#: archive-tar.c archive-zip.c +#, c-format +msgid "unsupported file mode: 0%o (SHA1: %s)" +msgstr "modh comhad gan tacaÃocht: 0%o (SHA1: %s)" + +#: archive-tar.c archive-zip.c builtin/pack-objects.c +#, c-format +msgid "deflate error (%d)" +msgstr "earráid dÃfhabhtaithe (%d)" + +#: archive-tar.c +#, c-format +msgid "unable to start '%s' filter" +msgstr "nach féidir scagaire '%s' a thosú" + +#: archive-tar.c +msgid "unable to redirect descriptor" +msgstr "nach féidir tuairiscà a atreorú" + +#: archive-tar.c +#, c-format +msgid "'%s' filter reported error" +msgstr "Earráid a thuairiscigh scagaire '%s'" + +#: archive-zip.c +#, c-format +msgid "path is not valid UTF-8: %s" +msgstr "nÃl cosán bailà UTF-8: %s" + +#: archive-zip.c +#, c-format +msgid "path too long (%d chars, SHA1: %s): %s" +msgstr "cosán rófhada (%d chars, SHA1: %s): %s" + +#: archive-zip.c +#, c-format +msgid "timestamp too large for this system: %<PRIuMAX>" +msgstr "stampa ama ró-mhór don chóras seo:%<PRIuMAX>" + +#: archive.c +msgid "git archive [<options>] <tree-ish> [<path>...]" +msgstr "git cartlan <options>n [] <tree-ish>[<path>...]" + +#: archive.c +msgid "" +"git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]" +msgstr "" +"<tree-ish><path>git archive --remote <repo>[--exec<cmd>] [] [...<options>]" + +#: archive.c +msgid "git archive --remote <repo> [--exec <cmd>] --list" +msgstr "<cmd>git archive --remote <repo>[--exec] --list" + +#: archive.c builtin/gc.c builtin/notes.c builtin/tag.c +#, c-format +msgid "cannot read '%s'" +msgstr "nà féidir '%s' a léamh" + +#: archive.c +#, c-format +msgid "pathspec '%s' matches files outside the current directory" +msgstr "meaitseálann pathspec '%s' comhaid lasmuigh den eolaire reatha" + +#: archive.c builtin/add.c builtin/rm.c +#, c-format +msgid "pathspec '%s' did not match any files" +msgstr "nÃor mheaitseáil pathspec '%s' aon chomhaid" + +#: archive.c +#, c-format +msgid "no such ref: %.*s" +msgstr "gan aon tagairt den sórt sin: %.*s" + +#: archive.c +#, c-format +msgid "not a valid object name: %s" +msgstr "nà ainm réad bailÃ: %s" + +#: archive.c t/helper/test-cache-tree.c +#, c-format +msgid "not a tree object: %s" +msgstr "nà réad crann: %s" + +#: archive.c +#, c-format +msgid "failed to unpack tree object %s" +msgstr "theip ar réad crann %s a dhÃphacáil" + +#: archive.c +#, c-format +msgid "File not found: %s" +msgstr "NÃor aimsÃodh an comhad: %s" + +#: archive.c +#, c-format +msgid "Not a regular file: %s" +msgstr "Nà comhad rialta: %s" + +#: archive.c +#, c-format +msgid "unclosed quote: '%s'" +msgstr "luachan neamhdhúnadh: '%s'" + +#: archive.c +#, c-format +msgid "missing colon: '%s'" +msgstr "colon in easnamh: '%s'" + +#: archive.c +#, c-format +msgid "empty file name: '%s'" +msgstr "ainm comhaid folamh: '%s'" + +#: archive.c +msgid "fmt" +msgstr "fmt" + +#: archive.c +msgid "archive format" +msgstr "formáid cartlann" + +#: archive.c builtin/log.c parse-options.h +msgid "prefix" +msgstr "réimÃr" + +#: archive.c +msgid "prepend prefix to each pathname in the archive" +msgstr "réimÃr a pholadh chuig gach ainm cosán sa chartlann" + +#: archive.c builtin/blame.c builtin/commit-tree.c builtin/config.c +#: builtin/fast-export.c builtin/gc.c builtin/grep.c builtin/hash-object.c +#: builtin/ls-files.c builtin/notes.c builtin/read-tree.c parse-options.h +msgid "file" +msgstr "comhad" + +#: archive.c +msgid "add untracked file to archive" +msgstr "cuir comhad neamhrianaithe leis an gcartlann" + +#: archive.c +msgid "path:content" +msgstr "bealach:ábhar" + +#: archive.c builtin/archive.c +msgid "write the archive to this file" +msgstr "scrÃobh an cartlann chuig an gcomhad seo" + +#: archive.c +msgid "read .gitattributes in working directory" +msgstr "léite.gitattributs san eolaire oibre" + +#: archive.c +msgid "report archived files on stderr" +msgstr "tuairisciú comhaid cartlainne ar stderr" + +#: archive.c builtin/clone.c builtin/fetch.c builtin/pack-objects.c +#: builtin/pull.c +msgid "time" +msgstr "am" + +#: archive.c +msgid "set modification time of archive entries" +msgstr "socraigh am modhnaithe iontrálacha cartlainne" + +#: archive.c +msgid "set compression level" +msgstr "leibhéal comhbhrú a shocrú" + +#: archive.c +msgid "list supported archive formats" +msgstr "liosta formáidà cartlainne tacaÃochta" + +#: archive.c builtin/archive.c builtin/clone.c builtin/submodule--helper.c +msgid "repo" +msgstr "stóras" + +#: archive.c builtin/archive.c +msgid "retrieve the archive from remote repository <repo>" +msgstr "aisghabháil an cartlann ó stór iargúlta <repo>" + +#: archive.c builtin/archive.c builtin/difftool.c builtin/notes.c +msgid "command" +msgstr "ordú" + +#: archive.c builtin/archive.c +msgid "path to the remote git-upload-archive command" +msgstr "cosán chuig an ordú iargúlta git-upload-archive" + +#: archive.c +msgid "Unexpected option --remote" +msgstr "Rogha gan choinne --remote" + +#: archive.c builtin/add.c builtin/checkout.c builtin/clone.c builtin/commit.c +#: builtin/fast-export.c builtin/index-pack.c builtin/log.c builtin/reset.c +#: builtin/rm.c builtin/stash.c builtin/worktree.c fetch-pack.c http-fetch.c +#: revision.c +#, c-format +msgid "the option '%s' requires '%s'" +msgstr "tá %s ag teastáil don rogha '%s'" + +#: archive.c +msgid "Unexpected option --output" +msgstr "Rogha gan choinne --output" + +#: archive.c t/unit-tests/unit-test.c +#, c-format +msgid "extra command line parameter '%s'" +msgstr "paraiméadar lÃne ordaithe breise '%s'" + +#: archive.c +#, c-format +msgid "Unknown archive format '%s'" +msgstr "Formáid cartlainne anaithnid '%s'" + +#: archive.c +#, c-format +msgid "Argument not supported for format '%s': -%d" +msgstr "Argóint nach dtacaÃtear le haghaidh formáid '%s': -%d" + +#: attr.c +#, c-format +msgid "%.*s is not a valid attribute name" +msgstr "%.*s nà ainm tréith bailà é" + +#: attr.c +msgid "unable to add additional attribute" +msgstr "in ann tréith bhreise a chur leis" + +#: attr.c +#, c-format +msgid "ignoring overly long attributes line %d" +msgstr "neamhaird a dhéanamh ar lÃne tréithe ró-fhada %d" + +#: attr.c +#, c-format +msgid "%s not allowed: %s:%d" +msgstr "%s nà cheadaÃtear %s:%d" + +#: attr.c +msgid "" +"Negative patterns are ignored in git attributes\n" +"Use '\\!' for literal leading exclamation." +msgstr "" +"Déantar neamhaird ar phatrúin dhiúltacha i d\n" +"Úsáid '\\!' le haghaidh brú ceannródaÃoch litriúil." + +#: attr.c +#, c-format +msgid "cannot fstat gitattributes file '%s'" +msgstr "nà féidir an comhad gitattributeanna '%s' fstat" + +#: attr.c +#, c-format +msgid "ignoring overly large gitattributes file '%s'" +msgstr "neamhaird a dhéanamh ar chomhad gitattributs ró-mhór '%s'" + +#: attr.c +#, c-format +msgid "ignoring overly large gitattributes blob '%s'" +msgstr "neamhaird a dhéanamh ar ghitattributs ró-mhór blob '%s'" + +#: attr.c +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "nà féidir --attr-source nó GIT_ATTR_SOURCE a úsáid gan repo" + +#: attr.c +msgid "bad --attr-source or GIT_ATTR_SOURCE" +msgstr "olc --attr-source nó GIT_ATTR_SOURCE" + +#: attr.c read-cache.c refs/packed-backend.c +#, c-format +msgid "unable to stat '%s'" +msgstr "nà féidir '%s' a shástáil" + +#: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c +#: builtin/pack-objects.c combine-diff.c object-file.c rerere.c +#, c-format +msgid "unable to read %s" +msgstr "nach féidir %s a léamh" + +#: bisect.c +#, c-format +msgid "Badly quoted content in file '%s': %s" +msgstr "Ãbhar a luaitear go dona sa chomhad '%s': %s" + +#: bisect.c +#, c-format +msgid "We cannot bisect more!\n" +msgstr "Nà féidir linn nÃos mó a dhÃcheangal!\n" + +#: bisect.c +#, c-format +msgid "Not a valid commit name %s" +msgstr "Nà ainm tiomanta bailà %s" + +#: bisect.c +#, c-format +msgid "" +"The merge base %s is bad.\n" +"This means the bug has been fixed between %s and [%s].\n" +msgstr "" +"Tá an bonn cumaisc %s go dona.\n" +"CiallaÃonn sé seo go bhfuil an fabht socraithe idir %s agus [%s].\n" + +#: bisect.c +#, c-format +msgid "" +"The merge base %s is new.\n" +"The property has changed between %s and [%s].\n" +msgstr "" +"Tá an bonn cumaisc %s nua.\n" +"Tá athrú tagtha ar an maoin idir %s agus [%s].\n" + +#: bisect.c +#, c-format +msgid "" +"The merge base %s is %s.\n" +"This means the first '%s' commit is between %s and [%s].\n" +msgstr "" +"Is é an bonn cumaisc %s ná %s.\n" +"CiallaÃonn sé seo go bhfuil an chéad thiomantas '%s' idir %s agus [%s].\n" + +#: bisect.c +#, c-format +msgid "" +"Some %s revs are not ancestors of the %s rev.\n" +"git bisect cannot work properly in this case.\n" +"Maybe you mistook %s and %s revs?\n" +msgstr "" +"Nà sinsear an %s rev iad roinnt revs %s\n" +"Nà féidir le git bisect oibriú i gceart sa chás seo.\n" +"B'fhéidir gur mheas tú %s agus %s revs?\n" + +#: bisect.c +#, c-format +msgid "" +"the merge base between %s and [%s] must be skipped.\n" +"So we cannot be sure the first %s commit is between %s and %s.\n" +"We continue anyway." +msgstr "" +"caithfear an bonn cumaisc idir %s agus [%s] a scipeáil.\n" +"Mar sin nà féidir linn a bheith cinnte go bhfuil an chéad thiomantas %s idir " +"%s agus %s.\n" +"Leanaimid orainn ar aon nós." + +#: bisect.c +#, c-format +msgid "Bisecting: a merge base must be tested\n" +msgstr "Déroinnt: nà mór bonn cumaisc a thástáil\n" + +#: bisect.c +#, c-format +msgid "a %s revision is needed" +msgstr "tá athbhreithniú %s ag teastáil" + +#: bisect.c +#, c-format +msgid "could not create file '%s'" +msgstr "nà fhéadfaà comhad '%s' a chruthú" + +#: bisect.c builtin/notes.c +#, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "nà féidir 'show' a thosú le haghaidh réad '%s'" + +#: bisect.c builtin/merge.c +#, c-format +msgid "could not read file '%s'" +msgstr "nà raibh in ann comhad '%s' a léamh" + +#: bisect.c +msgid "reading bisect refs failed" +msgstr "theip ar athbhreithnithe bisect a léamh" + +#: bisect.c +#, c-format +msgid "%s was both %s and %s\n" +msgstr "Bhà %s %s agus %s araon\n" + +#: bisect.c +#, c-format +msgid "" +"No testable commit found.\n" +"Maybe you started with bad path arguments?\n" +msgstr "" +"NÃor aimsÃodh aon tiomantas intástála.\n" +"B'fhéidir gur thosaigh tú le droch-argóintà cosáin?\n" + +#: bisect.c +#, c-format +msgid "(roughly %d step)" +msgid_plural "(roughly %d steps)" +msgstr[0] "(thart ar %d céim)" +msgstr[1] "(thart ar %d céim)" +msgstr[2] "(thart ar %d céim)" + +#. TRANSLATORS: the last %s will be replaced with "(roughly %d +#. steps)" translation. +#. +#: bisect.c +#, c-format +msgid "Bisecting: %d revision left to test after this %s\n" +msgid_plural "Bisecting: %d revisions left to test after this %s\n" +msgstr[0] "Ag trasnú: %d athbhreithniú fágtha le tástáil tar éis an %s seo\n" +msgstr[1] "" +"Ag roinnt ina dhá leath: %d athbhreithniú fágtha le tástáil tar éis an %s " +"seo\n" +msgstr[2] "" +"Ag roinnt ina dhá leath: %d athbhreithniú fágtha le tástáil tar éis an %s " +"seo\n" + +#: blame.c +msgid "--contents and --reverse do not blend well." +msgstr "Nà chumasc --contents agus --reverse go maith." + +#: blame.c +msgid "--reverse and --first-parent together require specified latest commit" +msgstr "" +"ÉilÃonn --reverse agus --first-parent le chéile an tiomantas sonraithe is " +"déanaÃ" + +#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c +#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c +#: remote.c sequencer.c submodule.c +msgid "revision walk setup failed" +msgstr "theip ar socrú siúlóid ath" + +#: blame.c +msgid "" +"--reverse --first-parent together require range along first-parent chain" +msgstr "" +"--reverse --first-parent le chéile, teastaÃonn raon feadh an tslabhra first-" +"parent" + +#: blame.c +#, c-format +msgid "no such path %s in %s" +msgstr "nÃl aon chosán den sórt sin %s i %s" + +#: blame.c +#, c-format +msgid "cannot read blob %s for path %s" +msgstr "nà féidir le blob %s a léamh le haghaidh cosán %s" + +#: branch.c +msgid "" +"cannot inherit upstream tracking configuration of multiple refs when " +"rebasing is requested" +msgstr "" +"nà féidir cumraÃocht rianaithe suas srutha iolracha a oidhreacht nuair a " +"iarrtar athbhunú" + +#: branch.c +#, c-format +msgid "not setting branch '%s' as its own upstream" +msgstr "gan brainse '%s' a shocrú mar a thuas an sruth féin" + +#: branch.c +#, c-format +msgid "branch '%s' set up to track '%s' by rebasing." +msgstr "bunaÃodh brainse '%s' chun '%s' a rianú trà athbhunú." + +#: branch.c +#, c-format +msgid "branch '%s' set up to track '%s'." +msgstr "bunaÃodh brainse '%s' chun '%s' a rianú." + +#: branch.c +#, c-format +msgid "branch '%s' set up to track:" +msgstr "bunaÃodh brainse '%s' chun rianú:" + +#: branch.c +msgid "unable to write upstream branch configuration" +msgstr "in ann cumraÃocht brainse suas srutha a scrÃobh" + +#: branch.c +msgid "" +"\n" +"After fixing the error cause you may try to fix up\n" +"the remote tracking information by invoking:" +msgstr "" +"\n" +"Tar éis an chúis earráide a shocrú féadfaidh tú iarracht a dhéanamh socrú\n" +"an fhaisnéis cianrianaithe trà ghairm a dhéanamh ar:" + +#: branch.c +#, c-format +msgid "asked to inherit tracking from '%s', but no remote is set" +msgstr "iarradh ar rianú oidhreachta ó '%s', ach nÃl aon iargúlta socraithe" + +#: branch.c +#, c-format +msgid "asked to inherit tracking from '%s', but no merge configuration is set" +msgstr "" +"iarrtar ar rianú oidhreachta ó '%s', ach nÃl aon chumraÃocht cumaisc " +"socraithe" + +#: branch.c +#, c-format +msgid "not tracking: ambiguous information for ref '%s'" +msgstr "gan rianú: faisnéis dhébhrÃoch le haghaidh tagairt '%s'" + +#. 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. +#. +#. 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 +#. around. +#. +#: branch.c object-name.c +#, c-format +msgid " %s\n" +msgstr " %s\n" + +#. TRANSLATORS: The second argument is a \n-delimited list of +#. duplicate refspecs, composed above. +#. +#: branch.c +#, c-format +msgid "" +"There are multiple remotes whose fetch refspecs map to the remote\n" +"tracking ref '%s':\n" +"%s\n" +"This is typically a configuration error.\n" +"\n" +"To support setting up tracking branches, ensure that\n" +"different remotes' fetch refspecs map into different\n" +"tracking namespaces." +msgstr "" +"Tá iomadúla iargúlta ann a bhfuil a léarscáil athfheidhmithe a fháil chuig " +"an iargúlta\n" +"tagairt rianaithe '%s':\n" +"%s\n" +"De ghnáth is earráid chumraÃochta é seo.\n" +"\n" +"Chun tacú le brainsà rianaithe a bhunú, cinntigh go\n" +"faigheann ciananna éagsúla léarscáil speisiúcháin go difriúil\n" +"spaisà ainmneacha a rianú." + +#: branch.c +#, c-format +msgid "'%s' is not a valid branch name" +msgstr "Nà ainm brainse bailà é '%s'" + +#: branch.c builtin/branch.c +msgid "See `man git check-ref-format`" +msgstr "Féach `man git check-ref-format`" + +#: branch.c +#, c-format +msgid "a branch named '%s' already exists" +msgstr "tá brainse darb ainm '%s' ann cheana" + +#: branch.c +#, c-format +msgid "cannot force update the branch '%s' used by worktree at '%s'" +msgstr "" +"nà féidir an brainse '%s' a úsáideann crann oibre a nuashonrú a chur i " +"bhfeidhm ag '%s'" + +#: branch.c +#, c-format +msgid "cannot set up tracking information; starting point '%s' is not a branch" +msgstr "" +"nà féidir faisnéis rianaithe a chur ar bun; nà brainse é pointe tosaigh '%s'" + +#: branch.c +#, c-format +msgid "the requested upstream branch '%s' does not exist" +msgstr "nÃl an brainse suas srutha iarrtha '%s' ann" + +#: branch.c +msgid "" +"\n" +"If you are planning on basing your work on an upstream\n" +"branch that already exists at the remote, you may need to\n" +"run \"git fetch\" to retrieve it.\n" +"\n" +"If you are planning to push out a new local branch that\n" +"will track its remote counterpart, you may want to use\n" +"\"git push -u\" to set the upstream config as you push." +msgstr "" +"\n" +"Má tá tú ag pleanáil do chuid oibre a bhunú ar an suas sruth\n" +"brainse atá ann cheana féin ag an iargúlta, b'fhéidir go mbeidh ort\n" +"reáchtáil “git fetch†chun é a aisghabháil.\n" +"\n" +"Má tá tú ag pleanáil brainse áitiúil nua a bhrú amach\n" +"rianóidh sé a mhacasamhail iargúlta, b'fhéidir gur mhaith leat a úsáid\n" +"“git push -u†chun an cumraÃocht suas sruth a shocrú agus tú ag brú." + +#: branch.c builtin/replace.c +#, c-format +msgid "not a valid object name: '%s'" +msgstr "nà ainm réad bailÃ: '%s'" + +#: branch.c +#, c-format +msgid "ambiguous object name: '%s'" +msgstr "ainm réad débhrÃoch: '%s'" + +#: branch.c +#, c-format +msgid "not a valid branch point: '%s'" +msgstr "nà pointe brainse bailÃ: '%s'" + +#: branch.c +#, c-format +msgid "submodule '%s': unable to find submodule" +msgstr "fo-mhodúl '%s': in ann fo-mhodúl a aimsiú" + +#: branch.c +#, c-format +msgid "" +"You may try updating the submodules using 'git checkout --no-recurse-" +"submodules %s && git submodule update --init'" +msgstr "" +"Is féidir leat triail a bhaint as na fo-mhodúil a nuashonrú ag baint úsáide " +"as 'git checkout --no-recurse-submodules %s && git submodule update --init'" + +#: branch.c +#, c-format +msgid "submodule '%s': cannot create branch '%s'" +msgstr "fo-mhodúl '%s': nà féidir brainse '%s' a chruthú" + +#: branch.c +#, c-format +msgid "'%s' is already used by worktree at '%s'" +msgstr "Úsáidtear '%s' cheana féin ag an gcrann oibre ag '%s'" + +#: builtin/add.c +msgid "git add [<options>] [--] <pathspec>..." +msgstr "git add [<options>] [--]<pathspec>..." + +#: builtin/add.c +#, c-format +msgid "cannot chmod %cx '%s'" +msgstr "nà féidir chmod %cx '%s'" + +#: builtin/add.c +msgid "Unstaged changes after refreshing the index:" +msgstr "Athruithe gan stáitse tar éis an t-innéacs a athnuachan:" + +#: builtin/add.c +msgid "could not read the index" +msgstr "nà raibh in ann an t-innéacs a léamh" + +#: builtin/add.c +msgid "editing patch failed" +msgstr "theip ar paiste eagarthóire" + +#: builtin/add.c read-cache.c +#, c-format +msgid "could not stat '%s'" +msgstr "nà fhéadfaà '%s' a stát" + +#: builtin/add.c +msgid "empty patch. aborted" +msgstr "paiste folam. a ghabhrú" + +#: builtin/add.c +#, c-format +msgid "could not apply '%s'" +msgstr "nà fhéadfaà '%s' a chur i bhfeidhm" + +#: builtin/add.c +msgid "The following paths are ignored by one of your .gitignore files:\n" +msgstr "" +"Déanann ceann de do chomhaid .gitignore neamhaird ar na cosáin seo a " +"leanas:\n" + +#: builtin/add.c builtin/clean.c builtin/fetch.c builtin/mv.c +#: builtin/prune-packed.c builtin/pull.c builtin/push.c builtin/remote.c +#: builtin/rm.c builtin/send-pack.c +msgid "dry run" +msgstr "rith tirim" + +#: builtin/add.c builtin/check-ignore.c builtin/commit.c +#: builtin/count-objects.c builtin/fsck.c builtin/log.c builtin/mv.c +#: builtin/read-tree.c builtin/refs.c +msgid "be verbose" +msgstr "a bheith inearálta" + +#: builtin/add.c +msgid "interactive picking" +msgstr "piocadh idirghnÃ" + +#: builtin/add.c builtin/checkout.c builtin/reset.c +msgid "select hunks interactively" +msgstr "roghnaigh hunks idirghnÃomhach" + +#: builtin/add.c +msgid "edit current diff and apply" +msgstr "athraigh an dif reatha agus cuir i bhfeidhm" + +#: builtin/add.c +msgid "allow adding otherwise ignored files" +msgstr "ligean comhaid a neamhaird a chur leis" + +#: builtin/add.c +msgid "update tracked files" +msgstr "comhaid rianaithe a nuashonrú" + +#: builtin/add.c +msgid "renormalize EOL of tracked files (implies -u)" +msgstr "" +"athormalú a dhéanamh ar EOL na gcomhaid rianaithe (tugann le tuiscint -u)" + +#: builtin/add.c +msgid "record only the fact that the path will be added later" +msgstr "nà thaifeadadh ach an fÃric go gcuirfear an cosán leis nÃos déanaÃ" + +#: builtin/add.c +msgid "add changes from all tracked and untracked files" +msgstr "cuir athruithe ó gach comhad rianaithe agus neamhrianaithe" + +#: builtin/add.c +msgid "ignore paths removed in the working tree (same as --no-all)" +msgstr "" +"neamhaird a dhéanamh ar chosáin a bhaintear sa chrann oibre (mar an gcéanna " +"le --no-all)" + +#: builtin/add.c +msgid "don't add, only refresh the index" +msgstr "ná cuir leis, ach an t-innéacs a athnuachan" + +#: builtin/add.c +msgid "just skip files which cannot be added because of errors" +msgstr "" +"nà gá ach comhaid a scipeáil nach féidir a chur leis mar gheall ar earráidÃ" + +#: builtin/add.c +msgid "check if - even missing - files are ignored in dry run" +msgstr "" +"seiceáil an ndéantar neamhaird ar chomhaid - fiú ar iarraidh - ar iarraidh" + +#: builtin/add.c builtin/mv.c builtin/rm.c +msgid "allow updating entries outside of the sparse-checkout cone" +msgstr "ligean iontrálacha a nuashonrú lasmuigh den chón seiceála neamh" + +#: builtin/add.c builtin/update-index.c +msgid "override the executable bit of the listed files" +msgstr "an giotán infhorghnÃomhaithe de na comhaid liostaithe a sháraigh" + +#: builtin/add.c +msgid "warn when adding an embedded repository" +msgstr "rabhadh agus stór leabaithe á chur leis" + +#: builtin/add.c +#, c-format +msgid "" +"You've added another git repository inside your current repository.\n" +"Clones of the outer repository will not contain the contents of\n" +"the embedded repository and will not know how to obtain it.\n" +"If you meant to add a submodule, use:\n" +"\n" +"\tgit submodule add <url> %s\n" +"\n" +"If you added this path by mistake, you can remove it from the\n" +"index with:\n" +"\n" +"\tgit rm --cached %s\n" +"\n" +"See \"git help submodule\" for more information." +msgstr "" +"Chuir tú stór git eile leis taobh istigh de do stór reatha.\n" +"Nà bheidh ábhar i gclóin an stór seachtrach\n" +"an stór leabaithe agus nà bheidh a fhios acu conas é a fháil.\n" +"Má bhà sé i gceist agat fo-mhodúl a chur leis, bain úsáid as:\n" +"\n" +" <url>Cuir submodule git %s\n" +"\n" +"Má chuir tú an cosán seo le botún, is féidir leat é a bhaint as an\n" +"innéacs le:\n" +"\n" +"\tgit rm --cached %s\n" +"\n" +"Féach “git help submodule†le haghaidh tuilleadh faisnéise." + +#: builtin/add.c +#, c-format +msgid "adding embedded git repository: %s" +msgstr "stór git leabaithe a chur leis: %s" + +#: builtin/add.c +msgid "Use -f if you really want to add them." +msgstr "Úsáid -f más mian leat iad a chur leis i ndáirÃre." + +#: builtin/add.c +msgid "adding files failed" +msgstr "theip ar chomhaid a chur leis" + +#: builtin/add.c +#, c-format +msgid "--chmod param '%s' must be either -x or +x" +msgstr "Caithfidh --chmod param '%s' a bheith -x nó +x" + +#: builtin/add.c builtin/checkout.c builtin/commit.c builtin/reset.c +#: builtin/rm.c builtin/stash.c +#, c-format +msgid "'%s' and pathspec arguments cannot be used together" +msgstr "Nà féidir argóintà '%s' agus pathspec a úsáid le chéile" + +#: builtin/add.c +#, c-format +msgid "Nothing specified, nothing added.\n" +msgstr "NÃl aon rud sonraithe, nà chuir aon rud leis.\n" + +#: builtin/add.c +msgid "Maybe you wanted to say 'git add .'?" +msgstr "B'fhéidir gur mhaith leat a rá 'git add. '?" + +#: builtin/add.c builtin/check-ignore.c builtin/checkout.c builtin/clean.c +#: builtin/commit.c builtin/diff-tree.c builtin/grep.c builtin/mv.c +#: builtin/reset.c builtin/rm.c builtin/submodule--helper.c read-cache.c +#: rerere.c submodule.c +msgid "index file corrupt" +msgstr "comhad innéacs truaillithe" + +#: builtin/add.c builtin/am.c builtin/checkout.c builtin/clone.c +#: builtin/commit.c builtin/stash.c merge.c rerere.c +msgid "unable to write new index file" +msgstr "in ann comhad innéacs nua a scrÃobh" + +#: builtin/am.c builtin/mailinfo.c mailinfo.c +#, c-format +msgid "bad action '%s' for '%s'" +msgstr "droch-ghnÃomh '%s' le haghaidh '%s'" + +#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c +#: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c +#: ls-refs.c parallel-checkout.c sequencer.c setup.c +#, c-format +msgid "invalid value for '%s': '%s'" +msgstr "luach neamhbhailà do '%s': '%s'" + +#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c +#, c-format +msgid "could not read '%s'" +msgstr "nà raibh in ann '%s' a léamh" + +#: builtin/am.c +msgid "could not parse author script" +msgstr "nà raibh sé in ann script údair a pharsáil" + +#: builtin/am.c builtin/replace.c commit.c sequencer.c +#, c-format +msgid "could not parse %s" +msgstr "nà fhéadfaà %s a pháirseáil" + +#: builtin/am.c +#, c-format +msgid "'%s' was deleted by the applypatch-msg hook" +msgstr "Scriosadh '%s' ag an crúca applypatch-msg" + +#: builtin/am.c +#, c-format +msgid "Malformed input line: '%s'." +msgstr "LÃne ionchuir mÃfhoirmithe: '%s'." + +#: builtin/am.c +#, c-format +msgid "Failed to copy notes from '%s' to '%s'" +msgstr "Theip ar nótaà a chóipeáil ó '%s' go '%s'" + +#: builtin/am.c +msgid "fseek failed" +msgstr "theip ar fseek" + +#: builtin/am.c builtin/rebase.c sequencer.c wrapper.c +#, c-format +msgid "could not open '%s' for reading" +msgstr "nà fhéadfaà '%s' a oscailt le haghaidh léamh" + +#: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c +#, c-format +msgid "could not open '%s' for writing" +msgstr "nà féidir '%s' a oscailt le haghaidh scrÃbhneoireachta" + +#: builtin/am.c +#, c-format +msgid "could not parse patch '%s'" +msgstr "nà raibh sé in ann paiste '%s' a pháirseáil" + +#: builtin/am.c +msgid "Only one StGIT patch series can be applied at once" +msgstr "" +"Nà féidir ach sraith paiste STGit amháin a chur i bhfeidhm ag an am céanna" + +#: builtin/am.c +msgid "invalid timestamp" +msgstr "stampa ama neamhbhailÃ" + +#: builtin/am.c +msgid "invalid Date line" +msgstr "lÃne dáta neamhbhailÃ" + +#: builtin/am.c +msgid "invalid timezone offset" +msgstr "fhritháireamh crios ama neamh" + +#: builtin/am.c +msgid "Patch format detection failed." +msgstr "Theip ar bhrath formáid paiste." + +#: builtin/am.c builtin/clone.c +#, c-format +msgid "failed to create directory '%s'" +msgstr "theip ar eolaire '%s' a chruthú" + +#: builtin/am.c +msgid "Failed to split patches." +msgstr "Theip ar phaistà a roinnt." + +#: builtin/am.c +#, c-format +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "" +"Nuair a bheidh an fhadhb seo réitithe agat, reáchtáil “%s --continueâ€.\n" + +#: builtin/am.c +#, c-format +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "" +"Más fearr leat an paiste seo a scipeáil, reáchtáil “%s --skip†ina ionad.\n" + +#: builtin/am.c +#, c-format +msgid "" +"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n" +msgstr "" +"Chun an paiste folamh a thaifeadadh mar thiomantas folamh, reáchtáil “%s --" +"allow-emptyâ€.\n" + +#: builtin/am.c +#, c-format +msgid "To restore the original branch and stop patching, run \"%s --abort\"." +msgstr "" +"Chun an brainse bunaidh a chur ar ais agus stopadh le patáil, reáchtáil “%s " +"--abortâ€." + +#: builtin/am.c +msgid "Patch sent with format=flowed; space at the end of lines might be lost." +msgstr "" +"Seoladh paiste le formáid = sreabhadh; d'fhéadfaà spás ag deireadh na lÃnte " +"a chailleadh." + +#: builtin/am.c +#, c-format +msgid "missing author line in commit %s" +msgstr "lÃne údair ar iarraidh i dtiomantas %s" + +#: builtin/am.c +#, c-format +msgid "invalid ident line: %.*s" +msgstr "lÃne aitheantais neamhbhailÃ: %.*s" + +#: builtin/am.c builtin/checkout.c builtin/clone.c commit-graph.c +#, c-format +msgid "unable to parse commit %s" +msgstr "nach féidir le tiomantas %s a pharsáil" + +#: builtin/am.c +msgid "Repository lacks necessary blobs to fall back on 3-way merge." +msgstr "" +"NÃl na blobanna riachtanacha ag an stór chun titim siar ar chumasc trà " +"bhealach." + +#: builtin/am.c +msgid "Using index info to reconstruct a base tree..." +msgstr "Eolas innéacs a úsáid chun bonn crann a athchóiriú..." + +#: builtin/am.c +msgid "" +"Did you hand edit your patch?\n" +"It does not apply to blobs recorded in its index." +msgstr "" +"Ar chuir tú do phaiste in eagar de láimh?\n" +"Nà bhaineann sé le blobs a taifeadtar ina innéacs." + +#: builtin/am.c +msgid "Falling back to patching base and 3-way merge..." +msgstr "Ag titim ar ais go bonn paiste agus cumasc trà bhealach..." + +#: builtin/am.c +msgid "Failed to merge in the changes." +msgstr "Theip ar na hathruithe a chumasc." + +#: builtin/am.c builtin/merge.c sequencer.c +msgid "git write-tree failed to write a tree" +msgstr "theip ar git write-tree crann a scrÃobh" + +#: builtin/am.c +msgid "applying to an empty history" +msgstr "iarratas a dhéanamh ar stair folamh" + +#: builtin/am.c builtin/commit.c builtin/merge.c builtin/replay.c sequencer.c +msgid "failed to write commit object" +msgstr "theip ar réad tiomanta a scrÃobh" + +#: builtin/am.c +#, c-format +msgid "cannot resume: %s does not exist." +msgstr "nà féidir atosú: nÃl %s ann." + +#: builtin/am.c +msgid "Commit Body is:" +msgstr "Is é an Comhlacht Tiomanta:" + +#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a] +#. in your translation. The program will only accept English +#. input at this point. +#. +#: builtin/am.c +#, c-format +msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: " +msgstr "" +"Cuir i bhfeidhm?[y]es/[n]o/[e]dit/[v]iew patch/[a]glacadh le gach rud: " + +#: builtin/am.c builtin/commit.c +msgid "unable to write index file" +msgstr "in ann comhad innéacs a scrÃobh" + +#: builtin/am.c +#, c-format +msgid "Dirty index: cannot apply patches (dirty: %s)" +msgstr "Innéacs salach: nà féidir paistà a chur i bhfeidhm (salach: %s)" + +#: builtin/am.c +#, c-format +msgid "Skipping: %.*s" +msgstr "Scipeáil: %.*s" + +#: builtin/am.c +#, c-format +msgid "Creating an empty commit: %.*s" +msgstr "Tiomantas folamh a chruthú: %.*s" + +#: builtin/am.c +msgid "Patch is empty." +msgstr "Tá paiste folamh." + +#: builtin/am.c +#, c-format +msgid "Applying: %.*s" +msgstr "Iarratas a dhéanamh: %.*s" + +#: builtin/am.c +msgid "No changes -- Patch already applied." +msgstr "Gan aon athruithe - paiste curtha i bhfeidhm cheana féin." + +#: builtin/am.c +#, c-format +msgid "Patch failed at %s %.*s" +msgstr "Theip ar phaiste ag %s%.*s" + +#: builtin/am.c +msgid "Use 'git am --show-current-patch=diff' to see the failed patch" +msgstr "" +"Úsáid 'git am --show-current-patch=diff' chun an paiste theip a fheiceáil" + +#: builtin/am.c +msgid "No changes - recorded it as an empty commit." +msgstr "Gan aon athruithe - taifeadadh é mar thiomantas folamh." + +#: builtin/am.c +msgid "" +"No changes - did you forget to use 'git add'?\n" +"If there is nothing left to stage, chances are that something else\n" +"already introduced the same changes; you might want to skip this patch." +msgstr "" +"Gan aon athruithe - ar ndearna tú dearmad 'git add' a úsáid?\n" +"Mura bhfuil aon rud fágtha chun na céime, tá seans ann go bhfuil rud éigin " +"eile\n" +"tugadh na hathruithe céanna isteach cheana féin; b'fhéidir gur mhaith leat " +"an paiste seo a scipeáil." + +#: builtin/am.c +msgid "" +"You still have unmerged paths in your index.\n" +"You should 'git add' each file with resolved conflicts to mark them as " +"such.\n" +"You might run `git rm` on a file to accept \"deleted by them\" for it." +msgstr "" +"Tá cosáin neamh-chumasaithe agat fós i d'innéacs.\n" +"Ba chóir duit gach comhad a 'chur leis 'git' le coinbhleachtaà réitithe chun " +"iad a mharcáil mar sin.\n" +"D'fhéadfá `git rm` a reáchtáil ar chomhad chun glacadh le “scriosta ag siad†" +"dó." + +#: builtin/am.c builtin/reset.c +#, c-format +msgid "Could not parse object '%s'." +msgstr "Nà fhéadfaà réad '%s' a pháirseáil." + +#: builtin/am.c +msgid "failed to clean index" +msgstr "theip ar innéacs a ghlanadh" + +#: builtin/am.c +msgid "" +"You seem to have moved HEAD since the last 'am' failure.\n" +"Not rewinding to ORIG_HEAD" +msgstr "" +"Is cosúil gur bhogadh tú HEAD ón teip 'am' deireanach.\n" +"Gan athfhillte chuig ORIG_HEAD" + +#: builtin/am.c builtin/bisect.c builtin/tag.c worktree.c +#, c-format +msgid "failed to read '%s'" +msgstr "theip ar '%s' a léamh" + +#: builtin/am.c +msgid "git am [<options>] [(<mbox> | <Maildir>)...]" +msgstr "git am [<options>] [(<mbox> | <Maildir>)...]" + +#: builtin/am.c +msgid "git am [<options>] (--continue | --skip | --abort)" +msgstr "git am [<options>] (--continue | --skip | --abort)" + +#: builtin/am.c +msgid "run interactively" +msgstr "rith idirghnÃomhach" + +#: builtin/am.c +msgid "bypass pre-applypatch and applypatch-msg hooks" +msgstr "seachbhóthar crúcaà réamh-applypatch agus applypatch-msg" + +#: builtin/am.c builtin/cat-file.c +msgid "historical option -- no-op" +msgstr "rogha stairiúil -- no-op" + +#: builtin/am.c +msgid "allow fall back on 3way merging if needed" +msgstr "ligean titim siar ar chumasc 3bhealach más gá" + +#: builtin/am.c builtin/init-db.c builtin/prune-packed.c builtin/repack.c +#: builtin/stash.c +msgid "be quiet" +msgstr "a bheith ciúin" + +#: builtin/am.c +msgid "add a Signed-off-by trailer to the commit message" +msgstr "cuir leantóir sÃnithe amach leis an teachtaireacht tiomanta" + +#: builtin/am.c +msgid "recode into utf8 (default)" +msgstr "athchóiriú isteach i utf8 (réamhshocraithe)" + +#: builtin/am.c +msgid "pass -k flag to git-mailinfo" +msgstr "pas bratach -k chuig git-mailinfo" + +#: builtin/am.c +msgid "pass -b flag to git-mailinfo" +msgstr "pas bratach -b chuig git-mailinfo" + +#: builtin/am.c +msgid "pass -m flag to git-mailinfo" +msgstr "pas bratach -m chuig git-mailinfo" + +#: builtin/am.c +msgid "pass --keep-cr flag to git-mailsplit for mbox format" +msgstr "pas bratach --keep-cr go git-mailsplit le haghaidh formáid mbox" + +#: builtin/am.c +msgid "strip everything before a scissors line" +msgstr "gach rud a tharraingt roimh lÃne siosúr" + +#: builtin/am.c +msgid "pass it through git-mailinfo" +msgstr "cuir ar aghaidh trà git-mailinfo" + +#: builtin/am.c +msgid "pass it through git-apply" +msgstr "cuir isteach é trà git-apply" + +#: builtin/am.c builtin/commit.c builtin/fmt-merge-msg.c builtin/grep.c +#: builtin/merge.c builtin/pull.c builtin/rebase.c builtin/repack.c +#: builtin/show-branch.c builtin/show-ref.c builtin/tag.c parse-options.h +msgid "n" +msgstr "n" + +#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c +#: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c +#: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c +#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c +msgid "format" +msgstr "formáid" + +#: builtin/am.c +msgid "format the patch(es) are in" +msgstr "formáid atá na paistea/na paiste iontu" + +#: builtin/am.c +msgid "override error message when patch failure occurs" +msgstr "teachtaireacht earráide a shárú nuair a tharlaÃonn teip" + +#: builtin/am.c +msgid "continue applying patches after resolving a conflict" +msgstr "leanúint ar aghaidh ag cur paistà a chur i bhfeidhm tar" + +#: builtin/am.c +msgid "synonyms for --continue" +msgstr "comhchiallaigh do --continue" + +#: builtin/am.c +msgid "skip the current patch" +msgstr "scipeáil an paiste reatha" + +#: builtin/am.c +msgid "restore the original branch and abort the patching operation" +msgstr "" +"an bhrainse bunaidh a chur ar ais agus cuir deireadh leis an oibrÃocht paiste" + +#: builtin/am.c +msgid "abort the patching operation but keep HEAD where it is" +msgstr "" +"déan deireadh leis an oibrÃocht paisteála ach coinnigh CEAD san áit a bhfuil " +"sé" + +#: builtin/am.c +msgid "show the patch being applied" +msgstr "taispeáin an paiste atá á chur i bhfeidhm" + +#: builtin/am.c +msgid "try to apply current patch again" +msgstr "déan iarracht paiste reatha a chur i bhfeidhm" + +#: builtin/am.c +msgid "record the empty patch as an empty commit" +msgstr "taifeadadh an paiste folamh mar thiomantas folamh" + +#: builtin/am.c +msgid "lie about committer date" +msgstr "bréag faoi dháta an choimisiúnaithe" + +#: builtin/am.c +msgid "use current timestamp for author date" +msgstr "bain úsáid as stampa ama reatha le haghaidh dáta an údair" + +#: builtin/am.c builtin/commit-tree.c builtin/commit.c builtin/merge.c +#: builtin/pull.c builtin/rebase.c builtin/revert.c builtin/tag.c +msgid "key-id" +msgstr "id eochair" + +#: builtin/am.c builtin/rebase.c +msgid "GPG-sign commits" +msgstr "Tiomanta comhartha GPG-Comhartha" + +#: builtin/am.c +msgid "how to handle empty patches" +msgstr "conas paistà folamh a láimhseáil" + +#: builtin/am.c +msgid "(internal use for git-rebase)" +msgstr "(úsáid inmheánach le haghaidh git-rebase)" + +#: builtin/am.c +msgid "" +"The -b/--binary option has been a no-op for long time, and\n" +"it will be removed. Please do not use it anymore." +msgstr "" +"Tá an rogha -b/--binary neamh-op le fada an lá, agus\n" +"bainfear é. Ná húsáid é nÃos mó le do thoil." + +#: builtin/am.c +msgid "failed to read the index" +msgstr "theip ar an t-innéacs a léamh" + +#: builtin/am.c +#, c-format +msgid "previous rebase directory %s still exists but mbox given." +msgstr "eolaire rebase roimhe seo %s ann fós ach tugadh mbox." + +#: builtin/am.c +#, c-format +msgid "" +"Stray %s directory found.\n" +"Use \"git am --abort\" to remove it." +msgstr "" +"Fuarthas eolaire %s stray.\n" +"Úsáid “git am --abort†chun é a bhaint." + +#: builtin/am.c +msgid "Resolve operation not in progress, we are not resuming." +msgstr "Réiteach oibrÃocht nach bhfuil ar siúl, nÃl muid ag atosú." + +#: builtin/am.c +msgid "interactive mode requires patches on the command line" +msgstr "éilÃonn modh idirghnÃomhach paistà ar an lÃne ordaithe" + +#: builtin/apply.c +msgid "git apply [<options>] [<patch>...]" +msgstr "git feidhm [<options>] [<patch>...]" + +#: builtin/archive.c diagnose.c +msgid "could not redirect output" +msgstr "nà fhéadfaà aschur a atreorú" + +#: builtin/archive.c +msgid "git archive: expected ACK/NAK, got a flush packet" +msgstr "cartlann git: ag súil le ACK/NAK, fuair sé paicéad sruthán" + +#: builtin/archive.c +#, c-format +msgid "git archive: NACK %s" +msgstr "git archive: NACK %s" + +#: builtin/archive.c +msgid "git archive: protocol error" +msgstr "git cartlann: earráid prótacal" + +#: builtin/archive.c +msgid "git archive: expected a flush" +msgstr "git archive: bhÃothas ag súil le sruthlú" + +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=<n>] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=<n>] [-- [no-] neart]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "fadhb ag luchtú seiceáil neamhchoiti" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "LÃon Ãosta rudaà le iarraidh ag an am" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Cuir srian ar na rudaà atá in easnamh don tseiceáil neamhchoitianta" + +#: builtin/bisect.c +msgid "" +"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" +"checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" +msgstr "" +"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-" +"checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]" + +#: builtin/bisect.c +msgid "git bisect (good|bad) [<rev>...]" +msgstr "<rev>git bisect (maith|olc) [...]" + +#: builtin/bisect.c +msgid "git bisect skip [(<rev>|<range>)...]" +msgstr "git bisect skip [(<rev>|<range>)...]" + +#: builtin/bisect.c +msgid "git bisect reset [<commit>]" +msgstr "<commit>athshocrú git bisect []" + +#: builtin/bisect.c +msgid "git bisect replay <logfile>" +msgstr "athsheinm git bisect <logfile>" + +#: builtin/bisect.c +msgid "git bisect run <cmd> [<arg>...]" +msgstr "git bisect a rith <cmd>[<arg>...]" + +#: builtin/bisect.c +#, c-format +msgid "cannot open file '%s' in mode '%s'" +msgstr "nà féidir comhad '%s' a oscailt sa mhodh '%s'" + +#: builtin/bisect.c +#, c-format +msgid "could not write to file '%s'" +msgstr "nà fhéadfaà scrÃobh chuig comhad '%s'" + +#: builtin/bisect.c +#, c-format +msgid "cannot open file '%s' for reading" +msgstr "nà féidir comhad '%s' a oscailt le haghaidh léamh" + +#: builtin/bisect.c +#, c-format +msgid "'%s' is not a valid term" +msgstr "Nà téarma bailà é '%s'" + +#: builtin/bisect.c +#, c-format +msgid "can't use the builtin command '%s' as a term" +msgstr "nà féidir an t-ordú bunaithe '%s' a úsáid mar théarma" + +#: builtin/bisect.c +#, c-format +msgid "can't change the meaning of the term '%s'" +msgstr "nà féidir le brà an téarma '%s' a athrú" + +#: builtin/bisect.c +msgid "please use two different terms" +msgstr "bain úsáid as dhá théarma éagsúla" + +#: builtin/bisect.c +#, c-format +msgid "We are not bisecting.\n" +msgstr "NÃlimid ag déileáil.\n" + +#: builtin/bisect.c +#, c-format +msgid "'%s' is not a valid commit" +msgstr "Nà gealltanas bailà é '%s'" + +#: builtin/bisect.c +#, c-format +msgid "" +"could not check out original HEAD '%s'. Try 'git bisect reset <commit>'." +msgstr "" +"nà fhéadfaà an HEAD bunaidh '%s' a sheiceáil. <commit>Bain triail as 'git " +"bisect reset '." + +#: builtin/bisect.c +#, c-format +msgid "Bad bisect_write argument: %s" +msgstr "Droch-argóint bisect_write: %s" + +#: builtin/bisect.c +#, c-format +msgid "couldn't get the oid of the rev '%s'" +msgstr "nà raibh in ann oid an rev '%s' a fháil" + +#: builtin/bisect.c +#, c-format +msgid "couldn't open the file '%s'" +msgstr "nà raibh in ann an comhad '%s' a oscailt" + +#: builtin/bisect.c +#, c-format +msgid "Invalid command: you're currently in a %s/%s bisect" +msgstr "Ordú neamhbhailÃ: tá tú i mbeagán %s/%s faoi láthair" + +#: builtin/bisect.c +#, c-format +msgid "" +"You need to give me at least one %s and %s revision.\n" +"You can use \"git bisect %s\" and \"git bisect %s\" for that." +msgstr "" +"Nà mór duit athbhreithniú %s agus %s amháin ar a laghad a thabhairt dom.\n" +"Is féidir leat “git bisect %s†agus “git bisect %s†a úsáid chuige sin." + +#: builtin/bisect.c +#, c-format +msgid "" +"You need to start by \"git bisect start\".\n" +"You then need to give me at least one %s and %s revision.\n" +"You can use \"git bisect %s\" and \"git bisect %s\" for that." +msgstr "" +"Nà mór duit tosú ag “git bisect startâ€.\n" +"Ansin nà mór duit athbhreithniú %s agus %s amháin ar a laghad a thabhairt " +"dom.\n" +"Is féidir leat “git bisect %s†agus “git bisect %s†a úsáid chuige sin." + +#: builtin/bisect.c +#, c-format +msgid "bisecting only with a %s commit" +msgstr "ag déileáil ach amháin le tiomantas %s" + +#. TRANSLATORS: Make sure to include [Y] and [n] in your +#. translation. The program will only accept English input +#. at this point. +#. +#: builtin/bisect.c +msgid "Are you sure [Y/n]? " +msgstr "An bhfuil tú cinnte [Y/n]? " + +#: builtin/bisect.c +msgid "status: waiting for both good and bad commits\n" +msgstr "stádas: ag fanacht le tiomáintà mhaith agus tiomáintà dona\n" + +#: builtin/bisect.c +#, c-format +msgid "status: waiting for bad commit, %d good commit known\n" +msgid_plural "status: waiting for bad commit, %d good commits known\n" +msgstr[0] "stádas: ag fanacht le droch-thiomnadh, %d dea-thiomnadh ar eolas\n" +msgstr[1] "" +"stádas: ag fanacht le droch-thiomantas, %d dea-thiomantas ar eolas\n" +msgstr[2] "" +"stádas: ag fanacht le droch-thiomantas, %d dea-thiomantas ar eolas\n" + +#: builtin/bisect.c +msgid "status: waiting for good commit(s), bad commit known\n" +msgstr "stádas: ag fanacht le tiomáintà maith, droch-tiomantas ar eolas\n" + +#: builtin/bisect.c +msgid "no terms defined" +msgstr "aon téarmaà sainmhÃnithe" + +#: builtin/bisect.c +#, c-format +msgid "" +"Your current terms are %s for the old state\n" +"and %s for the new state.\n" +msgstr "" +"Is iad na téarmaà reatha %s don seanstát\n" +"agus %s don stát nua.\n" + +#: builtin/bisect.c +#, c-format +msgid "" +"invalid argument %s for 'git bisect terms'.\n" +"Supported options are: --term-good|--term-old and --term-bad|--term-new." +msgstr "" +"argóint neamhbhailà %s le haghaidh 'git bisect terms'.\n" +"Is iad na roghanna tacaithe ná: --term-good|--term-old agus --term-bad|--" +"term-new." + +#: builtin/bisect.c +#, c-format +msgid "could not open '%s' for appending" +msgstr "nà fhéadfaà '%s' a oscailt le haghaidh cur isteach" + +#: builtin/bisect.c +msgid "'' is not a valid term" +msgstr "'' nà téarma bailà é" + +#: builtin/bisect.c +#, c-format +msgid "unrecognized option: '%s'" +msgstr "rogha gan aithint: '%s'" + +#: builtin/bisect.c +#, c-format +msgid "'%s' does not appear to be a valid revision" +msgstr "Nà cosúil gur athbhreithniú bailà é '%s'" + +#: builtin/bisect.c +msgid "bad HEAD - I need a HEAD" +msgstr "droch HEAD - TeastaÃonn HEAD uaim" + +#: builtin/bisect.c +#, c-format +msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'." +msgstr "" +"theip ar '%s' a sheiceáil. <valid-branch>Bain triail as 'git bisect start '." + +#: builtin/bisect.c +msgid "bad HEAD - strange symbolic ref" +msgstr "bad HEAD - tagairt siombalach aisteach" + +#: builtin/bisect.c +#, c-format +msgid "invalid ref: '%s'" +msgstr "tagairt neamhbhailÃ: '%s'" + +#: builtin/bisect.c +msgid "You need to start by \"git bisect start\"\n" +msgstr "Nà mór duit tosú ag “git bisect startâ€\n" + +#. TRANSLATORS: Make sure to include [Y] and [n] in your +#. translation. The program will only accept English input +#. at this point. +#. +#: builtin/bisect.c +msgid "Do you want me to do it for you [Y/n]? " +msgstr "An dteastaÃonn uait go ndéanfaidh mé é duit [Y/n]? " + +#: builtin/bisect.c +msgid "Please call `--bisect-state` with at least one argument" +msgstr "Glaoigh ar `--bisect-state` le do thoil le argóint amháin ar a laghad" + +#: builtin/bisect.c +#, c-format +msgid "'git bisect %s' can take only one argument." +msgstr "Nà féidir le 'git bisect %s' ach argóint amháin a ghlacadh." + +#: builtin/bisect.c +#, c-format +msgid "Bad rev input: %s" +msgstr "Droch-ionchur rev: %s" + +#: builtin/bisect.c +#, c-format +msgid "Bad rev input (not a commit): %s" +msgstr "Droch-ionchur rev (nà tiomantas): %s" + +#: builtin/bisect.c +msgid "We are not bisecting." +msgstr "NÃlimid ag déileáil." + +#: builtin/bisect.c +#, c-format +msgid "'%s'?? what are you talking about?" +msgstr "'%s'?? cad atá tú ag caint faoi?" + +#: builtin/bisect.c +#, c-format +msgid "cannot read file '%s' for replaying" +msgstr "nà féidir comhad '%s' a léamh le haghaidh athsheinm" + +#: builtin/bisect.c +#, c-format +msgid "running %s\n" +msgstr "ag rith %s\n" + +#: builtin/bisect.c +msgid "bisect run failed: no command provided." +msgstr "theip ar rith bioctha: nÃl aon ordú curtha ar fáil." + +#: builtin/bisect.c +#, c-format +msgid "unable to verify %s on good revision" +msgstr "nach féidir %s a fhÃorú ar athbhreithniú maith" + +#: builtin/bisect.c +#, c-format +msgid "bogus exit code %d for good revision" +msgstr "cód imeachta bréagach %d le haghaidh athbhreithniú maith" + +#: builtin/bisect.c +#, c-format +msgid "bisect run failed: exit code %d from %s is < 0 or >= 128" +msgstr "< 0 or >Theip ar rith bioctha: is é an cód imeachta %d ó %s = 128" + +#: builtin/bisect.c +#, c-format +msgid "cannot open file '%s' for writing" +msgstr "nà féidir comhad '%s' a oscailt le haghaidh scrÃobh" + +#: builtin/bisect.c +msgid "bisect run cannot continue any more" +msgstr "nà féidir le rith bisect leanúint ar aghaidh nÃos mó" + +#: builtin/bisect.c +msgid "bisect run success" +msgstr "rath reatha dhéagsúil" + +#: builtin/bisect.c +msgid "bisect found first bad commit" +msgstr "fuarthas bisect an chéad droch-thiomantas" + +#: builtin/bisect.c +#, c-format +msgid "bisect run failed: 'git bisect %s' exited with error code %d" +msgstr "theip ar rith bisect: D'éirigh 'git bisect %s' le cód earráide %d" + +#: builtin/bisect.c +#, c-format +msgid "'%s' requires either no argument or a commit" +msgstr "Nà éilÃonn '%s' aon argóint ná tiomantas" + +#: builtin/bisect.c +#, c-format +msgid "'%s' requires 0 or 1 argument" +msgstr "ÉilÃonn '%s' argóint 0 nó 1" + +#: builtin/bisect.c +#, c-format +msgid "'%s' requires 0 arguments" +msgstr "ÉilÃonn '%s' 0 argóint" + +#: builtin/bisect.c +msgid "no logfile given" +msgstr "nÃl aon logfile tugtha" + +#: builtin/bisect.c +#, c-format +msgid "'%s' failed: no command provided." +msgstr "Theip ar '%s': nÃl aon ordú curtha ar fáil." + +#: builtin/bisect.c +msgid "need a command" +msgstr "teastaÃonn ordú" + +#: builtin/bisect.c builtin/cat-file.c +#, c-format +msgid "unknown command: '%s'" +msgstr "ordú anaithnid: '%s'" + +#: builtin/blame.c +msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>" +msgstr "git an mille <options>án [<rev-opts>] [<rev>] [] [--] <file>" + +#: builtin/blame.c +msgid "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>" +msgstr "git annotate [<options>] [] [<rev-opts><rev>] [--] <file>" + +#: builtin/blame.c +msgid "<rev-opts> are documented in git-rev-list(1)" +msgstr "<rev-opts>iad doiciméadaithe i git-rev-list (1)" + +#: builtin/blame.c +#, c-format +msgid "expecting a color: %s" +msgstr "ag súil le dath: %s" + +#: builtin/blame.c +msgid "must end with a color" +msgstr "caithfidh deireadh a chur le dath" + +#: builtin/blame.c +#, c-format +msgid "cannot find revision %s to ignore" +msgstr "nà féidir athbhreithniú %s a fháil le neamhair" + +#: builtin/blame.c +msgid "show blame entries as we find them, incrementally" +msgstr "taispeáint iontrálacha milleán de réir mar a aimsÃmid iad, go chéile" + +#: builtin/blame.c +msgid "do not show object names of boundary commits (Default: off)" +msgstr "" +"ná taispeáin ainmneacha réada na ngealltanais teorann (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "do not treat root commits as boundaries (Default: off)" +msgstr "" +"ná déileáil le gealltanais fréimhe mar theorainneacha (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show work cost statistics" +msgstr "taispeáin staitisticà costas oibre" + +#: builtin/blame.c builtin/checkout.c builtin/clone.c builtin/commit-graph.c +#: builtin/fetch.c builtin/merge.c builtin/multi-pack-index.c builtin/pull.c +#: builtin/push.c builtin/remote.c builtin/send-pack.c +msgid "force progress reporting" +msgstr "tuairisciú dul chun cinn" + +#: builtin/blame.c +msgid "show output score for blame entries" +msgstr "taispeáin scór aschuir d'iontrálacha mille" + +#: builtin/blame.c +msgid "show original filename (Default: auto)" +msgstr "taispeáin ainm comhaid bunaidh (Réamhshocraithe: auto)" + +#: builtin/blame.c +msgid "show original linenumber (Default: off)" +msgstr "taispeáin uimhir lÃne bunaidh (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show in a format designed for machine consumption" +msgstr "taispeáint i bhformáid atá deartha le haghaidh tomhaltas meaisÃn" + +#: builtin/blame.c +msgid "show porcelain format with per-line commit information" +msgstr "formáid poircealláin a thaispeáint le faisnéis tiomanta" + +#: builtin/blame.c +msgid "use the same output mode as git-annotate (Default: off)" +msgstr "" +"bain úsáid as an modh aschuir céanna le git-annotate (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show raw timestamp (Default: off)" +msgstr "taispeáin ama amh (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show long commit SHA1 (Default: off)" +msgstr "taispeáin tiomantas fada SHA1 (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "suppress author name and timestamp (Default: off)" +msgstr "ainm an údair agus stampa ama a chur faoi chois (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show author email instead of name (Default: off)" +msgstr "taispeáin rÃomhphost an údair in ionad ainm (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "ignore whitespace differences" +msgstr "neamhaird a dhéanamh ar dhifrÃochtaà spás b" + +#: builtin/blame.c builtin/clone.c builtin/log.c +msgid "rev" +msgstr "rev" + +#: builtin/blame.c +msgid "ignore <rev> when blaming" +msgstr "neamhaird a <rev>dhéanamh agus an milleán" + +#: builtin/blame.c +msgid "ignore revisions from <file>" +msgstr "neamhaird ar athbhreithnithe <file>" + +#: builtin/blame.c +msgid "color redundant metadata from previous line differently" +msgstr "meiteashonraà iomarcach dath ó lÃne roimhe seo ar bheal" + +#: builtin/blame.c +msgid "color lines by age" +msgstr "lÃnte datha de réir aois" + +#: builtin/blame.c +msgid "spend extra cycles to find better match" +msgstr "timthriallta breise a chaitheamh chun meaitseáil nÃos fearr" + +#: builtin/blame.c +msgid "use revisions from <file> instead of calling git-rev-list" +msgstr "athbhreithnithe a úsáid as in <file>ionad glaoch ar git-rev-list" + +#: builtin/blame.c +msgid "use <file>'s contents as the final image" +msgstr "úsáid <file>ábhar mar an Ãomhá deiridh" + +#: builtin/blame.c +msgid "score" +msgstr "scór" + +#: builtin/blame.c +msgid "find line copies within and across files" +msgstr "faigh cóipeanna lÃne laistigh de chomhaid agus trasna" + +#: builtin/blame.c +msgid "find line movements within and across files" +msgstr "faigh gluaiseachtaà lÃne laistigh de chomhaid agus trasna" + +#: builtin/blame.c +msgid "range" +msgstr "raon" + +#: builtin/blame.c +msgid "process only line range <start>,<end> or function :<funcname>" +msgstr "ach raon lÃne, nó feidh <start>m a <end>phróiseáil: <funcname>" + +#: builtin/blame.c +msgid "--progress can't be used with --incremental or porcelain formats" +msgstr "Nà féidir --progress a úsáid le formáidà --incremental nó poircealláin" + +#. TRANSLATORS: This string is used to tell us the +#. maximum display width for a relative timestamp in +#. "git blame" output. For C locale, "4 years, 11 +#. months ago", which takes 22 places, is the longest +#. among various forms of relative timestamps, but +#. your language may need more or fewer display +#. columns. +#. +#: builtin/blame.c +msgid "4 years, 11 months ago" +msgstr "4 bliana, 11 mhà ó shin" + +#: builtin/blame.c +#, c-format +msgid "file %s has only %lu line" +msgid_plural "file %s has only %lu lines" +msgstr[0] "comhad %s nÃl ach %lu lÃne" +msgstr[1] "comhad %s nÃl ach %lu lÃnte" +msgstr[2] "comhad %s nÃl ach %lu lÃnte" + +#: builtin/blame.c +msgid "Blaming lines" +msgstr "An milleán ar lÃnte" + +#: builtin/branch.c +msgid "git branch [<options>] [-r | -a] [--merged] [--no-merged]" +msgstr "git branch [<options>] [-r | -a] [--merged] [--no-merged]" + +#: builtin/branch.c +msgid "" +"git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-" +"point>]" +msgstr "" +"git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-" +"point>]" + +#: builtin/branch.c +msgid "git branch [<options>] [-l] [<pattern>...]" +msgstr "git branch [<options>] [-l] [<pattern>...]" + +#: builtin/branch.c +msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..." +msgstr "git branch [<options>] [-r] (-d | -D) <branch-name>..." + +#: builtin/branch.c +msgid "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>" +msgstr "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>" + +#: builtin/branch.c +msgid "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>" +msgstr "git branch [<options>] (-c | -C) [<old-branch>] <new-branch>" + +#: builtin/branch.c +msgid "git branch [<options>] [-r | -a] [--points-at]" +msgstr "git branch [<options>] [-r | -a] [--points-at]" + +#: builtin/branch.c +msgid "git branch [<options>] [-r | -a] [--format]" +msgstr "git branch [<options>] [-r | -a] [--format]" + +#: builtin/branch.c +#, c-format +msgid "" +"deleting branch '%s' that has been merged to\n" +" '%s', but not yet merged to HEAD" +msgstr "" +"brainse '%s' a bhfuil cumasc orthu a scriosadh\n" +" '%s', ach nÃor chumasc le HEAD go fóill" + +#: builtin/branch.c +#, c-format +msgid "" +"not deleting branch '%s' that is not yet merged to\n" +" '%s', even though it is merged to HEAD" +msgstr "" +"gan brainse '%s' a scriosadh nach bhfuil cumasc fós leis\n" +" '%s', cé go ndéantar é a chumasc le HEAD" + +#: builtin/branch.c +#, c-format +msgid "couldn't look up commit object for '%s'" +msgstr "nà raibh in ann réad tiomanta a lorg suas le haghaidh '%s'" + +#: builtin/branch.c +#, c-format +msgid "the branch '%s' is not fully merged" +msgstr "nÃl an brainse '%s' cumaisc go hiomlán" + +#: builtin/branch.c +#, c-format +msgid "If you are sure you want to delete it, run 'git branch -D %s'" +msgstr "" +"Má tá tú cinnte gur mhaith leat é a scriosadh, reáchtáil 'git branch -D %s'" + +#: builtin/branch.c +msgid "update of config-file failed" +msgstr "theip ar nuashonrú comhad config-file" + +#: builtin/branch.c +msgid "cannot use -a with -d" +msgstr "nà féidir -a a úsáid le -d" + +#: builtin/branch.c +#, c-format +msgid "cannot delete branch '%s' used by worktree at '%s'" +msgstr "nà féidir brainse '%s' a úsáideann crann oibre ag '%s' a scriosadh" + +#: builtin/branch.c +#, c-format +msgid "remote-tracking branch '%s' not found" +msgstr "nÃor aimsÃodh brainse cianrianaithe '%s'" + +#: builtin/branch.c +#, c-format +msgid "" +"branch '%s' not found.\n" +"Did you forget --remote?" +msgstr "" +"nÃor aimsÃodh brainse '%s'.\n" +"Ar ndearna tú dearmad ar --remote?" + +#: builtin/branch.c +#, c-format +msgid "branch '%s' not found" +msgstr "nÃor aimsÃodh brainse '%s'" + +#: builtin/branch.c +#, c-format +msgid "Deleted remote-tracking branch %s (was %s).\n" +msgstr "Brainse cianrianaithe scriosta %s (bhà %s).\n" + +#: builtin/branch.c +#, c-format +msgid "Deleted branch %s (was %s).\n" +msgstr "Brainse %s scriosta (%s ba é).\n" + +#: builtin/branch.c builtin/tag.c +msgid "unable to parse format string" +msgstr "in ann teaghrán formáide a pháirseáil" + +#: builtin/branch.c +msgid "could not resolve HEAD" +msgstr "nà fhéadfaà HEAD a réiteach" + +#: builtin/branch.c +#, c-format +msgid "HEAD (%s) points outside of refs/heads/" +msgstr "Pointà HEAD (%s) lasmuigh de refs/heads/" + +#: builtin/branch.c +#, c-format +msgid "branch %s is being rebased at %s" +msgstr "tá brainse %s á athbhunú ag %s" + +#: builtin/branch.c +#, c-format +msgid "branch %s is being bisected at %s" +msgstr "tá brainse %s á dhÃscaoileadh ag %s" + +#: builtin/branch.c +#, c-format +msgid "HEAD of working tree %s is not updated" +msgstr "NÃl CEANN an chrainn oibre %s nuashonraithe" + +#: builtin/branch.c +#, c-format +msgid "invalid branch name: '%s'" +msgstr "ainm brainse neamhbhailÃ: '%s'" + +#: builtin/branch.c +#, c-format +msgid "no commit on branch '%s' yet" +msgstr "nÃl aon gealltanas ar bhrainse '%s' go fóill" + +#: builtin/branch.c +#, c-format +msgid "no branch named '%s'" +msgstr "nÃl aon bhrainse darb ainm '%s'" + +#: builtin/branch.c +msgid "branch rename failed" +msgstr "theip ar athainmniú brainse" + +#: builtin/branch.c +msgid "branch copy failed" +msgstr "theip ar chóip brainse" + +#: builtin/branch.c +#, c-format +msgid "created a copy of a misnamed branch '%s'" +msgstr "chruthaigh cóip de bhrainse mÃ-ainmnithe '%s'" + +#: builtin/branch.c +#, c-format +msgid "renamed a misnamed branch '%s' away" +msgstr "athainmnigh brainse mÃ-ainmnithe '%s' ar shiúl" + +#: builtin/branch.c +#, c-format +msgid "branch renamed to %s, but HEAD is not updated" +msgstr "athainmnÃodh brainse go %s, ach nÃl HEAD nuashonraithe" + +#: builtin/branch.c +msgid "branch is renamed, but update of config-file failed" +msgstr "athainmnÃtear brainse, ach theip ar nuashonrú ar chomhad config-file" + +#: builtin/branch.c +msgid "branch is copied, but update of config-file failed" +msgstr "cóipeáiltear brainse, ach theip ar nuashonrú comhad config-file" + +#: builtin/branch.c +#, c-format +msgid "" +"Please edit the description for the branch\n" +" %s\n" +"Lines starting with '%s' will be stripped.\n" +msgstr "" +"Cuir an tuairisc don bhrainse in eagar\n" +" %s\n" +"Déanfar lÃnte a thosaÃonn le '%s' a scriosadh.\n" + +#: builtin/branch.c +msgid "Generic options" +msgstr "Roghanna cineálacha" + +#: builtin/branch.c +msgid "show hash and subject, give twice for upstream branch" +msgstr "taispeáin hash agus ábhar, tabhair faoi dhó don bhrainse suas srutha" + +#: builtin/branch.c +msgid "suppress informational messages" +msgstr "teachtaireachtaà faisnéise a chur" + +#: builtin/branch.c builtin/checkout.c builtin/submodule--helper.c +msgid "set branch tracking configuration" +msgstr "cumraÃocht rianaithe brainse a shoc" + +#: builtin/branch.c +msgid "do not use" +msgstr "ná húsáid" + +#: builtin/branch.c +msgid "upstream" +msgstr "suas sruth" + +#: builtin/branch.c +msgid "change the upstream info" +msgstr "athraigh an fhaisnéis suas sruth" + +#: builtin/branch.c +msgid "unset the upstream info" +msgstr "dÃshocraigh an fhaisnéis suas sruth" + +#: builtin/branch.c +msgid "use colored output" +msgstr "úsáid aschur daite" + +#: builtin/branch.c +msgid "act on remote-tracking branches" +msgstr "gnÃomhú ar bhrainsà cianrianaithe" + +#: builtin/branch.c +msgid "print only branches that contain the commit" +msgstr "ach brainsà a phriontáil ina bhfuil an tiomantas" + +#: builtin/branch.c +msgid "print only branches that don't contain the commit" +msgstr "ach brainsà a phriontáil nach bhfuil an tiomantas" + +#: builtin/branch.c +msgid "Specific git-branch actions:" +msgstr "GnÃomhartha sonracha git-branch:" + +#: builtin/branch.c +msgid "list both remote-tracking and local branches" +msgstr "liostáil brainsà cianrianaithe agus áitiúla araon" + +#: builtin/branch.c +msgid "delete fully merged branch" +msgstr "scrios brainse lánchumaisc" + +#: builtin/branch.c +msgid "delete branch (even if not merged)" +msgstr "brainse a scriosadh (fiú mura bhfuil sé cumasaithe)" + +#: builtin/branch.c +msgid "move/rename a branch and its reflog" +msgstr "brainse a bhogadh/athainmniú agus a athainmniú" + +#: builtin/branch.c +msgid "move/rename a branch, even if target exists" +msgstr "brainse a bhogadh/athainmniú, fiú má tá sprioc ann" + +#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c +msgid "do not output a newline after empty formatted refs" +msgstr "ná aschur lÃne nua tar éis aifeanna formáidithe folamh" + +#: builtin/branch.c +msgid "copy a branch and its reflog" +msgstr "cóipeáil brainse agus a reflog" + +#: builtin/branch.c +msgid "copy a branch, even if target exists" +msgstr "cóipeáil brainse, fiú má tá sprioc ann" + +#: builtin/branch.c +msgid "list branch names" +msgstr "liosta ainmneacha brainse" + +#: builtin/branch.c +msgid "show current branch name" +msgstr "taispeáin ainm brainse reatha" + +#: builtin/branch.c builtin/submodule--helper.c +msgid "create the branch's reflog" +msgstr "athbhreithniú na brainse a chruthú" + +#: builtin/branch.c +msgid "edit the description for the branch" +msgstr "cuir an tuairisc don bhrainse a chur in eagar" + +#: builtin/branch.c +msgid "force creation, move/rename, deletion" +msgstr "cruthú fórsa, gluaise/athainmniú, scriosadh" + +#: builtin/branch.c +msgid "print only branches that are merged" +msgstr "ach brainsà a chumasc a phriontáil" + +#: builtin/branch.c +msgid "print only branches that are not merged" +msgstr "ach brainsà nach ndéantar cumasc a phriontáil" + +#: builtin/branch.c +msgid "list branches in columns" +msgstr "liostáil brainsà i gcolúin" + +#: builtin/branch.c builtin/for-each-ref.c builtin/notes.c builtin/tag.c +msgid "object" +msgstr "réad" + +#: builtin/branch.c +msgid "print only branches of the object" +msgstr "ach brainsà den réad a phriontáil" + +#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c +msgid "sorting and filtering are case insensitive" +msgstr "tá sórtáil agus scagadh neamh-Ãogair ó thaobh cásanna de" + +#: builtin/branch.c builtin/ls-files.c +msgid "recurse through submodules" +msgstr "athshlánú trà fho-mhodúil" + +#: builtin/branch.c builtin/for-each-ref.c builtin/ls-files.c builtin/ls-tree.c +#: builtin/tag.c builtin/verify-tag.c +msgid "format to use for the output" +msgstr "formáid le húsáid don aschur" + +#: builtin/branch.c +msgid "failed to resolve HEAD as a valid ref" +msgstr "theip ar HEAD a réiteach mar thagartha bailÃ" + +#: builtin/branch.c builtin/clone.c +msgid "HEAD not found below refs/heads!" +msgstr "Nà fhaightear CEAD thÃos na refs/heads!" + +#: builtin/branch.c +msgid "" +"branch with --recurse-submodules can only be used if " +"submodule.propagateBranches is enabled" +msgstr "" +"nà féidir brainse le --recurse-submodules a úsáid ach amháin má tá " +"submodule.propagateBranches cumasaithe" + +#: builtin/branch.c +msgid "--recurse-submodules can only be used to create branches" +msgstr "Nà féidir --recurse-submodules a úsáid ach chun brainsà a chruthú" + +#: builtin/branch.c +msgid "branch name required" +msgstr "ainm brainse ag teastáil" + +#: builtin/branch.c +msgid "cannot give description to detached HEAD" +msgstr "nà féidir cur sÃos a thabhairt ar HEAD scoite" + +#: builtin/branch.c +msgid "cannot edit description of more than one branch" +msgstr "nà féidir cur sÃos ar nÃos mó ná brainse amháin a chur in eagar" + +#: builtin/branch.c +msgid "cannot copy the current branch while not on any" +msgstr "nà féidir leis an mbrainse reatha a chóipeáil cé nach bhfuil ar aon" + +#: builtin/branch.c +msgid "cannot rename the current branch while not on any" +msgstr "nà féidir leis an mbrainse reatha a athainmniú cé nach bhfuil ar aon" + +#: builtin/branch.c +msgid "too many branches for a copy operation" +msgstr "an iomarca brainsà le haghaidh oibrÃocht cóipeála" + +#: builtin/branch.c +msgid "too many arguments for a rename operation" +msgstr "an iomarca argóintà maidir le hoibrÃocht athainmnithe" + +#: builtin/branch.c +msgid "too many arguments to set new upstream" +msgstr "an iomarca argóintà chun suas an sruth nua a shocrú" + +#: builtin/branch.c +#, c-format +msgid "" +"could not set upstream of HEAD to %s when it does not point to any branch" +msgstr "" +"nà fhéadfaà suas sruth de HEAD a shocrú go %s nuair nach dtugann sé in iúl " +"go dtà aon bhrainse" + +#: builtin/branch.c +#, c-format +msgid "no such branch '%s'" +msgstr "nÃl brainse den sórt sin '%s'" + +#: builtin/branch.c +#, c-format +msgid "branch '%s' does not exist" +msgstr "nÃl brainse '%s' ann" + +#: builtin/branch.c +msgid "too many arguments to unset upstream" +msgstr "an iomarca argóintà le dÃshocrú suas an sruth" + +#: builtin/branch.c +msgid "could not unset upstream of HEAD when it does not point to any branch" +msgstr "" +"nà fhéadfaà a dhÃshuiteáil suas an sruth den HEAD nuair nach dtugann sé in " +"iúl d'aon bhrainse" + +#: builtin/branch.c +#, c-format +msgid "branch '%s' has no upstream information" +msgstr "nÃl aon fhaisnéis suas sruth ag brainse '%s'" + +#: builtin/branch.c +msgid "" +"the -a, and -r, options to 'git branch' do not take a branch name.\n" +"Did you mean to use: -a|-r --list <pattern>?" +msgstr "" +"nà ghlacann na roghanna -a, agus -r, le 'git branch' ainm brainse.\n" +"<pattern>An raibh sé i gceist agat úsáid a bhaint as: -a|-r --list?" + +#: builtin/branch.c +msgid "" +"the '--set-upstream' option is no longer supported. Please use '--track' or " +"'--set-upstream-to' instead" +msgstr "" +"nà thacaÃtear leis an rogha '--set-upstream' a thuilleadh. Úsáid '--track' " +"nó '--set-upstream-to' ina ionad" + +#: builtin/bugreport.c +msgid "git version:\n" +msgstr "leagan git:\n" + +#: builtin/bugreport.c +msgid "compiler info: " +msgstr "eolas tiomsaitheora: " + +#: builtin/bugreport.c +msgid "libc info: " +msgstr "eolas libc: " + +#: builtin/bugreport.c +msgid "not run from a git repository - no hooks to show\n" +msgstr "gan rith ó stór git - gan aon chrúcaà le taispeáint\n" + +#: builtin/bugreport.c +msgid "" +"git bugreport [(-o | --output-directory) <path>]\n" +" [(-s | --suffix) <format> | --no-suffix]\n" +" [--diagnose[=<mode>]]" +msgstr "" +"<path>git bugreport [(-o | --output-directory)]\n" +" <format>[(-s | --iarmhÃr) | --no-iarmhÃr]\n" +" [--diagnóis [=<mode>]]" + +#: builtin/bugreport.c +msgid "" +"Thank you for filling out a Git bug report!\n" +"Please answer the following questions to help us understand your issue.\n" +"\n" +"What did you do before the bug happened? (Steps to reproduce your issue)\n" +"\n" +"What did you expect to happen? (Expected behavior)\n" +"\n" +"What happened instead? (Actual behavior)\n" +"\n" +"What's different between what you expected and what actually happened?\n" +"\n" +"Anything else you want to add:\n" +"\n" +"Please review the rest of the bug report below.\n" +"You can delete any lines you don't wish to share.\n" +msgstr "" +"Go raibh maith agat as tuarascáil fabht Git a lÃonadh!\n" +"Freagair na ceisteanna seo a leanas le do thoil chun cabhrú linn do cheist a " +"thuiscint\n" +"\n" +"Cad a rinne tú sular tharla an fabht? (Céimeanna chun d'eisiúint a " +"atáirgeadh)\n" +"\n" +"Cad a bhà tú ag súil go dtarlódh? (Iompar ag súil leis)\n" +"\n" +"Cad a tharla ina ionad sin? (Iompar iarbhÃr)\n" +"\n" +"Cad atá difriúil idir an méid a bhà súil agat leis agus cad a tharla i " +"ndáirÃre\n" +"\n" +"Aon rud eile a theastaÃonn uait a chur leis:\n" +"\n" +"Déan athbhreithniú ar an chuid eile den tuarascáil fabht thÃos.\n" +"Is féidir leat aon lÃnte nach dteastaÃonn uait a roinnt a scriosadh.\n" + +#: builtin/bugreport.c builtin/commit.c builtin/fast-export.c builtin/rebase.c +#: parse-options.h +msgid "mode" +msgstr "mód" + +#: builtin/bugreport.c +msgid "" +"create an additional zip archive of detailed diagnostics (default 'stats')" +msgstr "" +"cruthú cartlann zip breise de dhiagnóiseach mionsonraithe ('stats' " +"réamhshocraithe)" + +#: builtin/bugreport.c +msgid "specify a destination for the bugreport file(s)" +msgstr "sonraigh ceann scrÃbe don chomhad (Ã) bugreport" + +#: builtin/bugreport.c +msgid "specify a strftime format suffix for the filename(s)" +msgstr "sonraigh iarmhÃr formáid strftime don ainm (Ã) comhaid" + +#: builtin/bugreport.c +#, c-format +msgid "unknown argument `%s'" +msgstr "argóint anaithnid `%s'" + +#: builtin/bugreport.c builtin/diagnose.c +#, c-format +msgid "could not create leading directories for '%s'" +msgstr "nà fhéadfaà eolairà tosaigh a chruthú do '%s'" + +#: builtin/bugreport.c builtin/diagnose.c +#, c-format +msgid "unable to create diagnostics archive %s" +msgstr "nach féidir cartlann diagnóiseach %s a chruthú" + +#: builtin/bugreport.c +msgid "System Info" +msgstr "Eolas Córais" + +#: builtin/bugreport.c +msgid "Enabled Hooks" +msgstr "Crúcaà Cumasaithe" + +#: builtin/bugreport.c +#, c-format +msgid "unable to write to %s" +msgstr "nach féidir a scrÃobh chuig %s" + +#: builtin/bugreport.c +#, c-format +msgid "Created new report at '%s'.\n" +msgstr "CruthaÃodh tuarascáil nua ag '%s'.\n" + +#: builtin/bundle.c +msgid "" +"git bundle create [-q | --quiet | --progress]\n" +" [--version=<version>] <file> <git-rev-list-args>" +msgstr "" +"cruthaigh bonn git [-q | --quiet | --progress]\n" +" <version>[--leagan =] <file><git-rev-list-args>" + +#: builtin/bundle.c +msgid "git bundle verify [-q | --quiet] <file>" +msgstr "fÃorú beartán git [-q | --quiet] <file>" + +#: builtin/bundle.c +msgid "git bundle list-heads <file> [<refname>...]" +msgstr "<refname>ceannairà liosta bonn git <file>[...]" + +#: builtin/bundle.c +msgid "git bundle unbundle [--progress] <file> [<refname>...]" +msgstr "<refname>dÃbhuntáil bonn git [--progress] <file>[...]" + +#: builtin/bundle.c +msgid "need a <file> argument" +msgstr "teastaÃonn ar <file>góint" + +#: builtin/bundle.c builtin/pack-objects.c +msgid "do not show progress meter" +msgstr "ná taispeáin méadar dul chun cinn" + +#: builtin/bundle.c builtin/pack-objects.c +msgid "show progress meter" +msgstr "taispeáin méadar dul chun cinn" + +#: builtin/bundle.c +msgid "historical; same as --progress" +msgstr "stairiúil; mar an gcéanna le --progress" + +#: builtin/bundle.c +msgid "historical; does nothing" +msgstr "stairiúil; nà dhéanann aon rud" + +#: builtin/bundle.c +msgid "specify bundle format version" +msgstr "leagan formáid beartán a shonrú" + +#: builtin/bundle.c +msgid "Need a repository to create a bundle." +msgstr "TeastaÃonn stór chun beartán a chruthú." + +#: builtin/bundle.c +msgid "do not show bundle details" +msgstr "ná taispeáin sonraà beartán" + +#: builtin/bundle.c bundle.c +msgid "need a repository to verify a bundle" +msgstr "teastaÃonn stór chun beartán a fhÃorú" + +#: builtin/bundle.c +#, c-format +msgid "%s is okay\n" +msgstr "%s ceart go leor\n" + +#: builtin/bundle.c +msgid "Need a repository to unbundle." +msgstr "TeastaÃonn stór chun dÃcheangail a dhÃcheangal." + +#: builtin/bundle.c +msgid "Unbundling objects" +msgstr "Rudaà a dhÃcheangal" + +#: builtin/cat-file.c +#, c-format +msgid "cannot read object %s '%s'" +msgstr "nà féidir réad %s '%s' a léamh" + +#: builtin/cat-file.c +msgid "flush is only for --buffer mode" +msgstr "nÃl sruth ach le haghaidh mód --buffer" + +#: builtin/cat-file.c +msgid "empty command in input" +msgstr "ordú folamh san ionchur" + +#: builtin/cat-file.c +#, c-format +msgid "whitespace before command: '%s'" +msgstr "spás bán roimh an ordú: '%s'" + +#: builtin/cat-file.c +#, c-format +msgid "%s requires arguments" +msgstr "TeastaÃonn argóintà %s" + +#: builtin/cat-file.c +#, c-format +msgid "%s takes no arguments" +msgstr "Nà ghlacann %s aon argóintÃ" + +#: builtin/cat-file.c +msgid "only one batch option may be specified" +msgstr "nà féidir ach rogha baisc amháin a shonrú" + +#: builtin/cat-file.c +msgid "git cat-file <type> <object>" +msgstr "git cat-file <type> <object>" + +#: builtin/cat-file.c +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <réad>" + +#: builtin/cat-file.c +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>]" + +#: builtin/cat-file.c +msgid "" +"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" +"objects]\n" +" [--buffer] [--follow-symlinks] [--unordered]\n" +" [--textconv | --filters] [-Z]" +msgstr "" +"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" +"objects]\n" +" [--buffer] [--follow-symlinks] [--unordered]\n" +" [--textconv | --filters] [-Z]" + +#: builtin/cat-file.c +msgid "Check object existence or emit object contents" +msgstr "Seiceáil go bhfuil réad ann nó astaigh ábhar réad" + +#: builtin/cat-file.c +msgid "check if <object> exists" +msgstr "seiceáil an bhfuil <object> ann" + +#: builtin/cat-file.c +msgid "pretty-print <object> content" +msgstr "<object> ábhar priontáil álainn" + +#: builtin/cat-file.c +msgid "Emit [broken] object attributes" +msgstr "Easaigh tréithe réada [briste]" + +#: builtin/cat-file.c +msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)" +msgstr "" +"taispeáint cineál réad (ceann de 'blob', 'crann', 'tiomantas', 'tag',...)" + +#: builtin/cat-file.c +msgid "show object size" +msgstr "taispeáin méid an réad" + +#: builtin/cat-file.c builtin/log.c +msgid "use mail map file" +msgstr "úsáid comhad léarscáil rÃomhphoist" + +#: builtin/cat-file.c +msgid "Batch objects requested on stdin (or --batch-all-objects)" +msgstr "Baisc rudaà a iarrtar ar stdin (nó --batch-all-objects)" + +#: builtin/cat-file.c +msgid "show full <object> or <rev> contents" +msgstr "taispeáin iomlán <object>nó á <rev>bhar" + +#: builtin/cat-file.c +msgid "like --batch, but don't emit <contents>" +msgstr "cosúil le --batch, ach ná astaÃonn <contents>" + +#: builtin/cat-file.c +msgid "stdin is NUL-terminated" +msgstr "tá stdin foirceanta ag NUL" + +#: builtin/cat-file.c +msgid "stdin and stdout is NUL-terminated" +msgstr "tá stdin agus stdout foirceannta NUL" + +#: builtin/cat-file.c +msgid "read commands from stdin" +msgstr "léigh orduithe ó stdin" + +#: builtin/cat-file.c +msgid "with --batch[-check]: ignores stdin, batches all known objects" +msgstr "" +"le --batch [-check]: déanann neamhaird ar stdin, déanann baisceanna gach rud " +"aitheanta" + +#: builtin/cat-file.c +msgid "Change or optimize batch output" +msgstr "Athraigh nó barrfheabhsú aschur baisc" + +#: builtin/cat-file.c +msgid "buffer --batch output" +msgstr "maolán --batch baisc" + +#: builtin/cat-file.c +msgid "follow in-tree symlinks" +msgstr "lean naisc shiombailà in-chrann" + +#: builtin/cat-file.c +msgid "do not order objects before emitting them" +msgstr "ná ordaigh rudaà sula n-astaÃonn tú iad" + +#: builtin/cat-file.c +msgid "" +"Emit object (blob or tree) with conversion or filter (stand-alone, or with " +"batch)" +msgstr "" +"Rud a astaÃonn (blob nó crann) le comhshó nó scagaire (neamhspleách, nó le " +"baisc)" + +#: builtin/cat-file.c +msgid "run textconv on object's content" +msgstr "reáchtáil textconv ar ábhar an réad" + +#: builtin/cat-file.c +msgid "run filters on object's content" +msgstr "reáchtáil scagairà ar ábhar an rud" + +#: builtin/cat-file.c +msgid "blob|tree" +msgstr "blob | crann" + +#: builtin/cat-file.c +msgid "use a <path> for (--textconv | --filters); Not with 'batch'" +msgstr "úsáid a le <path>haghaidh (--textconv | --filters); Nà le 'baisc'" + +#: builtin/cat-file.c +msgid "objects filter only supported in batch mode" +msgstr "nà thacaÃtear scagaire rudaà ach i mód baisc" + +#: builtin/cat-file.c +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "nà thacaÃtear le scagaire réadanna: '%s'" + +#: builtin/cat-file.c +#, c-format +msgid "'%s=<%s>' needs '%s' or '%s'" +msgstr "'%s=<%s>' teastaÃonn '%s' nó '%s'" + +#: builtin/cat-file.c +msgid "path|tree-ish" +msgstr "cosán | crann-ish" + +#: builtin/cat-file.c +#, c-format +msgid "'%s' requires a batch mode" +msgstr "ÉilÃonn '%s' modh baisc" + +#: builtin/cat-file.c +#, c-format +msgid "'-%c' is incompatible with batch mode" +msgstr "NÃl '-%c' comhoiriúnach le mód baisc" + +#: builtin/cat-file.c +msgid "batch modes take no arguments" +msgstr "nà ghlacann modhanna baisc aon argóintÃ" + +#: builtin/cat-file.c +#, c-format +msgid "<rev> required with '%s'" +msgstr "<rev>ag teastáil le '%s'" + +#: builtin/cat-file.c +#, c-format +msgid "<object> required with '-%c'" +msgstr "<object>ag teastáil le '-%c'" + +#: builtin/cat-file.c +#, c-format +msgid "only two arguments allowed in <type> <object> mode, not %d" +msgstr "nà cheadaÃtear ach dhá argóint <type><object>sa mhodh, nà %d" + +#: builtin/check-attr.c +msgid "" +"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] " +"<pathname>..." +msgstr "" +"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] " +"<pathname>..." + +#: builtin/check-attr.c +msgid "" +"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" +msgstr "" +"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]" + +#: builtin/check-attr.c +msgid "report all attributes set on file" +msgstr "tuairisc a thabhairt ar gach tréithe atá leagtha sÃos" + +#: builtin/check-attr.c +msgid "use .gitattributes only from the index" +msgstr "bain úsáid as .gitattributs ach ón innéacs" + +#: builtin/check-attr.c builtin/check-ignore.c builtin/hash-object.c +msgid "read file names from stdin" +msgstr "léigh ainmneacha comhaid ó stdin" + +#: builtin/check-attr.c builtin/check-ignore.c +msgid "terminate input and output records by a NUL character" +msgstr "taifid ionchuir agus aschuir a fhoirceannadh le carachtar NUL" + +#: builtin/check-attr.c +msgid "<tree-ish>" +msgstr "<tree-ish>" + +#: builtin/check-attr.c +msgid "which tree-ish to check attributes at" +msgstr "cén crainn le tréithe a sheiceáil ag" + +#: builtin/check-ignore.c builtin/checkout.c builtin/gc.c builtin/worktree.c +msgid "suppress progress reporting" +msgstr "cur chun cinn tuairiscithe" + +#: builtin/check-ignore.c +msgid "show non-matching input paths" +msgstr "cosáin ionchuir neamh-mheaitseála" + +#: builtin/check-ignore.c +msgid "ignore index when checking" +msgstr "neamhaird a dhéanamh ar innéacs agus" + +#: builtin/check-ignore.c +msgid "cannot specify pathnames with --stdin" +msgstr "nà féidir ainmneacha cosáin a shonrú le --stdin" + +#: builtin/check-ignore.c +msgid "-z only makes sense with --stdin" +msgstr "Nà dhéanann -z ciall ach le --stdin" + +#: builtin/check-ignore.c +msgid "no path specified" +msgstr "nÃl aon chosán sonraithe" + +#: builtin/check-ignore.c +msgid "--quiet is only valid with a single pathname" +msgstr "NÃl --quiet bailà ach le ainm cosán amháin" + +#: builtin/check-ignore.c +msgid "cannot have both --quiet and --verbose" +msgstr "nà féidir --quiet agus --verbose araon a bheith agat" + +#: builtin/check-ignore.c +msgid "--non-matching is only valid with --verbose" +msgstr "NÃl --non-matching bailà ach le --verbose" + +#: builtin/check-mailmap.c +msgid "git check-mailmap [<options>] <contact>..." +msgstr "git check-mailmap [<options>] <contact>..." + +#: builtin/check-mailmap.c +msgid "also read contacts from stdin" +msgstr "léigh teagmhálacha ó stdin freisin" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from file" +msgstr "léigh iontrálacha rÃomhphoist breise ón gcomhad" + +#: builtin/check-mailmap.c +msgid "blob" +msgstr "blob" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from blob" +msgstr "léigh iontrálacha rÃomhphoist breise ó blob" + +#: builtin/check-mailmap.c +msgid "no contacts specified" +msgstr "aon teagmhálacha sonraithe" + +#: builtin/checkout--worker.c +msgid "git checkout--worker [<options>]" +msgstr "git checkout--worker [<options>]" + +#: builtin/checkout--worker.c builtin/checkout-index.c builtin/column.c +#: builtin/submodule--helper.c builtin/worktree.c +msgid "string" +msgstr "teaghrán" + +#: builtin/checkout--worker.c builtin/checkout-index.c +msgid "when creating files, prepend <string>" +msgstr "agus comhaid á gcruthú agat, déan iarracht <string>" + +#: builtin/checkout-index.c +msgid "git checkout-index [<options>] [--] [<file>...]" +msgstr "git checkout-index [<options>] [--] [<file>...]" + +#: builtin/checkout-index.c +msgid "stage should be between 1 and 3 or all" +msgstr "ba chóir go mbeadh an chéim idir 1 agus 3 nó gach ceann" + +#: builtin/checkout-index.c +msgid "check out all files in the index" +msgstr "seiceáil gach comhad san innéacs" + +#: builtin/checkout-index.c +msgid "do not skip files with skip-worktree set" +msgstr "ná scipeáil comhaid le tacar scip-work tree" + +#: builtin/checkout-index.c +msgid "force overwrite of existing files" +msgstr "athscrÃobh fórsa na gcomhaid atá ann cheana" + +#: builtin/checkout-index.c +msgid "no warning for existing files and files not in index" +msgstr "" +"gan aon rabhadh maidir le comhaid agus comhaid atá ann cheana nach bhfuil " +"san innéacs" + +#: builtin/checkout-index.c +msgid "don't checkout new files" +msgstr "ná seiceáil comhaid nua" + +#: builtin/checkout-index.c +msgid "update stat information in the index file" +msgstr "faisnéis stat a nuashonrú sa chomhad innéacs" + +#: builtin/checkout-index.c +msgid "read list of paths from the standard input" +msgstr "léigh liosta na gcosáin ón ionchur caighdeánach" + +#: builtin/checkout-index.c +msgid "write the content to temporary files" +msgstr "scrÃobh an t-ábhar chuig comhaid sealadacha" + +#: builtin/checkout-index.c +msgid "copy out the files from named stage" +msgstr "cóipeáil amach na comhaid ón gcéim ainmnithe" + +#: builtin/checkout.c +msgid "git checkout [<options>] <branch>" +msgstr "git checkout [<roghanna>] <brainse>" + +#: builtin/checkout.c +msgid "git checkout [<options>] [<branch>] -- <file>..." +msgstr "git checkout [<roghanna>] [<brainse>] --<comhad>..." + +#: builtin/checkout.c +msgid "git switch [<options>] [<branch>]" +msgstr "git switch [<roghanna>] [<brainse>]" + +#: builtin/checkout.c +msgid "git restore [<options>] [--source=<branch>] <file>..." +msgstr "git restore [<roghanna>] [--source=<brainse>] <comhad>..." + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have our version" +msgstr "nÃl ár leagan ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have their version" +msgstr "nÃl a leagan ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have all necessary versions" +msgstr "nÃl gach leagan riachtanach ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have necessary versions" +msgstr "nÃl leaganacha riachtanacha ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s': cannot merge" +msgstr "cosán '%s': nà féidir a chumasc" + +#: builtin/checkout.c +#, c-format +msgid "Unable to add merge result for '%s'" +msgstr "Nà féidir toradh cumaisc a chur le haghaidh '%s'" + +#: builtin/checkout.c +#, c-format +msgid "Recreated %d merge conflict" +msgid_plural "Recreated %d merge conflicts" +msgstr[0] "AthchruthaÃodh %d coimhlint chumasc" +msgstr[1] "AthchruthaÃodh %d coinbhleachtaà chumaisc" +msgstr[2] "AthchruthaÃodh %d coinbhleachtaà chumaisc" + +#: builtin/checkout.c +#, c-format +msgid "Updated %d path from %s" +msgid_plural "Updated %d paths from %s" +msgstr[0] "NuashonraÃodh %d cosán ó %s" +msgstr[1] "NuashonraÃodh %d cosán ó %s" +msgstr[2] "NuashonraÃodh %d cosán ó %s" + +#: builtin/checkout.c +#, c-format +msgid "Updated %d path from the index" +msgid_plural "Updated %d paths from the index" +msgstr[0] "NuashonraÃodh %d cosán ón innéacs" +msgstr[1] "NuashonraÃodh %d cosán ón innéacs" +msgstr[2] "NuashonraÃodh %d cosán ón innéacs" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot be used with updating paths" +msgstr "Nà féidir '%s' a úsáid le cosáin a nuashonrú" + +#: builtin/checkout.c +#, c-format +msgid "Cannot update paths and switch to branch '%s' at the same time." +msgstr "" +"Nà féidir cosáin a nuashonrú agus aistriú go brainse '%s' ag an am céanna." + +#: builtin/checkout.c +#, c-format +msgid "neither '%s' or '%s' is specified" +msgstr "nÃl '%s' ná '%s' sonraithe" + +#: builtin/checkout.c +#, c-format +msgid "'%s' must be used when '%s' is not specified" +msgstr "Nà mór '%s' a úsáid nuair nach sonraÃtear '%s'" + +#: builtin/checkout.c +#, c-format +msgid "'%s' or '%s' cannot be used with %s" +msgstr "Nà féidir '%s' nó '%s' a úsáid le %s" + +#: builtin/checkout.c +#, c-format +msgid "'%s', '%s', or '%s' cannot be used when checking out of a tree" +msgstr "" +"Nà féidir '%s', '%s', nó '%s' a úsáid agus tú ag seiceáil amach as crann" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' is unmerged" +msgstr "tá cosán '%s' neamh-chomhcheangailte" + +#: 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 "nach féidir crann a léamh (%s)" + +#: builtin/checkout.c +msgid "you need to resolve your current index first" +msgstr "nà mór duit d'innéacs reatha a réiteach ar dtús" + +#: builtin/checkout.c +#, c-format +msgid "" +"cannot continue with staged changes in the following files:\n" +"%s" +msgstr "" +"nà féidir leanúint ar aghaidh le hathruithe céime sna comhaid seo a leanas:\n" +"%s" + +#: builtin/checkout.c +#, c-format +msgid "Can not do reflog for '%s': %s\n" +msgstr "Nà féidir athbhreithniú a dhéanamh le haghaidh '%s': %s\n" + +#: builtin/checkout.c +msgid "HEAD is now at" +msgstr "Tá HEAD anois ag" + +#: builtin/checkout.c builtin/clone.c +msgid "unable to update HEAD" +msgstr "in ann HEAD a nuashonrú" + +#: builtin/checkout.c +#, c-format +msgid "Reset branch '%s'\n" +msgstr "Athshocraigh brainse '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid "Already on '%s'\n" +msgstr "Ar '%s' cheana féin\n" + +#: builtin/checkout.c +#, c-format +msgid "Switched to and reset branch '%s'\n" +msgstr "Aistrigh agus athshocraigh brainse '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid "Switched to a new branch '%s'\n" +msgstr "Aistrithe go brainse nua '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid "Switched to branch '%s'\n" +msgstr "Aistrithe go brainse '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid " ... and %d more.\n" +msgstr " ... agus %d nÃos mó.\n" + +#: builtin/checkout.c +#, c-format +msgid "" +"Warning: you are leaving %d commit behind, not connected to\n" +"any of your branches:\n" +"\n" +"%s\n" +msgid_plural "" +"Warning: you are leaving %d commits behind, not connected to\n" +"any of your branches:\n" +"\n" +"%s\n" +msgstr[0] "" +"Rabhadh: tá %d tiomantas á fhágáil agat, gan cheangal le haon cheann de do " +"bhrainsÃ:\n" +"\n" +"%s\n" +msgstr[1] "" +"Rabhadh: tá %d tiomantas á bhfágáil agat i do dhiaidh, gan aon cheangal le " +"haon cheann de do bhrainsÃ:\n" +"\n" +"%s\n" +msgstr[2] "" +"Rabhadh: tá %d tiomantas á bhfágáil agat i do dhiaidh, gan aon cheangal le " +"haon cheann de do bhrainsÃ:\n" +"\n" +"%s\n" + +#: builtin/checkout.c +#, c-format +msgid "" +"If you want to keep it by creating a new branch, this may be a good time\n" +"to do so with:\n" +"\n" +" git branch <new-branch-name> %s\n" +"\n" +msgid_plural "" +"If you want to keep them by creating a new branch, this may be a good time\n" +"to do so with:\n" +"\n" +" git branch <new-branch-name> %s\n" +"\n" +msgstr[0] "" +"Más mian leat é a choinneáil trà bhrainse nua a chruthú, b'fhéidir gur dea-" +"am é seo chun é sin a dhéanamh le:\n" +"\n" +"git branch <ainm-brainse-nua> %s\n" +msgstr[1] "" +"Más mian leat iad a choinneáil trà bhrainse nua a chruthú, b'fhéidir gur dea-" +"am é seo chun é sin a dhéanamh le:\n" +"\n" +"git branch <ainm-brainse-nua> %s\n" +msgstr[2] "" +"Más mian leat iad a choinneáil trà bhrainse nua a chruthú, b'fhéidir gur dea-" +"am é seo chun é sin a dhéanamh le:\n" +"\n" +"git branch <ainm-brainse-nua> %s\n" + +#: builtin/checkout.c +msgid "internal error in revision walk" +msgstr "earráid inmheánach i dsiúlóid" + +#: builtin/checkout.c +msgid "Previous HEAD position was" +msgstr "Bhà post CEAD roimhe seo" + +#: builtin/checkout.c +msgid "You are on a branch yet to be born" +msgstr "Tá tú ar bhrainse nach rugadh fós" + +#: builtin/checkout.c +#, c-format +msgid "" +"'%s' could be both a local file and a tracking branch.\n" +"Please use -- (and optionally --no-guess) to disambiguate" +msgstr "" +"D'fhéadfadh '%s' a bheith ina chomhad áitiúil agus ina bhrainse rianaithe " +"araon.\n" +"Úsáid le do thoil -- (agus go roghnach --no-guess) chun a dhÃbhriú" + +#: builtin/checkout.c +msgid "" +"If you meant to check out a remote tracking branch on, e.g. 'origin',\n" +"you can do so by fully qualifying the name with the --track option:\n" +"\n" +" git checkout --track origin/<name>\n" +"\n" +"If you'd like to always have checkouts of an ambiguous <name> prefer\n" +"one remote, e.g. the 'origin' remote, consider setting\n" +"checkout.defaultRemote=origin in your config." +msgstr "" +"Má bhà sé i gceist agat brainse cianrianaithe a sheiceáil ar, e.g. " +"'origin',\n" +"is féidir leat é sin a dhéanamh trÃd an ainm a cháiliú go hiomlán leis an " +"rogha --track:\n" +"\n" +" git checkout --track origin/<name>\n" +"\n" +"<name>Más mian leat seiceálacha débhrÃoch a bheith agat i gcónaà is fearr " +"leat\n" +"iargúlta amháin, e.g. an iargúlta 'origin', smaoinigh ar shocrú\n" +"checkout.defaultRemote=origin i do chumraÃocht." + +#: builtin/checkout.c +#, c-format +msgid "'%s' matched multiple (%d) remote tracking branches" +msgstr "Mheaitseáil '%s' roinnt (%d) brainsà rianaithe iargúlta" + +#: builtin/checkout.c +msgid "only one reference expected" +msgstr "nÃl ach tagairt amháin ag súil leis" + +#: builtin/checkout.c +#, c-format +msgid "only one reference expected, %d given." +msgstr "nÃl ach tagairt amháin ag súil leis, %d tugtha." + +#: builtin/checkout.c builtin/worktree.c +#, c-format +msgid "invalid reference: %s" +msgstr "tagairt neamhbhailÃ: %s" + +#: builtin/checkout.c +#, c-format +msgid "reference is not a tree: %s" +msgstr "nà crann é tagairt: %s" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got tag '%s'" +msgstr "táthar ag súil le brainse, faightear tag '%s'" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got remote branch '%s'" +msgstr "táthar ag súil le brainse, fuair brainse iargúlta '%s'" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got '%s'" +msgstr "táthar ag súil le brainse, fuair '%s'" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got commit '%s'" +msgstr "táthar ag súil le brainse, fuair sé tiomantas '%s'" + +#: builtin/checkout.c +msgid "" +"If you want to detach HEAD at the commit, try again with the --detach option." +msgstr "" +"Más mian leat HEAD a dhÃcheangal ag an tiomantas, déan iarracht arÃs leis an " +"rogha --detach." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while merging\n" +"Consider \"git merge --quit\" or \"git worktree add\"." +msgstr "" +"nà féidir brainse a athrú agus cumasc á dhéanamh\n" +"Smaoinigh ar \"git merge --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch in the middle of an am session\n" +"Consider \"git am --quit\" or \"git worktree add\"." +msgstr "" +"nà féidir brainse a athrú i lár seisiún am\n" +"Smaoinigh ar \"git am --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while rebasing\n" +"Consider \"git rebase --quit\" or \"git worktree add\"." +msgstr "" +"nà féidir brainse a athrú agus athbhunú á dhéanamh\n" +"Smaoinigh ar \"git rebase --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while cherry-picking\n" +"Consider \"git cherry-pick --quit\" or \"git worktree add\"." +msgstr "" +"nà féidir brainse a athrú agus tú ag cherry-picking\n" +"Smaoinigh ar \"git cherry-pick --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while reverting\n" +"Consider \"git revert --quit\" or \"git worktree add\"." +msgstr "" +"nà féidir brainse a athrú agus aisiompú á dhéanamh\n" +"Smaoinigh ar \"git revert --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "you are switching branch while bisecting" +msgstr "tá tú ag athrú brainse agus tú ag déileáil" + +#: builtin/checkout.c +msgid "paths cannot be used with switching branches" +msgstr "nà féidir cosáin a úsáid le brainsà a athrú" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot be used with switching branches" +msgstr "Nà féidir '%s' a úsáid le brainsà a athrú" + +#: builtin/checkout.c +#, c-format +msgid "'%s' needs the paths to check out" +msgstr "TeastaÃonn '%s' na cosáin chun seiceáil" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot be used with '%s'" +msgstr "Nà féidir '%s' a úsáid le '%s'" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot take <start-point>" +msgstr "Nà féidir '%s' a ghlacadh <start-point>" + +#: builtin/checkout.c +#, c-format +msgid "Cannot switch branch to a non-commit '%s'" +msgstr "Nà féidir brainse a aistriú go '%s' neamh-thiomanta" + +#: builtin/checkout.c +msgid "missing branch or commit argument" +msgstr "brainse ar iarraidh nó argóint a dhéanamh" + +#: builtin/checkout.c +#, c-format +msgid "unknown conflict style '%s'" +msgstr "stÃl choimhlinte anaithnid '%s'" + +#: builtin/checkout.c +msgid "perform a 3-way merge with the new branch" +msgstr "cumasc 3 bhealach a dhéanamh leis an mbrainse nua" + +#: builtin/checkout.c builtin/log.c builtin/range-diff.c parse-options.h +msgid "style" +msgstr "stÃl" + +#: builtin/checkout.c +msgid "conflict style (merge, diff3, or zdiff3)" +msgstr "stÃl choimhlinte (cumaisc, diff3, nó zdiff3)" + +#: builtin/checkout.c builtin/worktree.c +msgid "detach HEAD at named commit" +msgstr "dÃcheangail HEAD ag an tiomnú ainmnithe" + +#: builtin/checkout.c +msgid "force checkout (throw away local modifications)" +msgstr "seiceáil fórsa (caith modhnuithe áitiúla)" + +#: builtin/checkout.c +msgid "new-branch" +msgstr "brainse-nua" + +#: builtin/checkout.c +msgid "new unborn branch" +msgstr "brainse nua gan breith" + +#: builtin/checkout.c builtin/merge.c +msgid "update ignored files (default)" +msgstr "nuashonrú comhaid a dhéantar neamhaird orthu" + +#: builtin/checkout.c +msgid "do not check if another worktree is using this branch" +msgstr "" +"ná seiceáil an bhfuil crann oibre eile á úsáid ag baint úsáide as an " +"mbrainse seo" + +#: builtin/checkout.c +msgid "checkout our version for unmerged files" +msgstr "seiceáil ár leagan le haghaidh comhaid neamh-chumasaithe" + +#: builtin/checkout.c +msgid "checkout their version for unmerged files" +msgstr "seiceáil a leagan le haghaidh comhaid neamh-chumasaithe" + +#: builtin/checkout.c +msgid "do not limit pathspecs to sparse entries only" +msgstr "ná teorainn le speisiúintà cosáin le hiontrálacha neamhchoitianta" + +#: builtin/checkout.c +#, c-format +msgid "options '-%c', '-%c', and '%s' cannot be used together" +msgstr "nà féidir na roghanna '-%c', '-%c', agus '%s' a úsáid le chéile" + +#: builtin/checkout.c +msgid "--track needs a branch name" +msgstr "--track tá ainm brainse ag teastáil" + +#: builtin/checkout.c +#, c-format +msgid "missing branch name; try -%c" +msgstr "ainm brainse ar iarraidh; iarracht -%c" + +#: builtin/checkout.c +#, c-format +msgid "could not resolve %s" +msgstr "nà fhéadfaà %s a réiteach" + +#: builtin/checkout.c +msgid "invalid path specification" +msgstr "sonraÃocht cosáin nebhail" + +#: builtin/checkout.c +#, c-format +msgid "'%s' is not a commit and a branch '%s' cannot be created from it" +msgstr "Nà tiomantas é '%s' agus nà féidir brainse '%s' a chruthú uaidh" + +#: builtin/checkout.c +#, c-format +msgid "git checkout: --detach does not take a path argument '%s'" +msgstr "git checkout: --detach nà ghlacann argóint cosáin '%s'" + +#: builtin/checkout.c +msgid "" +"git checkout: --ours/--theirs, --force and --merge are incompatible when\n" +"checking out of the index." +msgstr "" +"git checkout: --ours/--theirs, --force agus --merge neamhoiriúnach nuair\n" +"seiceáil amach as an innéacs." + +#: builtin/checkout.c +msgid "you must specify path(s) to restore" +msgstr "nà mór duit cosáin(Ã) a shonrú chun athchóiriú" + +#: builtin/checkout.c builtin/clone.c builtin/remote.c builtin/replay.c +#: builtin/submodule--helper.c builtin/worktree.c +msgid "branch" +msgstr "brainse" + +#: builtin/checkout.c +msgid "create and checkout a new branch" +msgstr "brainse nua a chruthú agus a sheiceáil" + +#: builtin/checkout.c +msgid "create/reset and checkout a branch" +msgstr "cruthaigh/athshocraigh agus seiceáil amach brainse" + +#: builtin/checkout.c +msgid "create reflog for new branch" +msgstr "cruthú reflog do bhrainse nua" + +#: builtin/checkout.c +msgid "second guess 'git checkout <no-such-branch>' (default)" +msgstr "an dara tuairim 'git check <no-such-branch>'(réamhshocraithe)" + +#: builtin/checkout.c +msgid "use overlay mode (default)" +msgstr "úsáid modh forleagtha (réamhshocraithe)" + +#: builtin/checkout.c +msgid "create and switch to a new branch" +msgstr "cruthú agus aistrigh go brainse nua" + +#: builtin/checkout.c +msgid "create/reset and switch to a branch" +msgstr "cruthú/athshocraigh agus aistrigh go brainse" + +#: builtin/checkout.c +msgid "second guess 'git switch <no-such-branch>'" +msgstr "buille faoi thuairim eile 'git switch <gan-bhrainse-den-sórt-sin>'" + +#: builtin/checkout.c +msgid "throw away local modifications" +msgstr "modhnuithe áitiúla a chaitheamh" + +#: builtin/checkout.c +msgid "which tree-ish to checkout from" +msgstr "cén crainn le seiceáil uaidh" + +#: builtin/checkout.c +msgid "restore the index" +msgstr "an t-innéacs a chur ar ais" + +#: builtin/checkout.c +msgid "restore the working tree (default)" +msgstr "an crann oibre a chur ar ais (réamhshocraithe)" + +#: builtin/checkout.c +msgid "ignore unmerged entries" +msgstr "neamhaird a dhéanamh ar iontrálacha" + +#: builtin/checkout.c +msgid "use overlay mode" +msgstr "úsáid modh forleagtha" + +#: builtin/clean.c +msgid "" +"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] " +"[<pathspec>...]" +msgstr "" +"<pathspec>git glan [-d] [-f] [-i] [-n] [-q] [-e] [- <pattern>x | -X] [--] " +"[...]" + +#: builtin/clean.c +#, c-format +msgid "Removing %s\n" +msgstr "Ag baint %s\n" + +#: builtin/clean.c +#, c-format +msgid "Would remove %s\n" +msgstr "Bainfeadh %s\n" + +#: builtin/clean.c +#, c-format +msgid "Skipping repository %s\n" +msgstr "Ag scipeáil an stóras %s\n" + +#: builtin/clean.c +#, c-format +msgid "Would skip repository %s\n" +msgstr "Scaipfeadh stóras %s\n" + +#: builtin/clean.c midx.c +#, c-format +msgid "failed to remove %s" +msgstr "theip ar %s a bhaint" + +#: builtin/clean.c +#, c-format +msgid "could not lstat %s\n" +msgstr "nà fhéadfaà lstat %s\n" + +#: builtin/clean.c +msgid "Refusing to remove current working directory\n" +msgstr "Ag diúltú an t-eolaire oibre reatha a bhaint\n" + +#: builtin/clean.c +msgid "Would refuse to remove current working directory\n" +msgstr "Dhiúltódh sé/sà an t-eolaire oibre reatha a bhaint\n" + +#: builtin/clean.c +#, c-format +msgid "" +"Prompt help:\n" +"1 - select a numbered item\n" +"foo - select item based on unique prefix\n" +" - (empty) select nothing\n" +msgstr "" +"Cabhair pras:\n" +"1 - roghnaigh mÃr uimhrithe\n" +"foo - roghnaigh mÃr bunaithe ar réimÃr uathúil\n" +" - (folamh) roghnaigh aon rud\n" + +#: builtin/clean.c +#, c-format +msgid "" +"Prompt help:\n" +"1 - select a single item\n" +"3-5 - select a range of items\n" +"2-3,6-9 - select multiple ranges\n" +"foo - select item based on unique prefix\n" +"-... - unselect specified items\n" +"* - choose all items\n" +" - (empty) finish selecting\n" +msgstr "" +"Cabhair pras:\n" +"1 - roghnaigh mÃr amháin\n" +"3-5 - roghnaigh raon earraÃ\n" +"2-3,6-9 - roghnaigh raonta iolracha\n" +"foo - roghnaigh mÃr bunaithe ar réimÃr uathúil\n" +"-... - mÃreanna sonraithe a dhÃroghnú\n" +"* - roghnaigh gach earra\n" +" - (folamh) bailchrÃoch a roghnú\n" + +#: builtin/clean.c +#, c-format +msgid "Huh (%s)?\n" +msgstr "Huh (%s)?\n" + +#: builtin/clean.c +#, c-format +msgid "Input ignore patterns>> " +msgstr "Patrúin neamhaird ionchuir >> " + +#: builtin/clean.c +#, c-format +msgid "WARNING: Cannot find items matched by: %s" +msgstr "RABHADH: Nà féidir mÃreanna a mheaitseáil le: %s a aimsiú" + +#: builtin/clean.c +msgid "Select items to delete" +msgstr "Roghnaigh mÃreanna le scriosadh" + +#. TRANSLATORS: Make sure to keep [y/N] as is +#: builtin/clean.c +#, c-format +msgid "Remove %s [y/N]? " +msgstr "Bain %s [y/N]? " + +#: builtin/clean.c +msgid "" +"clean - start cleaning\n" +"filter by pattern - exclude items from deletion\n" +"select by numbers - select items to be deleted by numbers\n" +"ask each - confirm each deletion (like \"rm -i\")\n" +"quit - stop cleaning\n" +"help - this screen\n" +"? - help for prompt selection" +msgstr "" +"glan - tosú ag glanadh\n" +"scagadh de réir patrún - eisiamh mÃreanna ó scriosadh\n" +"roghnaigh de réir uimhreacha - roghnaigh mÃreanna atá le scriosadh de réir\n" +"fiafraigh gach ceann - deimhnigh gach scriosadh (cosúil le “rm -iâ€)\n" +"scor - stop glanadh\n" +"cabhair - an scáileán seo\n" +"? - cabhair le haghaidh roghnú pras" + +#: builtin/clean.c +msgid "Would remove the following item:" +msgid_plural "Would remove the following items:" +msgstr[0] "Bhainfeadh sé an mhÃr seo a leanas:" +msgstr[1] "Bainfà na mÃreanna seo a leanas:" +msgstr[2] "Bainfà na mÃreanna seo a leanas:" + +#: builtin/clean.c +msgid "No more files to clean, exiting." +msgstr "NÃl aon nÃos mó comhaid le glanadh, ag imeacht amach." + +#: builtin/clean.c +msgid "do not print names of files removed" +msgstr "ná priontáil ainmneacha na gcomhaid a bhaintear" + +#: builtin/clean.c +msgid "force" +msgstr "fórsa" + +#: builtin/clean.c +msgid "interactive cleaning" +msgstr "glanadh idirghnÃ" + +#: builtin/clean.c +msgid "remove whole directories" +msgstr "bain eolairà iomlána" + +#: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c +#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c +#: builtin/show-ref.c ref-filter.h +msgid "pattern" +msgstr "patrún" + +#: builtin/clean.c +msgid "add <pattern> to ignore rules" +msgstr "cuir leis <pattern>na rialacha a neamhaird" + +#: builtin/clean.c +msgid "remove ignored files, too" +msgstr "bain comhaid a neamhaird orthu, freisin" + +#: builtin/clean.c +msgid "remove only ignored files" +msgstr "bain ach comhaid a neamhaird orthu" + +#: builtin/clean.c +msgid "clean.requireForce is true and -f not given: refusing to clean" +msgstr "tá clean.requireForce fÃor agus nà thugtar -f: diúltú glanadh" + +#: builtin/clone.c +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "eolas: Nà féidir malartach a chur le haghaidh '%s': %s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "theip ar '%s' a stáil" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "Tá %s ann agus nà eolaire é" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "Is nasc comhsheasmhach é '%s', ag diúltú clónú le --local" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "theip ar an iterator a thosú thar '%s'" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "tá nasc symlink '%s' ann, ag diúltú clónú le --local" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "theip ar '%s' a dhÃnascadh" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "nà féidir crua-nasc a sheiceáil ag '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "crua-nasc difriúil ó fhoinse ag '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "theip ar nasc '%s' a chruthú" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "theip ar chomhad a chóipeáil chuig '%s'" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "theip ar athrá thar '%s'" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "déanta.\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"D'éirigh le clón, ach theip ar an tseiceáil.\n" +"Is féidir leat iniúchadh a dhéanamh ar an méid a sheiceáladh le 'git " +"status'\n" +"agus déan iarracht arÃs le 'git restore --source=HEAD : /'\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "nÃor sheol iargúlta gach rud riachtanach" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "nach féidir %s a nuashonrú" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "theip ar sheiceáil éagsúil a thosú" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"tagraÃonn iargúlta HEAD do thagartha nach bhfuil ann, nach féidir a sheiceáil" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "in ann crann oibre a sheiceáil" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "in ann paraiméadair a scrÃobh chuig comhad cumraithe" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "nà féidir athphacáil chun glanadh" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "nà féidir le comhad malartacha sealadacha a dhÃnascadh" + +#: builtin/clone.c +msgid "don't clone shallow repository" +msgstr "ná clóin stór éadomhain" + +#: builtin/clone.c +msgid "don't create a checkout" +msgstr "ná cruthaigh seiceáil" + +#: builtin/clone.c builtin/init-db.c +msgid "create a bare repository" +msgstr "stóras lom a chruthú" + +#: builtin/clone.c +msgid "create a mirror repository (implies --bare)" +msgstr "stóras scátháin a chruthú (tugann le tuiscint --bare)" + +#: builtin/clone.c +msgid "to clone from a local repository" +msgstr "a chlónú ó stór áitiúil" + +#: builtin/clone.c +msgid "don't use local hardlinks, always copy" +msgstr "ná húsáid crua-naisc áitiúla, cóipeáil i gcónaÃ" + +#: builtin/clone.c +msgid "setup as shared repository" +msgstr "socrú mar stór roinnte" + +#: builtin/clone.c +msgid "pathspec" +msgstr "sonraÃocht chosáin" + +#: builtin/clone.c +msgid "initialize submodules in the clone" +msgstr "fo-mhodúil a thionscnamh sa chlón" + +#: builtin/clone.c +msgid "number of submodules cloned in parallel" +msgstr "lÃon na bhfo-mhodúil atá clónaithe go comhthreomhar" + +#: builtin/clone.c builtin/init-db.c +msgid "template-directory" +msgstr "eolaire teimpléad" + +#: builtin/clone.c builtin/init-db.c +msgid "directory from which templates will be used" +msgstr "eolaire as a n-úsáidfear teimpléid" + +#: builtin/clone.c builtin/submodule--helper.c +msgid "reference repository" +msgstr "stór tagartha" + +#: builtin/clone.c builtin/submodule--helper.c +msgid "use --reference only while cloning" +msgstr "bain úsáid as --reference amháin agus tú ag clónú" + +#: builtin/clone.c builtin/column.c builtin/fmt-merge-msg.c builtin/init-db.c +#: builtin/merge-file.c builtin/merge.c builtin/pack-objects.c builtin/repack.c +#: builtin/submodule--helper.c t/helper/test-simple-ipc.c +msgid "name" +msgstr "ainm" + +#: builtin/clone.c +msgid "use <name> instead of 'origin' to track upstream" +msgstr "úsáid in <name> ionad 'origin' chun suas an sruth a rianú" + +#: builtin/clone.c +msgid "checkout <branch> instead of the remote's HEAD" +msgstr "seiceáil <brainse> in ionad CEAD an iargúlta" + +#: builtin/clone.c +msgid "clone single revision <rev> and check out" +msgstr "clónáil athbhreithniú aonair <rev> agus seiceáil amach" + +#: builtin/clone.c +msgid "path to git-upload-pack on the remote" +msgstr "cosán chuig git-upload-pack ar an gcianrialtán" + +#: builtin/clone.c builtin/fetch.c builtin/pull.c +msgid "depth" +msgstr "doimhneacht" + +#: builtin/clone.c +msgid "create a shallow clone of that depth" +msgstr "clón éadomhain den doimhneacht sin a chruthú" + +#: builtin/clone.c +msgid "create a shallow clone since a specific time" +msgstr "clón éadrom a chruthú ó am ar leith" + +#: builtin/clone.c builtin/fetch.c builtin/pull.c +msgid "ref" +msgstr "tagairt" + +#: builtin/clone.c builtin/fetch.c builtin/pull.c +msgid "deepen history of shallow clone, excluding ref" +msgstr "stair an chlóin éadomhain a dhoimhniú, gan tagairt" + +#: builtin/clone.c builtin/submodule--helper.c +msgid "clone only one branch, HEAD or --branch" +msgstr "clóin ach brainse amháin, HEAD nó --branch" + +#: builtin/clone.c +msgid "clone tags, and make later fetches not to follow them" +msgstr "clibeanna clóin, agus tógáil nÃos déanaà a dhéanamh gan iad a leanúint" + +#: builtin/clone.c +msgid "any cloned submodules will be shallow" +msgstr "beidh aon fho-mhodúil clónaithe éadrom" + +#: builtin/clone.c builtin/init-db.c +msgid "gitdir" +msgstr "gitdir" + +#: builtin/clone.c builtin/init-db.c +msgid "separate git dir from working tree" +msgstr "git dir ar leithligh ó chrann oibre" + +#: builtin/clone.c builtin/init-db.c builtin/submodule--helper.c +msgid "specify the reference format to use" +msgstr "sonraigh an fhormáid tagartha le húsáid" + +#: builtin/clone.c +msgid "key=value" +msgstr "eochair=luach" + +#: builtin/clone.c +msgid "set config inside the new repository" +msgstr "socraigh cumraÃocht taobh istigh den stór nua" + +#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c +#: builtin/push.c builtin/send-pack.c +msgid "server-specific" +msgstr "freastalaÃ-shonrach" + +#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c +#: builtin/push.c builtin/send-pack.c +msgid "option to transmit" +msgstr "rogha a tharchur" + +#: builtin/clone.c +msgid "apply partial clone filters to submodules" +msgstr "cuir scagairà clóin páirteacha i bhfeidhm" + +#: builtin/clone.c +msgid "any cloned submodules will use their remote-tracking branch" +msgstr "úsáidfidh aon fho-mhodúil clónaithe a mbrainse cianrianaithe" + +#: builtin/clone.c +msgid "initialize sparse-checkout file to include only files at root" +msgstr "" +"comhad seiceála neamhchoitianta a thosú chun comhaid amháin a áireamh ag " +"fréamh" + +#: builtin/clone.c +msgid "uri" +msgstr "uri" + +#: builtin/clone.c +msgid "a URI for downloading bundles before fetching from origin remote" +msgstr "" +"a URI chun cuachtaà a Ãoslódáil sula n-iarrtar iad ó chianchéim tionscnaimh" + +#: builtin/clone.c +msgid "git clone [<options>] [--] <repo> [<dir>]" +msgstr "git clone [<roghanna>] [--] <stóras>[<eolaire>]" + +#: builtin/clone.c +msgid "Too many arguments." +msgstr "An iomarca argóintÃ." + +#: builtin/clone.c scalar.c +msgid "You must specify a repository to clone." +msgstr "Nà mór duit stór a shonrú le clónú." + +#: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c +#: setup.c +#, c-format +msgid "unknown ref storage format '%s'" +msgstr "formáid stórála tagartha anaithnid '%s'" + +#: builtin/clone.c +#, c-format +msgid "repository '%s' does not exist" +msgstr "nÃl an stóras '%s' ann" + +#: builtin/clone.c builtin/fetch.c +#, c-format +msgid "depth %s is not a positive number" +msgstr "nà uimhir dhearfach é doimhneacht %s" + +#: builtin/clone.c +#, c-format +msgid "destination path '%s' already exists and is not an empty directory." +msgstr "tá cosán ceann scrÃbe '%s' ann cheana féin agus nà eolaire folamh é." + +#: builtin/clone.c +#, c-format +msgid "repository path '%s' already exists and is not an empty directory." +msgstr "tá cosán stórais '%s' ann cheana féin agus nà eolaire folamh é." + +#: builtin/clone.c +#, c-format +msgid "working tree '%s' already exists." +msgstr "tá crann oibre '%s' ann cheana féin." + +#: builtin/clone.c builtin/difftool.c builtin/log.c builtin/worktree.c +#, c-format +msgid "could not create leading directories of '%s'" +msgstr "nà fhéadfaà eolairà tosaigh de '%s' a chruthú" + +#: builtin/clone.c +#, c-format +msgid "could not create work tree dir '%s'" +msgstr "nà fhéadfaà crann oibre a chruthú dir '%s'" + +#: builtin/clone.c +#, c-format +msgid "Cloning into bare repository '%s'...\n" +msgstr "Clónáil isteach i stóras lom '%s'...\n" + +#: builtin/clone.c +#, c-format +msgid "Cloning into '%s'...\n" +msgstr "Clónáil isteach '%s'...\n" + +#: builtin/clone.c +msgid "" +"clone --recursive is not compatible with both --reference and --reference-if-" +"able" +msgstr "" +"nÃl clón --recursive comhoiriúnach le --reference agus --reference-if-able" + +#: builtin/clone.c builtin/remote.c +#, c-format +msgid "'%s' is not a valid remote name" +msgstr "Nà ainm iargúlta bailà é '%s'" + +#: builtin/clone.c +msgid "--depth is ignored in local clones; use file:// instead." +msgstr "" +"--depth déantar neamhaird de i gclóin áitiúla; bain úsáid as comhad:// ina " +"ionad." + +#: builtin/clone.c +msgid "--shallow-since is ignored in local clones; use file:// instead." +msgstr "" +"--shallow-since déantar neamhaird de i gclóin áitiúla; bain úsáid as file:// " +"ina ionad." + +#: builtin/clone.c +msgid "--shallow-exclude is ignored in local clones; use file:// instead." +msgstr "" +"--shallow-exclude déantar neamhaird de i gclóin áitiúla; bain úsáid as " +"file:// ina ionad." + +#: builtin/clone.c +msgid "--filter is ignored in local clones; use file:// instead." +msgstr "" +"--filter déantar neamhaird de i gclóin áitiúla; bain úsáid as file:// ina " +"ionad." + +#: builtin/clone.c fetch-pack.c +msgid "source repository is shallow, reject to clone." +msgstr "tá stóras foinse éadrom, diúltaigh clóin." + +#: builtin/clone.c +msgid "source repository is shallow, ignoring --local" +msgstr "tá stóras foinse éadrom, ag neamhaird a dhéanamh ar --local" + +#: builtin/clone.c +msgid "--local is ignored" +msgstr "--local déantar neamhaird de" + +#: builtin/clone.c +msgid "cannot clone from filtered bundle" +msgstr "nà féidir clónú ó bhearta scagtha" + +#: builtin/clone.c +msgid "failed to initialize the repo, skipping bundle URI" +msgstr "theip ar an repo a thionscnamh, ag scipeáil URI beartán" + +#: builtin/clone.c +#, c-format +msgid "failed to fetch objects from bundle URI '%s'" +msgstr "theip ar rudaà a fháil ó URI '%s'" + +#: builtin/clone.c +msgid "failed to fetch advertised bundles" +msgstr "theip orthu beartáin fógraithe a fháil" + +#: builtin/clone.c +msgid "remote transport reported error" +msgstr "earráid tuairiscithe ar iompar" + +#: builtin/clone.c +#, c-format +msgid "Remote branch %s not found in upstream %s" +msgstr "NÃor aimsÃodh brainse iargúlta %s i suas sruth %s" + +#: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Nà aimsÃodh athbhreithniú iargúlta %s i suas sruth %s" + +#: builtin/clone.c +msgid "You appear to have cloned an empty repository." +msgstr "Is cosúil gur chlónaigh tú stór folamh." + +#: builtin/column.c +msgid "git column [<options>]" +msgstr "colún git [<options>]" + +#: builtin/column.c +msgid "lookup config vars" +msgstr "earraà cumraÃochta cuardaigh" + +#: builtin/column.c +msgid "layout to use" +msgstr "leagan amach le húsáid" + +#: builtin/column.c +msgid "maximum width" +msgstr "leithead uasta" + +#: builtin/column.c +msgid "padding space on left border" +msgstr "spás padding ar an teorainn chlé" + +#: builtin/column.c +msgid "padding space on right border" +msgstr "spás padding ar an teorainn dheis" + +#: builtin/column.c +msgid "padding space between columns" +msgstr "spás padding idir colúin" + +#: builtin/column.c +#, c-format +msgid "%s must be non-negative" +msgstr "Caithfidh %s a bheith neamh-diúltach" + +#: builtin/column.c +msgid "--command must be the first argument" +msgstr "Nà mór gurb é --command an chéad argóint" + +#: builtin/commit-graph.c +msgid "" +"git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]" +msgstr "" +"git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]" + +#: builtin/commit-graph.c +msgid "" +"git commit-graph write [--object-dir <dir>] [--append]\n" +" [--split[=<strategy>]] [--reachable | --stdin-packs | " +"--stdin-commits]\n" +" [--changed-paths] [--[no-]max-new-filters <n>] [--" +"[no-]progress]\n" +" <split-options>" +msgstr "" +"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>" + +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c +msgid "dir" +msgstr "redir" + +#: builtin/commit-graph.c +msgid "the object directory to store the graph" +msgstr "an eolaire réada chun an graf a stóráil" + +#: builtin/commit-graph.c +msgid "if the commit-graph is split, only verify the tip file" +msgstr "má tá an graf coimite scoilte, nà fhÃoraigh ach an comhad leid" + +#: builtin/commit-graph.c +#, c-format +msgid "Could not open commit-graph '%s'" +msgstr "NÃor féidir graf coimisiúnaithe '%s' a oscailt" + +#: builtin/commit-graph.c +#, c-format +msgid "could not open commit-graph chain '%s'" +msgstr "nà fhéadfaà slabhra coimisi-graf '%s' a oscailt" + +#: builtin/commit-graph.c +#, c-format +msgid "unrecognized --split argument, %s" +msgstr "argóint --split gan aithint, %s" + +#: builtin/commit-graph.c +#, c-format +msgid "unexpected non-hex object ID: %s" +msgstr "id réada neamh-heicsidheachúlach gan choinne: %s" + +#: builtin/commit-graph.c +#, c-format +msgid "invalid object: %s" +msgstr "réad neamhbhailÃ: %s" + +#: builtin/commit-graph.c parse-options-cb.c +#, c-format +msgid "option `%s' expects a numerical value" +msgstr "tá rogha `%s' ag súil le luach uimhriúil" + +#: builtin/commit-graph.c +msgid "start walk at all refs" +msgstr "tosú ag siúl ag gach ceann" + +#: builtin/commit-graph.c +msgid "scan pack-indexes listed by stdin for commits" +msgstr "" +"scanadh innéacsanna pacáiste atá liostaithe ag stdin le haghaidh gealltanais" + +#: builtin/commit-graph.c +msgid "start walk at commits listed by stdin" +msgstr "tosú ag siúl ag gealltanais atá liostaithe ag stdin" + +#: builtin/commit-graph.c +msgid "include all commits already in the commit-graph file" +msgstr "" +"áireamh na gealltanais go léir cheana féin sa chomhad gráf coimisiúnaithe" + +#: builtin/commit-graph.c +msgid "enable computation for changed paths" +msgstr "rÃomh a chumasú le haghaidh cosáin athraithe" + +#: builtin/commit-graph.c +msgid "allow writing an incremental commit-graph file" +msgstr "ligean comhad gráf choimisiúnaithe a scrÃobh" + +#: builtin/commit-graph.c +msgid "maximum number of commits in a non-base split commit-graph" +msgstr "uaslÃon na ngealltanais i ngráf coiste scoilte neamh-bhonn" + +#: builtin/commit-graph.c +msgid "maximum ratio between two levels of a split commit-graph" +msgstr "cóimheas uasta idir dhá leibhéal de ghraf coimiste scoilte" + +#: builtin/commit-graph.c +msgid "only expire files older than a given date-time" +msgstr "nà rachaidh in éag ach comhaid nÃos sine ná dáta-am ar leith" + +#: builtin/commit-graph.c +msgid "maximum number of changed-path Bloom filters to compute" +msgstr "lÃon uasta scagairà Bloom cosáin athraithe le rÃomh" + +#: builtin/commit-graph.c +msgid "use at most one of --reachable, --stdin-commits, or --stdin-packs" +msgstr "" +"bain úsáid as ceann de --reachable, --stdin-commits, nó --stdin-packs ar a " +"mhéad" + +#: builtin/commit-graph.c +msgid "Collecting commits from input" +msgstr "Gealltanais a bhailiú ó ionchur" + +#: builtin/commit-tree.c +msgid "git commit-tree <tree> [(-p <parent>)...]" +msgstr "<parent>git commit-tree <tree>[(-p)...]" + +#: builtin/commit-tree.c +msgid "" +"git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n" +" [(-F <file>)...] <tree>" +msgstr "" +"<parent>git commit-tree [(-p)...] [-S [<keyid>]] [(-m<message>)...]\n" +" [(-F<file>)...] <tree>" + +#: builtin/commit-tree.c +#, c-format +msgid "duplicate parent %s ignored" +msgstr "neamhaird déanta ar thuismitheoir dúblach %s" + +#: builtin/commit-tree.c builtin/log.c +#, c-format +msgid "not a valid object name %s" +msgstr "nà ainm réad bailà %s" + +#: builtin/commit-tree.c +#, c-format +msgid "git commit-tree: failed to read '%s'" +msgstr "git commit-tree: theip ar '%s' a léamh" + +#: builtin/commit-tree.c +#, c-format +msgid "git commit-tree: failed to close '%s'" +msgstr "git commit-tree: theip ar '%s' a dhúnadh" + +#: builtin/commit-tree.c +msgid "parent" +msgstr "tuismitheoir" + +#: builtin/commit-tree.c +msgid "id of a parent commit object" +msgstr "id réad tiomanta tuismitheora" + +#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/notes.c +#: builtin/stash.c builtin/tag.c +msgid "message" +msgstr "teachtaireacht" + +#: builtin/commit-tree.c builtin/commit.c +msgid "commit message" +msgstr "teachtaireacht a thabhairt" + +#: builtin/commit-tree.c +msgid "read commit log message from file" +msgstr "léigh teachtaireacht logála tiomanta ón gcomhad" + +#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/pull.c +#: builtin/revert.c +msgid "GPG sign commit" +msgstr "Tiomantas comhartha GPG" + +#: builtin/commit-tree.c +msgid "must give exactly one tree" +msgstr "caithfidh crann amháin a thabhairt go dÃreach" + +#: builtin/commit-tree.c +msgid "git commit-tree: failed to read" +msgstr "git commit-tree: theip ar léamh" + +#: builtin/commit.c +msgid "" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" +" [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" +"reword):]<commit>]\n" +" [-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[<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>...]" + +#: builtin/commit.c +msgid "git status [<options>] [--] [<pathspec>...]" +msgstr "stádas git [<options>] [--] [<pathspec>...]" + +#: builtin/commit.c +msgid "" +"You asked to amend the most recent commit, but doing so would make\n" +"it empty. You can repeat your command with --allow-empty, or you can\n" +"remove the commit entirely with \"git reset HEAD^\".\n" +msgstr "" +"D'iarr tú an gealltanas is déanaà a leasú, ach déanfaà amhlaidh a dhéanamh\n" +"folamh é. Is féidir leat d'ordú a athdhéanamh le --allow-empty, nó is féidir " +"leat\n" +"bain an tiomantas go hiomlán le “git reset HEAD^â€.\n" + +#: builtin/commit.c +msgid "" +"The previous cherry-pick is now empty, possibly due to conflict resolution.\n" +"If you wish to commit it anyway, use:\n" +"\n" +" git commit --allow-empty\n" +"\n" +msgstr "" +"Tá an pioc silÃnà roimhe seo folamh anois, b'fhéidir mar gheall ar réiteach " +"coinbhleachta.\n" +"Más mian leat é a dhéanamh ar aon nós, bain úsáid as:\n" +"\n" +" git commit --allow-empty\n" +"\n" + +#: builtin/commit.c +msgid "Otherwise, please use 'git rebase --skip'\n" +msgstr "Seachas sin, bain úsáid as 'git rebase --skip'\n" + +#: builtin/commit.c +msgid "Otherwise, please use 'git cherry-pick --skip'\n" +msgstr "Seachas sin, bain úsáid as 'git cherry-pick --skip'\n" + +#: builtin/commit.c +msgid "" +"and then use:\n" +"\n" +" git cherry-pick --continue\n" +"\n" +"to resume cherry-picking the remaining commits.\n" +"If you wish to skip this commit, use:\n" +"\n" +" git cherry-pick --skip\n" +"\n" +msgstr "" +"agus ansin bain úsáid as:\n" +"\n" +" git cherry-pick --continue\n" +"\n" +"chun na gealltanais atá fágtha a atosú ag piocadh silÃnÃ.\n" +"Más mian leat an tiomantas seo a scipeáil, bain úsáid as:\n" +"\n" +" git cherry-pick --skip\n" + +#: builtin/commit.c read-cache.c +msgid "updating files failed" +msgstr "theip ar nuashonrú comhaid" + +#: builtin/commit.c +msgid "failed to unpack HEAD tree object" +msgstr "theip orthu réad crann HEAD a dhÃphacáil" + +#: builtin/commit.c +msgid "No paths with --include/--only does not make sense." +msgstr "NÃl ciall ag aon chosáin le --include/--only." + +#: builtin/commit.c +msgid "unable to create temporary index" +msgstr "in ann innéacs sealadach a chruthú" + +#: builtin/commit.c +msgid "interactive add failed" +msgstr "theip ar chur idirghnÃomh" + +#: builtin/commit.c +msgid "unable to update temporary index" +msgstr "in ann innéacs sealadach a nuashonrú" + +#: builtin/commit.c +msgid "Failed to update main cache tree" +msgstr "Theip ar phrÃomhchrann taisce a nuashonrú" + +#: builtin/commit.c +msgid "cannot do a partial commit during a merge." +msgstr "nà féidir le tiomantas páirteach a dhéanamh le linn cumaisc." + +#: builtin/commit.c +msgid "cannot do a partial commit during a cherry-pick." +msgstr "nà féidir le tiomantas páirteach a dhéanamh le linn pioc silÃnÃ." + +#: builtin/commit.c +msgid "cannot do a partial commit during a rebase." +msgstr "nà féidir le tiomantas páirteach a dhéanamh le linn athbhunaithe." + +#: builtin/commit.c +msgid "cannot read the index" +msgstr "nà féidir leis an innéacs a léamh" + +#: builtin/commit.c +msgid "unable to write temporary index file" +msgstr "in ann comhad innéacs sealadach a scrÃobh" + +#: builtin/commit.c +#, c-format +msgid "commit '%s' lacks author header" +msgstr "nÃl ceannteideal údair ag comhoiriú '%s'" + +#: builtin/commit.c +#, c-format +msgid "commit '%s' has malformed author line" +msgstr "comtal tá lÃne údair mÃfhoirmithe ag '%s'" + +#: builtin/commit.c +msgid "malformed --author parameter" +msgstr "paraiméadar --author mÃfhoirmithe" + +#: builtin/commit.c ident.c +#, c-format +msgid "invalid date format: %s" +msgstr "formáid dáta neamhbhailÃ: %s" + +#: builtin/commit.c +msgid "" +"unable to select a comment character that is not used\n" +"in the current commit message" +msgstr "" +"nach féidir carachtar tráchta a roghnú nach n-úsáidtear\n" +"sa teachtaireacht tiomanta reatha" + +#: builtin/commit.c +#, c-format +msgid "could not lookup commit '%s'" +msgstr "nà fhéadfaà cuardach a dhéanamh ar '%s'" + +#: builtin/commit.c builtin/shortlog.c +#, c-format +msgid "(reading log message from standard input)\n" +msgstr "(teachtaireacht log a léamh ó ionchur caighdeánach)\n" + +#: builtin/commit.c +msgid "could not read log from standard input" +msgstr "nà raibh in ann log a léamh ó ionchur caighdeánach" + +#: builtin/commit.c +#, c-format +msgid "could not read log file '%s'" +msgstr "nà raibh in ann comhad logála '%s' a léamh" + +#: builtin/commit.c +#, c-format +msgid "options '%s' and '%s:%s' cannot be used together" +msgstr "nà féidir roghanna '%s' agus '%s: %s' a úsáid le chéile" + +#: builtin/commit.c +msgid "could not read SQUASH_MSG" +msgstr "nà raibh in ann SQUASH_MSG a léamh" + +#: builtin/commit.c +msgid "could not read MERGE_MSG" +msgstr "nà raibh in ann MERGE_MSG a léamh" + +#: builtin/commit.c bundle.c rerere.c sequencer.c +#, c-format +msgid "could not open '%s'" +msgstr "nà fhéadfaà '%s' a oscailt" + +#: builtin/commit.c +msgid "could not write commit template" +msgstr "nà raibh sé in ann teimpléad tiomanta a" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be ignored.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. LÃnte ag " +"tosú\n" +"déanfar neamhaird le '%s'.\n" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be ignored, and an empty message aborts the commit.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. LÃnte ag " +"tosú\n" +"déanfar neamhaird le '%s', agus déanfar teachtaireacht folamh deireadh leis " +"an tiomantas.\n" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be kept; you may remove them yourself if you want to.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. LÃnte ag " +"tosú\n" +"coimeádfar le '%s'; féadfaidh tú iad a bhaint féin más mian leat.\n" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be kept; you may remove them yourself if you want to.\n" +"An empty message aborts the commit.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. LÃnte ag " +"tosú\n" +"coimeádfar le '%s'; féadfaidh tú iad a bhaint féin más mian leat.\n" +"Déanann teachtaireacht folamh deireadh leis an tiomantas.\n" + +#: builtin/commit.c +msgid "" +"\n" +"It looks like you may be committing a merge.\n" +"If this is not correct, please run\n" +"\tgit update-ref -d MERGE_HEAD\n" +"and try again.\n" +msgstr "" +"\n" +"Is cosúil go bhfuil tú ag déanamh cumasc.\n" +"Mura bhfuil sé seo ceart, rith\n" +"git update-ref -d MERGE_HEAD\n" +"agus déan iarracht arÃs.\n" + +#: builtin/commit.c +msgid "" +"\n" +"It looks like you may be committing a cherry-pick.\n" +"If this is not correct, please run\n" +"\tgit update-ref -d CHERRY_PICK_HEAD\n" +"and try again.\n" +msgstr "" +"\n" +"Is cosúil go bhfuil tú ag déanamh rogha neamhghnách.\n" +"Mura bhfuil sé seo ceart, rith\n" +"\tgit update-ref -d CHERRY_PICK_HEAD\n" +"agus déan iarracht arÃs.\n" + +#: builtin/commit.c +#, c-format +msgid "%sAuthor: %.*s <%.*s>" +msgstr "%sÚdar: %.*s <%.*s>" + +#: builtin/commit.c +#, c-format +msgid "%sDate: %s" +msgstr "%sDáta: %s" + +#: builtin/commit.c +#, c-format +msgid "%sCommitter: %.*s <%.*s>" +msgstr "%sCeannasaÃ: %.*s <%.*s>" + +#: builtin/commit.c +msgid "Cannot read index" +msgstr "Nà féidir innéacs a léamh" + +#: builtin/commit.c builtin/tag.c +msgid "unable to pass trailers to --trailers" +msgstr "nach féidir leantóirà a chur chuig --trailers" + +#: builtin/commit.c +msgid "Error building trees" +msgstr "Earráid ag tógáil crainn" + +#: builtin/commit.c builtin/tag.c +#, c-format +msgid "Please supply the message using either -m or -F option.\n" +msgstr "" +"Soláthair an teachtaireacht le do thoil ag baint úsáide as rogha -m nó -F.\n" + +#: builtin/commit.c +#, c-format +msgid "--author '%s' is not 'Name <email>' and matches no existing author" +msgstr "" +"Nà 'Ainm' é --author '%s' agus nà mheaitseálann <email>aon údar atá ann " +"cheana" + +#: builtin/commit.c +#, c-format +msgid "Invalid ignored mode '%s'" +msgstr "Modh neamhbhailà neamhaird '%s'" + +#: builtin/commit.c +#, c-format +msgid "Invalid untracked files mode '%s'" +msgstr "Modh comhaid neamhrianaithe neamhbhailà '%s'" + +#: builtin/commit.c +msgid "You are in the middle of a merge -- cannot reword." +msgstr "Tá tú i lár cumaisc - nà féidir athfhocal a athfhocal." + +#: builtin/commit.c +msgid "You are in the middle of a cherry-pick -- cannot reword." +msgstr "Tá tú i lár pioc silÃnà - nà féidir athfhocal a athfhocal." + +#: builtin/commit.c +#, c-format +msgid "reword option of '%s' and path '%s' cannot be used together" +msgstr "nà féidir rogha athfhocal de '%s' agus cosán '%s' a úsáid le chéile" + +#: builtin/commit.c +#, c-format +msgid "reword option of '%s' and '%s' cannot be used together" +msgstr "nà féidir rogha athfhocal de '%s' agus '%s' a úsáid le chéile" + +#: builtin/commit.c +msgid "You have nothing to amend." +msgstr "NÃl aon rud le leasú agat." + +#: builtin/commit.c +msgid "You are in the middle of a merge -- cannot amend." +msgstr "Tá tú i lár cumaisc - nà féidir leat leasú." + +#: builtin/commit.c +msgid "You are in the middle of a cherry-pick -- cannot amend." +msgstr "Tá tú i lár rogha silÃnà - nà féidir leat leasú." + +#: builtin/commit.c +msgid "You are in the middle of a rebase -- cannot amend." +msgstr "Tá tú i lár athbhunaithe - nà féidir leat leasú." + +#: builtin/commit.c +msgid "--reset-author can be used only with -C, -c or --amend." +msgstr "Nà féidir --reset-author a úsáid ach le -C, -c nó --amend." + +#: builtin/commit.c +#, c-format +msgid "unknown option: --fixup=%s:%s" +msgstr "rogha anaithnid: --fixup=%s:%s" + +#: builtin/commit.c +#, c-format +msgid "paths '%s ...' with -a does not make sense" +msgstr "nà chiallaÃonn cosáin '%s... 'le -a" + +#: builtin/commit.c +msgid "show status concisely" +msgstr "taispeáin stádas go hachomair" + +#: builtin/commit.c +msgid "show branch information" +msgstr "taispeáin faisnéis bhrainse" + +#: builtin/commit.c +msgid "show stash information" +msgstr "taispeáin faisnéis stash" + +#: builtin/commit.c +msgid "compute full ahead/behind values" +msgstr "luachanna iomlána/taobh thiar de na luachanna a rÃomh" + +#: builtin/commit.c +msgid "version" +msgstr "leagan" + +#: builtin/commit.c builtin/fetch.c builtin/push.c builtin/worktree.c +msgid "machine-readable output" +msgstr "aschur inléite meaisÃn" + +#: builtin/commit.c +msgid "show status in long format (default)" +msgstr "stádas taispeáint i bhformáid fhada (réamhshocraithe)" + +#: builtin/commit.c +msgid "terminate entries with NUL" +msgstr "foirceannadh na hiontrálacha" + +#: builtin/commit.c +msgid "show untracked files, optional modes: all, normal, no. (Default: all)" +msgstr "" +"taispeáin comhaid neamhrianaithe, modhanna roghnacha: gach, gnáth, nÃl. " +"(Réamhshocraithe: gach)" + +#: builtin/commit.c +msgid "" +"show ignored files, optional modes: traditional, matching, no. (Default: " +"traditional)" +msgstr "" +"taispeáint comhaid neamhaird orthu, modhanna roghnacha: traidisiúnta, " +"meaitseáil, (Réamhshocraithe: traidisiúnta)" + +#: builtin/commit.c parse-options.h +msgid "when" +msgstr "nuair a" + +#: builtin/commit.c +msgid "" +"ignore changes to submodules, optional when: all, dirty, untracked. " +"(Default: all)" +msgstr "" +"neamhaird a dhéanamh ar athruithe ar fho-mhodúil, roghnach nuair a bhÃonn: " +"gach, salach, gan rianú. (Réamhshocraithe: gach)" + +#: builtin/commit.c +msgid "list untracked files in columns" +msgstr "liostáil comhaid neamhrianaithe i gcolúin" + +#: builtin/commit.c +msgid "do not detect renames" +msgstr "ná athainmneacha a bhrath" + +#: builtin/commit.c +msgid "detect renames, optionally set similarity index" +msgstr "athainmneacha a bhrath, innéacs cosúlachta a shocrú go ro" + +#: builtin/commit.c +msgid "Unsupported combination of ignored and untracked-files arguments" +msgstr "Teaglaim gan tacaÃocht d'argóintà comhaid a neamhaird agus gan rianú" + +#: builtin/commit.c +msgid "suppress summary after successful commit" +msgstr "achoimre a chur faoi chois tar éis tiomantas" + +#: builtin/commit.c +msgid "show diff in commit message template" +msgstr "taispeáin diff i teimpléad teachtaireachta tiomanta" + +#: builtin/commit.c +msgid "Commit message options" +msgstr "Tiomanta roghanna teachtaire" + +#: builtin/commit.c builtin/merge.c builtin/tag.c +msgid "read message from file" +msgstr "léigh teachtaireacht ón gcomhad" + +#: builtin/commit.c +msgid "author" +msgstr "údar" + +#: builtin/commit.c +msgid "override author for commit" +msgstr "an t-údar a shárú le haghaidh tiomantas" + +#: builtin/commit.c builtin/gc.c +msgid "date" +msgstr "dáta" + +#: builtin/commit.c +msgid "override date for commit" +msgstr "dáta athsháraithe le haghaidh tiomanta" + +#: builtin/commit.c parse-options.h ref-filter.h +msgid "commit" +msgstr "tiomantas" + +#: builtin/commit.c +msgid "reuse and edit message from specified commit" +msgstr "teachtaireacht a athúsáid agus a chur in eagar ó thiomantas" + +#: builtin/commit.c +msgid "reuse message from specified commit" +msgstr "teachtaireacht athúsáid ó thiomantas sonraithe" + +#. TRANSLATORS: Leave "[(amend|reword):]" as-is, +#. and only translate <commit>. +#. +#: builtin/commit.c +msgid "[(amend|reword):]commit" +msgstr "[(leaso|athfhocal):] comhartha" + +#: builtin/commit.c +msgid "" +"use autosquash formatted message to fixup or amend/reword specified commit" +msgstr "" +"úsáid teachtaireacht fhormáidithe autosquash chun gealltanas sonraithe a " +"shocrú nó a leasú/athfhocal" + +#: builtin/commit.c +msgid "use autosquash formatted message to squash specified commit" +msgstr "" +"úsáid teachtaireacht fhormáidithe autosquash chun tiomantas sonraithe squash" + +#: builtin/commit.c +msgid "the commit is authored by me now (used with -C/-c/--amend)" +msgstr "tá an gealltanas údar agam anois (úsáidtear le -C/-c/--amend)" + +#: builtin/commit.c builtin/interpret-trailers.c builtin/tag.c +msgid "trailer" +msgstr "leantóir" + +#: builtin/commit.c builtin/tag.c +msgid "add custom trailer(s)" +msgstr "cuir leantóir (Ã) saincheaptha" + +#: builtin/commit.c builtin/log.c builtin/merge.c builtin/pull.c +#: builtin/revert.c +msgid "add a Signed-off-by trailer" +msgstr "cuir leantóir sÃnithe as" + +#: builtin/commit.c +msgid "use specified template file" +msgstr "úsáid comhad teimpléad sonraithe" + +#: builtin/commit.c +msgid "force edit of commit" +msgstr "eagarthóireacht fórsa ar thiomantas" + +#: builtin/commit.c +msgid "include status in commit message template" +msgstr "áireamh stádas i dteimpléad teachtaireachta" + +#: builtin/commit.c +msgid "Commit contents options" +msgstr "Tiomnaigh roghanna ábhair" + +#: builtin/commit.c +msgid "commit all changed files" +msgstr "gach comhad athraithe a thiomnú" + +#: builtin/commit.c +msgid "add specified files to index for commit" +msgstr "cuir comhaid sonraithe leis an innéacs le haghaidh tiomanta" + +#: builtin/commit.c +msgid "interactively add files" +msgstr "cuir comhaid idirghnÃomhach" + +#: builtin/commit.c +msgid "interactively add changes" +msgstr "cuir athruithe idirghnÃomhach" + +#: builtin/commit.c +msgid "commit only specified files" +msgstr "ach comhaid shonraithe a dhéanamh" + +#: builtin/commit.c +msgid "bypass pre-commit and commit-msg hooks" +msgstr "seachbhóthar crúcaà réamh-thiomanta agus comh-msg" + +#: builtin/commit.c +msgid "show what would be committed" +msgstr "taispeáint cad a bheadh tiomanta" + +#: builtin/commit.c +msgid "amend previous commit" +msgstr "leasú a leasú" + +#: builtin/commit.c +msgid "bypass post-rewrite hook" +msgstr "seachbhóthar crúca iar-athsc" + +#: builtin/commit.c +msgid "ok to record an empty change" +msgstr "ceart go leor chun athrú folamh a thaifeadadh" + +#: builtin/commit.c +msgid "ok to record a change with an empty message" +msgstr "ceart go leor chun athrú a thaifeadadh le teachtaireacht folamh" + +#: builtin/commit.c sequencer.c +msgid "could not parse HEAD commit" +msgstr "nà fhéadfadh sé gealltanas HEAD a pharsáil" + +#: builtin/commit.c +#, c-format +msgid "Corrupt MERGE_HEAD file (%s)" +msgstr "Comhad truaillithe MERGE_HEAD (%s)" + +#: builtin/commit.c +msgid "could not read MERGE_MODE" +msgstr "nà raibh in ann MERGE_MODE a léamh" + +#: builtin/commit.c +#, c-format +msgid "could not read commit message: %s" +msgstr "nà féidir teachtaireacht tiomanta a léamh: %s" + +#: builtin/commit.c +#, c-format +msgid "Aborting commit due to empty commit message.\n" +msgstr "Tiomantas a ghabháil mar gheall ar theachtaireacht tiomanta folamh\n" + +#: builtin/commit.c +#, c-format +msgid "Aborting commit; you did not edit the message.\n" +msgstr "Tiomantas a ghearradh; nÃor chuir tú an teachtaireacht in eagar.\n" + +#: builtin/commit.c +#, c-format +msgid "Aborting commit due to empty commit message body.\n" +msgstr "" +"Tiomantas a ghabháil mar gheall ar chorp teachtaireachta tiomanta folamh.\n" + +#: builtin/commit.c +msgid "" +"repository has been updated, but unable to write\n" +"new index file. Check that disk is not full and quota is\n" +"not exceeded, and then \"git restore --staged :/\" to recover." +msgstr "" +"nuashonraÃodh an stór, ach nà féidir scrÃobh\n" +"comhad innéacs nua. Seiceáil nach bhfuil an diosca \n" +"lán agus nach bhfuil an cuóta sáraithe, agus ansin \"git restore --staged :/" +"\" chun é a aisghabháil." + +#: builtin/config.c +msgid "git config list [<file-option>] [<display-option>] [--includes]" +msgstr "liosta config git [<file-option>] [<display-option>] [--include]" + +#: builtin/config.c +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>" +msgstr "" +"<value><default>git config a fháil [<file-option>] [] [--include<display-" +"option>] [--all] [--regexp] [--value=] [--luach seasta] [--default=] <name>" + +#: builtin/config.c +msgid "" +"git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--" +"fixed-value] <name> <value>" +msgstr "" +"<value>git config set [<file-option>] [--type =] [--all] [--value=<type>] [--" +"luach seasta] <name><value>" + +#: builtin/config.c +msgid "" +"git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] " +"<name>" +msgstr "" +"<value>git config gan socrú [] [--gach<file-option>] [--value=] [--luach " +"seasta] <name>" + +#: builtin/config.c +msgid "git config rename-section [<file-option>] <old-name> <new-name>" +msgstr "<file-option>roinn athainmnithe git config [] <old-name><new-name>" + +#: builtin/config.c +msgid "git config remove-section [<file-option>] <name>" +msgstr "<file-option>roinn aistrithe git config [] <name>" + +#: builtin/config.c +msgid "git config edit [<file-option>]" +msgstr "<file-option>Eagarthóireacht config git []" + +#: builtin/config.c +msgid "git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]" +msgstr "<name><stdout-is-tty>git config [<file-option>] --get-colorbool []" + +#: builtin/config.c +msgid "" +"git config get [<file-option>] [<display-option>] [--includes] [--all] [--" +"regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] " +"<name>" +msgstr "" +"<value><default>git config a fháil [<file-option>] [] [--include<display-" +"option>] [--all] [--regexp=] [-- <regexp>value=] [--luach seasta] [--" +"default=] <name>" + +#: builtin/config.c +msgid "" +"git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] " +"[--value=<value>] [--fixed-value] <name> <value>" +msgstr "" +"<value>git config set [<file-option>] [--type =] [--comment =<type>] [--all] " +"[--value=<message>] [--luach seasta] <name><value>" + +#: builtin/config.c +msgid "Config file location" +msgstr "SuÃomh comhad Config" + +#: builtin/config.c +msgid "use global config file" +msgstr "bain úsáid as comhad cumraÃochta domhanda" + +#: builtin/config.c +msgid "use system config file" +msgstr "bain úsáid as comhad cumraÃochta córais" + +#: builtin/config.c +msgid "use repository config file" +msgstr "bain úsáid as comhad cumraÃochta stórais" + +#: builtin/config.c +msgid "use per-worktree config file" +msgstr "bain úsáid as comhad cumraÃochta in aghaidh an chrann oibre" + +#: builtin/config.c builtin/gc.c +msgid "use given config file" +msgstr "bain úsáid as comhad cumraÃochta tugtha" + +#: builtin/config.c +msgid "blob-id" +msgstr "blob-id" + +#: builtin/config.c +msgid "read config from given blob object" +msgstr "léigh cumraÃocht ó réad blob a thugtar" + +#: builtin/config.c +msgid "Type" +msgstr "Cineál" + +#: builtin/config.c builtin/hash-object.c +msgid "type" +msgstr "cineál" + +#: builtin/config.c +msgid "value is given this type" +msgstr "tugtar luach an cineál seo" + +#: builtin/config.c +msgid "value is \"true\" or \"false\"" +msgstr "tá luach “fÃor†nó “bréagachâ€" + +#: builtin/config.c +msgid "value is decimal number" +msgstr "is é luach uimhir deachúil" + +#: builtin/config.c +msgid "value is --bool or --int" +msgstr "is é luach --bool nó --int" + +#: builtin/config.c +msgid "value is --bool or string" +msgstr "is é luach --bool nó teaghrán" + +#: builtin/config.c +msgid "value is a path (file or directory name)" +msgstr "is cosán é luach (ainm comhad nó eolaire)" + +#: builtin/config.c +msgid "value is an expiry date" +msgstr "is dáta éaga é luach" + +#: builtin/config.c +msgid "Display options" +msgstr "Roghanna taispeána" + +#: builtin/config.c +msgid "terminate values with NUL byte" +msgstr "foirceannadh luachanna le nóta NUL" + +#: builtin/config.c +msgid "show variable names only" +msgstr "taispeáin ainmneacha athróg amháin" + +#: builtin/config.c +msgid "show origin of config (file, standard input, blob, command line)" +msgstr "" +"taispeáint bunús an chumraÃochta (comhad, ionchur caighdeánach, blob, lÃne " +"ordaithe)" + +#: builtin/config.c +msgid "show scope of config (worktree, local, global, system, command)" +msgstr "" +"taispeáin raon feidhme an chumraÃochta (crann oibre, áitiúil, domhanda, " +"córas, ordú)" + +#: builtin/config.c +msgid "show config keys in addition to their values" +msgstr "taispeáin eochracha cumraithe i dteannta lena luachanna" + +#: builtin/config.c +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "argóint --type gan aithint, %s" + +#: builtin/config.c +msgid "only one type at a time" +msgstr "ach cineál amháin ag an am" + +#: builtin/config.c +#, c-format +msgid "wrong number of arguments, should be %d" +msgstr "lÃon mÃcheart na n-argóintÃ, ba chóir go mbeadh %d" + +#: builtin/config.c +#, c-format +msgid "wrong number of arguments, should be from %d to %d" +msgstr "ba chóir go mbeadh lÃon mÃcheart na n-argóintà ó %d go %d" + +#: builtin/config.c +#, c-format +msgid "invalid key pattern: %s" +msgstr "patrún eochair neamhbhailÃ: %s" + +#: builtin/config.c config.c +#, c-format +msgid "invalid pattern: %s" +msgstr "patrún neamhbhailÃ: %s" + +#: builtin/config.c +#, c-format +msgid "failed to format default config value: %s" +msgstr "theip ar luach cumraÃochta réamhshocraithe a fhormáidiú: %s" + +#: builtin/config.c +#, c-format +msgid "cannot parse color '%s'" +msgstr "nà féidir dath '%s' a pháirseáil" + +#: builtin/config.c +msgid "unable to parse default color value" +msgstr "in ann luach dath réamhshocraithe a pharsáil" + +#: builtin/config.c +msgid "not in a git directory" +msgstr "nach bhfuil i eolaire git" + +#: builtin/config.c +msgid "writing to stdin is not supported" +msgstr "nà thacaÃtear le scrÃobh chuig stdin" + +#: builtin/config.c +msgid "writing config blobs is not supported" +msgstr "nà thacaÃtear le blobs cumraÃochta a scrÃobh" + +#: builtin/config.c +#, c-format +msgid "" +"# This is Git's per-user configuration file.\n" +"[user]\n" +"# Please adapt and uncomment the following lines:\n" +"#\tname = %s\n" +"#\temail = %s\n" +msgstr "" +"# Seo comhad cumraÃochta Git in aghaidh an úsáideora.\n" +"[úsáideoir]\n" +"# Oiriúnaigh agus bain trácht de na lÃnte seo a leanas le do thoil:\n" +"#\tainm = %s\n" +"#\trÃomhphost = %s\n" + +#: builtin/config.c +msgid "only one config file at a time" +msgstr "ach comhad cumraithe amháin ag an am" + +#: builtin/config.c +msgid "--local can only be used inside a git repository" +msgstr "Nà féidir --local a úsáid ach taobh istigh de stór git" + +#: builtin/config.c +msgid "--blob can only be used inside a git repository" +msgstr "Nà féidir --blob a úsáid ach taobh istigh de stór git" + +#: builtin/config.c +msgid "--worktree can only be used inside a git repository" +msgstr "Nà féidir --worktree a úsáid ach taobh istigh de stór git" + +#: builtin/config.c builtin/gc.c +msgid "$HOME not set" +msgstr "NÃl $HOME socraithe" + +#: builtin/config.c +msgid "" +"--worktree cannot be used with multiple working trees unless the config\n" +"extension worktreeConfig is enabled. Please read \"CONFIGURATION FILE\"\n" +"section in \"git help worktree\" for details" +msgstr "" +"Nà féidir --worktree a úsáid le crainn oibre iolracha mura bhfuil an " +"cumraÃocht\n" +"Tá sÃneadh WorkTreeConfig cumasaithe. Léigh “COMHAD CUMRAÃOCHTAâ€\n" +"roinn i “git help worktree†le haghaidh sonraÃ" + +#: builtin/config.c +msgid "Other" +msgstr "Eile" + +#: builtin/config.c +msgid "respect include directives on lookup" +msgstr "meas lena n-áirÃtear treoracha maidir le cuardach" + +#: builtin/config.c +#, c-format +msgid "unable to read config file '%s'" +msgstr "nach féidir an comhad cumraithe '%s' a léamh" + +#: builtin/config.c +msgid "error processing config file(s)" +msgstr "comhad (Ã) cumraÃochta próiseála earráide" + +#: builtin/config.c +msgid "Filter options" +msgstr "Roghanna scagaire" + +#: builtin/config.c +msgid "return all values for multi-valued config options" +msgstr "" +"gach luach a thabhairt ar ais le haghaidh roghanna cumraithe illuachmhara" + +#: builtin/config.c +msgid "interpret the name as a regular expression" +msgstr "léirmhÃniú an t-ainm mar abairt rialta" + +#: builtin/config.c +msgid "show config with values matching the pattern" +msgstr "taispeáin cumraÃocht le luachanna a mheaitseann an phatrún" + +#: builtin/config.c +msgid "use string equality when comparing values to value pattern" +msgstr "bain úsáid as comhionannas sreangán agus luachanna á gcomparáid" + +#: builtin/config.c +msgid "URL" +msgstr "URL" + +#: builtin/config.c +msgid "show config matching the given URL" +msgstr "taispeáin configà a mheaitseáil leis an URL tugtha" + +#: builtin/config.c +msgid "value" +msgstr "luach" + +#: builtin/config.c +msgid "use default value when missing entry" +msgstr "bain úsáid as luach réamhshocraithe agus iontráil" + +#: builtin/config.c +msgid "--fixed-value only applies with 'value-pattern'" +msgstr "Nà bhaineann --fixed-value ach le 'patrún luacha'" + +#: builtin/config.c +msgid "--default= cannot be used with --all or --url=" +msgstr "Nà féidir --default= a úsáid le --all nó --url =" + +#: builtin/config.c +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "Nà féidir --url = a úsáid le --all, --regexp nó --value" + +#: builtin/config.c +msgid "Filter" +msgstr "Scagaire" + +#: builtin/config.c +msgid "replace multi-valued config option with new value" +msgstr "luach nua a chur in ionad rogha cumraÃochta illuachmhara" + +#: builtin/config.c +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"teaghrán tráchtaireachta inléite don duine (déanfar # a ullmhú de réir mar " +"is gá)" + +#: builtin/config.c +msgid "add a new line without altering any existing values" +msgstr "lÃne nua a chur leis gan aon luachanna atá ann cheana a athrú" + +#: builtin/config.c +msgid "--fixed-value only applies with --value=<pattern>" +msgstr "nà bhaineann --fixed-value ach le --value=<pattern>" + +#: builtin/config.c +msgid "--append cannot be used with --value=<pattern>" +msgstr "Nà féidir --append a úsáid le --value=<pattern>" + +#: builtin/config.c +#, c-format +msgid "" +"cannot overwrite multiple values with a single value\n" +" Use a regexp, --add or --replace-all to change %s." +msgstr "" +"nà féidir luachanna iolracha a fhorscrÃobh le luach amháin\n" +" Úsáid regexp, --add nó --replace-all chun %s a athrú." + +#: builtin/config.c +#, c-format +msgid "no such section: %s" +msgstr "gan aon chuid den sórt sin: %s" + +#: builtin/config.c +msgid "editing stdin is not supported" +msgstr "nà thacaÃtear le stdin eagarthóireachta" + +#: builtin/config.c +msgid "editing blobs is not supported" +msgstr "nà thacaÃtear le blobs eagarthóireachta" + +#: builtin/config.c +#, c-format +msgid "cannot create configuration file %s" +msgstr "nà féidir comhad cumraÃochta %s a chruthú" + +#: builtin/config.c +msgid "Action" +msgstr "GnÃomhaÃocht" + +#: builtin/config.c +msgid "get value: name [<value-pattern>]" +msgstr "luach a fháil: ainm [<value-pattern>]" + +#: builtin/config.c +msgid "get all values: key [<value-pattern>]" +msgstr "faigh na luachanna go léir: eochair [<value-pattern>]" + +#: builtin/config.c +msgid "get values for regexp: name-regex [<value-pattern>]" +msgstr "<value-pattern>luachanna a fháil do regexp: ainm-regex []" + +#: builtin/config.c +msgid "get value specific for the URL: section[.var] URL" +msgstr "faigh luach sonrach don URL: rannán [.var] URL" + +#: builtin/config.c +msgid "replace all matching variables: name value [<value-pattern>]" +msgstr "athróg meaitseála go léir in ionad: luach ainm [<value-pattern>]" + +#: builtin/config.c +msgid "add a new variable: name value" +msgstr "cuir athróg nua leis: luach ainm" + +#: builtin/config.c +msgid "remove a variable: name [<value-pattern>]" +msgstr "bhaint athróg: ainm [<value-pattern>]" + +#: builtin/config.c +msgid "remove all matches: name [<value-pattern>]" +msgstr "bhaint gach cluiche: ainm [<value-pattern>]" + +#: builtin/config.c +msgid "rename section: old-name new-name" +msgstr "athainmnigh an chuid: sean-ainm nua-ainm" + +#: builtin/config.c +msgid "remove a section: name" +msgstr "cuid a bhaint: ainm" + +#: builtin/config.c +msgid "list all" +msgstr "liostáil go léir" + +#: builtin/config.c +msgid "open an editor" +msgstr "eagarthóir a oscailt" + +#: builtin/config.c +msgid "find the color configured: slot [<default>]" +msgstr "faigh an dath cumraithe: sliotán [<default>]" + +#: builtin/config.c +msgid "find the color setting: slot [<stdout-is-tty>]" +msgstr "faigh an socrú dath: sliotán [<stdout-is-tty>]" + +#: builtin/config.c +msgid "with --get, use default value when missing entry" +msgstr "le --get, bain úsáid as luach réamhshocraithe agus iontráil in easnamh" + +#: builtin/config.c +msgid "--get-color and variable type are incoherent" +msgstr "Tá --get-color agus cineál athraitheach neamhchomhtháite" + +#: builtin/config.c +msgid "no action specified" +msgstr "aon ghnÃomh sonraithe" + +#: builtin/config.c +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "NÃl --name-only infheidhme ach le --list nó --get-regexp" + +#: builtin/config.c +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"NÃl --show-origin infheidhme ach le --get, --get-all, --get-regexp, agus --" +"list" + +#: builtin/config.c +msgid "--default is only applicable to --get" +msgstr "NÃl --default infheidhme ach le --get" + +#: builtin/config.c +msgid "--comment is only applicable to add/set/replace operations" +msgstr "" +"NÃl --comment infheidhme ach le hoibrÃochtaà a chur leis /socraÃ/athsholáthar" + +#: builtin/count-objects.c +msgid "print sizes in human readable format" +msgstr "méideanna priontála i bhformáid inléite don duine" + +#: builtin/credential-cache--daemon.c +#, c-format +msgid "" +"The permissions on your socket directory are too loose; other\n" +"users may be able to read your cached credentials. Consider running:\n" +"\n" +"\tchmod 0700 %s" +msgstr "" +"Tá na ceadanna ar d'eolaire soicéad ró-scaoilte; eile\n" +"b'fhéidir go mbeidh úsáideoirà in ann do dhintiúir taiscéadaithe a léamh. " +"Smaoinigh ar rith:\n" +"\n" +" chmod 0700 %s" + +#: builtin/credential-cache--daemon.c +msgid "print debugging messages to stderr" +msgstr "teachtaireachtaà dÃfhabhtaithe a phriontáil chuig stderr" + +#: builtin/credential-cache--daemon.c +msgid "credential-cache--daemon unavailable; no unix socket support" +msgstr "credential-cache--daemon ar fáil; gan aon tacaÃocht soicéad unix" + +#: builtin/credential-cache.c +msgid "credential-cache unavailable; no unix socket support" +msgstr "taisce creidiúnaithe ar fáil; gan aon tacaÃocht soicéad unix" + +#: builtin/credential-store.c +#, c-format +msgid "unable to get credential storage lock in %d ms" +msgstr "in ann glas stórála creidiúnaithe a fháil in %d ms" + +#: builtin/describe.c +msgid "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]" +msgstr "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]" + +#: builtin/describe.c +msgid "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]" +msgstr "" +"git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]" + +#: builtin/describe.c +msgid "git describe <blob>" +msgstr "git cur sÃos <blob>" + +#: builtin/describe.c +msgid "head" +msgstr "ceann" + +#: builtin/describe.c +msgid "lightweight" +msgstr "éadrom" + +#: builtin/describe.c +msgid "annotated" +msgstr "anótáilte" + +#: builtin/describe.c +#, c-format +msgid "annotated tag %s not available" +msgstr "nÃl clib anótáilte %s ar fáil" + +#: builtin/describe.c +#, c-format +msgid "tag '%s' is externally known as '%s'" +msgstr "tugtar '%s' ar an gclib '%s' go seachtrach" + +#: builtin/describe.c +#, c-format +msgid "no tag exactly matches '%s'" +msgstr "nÃl aon chlib ag teacht go dÃreach le '%s'" + +#: builtin/describe.c +#, c-format +msgid "No exact match on refs or tags, searching to describe\n" +msgstr "" +"NÃl aon mheaitseáil cruinn ar thaifeanna nó clibeanna, ag cuardach chun cur " +"sÃos\n" + +#: builtin/describe.c +#, c-format +msgid "finished search at %s\n" +msgstr "cuardach crÃochnaithe ag %s\n" + +#: builtin/describe.c +#, c-format +msgid "" +"No annotated tags can describe '%s'.\n" +"However, there were unannotated tags: try --tags." +msgstr "" +"Nà féidir le haon chlibeanna anótaithe cur sÃos a dhéanamh ar '%s'.\n" +"Mar sin féin, bhà clibeanna gan anótáil ann: triail as --tags." + +#: builtin/describe.c +#, c-format +msgid "" +"No tags can describe '%s'.\n" +"Try --always, or create some tags." +msgstr "" +"Nà féidir le clibeanna cur sÃos a dhéanamh ar '%s'.\n" +"Bain triail as --always, nó cruthaigh roinnt clibeanna." + +#: builtin/describe.c +#, c-format +msgid "traversed %lu commits\n" +msgstr "gealltanais %lu a thrasnaÃodh\n" + +#: builtin/describe.c +#, c-format +msgid "found %i tags; gave up search at %s\n" +msgstr "fuarthas %i clibeanna; thréig an cuardach ag %s\n" + +#: builtin/describe.c +#, c-format +msgid "describe %s\n" +msgstr "déan cur sÃos ar %s\n" + +#: builtin/describe.c +#, c-format +msgid "Not a valid object name %s" +msgstr "Nà ainm réad bailà %s" + +#: builtin/describe.c +#, c-format +msgid "%s is neither a commit nor blob" +msgstr "Nà gealltanas ná blob é %s" + +#: builtin/describe.c +msgid "find the tag that comes after the commit" +msgstr "faigh an chlib a thagann tar éis an tiomanta" + +#: builtin/describe.c +msgid "debug search strategy on stderr" +msgstr "straitéis cuardaigh dÃfhabhtú ar stderr" + +#: builtin/describe.c +msgid "use any ref" +msgstr "bain úsáid as aon tagairt" + +#: builtin/describe.c +msgid "use any tag, even unannotated" +msgstr "úsáid aon chlib, fiú gan anótáil" + +#: builtin/describe.c +msgid "always use long format" +msgstr "úsáid formáid fada i gcónaÃ" + +#: builtin/describe.c +msgid "only follow first parent" +msgstr "lean ach an chéad thuismitheoir" + +#: builtin/describe.c +msgid "only output exact matches" +msgstr "ach cluichà cruinne aschuir" + +#: builtin/describe.c +msgid "consider <n> most recent tags (default: 10)" +msgstr "machnamh <n>ar na clibeanna is déanaà (réamhshocraithe: 10)" + +#: builtin/describe.c +msgid "only consider tags matching <pattern>" +msgstr "nà mheas ach meaitseáil clibeanna <pattern>" + +#: builtin/describe.c +msgid "do not consider tags matching <pattern>" +msgstr "ná smaoinigh ar mheaitseáil clibeanna <pattern>" + +#: builtin/describe.c builtin/name-rev.c +msgid "show abbreviated commit object as fallback" +msgstr "taispeáint réad tiomanta giorraithe mar fhilleadh" + +#: builtin/describe.c +msgid "mark" +msgstr "marc" + +#: builtin/describe.c +msgid "append <mark> on dirty working tree (default: \"-dirty\")" +msgstr "cuir isteach <mark>ar chrann oibre salach (réamhshocraithe: “-salachâ€)" + +#: builtin/describe.c +msgid "append <mark> on broken working tree (default: \"-broken\")" +msgstr "cuir isteach <mark>ar chrann oibre briste (réamhshocraithe: “-brokenâ€)" + +#: builtin/describe.c +msgid "No names found, cannot describe anything." +msgstr "" +"NÃor aimsÃodh aon ainmneacha, nà féidir cur sÃos a dhéanamh ar aon rud." + +#: builtin/describe.c +#, c-format +msgid "option '%s' and commit-ishes cannot be used together" +msgstr "nà féidir rogha '%s' agus coimistà a úsáid le chéile" + +#: builtin/diagnose.c +msgid "" +"git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n" +" [--mode=<mode>]" +msgstr "" +"<format>git diagnosis [(-o | --output-directory)] [(-s | -- <path>suffix)]\n" +" <mode>[--mód =]" + +#: builtin/diagnose.c +msgid "specify a destination for the diagnostics archive" +msgstr "sonraigh ceann scrÃbe don chartlann diagnóisic" + +#: builtin/diagnose.c +msgid "specify a strftime format suffix for the filename" +msgstr "sonraigh iarmhÃr formáid strftime don ainm comhaid" + +#: builtin/diagnose.c +msgid "specify the content of the diagnostic archive" +msgstr "sonraigh ábhar an chartlann dhiagnóiseach" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse mode: %s" +msgstr "nach féidir modh a pháirseáil: %s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse object id: %s" +msgstr "nach féidir id réad a pháirseáil: %s" + +#: builtin/diff-pairs.c +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<diff-options>]" + +#: builtin/diff-pairs.c builtin/log.c builtin/replay.c builtin/shortlog.c +#: bundle.c +#, c-format +msgid "unrecognized argument: %s" +msgstr "argóint gan aithint: %s" + +#: builtin/diff-pairs.c +msgid "working without -z is not supported" +msgstr "nà thacaÃtear le bheith ag obair gan -z" + +#: builtin/diff-pairs.c +msgid "pathspec arguments not supported" +msgstr "argóintà pathspec nach dtacaÃtear leis" + +#: builtin/diff-pairs.c +msgid "revision arguments not allowed" +msgstr "argóintà athbhreithnithe nach" + +#: builtin/diff-pairs.c +msgid "invalid raw diff input" +msgstr "ionchur diff amh neamhbhailÃ" + +#: builtin/diff-pairs.c +msgid "tree objects not supported" +msgstr "rudaà crann nach dtacaÃtear leis" + +#: builtin/diff-pairs.c +msgid "got EOF while reading path" +msgstr "fuair EOF agus tú ag léamh cosán" + +#: builtin/diff-pairs.c +msgid "got EOF while reading destination path" +msgstr "fuair EOF agus tú ag léamh cosán ceann scrÃbe" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "nach féidir scór athainmniú/cóipeáil a pháirseáil: %s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unknown diff status: %c" +msgstr "stádas diff anaithnid: %c" + +#: builtin/diff-tree.c +msgid "--merge-base only works with two commits" +msgstr "Nà oibrÃonn --merge-base ach le dhá thiomantas" + +#: builtin/diff.c +#, c-format +msgid "'%s': not a regular file or symlink" +msgstr "'%s': nà comhad rialta nó comhnasc" + +#: builtin/diff.c +msgid "no merge given, only parents." +msgstr "nà thugtar aon chumasc, tuismitheoirà amháin." + +#: builtin/diff.c +#, c-format +msgid "invalid option: %s" +msgstr "rogha neamhbhailÃ: %s" + +#: builtin/diff.c +#, c-format +msgid "%s...%s: no merge base" +msgstr "%s... %s: gan aon bhonn cumaisc" + +#: builtin/diff.c +msgid "Not a git repository" +msgstr "Nà stór git" + +#: builtin/diff.c builtin/grep.c +#, c-format +msgid "invalid object '%s' given." +msgstr "réad neamhbhailà '%s' tugtha." + +#: builtin/diff.c +#, c-format +msgid "more than two blobs given: '%s'" +msgstr "nÃos mó ná dhá bhlob a thugtar: '%s'" + +#: builtin/diff.c +#, c-format +msgid "unhandled object '%s' given." +msgstr "réad neamh-láimhseáilte '%s' tugtha." + +#: builtin/diff.c +#, c-format +msgid "%s...%s: multiple merge bases, using %s" +msgstr "%s... %s: bonn cumaisc iolracha, ag baint úsáide as %s" + +#: builtin/difftool.c +msgid "git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]" +msgstr "git difftool [[<options>]] <commit>[[<commit>]] [--] [<path>...]" + +#: builtin/difftool.c +#, c-format +msgid "could not read symlink %s" +msgstr "nà fhéadfaà nasc simtéarach %s a léamh" + +#: builtin/difftool.c +#, c-format +msgid "could not read symlink file %s" +msgstr "nà raibh in ann comhad simnasc %s a léamh" + +#: builtin/difftool.c +#, c-format +msgid "could not read object %s for symlink %s" +msgstr "nà raibh in ann réad %s a léamh le haghaidh nasc simtéarach %s" + +#: builtin/difftool.c +msgid "" +"combined diff formats ('-c' and '--cc') are not supported in\n" +"directory diff mode ('-d' and '--dir-diff')." +msgstr "" +"nà thacaÃtear le formáidà diff comhcheangailte ('-c' agus '--cc') i\n" +"modh diff eolaire ('-d' agus '--dir-diff')." + +#: builtin/difftool.c +#, c-format +msgid "both files modified: '%s' and '%s'." +msgstr "modhnaigh an dá chomhad: '%s' agus '%s'." + +#: builtin/difftool.c +msgid "working tree file has been left." +msgstr "tá comhad crann oibre fágtha." + +#: builtin/difftool.c sequencer.c +#, c-format +msgid "could not copy '%s' to '%s'" +msgstr "nà fhéadfaà '%s' a chóipeáil chuig '%s'" + +#: builtin/difftool.c +#, c-format +msgid "temporary files exist in '%s'." +msgstr "tá comhaid shealadacha ann i '%s'." + +#: builtin/difftool.c +msgid "you may want to cleanup or recover these." +msgstr "b'fhéidir gur mhaith leat iad seo a ghlanadh nó a aisghabháil." + +#: builtin/difftool.c +#, c-format +msgid "failed: %d" +msgstr "theip ar: %d" + +#: builtin/difftool.c +msgid "use `diff.guitool` instead of `diff.tool`" +msgstr "bain úsáid as `diff.guitool` in ionad `diff.tool`" + +#: builtin/difftool.c +msgid "perform a full-directory diff" +msgstr "éagsúlacht eolaire lán-eolaire a dhéanamh" + +#: builtin/difftool.c +msgid "do not prompt before launching a diff tool" +msgstr "ná spreag sula seolann tú uirlis diff" + +#: builtin/difftool.c +msgid "use symlinks in dir-diff mode" +msgstr "bain úsáid as naisc siombailte i mód dir-diff" + +#: builtin/difftool.c +msgid "tool" +msgstr "uirlis" + +#: builtin/difftool.c +msgid "use the specified diff tool" +msgstr "bain úsáid as an uirlis diff sonraithe" + +#: builtin/difftool.c +msgid "print a list of diff tools that may be used with `--tool`" +msgstr "liosta d'uirlisà diff is féidir a úsáid le `--tool` a phriontáil" + +#: builtin/difftool.c +msgid "" +"make 'git-difftool' exit when an invoked diff tool returns a non-zero exit " +"code" +msgstr "" +"imeacht 'git-difftool' a dhéanamh nuair a fhilleann uirlis diff a ghairmtear " +"cód imeachta neamh-nialasach" + +#: builtin/difftool.c +msgid "specify a custom command for viewing diffs" +msgstr "sonraigh ordú saincheaptha chun féachaint ar dhifrÃochtaÃ" + +#: builtin/difftool.c +msgid "passed to `diff`" +msgstr "cuireadh chuig `diff`" + +#: builtin/difftool.c +msgid "difftool requires worktree or --no-index" +msgstr "éilÃonn difftool crann oibre nó --no-index" + +#: builtin/difftool.c +msgid "no <tool> given for --tool=<tool>" +msgstr "nÃl aon tu <tool> gadh le haghaidh --tool=<tool>" + +#: builtin/difftool.c +msgid "no <cmd> given for --extcmd=<cmd>" +msgstr "nÃl <cmd> tugtha do --extcmd=<cmd>" + +#: builtin/fast-export.c +msgid "git fast-export [<rev-list-opts>]" +msgstr "git fast-export [<rev-list-opts>]" + +#: builtin/fast-export.c +msgid "Error: Cannot export nested tags unless --mark-tags is specified." +msgstr "" +"Earráid: Nà féidir clibeanna neadaithe a onnmhairiú mura sonraÃtear --mark-" +"tags." + +#: builtin/fast-export.c +msgid "--anonymize-map token cannot be empty" +msgstr "Nà féidir le comhartha --anonymize-map a bheith folamh" + +#: builtin/fast-export.c +msgid "show progress after <n> objects" +msgstr "dhul chun cinn a thaispe <n>áint" + +#: builtin/fast-export.c +msgid "select handling of signed tags" +msgstr "roghnaigh láimhseáil na clibeanna" + +#: builtin/fast-export.c +msgid "select handling of signed commits" +msgstr "roghnaigh láimhseáil tiomantas sÃnithe" + +#: builtin/fast-export.c +msgid "select handling of tags that tag filtered objects" +msgstr "roghnaigh láimhseáil clibeanna a ligeann rudaÃ" + +#: builtin/fast-export.c +msgid "select handling of commit messages in an alternate encoding" +msgstr "roghnaigh láimhseáil teachtaireachtaà tiomanta i ionchódú" + +#: builtin/fast-export.c +msgid "dump marks to this file" +msgstr "marcanna dumpáil chuig an gcomhad seo" + +#: builtin/fast-export.c +msgid "import marks from this file" +msgstr "marcanna iompórtáil ón gcomhad seo" + +#: builtin/fast-export.c +msgid "import marks from this file if it exists" +msgstr "marcanna a iompórtáil ón gcomhad seo má tá sé ann" + +#: builtin/fast-export.c +msgid "fake a tagger when tags lack one" +msgstr "clibeoir bréige nuair nach bhfuil ceann ag clibeanna" + +#: builtin/fast-export.c +msgid "output full tree for each commit" +msgstr "aschur crann iomlán do gach tiomantas" + +#: builtin/fast-export.c +msgid "use the done feature to terminate the stream" +msgstr "úsáid an ghné déanta chun an sruth a fhoirceannadh" + +#: builtin/fast-export.c +msgid "skip output of blob data" +msgstr "scipeáil aschur sonraà blob" + +#: builtin/fast-export.c builtin/log.c +msgid "refspec" +msgstr "refspec" + +#: builtin/fast-export.c +msgid "apply refspec to exported refs" +msgstr "refspec a chur i bhfeidhm ar thaifeanna onnmhair" + +#: builtin/fast-export.c +msgid "anonymize output" +msgstr "aschur gan ainm" + +#: builtin/fast-export.c +msgid "from:to" +msgstr "ó:go" + +#: builtin/fast-export.c +msgid "convert <from> to <to> in anonymized output" +msgstr "tiontaigh <from>go <to>in aschur gan ainm" + +#: builtin/fast-export.c +msgid "reference parents which are not in fast-export stream by object id" +msgstr "" +"tuismitheoirà tagartha nach bhfuil i sruth tapa onnmhairithe de réir id réad" + +#: builtin/fast-export.c +msgid "show original object ids of blobs/commits" +msgstr "taispeáin id réad bunaidh de bhlobanna/gealltanna" + +#: builtin/fast-export.c +msgid "label tags with mark ids" +msgstr "clibeanna lipéad le id marc" + +#: builtin/fast-import.c +#, c-format +msgid "Missing from marks for submodule '%s'" +msgstr "Ar iarraidh ó mharcanna don fho-mhodúl '%s'" + +#: builtin/fast-import.c +#, c-format +msgid "Missing to marks for submodule '%s'" +msgstr "Ar iarraidh marcanna don fho-mhodúl '%s'" + +#: builtin/fast-import.c +#, c-format +msgid "Expected 'mark' command, got %s" +msgstr "Táthar ag súil leis an ordú 'marc', fuair %s" + +#: builtin/fast-import.c +#, c-format +msgid "Expected 'to' command, got %s" +msgstr "Táthar ag súil leis an ordú 'to', fuair %s" + +#: builtin/fast-import.c +msgid "Expected format name:filename for submodule rewrite option" +msgstr "" +"Ainm formáid a bhfuil súil leis ainm comhaid don rogha athscrÃobh fo-mhodúil" + +#: builtin/fast-import.c +#, c-format +msgid "feature '%s' forbidden in input without --allow-unsafe-features" +msgstr "feature '%s' forbidden in input without --allow-unsafe-features" + +#: builtin/fetch-pack.c +#, c-format +msgid "Lockfile created but not reported: %s" +msgstr "CruthaÃodh comhad Lockfile ach nár tuairiscigh: %s" + +#: builtin/fetch.c +msgid "git fetch [<options>] [<repository> [<refspec>...]]" +msgstr "git fetch [<options>] [<repository> [<refspec>...]]" + +#: builtin/fetch.c +msgid "git fetch [<options>] <group>" +msgstr "git fetch [<options>] <group>" + +#: builtin/fetch.c +msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]" +msgstr "git fetch --multiple [<options>] [(<repository> | <group>)...]" + +#: builtin/fetch.c +msgid "git fetch --all [<options>]" +msgstr "git fetch --all [<options>]" + +#: builtin/fetch.c +msgid "fetch.parallel cannot be negative" +msgstr "nà féidir fetch.parallel a bheith diúltach" + +#: builtin/fetch.c +msgid "couldn't find remote ref HEAD" +msgstr "nà raibh in ann ciantagartha HEAD a fháil" + +#: builtin/fetch.c +#, c-format +msgid "From %.*s\n" +msgstr "Ó %.*s\n" + +#: builtin/fetch.c +#, c-format +msgid "object %s not found" +msgstr "nÃor aimsÃodh réad %s" + +#: builtin/fetch.c +msgid "[up to date]" +msgstr "[cothrom le dáta]" + +#: builtin/fetch.c +msgid "[rejected]" +msgstr "[diúltaithe]" + +#: builtin/fetch.c +msgid "can't fetch into checked-out branch" +msgstr "nà féidir teacht isteach i mbrainse seiceáilte" + +#: builtin/fetch.c +msgid "[tag update]" +msgstr "[Nuashonrú tag]" + +#: builtin/fetch.c +msgid "unable to update local ref" +msgstr "in ann tagairt áitiúil a nuashonrú" + +#: builtin/fetch.c +msgid "would clobber existing tag" +msgstr "chuirfeadh an chlib atá ann cheana" + +#: builtin/fetch.c +msgid "[new tag]" +msgstr "[tag nua]" + +#: builtin/fetch.c +msgid "[new branch]" +msgstr "[brainse nua]" + +#: builtin/fetch.c +msgid "[new ref]" +msgstr "[tagartha nua]" + +#: builtin/fetch.c +msgid "forced update" +msgstr "nuashonrú éigeant" + +#: builtin/fetch.c +msgid "non-fast-forward" +msgstr "neamh-tapa ar aghaidh" + +#: builtin/fetch.c builtin/grep.c sequencer.c +#, c-format +msgid "cannot open '%s'" +msgstr "nà féidir '%s' a oscailt" + +#: builtin/fetch.c +msgid "" +"fetch normally indicates which branches had a forced update,\n" +"but that check has been disabled; to re-enable, use '--show-forced-updates'\n" +"flag or run 'git config fetch.showForcedUpdates true'" +msgstr "" +"is gnách go léirÃonn teacht na brainsà a raibh nuashonrú éigeantach orthu,\n" +"ach tá an seiceáil sin dÃchumasaithe; chun athchumasú, bain úsáid as '--show-" +"forced-updates'\n" +"bratach nó rith 'git config fetch.showForcedUpdates true'" + +#: builtin/fetch.c +#, c-format +msgid "" +"it took %.2f seconds to check forced updates; you can use\n" +"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates " +"false'\n" +"to avoid this check\n" +msgstr "" +"thóg sé %.2f soicind chun nuashonruithe éigeantacha a sheiceáil; is féidir " +"leat úsáid\n" +"'--no-show-forced-updates 'nó rith 'git config fetch.showForcedUpdates " +"bréaga'\n" +"chun an seiceáil seo a sheachaint\n" + +#: builtin/fetch.c +#, c-format +msgid "%s did not send all necessary objects" +msgstr "NÃor sheol %s na rudaà riachtanacha go léir" + +#: builtin/fetch.c +#, c-format +msgid "rejected %s because shallow roots are not allowed to be updated" +msgstr "dhiúltaigh %s toisc nach gceadaÃtear fréamhacha éadmhara a nuashonrú" + +#: builtin/fetch.c +#, c-format +msgid "" +"some local refs could not be updated; try running\n" +" 'git remote prune %s' to remove any old, conflicting branches" +msgstr "" +"nà fhéadfaà roinnt fios áitiúla a nuashonrú; déan iarracht rith\n" +" 'git remote prune%s' chun aon bhrainsà sean-fhrithsheasmhach a bhaint" + +#: builtin/fetch.c +#, c-format +msgid " (%s will become dangling)" +msgstr " (beidh %s ag crochadh)" + +#: builtin/fetch.c +#, c-format +msgid " (%s has become dangling)" +msgstr " (%s has become dangling)" + +#: builtin/fetch.c +msgid "[deleted]" +msgstr "[scriosta]" + +#: builtin/fetch.c builtin/remote.c +msgid "(none)" +msgstr "(nÃl aon)" + +#: builtin/fetch.c +#, c-format +msgid "refusing to fetch into branch '%s' checked out at '%s'" +msgstr "ag diúltú teacht isteach i mbrainse '%s' a sheiceáil amach ag '%s'" + +#: builtin/fetch.c +#, c-format +msgid "option \"%s\" value \"%s\" is not valid for %s" +msgstr "nÃl an rogha “%s†luach “%s†bailà do %s" + +#: builtin/fetch.c +#, c-format +msgid "option \"%s\" is ignored for %s" +msgstr "déantar neamhaird ar rogha “%s†do %s" + +#: builtin/fetch.c object-store.c +#, c-format +msgid "%s is not a valid object" +msgstr "Nà réad bailà é %s" + +#: builtin/fetch.c +#, c-format +msgid "the object %s does not exist" +msgstr "nÃl an réad %s ann" + +#: builtin/fetch.c +#, c-format +msgid "" +"Run 'git remote set-head %s %s' to follow the change, or set\n" +"'remote.%s.followRemoteHEAD' configuration option to a different value\n" +"if you do not want to see this message. Specifically running\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." +msgstr "" +"Rith 'git remote set-head %s %s' chun an t-athrú a leanúint, nó socraigh\n" +"rogha cumraÃochta 'remote.%s.followRemoteHEAD' go luach difriúil\n" +"mura mian leat an teachtaireacht seo a fheiceáil. Go sonrach, má ritheann " +"tú\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"dÃchumasófar an rabhadh go dtà go n-athraÃonn an cianda HEAD go rud éigin " +"eile." + +#: builtin/fetch.c +msgid "multiple branches detected, incompatible with --set-upstream" +msgstr "brainsà iolracha brainsà braite, gan oiriúint le --set-upstream" + +#: builtin/fetch.c +#, c-format +msgid "" +"could not set upstream of HEAD to '%s' from '%s' when it does not point to " +"any branch." +msgstr "" +"nà fhéadfaà suas sruth de HEAD a shocrú go '%s' ó '%s' nuair nach dtugann sé " +"in iúl go dtà aon bhrainse." + +#: builtin/fetch.c +msgid "not setting upstream for a remote remote-tracking branch" +msgstr "gan socrú suas sruth do bhrainse cianrianaithe" + +#: builtin/fetch.c +msgid "not setting upstream for a remote tag" +msgstr "gan a shocrú suas sruth le haghaidh clib iargúlta" + +#: builtin/fetch.c +msgid "unknown branch type" +msgstr "cineál brainse anaithnid" + +#: builtin/fetch.c +msgid "" +"no source branch found;\n" +"you need to specify exactly one branch with the --set-upstream option" +msgstr "" +"nà bhfuarthas aon bhrainse foinse;\n" +"nà mór duit brainse amháin a shonrú go dÃreach leis an rogha --set-upstream" + +#: builtin/fetch.c +#, c-format +msgid "Fetching %s\n" +msgstr "Ag tarraingt %s\n" + +#: builtin/fetch.c +#, c-format +msgid "could not fetch %s" +msgstr "nà fhéadfaà %s a fháil" + +#: builtin/fetch.c +#, c-format +msgid "could not fetch '%s' (exit code: %d)\n" +msgstr "nÃorbh fhéidir '%s' a fháil (cód scoir: %d)\n" + +#: builtin/fetch.c +msgid "" +"no remote repository specified; please specify either a URL or a\n" +"remote name from which new revisions should be fetched" +msgstr "" +"nÃl aon stór iargúlta sonraithe; sonraigh URL nó a\n" +"ainm iargúlta ar chóir athbhreithnithe nua a fháil" + +#: builtin/fetch.c +msgid "you need to specify a tag name" +msgstr "nà mór duit ainm clib a shonrú" + +#: builtin/fetch.c builtin/pull.c +msgid "fetch from all remotes" +msgstr "faigh ó gach iargúlta" + +#: builtin/fetch.c builtin/pull.c +msgid "set upstream for git pull/fetch" +msgstr "socraigh suas sruth le haghaidh git pull/fetch" + +#: builtin/fetch.c builtin/pull.c +msgid "append to .git/FETCH_HEAD instead of overwriting" +msgstr "cuir chuig .git/FETCH_HEAD in ionad athscrÃobh" + +#: builtin/fetch.c +msgid "use atomic transaction to update references" +msgstr "úsáid idirbheart adamach chun tagairtà a nuashonrú" + +#: builtin/fetch.c builtin/pull.c +msgid "path to upload pack on remote end" +msgstr "cosán chun pacáiste a uaslódáil ar iargúlta" + +#: builtin/fetch.c +msgid "force overwrite of local reference" +msgstr "tagairt áitiúil a fhorscrÃobh" + +#: builtin/fetch.c +msgid "fetch from multiple remotes" +msgstr "a fháil ó iomadúla iargúlta" + +#: builtin/fetch.c builtin/pull.c +msgid "fetch all tags and associated objects" +msgstr "gach clib agus rudaà gaolmhara a fháil" + +#: builtin/fetch.c +msgid "do not fetch all tags (--no-tags)" +msgstr "ná faigh gach clib (--no-tags)" + +#: builtin/fetch.c +msgid "number of submodules fetched in parallel" +msgstr "lÃon na bhfo-mhodúil a fuarthas go comhthreomhar" + +#: builtin/fetch.c +msgid "modify the refspec to place all refs within refs/prefetch/" +msgstr "an refspec a mhodhnú chun gach refs a chur laistigh de refs/prefetch/" + +#: builtin/fetch.c builtin/pull.c +msgid "prune remote-tracking branches no longer on remote" +msgstr "brainsà cianrianaithe a ghearradh nach bhfuil ar iargúlta a" + +#: builtin/fetch.c +msgid "prune local tags no longer on remote and clobber changed tags" +msgstr "" +"clibeanna áitiúla a ghearradh nach bhfuil ar chlibeanna iargúlta agus " +"athraithe clobber" + +#: builtin/fetch.c builtin/pull.c +msgid "on-demand" +msgstr "ar éileamh" + +#: builtin/fetch.c +msgid "control recursive fetching of submodules" +msgstr "tógáil athfhillteach fo-mhodúil a rialú" + +#: builtin/fetch.c +msgid "write fetched references to the FETCH_HEAD file" +msgstr "scrÃobh tagairtà faighte don chomhad FETCH_HEAD" + +#: builtin/fetch.c builtin/pull.c +msgid "keep downloaded pack" +msgstr "pacáiste Ãoslódáilte" + +#: builtin/fetch.c +msgid "allow updating of HEAD ref" +msgstr "cead a thabhairt do nuashonrú HEAD ref" + +#: builtin/fetch.c builtin/pull.c +msgid "deepen history of shallow clone" +msgstr "stair clón éadomhain a dhoimhniú" + +#: builtin/fetch.c builtin/pull.c +msgid "deepen history of shallow repository based on time" +msgstr "stair stór éadomhain a dhoimhniú bunaithe ar am" + +#: builtin/fetch.c builtin/pull.c +msgid "convert to a complete repository" +msgstr "tiontaigh go stór iomlán" + +#: builtin/fetch.c +msgid "re-fetch without negotiating common commits" +msgstr "athghabháil gan gealltanais choiteanna a chaibidliú" + +#: builtin/fetch.c +msgid "prepend this to submodule path output" +msgstr "é seo a chur ar aghaidh chuig aschur cosán fo-mhodúil" + +#: builtin/fetch.c +msgid "" +"default for recursive fetching of submodules (lower priority than config " +"files)" +msgstr "" +"réamhshocraithe maidir le fo-mhodúil a fháil athshlánach (tosaÃocht nÃos " +"Ãsle ná comhaid chumraithe)" + +#: builtin/fetch.c builtin/pull.c +msgid "accept refs that update .git/shallow" +msgstr "glacadh le hiarrachtaà a nuashonraÃonn .git/shalach" + +#: builtin/fetch.c builtin/pull.c +msgid "refmap" +msgstr "athléarscáil" + +#: builtin/fetch.c builtin/pull.c +msgid "specify fetch refmap" +msgstr "sonraigh refmap a fháil" + +#: builtin/fetch.c builtin/pull.c builtin/rebase.c builtin/replay.c +msgid "revision" +msgstr "athbhreithiú" + +#: builtin/fetch.c builtin/pull.c +msgid "report that we have only objects reachable from this object" +msgstr "tuairisciú nach bhfuil ach rudaà inrochtana againn ón réad seo" + +#: builtin/fetch.c +msgid "do not fetch a packfile; instead, print ancestors of negotiation tips" +msgstr "" +"ná faigh comhad pacáiste; ina ionad sin, priontáil sinsear leideanna " +"idirbheartaÃochta" + +#: builtin/fetch.c +msgid "run 'maintenance --auto' after fetching" +msgstr "reáchtáil 'cothabháil --auto' tar éis a fháil" + +#: builtin/fetch.c builtin/pull.c +msgid "check for forced-updates on all updated branches" +msgstr "seiceáil ar nuashonruithe éigeantacha ar gach brainse nuashonraithe" + +#: builtin/fetch.c +msgid "write the commit-graph after fetching" +msgstr "scrÃobh an graf coimisiúnaithe tar éis a fháil" + +#: builtin/fetch.c +msgid "accept refspecs from stdin" +msgstr "glacadh le refspecs ó stdin" + +#: builtin/fetch.c +msgid "--negotiate-only needs one or more --negotiation-tip=*" +msgstr "" +"--negotiate-only teastaÃonn ceann amháin nó nÃos mó --negotiation-tip=*" + +#: builtin/fetch.c +msgid "negative depth in --deepen is not supported" +msgstr "nà thacaÃtear le doimhneacht dhiúltach i --deepen" + +#: builtin/fetch.c +msgid "--unshallow on a complete repository does not make sense" +msgstr "nÃl ciall le --unshallow ar stórlann iomlán" + +#: builtin/fetch.c +#, c-format +msgid "failed to fetch bundles from '%s'" +msgstr "theip ar bhaclaà a fháil ó '%s'" + +#: builtin/fetch.c +msgid "fetch --all does not take a repository argument" +msgstr "nà ghlacann fetch --all argóint stór" + +#: builtin/fetch.c +msgid "fetch --all does not make sense with refspecs" +msgstr "nà bhÃonn ciall ag teacht --all le refspecs" + +#: builtin/fetch.c +#, c-format +msgid "no such remote or remote group: %s" +msgstr "gan aon ghrúpa iargúlta nó cianda den sórt sin: %s" + +#: builtin/fetch.c +msgid "fetching a group and specifying refspecs does not make sense" +msgstr "nÃl ciall grúpa a fháil agus refspecs a shonrú" + +#: builtin/fetch.c +msgid "must supply remote when using --negotiate-only" +msgstr "nà mór iargúlta a sholáthar agus tú ag úsáid --negotiate-only" + +#: builtin/fetch.c +msgid "protocol does not support --negotiate-only, exiting" +msgstr "nà thacaÃonn an prótacal le --negotiate-only, ag scoir" + +#: builtin/fetch.c +msgid "" +"--filter can only be used with the remote configured in " +"extensions.partialclone" +msgstr "" +"--filter Nà féidir ach an scagaire a úsáid ach leis an iargúlta cumraithe in " +"extensions.partialclone" + +#: builtin/fetch.c +msgid "--atomic can only be used when fetching from one remote" +msgstr "" +"--atomic nà féidir ach adamhach a úsáid ach amháin nuair a bhÃonn sé á fháil " +"ó chianrialtán amháin" + +#: builtin/fetch.c +msgid "--stdin can only be used when fetching from one remote" +msgstr "" +"Nà féidir --stdin a úsáid ach amháin nuair a bhfaightear é ó iargúlta amháin" + +#: builtin/fmt-merge-msg.c +msgid "" +"git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]" +msgstr "" +"<n><file>git fmt-merge-msg [-m<message>] [--log [=] | --no-log] [--comhad]" + +#: builtin/fmt-merge-msg.c +msgid "populate log with at most <n> entries from shortlog" +msgstr "logáil a chomhlánú le hiontrálacha is mó <n>ó ghearrlog" + +#: builtin/fmt-merge-msg.c +msgid "alias for --log (deprecated)" +msgstr "alias le haghaidh --log (mÃsheasmhach)" + +#: builtin/fmt-merge-msg.c +msgid "text" +msgstr "téacs" + +#: builtin/fmt-merge-msg.c +msgid "use <text> as start of message" +msgstr "úsáid <text> mar thús na teachtaireachta" + +#: builtin/fmt-merge-msg.c +msgid "use <name> instead of the real target branch" +msgstr "úsáid in <name> ionad na fÃor-spriocbhrainse" + +#: builtin/fmt-merge-msg.c +msgid "file to read from" +msgstr "comhad le léamh ó" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [<options>] [<pattern>]" +msgstr "git for-each-ref [<options>] [<pattern>]" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [--points-at <object>]" +msgstr "git for-each-ref [--points-at <object>]" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]" +msgstr "git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]" +msgstr "git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for shells" +msgstr "sealbhóirà áiteanna a luachan go oiriúnach do" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for perl" +msgstr "sealbhóirà áiteanna a luachan go oiriúnach do perl" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for python" +msgstr "sealbhóirà áiteanna a luaigh go oiriúnach do python" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for Tcl" +msgstr "sealbhóirà áiteanna a luachan go oiriúnach do Tcl" + +#: builtin/for-each-ref.c +msgid "show only <n> matched refs" +msgstr "taispeáin ach sonraà com <n>hoiriúnaithe" + +#: builtin/for-each-ref.c builtin/tag.c +msgid "respect format colors" +msgstr "meas dathanna formáid" + +#: builtin/for-each-ref.c +msgid "print only refs which points at the given object" +msgstr "nà phriontáil ach téacsanna a phointÃonn ar an réad a thugtar" + +#: builtin/for-each-ref.c +msgid "print only refs that are merged" +msgstr "nà phriontáil ach scrÃbhneoireachtaà atá cumasaithe" + +#: builtin/for-each-ref.c +msgid "print only refs that are not merged" +msgstr "priontáil ach scrÃbhinnà nach bhfuil cumasc" + +#: builtin/for-each-ref.c +msgid "print only refs which contain the commit" +msgstr "nà phriontáil ach téifeanna ina bhfuil an tiomantas" + +#: builtin/for-each-ref.c +msgid "print only refs which don't contain the commit" +msgstr "nà phriontáil ach scrÃbhneoirà nach bhfuil an tiomantas" + +#: builtin/for-each-ref.c +msgid "read reference patterns from stdin" +msgstr "léigh patrúin tagartha ó stdin" + +#: builtin/for-each-ref.c +msgid "also include HEAD ref and pseudorefs" +msgstr "san áireamh freisin HEAD ref agus pseudorefs" + +#: builtin/for-each-ref.c +msgid "unknown arguments supplied with --stdin" +msgstr "argóintà anaithnid a sholáthraÃtear le --stdin" + +#: builtin/for-each-repo.c +msgid "git for-each-repo --config=<config> [--] <arguments>" +msgstr "git for-each-repo --config=<config> [--] <arguments>" + +#: builtin/for-each-repo.c +msgid "config" +msgstr "cumraÃocht" + +#: builtin/for-each-repo.c +msgid "config key storing a list of repository paths" +msgstr "eochair chumraithe a stóráil liosta de chosáin stórais" + +#: builtin/for-each-repo.c +msgid "keep going even if command fails in a repository" +msgstr "coinnigh ort fiú má theipeann an t-ordú i stóras" + +#: builtin/for-each-repo.c +msgid "missing --config=<config>" +msgstr "ar iarraidh --config=<config>" + +#: builtin/for-each-repo.c +#, c-format +msgid "got bad config --config=%s" +msgstr "fuair go dona cumraÃocht --config=%s" + +#: builtin/fsck.c +msgid "unknown" +msgstr "anaithnid" + +#. TRANSLATORS: e.g. error in tree 01bfda: <more explanation> +#: builtin/fsck.c +#, c-format +msgid "error in %s %s: %s" +msgstr "earráid i %s %s: %s" + +#. TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> +#: builtin/fsck.c +#, c-format +msgid "warning in %s %s: %s" +msgstr "rabhadh i %s %s: %s" + +#: builtin/fsck.c +#, c-format +msgid "broken link from %7s %s" +msgstr "nasc briste ó %7s %s" + +#: builtin/fsck.c +msgid "wrong object type in link" +msgstr "cineál réad mÃcheart i nasc" + +#: builtin/fsck.c +#, c-format +msgid "" +"broken link from %7s %s\n" +" to %7s %s" +msgstr "" +"nasc briste ó %7s %s\n" +" chuig %7s %s" + +#: builtin/fsck.c builtin/prune.c connected.c +msgid "Checking connectivity" +msgstr "Nascacht a sheiceáil" + +#: builtin/fsck.c +#, c-format +msgid "missing %s %s" +msgstr "%s %s ar iarraidh" + +#: builtin/fsck.c +#, c-format +msgid "unreachable %s %s" +msgstr "%s %s neamh-inrochtana" + +#: builtin/fsck.c +#, c-format +msgid "dangling %s %s" +msgstr "ag crochadh %s %s" + +#: builtin/fsck.c +msgid "could not create lost-found" +msgstr "nà fhéadfaà a chruthú a aimsÃodh caillte" + +#: builtin/fsck.c builtin/gc.c builtin/rebase.c rebase-interactive.c rerere.c +#: sequencer.c +#, c-format +msgid "could not write '%s'" +msgstr "nà fhéadfaà '%s' a scrÃobh" + +#: builtin/fsck.c +#, c-format +msgid "could not finish '%s'" +msgstr "nà raibh '%s' in ann a chrÃochnú" + +#: builtin/fsck.c +#, c-format +msgid "Checking %s" +msgstr "Seiceáil %s" + +#: builtin/fsck.c +#, c-format +msgid "Checking connectivity (%d objects)" +msgstr "Ag seiceáil nascachta (%d réad)" + +#: builtin/fsck.c +#, c-format +msgid "Checking %s %s" +msgstr "Seiceáil %s %s" + +#: builtin/fsck.c +msgid "broken links" +msgstr "naisc briste" + +#: builtin/fsck.c +#, c-format +msgid "root %s" +msgstr "fréamh %s" + +#: builtin/fsck.c +#, c-format +msgid "tagged %s %s (%s) in %s" +msgstr "clib %s %s (%s) i %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: object corrupt or missing" +msgstr "%s: réad truaillithe nó ar iarraidh" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid reflog entry %s" +msgstr "%s: iontráil reflog neamhbhailà %s" + +#: builtin/fsck.c +#, c-format +msgid "Checking reflog %s->%s" +msgstr "Seiceáil reflog %s->%s" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid sha1 pointer %s" +msgstr "%s: pointeoir sha1 neamhbhailà %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: not a commit" +msgstr "%s: nà gealltanas" + +#: builtin/fsck.c +msgid "notice: No default references" +msgstr "fógra: Gan aon tagairtà réamhshocraithe" + +#: builtin/fsck.c +#, c-format +msgid "%s: hash-path mismatch, found at: %s" +msgstr "%s: mÃchomhoiriúnú hash-path, le fáil ag: %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: object corrupt or missing: %s" +msgstr "%s: réad truaillithe nó ar iarraidh: %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: object could not be parsed: %s" +msgstr "%s: nà fhéadfaà réad a pháirseáil: %s" + +#: builtin/fsck.c +#, c-format +msgid "bad sha1 file: %s" +msgstr "comhad sha1 olc: %s" + +#: builtin/fsck.c +msgid "Checking object directory" +msgstr "Seiceáil eolaire réada" + +#: builtin/fsck.c +msgid "Checking object directories" +msgstr "Seiceáil eolairà réada" + +#: builtin/fsck.c +#, c-format +msgid "Checking %s link" +msgstr "Nasc %s a sheiceáil" + +#: builtin/fsck.c builtin/index-pack.c +#, c-format +msgid "invalid %s" +msgstr "%s neamhbhailÃ" + +#: builtin/fsck.c +#, c-format +msgid "%s points to something strange (%s)" +msgstr "LéirÃonn %s rud éigin aisteach (%s)" + +#: builtin/fsck.c +#, c-format +msgid "%s: detached HEAD points at nothing" +msgstr "%s: pointà HEAD scoite ag aon rud" + +#: builtin/fsck.c +#, c-format +msgid "notice: %s points to an unborn branch (%s)" +msgstr "fógra: DÃrÃonn %s chuig brainse neamhbhreithe (%s)" + +#: builtin/fsck.c +#, c-format +msgid "Checking cache tree of %s" +msgstr "Crann taisce de %s a sheiceáil" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid sha1 pointer in cache-tree of %s" +msgstr "%s: pointeoir sha1 neamhbhailà i gcrann cache-%s" + +#: builtin/fsck.c +msgid "non-tree in cache-tree" +msgstr "neamh-chrann i gcrann cache-" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid sha1 pointer in resolve-undo of %s" +msgstr "%s: pointeoir sha1 neamhbhailà i réiteach a chealú de %s" + +#: builtin/fsck.c +#, c-format +msgid "unable to load rev-index for pack '%s'" +msgstr "in ann innéacs rev-innéacs a luchtú do phacáiste '%s'" + +#: builtin/fsck.c +#, c-format +msgid "invalid rev-index for pack '%s'" +msgstr "innéacs rev-neamhbhailà do phacáiste '%s'" + +#: builtin/fsck.c +msgid "Checking ref database" +msgstr "Seiceáil bunachar sonraà tagairt" + +#: builtin/fsck.c +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] [--[no-]references] [<object>...]" +msgstr "" +"git fsck [--tags] [--root] [--inrochtana] [--cache] [--no-reflogs]\n" +" [-- [no-] iomlán] [--dian] [--verbose] [--caillte]\n" +" [-- [gan-] ag crochadh] [-- [gan-] dul chun cinn] [--nascacht amháin]\n" +" <object>[-- [no-] ainm-rudaÃ] [-- [aon-] tagairtÃ] [...]" + +#: builtin/fsck.c +msgid "show unreachable objects" +msgstr "taispeáint rudaà dochreidte" + +#: builtin/fsck.c +msgid "show dangling objects" +msgstr "taispeáin rudaà crochtanacha" + +#: builtin/fsck.c +msgid "report tags" +msgstr "clibeanna tuarascála" + +#: builtin/fsck.c +msgid "report root nodes" +msgstr "nóid fréimhe a thuairisc" + +#: builtin/fsck.c +msgid "make index objects head nodes" +msgstr "nóid ceann rudaà innéacs a dhéanamh" + +#: builtin/fsck.c +msgid "make reflogs head nodes (default)" +msgstr "nóid ceann reflogs a dhéanamh (réamhshocraithe)" + +#: builtin/fsck.c +msgid "also consider packs and alternate objects" +msgstr "smaoinigh freisin ar phacáistà agus rudaÃ" + +#: builtin/fsck.c +msgid "check only connectivity" +msgstr "seiceáil ach nascacht" + +#: builtin/fsck.c builtin/mktag.c +msgid "enable more strict checking" +msgstr "cumasú seiceáil nÃos docht" + +#: builtin/fsck.c +msgid "write dangling objects in .git/lost-found" +msgstr "scrÃobh rudaà crochta in .git/lost-found" + +#: builtin/fsck.c builtin/prune.c +msgid "show progress" +msgstr "taispeáin dul chun cinn" + +#: builtin/fsck.c +msgid "show verbose names for reachable objects" +msgstr "taispeáint ainmneacha fabhracha do rudaà inrochtana" + +#: builtin/fsck.c +msgid "check reference database consistency" +msgstr "seiceáil comhsheasmhacht bunachair" + +#: builtin/fsck.c builtin/index-pack.c +msgid "Checking objects" +msgstr "Rud a sheiceáil" + +#: builtin/fsck.c +#, c-format +msgid "%s: object missing" +msgstr "%s: réad ar iarraidh" + +#: builtin/fsck.c +#, c-format +msgid "invalid parameter: expected sha1, got '%s'" +msgstr "paraiméadar neamhbhailÃ: súil le sha1, fuair '%s'" + +#: builtin/fsmonitor--daemon.c +msgid "git fsmonitor--daemon start [<options>]" +msgstr "git fsmonitor--daemon start [<options>]" + +#: builtin/fsmonitor--daemon.c +msgid "git fsmonitor--daemon run [<options>]" +msgstr "git fsmonitor--daemon run [<options>]" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "value of '%s' out of range: %d" +msgstr "luach '%s' lasmuigh den raon: %d" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "value of '%s' not bool or int: %d" +msgstr "luach '%s' gan bool nó int: %d" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor-daemon is watching '%s'\n" +msgstr "tá fsmonitor-daemon ag féachaint ar '%s'\n" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor-daemon is not watching '%s'\n" +msgstr "nÃl fsmonitor-daemon ag féachaint ar '%s'\n" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "could not create fsmonitor cookie '%s'" +msgstr "nà fhéadfaà fianán fsmonitor '%s' a chruthú" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor: cookie_result '%d' != SEEN" +msgstr "fsmonitor: cookie_result '%d' != SEEN" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "could not start IPC thread pool on '%s'" +msgstr "nà fhéadfaà linn snáithe IPC a thosú ar '%s'" + +#: builtin/fsmonitor--daemon.c +msgid "could not start fsmonitor listener thread" +msgstr "nà fhéadfaà snáithe éisteora fsmonitor a thosú" + +#: builtin/fsmonitor--daemon.c +msgid "could not start fsmonitor health thread" +msgstr "nà fhéadfaà snáithe sláinte fsmonitor a thosú" + +#: builtin/fsmonitor--daemon.c +msgid "could not initialize listener thread" +msgstr "nà fhéadfadh snáithe éisteora a thionscnamh" + +#: builtin/fsmonitor--daemon.c +msgid "could not initialize health thread" +msgstr "nà fhéadfaà snáithe sláinte a thionscnamh" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "could not cd home '%s'" +msgstr "nà fhéadfaà cd baile '%s'" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor--daemon is already running '%s'" +msgstr "tá fsmonitor--daemon ag rith '%s' cheana féin" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "running fsmonitor-daemon in '%s'\n" +msgstr "ag rith fsmonitor-daemon i '%s'\n" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "starting fsmonitor-daemon in '%s'\n" +msgstr "ag tosú fsmonitor-daemon i '%s'\n" + +#: builtin/fsmonitor--daemon.c +msgid "daemon failed to start" +msgstr "theip ar daemon a thosú" + +#: builtin/fsmonitor--daemon.c +msgid "daemon not online yet" +msgstr "daemon nach bhfuil ar lÃne fós" + +#: builtin/fsmonitor--daemon.c +msgid "daemon terminated" +msgstr "deireadh le déemon" + +#: builtin/fsmonitor--daemon.c +msgid "detach from console" +msgstr "dÃcheangal ón gconsól" + +#: builtin/fsmonitor--daemon.c +msgid "use <n> ipc worker threads" +msgstr "úsáid snái <n>theanna oibrithe ipc" + +#: builtin/fsmonitor--daemon.c +msgid "max seconds to wait for background daemon startup" +msgstr "soicind uasta chun fanacht le tosú daemon cúlra" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "invalid 'ipc-threads' value (%d)" +msgstr "luach 'ipc-snáitheanna' neamhbhailà (%d)" + +#: builtin/fsmonitor--daemon.c t/helper/test-cache-tree.c +#, c-format +msgid "Unhandled subcommand '%s'" +msgstr "Foordú neamh-láimhseáilte '%s'" + +#: builtin/fsmonitor--daemon.c +msgid "fsmonitor--daemon not supported on this platform" +msgstr "fsmonitor--daemon nach dtacaÃonn sé ar an ardán seo" + +#: builtin/gc.c +msgid "git gc [<options>]" +msgstr "git gc [<options>]" + +#: builtin/gc.c +#, c-format +msgid "Failed to fstat %s: %s" +msgstr "Theip ar fstat %s: %s" + +#: builtin/gc.c +#, c-format +msgid "failed to parse '%s' value '%s'" +msgstr "theip ar luach '%s' a pharsáil '%s'" + +#: builtin/gc.c setup.c +#, c-format +msgid "cannot stat '%s'" +msgstr "nà féidir '%s' a stát" + +#: builtin/gc.c +#, c-format +msgid "" +"The last gc run reported the following. Please correct the root cause\n" +"and remove %s\n" +"Automatic cleanup will not be performed until the file is removed.\n" +"\n" +"%s" +msgstr "" +"Tuairiscigh an rith gc deireanach an méid seo a leanas Ceartaigh an bunchúis " +"le do thoil\n" +"agus bain %s\n" +"Nà dhéanfar glantachán uathoibrÃoch go dtà go mbainfear an comhad.\n" +"\n" +"%s" + +#: builtin/gc.c +msgid "prune unreferenced objects" +msgstr "rudaà gan tagairt a ghearradh" + +#: builtin/gc.c +msgid "pack unreferenced objects separately" +msgstr "rudaà gan tagairt a phacáil ar leithligh" + +#: builtin/gc.c builtin/repack.c +msgid "with --cruft, limit the size of new cruft packs" +msgstr "le --cruft, teorainn le méid pacáistà cruft nua" + +#: builtin/gc.c +msgid "be more thorough (increased runtime)" +msgstr "a bheith nÃos crÃochnúla (tréimhse méadaithe)" + +#: builtin/gc.c +msgid "enable auto-gc mode" +msgstr "mód auto-gc a chumasú" + +#: builtin/gc.c +msgid "perform garbage collection in the background" +msgstr "bailiú truflais a dhéanamh sa chúlra" + +#: builtin/gc.c +msgid "force running gc even if there may be another gc running" +msgstr "fórsa ag rith gc fiú má d'fhéadfadh gc eile a bheith ag rith" + +#: builtin/gc.c +msgid "repack all other packs except the largest pack" +msgstr "gach pacáiste eile a athphacáil ach amháin an pacáiste is mó" + +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "réimÃr pacáiste chun pacáiste ina bhfuil rudaà gearrtha a stóráil" + +#: builtin/gc.c +#, c-format +msgid "failed to parse gc.logExpiry value %s" +msgstr "theip ar luach gc.logExpiry %s a pháirseáil" + +#: builtin/gc.c +#, c-format +msgid "failed to parse prune expiry value %s" +msgstr "theip ar luach éaga brúite %s a pharsáil" + +#: builtin/gc.c +#, c-format +msgid "Auto packing the repository in background for optimum performance.\n" +msgstr "Pacáil uathoibrÃoch an stór sa chúlra chun an fheidhmÃocht is fearr\n" + +#: builtin/gc.c +#, c-format +msgid "Auto packing the repository for optimum performance.\n" +msgstr "Pacáil uathoibrÃoch an stór chun an fheidhmÃocht is fearr\n" + +#: builtin/gc.c +#, c-format +msgid "See \"git help gc\" for manual housekeeping.\n" +msgstr "Féach \"git help gc\" le haghaidh obair tà láimhe.\n" + +#: builtin/gc.c +#, c-format +msgid "" +"gc is already running on machine '%s' pid %<PRIuMAX> (use --force if not)" +msgstr "" +"tá gc ag rith cheana féin ar mheaisÃn '%s' pid%<PRIuMAX>(bain úsáid as --" +"force mura bhfuil)" + +#: builtin/gc.c +msgid "" +"There are too many unreachable loose objects; run 'git prune' to remove them." +msgstr "" +"Tá an iomarca rudaà scaoilte neamh-inrochtana ann; reáchtáil 'git prune' " +"chun iad a bhaint." + +#: builtin/gc.c +msgid "" +"git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]" +msgstr "" +"<task>rith cothabhála git [--auto] [-- [no-] ciúin] [--task=] [--schedule]" + +#: builtin/gc.c +msgid "--no-schedule is not allowed" +msgstr "Nà cheadaÃtear --no-schedule" + +#: builtin/gc.c +#, c-format +msgid "unrecognized --schedule argument '%s'" +msgstr "argóint --schedule gan aithint '%s'" + +#: builtin/gc.c +msgid "failed to write commit-graph" +msgstr "theip orthu graf coimisiúnaithe a scrÃobh" + +#: builtin/gc.c +msgid "failed to prefetch remotes" +msgstr "theip ar iargúlta iargúlta a réamhghabháil" + +#: builtin/gc.c +msgid "failed to start 'git pack-objects' process" +msgstr "theip ar phróiseas 'git pack-objects' a thosú" + +#: builtin/gc.c +msgid "failed to finish 'git pack-objects' process" +msgstr "theip ar phróiseas 'git pack-objects' a chrÃochnú" + +#: builtin/gc.c +msgid "failed to write multi-pack-index" +msgstr "theip ar innéacs il-phacáiste a scrÃobh" + +#: builtin/gc.c +msgid "'git multi-pack-index expire' failed" +msgstr "Theip ar 'git multi-pack-index in éag'" + +#: builtin/gc.c +msgid "'git multi-pack-index repack' failed" +msgstr "Theip ar 'git multi-pack-index repack'" + +#: builtin/gc.c +msgid "" +"skipping incremental-repack task because core.multiPackIndex is disabled" +msgstr "" +"tasc athphacáil fáis a scipeáil toisc go bhfuil core.multiPackIndex " +"dÃchumasaithe" + +#: builtin/gc.c +#, c-format +msgid "lock file '%s' exists, skipping maintenance" +msgstr "tá comhad glasála '%s' ann, ag scipeáil cothabháil" + +#: builtin/gc.c +#, c-format +msgid "task '%s' failed" +msgstr "theip ar thasc '%s'" + +#: builtin/gc.c +#, c-format +msgid "'%s' is not a valid task" +msgstr "Nà tasc bailà é '%s'" + +#: builtin/gc.c +#, c-format +msgid "task '%s' cannot be selected multiple times" +msgstr "nà féidir tasc '%s' a roghnú arÃs agus arÃs eile" + +#: builtin/gc.c +msgid "run tasks based on the state of the repository" +msgstr "tascanna a reáchtáil bunaithe ar staid an stór" + +#: builtin/gc.c +msgid "perform maintenance in the background" +msgstr "cothabháil a dhéanamh sa chúlra" + +#: builtin/gc.c +msgid "frequency" +msgstr "minicÃocht" + +#: builtin/gc.c +msgid "run tasks based on frequency" +msgstr "tascanna a rith bunaithe ar mhinicÃocht" + +#: builtin/gc.c +msgid "do not report progress or other information over stderr" +msgstr "ná tuairiscigh dul chun cinn nó faisnéis eile faoi stderr" + +#: builtin/gc.c +msgid "task" +msgstr "tasc" + +#: builtin/gc.c +msgid "run a specific task" +msgstr "tasc ar leith a reáchtáil" + +#: builtin/gc.c +msgid "use at most one of --auto and --schedule=<frequency>" +msgstr "bain úsáid as --auto agus --schedule=<frequency> ar a mhéad" + +#: builtin/gc.c +#, c-format +msgid "unable to add '%s' value of '%s'" +msgstr "nach féidir luach '%s' de '%s' a chur leis" + +#: builtin/gc.c +msgid "return success even if repository was not registered" +msgstr "rath ar ais fiú mura raibh stór cláraithe" + +#: builtin/gc.c +#, c-format +msgid "unable to unset '%s' value of '%s'" +msgstr "nach féidir luach '%s' de '%s' a dhÃshocrú" + +#: builtin/gc.c +#, c-format +msgid "repository '%s' is not registered" +msgstr "nÃl stór '%s' cláraithe" + +#: builtin/gc.c +#, c-format +msgid "failed to expand path '%s'" +msgstr "theip ar an gcosán '%s' a leathnú" + +#: builtin/gc.c +msgid "failed to start launchctl" +msgstr "theip ar launchctl a thosú" + +#: builtin/gc.c +#, c-format +msgid "failed to create directories for '%s'" +msgstr "theip ar eolairà a chruthú do '%s'" + +#: builtin/gc.c +#, c-format +msgid "failed to bootstrap service %s" +msgstr "theip ar sheirbhÃs bootstrap %s" + +#: builtin/gc.c +msgid "failed to create temp xml file" +msgstr "theip ar chomhad xml temp a chruthú" + +#: builtin/gc.c +msgid "failed to start schtasks" +msgstr "theip ar schasks a thosú" + +#: builtin/gc.c +msgid "failed to run 'crontab -l'; your system might not support 'cron'" +msgstr "" +"theip ar 'crontab -l' a reáchtáil; b'fhéidir nach dtacaÃonn do chóras le " +"'cron'" + +#: builtin/gc.c +msgid "failed to create crontab temporary file" +msgstr "theip ar chomhad sealadach crontab a chruthú" + +#: builtin/gc.c +msgid "failed to open temporary file" +msgstr "theip ar chomhad sealadach a oscailt" + +#: builtin/gc.c +msgid "failed to run 'crontab'; your system might not support 'cron'" +msgstr "" +"theip ar 'crontab' a reáchtáil; b'fhéidir nach dtacaÃonn do chóras le 'cron'" + +#: builtin/gc.c +msgid "'crontab' died" +msgstr "Fuair 'crontab' bás" + +#: builtin/gc.c builtin/worktree.c +#, c-format +msgid "failed to delete '%s'" +msgstr "theip ar '%s' a scriosadh" + +#: builtin/gc.c rerere.c +#, c-format +msgid "failed to flush '%s'" +msgstr "theip ar '%s' a shruthlú" + +#: builtin/gc.c +msgid "failed to start systemctl" +msgstr "theip ar systemctl a thosú" + +#: builtin/gc.c +msgid "failed to run systemctl" +msgstr "theip ar systemctl a reáchtáil" + +#: builtin/gc.c +#, c-format +msgid "unrecognized --scheduler argument '%s'" +msgstr "argóint --scheduler gan aithint '%s'" + +#: builtin/gc.c +msgid "neither systemd timers nor crontab are available" +msgstr "nÃl uaireoirà systemd ná crontab ar fáil" + +#: builtin/gc.c +#, c-format +msgid "%s scheduler is not available" +msgstr "NÃl sceidealóir %s ar fáil" + +#: builtin/gc.c +#, c-format +msgid "" +"unable to create '%s.lock': %s.\n" +"\n" +"Another scheduled git-maintenance(1) process seems to be running in this\n" +"repository. Please make sure no other maintenance processes are running and\n" +"then try again. If it still fails, a git-maintenance(1) process may have\n" +"crashed in this repository earlier: remove the file manually to continue." +msgstr "" +"nach féidir '%s.lock' a chruthú: %s.\n" +"\n" +"Is cosúil go bhfuil próiseas sceidealaithe eile git-maintenance(1) ag rith " +"sa\n" +"stórlann seo\n" +"Déan cinnte go bhfuil aon phróisis chothabhála eile ag rith agus\n" +"ansin déan iarracht arÃs. Má theipeann air fós, d'fhéadfadh go mbeadh " +"próiseas cothabhála git-maintenance (1)\n" +"tháinig isteach sa stór seo nÃos luaithe: bain an comhad de láimh chun " +"leanúint ar aghaidh." + +#: builtin/gc.c +msgid "cannot acquire lock for scheduled background maintenance" +msgstr "nà féidir glas a fháil le haghaidh cothabháil sceidealta cúlra" + +#: builtin/gc.c +msgid "git maintenance start [--scheduler=<scheduler>]" +msgstr "<scheduler>tús cothabhála git [--scheduler=]" + +#: builtin/gc.c +msgid "scheduler" +msgstr "sceidealóir" + +#: builtin/gc.c +msgid "scheduler to trigger git maintenance run" +msgstr "sceidealóir chun rith cothabhála git a spreagadh" + +#: builtin/gc.c +msgid "failed to set up maintenance schedule" +msgstr "theip ar sceideal cothabhála a chur ar bun" + +#: builtin/gc.c +msgid "failed to add repo to global config" +msgstr "theip ar repo a chur le cumraÃocht domhanda" + +#: builtin/gc.c +msgid "git maintenance <subcommand> [<options>]" +msgstr "cothabháil git <subcommand>[<options>]" + +#: builtin/grep.c +msgid "git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]" +msgstr "git grep [<options>] [-e] <pattern>[<rev>...] [[--]<path>...]" + +#: builtin/grep.c +#, c-format +msgid "grep: failed to create thread: %s" +msgstr "grep: theip ar shnáithe a chruthú: %s" + +#: builtin/grep.c +#, c-format +msgid "invalid number of threads specified (%d) for %s" +msgstr "lÃon neamhbhailà na snáitheanna a shonraÃtear (%d) do %s" + +#. TRANSLATORS: %s is the configuration +#. variable for tweaking threads, currently +#. grep.threads +#. +#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "no threads support, ignoring %s" +msgstr "gan tacaÃocht do shnáitheanna, ag déanamh neamhaird ar %s" + +#: builtin/grep.c +#, c-format +msgid "unable to read tree %s" +msgstr "nach féidir crann %s a léamh" + +#: builtin/grep.c +#, c-format +msgid "unable to grep from object of type %s" +msgstr "in ann grep ó réad de chineál %s" + +#: builtin/grep.c +#, c-format +msgid "switch `%c' expects a numerical value" +msgstr "tá an lasc `%c' ag súil le luach uimhriúil" + +#: builtin/grep.c +msgid "search in index instead of in the work tree" +msgstr "cuardaigh san innéacs in ionad sa chrann oibre" + +#: builtin/grep.c +msgid "find in contents not managed by git" +msgstr "aimsigh in ábhar nach mbainistÃonn git" + +#: builtin/grep.c +msgid "search in both tracked and untracked files" +msgstr "cuardach i gcomhaid rianaithe agus neamhrianaithe araon" + +#: builtin/grep.c +msgid "ignore files specified via '.gitignore'" +msgstr "neamhaird a dhéanamh ar chomhaid a shonraÃtear trà '.gitignore'" + +#: builtin/grep.c +msgid "recursively search in each submodule" +msgstr "cuardach athshlánach i ngach fo-mhodúl" + +#: builtin/grep.c +msgid "show non-matching lines" +msgstr "lÃnte neamh-mheaitseála a" + +#: builtin/grep.c +msgid "case insensitive matching" +msgstr "meaitseáil cás neamhÃogair" + +#: builtin/grep.c +msgid "match patterns only at word boundaries" +msgstr "patrúin a mheaitseáil ach ag teorainneacha focal" + +#: builtin/grep.c +msgid "process binary files as text" +msgstr "comhaid dénártha a phróiseáil mar th" + +#: builtin/grep.c +msgid "don't match patterns in binary files" +msgstr "ná meaitseáil patrúin i gcomhaid dénártha" + +#: builtin/grep.c +msgid "process binary files with textconv filters" +msgstr "comhaid dénártha a phróiseáil le scagairà textconv" + +#: builtin/grep.c +msgid "search in subdirectories (default)" +msgstr "cuardaigh i bhfo-eolairà (réamhshocrú)" + +#: builtin/grep.c +msgid "descend at most <n> levels" +msgstr "sÃos ag an bhformhór na <n>leibh" + +#: builtin/grep.c +msgid "use extended POSIX regular expressions" +msgstr "bain úsáid as nathanna rialta POSIX leathnaithe" + +#: builtin/grep.c +msgid "use basic POSIX regular expressions (default)" +msgstr "úsáid abairtà rialta bunúsacha POSIX (réamhshocraithe)" + +#: builtin/grep.c +msgid "interpret patterns as fixed strings" +msgstr "patrúin a léiriú mar teaghráin seasta" + +#: builtin/grep.c +msgid "use Perl-compatible regular expressions" +msgstr "úsáid abairtà rialta atá comhoiriúnach le PERL" + +#: builtin/grep.c +msgid "show line numbers" +msgstr "taispeáin uimhreacha lÃne" + +#: builtin/grep.c +msgid "show column number of first match" +msgstr "taispeáin uimhir cholún an chéad chluiche" + +#: builtin/grep.c +msgid "don't show filenames" +msgstr "ná taispeáin ainmneacha comhaid" + +#: builtin/grep.c +msgid "show filenames" +msgstr "taispeáin ainmneacha comhaid" + +#: builtin/grep.c +msgid "show filenames relative to top directory" +msgstr "ainmneacha comhaid a thaispeáint i gcoibhneas" + +#: builtin/grep.c +msgid "show only filenames instead of matching lines" +msgstr "taispeáint ach ainmneacha comhaid in ionad lÃnte meaitseála" + +#: builtin/grep.c +msgid "synonym for --files-with-matches" +msgstr "comhchiallach do --files-with-matches" + +#: builtin/grep.c +msgid "show only the names of files without match" +msgstr "taispeáint ach ainmneacha na gcomhaid gan meaitseáil" + +#: builtin/grep.c +msgid "print NUL after filenames" +msgstr "priontáil NUL tar éis ainmneacha comhaid" + +#: builtin/grep.c +msgid "show only matching parts of a line" +msgstr "taispeáin ach codanna de lÃne a mheaitseáil" + +#: builtin/grep.c +msgid "show the number of matches instead of matching lines" +msgstr "taispeáint lÃon na gcluichà in ionad lÃnte meaitseála" + +#: builtin/grep.c +msgid "highlight matches" +msgstr "cluichà aibhsithe" + +#: builtin/grep.c +msgid "print empty line between matches from different files" +msgstr "priontáil lÃne folamh idir cluichà ó chomhaid éagsúla" + +#: builtin/grep.c +msgid "show filename only once above matches from same file" +msgstr "" +"taispeáin ainm comhaid ach uair amháin thuas na cluichà ón gcomhad céanna" + +#: builtin/grep.c +msgid "show <n> context lines before and after matches" +msgstr "<n>lÃnte comhthéacs a thaispeáint roimh agus tar" + +#: builtin/grep.c +msgid "show <n> context lines before matches" +msgstr "<n>lÃnte comhthéacs a thaispeáint" + +#: builtin/grep.c +msgid "show <n> context lines after matches" +msgstr "<n>lÃnte comhthéacs a thaispeáint" + +#: builtin/grep.c +msgid "use <n> worker threads" +msgstr "úsáid sná <n>itheanna oibrithe" + +#: builtin/grep.c +msgid "shortcut for -C NUM" +msgstr "aicearra le haghaidh -C NUM" + +#: builtin/grep.c +msgid "show a line with the function name before matches" +msgstr "taispeáint lÃne leis an ainm feidhme roimh mheaitseálacha" + +#: builtin/grep.c +msgid "show the surrounding function" +msgstr "taispeáin an fheidhm máguaird" + +#: builtin/grep.c +msgid "read patterns from file" +msgstr "patrúin a léamh ón gcomhad" + +#: builtin/grep.c +msgid "match <pattern>" +msgstr "comhoiriúnú <pattern>" + +#: builtin/grep.c +msgid "combine patterns specified with -e" +msgstr "comhcheangal patrúin a shonraÃtear le -e" + +#: builtin/grep.c +msgid "indicate hit with exit status without output" +msgstr "léirigh bualadh le stádas imeachta gan aschur" + +#: builtin/grep.c +msgid "show only matches from files that match all patterns" +msgstr "taispeáin ach cluichà ó chomhaid a mheaitseálann gach patrún" + +#: builtin/grep.c +msgid "pager" +msgstr "pager" + +#: builtin/grep.c +msgid "show matching files in the pager" +msgstr "taispeáint comhaid mheaitseála sa pager" + +#: builtin/grep.c +msgid "allow calling of grep(1) (ignored by this build)" +msgstr "cead a ghlaoch grep (1) (neamhaird ag an tógáil seo)" + +#: builtin/grep.c +msgid "maximum number of results per file" +msgstr "lÃon uasta na dtorthaà in aghaidh an chomhad" + +#: builtin/grep.c +msgid "no pattern given" +msgstr "aon phatrún a thugtar" + +#: builtin/grep.c +msgid "--no-index or --untracked cannot be used with revs" +msgstr "Nà féidir --no-index nó --untracked a úsáid le hathairÃ" + +#: builtin/grep.c +#, c-format +msgid "unable to resolve revision: %s" +msgstr "nach féidir athbhreithniú a réiteach: %s" + +#: builtin/grep.c +msgid "--untracked not supported with --recurse-submodules" +msgstr "--untracked nach dtacaÃtear le --recurse-submodules" + +#: builtin/grep.c +msgid "invalid option combination, ignoring --threads" +msgstr "teaglaim roghanna neamhbhailÃ, ag neamhaird --threads" + +#: builtin/grep.c builtin/pack-objects.c +msgid "no threads support, ignoring --threads" +msgstr "nÃl aon tacaÃocht do shnáitheanna, ag déanamh neamhaird ar --threads" + +#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "invalid number of threads specified (%d)" +msgstr "lÃon neamhbhailà na snáitheanna sonraithe (%d)" + +#: builtin/grep.c +msgid "--open-files-in-pager only works on the worktree" +msgstr "Nà oibrÃonn --open-files-in-pager ach ar an gcrann oibre" + +#: builtin/grep.c +msgid "--[no-]exclude-standard cannot be used for tracked contents" +msgstr "" +"- nà féidir caighdeán eisiach [no-] a úsáid le haghaidh ábhar rianaithe" + +#: builtin/grep.c +msgid "both --cached and trees are given" +msgstr "tugtar --cached agus crainn araon" + +#: builtin/hash-object.c +msgid "" +"git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n" +" [--stdin [--literally]] [--] <file>..." +msgstr "" +"git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n" +" [--stdin [--literally]] [--] <file>..." + +#: builtin/hash-object.c +msgid "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]" +msgstr "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]" + +#: builtin/hash-object.c +msgid "object type" +msgstr "cineál réad" + +#: builtin/hash-object.c +msgid "write the object into the object database" +msgstr "scrÃobh an réad isteach sa bhunachar sonraà réad" + +#: builtin/hash-object.c +msgid "read the object from stdin" +msgstr "léigh an réad ó stdin" + +#: builtin/hash-object.c +msgid "store file as is without filters" +msgstr "comhad a stóráil mar atá gan scagairÃ" + +#: builtin/hash-object.c +msgid "" +"just hash any random garbage to create corrupt objects for debugging Git" +msgstr "" +"nà gá ach aon truflais randamach a chur chun rudaà truaillithe a chruthú le " +"haghaidh dÃfhab" + +#: builtin/hash-object.c +msgid "process file as it were from this path" +msgstr "comhad próiseála mar a bhà sé ón gcosán seo" + +#: builtin/help.c +msgid "print all available commands" +msgstr "gach ordú atá ar fáil a phriontáil" + +#: builtin/help.c +msgid "show external commands in --all" +msgstr "taispeáint orduithe seachtracha i --all" + +#: builtin/help.c +msgid "show aliases in --all" +msgstr "taispeáin ainmneacha in --all" + +#: builtin/help.c +msgid "exclude guides" +msgstr "treoracha a eisiamh" + +#: builtin/help.c +msgid "show man page" +msgstr "taispeáin leathanach fear" + +#: builtin/help.c +msgid "show manual in web browser" +msgstr "taispeáin lámhleabhar sa bhrabhsála" + +#: builtin/help.c +msgid "show info page" +msgstr "taispeáin leathanach faisnéise" + +#: builtin/help.c +msgid "print command description" +msgstr "cur sÃos ordaithe priontála" + +#: builtin/help.c +msgid "print list of useful guides" +msgstr "liosta priontáil de threoracha úsáideacha" + +#: builtin/help.c +msgid "print list of user-facing repository, command and file interfaces" +msgstr "" +"liosta priontála de stór, comhéadain ordaithe agus comhad atá os comhair " +"úsáideora" + +#: builtin/help.c +msgid "print list of file formats, protocols and other developer interfaces" +msgstr "" +"liosta priontála formáidà comhaid, prótacail agus comhéadain forbróra eile" + +#: builtin/help.c +msgid "print all configuration variable names" +msgstr "priontáil gach ainm athróg cumraÃochta" + +#: builtin/help.c +msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]" +msgstr "<command><doc>git help [[-i|--eolas] [-m|--fear] [-w|--gréasáin]] [|]" + +#: builtin/help.c +#, c-format +msgid "unrecognized help format '%s'" +msgstr "formáid cabhrach gan aithint '%s'" + +#: builtin/help.c +msgid "Failed to start emacsclient." +msgstr "Theip ar emacsclient a thosú." + +#: builtin/help.c +msgid "Failed to parse emacsclient version." +msgstr "Theip ar leagan emacsclient a pháirseáil." + +#: builtin/help.c +#, c-format +msgid "emacsclient version '%d' too old (< 22)." +msgstr "leagan imacsclient '%d' ró-sean (< 22)." + +#: builtin/help.c +#, c-format +msgid "failed to exec '%s'" +msgstr "theip ar '%s' a fheidhmiú" + +#: builtin/help.c +#, c-format +msgid "" +"'%s': path for unsupported man viewer.\n" +"Please consider using 'man.<tool>.cmd' instead." +msgstr "" +"'%s': cosán do lucht féachana fear gan tacaÃocht.\n" +"Smaoinigh ar 'fear a úsáid le do thoil. <tool>.cmd' ina ionad." + +#: builtin/help.c +#, c-format +msgid "" +"'%s': cmd for supported man viewer.\n" +"Please consider using 'man.<tool>.path' instead." +msgstr "" +"'%s': cmd do lucht féachana fear tacaithe.\n" +"Smaoinigh ar 'fear a úsáid le do thoil. <tool>.path' ina ionad sin." + +#: builtin/help.c +#, c-format +msgid "'%s': unknown man viewer." +msgstr "'%s': féachtóir fear anaithnid." + +#: builtin/help.c +msgid "no man viewer handled the request" +msgstr "nÃl aon fhéachtóir fear ar an iarraidh" + +#: builtin/help.c +msgid "no info viewer handled the request" +msgstr "nÃl aon fhéachtóir faisnéise ag láimhseáil" + +#: builtin/help.c git.c +#, c-format +msgid "'%s' is aliased to '%s'" +msgstr "Tá '%s' aistrithe go '%s'" + +#: builtin/help.c git.c +#, c-format +msgid "bad alias.%s string: %s" +msgstr "droch-ainm. Teagán %s: %s" + +#: builtin/help.c +#, c-format +msgid "the '%s' option doesn't take any non-option arguments" +msgstr "nà ghlacann an rogha '%s' aon argóintà neamh-rogha" + +#: builtin/help.c +msgid "" +"the '--no-[external-commands|aliases]' options can only be used with '--all'" +msgstr "" +"nà féidir na roghanna '--no- [external-commands|aliases] 'a úsáid ach le' --" +"all '" + +#: builtin/help.c +#, c-format +msgid "usage: %s%s" +msgstr "úsáid: %s%s" + +#: builtin/help.c +msgid "'git help config' for more information" +msgstr "'git help config' le haghaidh tuilleadh faisnéise" + +#: builtin/hook.c +msgid "" +"git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-" +"args>]" +msgstr "" +"<path><hook-name><hook-args>git hook run [--ignore-missing] [--to-stdin =] " +"[--]" + +#: builtin/hook.c +msgid "silently ignore missing requested <hook-name>" +msgstr "neamhaird go ciúin a iarrtar ar <hook-name>" + +#: builtin/hook.c +msgid "file to read into hooks' stdin" +msgstr "comhad le léamh isteach i stdin na hracaÃ" + +#: builtin/index-pack.c +#, c-format +msgid "object type mismatch at %s" +msgstr "mÃmheaitseáil cineál réad ag %s" + +#: builtin/index-pack.c +#, c-format +msgid "did not receive expected object %s" +msgstr "nár bhfuair sé réad ag súil leis %s" + +#: builtin/index-pack.c +#, c-format +msgid "object %s: expected type %s, found %s" +msgstr "réad %s: súil leis an gcineál %s, aimsÃodh %s" + +#: builtin/index-pack.c +#, c-format +msgid "cannot fill %d byte" +msgid_plural "cannot fill %d bytes" +msgstr[0] "nà féidir %d beart a lÃonadh" +msgstr[1] "nà féidir %d beart a lÃonadh" +msgstr[2] "nà féidir %d beart a lÃonadh" + +#: builtin/index-pack.c +msgid "early EOF" +msgstr "luath EOF" + +#: builtin/index-pack.c +msgid "read error on input" +msgstr "earráid léigh ar ionchur" + +#: builtin/index-pack.c +msgid "used more bytes than were available" +msgstr "úsáideadh nÃos mó bytes ná mar a bhà ar fáil" + +#: builtin/index-pack.c builtin/pack-objects.c +msgid "pack too large for current definition of off_t" +msgstr "pacáiste ró-mhór le haghaidh sainmhÃniú reatha ar off_t" + +#: builtin/index-pack.c +#, c-format +msgid "pack exceeds maximum allowed size (%s)" +msgstr "sáraÃonn an pacáiste an méid uasta ceadaithe (%s)" + +#: builtin/index-pack.c +msgid "pack signature mismatch" +msgstr "mÃmheaitseáil sÃnithe pacáiste" + +#: builtin/index-pack.c +#, c-format +msgid "pack version %<PRIu32> unsupported" +msgstr "leagan pacáiste %<PRIu32> gan tacaÃocht" + +#: builtin/index-pack.c +#, c-format +msgid "pack has bad object at offset %<PRIuMAX>: %s" +msgstr "tá réad lochtach sa phacáiste ag an bhfritháireamh %<PRIuMAX>: %s" + +#: builtin/index-pack.c +#, c-format +msgid "inflate returned %d" +msgstr "infleáil ar ais %d" + +#: builtin/index-pack.c +msgid "offset value overflow for delta base object" +msgstr "ró-shreabhadh luacha a fhritháireamh do réad" + +#: builtin/index-pack.c +msgid "delta base offset is out of bound" +msgstr "tá fhritháireamh bonn delta as ceangailte" + +#: builtin/index-pack.c +#, c-format +msgid "unknown object type %d" +msgstr "cineál réad anaithnid %d" + +#: builtin/index-pack.c +msgid "cannot pread pack file" +msgstr "nà féidir comhad pacáiste a roghnú" + +#: builtin/index-pack.c +#, c-format +msgid "premature end of pack file, %<PRIuMAX> byte missing" +msgid_plural "premature end of pack file, %<PRIuMAX> bytes missing" +msgstr[0] "deireadh roimh am comhaid phacáiste, %<PRIuMAX> beart ar iarraidh" +msgstr[1] "deireadh roimh am comhaid phacáiste, %<PRIuMAX> beart ar iarraidh" +msgstr[2] "deireadh roimh am comhaid phacáiste, %<PRIuMAX> beart ar iarraidh" + +#: builtin/index-pack.c +msgid "serious inflate inconsistency" +msgstr "neamhchomhsheasmhacht tromchúiseach" + +#: builtin/index-pack.c +#, c-format +msgid "SHA1 COLLISION FOUND WITH %s !" +msgstr "FUARTHAS IMBHALL SHA1 LE %s!" + +#: builtin/index-pack.c +#, c-format +msgid "cannot read existing object info %s" +msgstr "nà féidir faisnéis réad atá ann cheana %s a léamh" + +#: builtin/index-pack.c +#, c-format +msgid "cannot read existing object %s" +msgstr "nà féidir réad %s atá ann cheana a léamh" + +#: builtin/index-pack.c +#, c-format +msgid "invalid blob object %s" +msgstr "réad blob neamhbhailà %s" + +#: builtin/index-pack.c +msgid "fsck error in packed object" +msgstr "earráid fsck i réad pacáilte" + +#: builtin/index-pack.c +#, c-format +msgid "Not all child objects of %s are reachable" +msgstr "NÃl gach réad leanbh de %s inrochtana" + +#: builtin/index-pack.c +msgid "failed to apply delta" +msgstr "theip ar delta a chur i bhfeidhm" + +#: builtin/index-pack.c +msgid "Receiving objects" +msgstr "Rudaà a fháil" + +#: builtin/index-pack.c +msgid "Indexing objects" +msgstr "Rudaà innéacsála" + +#: builtin/index-pack.c +msgid "pack is corrupted (SHA1 mismatch)" +msgstr "tá an pacáiste truaillithe (neamhoiriúnú SHA1)" + +#: builtin/index-pack.c +msgid "cannot fstat packfile" +msgstr "nà féidir le pacáiste fstat" + +#: builtin/index-pack.c +msgid "pack has junk at the end" +msgstr "tá bruscar ag an bpacáiste ag an deireadh" + +#: builtin/index-pack.c +msgid "confusion beyond insanity in parse_pack_objects()" +msgstr "mearbhall nÃos faide ná imnà i parse_pack_objects()" + +#: builtin/index-pack.c +msgid "Resolving deltas" +msgstr "Deltas a réiteach" + +#: builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "unable to create thread: %s" +msgstr "nach féidir snáithe a chruthú: %s" + +#: builtin/index-pack.c +msgid "confusion beyond insanity" +msgstr "mearbhall nÃos faide ná mar gheall" + +#: builtin/index-pack.c +#, c-format +msgid "completed with %d local object" +msgid_plural "completed with %d local objects" +msgstr[0] "crÃochnaithe le %d réad áitiúil" +msgstr[1] "crÃochnaithe le %d réad áitiúil" +msgstr[2] "crÃochnaithe le %d réad áitiúil" + +#: builtin/index-pack.c +#, c-format +msgid "Unexpected tail checksum for %s (disk corruption?)" +msgstr "Seicsum eireaball gan choinne do %s (éilliú diosca?)" + +#: builtin/index-pack.c +#, c-format +msgid "pack has %d unresolved delta" +msgid_plural "pack has %d unresolved deltas" +msgstr[0] "tá %d delta gan réiteach sa phacáiste" +msgstr[1] "tá %d deiltà gan réiteach sa phacáiste" +msgstr[2] "tá %d deiltà gan réiteach sa phacáiste" + +#: builtin/index-pack.c +#, c-format +msgid "unable to deflate appended object (%d)" +msgstr "nach féidir réad cuibheangailte a dhÃscaoileadh (%d)" + +#: builtin/index-pack.c +#, c-format +msgid "local object %s is corrupt" +msgstr "tá réad áitiúil %s truaillithe" + +#: builtin/index-pack.c +#, c-format +msgid "packfile name '%s' does not end with '.%s'" +msgstr "nà chrÃochnaÃonn ainm pacáiste '%s' le '.%s'" + +#: builtin/index-pack.c +#, c-format +msgid "cannot write %s file '%s'" +msgstr "nà féidir comhad %s '%s' a scrÃobh" + +#: builtin/index-pack.c +#, c-format +msgid "cannot close written %s file '%s'" +msgstr "nà féidir comhad %s scrÃofa '%s' a dhúnadh" + +#: builtin/index-pack.c +#, c-format +msgid "unable to rename temporary '*.%s' file to '%s'" +msgstr "in ann athainmniú sealadach '*.%s' comhad chuig '%s'" + +#: builtin/index-pack.c +msgid "error while closing pack file" +msgstr "earráid agus comhad pacáiste á dúnadh" + +#: builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "bad pack.indexVersion=%<PRIu32>" +msgstr "droch-pack.indexVersion=%<PRIu32>" + +#: builtin/index-pack.c +#, c-format +msgid "Cannot open existing pack file '%s'" +msgstr "Nà féidir comhad pacáiste atá ann cheana '%s' a oscailt" + +#: builtin/index-pack.c +#, c-format +msgid "Cannot open existing pack idx file for '%s'" +msgstr "Nà féidir comhad idx pacáiste atá ann cheana a oscailt do '%s'" + +#: builtin/index-pack.c +#, c-format +msgid "non delta: %d object" +msgid_plural "non delta: %d objects" +msgstr[0] "neamh-delta: %d réad" +msgstr[1] "neamh-delta: %d réad" +msgstr[2] "neamh-delta: %d réad" + +#: builtin/index-pack.c +#, c-format +msgid "chain length = %d: %lu object" +msgid_plural "chain length = %d: %lu objects" +msgstr[0] "fad slabhra = %d: %lu réad" +msgstr[1] "fad slabhra = %d: %lu réada" +msgstr[2] "fad slabhra = %d: %lu réada" + +#: builtin/index-pack.c +msgid "could not start pack-objects to repack local links" +msgstr "nà fhéadfaà pacáiste-earraà a thosú chun naisc áitiúla a athphacáil" + +#: builtin/index-pack.c +msgid "failed to feed local object to pack-objects" +msgstr "theip ar réad áitiúil a bheathú ar rudaà pacáiste" + +#: builtin/index-pack.c +msgid "index-pack: Expecting full hex object ID lines only from pack-objects." +msgstr "" +"index-pack: Ag súil le lÃnte aitheantais réada heicsidheachúlach iomlán ó " +"pack-objects amháin." + +#: builtin/index-pack.c +msgid "could not finish pack-objects to repack local links" +msgstr "nà fhéadfaà pacáistà a chrÃochnú chun naisc áitiúla a athphacáil" + +#: builtin/index-pack.c +msgid "Cannot come back to cwd" +msgstr "Nà féidir teacht ar ais chuig cwd" + +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "droch --pack_header: %s" + +#: builtin/index-pack.c +#, c-format +msgid "bad %s" +msgstr "droch %s" + +#: builtin/index-pack.c builtin/init-db.c setup.c +#, c-format +msgid "unknown hash algorithm '%s'" +msgstr "algartam hais anaithnid '%s'" + +#: builtin/index-pack.c +msgid "--promisor cannot be used with a pack name" +msgstr "--promisor nà féidir é a úsáid le hainm pacáiste" + +#: builtin/index-pack.c +msgid "--stdin requires a git repository" +msgstr "--stdin teastaÃonn stórlann git" + +#: builtin/index-pack.c +msgid "--verify with no packfile name given" +msgstr "--verify gan ainm comhaid pacáiste tugtha" + +#: builtin/index-pack.c builtin/unpack-objects.c +msgid "fsck error in pack objects" +msgstr "fsck earráid i rudaà pacáiste" + +#: builtin/init-db.c +msgid "" +"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=<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>]" + +#: builtin/init-db.c +msgid "permissions" +msgstr "ceadanna" + +#: builtin/init-db.c +msgid "specify that the git repository is to be shared amongst several users" +msgstr "sonraigh go bhfuil an stór git le roinnt i measc roinnt úsáideoirÃ" + +#: builtin/init-db.c +msgid "override the name of the initial branch" +msgstr "ainm na brainse tosaigh a shárú" + +#: builtin/init-db.c builtin/verify-pack.c +msgid "hash" +msgstr "hash" + +#: builtin/init-db.c builtin/show-index.c builtin/verify-pack.c +msgid "specify the hash algorithm to use" +msgstr "sonraigh an algartam hash le húsáid" + +#: builtin/init-db.c +#, c-format +msgid "cannot mkdir %s" +msgstr "nà féidir teacht ar %s" + +#: builtin/init-db.c +#, c-format +msgid "cannot chdir to %s" +msgstr "nà féidir teacht chuig %s" + +#: builtin/init-db.c +#, c-format +msgid "" +"%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-" +"dir=<directory>)" +msgstr "" +"%s (or --work-tree=<directory>) nà cheadaÃtear gan sonrú %s (or --git-" +"dir=<directory>)" + +#: builtin/init-db.c +#, c-format +msgid "Cannot access work tree '%s'" +msgstr "Nà féidir rochtain a fháil ar chrann oibre '%s'" + +#: builtin/init-db.c +msgid "--separate-git-dir incompatible with bare repository" +msgstr "--separate-git-dir neamhoiriúnach le stór lom" + +#: builtin/interpret-trailers.c +msgid "" +"git interpret-trailers [--in-place] [--trim-empty]\n" +" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n" +" [--parse] [<file>...]" +msgstr "" +"git interpret-trailers [--in-place] [--trim-empty]\n" +" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n" +" [--parse] [<file>...]" + +#: builtin/interpret-trailers.c wrapper.c +#, c-format +msgid "could not stat %s" +msgstr "nà raibh ann %s a shástáil" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not a regular file" +msgstr "nà comhad rialta é comhad %s" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not writable by user" +msgstr "nà féidir an t-úsáideoir comhad %s a scrÃobh" + +#: builtin/interpret-trailers.c +msgid "could not open temporary file" +msgstr "nà fhéadfadh comhad sealadach a oscailt" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not read input file '%s'" +msgstr "nà raibh in ann comhad ionchuir '%s' a léamh" + +#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c +msgid "could not read from stdin" +msgstr "nà fhéadfaà léamh ó stdin" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not rename temporary file to %s" +msgstr "nà fhéadfaà comhad sealadach a athainmniú go %s" + +#: builtin/interpret-trailers.c +msgid "edit files in place" +msgstr "comhaid in áit a chur in eagar" + +#: builtin/interpret-trailers.c +msgid "trim empty trailers" +msgstr "leantóirà folamh a ghear" + +#: builtin/interpret-trailers.c +msgid "placement" +msgstr "socrúcháin" + +#: builtin/interpret-trailers.c +msgid "where to place the new trailer" +msgstr "cá háit a chuirfear an leantóir nua" + +#: builtin/interpret-trailers.c +msgid "action if trailer already exists" +msgstr "gnÃomh má tá leantóir ann cheana féin" + +#: builtin/interpret-trailers.c +msgid "action if trailer is missing" +msgstr "gnÃomh má tá leantóir ar iarraidh" + +#: builtin/interpret-trailers.c +msgid "output only the trailers" +msgstr "aschur ach na leantóirÃ" + +#: builtin/interpret-trailers.c +msgid "do not apply trailer.* configuration variables" +msgstr "ná cuir leantóir i bhfeidhm.* athróga cumraÃochta" + +#: builtin/interpret-trailers.c +msgid "reformat multiline trailer values as single-line values" +msgstr "luachanna leantóra illÃne a athfhormáidiú mar luachanna aon-lÃne" + +#: builtin/interpret-trailers.c +msgid "alias for --only-trailers --only-input --unfold" +msgstr "ainm le haghaidh --only-trailers --only-input --unfold" + +#: builtin/interpret-trailers.c +msgid "do not treat \"---\" as the end of input" +msgstr "ná déileáil le “---†mar dheireadh an ionchuir" + +#: builtin/interpret-trailers.c +msgid "trailer(s) to add" +msgstr "leantóir (Ã) le cur leis" + +#: builtin/interpret-trailers.c +msgid "--trailer with --only-input does not make sense" +msgstr "nÃl ciall le --trailer le --only-input" + +#: builtin/interpret-trailers.c +msgid "no input file given for in-place editing" +msgstr "nÃl aon chomhad ionchuir a thugtar le haghaidh eagarthóireachta" + +#: builtin/log.c +msgid "git log [<options>] [<revision-range>] [[--] <path>...]" +msgstr "logáil git [<options>] [<revision-range>] [[--]<path>...]" + +#: builtin/log.c +msgid "git show [<options>] <object>..." +msgstr "git show [<options>]<object>..." + +#: builtin/log.c +#, c-format +msgid "invalid --decorate option: %s" +msgstr "rogha neamhbhailà --decorate: %s" + +#: builtin/log.c diff.c +msgid "suppress diff output" +msgstr "aschur diff a chur faoi chois" + +#: builtin/log.c +msgid "show source" +msgstr "foinse taispeáin" + +#: builtin/log.c +msgid "clear all previously-defined decoration filters" +msgstr "glan na scagairà maisiúcháin atá sainmhÃnithe roimhe seo" + +#: builtin/log.c +msgid "only decorate refs that match <pattern>" +msgstr "nà mhaisigh ach na cinn a mheaitseálann <pattern>" + +#: builtin/log.c +msgid "do not decorate refs that match <pattern>" +msgstr "ná maisigh na cinn a mheaitseálann <pattern>" + +#: builtin/log.c +msgid "decorate options" +msgstr "roghanna maisiú" + +#: builtin/log.c +msgid "" +"trace the evolution of line range <start>,<end> or function :<funcname> in " +"<file>" +msgstr "éabhlóid raon lÃne<start>, <end>nó feidhm <funcname>a rianú: i <file>" + +#: builtin/log.c +msgid "-L<range>:<file> cannot be used with pathspec" +msgstr "-L<range>: nà <file>féidir é a úsáid le pathspec" + +#: builtin/log.c +#, c-format +msgid "Final output: %d %s\n" +msgstr "Aschur deiridh: %d %s\n" + +#: builtin/log.c +#, c-format +msgid "git show %s: bad file" +msgstr "git show %s: droch-chomhad" + +#: builtin/log.c +#, c-format +msgid "could not read object %s" +msgstr "nà raibh in ann réad %s a léamh" + +#: builtin/log.c +#, c-format +msgid "unknown type: %d" +msgstr "cineál anaithnid: %d" + +#: builtin/log.c +#, c-format +msgid "%s: invalid cover from description mode" +msgstr "%s: clúdach neamhbhailà ó mhodh tuairisc" + +#: builtin/log.c +msgid "format.headers without value" +msgstr "format.headers gan luach" + +#: builtin/log.c +#, c-format +msgid "cannot open patch file %s" +msgstr "nà féidir comhad paiste %s a oscailt" + +#: builtin/log.c +msgid "need exactly one range" +msgstr "teastaÃonn raon amháin dÃreach" + +#: builtin/log.c +msgid "not a range" +msgstr "nà raon" + +#: builtin/log.c +#, c-format +msgid "unable to read branch description file '%s'" +msgstr "nach féidir an comhad tuairisc brainse '%s' a léamh" + +#: builtin/log.c +msgid "cover letter needs email format" +msgstr "teastaÃonn formáid rÃomhphoist ó litir" + +#: builtin/log.c +msgid "failed to create cover-letter file" +msgstr "theip ar chomhad litir chlúdaigh a chruthú" + +#: builtin/log.c +#, c-format +msgid "insane in-reply-to: %s" +msgstr "in-fhreagairt daingniúil: %s" + +#: builtin/log.c +msgid "git format-patch [<options>] [<since> | <revision-range>]" +msgstr "git format-patch [<roghanna>] [<ó> | <raon-athbhreithnithe>]" + +#: builtin/log.c +msgid "two output directories?" +msgstr "dhá eolaire aschuir?" + +#: builtin/log.c +#, c-format +msgid "unknown commit %s" +msgstr "tiomantas anaithnid %s" + +#: builtin/log.c builtin/replace.c +#, c-format +msgid "failed to resolve '%s' as a valid ref" +msgstr "theip ar '%s' a réiteach mar thagartha bailÃ" + +#: builtin/log.c +msgid "could not find exact merge base" +msgstr "nà fhéadfaà bonn cumaisc cruinn a fháil" + +#: builtin/log.c +msgid "" +"failed to get upstream, if you want to record base commit automatically,\n" +"please use git branch --set-upstream-to to track a remote branch.\n" +"Or you could specify base commit by --base=<base-commit-id> manually" +msgstr "" +"theip ar an dul suas sruth, más mian leat an gealltanas bonn a thaifeadadh " +"go huathoibrÃoch,\n" +"bain úsáid as git branch --set-upstream-to chun brainse iargúlta a rianú.\n" +"Nó d'fhéadfá an gealltanas bonn a shonrú trà --base=<base-commit-id> de láimh" + +#: builtin/log.c +msgid "failed to find exact merge base" +msgstr "theip orthu bonn cumaisc cruinn a fháil" + +#: builtin/log.c +msgid "base commit should be the ancestor of revision list" +msgstr "ba cheart gurb é bonn tiomantas ina sinsear an liosta athbhrei" + +#: builtin/log.c +msgid "base commit shouldn't be in revision list" +msgstr "nÃor cheart go mbeadh tiomantas bonn sa liosta athbhrei" + +#: builtin/log.c +msgid "cannot get patch id" +msgstr "nà féidir id paiste a fháil" + +#: builtin/log.c +msgid "failed to infer range-diff origin of current series" +msgstr "theip ar thionscnamh raon difriúil na sraithe reatha a thabhairt amach" + +#: builtin/log.c +#, c-format +msgid "using '%s' as range-diff origin of current series" +msgstr "ag baint úsáide as '%s' mar bhunús diff raon na sraithe reatha" + +#: builtin/log.c +msgid "use [PATCH n/m] even with a single patch" +msgstr "bain úsáid as [PATCH n/m] fiú le paiste amháin" + +#: builtin/log.c +msgid "use [PATCH] even with multiple patches" +msgstr "bain úsáid as [PATCH] fiú le paistà iolracha" + +#: builtin/log.c +msgid "print patches to standard out" +msgstr "paistà a phriontáil chun caighdeánach" + +#: builtin/log.c +msgid "generate a cover letter" +msgstr "litir chlúdaigh a ghiniúint" + +#: builtin/log.c +msgid "use simple number sequence for output file names" +msgstr "úsáid seicheamh uimhreacha simplà d'ainmneacha comhaid aschu" + +#: builtin/log.c +msgid "sfx" +msgstr "sfx" + +#: builtin/log.c +msgid "use <sfx> instead of '.patch'" +msgstr "úsáid <sfx>in ionad '.patch'" + +#: builtin/log.c +msgid "start numbering patches at <n> instead of 1" +msgstr "tosú ag uimhriú paistà ag <n>seachas 1" + +#: builtin/log.c +msgid "reroll-count" +msgstr "comhaireamh ath-rollta" + +#: builtin/log.c +msgid "mark the series as Nth re-roll" +msgstr "marcáil an tsraith mar Nú ath-rolla" + +#: builtin/log.c +msgid "max length of output filename" +msgstr "fad uasta ainm an chomhaid aschuir" + +#: builtin/log.c +msgid "rfc" +msgstr "rfc" + +#: builtin/log.c +msgid "add <rfc> (default 'RFC') before 'PATCH'" +msgstr "cuir <rfc>(réamhshocraithe 'RFC') roimh 'PATCH'" + +#: builtin/log.c +msgid "cover-from-description-mode" +msgstr "modh clúdaigh ó-tuairiscrÃbhinnÃ" + +#: builtin/log.c +msgid "generate parts of a cover letter based on a branch's description" +msgstr "codanna de litir chlúdaigh a ghiniúint bunaithe ar thuairisc brainse" + +#: builtin/log.c +msgid "use branch description from file" +msgstr "úsáid cur sÃos brainse ón gcomhad" + +#: builtin/log.c +msgid "use [<prefix>] instead of [PATCH]" +msgstr "úsáid [<prefix>] in ionad [PATCH]" + +#: builtin/log.c +msgid "store resulting files in <dir>" +msgstr "comhaid mar thoradh air a stóráil i <dir>" + +#: builtin/log.c +msgid "don't strip/add [PATCH]" +msgstr "ná stiall/cuir [PATCH] leis" + +#: builtin/log.c +msgid "don't output binary diffs" +msgstr "ná aschur difrÃochtaà dénártha" + +#: builtin/log.c +msgid "output all-zero hash in From header" +msgstr "aschur hash uile-nialas i Ó cheanntásc" + +#: builtin/log.c +msgid "don't include a patch matching a commit upstream" +msgstr "ná cuir paiste a mheaitseann le tiomantas suas an sruth" + +#: builtin/log.c +msgid "show patch format instead of default (patch + stat)" +msgstr "taispeáin formáid paiste in ionad réamhshocraithe (paiste + stat)" + +#: builtin/log.c +msgid "Messaging" +msgstr "TeachtaireachtaÃ" + +#: builtin/log.c +msgid "header" +msgstr "ceanntásc" + +#: builtin/log.c +msgid "add email header" +msgstr "ceanntásc rÃomhphoist leis" + +#: builtin/log.c +msgid "email" +msgstr "rÃomhphost" + +#: builtin/log.c +msgid "add To: header" +msgstr "cuir Le: ceanntásc" + +#: builtin/log.c +msgid "add Cc: header" +msgstr "cuir Cc leis: ceanntásc" + +#: builtin/log.c +msgid "ident" +msgstr "idirghnÃomhaire" + +#: builtin/log.c +msgid "set From address to <ident> (or committer ident if absent)" +msgstr "" +"socraigh Ó sheoladh go dtà <ident>(nó aitheantas an tiomantais mura bhfuil " +"sé ann)" + +#: builtin/log.c +msgid "message-id" +msgstr "id teachtaireachta" + +#: builtin/log.c +msgid "make first mail a reply to <message-id>" +msgstr "déan freagra ar an gcéad phost <message-id>" + +#: builtin/log.c +msgid "boundary" +msgstr "teorainn" + +#: builtin/log.c +msgid "attach the patch" +msgstr "ceangail an paiste" + +#: builtin/log.c +msgid "inline the patch" +msgstr "inlÃne an paiste" + +#: builtin/log.c +msgid "enable message threading, styles: shallow, deep" +msgstr "cumasú snáithe teachtaireachta, stÃleanna: éadomhain, domhain" + +#: builtin/log.c +msgid "signature" +msgstr "sÃniú" + +#: builtin/log.c +msgid "add a signature" +msgstr "cuir sÃniú" + +#: builtin/log.c +msgid "base-commit" +msgstr "bun-tiomantas" + +#: builtin/log.c +msgid "add prerequisite tree info to the patch series" +msgstr "cuir faisnéis rainn réamhriachtanais leis an tsraith paiste" + +#: builtin/log.c +msgid "add a signature from a file" +msgstr "cuir sÃniú ó chomhad" + +#: builtin/log.c +msgid "don't print the patch filenames" +msgstr "ná priontáil na hainmneacha comhaid paiste" + +#: builtin/log.c +msgid "show progress while generating patches" +msgstr "dul chun cinn a thaispeáint agus paistÃ" + +#: builtin/log.c +msgid "show changes against <rev> in cover letter or single patch" +msgstr "athruithe a thaispeá <rev>int i gcoinne i litir chlúdaigh nó" + +#: builtin/log.c +msgid "show changes against <refspec> in cover letter or single patch" +msgstr "athruithe a thaispeá <refspec>int i gcoinne i litir chlúdaigh nó" + +#: builtin/log.c builtin/range-diff.c +msgid "percentage by which creation is weighted" +msgstr "céatadán faoina n-ualaÃtear an cruthú" + +#: builtin/log.c +msgid "show in-body From: even if identical to the e-mail header" +msgstr "" +"taispeáin in-chorp Ó: fiú más comhionann leis an gceannteideal rÃomhphoist" + +#: builtin/log.c +#, c-format +msgid "invalid ident line: %s" +msgstr "lÃne aitheantais neamhbhailÃ: %s" + +#: builtin/log.c +msgid "--name-only does not make sense" +msgstr "Nà bhÃonn ciall ag --name-only" + +#: builtin/log.c +msgid "--name-status does not make sense" +msgstr "Nà bhÃonn ciall ag --name-status" + +#: builtin/log.c +msgid "--check does not make sense" +msgstr "Nà bhÃonn ciall ag --check" + +#: builtin/log.c +msgid "--remerge-diff does not make sense" +msgstr "Nà bhÃonn ciall ag --remerge-diff" + +#: builtin/log.c builtin/submodule--helper.c rerere.c submodule.c +#, c-format +msgid "could not create directory '%s'" +msgstr "nà fhéadfaà eolaire '%s' a chruthú" + +#: builtin/log.c +msgid "--interdiff requires --cover-letter or single patch" +msgstr "éilÃonn --interdiff --cover-letter nó paiste singil" + +#: builtin/log.c +msgid "Interdiff:" +msgstr "Interdiff:" + +#: builtin/log.c +#, c-format +msgid "Interdiff against v%d:" +msgstr "Interdiff i gcoinne v%d:" + +#: builtin/log.c +msgid "--range-diff requires --cover-letter or single patch" +msgstr "ÉilÃonn --range-diff --cover-letter nó paiste aonair" + +#: builtin/log.c +msgid "Range-diff:" +msgstr "DifrÃocht raon:" + +#: builtin/log.c +#, c-format +msgid "Range-diff against v%d:" +msgstr "DifrÃocht raon i gcoinne v%d:" + +#: builtin/log.c +#, c-format +msgid "unable to read signature file '%s'" +msgstr "nach féidir an comhad sÃnithe '%s' a léamh" + +#: builtin/log.c +msgid "Generating patches" +msgstr "Giniúint paistÃ" + +#: builtin/log.c +msgid "failed to create output files" +msgstr "theip ar chomhaid aschuir a chruthú" + +#: builtin/log.c +msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]" +msgstr "git cherry [-v] [<upstream> [<head> [<limit>]]]" + +#: builtin/log.c +#, c-format +msgid "" +"Could not find a tracked remote branch, please specify <upstream> manually.\n" +msgstr "" +"NÃor féidir brainse iargúlta rianaithe a fháil, sonraigh de láimh le do th " +"<upstream>oil.\n" + +#: builtin/ls-files.c builtin/ls-tree.c +#, c-format +msgid "could not get object info about '%s'" +msgstr "nà fhéadfaà faisnéis réada a fháil faoi '%s'" + +#: builtin/ls-files.c +msgid "git ls-files [<options>] [<file>...]" +msgstr "git ls-files [<options>] [<file>...]" + +#: builtin/ls-files.c builtin/merge-tree.c +msgid "separate paths with the NUL character" +msgstr "cosáin ar leithligh leis an carachtar NUL" + +#: builtin/ls-files.c +msgid "identify the file status with tags" +msgstr "stádas an chomhaid a aithint le clibeanna" + +#: builtin/ls-files.c +msgid "use lowercase letters for 'assume unchanged' files" +msgstr "" +"bain úsáid as litreacha beaga le haghaidh comhaid 'glacadh leis gan " +"athraithe'" + +#: builtin/ls-files.c +msgid "use lowercase letters for 'fsmonitor clean' files" +msgstr "bain úsáid as litreacha beaga le haghaidh comhaid 'fsmonitor clean'" + +#: builtin/ls-files.c +msgid "show cached files in the output (default)" +msgstr "taispeáint comhaid taispeána san aschur (réamhshocraithe)" + +#: builtin/ls-files.c +msgid "show deleted files in the output" +msgstr "taispeáint comhaid scriosta san aschur" + +#: builtin/ls-files.c +msgid "show modified files in the output" +msgstr "taispeáint comhaid modhnaithe san aschur" + +#: builtin/ls-files.c +msgid "show other files in the output" +msgstr "taispeáint comhaid eile san aschur" + +#: builtin/ls-files.c +msgid "show ignored files in the output" +msgstr "taispeáint comhaid a neamhaird san aschur" + +#: builtin/ls-files.c +msgid "show staged contents' object name in the output" +msgstr "taispeáin ainm réad ábhair stáitseáilte san aschur" + +#: builtin/ls-files.c +msgid "show files on the filesystem that need to be removed" +msgstr "taispeáint comhaid ar an gcóras comhaid is gá a bhaint" + +#: builtin/ls-files.c +msgid "show 'other' directories' names only" +msgstr "taispeáin ainmneacha 'eile' amháin" + +#: builtin/ls-files.c +msgid "show line endings of files" +msgstr "taispeáint deireadh lÃne na gcomhaid" + +#: builtin/ls-files.c +msgid "don't show empty directories" +msgstr "ná taispeáin eolairà folamh" + +#: builtin/ls-files.c +msgid "show unmerged files in the output" +msgstr "taispeáint comhaid neamh-chumhdaithe san aschur" + +#: builtin/ls-files.c +msgid "show resolve-undo information" +msgstr "taispeáin faisnéis réitigh a chealú" + +#: builtin/ls-files.c +msgid "skip files matching pattern" +msgstr "patrún meaitseála comhaid scipeála" + +#: builtin/ls-files.c +msgid "read exclude patterns from <file>" +msgstr "léigh patrúin eisiamh ó <file>" + +#: builtin/ls-files.c +msgid "read additional per-directory exclude patterns in <file>" +msgstr "léigh patrúin breise in aghaidh eolaire a eisiamh i <file>" + +#: builtin/ls-files.c +msgid "add the standard git exclusions" +msgstr "cuir na heisiaimh caighdeánacha git" + +#: builtin/ls-files.c +msgid "make the output relative to the project top directory" +msgstr "déan an t-aschur i gcoibhneas le barr-eolaire an tion" + +#: builtin/ls-files.c +msgid "if any <file> is not in the index, treat this as an error" +msgstr "" +"mura <file>bhfuil aon cheann san innéacs, déileáil leis seo mar earráid" + +#: builtin/ls-files.c builtin/merge-tree.c +msgid "tree-ish" +msgstr "crainn" + +#: builtin/ls-files.c +msgid "pretend that paths removed since <tree-ish> are still present" +msgstr "ligean go bhfuil cosáin a bhain <tree-ish>tear ó shin fós i láthair" + +#: builtin/ls-files.c +msgid "show debugging data" +msgstr "taispeáin sonraà dÃfhabhtaithe" + +#: builtin/ls-files.c +msgid "suppress duplicate entries" +msgstr "iontrálacha dúbailte a chur" + +#: builtin/ls-files.c +msgid "show sparse directories in the presence of a sparse index" +msgstr "taispeáint eolairà neamhchoitianta i láthair innéacs neamhchoitianta" + +#: builtin/ls-files.c +msgid "" +"--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, " +"--eol" +msgstr "" +"Nà féidir --format a úsáid le -s, -o, -k, -t, --resolve-undo, --deduplicate, " +"--eol" + +#: builtin/ls-remote.c +msgid "" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" +" [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" +" [--symref] [<repository> [<patterns>...]]" +msgstr "" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=<exec>]\n" +" [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n" +" [--symref] [<repository> [<patterns>...]]" + +#: builtin/ls-remote.c +msgid "do not print remote URL" +msgstr "ná priontáil URL iargúlta" + +#: builtin/ls-remote.c builtin/rebase.c +msgid "exec" +msgstr "feidhmiúcháin" + +#: builtin/ls-remote.c +msgid "path of git-upload-pack on the remote host" +msgstr "cosán git-upload-pack ar an óstach cianda" + +#: builtin/ls-remote.c +msgid "limit to tags" +msgstr "teorainn le clibeanna" + +#: builtin/ls-remote.c +msgid "limit to branches" +msgstr "teorainn le brainsÃ" + +#: builtin/ls-remote.c builtin/show-ref.c +msgid "deprecated synonym for --branches" +msgstr "comhchiallach scoite do --branches" + +#: builtin/ls-remote.c +msgid "do not show peeled tags" +msgstr "ná taispeáin clibeanna scáilte" + +#: builtin/ls-remote.c +msgid "take url.<base>.insteadOf into account" +msgstr "glacadh url. <base>.insteadOf san áireamh" + +#: builtin/ls-remote.c +msgid "exit with exit code 2 if no matching refs are found" +msgstr "imeacht le cód imeachta 2 mura bhfaightear aon aifeanna meaitseála" + +#: builtin/ls-remote.c +msgid "show underlying ref in addition to the object pointed by it" +msgstr "taispeáint an tagairt bhunúsach i dteannta leis an réad a thug sé" + +#: builtin/ls-tree.c +msgid "git ls-tree [<options>] <tree-ish> [<path>...]" +msgstr "<path>git ls-tree [<options>] [...<tree-ish>]" + +#: builtin/ls-tree.c +msgid "only show trees" +msgstr "ach crainn a thaispeáint" + +#: builtin/ls-tree.c +msgid "recurse into subtrees" +msgstr "athshlánú isteach i bhfo-chrainn" + +#: builtin/ls-tree.c +msgid "show trees when recursing" +msgstr "crainn a thaispeáint agus tú ag athf" + +#: builtin/ls-tree.c +msgid "terminate entries with NUL byte" +msgstr "foirceannadh iontrálacha le bait NUL" + +#: builtin/ls-tree.c +msgid "include object size" +msgstr "méid an rud san áireamh" + +#: builtin/ls-tree.c +msgid "list only filenames" +msgstr "ainmneacha comhaid amháin a liostáil" + +#: builtin/ls-tree.c +msgid "list only objects" +msgstr "rudaà amháin a liostáil" + +#: builtin/ls-tree.c +msgid "use full path names" +msgstr "úsáid ainmneacha cosáin iomlána" + +#: builtin/ls-tree.c +msgid "list entire tree; not just current directory (implies --full-name)" +msgstr "" +"liostáil crann iomlán; nà hamháin eolaire reatha (tugann le tuiscint --full-" +"name)" + +#: builtin/ls-tree.c +msgid "--format can't be combined with other format-altering options" +msgstr "" +"Nà féidir --format a chomhcheangal le roghanna eile a athraÃonn formáidÃ" + +#. TRANSLATORS: keep <> in "<" mail ">" info. +#: builtin/mailinfo.c +msgid "git mailinfo [<options>] <msg> <patch> < mail >info" +msgstr "git mailinfo [<options>] <msg> <patch> < mail >info" + +#: builtin/mailinfo.c +msgid "keep subject" +msgstr "coinnigh ábhar" + +#: builtin/mailinfo.c +msgid "keep non patch brackets in subject" +msgstr "coinnigh lúibÃnà gan paiste san ábhar" + +#: builtin/mailinfo.c +msgid "copy Message-ID to the end of commit message" +msgstr "" +"cóipeáil ID teachtaireachtaà go dtà deireadh na teachtaireachta tiomanta" + +#: builtin/mailinfo.c +msgid "re-code metadata to i18n.commitEncoding" +msgstr "meiteashonraà a athchódú chuig i18N.CommitEncoding" + +#: builtin/mailinfo.c +msgid "disable charset re-coding of metadata" +msgstr "dÃchumasú ath-chódú charset meiteashonraÃ" + +#: builtin/mailinfo.c +msgid "encoding" +msgstr "ionchódú" + +#: builtin/mailinfo.c +msgid "re-code metadata to this encoding" +msgstr "athchódú meiteashonraà don ionchódú seo" + +#: builtin/mailinfo.c +msgid "use scissors" +msgstr "siosúr a úsáid" + +#: builtin/mailinfo.c +msgid "<action>" +msgstr "<action>" + +#: builtin/mailinfo.c +msgid "action when quoted CR is found" +msgstr "gnÃomh nuair a aimsÃtear CR a luaitear" + +#: builtin/mailinfo.c +msgid "use headers in message's body" +msgstr "ceanntásca a úsáid i gcorp na teachtaireachta" + +#: builtin/mailsplit.c +msgid "reading patches from stdin/tty..." +msgstr "paistà a léamh ó stdin/tty..." + +#: builtin/mailsplit.c +#, c-format +msgid "empty mbox: '%s'" +msgstr "mbox folamh: '%s'" + +#: builtin/merge-base.c +msgid "git merge-base [-a | --all] <commit> <commit>..." +msgstr "git merge-base [-a | --all] <commit> <commit>..." + +#: builtin/merge-base.c +msgid "git merge-base [-a | --all] --octopus <commit>..." +msgstr "git merge-base [-a | --all] --octopus <commit>..." + +#: builtin/merge-base.c +msgid "git merge-base --is-ancestor <commit> <commit>" +msgstr "git merge-base --is-ancestor <commit> <commit>" + +#: builtin/merge-base.c +msgid "git merge-base --independent <commit>..." +msgstr "git merge-base --independent <commit>..." + +#: builtin/merge-base.c +msgid "git merge-base --fork-point <ref> [<commit>]" +msgstr "git merge-base --fork-point <ref> [<commit>]" + +#: builtin/merge-base.c +msgid "output all common ancestors" +msgstr "aschur gach sinsear coitianta" + +#: builtin/merge-base.c +msgid "find ancestors for a single n-way merge" +msgstr "aimsigh sinsear le haghaidh cumasc n-bhealach amháin" + +#: builtin/merge-base.c +msgid "list revs not reachable from others" +msgstr "liosta revs nach féidir teacht ó dhaoine eile" + +#: builtin/merge-base.c +msgid "is the first one ancestor of the other?" +msgstr "an é an chéad sinsear amháin den duine eile?" + +#: builtin/merge-base.c +msgid "find where <commit> forked from reflog of <ref>" +msgstr "faigh cén áit a <commit> bhforcáladh ó athbhreithniú <ref>" + +#: builtin/merge-file.c +msgid "" +"git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> " +"<orig-file> <file2>" +msgstr "" +"git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> " +"<orig-file> <file2>" + +#: builtin/merge-file.c diff.c +msgid "" +"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and " +"\"histogram\"" +msgstr "" +"glacann difr-algartam rogha le “myersâ€, “Ãostaâ€, “foighne†agus “histogramâ€" + +#: builtin/merge-file.c +msgid "send results to standard output" +msgstr "torthaà a sheoladh chuig aschur caigh" + +#: builtin/merge-file.c +msgid "use object IDs instead of filenames" +msgstr "úsáid ID réad in ionad ainmneacha comhaid" + +#: builtin/merge-file.c +msgid "use a diff3 based merge" +msgstr "bain úsáid as cumaisc atá bunaithe ar diff3" + +#: builtin/merge-file.c +msgid "use a zealous diff3 based merge" +msgstr "bain úsáid as cumaisc dÃograiseach bunaithe ar diff3" + +#: builtin/merge-file.c diff.c +msgid "<algorithm>" +msgstr "<algorithm>" + +#: builtin/merge-file.c diff.c +msgid "choose a diff algorithm" +msgstr "roghnaigh algartam diff" + +#: builtin/merge-file.c +msgid "for conflicts, use this marker size" +msgstr "le haghaidh coinbhleachtaÃ, bain úsáid as an méid marcóra" + +#: builtin/merge-file.c +msgid "do not warn about conflicts" +msgstr "ná tabhair rabhadh faoi choimhlintÃ" + +#: builtin/merge-file.c +msgid "set labels for file1/orig-file/file2" +msgstr "lipéid a shocrú le haghaidh comhad1/orig-file/file2" + +#: builtin/merge-file.c +#, c-format +msgid "object '%s' does not exist" +msgstr "nÃl réad '%s' ann" + +#: builtin/merge-file.c +msgid "Could not write object file" +msgstr "Nà fhéadfaà comhad réad a scrÃobh" + +#: builtin/merge-recursive.c +#, c-format +msgid "unknown option %s" +msgstr "rogha anaithnid %s" + +#: builtin/merge-recursive.c +#, c-format +msgid "could not parse object '%s'" +msgstr "nà fhéadfaà réad '%s' a pháirseáil" + +#: builtin/merge-recursive.c +#, c-format +msgid "cannot handle more than %d base. Ignoring %s." +msgid_plural "cannot handle more than %d bases. Ignoring %s." +msgstr[0] "nà féidir nÃos mó ná %d bonn a láimhseáil. Ag neamhaird de %s." +msgstr[1] "nà féidir nÃos mó ná %d bonn a láimhseáil. Ag neamhaird de %s." +msgstr[2] "nà féidir nÃos mó ná %d bonn a láimhseáil. Ag neamhaird de %s." + +#: builtin/merge-recursive.c +msgid "not handling anything other than two heads merge." +msgstr "gan láimhseáil aon rud seachas dhá cheann a chumasc." + +#: builtin/merge-recursive.c +#, c-format +msgid "could not resolve ref '%s'" +msgstr "nà fhéadfaà tagairt '%s' a réiteach" + +#: builtin/merge-recursive.c +#, c-format +msgid "Merging %s with %s\n" +msgstr "Cumasc %s le %s\n" + +#: builtin/merge-tree.c +#, c-format +msgid "could not parse as tree '%s'" +msgstr "nà fhéadfaà parsáil mar chrann '%s'" + +#: builtin/merge-tree.c builtin/merge.c +msgid "not something we can merge" +msgstr "nà rud is féidir linn a chumasc" + +#: builtin/merge-tree.c builtin/merge.c +msgid "refusing to merge unrelated histories" +msgstr "diúltú stair neamhghaolmhara a chumasc" + +#: builtin/merge-tree.c +msgid "failure to merge" +msgstr "teip a chumasc" + +#: builtin/merge-tree.c +msgid "git merge-tree [--write-tree] [<options>] <branch1> <branch2>" +msgstr "git merge-tree [--write-tree] [<options>] <branch1> <branch2>" + +#: builtin/merge-tree.c +msgid "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>" +msgstr "git merge-tree [--trivial-cumaisc] <base-tree><branch1><branch2>" + +#: builtin/merge-tree.c +msgid "do a real merge instead of a trivial merge" +msgstr "déan fÃor-chumasc in ionad cumaisc triobháideach" + +#: builtin/merge-tree.c +msgid "do a trivial merge only" +msgstr "déan cumaisc thréimhseach amháin" + +#: builtin/merge-tree.c +msgid "also show informational/conflict messages" +msgstr "taispeáin teachtaireachtaà faisnéis/coinbhleachta freisin" + +#: builtin/merge-tree.c +msgid "suppress all output; only exit status wanted" +msgstr "cosc a chur ar an aschur go léir; nÃl uaim ach stádas scoir" + +#: builtin/merge-tree.c +msgid "list filenames without modes/oids/stages" +msgstr "ainmneacha comhaid a liostáil gan modhair/oids/céimeanna" + +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c +msgid "allow merging unrelated histories" +msgstr "ligean stair neamhghaolmhara a chumasc" + +#: builtin/merge-tree.c +msgid "perform multiple merges, one per line of input" +msgstr "cumaisc iolracha a dhéanamh, ceann in aghaidh an lÃne ionchuir" + +#: builtin/merge-tree.c +msgid "specify a merge-base for the merge" +msgstr "sonraigh bonn cumaisc don chumasc" + +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c +msgid "option=value" +msgstr "rogha = luach" + +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c +msgid "option for selected merge strategy" +msgstr "rogha do straitéis cumaisc roghnaithe" + +#: builtin/merge-tree.c +msgid "--trivial-merge is incompatible with all other options" +msgstr "Tá --trivial-merge neamhoiriúnach le gach rogha eile" + +#: builtin/merge-tree.c builtin/merge.c +#, c-format +msgid "unknown strategy option: -X%s" +msgstr "rogha straitéise anaithnid: -X%s" + +#: builtin/merge-tree.c builtin/notes.c +#, c-format +msgid "malformed input line: '%s'." +msgstr "lÃne ionchuir mÃfhoirmithe: '%s'." + +#: builtin/merge.c +msgid "git merge [<options>] [<commit>...]" +msgstr "git cumaisc [<options>] [<commit>...]" + +#: builtin/merge.c +msgid "switch `m' requires a value" +msgstr "teastaÃonn luach ag lasc `m'" + +#: builtin/merge.c +#, c-format +msgid "option `%s' requires a value" +msgstr "teastaÃonn luach ag rogha `%s'" + +#: builtin/merge.c +#, c-format +msgid "Could not find merge strategy '%s'.\n" +msgstr "NÃorbh fhéidir straitéis cumaisc '%s' a fháil.\n" + +#: builtin/merge.c +#, c-format +msgid "Available strategies are:" +msgstr "Is iad straitéisà atá ar fáil:" + +#: builtin/merge.c +#, c-format +msgid "Available custom strategies are:" +msgstr "Is iad seo a leanas na straitéisà saincheaptha atá ar fáil:" + +#: builtin/merge.c builtin/pull.c +msgid "do not show a diffstat at the end of the merge" +msgstr "ná taispeáin diffstat ag deireadh an chumaisc" + +#: builtin/merge.c builtin/pull.c +msgid "show a diffstat at the end of the merge" +msgstr "taispeáin diffstat ag deireadh an chumaisc" + +#: builtin/merge.c builtin/pull.c +msgid "(synonym to --stat)" +msgstr "(Comhchiallach le --stat)" + +#: builtin/merge.c builtin/pull.c +msgid "add (at most <n>) entries from shortlog to merge commit message" +msgstr "" +"cuir iontrálacha (ar a mh <n>éad) ó gearrlog chun teachtaireacht tiomanta a " +"chumasc" + +#: builtin/merge.c builtin/pull.c +msgid "create a single commit instead of doing a merge" +msgstr "tiomantas amháin a chruthú in ionad cumaisc a dhéanamh" + +#: builtin/merge.c builtin/pull.c +msgid "perform a commit if the merge succeeds (default)" +msgstr "tiomantas a dhéanamh má éireoidh leis an gcumasc (réamhshocraithe)" + +#: builtin/merge.c builtin/pull.c +msgid "edit message before committing" +msgstr "teachtaireacht in eagar sula ndéanann" + +#: builtin/merge.c +msgid "allow fast-forward (default)" +msgstr "ligean go tapa ar aghaidh (réamhshocraithe)" + +#: builtin/merge.c builtin/pull.c +msgid "abort if fast-forward is not possible" +msgstr "déan deireadh a chur ar aghaidh mura féidir go tapa ar aghaidh" + +#: builtin/merge.c builtin/pull.c +msgid "verify that the named commit has a valid GPG signature" +msgstr "fÃorú go bhfuil sÃniú bailà GPG ag an tiomantas ainmnithe" + +#: builtin/merge.c builtin/notes.c builtin/pull.c builtin/rebase.c +#: builtin/revert.c +msgid "strategy" +msgstr "straitéis" + +#: builtin/merge.c builtin/pull.c +msgid "merge strategy to use" +msgstr "straitéis a chumasc le húsáid" + +#: builtin/merge.c +msgid "merge commit message (for a non-fast-forward merge)" +msgstr "" +"teachtaireacht tiomanta a chumasc (le haghaidh cumaisc neamh-tapa ar aghaidh)" + +#: builtin/merge.c +msgid "use <name> instead of the real target" +msgstr "úsáid in <name>ionad an sprioc fÃor" + +#: builtin/merge.c +msgid "abort the current in-progress merge" +msgstr "deireadh a chur leis an gcumasc reatha atá ar siúl" + +#: builtin/merge.c +msgid "--abort but leave index and working tree alone" +msgstr "--abort ach fág an t-innéacs agus an crann oibre ina n-aonar" + +#: builtin/merge.c +msgid "continue the current in-progress merge" +msgstr "leanúint leis an gcumasc atá ar siúl reatha" + +#: builtin/merge.c +msgid "bypass pre-merge-commit and commit-msg hooks" +msgstr "seachbhóthar crúcaà réamh-chumaisc-tiomantas agus comh-msg" + +#: builtin/merge.c +msgid "could not run stash." +msgstr "nà fhéadfadh stash a reáchtáil." + +#: builtin/merge.c +msgid "stash failed" +msgstr "theip ar stash" + +#: builtin/merge.c +#, c-format +msgid "not a valid object: %s" +msgstr "nà réad bailÃ: %s" + +#: builtin/merge.c +msgid "read-tree failed" +msgstr "theip ar chrann léitheoireachta" + +#: builtin/merge.c +msgid "Already up to date. (nothing to squash)" +msgstr "Cothrom le dáta cheana féin. (rud ar bith le squash)" + +#: builtin/merge.c merge-ort-wrappers.c +msgid "Already up to date." +msgstr "Cothrom le dáta cheana féin." + +#: builtin/merge.c +#, c-format +msgid "Squash commit -- not updating HEAD\n" +msgstr "Tiomantas Squash - gan HEAD a nuashonrú\n" + +#: builtin/merge.c +#, c-format +msgid "No merge message -- not updating HEAD\n" +msgstr "Gan aon teachtaireacht cumaisc - gan HEAD a nuashonrú\n" + +#: builtin/merge.c +#, c-format +msgid "'%s' does not point to a commit" +msgstr "Nà thugann '%s' in iúl do thiomantas" + +#: builtin/merge.c +#, c-format +msgid "Bad branch.%s.mergeoptions string: %s" +msgstr "Drochbhrainse. %s.mergeoptions teaghrán: %s" + +#: builtin/merge.c merge-ort-wrappers.c +msgid "Unable to write index." +msgstr "Nà féidir innéacs a scrÃobh." + +#: builtin/merge.c +msgid "Not handling anything other than two heads merge." +msgstr "Gan aon rud a láimhseáil seachas dhá cheann cumasc." + +#: builtin/merge.c builtin/sparse-checkout.c +#, c-format +msgid "unable to write %s" +msgstr "nach féidir %s a scrÃobh" + +#: builtin/merge.c +#, c-format +msgid "Could not read from '%s'" +msgstr "Nà féidir léamh ó '%s'" + +#: builtin/merge.c +#, c-format +msgid "Not committing merge; use 'git commit' to complete the merge.\n" +msgstr "" +"Gan cumasc a dhéanamh; bain úsáid as 'git commit' chun an cumaisc a chur i " +"gcrÃch.\n" + +#: builtin/merge.c +msgid "" +"Please enter a commit message to explain why this merge is necessary,\n" +"especially if it merges an updated upstream into a topic branch.\n" +"\n" +msgstr "" +"Cuir isteach teachtaireacht tiomanta le do thoil chun a mhÃniú cén fáth go " +"bhfuil gá leis\n" +"go háirithe má chomhcheanglaÃonn sé nuashonraithe suas sruth i mbrainse " +"ábhair.\n" + +#: builtin/merge.c +msgid "An empty message aborts the commit.\n" +msgstr "Cuireann teachtaireacht fholamh deireadh leis an tiomantas.\n" + +#: builtin/merge.c +#, c-format +msgid "" +"Lines starting with '%s' will be ignored, and an empty message aborts\n" +"the commit.\n" +msgstr "" +"Déanfar neamhaird ar lÃnte a thosaÃonn le '%s', \n" +"agus cuirfidh teachtaireacht fholamh deireadh leis an tiomantas.\n" + +#: builtin/merge.c +msgid "Empty commit message." +msgstr "Teachtaireacht tiomanta folamh." + +#: builtin/merge.c +#, c-format +msgid "Wonderful.\n" +msgstr "Iontach.\n" + +#: builtin/merge.c +#, c-format +msgid "Automatic merge failed; fix conflicts and then commit the result.\n" +msgstr "" +"Theip ar chumasc uathoibrÃoch; coimhlintà a shocrú agus ansin an toradh\n" + +#: builtin/merge.c +msgid "No current branch." +msgstr "NÃl aon bhrainse reatha." + +#: builtin/merge.c +msgid "No remote for the current branch." +msgstr "NÃl aon iargúlta don bhrainse reatha." + +#: builtin/merge.c +msgid "No default upstream defined for the current branch." +msgstr "NÃl aon réamhshocraithe suas sruth sainithe don bhrainse reatha." + +#: builtin/merge.c +#, c-format +msgid "No remote-tracking branch for %s from %s" +msgstr "Gan aon bhrainse cianrianaithe do %s ó %s" + +#: builtin/merge.c +#, c-format +msgid "Bad value '%s' in environment '%s'" +msgstr "Drochluach '%s' sa timpeallacht '%s'" + +#: builtin/merge.c editor.c read-cache.c wrapper.c +#, c-format +msgid "could not close '%s'" +msgstr "nà fhéadfaà '%s' a dhúnadh" + +#: builtin/merge.c +#, c-format +msgid "not something we can merge in %s: %s" +msgstr "nà rud is féidir linn a chumasc i %s: %s" + +#: builtin/merge.c +msgid "--abort expects no arguments" +msgstr "--abort ag súil nach bhfuil aon argóintÃ" + +#: builtin/merge.c +msgid "There is no merge to abort (MERGE_HEAD missing)." +msgstr "NÃl aon chumasc ann chun deireadh a chur (MERGE_HEAD ar iarraidh)." + +#: builtin/merge.c +msgid "--quit expects no arguments" +msgstr "Tá --quit ag súil nach bhfuil aon argóintÃ" + +#: builtin/merge.c +msgid "--continue expects no arguments" +msgstr "--continue gan aon argóintà ag súil leo" + +#: builtin/merge.c +msgid "There is no merge in progress (MERGE_HEAD missing)." +msgstr "NÃl aon chumasc ar siúl (MERGE_HEAD ar iarraidh)." + +#: builtin/merge.c +msgid "" +"You have not concluded your merge (MERGE_HEAD exists).\n" +"Please, commit your changes before you merge." +msgstr "" +"NÃor thug tú do chumasc i gcrÃch (MERGE_HEAD ann).\n" +"Déan do chuid athruithe a dhéanamh sula ndéanann tú cumasc." + +#: builtin/merge.c +msgid "" +"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" +"Please, commit your changes before you merge." +msgstr "" +"NÃor thug tú do phiocadh silÃnà i gcrÃch (CHERRY_PICK_HEAD ann).\n" +"Déan do chuid athruithe a dhéanamh sula ndéanann tú cumasc." + +#: builtin/merge.c +msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)." +msgstr "NÃor thug tú do phiocadh silÃnà i gcrÃch (CHERRY_PICK_HEAD ann)." + +#: builtin/merge.c +msgid "No commit specified and merge.defaultToUpstream not set." +msgstr "" +"NÃl aon tiomantas sonraithe agus nÃl merge.defaultToUpstream socraithe." + +#: builtin/merge.c +msgid "Squash commit into empty head not supported yet" +msgstr "Tiomann squash isteach i gceann folamh nach dtacaÃtear go fóill" + +#: builtin/merge.c +msgid "Non-fast-forward commit does not make sense into an empty head" +msgstr "NÃl ciall ar thiomantas neamh-thapa ar aghaidh i gceann folamh" + +#: builtin/merge.c +#, c-format +msgid "%s - not something we can merge" +msgstr "%s - nà rud is féidir linn a chumasc" + +#: builtin/merge.c +msgid "Can merge only exactly one commit into empty head" +msgstr "Nà féidir ach tiomantas amháin a chumasc i gceann folamh" + +#: builtin/merge.c +#, c-format +msgid "Updating %s..%s\n" +msgstr "Ag nuashonrú %s..%s\n" + +#: builtin/merge.c merge-ort-wrappers.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by merge:\n" +" %s" +msgstr "" +"Déanfaà d'athruithe áitiúla ar na comhaid seo a leanas a fhorscrÃobh trà " +"chumasc:\n" +" %s" + +#: builtin/merge.c +#, c-format +msgid "Trying really trivial in-index merge...\n" +msgstr "Ag triail a dhéanamh cumasc in-innéacs fÃor-thrá\n" + +#: builtin/merge.c +#, c-format +msgid "Nope.\n" +msgstr "Nà hea..\n" + +#: builtin/merge.c +#, c-format +msgid "Rewinding the tree to pristine...\n" +msgstr "Ag athchasadh an chrainn go dtà go mbeidh sé foirfe...\n" + +#: builtin/merge.c +#, c-format +msgid "Trying merge strategy %s...\n" +msgstr "Ag iarraidh straitéis cumaisc %s...\n" + +#: builtin/merge.c +#, c-format +msgid "No merge strategy handled the merge.\n" +msgstr "NÃor láimhseáil aon straitéis chumaisc an cumasc.\n" + +#: builtin/merge.c +#, c-format +msgid "Merge with strategy %s failed.\n" +msgstr "Theip ar chumasc le straitéis %s.\n" + +#: builtin/merge.c +#, c-format +msgid "Using the %s strategy to prepare resolving by hand.\n" +msgstr "Ag baint úsáide as straitéis %s chun réiteach a ullmhú de láimh.\n" + +#: builtin/merge.c +#, c-format +msgid "Automatic merge went well; stopped before committing as requested\n" +msgstr "Chuaigh cumaisc uathoibrÃoch go maith; stad sula ndearna sé tiomanta\n" + +#: builtin/merge.c +#, c-format +msgid "When finished, apply stashed changes with `git stash pop`\n" +msgstr "" +"Nuair a bheidh crÃochnaithe, cuir athruithe stashed i bhfeidhm le `git stash " +"pop`\n" + +#: builtin/mktag.c +#, c-format +msgid "warning: tag input does not pass fsck: %s" +msgstr "rabhadh: nà théann ionchur clib ar fsck: %s" + +#: builtin/mktag.c +#, c-format +msgid "error: tag input does not pass fsck: %s" +msgstr "earráid: nà théann ionchur clib ar fsck: %s" + +#: builtin/mktag.c +#, c-format +msgid "%d (FSCK_IGNORE?) should never trigger this callback" +msgstr "%d (FSCK_IGNORE?) nÃor cheart go spreagfadh an t-aisghlaoch seo" + +#: builtin/mktag.c +#, c-format +msgid "could not read tagged object '%s'" +msgstr "nà fhéadfaà réad clibeáilte '%s' a léamh" + +#: builtin/mktag.c +#, c-format +msgid "object '%s' tagged as '%s', but is a '%s' type" +msgstr "réad '%s' clibeáilte mar '%s', ach is cineál '%s' é" + +#: builtin/mktag.c +msgid "tag on stdin did not pass our strict fsck check" +msgstr "nÃor rith tag ar stdin ár seiceáil dhian fsck" + +#: builtin/mktag.c +msgid "tag on stdin did not refer to a valid object" +msgstr "nÃor thagraigh an chlib ar stdin do réad bailÃ" + +#: builtin/mktag.c builtin/tag.c +msgid "unable to write tag file" +msgstr "in ann comhad clib a scrÃobh" + +#: builtin/mktree.c +msgid "input is NUL terminated" +msgstr "cuirtear deireadh le hionchur NUL" + +#: builtin/mktree.c builtin/write-tree.c +msgid "allow missing objects" +msgstr "cead a cheadú rudaÃ" + +#: builtin/mktree.c +msgid "allow creation of more than one tree" +msgstr "cead nÃos mó ná crann amháin a chruthú" + +#: builtin/multi-pack-index.c +msgid "" +"git multi-pack-index [<options>] write [--preferred-pack=<pack>][--refs-" +"snapshot=<path>]" +msgstr "" +"git multi-pack-index [<options>] write [--preferred-pack=<pack>][--refs-" +"snapshot=<path>]" + +#: builtin/multi-pack-index.c +msgid "git multi-pack-index [<options>] verify" +msgstr "git multi-pack-index [<options>] verify" + +#: builtin/multi-pack-index.c +msgid "git multi-pack-index [<options>] expire" +msgstr "git multi-pack-index [<options>] expire" + +#: builtin/multi-pack-index.c +msgid "git multi-pack-index [<options>] repack [--batch-size=<size>]" +msgstr "git multi-pack-index [<options>] repack [--batch-size=<size>]" + +#: builtin/multi-pack-index.c +msgid "directory" +msgstr "eolaire" + +#: builtin/multi-pack-index.c +msgid "object directory containing set of packfile and pack-index pairs" +msgstr "" +"eolaire réada ina bhfuil tacar de phéirà pacáiste agus innéacs pacáiste" + +#: builtin/multi-pack-index.c +msgid "preferred-pack" +msgstr "pacáiste is fearr leat" + +#: builtin/multi-pack-index.c +msgid "pack for reuse when computing a multi-pack bitmap" +msgstr "pacáiste le húsáid agus bitmap il-phacáiste á rÃomh" + +#: builtin/multi-pack-index.c +msgid "write multi-pack bitmap" +msgstr "scrÃobh bitmap il-phacáiste" + +#: builtin/multi-pack-index.c +msgid "write a new incremental MIDX" +msgstr "scrÃobh MIDX incrementach nua" + +#: builtin/multi-pack-index.c +msgid "write multi-pack index containing only given indexes" +msgstr "scrÃobh innéacs il-phacáiste nach bhfuil ach innéacsanna ar leith" + +#: builtin/multi-pack-index.c +msgid "refs snapshot for selecting bitmap commits" +msgstr "léargas refs chun gealltanais bitmap a roghnú" + +#: builtin/multi-pack-index.c +msgid "" +"during repack, collect pack-files of smaller size into a batch that is " +"larger than this size" +msgstr "" +"le linn athphacáil, bailigh comhaid pacáiste de mhéid nÃos lú i mbaisc atá " +"nÃos mó ná an méid seo" + +#: builtin/mv.c +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <source><destination>" + +#: builtin/mv.c +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "<source>git mv [-v] [-f] [-n] [-k]... <destination-directory>" + +#: builtin/mv.c +#, c-format +msgid "Directory %s is in index and no submodule?" +msgstr "Tá eolaire %s in innéacs agus nÃl aon fho-mhodúl ann?" + +#: builtin/mv.c +msgid "Please stage your changes to .gitmodules or stash them to proceed" +msgstr "" +"Cuir do chuid athruithe ar .gitmodules nó iad a stóráil chun dul ar aghaidh" + +#: builtin/mv.c +#, c-format +msgid "%.*s is in index" +msgstr "%.*s atá san innéacs" + +#: builtin/mv.c +msgid "force move/rename even if target exists" +msgstr "aistriúin/athainmniú a fhorbairt fiú má tá sprioc ann" + +#: builtin/mv.c +msgid "skip move/rename errors" +msgstr "scipeáil earráidà a bhogadh/athainmniú" + +#: builtin/mv.c +#, c-format +msgid "destination '%s' is not a directory" +msgstr "nà eolaire é ceann scrÃbe '%s'" + +#: builtin/mv.c +#, c-format +msgid "Checking rename of '%s' to '%s'\n" +msgstr "Seiceáil athainmniú '%s' go '%s'\n" + +#: builtin/mv.c +msgid "bad source" +msgstr "droch-fhoinse" + +#: builtin/mv.c +msgid "destination exists" +msgstr "ceann scrÃbe ann" + +#: builtin/mv.c +msgid "can not move directory into itself" +msgstr "nà féidir eolaire a bhogadh isteach ina féin" + +#: builtin/mv.c +msgid "destination already exists" +msgstr "ceann scrÃbe ann cheana féin" + +#: builtin/mv.c +msgid "source directory is empty" +msgstr "tá eolaire foinse folamh" + +#: builtin/mv.c +msgid "not under version control" +msgstr "nach bhfuil faoi rialú leagan" + +#: builtin/mv.c +msgid "conflicted" +msgstr "coimhlinneach" + +#: builtin/mv.c +#, c-format +msgid "overwriting '%s'" +msgstr "athscrÃobh '%s'" + +#: builtin/mv.c +msgid "Cannot overwrite" +msgstr "Nà féidir athscrÃobh" + +#: builtin/mv.c +msgid "multiple sources for the same target" +msgstr "foinsà iolracha don sprioc chéanna" + +#: builtin/mv.c +msgid "destination directory does not exist" +msgstr "nÃl eolaire ceann scrÃbe ann" + +#: builtin/mv.c +msgid "destination exists in the index" +msgstr "ceann scrÃbe ann san innéacs" + +#: builtin/mv.c +#, c-format +msgid "%s, source=%s, destination=%s" +msgstr "%s, foinse = %s, ceann scrÃbe = %s" + +#: builtin/mv.c +#, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "nà féidir '%s' agus a eolaire tuismitheora '%s' a bhogadh" + +#: builtin/mv.c +#, c-format +msgid "Renaming %s to %s\n" +msgstr "Athainmniú %s go %s\n" + +#: builtin/mv.c builtin/remote.c +#, c-format +msgid "renaming '%s' failed" +msgstr "theip ar athainmniú '%s'" + +#: builtin/name-rev.c +msgid "git name-rev [<options>] <commit>..." +msgstr "git name-rev [<options>] <commit>..." + +#: builtin/name-rev.c +msgid "git name-rev [<options>] --all" +msgstr "git name-rev [<options>] --all" + +#: builtin/name-rev.c +msgid "git name-rev [<options>] --annotate-stdin" +msgstr "git name-rev [<options>] --annotate-stdin" + +#: builtin/name-rev.c +msgid "print only ref-based names (no object names)" +msgstr "ainmneacha ref-bhunaithe amháin a phriontáil (gan ainmneacha réada)" + +#: builtin/name-rev.c +msgid "only use tags to name the commits" +msgstr "nà húsáid ach clibeanna chun na gealltanais a ainmniú" + +#: builtin/name-rev.c +msgid "only use refs matching <pattern>" +msgstr "nà úsáideann ach meaitseáil refs <pattern>" + +#: builtin/name-rev.c +msgid "ignore refs matching <pattern>" +msgstr "neamhaird a dhéanamh ar mheaitseáil <pattern>" + +#: builtin/name-rev.c +msgid "list all commits reachable from all refs" +msgstr "liostáil na gealltanais go léir atá inrochtana ó gach ceann" + +#: builtin/name-rev.c +msgid "deprecated: use --annotate-stdin instead" +msgstr "dÃscrÃofa: bain úsáid as --annotate-stdin ina ionad" + +#: builtin/name-rev.c +msgid "annotate text from stdin" +msgstr "téacs a anótáil ó stdin" + +#: builtin/name-rev.c +msgid "allow to print `undefined` names (default)" +msgstr "" +"cead a thabhairt d'ainmneacha “neamhshainithe†a phriontáil (réamhshocrú" + +#: builtin/name-rev.c +msgid "dereference tags in the input (internal use)" +msgstr "clibeanna dereference san ionchur (úsáid inmheánach)" + +#: builtin/notes.c +msgid "git notes [--ref <notes-ref>] [list [<object>]]" +msgstr "git notes [--ref <notes-ref>] [list [<object>]]" + +#: builtin/notes.c +msgid "" +"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " +"| -C) <object>] [<object>] [-e]" +msgstr "" +"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " +"| -C) <object>] [<object>] [-e]" + +#: builtin/notes.c +msgid "git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>" +msgstr "git notes [--ref<notes-ref>] cóipeáil [-f] <from-object><to-object>" + +#: builtin/notes.c +msgid "" +"git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " +"| -C) <object>] [<object>] [-e]" +msgstr "" +"git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--" +"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c " +"| -C) <object>] [<object>] [-e]" + +#: builtin/notes.c +msgid "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]" +msgstr "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]" + +#: builtin/notes.c +msgid "git notes [--ref <notes-ref>] show [<object>]" +msgstr "git notes [--ref <notes-ref>] show [<object>]" + +#: builtin/notes.c +msgid "" +"git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>" +msgstr "" +"git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>" + +#: builtin/notes.c +msgid "git notes [--ref <notes-ref>] remove [<object>...]" +msgstr "git notes [--ref <notes-ref>] remove [<object>...]" + +#: builtin/notes.c +msgid "git notes [--ref <notes-ref>] prune [-n] [-v]" +msgstr "git notes [--ref <notes-ref>] prune [-n] [-v]" + +#: builtin/notes.c +msgid "git notes [--ref <notes-ref>] get-ref" +msgstr "git notes [--ref <notes-ref>] get-ref" + +#: builtin/notes.c +msgid "git notes [list [<object>]]" +msgstr "git notes [list [<object>]]" + +#: builtin/notes.c +msgid "git notes add [<options>] [<object>]" +msgstr "git notes add [<options>] [<object>]" + +#: builtin/notes.c +msgid "git notes copy [<options>] <from-object> <to-object>" +msgstr "git notes copy [<options>] <from-object> <to-object>" + +#: builtin/notes.c +msgid "git notes copy --stdin [<from-object> <to-object>]..." +msgstr "git notes copy --stdin [<from-object> <to-object>]..." + +#: builtin/notes.c +msgid "git notes append [<options>] [<object>]" +msgstr "git notes append [<options>] [<object>]" + +#: builtin/notes.c +msgid "git notes edit [<object>]" +msgstr "nótaà git a chur in eagar [<object>]" + +#: builtin/notes.c +msgid "git notes show [<object>]" +msgstr "taispeánann nótaà git [<object>]" + +#: builtin/notes.c +msgid "git notes merge [<options>] <notes-ref>" +msgstr "cumaisc nótaà git [<options>] <notes-ref>" + +#: builtin/notes.c +msgid "git notes merge --commit [<options>]" +msgstr "git notes merge --commit [<options>]" + +#: builtin/notes.c +msgid "git notes merge --abort [<options>]" +msgstr "git notes merge --abort [<options>]" + +#: builtin/notes.c +msgid "git notes remove [<object>]" +msgstr "git notes remove [<object>]" + +#: builtin/notes.c +msgid "git notes prune [<options>]" +msgstr "git notes prune [<options>]" + +#: builtin/notes.c +msgid "Write/edit the notes for the following object:" +msgstr "ScrÃobh/cuir in eagar na nótaà don réad seo a leanas:" + +#: builtin/notes.c +msgid "could not read 'show' output" +msgstr "nà raibh in ann aschur 'taispeáin' a léamh" + +#: builtin/notes.c +#, c-format +msgid "failed to finish 'show' for object '%s'" +msgstr "theip ar 'show' a chrÃochnú le haghaidh réad '%s'" + +#: builtin/notes.c +msgid "please supply the note contents using either -m or -F option" +msgstr "soláthar ábhar an nóta le do thoil ag baint úsáide as rogha -m nó -F" + +#: builtin/notes.c +msgid "unable to write note object" +msgstr "in ann réad nótaà a scrÃobh" + +#: builtin/notes.c +#, c-format +msgid "the note contents have been left in %s" +msgstr "tá ábhar an nóta fágtha i %s" + +#: builtin/notes.c builtin/tag.c +#, c-format +msgid "could not open or read '%s'" +msgstr "nà fhéadfaà '%s' a oscailt nó a léamh" + +#: builtin/notes.c +#, c-format +msgid "failed to resolve '%s' as a valid ref." +msgstr "theip ar '%s' a réiteach mar thagartha bailÃ." + +#: builtin/notes.c +#, c-format +msgid "failed to read object '%s'." +msgstr "theip ar réad '%s' a léamh." + +#: builtin/notes.c +#, c-format +msgid "cannot read note data from non-blob object '%s'." +msgstr "nà féidir sonraà nótaà a léamh ó réad neamh-blob '%s'." + +#: builtin/notes.c +#, c-format +msgid "failed to copy notes from '%s' to '%s'" +msgstr "theip ar nótaà a chóipeáil ó '%s' go '%s'" + +#. TRANSLATORS: the first %s will be replaced by a git +#. notes command: 'add', 'merge', 'remove', etc. +#. +#: builtin/notes.c +#, c-format +msgid "refusing to %s notes in %s (outside of refs/notes/)" +msgstr "diúltú do %s nótaà i %s (lasmuigh de refs/notes/)" + +#: builtin/notes.c +#, c-format +msgid "no note found for object %s." +msgstr "nà bhfuarthas aon nóta do réad %s." + +#: builtin/notes.c +msgid "note contents as a string" +msgstr "tabhair faoi deara ábhar mar shreang" + +#: builtin/notes.c +msgid "note contents in a file" +msgstr "tabhair faoi deara ábhar i gcomhad" + +#: builtin/notes.c +msgid "reuse and edit specified note object" +msgstr "réad nóta sonraithe a úsáid agus a chur in eagar" + +#: builtin/notes.c +msgid "edit note message in editor" +msgstr "teachtaireacht nóta in eagar san eagarthóir" + +#: builtin/notes.c +msgid "reuse specified note object" +msgstr "réad nóta sonraithe a athúsáid" + +#: builtin/notes.c +msgid "allow storing empty note" +msgstr "ligean nóta folamh a stóráil" + +#: builtin/notes.c +msgid "replace existing notes" +msgstr "nótaà atá ann cheana in ionad" + +#: builtin/notes.c +msgid "<paragraph-break>" +msgstr "<paragraph-break>" + +#: builtin/notes.c +msgid "insert <paragraph-break> between paragraphs" +msgstr "cuir isteach <paragraph-break>idir mÃreanna" + +#: builtin/notes.c +msgid "remove unnecessary whitespace" +msgstr "bain spás bán neamhriachtanach" + +#: builtin/notes.c +#, c-format +msgid "" +"Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite " +"existing notes" +msgstr "" +"Nà féidir nótaà a chur leis. Fuarthas nótaà atá ann cheana don réad %s. " +"Úsáid '-f' chun nótaà atá ann cheana a fhorscrÃobh" + +#: builtin/notes.c +#, c-format +msgid "Overwriting existing notes for object %s\n" +msgstr "AthscrÃobh nótaà atá ann cheana don réad %s\n" + +#: builtin/notes.c +#, c-format +msgid "Removing note for object %s\n" +msgstr "Nóta a bhaint le haghaidh réad %s\n" + +#: builtin/notes.c +msgid "read objects from stdin" +msgstr "léigh rudaà ó stdin" + +#: builtin/notes.c +msgid "load rewriting config for <command> (implies --stdin)" +msgstr "" +"cumraÃocht athscrÃbhneoireachta ualaigh le haghaidh <command>(tugann le " +"tuiscint --stdin)" + +#: builtin/notes.c +msgid "too few arguments" +msgstr "ró-bheag argóintÃ" + +#: builtin/notes.c +#, c-format +msgid "" +"Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite " +"existing notes" +msgstr "" +"Nà féidir nótaà a chóipeáil. Fuarthas nótaà atá ann cheana don réad %s. " +"Úsáid '-f' chun nótaà atá ann cheana a fhorscrÃobh" + +#: builtin/notes.c +#, c-format +msgid "missing notes on source object %s. Cannot copy." +msgstr "nótaà in easnamh ar réad foinse %s. Nà féidir cóipeáil." + +#: builtin/notes.c +#, c-format +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 "" +"Tá na roghanna -M/-f/-c/-c curtha as an bhfo-ordú 'eagarthóireach'.\n" +"Úsáid le do thoil 'git notes add -f -m/-f/-c/-C' ina ionad.\n" + +#: builtin/notes.c +msgid "failed to delete ref NOTES_MERGE_PARTIAL" +msgstr "theip ar an tagairt NOTES_MERGE_PARTIAL a scriosadh" + +#: builtin/notes.c +msgid "failed to delete ref NOTES_MERGE_REF" +msgstr "theip ar an ref a scriosadh NOTES_MERGE_REF" + +#: builtin/notes.c +msgid "failed to remove 'git notes merge' worktree" +msgstr "theip ar chrann oibre 'git notes merge' a bhaint" + +#: builtin/notes.c +msgid "failed to read ref NOTES_MERGE_PARTIAL" +msgstr "theip ar an tagairt NOTES_MERGE_PARTIAL a léamh" + +#: builtin/notes.c +msgid "could not find commit from NOTES_MERGE_PARTIAL." +msgstr "nà raibh sé in ann tiomantas a fháil ó NOTES_MERGE_PARTIAL." + +#: builtin/notes.c +msgid "could not parse commit from NOTES_MERGE_PARTIAL." +msgstr "nà raibh sé in ann tiomantas a pharsáil ó NOTES_MERGE_PARTIAL." + +#: builtin/notes.c +msgid "failed to resolve NOTES_MERGE_REF" +msgstr "theip orthu NOTES_MERGE_REF a réiteach" + +#: builtin/notes.c +msgid "failed to finalize notes merge" +msgstr "theip orthu nótaà a chumasc a chur i gcrÃch" + +#: builtin/notes.c +#, c-format +msgid "unknown notes merge strategy %s" +msgstr "straitéis cumaisc nótaà anaithnid %s" + +#: builtin/notes.c +msgid "General options" +msgstr "Roghanna ginearálta" + +#: builtin/notes.c +msgid "Merge options" +msgstr "Roghanna cumaisc" + +#: builtin/notes.c +msgid "" +"resolve notes conflicts using the given strategy (manual/ours/theirs/union/" +"cat_sort_uniq)" +msgstr "" +"coimhlintà nótaà a réiteach ag baint úsáide as an straitéis a thugtar " +"(lámhleabhair/innir/a nd/union/cat_sort_uniq)" + +#: builtin/notes.c +msgid "Committing unmerged notes" +msgstr "Nótaà neamh-mheánaithe a dhéanamh" + +#: builtin/notes.c +msgid "finalize notes merge by committing unmerged notes" +msgstr "cumasc nótaà a chrÃochnú trà nótaà neamh-chumasaithe a dhéanamh" + +#: builtin/notes.c +msgid "Aborting notes merge resolution" +msgstr "Rún cumasc le nótaà a ghearradh" + +#: builtin/notes.c +msgid "abort notes merge" +msgstr "cumaisc nótaà abort" + +#: builtin/notes.c +msgid "cannot mix --commit, --abort or -s/--strategy" +msgstr "nà féidir --commit, --abort nó -s/--strategy a mheascadh" + +#: builtin/notes.c +msgid "must specify a notes ref to merge" +msgstr "nà mór tagairt nótaà a shonrú chun cumasc" + +#: builtin/notes.c +#, c-format +msgid "unknown -s/--strategy: %s" +msgstr "anaithnid -s/--strategy: %s" + +#: builtin/notes.c +#, c-format +msgid "a notes merge into %s is already in-progress at %s" +msgstr "tá nótaà a chumasc i %s ar siúl cheana féin ag %s" + +#: builtin/notes.c +#, c-format +msgid "failed to store link to current notes ref (%s)" +msgstr "theip ar nasc a stóráil le nótaà reatha tagairt (%s)" + +#: builtin/notes.c +#, c-format +msgid "" +"Automatic notes merge failed. Fix conflicts in %s and commit the result with " +"'git notes merge --commit', or abort the merge with 'git notes merge --" +"abort'.\n" +msgstr "" +"Theip ar chumasc nótaà uathoibrÃoch Socraigh coinbhleachtaà i %s agus déan " +"an toradh a dhéanamh le 'git notes merge --commit', nó cuir deireadh leis an " +"cumasc le 'git notes merge --abort'.\n" + +#: builtin/notes.c builtin/tag.c +#, c-format +msgid "Failed to resolve '%s' as a valid ref." +msgstr "Theip ar '%s' a réiteach mar thagartha bailÃ." + +#: builtin/notes.c +#, c-format +msgid "Object %s has no note\n" +msgstr "NÃl aon nóta ag réad %s\n" + +#: builtin/notes.c +msgid "attempt to remove non-existent note is not an error" +msgstr "nà earráid é iarracht nóta nach bhfuil ann a bhaint" + +#: builtin/notes.c +msgid "read object names from the standard input" +msgstr "léigh ainmneacha réada ón ionchur caighdeánach" + +#: builtin/notes.c builtin/prune.c builtin/worktree.c +msgid "do not remove, show only" +msgstr "ná bain, taispeáin amháin" + +#: builtin/notes.c +msgid "report pruned notes" +msgstr "nótaà gearrtha a thuairisciú" + +#: builtin/notes.c +msgid "notes-ref" +msgstr "nótairea-tagairt" + +#: builtin/notes.c +msgid "use notes from <notes-ref>" +msgstr "úsáid nótaà ó <notes-ref>" + +#: builtin/notes.c builtin/remote.c parse-options.c +#, c-format +msgid "unknown subcommand: `%s'" +msgstr "fo-ordú anaithnid: `%s'" + +#: builtin/pack-objects.c +msgid "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]" +msgstr "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]" + +#: builtin/pack-objects.c +msgid "" +"git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]" +msgstr "" +"git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]" + +#: builtin/pack-objects.c +#, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "rogha neamhbhailà --name-hash-version: %d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "faoi láthair, teastaÃonn --write-bitmap-index --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"write_reuse_object: could not locate %s, expected at offset %<PRIuMAX> in " +"pack %s" +msgstr "" +"write_reuse_object: nÃorbh fhéidir %s a aimsiú, bhÃothas ag súil leis ag an " +"bhfritháireamh %<PRIuMAX> sa phacáiste %s" + +#: builtin/pack-objects.c +#, c-format +msgid "bad packed object CRC for %s" +msgstr "réad pacáilte dona CRC le haghaidh %s" + +#: builtin/pack-objects.c +#, c-format +msgid "corrupt packed object for %s" +msgstr "réad pacáilte truaillithe do %s" + +#: builtin/pack-objects.c +#, c-format +msgid "recursive delta detected for object %s" +msgstr "braithÃodh delta athfhillteach do réad %s" + +#: builtin/pack-objects.c +#, c-format +msgid "ordered %u objects, expected %<PRIu32>" +msgstr "rudaà %u ordaithe, súil leis% <PRIu32>" + +#: builtin/pack-objects.c +#, c-format +msgid "expected object at offset %<PRIuMAX> in pack %s" +msgstr "" +"réad a bhÃothas ag súil leis ag an bhfritháireamh %<PRIuMAX> sa phacáiste %s" + +#: builtin/pack-objects.c +msgid "disabling bitmap writing, packs are split due to pack.packSizeLimit" +msgstr "" +"scrÃobh bitmap a dhÃchumasú, roinntear pacáistà mar gheall ar " +"pack.packSizeLimit" + +#: builtin/pack-objects.c +msgid "Writing objects" +msgstr "Rudaà a scrÃobh" + +#: builtin/pack-objects.c builtin/update-index.c +#, c-format +msgid "failed to stat %s" +msgstr "theip ar stát %s" + +#: builtin/pack-objects.c object-file.c +#, c-format +msgid "failed utime() on %s" +msgstr "theip ar utime () ar %s" + +#: builtin/pack-objects.c +msgid "failed to write bitmap index" +msgstr "theip ar innéacs bitmap a scrÃobh" + +#: builtin/pack-objects.c +#, c-format +msgid "wrote %<PRIu32> objects while expecting %<PRIu32>" +msgstr "scrÃobh %<PRIu32> rudaà agus iad ag súil leis %<PRIu32>" + +#: builtin/pack-objects.c builtin/repack.c +msgid "disabling bitmap writing, as some objects are not being packed" +msgstr "scrÃobh bitmap a dhÃchumasú, toisc nach bhfuil roinnt rudaà á phacáil" + +#: builtin/pack-objects.c +#, c-format +msgid "delta base offset overflow in pack for %s" +msgstr "forsreabhadh fhritháireamh bonn delta i bpacáiste do %s" + +#: builtin/pack-objects.c +#, c-format +msgid "delta base offset out of bound for %s" +msgstr "bonn delta a fhritháireamh as ceangailte do %s" + +#: builtin/pack-objects.c +msgid "Counting objects" +msgstr "Rud a chomhaireamh" + +#: builtin/pack-objects.c pack-bitmap.c +#, c-format +msgid "unable to get size of %s" +msgstr "nach féidir méid %s a fháil" + +#: builtin/pack-objects.c +#, c-format +msgid "unable to parse object header of %s" +msgstr "nach féidir ceanntásc réad %s a pháirseáil" + +#: builtin/pack-objects.c +#, c-format +msgid "object %s cannot be read" +msgstr "nà féidir réad %s a léamh" + +#: builtin/pack-objects.c +#, c-format +msgid "object %s inconsistent object length (%<PRIuMAX> vs %<PRIuMAX>)" +msgstr "fad réada neamhréireach réad %s (%<PRIuMAX> vs %<PRIuMAX>)" + +#: builtin/pack-objects.c +msgid "suboptimal pack - out of memory" +msgstr "pacáiste suboptimal - as cuimhne" + +#: builtin/pack-objects.c +#, c-format +msgid "Delta compression using up to %d threads" +msgstr "Comhbhrú Delta ag úsáid suas le snáitheanna %d" + +#: builtin/pack-objects.c +#, c-format +msgid "unable to pack objects reachable from tag %s" +msgstr "nach féidir rudaà a phacáil inrochtana ó chlib %s" + +#: builtin/pack-objects.c commit-graph.c +#, c-format +msgid "unable to get type of object %s" +msgstr "nach féidir cineál réada %s a fháil" + +#: builtin/pack-objects.c +msgid "Compressing objects" +msgstr "Rudaà comhbhrúite" + +#: builtin/pack-objects.c +msgid "inconsistency with delta count" +msgstr "neamhréireacht le comhaireamh delta" + +#: builtin/pack-objects.c +#, c-format +msgid "invalid pack.allowPackReuse value: '%s'" +msgstr "luach pack.allowPackReuse neamhbhailÃ: '%s'" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-" +"hash> <uri>' (got '%s')" +msgstr "" +"<object-hash><pack-hash><uri>caithfidh luach uploadpack.blobpackfileuri a " +"bheith den fhoirm '' (fuair '%s')" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"object already configured in another uploadpack.blobpackfileuri (got '%s')" +msgstr "" +"réad cumraithe cheana féin i uploadpack.blobpackfileuri eile (fuair '%s')" + +#: builtin/pack-objects.c +#, c-format +msgid "could not get type of object %s in pack %s" +msgstr "nà fhéadfaà cineál réada %s a fháil i bpacáiste %s" + +#: builtin/pack-objects.c +#, c-format +msgid "could not find pack '%s'" +msgstr "nà raibh an pacáiste '%s' in ann a aimsiú" + +#: builtin/pack-objects.c +#, c-format +msgid "packfile %s cannot be accessed" +msgstr "nà féidir teacht ar chomhad pacáiste %s" + +#: builtin/pack-objects.c +msgid "Enumerating cruft objects" +msgstr "Ag áireamh rudaà cruft" + +#: builtin/pack-objects.c +msgid "unable to add cruft objects" +msgstr "in ann rudaà cruft a chur leis" + +#: builtin/pack-objects.c +msgid "Traversing cruft objects" +msgstr "Ag trasnú ar rudaà cruth" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"expected edge object ID, got garbage:\n" +" %s" +msgstr "" +"ag súil le haitheantas réada imeall, fuarthas bruscar:\n" +"%s" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"expected object ID, got garbage:\n" +" %s" +msgstr "" +"aitheantas réada a bhfuil súil leis, fuair truflais:\n" +" %s" + +#: builtin/pack-objects.c reachable.c +msgid "could not load cruft pack .mtimes" +msgstr "nà fhéadfaà pacáiste cruft a luchtú .mtimes" + +#: builtin/pack-objects.c +msgid "cannot open pack index" +msgstr "nà féidir innéacs pacáiste a osc" + +#: builtin/pack-objects.c +#, c-format +msgid "loose object at %s could not be examined" +msgstr "nà fhéadfaà réad scaoilte ag %s a scrúdú" + +#: builtin/pack-objects.c +msgid "unable to force loose object" +msgstr "in ann rud scaoilte a chur i bhfeidhm" + +#: builtin/pack-objects.c +#, c-format +msgid "not a rev '%s'" +msgstr "nà rev '%s'" + +#: builtin/pack-objects.c builtin/rev-parse.c +#, c-format +msgid "bad revision '%s'" +msgstr "droch-athbhreithniú '%s'" + +#: builtin/pack-objects.c +msgid "unable to add recent objects" +msgstr "in ann rudaà le déanaà a chur leis" + +#: builtin/pack-objects.c +#, c-format +msgid "unsupported index version %s" +msgstr "leagan innéacs neamhthacaithe %s" + +#: builtin/pack-objects.c +#, c-format +msgid "bad index version '%s'" +msgstr "droch-leagan innéacs '%s'" + +#: builtin/pack-objects.c +msgid "show progress meter during object writing phase" +msgstr "méadar dul chun cinn a thaispeáint le linn céim sc" + +#: builtin/pack-objects.c +msgid "similar to --all-progress when progress meter is shown" +msgstr "cosúil le --all-progress nuair a thaispeántar méadar dul chun cinn" + +#: builtin/pack-objects.c +msgid "<version>[,<offset>]" +msgstr "<version>[,<offset>]" + +#: builtin/pack-objects.c +msgid "write the pack index file in the specified idx format version" +msgstr "scrÃobh an comhad innéacs pacáiste sa leagan formáid idx sonraithe" + +#: builtin/pack-objects.c +msgid "maximum size of each output pack file" +msgstr "uasmhéid gach comhad pacáiste aschuir" + +#: builtin/pack-objects.c +msgid "ignore borrowed objects from alternate object store" +msgstr "neamhaird a dhéanamh ar rudaà atá ar iasacht ó stór" + +#: builtin/pack-objects.c +msgid "ignore packed objects" +msgstr "neamhaird a dhéanamh ar earraÃ" + +#: builtin/pack-objects.c +msgid "limit pack window by objects" +msgstr "teorainn fuinneog pacáiste de réir rudaÃ" + +#: builtin/pack-objects.c +msgid "limit pack window by memory in addition to object limit" +msgstr "teorainn le fuinneog pacáiste de réir chuimhne i dteannta le teorainn" + +#: builtin/pack-objects.c +msgid "maximum length of delta chain allowed in the resulting pack" +msgstr "fad uasta an slabhra delta a cheadaÃtear sa phacáiste mar thoradh air" + +#: builtin/pack-objects.c +msgid "reuse existing deltas" +msgstr "déltaà atá ann cheana a athúsáid" + +#: builtin/pack-objects.c +msgid "reuse existing objects" +msgstr "athúsáid rudaà atá ann cheana" + +#: builtin/pack-objects.c +msgid "use OFS_DELTA objects" +msgstr "bain úsáid as rudaà OFS_DELTA" + +#: builtin/pack-objects.c +msgid "use threads when searching for best delta matches" +msgstr "úsáid snáitheanna agus tú ag cuardach na cluichà delta is fearr" + +#: builtin/pack-objects.c +msgid "do not create an empty pack output" +msgstr "ná cruthaigh aschur pacáiste folamh" + +#: builtin/pack-objects.c +msgid "read revision arguments from standard input" +msgstr "léigh argóintà athbhreithnithe ó ionchur" + +#: builtin/pack-objects.c +msgid "limit the objects to those that are not yet packed" +msgstr "teorainn leis na rudaà dóibh siúd nach bhfuil pacáilte fós" + +#: builtin/pack-objects.c +msgid "include objects reachable from any reference" +msgstr "áireamh rudaà atá inrochtana ó aon tagairt" + +#: builtin/pack-objects.c +msgid "include objects referred by reflog entries" +msgstr "áireamh rudaà a dtagraÃtear ag iontrálacha reflog" + +#: builtin/pack-objects.c +msgid "include objects referred to by the index" +msgstr "áireamh rudaà dá dtagraÃonn an t-innéacs" + +#: builtin/pack-objects.c +msgid "read packs from stdin" +msgstr "léigh pacáistà ó stdin" + +#: builtin/pack-objects.c +msgid "output pack to stdout" +msgstr "pacáiste aschuir go stdout" + +#: builtin/pack-objects.c +msgid "include tag objects that refer to objects to be packed" +msgstr "áireamh rudaà clibeanna a thagraÃonn do rudaà atá le pacáil" + +#: builtin/pack-objects.c +msgid "keep unreachable objects" +msgstr "rudaà nach féidir a choinneáil" + +#: builtin/pack-objects.c +msgid "pack loose unreachable objects" +msgstr "rudaà scaoilte nach féidir a phacáil" + +#: builtin/pack-objects.c +msgid "unpack unreachable objects newer than <time>" +msgstr "rudaà nach féidir a dhÃphacáil nÃos nuaà ná <time>" + +#: builtin/pack-objects.c +msgid "create a cruft pack" +msgstr "cruthaigh pacáiste cruft" + +#: builtin/pack-objects.c +msgid "expire cruft objects older than <time>" +msgstr "dul in éag rudaà cruft nÃos sine ná <time>" + +#: builtin/pack-objects.c +msgid "use the sparse reachability algorithm" +msgstr "úsáid an algartam inrochtaineachta neamhchoitianta" + +#: builtin/pack-objects.c +msgid "create thin packs" +msgstr "cruthaigh pacáistà tanaÃ" + +#: builtin/pack-objects.c +msgid "create packs suitable for shallow fetches" +msgstr "pacáistà a chruthú atá oiriúnach le haghaidh tógá" + +#: builtin/pack-objects.c +msgid "ignore packs that have companion .keep file" +msgstr "neamhaird a dhéanamh ar phacáistà a bhfuil comhad compánach" + +#: builtin/pack-objects.c +msgid "ignore this pack" +msgstr "neamhaird a dhéanamh ar an b" + +#: builtin/pack-objects.c +msgid "pack compression level" +msgstr "leibhéal comhbhrú pacáiste" + +#: builtin/pack-objects.c +msgid "do not hide commits by grafts" +msgstr "ná déan gealltanais ag grafts i bhfolach" + +#: builtin/pack-objects.c +msgid "use a bitmap index if available to speed up counting objects" +msgstr "" +"úsáid innéacs bitmap má tá sé ar fáil chun rudaà a chomhaireamh a bhrostú" + +#: builtin/pack-objects.c +msgid "write a bitmap index together with the pack index" +msgstr "scrÃobh innéacs bitmap in éineacht leis an innéacs pacáiste" + +#: builtin/pack-objects.c +msgid "write a bitmap index if possible" +msgstr "scrÃobh innéacs bitmap más féidir" + +#: builtin/pack-objects.c +msgid "handling for missing objects" +msgstr "láimhseáil le haghaidh rudaà atá" + +#: builtin/pack-objects.c +msgid "do not pack objects in promisor packfiles" +msgstr "ná pacáil rudaà i gcomhaid pacáiste gealltanais" + +#: builtin/pack-objects.c +msgid "implies --missing=allow-any" +msgstr "tugann le tuiscint --missing=allow-any" + +#: builtin/pack-objects.c +msgid "respect islands during delta compression" +msgstr "meas ar oileáin le linn comhbhrúite delta" + +#: builtin/pack-objects.c +msgid "protocol" +msgstr "prótacal" + +#: builtin/pack-objects.c +msgid "exclude any configured uploadpack.blobpackfileuri with this protocol" +msgstr "eisiamh aon uploadpack.blobpackfileuri cumraithe leis an bprótacal seo" + +#: builtin/pack-objects.c +msgid "use the specified name-hash function to group similar objects" +msgstr "" +"bain úsáid as an bhfeidhm sonraithe ainm-hash chun rudaà den chineál céanna a" + +#: builtin/pack-objects.c +#, c-format +msgid "delta chain depth %d is too deep, forcing %d" +msgstr "" +"tá doimhneacht slabhra delta %d ró-dhomhain, rud a chuireann iallach ar %d" + +#: builtin/pack-objects.c +#, c-format +msgid "pack.deltaCacheLimit is too high, forcing %d" +msgstr "pack.deltaCacheLimit ró-ard, ag cur %d i bhfeidhm" + +#: builtin/pack-objects.c config.c +#, c-format +msgid "bad pack compression level %d" +msgstr "leibhéal comhbhrúite droch-phacáiste %d" + +#: builtin/pack-objects.c +msgid "--max-pack-size cannot be used to build a pack for transfer" +msgstr "Nà féidir --max-pack-size a úsáid chun pacáiste a thógáil le haistriú" + +#: builtin/pack-objects.c +msgid "minimum pack size limit is 1 MiB" +msgstr "is é teorainn Ãosta méid an phacáiste ná 1 MiB" + +#: builtin/pack-objects.c +msgid "--thin cannot be used to build an indexable pack" +msgstr "Nà féidir --thin a úsáid chun pacáiste innéacsaithe a thógáil" + +#: builtin/pack-objects.c +msgid "cannot use --filter with --stdin-packs" +msgstr "nà féidir --filter a úsáid le --stdin-packs" + +#: builtin/pack-objects.c +msgid "cannot use internal rev list with --stdin-packs" +msgstr "nà féidir liosta rev inmheánach a úsáid le --stdin-packs" + +#: builtin/pack-objects.c +msgid "cannot use internal rev list with --cruft" +msgstr "nà féidir liosta rev inmheánach a úsáid le --cruft" + +#: builtin/pack-objects.c +msgid "cannot use --stdin-packs with --cruft" +msgstr "nà féidir --stdin-packs a úsáid le --cruft" + +#: builtin/pack-objects.c +msgid "Enumerating objects" +msgstr "Rudaà a chur san áireamh" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-" +"reused %<PRIu32> (from %<PRIuMAX>)" +msgstr "" +"%<PRIu32> iomlán (delta %<PRIu32>), %<PRIu32> athúsáidte (delta %<PRIu32>), " +"%<PRIu32> athúsáidte sa phacáiste (ó %<PRIuMAX>)" + +#: builtin/pack-redundant.c +msgid "" +"'git pack-redundant' is nominated for removal.\n" +"If you still use this command, please add an extra\n" +"option, '--i-still-use-this', on the command line\n" +"and let us know you still use it by sending an e-mail\n" +"to <git@vger.kernel.org>. Thanks.\n" +msgstr "" +"Tá 'git pack-redundant' ainmnithe le baint.\n" +"Má úsáideann tú an t-ordú seo fós, cuir rogha b\n" +"hreise, '--i-still-use-this', leis an lÃne ordaithe \n" +"agus cuir in iúl dúinn go n-úsáideann tú fós é trà rÃomhphost \n" +"a sheoladh chuig <git@vger.kernel.org>. Go raibh maith agat.\n" + +#: builtin/pack-redundant.c +msgid "refusing to run without --i-still-use-this" +msgstr "ag diúltú rith gan --i-still-use-this fós" + +#: builtin/pack-refs.c +msgid "" +"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude " +"<pattern>]" +msgstr "" +"<pattern><pattern>git pack-refs [--all] [--no-prunes] [--auto] [--include] " +"[--eisiamh]" + +#: builtin/pack-refs.c +msgid "pack everything" +msgstr "pacáil gach rud" + +#: builtin/pack-refs.c +msgid "prune loose refs (default)" +msgstr "briseadh scaoilte (réamhshocraithe)" + +#: builtin/pack-refs.c +msgid "auto-pack refs as needed" +msgstr "tuairiscintà uathoibrÃoch pacáiste" + +#: builtin/pack-refs.c +msgid "references to include" +msgstr "tagairtà lena n-áirÃtear" + +#: builtin/pack-refs.c +msgid "references to exclude" +msgstr "tagairtà chun eisiamh" + +#: builtin/patch-id.c +msgid "git patch-id [--stable | --unstable | --verbatim]" +msgstr "git patch-id [--seasmhach | --éagobhsaà | --verbatim]" + +#: builtin/patch-id.c +msgid "use the unstable patch-id algorithm" +msgstr "bain úsáid as an algartam paith-id éagobhsaÃ" + +#: builtin/patch-id.c +msgid "use the stable patch-id algorithm" +msgstr "bain úsáid as an algartam paith-id cobhsaÃ" + +#: builtin/patch-id.c +msgid "don't strip whitespace from the patch" +msgstr "ná tarraingt spás bán ón bpaiste" + +#: builtin/prune.c +msgid "git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]" +msgstr "<head>git plum [-n] [-v] [--progress] [--dul in éag] [<time>--] [...]" + +#: builtin/prune.c +msgid "report pruned objects" +msgstr "tuairisciú rudaà gearrtha" + +#: builtin/prune.c +msgid "expire objects older than <time>" +msgstr "dul in éag rudaà nÃos sine ná <time>" + +#: builtin/prune.c +msgid "limit traversal to objects outside promisor packfiles" +msgstr "teorainn a chur ar thrasú le rudaà lasmuigh de phacáiste gealltan" + +#: builtin/prune.c +msgid "cannot prune in a precious-objects repo" +msgstr "nà féidir le bearradh i repo rudaà luachmhara" + +#: builtin/pull.c +msgid "git pull [<options>] [<repository> [<refspec>...]]" +msgstr "git pull [<options>] [<repository>[<refspec>...]]" + +#: builtin/pull.c +msgid "control for recursive fetching of submodules" +msgstr "rialú maidir le fo-mhodúil a fháil athshlánach" + +#: builtin/pull.c +msgid "Options related to merging" +msgstr "Roghanna a bhaineann le cumasc" + +#: builtin/pull.c +msgid "incorporate changes by rebasing rather than merging" +msgstr "athruithe a ionchorprú trà athbhunú seachas cumasc" + +#: builtin/pull.c builtin/revert.c +msgid "allow fast-forward" +msgstr "ligean go tapa ar aghaidh" + +#: builtin/pull.c +msgid "control use of pre-merge-commit and commit-msg hooks" +msgstr "úsáid crúcaà réamh-chumaisc agus comh-msg a rialú" + +#: builtin/pull.c parse-options.h +msgid "automatically stash/stash pop before and after" +msgstr "pop a stash/stash go huathoibrÃoch roimh agus tar éis" + +#: builtin/pull.c +msgid "Options related to fetching" +msgstr "Roghanna a bhaineann le tarraingt" + +#: builtin/pull.c +msgid "force overwrite of local branch" +msgstr "forscrÃobh fórsa ar bhrainse áitiúil" + +#: builtin/pull.c +msgid "number of submodules pulled in parallel" +msgstr "lÃon na bhfo-mhodúil tarraingthe go comhthreom" + +#: builtin/pull.c parse-options.h +msgid "use IPv4 addresses only" +msgstr "bain úsáid as seoltaà IPv4 amháin" + +#: builtin/pull.c parse-options.h +msgid "use IPv6 addresses only" +msgstr "bain úsáid as seoltaà IPv6 amháin" + +#: builtin/pull.c +msgid "" +"There is no candidate for rebasing against among the refs that you just " +"fetched." +msgstr "" +"NÃl aon iarrthóir ann chun athbhreithniú i measc na n-airÃonna a fuair tú " +"dÃreach." + +#: builtin/pull.c +msgid "" +"There are no candidates for merging among the refs that you just fetched." +msgstr "" +"NÃl aon iarrthóirà ann chun cumasc i measc na gcomharthaà a fuair tú dÃreach." + +#: builtin/pull.c +msgid "" +"Generally this means that you provided a wildcard refspec which had no\n" +"matches on the remote end." +msgstr "" +"Go ginearálta ciallaÃonn sé seo gur sholáthraÃonn tú refspec cárta fiáin " +"nach raibh aon\n" +"cluichà ar an gceann iargúlta." + +#: builtin/pull.c +#, c-format +msgid "" +"You asked to pull from the remote '%s', but did not specify\n" +"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 "" +"D'iarr tú tarraingt ón iargúlta '%s', ach nÃor shonraigh tú\n" +"brainse. Toisc nach é seo an cianda cumraithe réamhshocraithe\n" +"do bhrainse reatha, nà mór duit brainse a shonrú ar an lÃne ordaithe." + +#: builtin/pull.c builtin/rebase.c +msgid "You are not currently on a branch." +msgstr "NÃl tú ar bhrainse faoi láthair." + +#: builtin/pull.c +msgid "Please specify which branch you want to rebase against." +msgstr "Sonraigh le do thoil cén brainse is mian leat a athbhunú ina choinne." + +#: builtin/pull.c +msgid "Please specify which branch you want to merge with." +msgstr "Sonraigh le do thoil cén brainse is mian leat a chumasc leis." + +#: builtin/pull.c +msgid "See git-pull(1) for details." +msgstr "Féach git-pull (1) le haghaidh sonraÃ." + +#: builtin/pull.c builtin/rebase.c +msgid "<remote>" +msgstr "<remote>" + +#: builtin/pull.c scalar.c +msgid "<branch>" +msgstr "<branch>" + +#: builtin/pull.c builtin/rebase.c +msgid "There is no tracking information for the current branch." +msgstr "NÃl aon fhaisnéis rianaithe don bhrainse reatha." + +#: builtin/pull.c +msgid "" +"If you wish to set tracking information for this branch you can do so with:" +msgstr "" +"Más mian leat faisnéis rianaithe a shocrú don bhrainse seo is féidir leat é " +"sin a dhéanamh le:" + +#: builtin/pull.c +#, c-format +msgid "" +"Your configuration specifies to merge with the ref '%s'\n" +"from the remote, but no such ref was fetched." +msgstr "" +"SonraÃonn do chumraÃocht a chumasc leis an tagairt '%s'\n" +"ón iargúlta, ach nÃor faightear aon tagairt den sórt sin." + +#: builtin/pull.c +#, c-format +msgid "unable to access commit %s" +msgstr "nach féidir teacht ar thiomantas %s" + +#: builtin/pull.c refspec.c +#, c-format +msgid "invalid refspec '%s'" +msgstr "refspec neamhbhailà '%s'" + +#: builtin/pull.c +msgid "ignoring --verify-signatures for rebase" +msgstr "ag neamhaird --verify-signatures le haghaidh athbhunú" + +#: builtin/pull.c +msgid "" +"You have divergent branches and need to specify how to reconcile them.\n" +"You can do so by running one of the following commands sometime before\n" +"your next pull:\n" +"\n" +" git config pull.rebase false # merge\n" +" git config pull.rebase true # rebase\n" +" git config pull.ff only # fast-forward only\n" +"\n" +"You can replace \"git config\" with \"git config --global\" to set a " +"default\n" +"preference for all repositories. You can also pass --rebase, --no-rebase,\n" +"or --ff-only on the command line to override the configured default per\n" +"invocation.\n" +msgstr "" +"Tá brainsà éagsúla agat agus nà mór duit a shonrú conas iad a réiteach.\n" +"Is féidir leat é sin a dhéanamh trà cheann de na horduithe seo a leanas a " +"reáchtáil rud éigin\n" +"do chéad tarraingt eile:\n" +"\n" +" git config pull.rebase false # cumaisc\n" +" git config pull.rebase true # rebase\n" +" git config pull.ff only # tapa ar aghaidh amháin\n" +"\n" +"Is féidir leat “git config --global†a chur in ionad “git config†chun " +"réamhshocrú a shocrú\n" +"rogha do gach stórais. Is féidir leat pas a chur freisin --rebase, --no-" +"rebase,\n" +"nó --ff-only ar an lÃne ordaithe chun an réamhshocrú cumraithe in aghaidh a " +"shárú\n" +"ionghairm.\n" + +#: builtin/pull.c +msgid "Updating an unborn branch with changes added to the index." +msgstr "Brainse breithe a nuashonrú le hathruithe curtha leis an innéacs." + +#: builtin/pull.c +msgid "pull with rebase" +msgstr "tarraing le rebase" + +#: builtin/pull.c builtin/rebase.c +msgid "Please commit or stash them." +msgstr "Déan iad a thiomantas nó a stóráil le do thoil." + +#: builtin/pull.c +#, c-format +msgid "" +"fetch updated the current branch head.\n" +"fast-forwarding your working tree from\n" +"commit %s." +msgstr "" +"nuashonraigh teacht ceann an bhrainse reatha.\n" +"do chrann oibre a chur ar aghaidh go tapa ó\n" +"tiomantas %s." + +#: builtin/pull.c +#, c-format +msgid "" +"Cannot fast-forward your working tree.\n" +"After making sure that you saved anything precious from\n" +"$ git diff %s\n" +"output, run\n" +"$ git reset --hard\n" +"to recover." +msgstr "" +"Nà féidir do chrann oibre a chur ar aghaidh a thosú.\n" +"Tar éis duit a chinntiú gur shábháil tú aon rud luachmhar ó\n" +"$ git diff %s\n" +"aschur, rith\n" +"$ git reset --hard\n" +"chun aisghabháil." + +#: builtin/pull.c +msgid "Cannot merge multiple branches into empty head." +msgstr "Nà féidir brainsà iomadúla a chumasc i gceann folamh." + +#: builtin/pull.c +msgid "Cannot rebase onto multiple branches." +msgstr "Nà féidir athbhunú ar iliomad brainsÃ." + +#: builtin/pull.c +msgid "Cannot fast-forward to multiple branches." +msgstr "Nà féidir dul ar aghaidh go tapa go brainsà iolracha." + +#: builtin/pull.c +msgid "Need to specify how to reconcile divergent branches." +msgstr "Nà mór a shonrú conas brainsà éagsúla a réiteach." + +#: builtin/pull.c +msgid "cannot rebase with locally recorded submodule modifications" +msgstr "nà féidir athbhunú le modhnuithe fo-mhodúil atá taifeadta" + +#: builtin/push.c +msgid "git push [<options>] [<repository> [<refspec>...]]" +msgstr "git push [<roghanna>] [<stóras> [<refspec>...]]" + +#: builtin/push.c +msgid "tag shorthand without <tag>" +msgstr "gearrthand clib gan <tag>" + +#: builtin/push.c +msgid "--delete only accepts plain target ref names" +msgstr "--delete nà ghlacann sé ach le hainmneacha tagartha sprice simplÃ" + +#: builtin/push.c +msgid "" +"\n" +"To choose either option permanently, see push.default in 'git help config'.\n" +msgstr "" +"\n" +"Chun ceachtar rogha a roghnú go buan, féach push.default i 'git help " +"config'.\n" + +#: builtin/push.c +msgid "" +"\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" +"Chun brainse suas srutha a chumrú go huathoibrÃoch a sheachaint nuair a\n" +"nà mheaitseoidh sé leis an mbrainse áitiúil, féach an rogha 'simplÃ' de " +"branch.autoSetupMerge\n" +"i 'git help config'.\n" + +#: builtin/push.c +#, c-format +msgid "" +"The upstream branch of your current branch does not match\n" +"the name of your current branch. To push to the upstream branch\n" +"on the remote, use\n" +"\n" +" git push %s HEAD:%s\n" +"\n" +"To push to the branch of the same name on the remote, use\n" +"\n" +" git push %s HEAD\n" +"%s%s" +msgstr "" +"Nà mheaitseálann an brainse suas srutha de do bhrainse reatha\n" +"ainm do bhrainse reatha. Chun brú go dtà an bhrainse suas srutha\n" +"ar an iargúlta, bain úsáid as\n" +"\n" +" git push %s HEAD:%s\n" +"\n" +"Chun brú chuig an mbrainse den ainm céanna ar an iargúlta, bain úsáid as\n" +"\n" +" git push %s HEAD\n" +"%s%s" + +#: builtin/push.c +#, c-format +msgid "" +"You are not currently on a branch.\n" +"To push the history leading to the current (detached HEAD)\n" +"state now, use\n" +"\n" +" git push %s HEAD:<name-of-remote-branch>\n" +msgstr "" +"NÃl tú ar bhrainse faoi láthair.\n" +"Chun an stair a bhrú mar thoradh ar an gceann reatha (CEAD scoite)\n" +"stát anois, bain úsáid as\n" +"\n" +" git push %s HEAD:<ainm-na-brainse-cianda>\n" + +#: builtin/push.c +msgid "" +"\n" +"To have this happen automatically for branches without a tracking\n" +"upstream, see 'push.autoSetupRemote' in 'git help config'.\n" +msgstr "" +"\n" +"Chun é seo a tharlóidh go huathoibrÃoch do bhrainsà gan rianú\n" +"suas sruth, féach 'push.autoSetupRemote' i 'git help config'.\n" + +#: builtin/push.c +#, c-format +msgid "" +"The current branch %s has no upstream branch.\n" +"To push the current branch and set the remote as upstream, use\n" +"\n" +" git push --set-upstream %s %s\n" +"%s" +msgstr "" +"NÃl brainse suas srutha ag an mbrainse reatha %s.\n" +"Chun an brainse reatha a bhrú agus an iargúlta a shocrú mar thuas an sruth, " +"bain úsáid as\n" +"\n" +" git push --set-upstream %s %s\n" +"%s" + +#: builtin/push.c +#, c-format +msgid "The current branch %s has multiple upstream branches, refusing to push." +msgstr "" +"Tá brainsà iolracha suas srutha ag an mbrainse reatha %s, ag diúltú brú." + +#: builtin/push.c +msgid "" +"You didn't specify any refspecs to push, and push.default is \"nothing\"." +msgstr "" +"NÃor shonraigh tú aon refspec le brú, agus is é push.default “rud ar bithâ€." + +#: builtin/push.c +#, c-format +msgid "" +"You are pushing to remote '%s', which is not the upstream of\n" +"your current branch '%s', without telling me what to push\n" +"to update which remote branch." +msgstr "" +"Tá tú ag brú chuig '%s' iargúlta, nach bhfuil suas sruth\n" +"do bhrainse reatha '%s', gan insint liom cad ba cheart a bhrú\n" +"chun an brainse iargúlta a nuashonrú." + +#: builtin/push.c +msgid "" +"Updates were rejected because the tip of your current branch is behind\n" +"its remote counterpart. If you want to integrate the remote changes,\n" +"use 'git pull' before pushing again.\n" +"See the 'Note about fast-forwards' in 'git push --help' for details." +msgstr "" +"DiúltaÃodh nuashonruithe toisc go bhfuil barr do bhrainse reatha taobh thiar " +"de\n" +"a mhacasamhail iargúlta. Más mian leat na hathruithe iargúlta a " +"chomhtháthú,\n" +"bain úsáid as 'git pull' sula mbrú arÃs.\n" +"Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraÃ." + +#: builtin/push.c +msgid "" +"Updates were rejected because a pushed branch tip is behind its remote\n" +"counterpart. If you want to integrate the remote changes, use 'git pull'\n" +"before pushing again.\n" +"See the 'Note about fast-forwards' in 'git push --help' for details." +msgstr "" +"DiúltaÃodh nuashonruithe toisc go bhfuil barr brainse brúite taobh thiar dá\n" +"comhghleacaÃ. Más mian leat na hathruithe iargúlta a chomhtháthú, bain úsáid " +"as 'git pull'\n" +"sula ndéantar é a bhrú arÃs.\n" +"Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraÃ." + +#: builtin/push.c +msgid "" +"Updates were rejected because the remote contains work that you do not\n" +"have locally. This is usually caused by another repository pushing to\n" +"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 "" +"DiúltaÃodh nuashonruithe toisc go bhfuil obair nach ndéanann tú san " +"iargúlta\n" +"a bheith agat go háitiúil. De ghnáth bÃonn stór eile ag brú chuig seo\n" +"an tagairt chéanna. Más mian leat na hathruithe iargúlta a chomhtháthú, bain " +"úsáid as\n" +"'git tarraing' sula ndéantar é a bhrú arÃs.\n" +"Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraÃ." + +#: builtin/push.c +msgid "Updates were rejected because the tag already exists in the remote." +msgstr "" +"DiúltaÃodh nuashonruithe toisc go bhfuil an clib ann cheana féin sa iargúlta." + +#: builtin/push.c +msgid "" +"You cannot update a remote ref that points at a non-commit object,\n" +"or update a remote ref to make it point at a non-commit object,\n" +"without using the '--force' option.\n" +msgstr "" +"Nà féidir leat tagairt iargúlta a nuashonrú a chuireann in iúl ar réad neamh-" +"thiomanta,\n" +"nó tagairt iargúlta a nuashonrú chun é a chur in iúl ar réad neamh-" +"thiomanta,\n" +"gan an rogha '--force' a úsáid.\n" + +#: builtin/push.c +msgid "" +"Updates were rejected because the tip of the remote-tracking branch has\n" +"been updated since the last checkout. If you want to integrate the\n" +"remote changes, use 'git pull' before pushing again.\n" +"See the 'Note about fast-forwards' in 'git push --help' for details." +msgstr "" +"DiúltaÃodh nuashonruithe toisc go bhfuil barr na brainse cianrianaithe\n" +"nuashonraÃodh ón tseiceáil deireanach. Más mian leat an\n" +"athruithe iargúlta, bain úsáid as 'git pull' sula mbrú arÃs.\n" +"Féach an 'Nóta faoi fast-forward 'i 'git push --help' le haghaidh sonraÃ." + +#: builtin/push.c +#, c-format +msgid "Pushing to %s\n" +msgstr "Ag brú chuig %s\n" + +#: builtin/push.c +#, c-format +msgid "failed to push some refs to '%s'" +msgstr "theip ar roinnt réimsà a bhrú chuig '%s'" + +#: builtin/push.c +msgid "" +"recursing into submodule with push.recurseSubmodules=only; using on-demand " +"instead" +msgstr "" +"athfhillteach isteach i bhfo-mhodúl le push.recurseSubmodules=only; ag baint " +"úsáide as ar-éileamh ina ionad" + +#: builtin/push.c builtin/send-pack.c submodule-config.c +#, c-format +msgid "invalid value for '%s'" +msgstr "luach neamhbhailà do '%s'" + +#: builtin/push.c builtin/submodule--helper.c +msgid "repository" +msgstr "stóras" + +#: builtin/push.c +msgid "push all branches" +msgstr "brúigh gach brainse" + +#: builtin/push.c builtin/send-pack.c +msgid "mirror all refs" +msgstr "scáthán gach ceann" + +#: builtin/push.c +msgid "delete refs" +msgstr "scrios réimsÃ" + +#: builtin/push.c +msgid "push tags (can't be used with --all or --branches or --mirror)" +msgstr "" +"clibeanna brú (nà féidir iad a úsáid le --all nó --branches nó --mirror)" + +#: builtin/push.c builtin/send-pack.c +msgid "force updates" +msgstr "nuashonruithe fórsa" + +#: builtin/push.c builtin/send-pack.c +msgid "<refname>:<expect>" +msgstr "<refname>:<expect>" + +#: builtin/push.c builtin/send-pack.c +msgid "require old value of ref to be at this value" +msgstr "a cheangal go mbeadh seanluach an tagartha ag an luach seo" + +#: builtin/push.c builtin/send-pack.c +msgid "require remote updates to be integrated locally" +msgstr "éilÃonn go ndéanfaà nuashonruithe iargúlta" + +#: builtin/push.c +msgid "control recursive pushing of submodules" +msgstr "brú athfhillteach ar fho-mhodúil a rialú" + +#: builtin/push.c builtin/send-pack.c +msgid "use thin pack" +msgstr "bain úsáid as pacáiste tanaÃ" + +#: builtin/push.c builtin/send-pack.c +msgid "receive pack program" +msgstr "clár pacáiste a fháil" + +#: builtin/push.c +msgid "set upstream for git pull/status" +msgstr "socraigh suas sruth le haghaidh tarraing/stádas git" + +#: builtin/push.c +msgid "prune locally removed refs" +msgstr "gearradh a bhaintear go háitiúil" + +#: builtin/push.c +msgid "bypass pre-push hook" +msgstr "seachbhóthar crúca réamh" + +#: builtin/push.c +msgid "push missing but relevant tags" +msgstr "clibeanna atá ar iarraidh ach ábhartha a" + +#: builtin/push.c builtin/send-pack.c +msgid "GPG sign the push" +msgstr "SÃnÃonn GPG an brú" + +#: builtin/push.c builtin/send-pack.c +msgid "request atomic transaction on remote side" +msgstr "iarraidh idirbheart adamach ar an taobh iargúl" + +#: builtin/push.c +msgid "--delete doesn't make sense without any refs" +msgstr "--delete nÃl ciall leis gan aon réiteoirÃ" + +#: builtin/push.c t/helper/test-bundle-uri.c +#, c-format +msgid "bad repository '%s'" +msgstr "droch-stóras '%s'" + +#: builtin/push.c +msgid "" +"No configured push destination.\n" +"Either specify the URL from the command-line or configure a remote " +"repository using\n" +"\n" +" git remote add <name> <url>\n" +"\n" +"and then push using the remote name\n" +"\n" +" git push <name>\n" +msgstr "" +"Gan aon cheann scrÃbe brúite cumraithe.\n" +"Sonraigh an URL ón lÃne ordaithe nó cumraigh stór iargúlta ag baint úsáide " +"as\n" +"\n" +" git remote add <name> <url>\n" +"\n" +"agus ansin brúigh ag úsáid an ainm iargúlta\n" +"\n" +" git push <ainm>\n" + +#: builtin/push.c +msgid "--all can't be combined with refspecs" +msgstr "--all nà féidir é a chomhcheangal le refspecs" + +#: builtin/push.c +msgid "--mirror can't be combined with refspecs" +msgstr "--mirror nà féidir é a chomhcheangal le refspecs" + +#: builtin/push.c +msgid "push options must not have new line characters" +msgstr "nà chóir go mbeadh carachtair lÃne nua ag roghanna brú" + +#: builtin/range-diff.c +msgid "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>" +msgstr "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>" + +#: builtin/range-diff.c +msgid "git range-diff [<options>] <old-tip>...<new-tip>" +msgstr "git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>" + +#: builtin/range-diff.c +msgid "git range-diff [<options>] <base> <old-tip> <new-tip>" +msgstr "git range-diff [<options>] <base> <old-tip> <new-tip>" + +#: builtin/range-diff.c +msgid "use simple diff colors" +msgstr "bain úsáid as dathanna diff simplÃ" + +#: builtin/range-diff.c +msgid "notes" +msgstr "nótaÃ" + +#: builtin/range-diff.c +msgid "passed to 'git log'" +msgstr "cuireadh chuig 'git log'" + +#: builtin/range-diff.c +msgid "only emit output related to the first range" +msgstr "nà scaoileann ach aschur a bhaineann leis an gcéad raon" + +#: builtin/range-diff.c +msgid "only emit output related to the second range" +msgstr "nà scaoileann ach aschur a bhaineann leis an dara raon" + +#: builtin/range-diff.c +#, c-format +msgid "not a revision: '%s'" +msgstr "nà athbhreithniú: '%s'" + +#: builtin/range-diff.c +#, c-format +msgid "not a commit range: '%s'" +msgstr "nà raon tiomanta: '%s'" + +#: builtin/range-diff.c +#, c-format +msgid "not a symmetric range: '%s'" +msgstr "nà raon siméadrach: '%s'" + +#: builtin/range-diff.c +msgid "need two commit ranges" +msgstr "dhá raon tiomanta ag teastáil" + +#: builtin/read-tree.c +msgid "" +"git read-tree [(-m [--trivial] [--aggressive] | --reset | --" +"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=<prefix>)\n" +" [-u | -i]] [--index-output=<file>] [--no-sparse-checkout]\n" +" (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])" + +#: builtin/read-tree.c +msgid "write resulting index to <file>" +msgstr "scrÃobh innéacs mar thoradh air go <file>" + +#: builtin/read-tree.c +msgid "only empty the index" +msgstr "ach an t-innéacs a fholmhú" + +#: builtin/read-tree.c +msgid "Merging" +msgstr "Cumaisc" + +#: builtin/read-tree.c +msgid "perform a merge in addition to a read" +msgstr "cumaisc a dhéanamh i dteannta le léamh" + +#: builtin/read-tree.c +msgid "3-way merge if no file level merging required" +msgstr "Cumaisc trà bhealach mura gá cumasc leibhéal comhaid" + +#: builtin/read-tree.c +msgid "3-way merge in presence of adds and removes" +msgstr "Cumaisc 3 bhealach i láthair breiseanna agus bainteanna" + +#: builtin/read-tree.c +msgid "same as -m, but discard unmerged entries" +msgstr "mar an gcéanna le -m, ach caith iontrálacha neamh-chumhdaithe" + +#: builtin/read-tree.c +msgid "<subdirectory>/" +msgstr "<subdirectory>/" + +#: builtin/read-tree.c +msgid "read the tree into the index under <subdirectory>/" +msgstr "léigh an crann isteach san innéacs faoi<subdirectory>/" + +#: builtin/read-tree.c +msgid "update working tree with merge result" +msgstr "crann oibre a nuashonrú le toradh cumaisc" + +#: builtin/read-tree.c +msgid "gitignore" +msgstr "gignor" + +#: builtin/read-tree.c +msgid "allow explicitly ignored files to be overwritten" +msgstr "ligean do chomhaid a dhéantar neamhaird air go sainrá" + +#: builtin/read-tree.c +msgid "don't check the working tree after merging" +msgstr "ná seiceáil an crann oibre tar éis a chumasc" + +#: builtin/read-tree.c +msgid "don't update the index or the work tree" +msgstr "ná nuashonraigh an t-innéacs nó an crann oibre" + +#: builtin/read-tree.c +msgid "skip applying sparse checkout filter" +msgstr "scipeáil scagaire seiceála neamhchoitianta a" + +#: builtin/read-tree.c +msgid "debug unpack-trees" +msgstr "crainn dÃphacáilte a dhÃfhabhtú" + +#: builtin/read-tree.c +msgid "suppress feedback messages" +msgstr "teachtaireachtaà aiseolais" + +#: builtin/read-tree.c +msgid "You need to resolve your current index first" +msgstr "Nà mór duit d'innéacs reatha a réiteach ar dtús" + +#: builtin/rebase.c +msgid "" +"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase> | --keep-base] " +"[<upstream> [<branch>]]" +msgstr "" +"<upstream><branch>git rebase [-i] [roghanna] [--exec<cmd>] [--onto " +"<newbase>| --keep-base] [[]]" + +#: builtin/rebase.c +msgid "" +"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]" +msgstr "" +"<newbase><branch>git rebase [-i] [roghanna] [--exec] [-- <cmd>onto] --root []" + +#: builtin/rebase.c sequencer.c +#, c-format +msgid "could not read '%s'." +msgstr "nà raibh '%s' in ann a léamh." + +#: builtin/rebase.c +#, c-format +msgid "could not create temporary %s" +msgstr "nà fhéadfaà %s sealadach a chruthú" + +#: builtin/rebase.c +msgid "could not mark as interactive" +msgstr "nà fhéadfaà marcáil mar idirghnÃomh" + +#: builtin/rebase.c +msgid "could not generate todo list" +msgstr "nà raibh in ann liosta todo a ghiniúint" + +#: builtin/rebase.c +msgid "a base commit must be provided with --upstream or --onto" +msgstr "caithfear gealltanas bonn a sholáthar le --upstream nó --onto" + +#: builtin/rebase.c +#, c-format +msgid "%s requires the merge backend" +msgstr "TeastaÃonn %s an cúltaca cumaisc" + +#: builtin/rebase.c +#, c-format +msgid "invalid onto: '%s'" +msgstr "neamhbhailà ar: '%s'" + +#: builtin/rebase.c +#, c-format +msgid "invalid orig-head: '%s'" +msgstr "orig-head neamhbhailÃ: '%s'" + +#: builtin/rebase.c +#, c-format +msgid "ignoring invalid allow_rerere_autoupdate: '%s'" +msgstr "neamhaird a dhéanamh de allow_rerere_autoupdate neamhbhailÃ: '%s'" + +#: builtin/rebase.c builtin/rm.c sequencer.c +#, c-format +msgid "could not remove '%s'" +msgstr "nà fhéadfaà '%s' a bhaint" + +#: builtin/rebase.c +#, c-format +msgid "" +"\n" +"git encountered an error while preparing the patches to replay\n" +"these revisions:\n" +"\n" +" %s\n" +"\n" +"As a result, git cannot rebase them." +msgstr "" +"\n" +"Bhà earráid ag git agus é ag ullmhú na paistà chun athsheinm\n" +"na hathbhreithnithe seo:\n" +"\n" +" %s\n" +"\n" +"Mar thoradh air sin, nà féidir le git iad a athbhunú." + +#: builtin/rebase.c +#, c-format +msgid "Unknown rebase-merges mode: %s" +msgstr "Modh rebase-chumaisc anaithnid: %s" + +#: builtin/rebase.c +#, c-format +msgid "could not switch to %s" +msgstr "nà fhéadfaà aistriú go %s" + +#: builtin/rebase.c +msgid "apply options and merge options cannot be used together" +msgstr "roghanna i bhfeidhm agus nà féidir roghanna cumaisc a úsáid le chéile" + +#: builtin/rebase.c +msgid "--empty=ask is deprecated; use '--empty=stop' instead." +msgstr "Tá --empty=ask dÃscrÃofa; bain úsáid as '--empty=stop' ina ionad." + +#: builtin/rebase.c +#, c-format +msgid "" +"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and " +"\"stop\"." +msgstr "" +"cineál folamh gan aithint '%s'; is iad na luachanna bailà ná “dropâ€, “keepâ€, " +"agus “stopâ€." + +#: builtin/rebase.c +msgid "" +"--rebase-merges with an empty string argument is deprecated and will stop " +"working in a future version of Git. Use --rebase-merges without an argument " +"instead, which does the same thing." +msgstr "" +"Tá --rebase-merges le argóint teaghrán folamh mÃshuanta agus stopfaidh sé ag " +"obair i leagan amach anseo de Git. Úsáid --rebase-merges gan argóint ina " +"ionad sin, a dhéanann an rud céanna." + +#: builtin/rebase.c +#, c-format +msgid "" +"%s\n" +"Please specify which branch you want to rebase against.\n" +"See git-rebase(1) for details.\n" +"\n" +" git rebase '<branch>'\n" +"\n" +msgstr "" +"%s\n" +"Sonraigh le do thoil cén brainse ar mhaith leat athbhunú ina choinne.\n" +"Féach git-rebase(1) le haghaidh sonraÃ.\n" +"\n" +"git rebase '<brainse>'\n" +"\n" + +#: builtin/rebase.c +#, c-format +msgid "" +"If you wish to set tracking information for this branch you can do so with:\n" +"\n" +" git branch --set-upstream-to=%s/<branch> %s\n" +"\n" +msgstr "" +"Más mian leat faisnéis rianaithe a shocrú don bhrainse seo is féidir leat é " +"sin a dhéanamh le:\n" +"\n" +" git branch --set-upstream-to=%s/<branch> %s\n" +"\n" + +#: builtin/rebase.c +msgid "exec commands cannot contain newlines" +msgstr "nà féidir lÃnte nua a bheith ag orduithe exec" + +#: builtin/rebase.c +msgid "empty exec command" +msgstr "ordú exec folamh" + +#: builtin/rebase.c +msgid "rebase onto given branch instead of upstream" +msgstr "athbhunú ar an mbrainse ar leith in ionad suas an sruth" + +#: builtin/rebase.c +msgid "use the merge-base of upstream and branch as the current base" +msgstr "bain úsáid as bonn cumaisc suas sruth agus brainse mar an bonn reatha" + +#: builtin/rebase.c +msgid "allow pre-rebase hook to run" +msgstr "ligean do chrúca réamh-athbhunaithe rith" + +#: builtin/rebase.c +msgid "be quiet. implies --no-stat" +msgstr "a bheith ciúin. tugann le tuiscint --no-stat" + +#: builtin/rebase.c +msgid "display a diffstat of what changed upstream" +msgstr "taispeáint diffstat den rud a d'athraigh suas an sruth" + +#: builtin/rebase.c +msgid "do not show diffstat of what changed upstream" +msgstr "ná taispeáin diffstat den mhéid a d'athraigh suas an sruth" + +#: builtin/rebase.c +msgid "add a Signed-off-by trailer to each commit" +msgstr "cuir leantóir sÃnithe le gach tiomantas" + +#: builtin/rebase.c +msgid "make committer date match author date" +msgstr "dáta an údair comhoiriúnaithe dáta a dhéanamh" + +#: builtin/rebase.c +msgid "ignore author date and use current date" +msgstr "neamhaird a dhéanamh ar dháta údair agus bain úsáid as" + +#: builtin/rebase.c +msgid "synonym of --reset-author-date" +msgstr "comhchiallach de --reset-author-date" + +#: builtin/rebase.c +msgid "passed to 'git apply'" +msgstr "cuireadh chuig 'git apply'" + +#: builtin/rebase.c +msgid "ignore changes in whitespace" +msgstr "neamhaird a dhéanamh ar athruithe i spás bán" + +#: builtin/rebase.c +msgid "cherry-pick all commits, even if unchanged" +msgstr "roghnaigh silÃnà gach gealltanas, fiú mura bhfuil gan athrú" + +#: builtin/rebase.c +msgid "continue" +msgstr "leanúint" + +#: builtin/rebase.c +msgid "skip current patch and continue" +msgstr "scipeáil an paiste reatha agus lean ar aghaidh" + +#: builtin/rebase.c +msgid "abort and check out the original branch" +msgstr "déan deireadh a chur agus seiceáil ar an mbrainse bunaidh" + +#: builtin/rebase.c +msgid "abort but keep HEAD where it is" +msgstr "déan deireadh ach coinnigh CEAD san áit a bhfuil sé" + +#: builtin/rebase.c +msgid "edit the todo list during an interactive rebase" +msgstr "cuir an liosta todo in eagar le linn athbhunú idirghnÃomhach" + +#: builtin/rebase.c +msgid "show the patch file being applied or merged" +msgstr "taispeáin an comhad paiste atá á chur i bhfeidhm nó á chumas" + +#: builtin/rebase.c +msgid "use apply strategies to rebase" +msgstr "úsáid straitéisà i bhfeidhm chun athbhunú" + +#: builtin/rebase.c +msgid "use merging strategies to rebase" +msgstr "straitéisà cumaisc a úsáid chun athbhunú" + +#: builtin/rebase.c +msgid "let the user edit the list of commits to rebase" +msgstr "lig don úsáideoir liosta na dtiomantas a athbhunú a chur in eagar" + +#: builtin/rebase.c +msgid "(REMOVED) was: try to recreate merges instead of ignoring them" +msgstr "" +"(Bainte) a bhÃ: déan iarracht cumaisc a athchruthú in ionad neamhaird a " +"dhéanamh orthu" + +#: builtin/rebase.c builtin/revert.c +msgid "how to handle commits that become empty" +msgstr "conas gealltanais a éirÃonn folamh a láimhseáil" + +#: builtin/rebase.c +msgid "keep commits which start empty" +msgstr "coinnigh gealltanais a thosaÃonn folamh" + +#: builtin/rebase.c +msgid "move commits that begin with squash!/fixup! under -i" +msgstr "gealltanna gluaiseachta a thosaÃonn le squash! /socrú! faoi -i" + +#: builtin/rebase.c +msgid "update branches that point to commits that are being rebased" +msgstr "brainsà a nuashonrú a thugann in iúl do ghealltanais atá á athbhunú" + +#: builtin/rebase.c +msgid "add exec lines after each commit of the editable list" +msgstr "" +"lÃnte exec a chur leis tar éis gach tiomantas den liosta in-eagarthóireachta" + +#: builtin/rebase.c +msgid "allow rebasing commits with empty messages" +msgstr "ligean do thiomantas a athbhunú le teachtaireachtaà folamh" + +#: builtin/rebase.c +msgid "try to rebase merges instead of skipping them" +msgstr "déan iarracht cumaisc a athbhunú in ionad iad a scipeáil" + +#: builtin/rebase.c +msgid "use 'merge-base --fork-point' to refine upstream" +msgstr "bain úsáid as 'merge-base --fork-point' chun suas an sruth a bheachtú" + +#: builtin/rebase.c +msgid "use the given merge strategy" +msgstr "bain úsáid as an straitéis cumaisc tugtha" + +#: builtin/rebase.c builtin/revert.c +msgid "option" +msgstr "rogha" + +#: builtin/rebase.c +msgid "pass the argument through to the merge strategy" +msgstr "an argóint a chur ar aghaidh chuig an straitéis cumaisc" + +#: builtin/rebase.c +msgid "rebase all reachable commits up to the root(s)" +msgstr "" +"athbhunú gach gealltanas inrochtana suas go dtà an fhréamh/na fréamhacha" + +#: builtin/rebase.c +msgid "automatically re-schedule any `exec` that fails" +msgstr "athsceidealú go huathoibrÃoch aon `executaithe' a the" + +#: builtin/rebase.c +msgid "apply all changes, even those already present upstream" +msgstr "gach athrú a chur i bhfeidhm, fiú iad siúd atá i láthair suas an" + +#: builtin/rebase.c +msgid "It looks like 'git am' is in progress. Cannot rebase." +msgstr "Is cosúil go bhfuil 'git am' ar siúl. Nà féidir athbhunú." + +#: builtin/rebase.c +msgid "" +"`rebase --preserve-merges` (-p) is no longer supported.\n" +"Use `git rebase --abort` to terminate current rebase.\n" +"Or downgrade to v2.33, or earlier, to complete the rebase." +msgstr "" +"Nà thacaÃtear le `rebase --preserve-merges` (-p) a thuilleadh.\n" +"Úsáid `git rebase --abort` chun rebase reatha a fhoirceannadh.\n" +"Nó Ãosghrádú go v2.33, nó nÃos luaithe, chun an athbhunú a chur i gcrÃch." + +#: builtin/rebase.c +msgid "" +"--preserve-merges was replaced by --rebase-merges\n" +"Note: Your `pull.rebase` configuration may also be set to 'preserve',\n" +"which is no longer supported; use 'merges' instead" +msgstr "" +"Cuireadh --preserve-merges in ionad --rebase-merges\n" +"Nóta: Féadfar do chumraÃocht `pull.rebase` a shocrú chun 'caomhnú' freisin,\n" +"nach dtacaÃtear leis a thuilleadh; bain úsáid as 'cumaisc' ina ionad" + +#: builtin/rebase.c +msgid "no rebase in progress" +msgstr "nÃl aon athbhunú ar siúl" + +#: builtin/rebase.c +msgid "The --edit-todo action can only be used during interactive rebase." +msgstr "" +"Nà féidir an gnÃomh --edit-todo a úsáid ach le linn athbhunú idirghnÃomhach." + +#: builtin/rebase.c +msgid "Cannot read HEAD" +msgstr "Nà féidir HEAD a léamh" + +#: builtin/rebase.c +msgid "" +"You must edit all merge conflicts and then\n" +"mark them as resolved using git add" +msgstr "" +"Nà mór duit gach coinbhleacht cumaisc a chur in eagar agus ansin\n" +"iad a mharcáil mar réitigh ag úsáid git add" + +#: builtin/rebase.c +msgid "could not discard worktree changes" +msgstr "nà fhéadfadh athruithe crann oibre a dhiúscairt" + +#: builtin/rebase.c +#, c-format +msgid "could not move back to %s" +msgstr "nà fhéadfaà bogadh ar ais chuig %s" + +#: builtin/rebase.c +#, c-format +msgid "" +"It seems that there is already a %s directory, and\n" +"I wonder if you are in the middle of another rebase. If that is the\n" +"case, please try\n" +"\t%s\n" +"If that is not the case, please\n" +"\t%s\n" +"and run me again. I am stopping in case you still have something\n" +"valuable there.\n" +msgstr "" +"DealraÃonn sé go bhfuil eolaire %s ann cheana féin, agus\n" +"N'fheadar an bhfuil tú i lár athbhunaithe eile. Más é sin an\n" +"cás, déan iarracht\n" +" %s\n" +"Mura bhfuil sé sin an cás, le do thoil\n" +" %s\n" +"agus rith mé arÃs. Táim ag stopadh i gcás go bhfuil rud éigin agat fós\n" +"luachmhar ansin.\n" + +#: builtin/rebase.c +msgid "switch `C' expects a numerical value" +msgstr "tá an lasc `C' ag súil le luach uimhriúil" + +#: builtin/rebase.c +msgid "" +"apply options are incompatible with rebase.rebaseMerges. Consider adding --" +"no-rebase-merges" +msgstr "" +"tá roghanna cur i bhfeidhm neamhoiriúnach le rebase.rebaseMerges. Smaoinigh " +"ar --no-rebase-merges a chur leis" + +#: builtin/rebase.c +msgid "" +"apply options are incompatible with rebase.updateRefs. Consider adding --no-" +"update-refs" +msgstr "" +"tá roghanna cur i bhfeidhm neamhoiriúnach le rebase.updateRefs. Smaoinigh ar " +"--no-update-refs a chur leis" + +#: builtin/rebase.c +#, c-format +msgid "Unknown rebase backend: %s" +msgstr "Cúltaca athbhunaithe anaithnid: %s" + +#: builtin/rebase.c +msgid "--reschedule-failed-exec requires --exec or --interactive" +msgstr "ÉilÃonn --reschedule-failed-exec --exec nó --interactive" + +#: builtin/rebase.c +#, c-format +msgid "invalid upstream '%s'" +msgstr "neamhbhailà suas sruth '%s'" + +#: builtin/rebase.c +msgid "Could not create new root commit" +msgstr "Nà fhéadfaà tiomantas fréimhe nua a chruthú" + +#: builtin/rebase.c +#, c-format +msgid "no such branch/commit '%s'" +msgstr "gan aon bhrainse/tiomantas '%s' den sórt sin" + +#: builtin/rebase.c builtin/submodule--helper.c +#, c-format +msgid "No such ref: %s" +msgstr "NÃl aon tagairt den sórt sin: %s" + +#: builtin/rebase.c +msgid "Could not resolve HEAD to a commit" +msgstr "Nà fhéadfaà HEAD a réiteach le tiomantas" + +#: builtin/rebase.c +#, c-format +msgid "'%s': need exactly one merge base with branch" +msgstr "'%s': teastaÃonn bonn cumaisc amháin dÃreach le brainse" + +#: builtin/rebase.c +#, c-format +msgid "'%s': need exactly one merge base" +msgstr "'%s': teastaÃonn bonn cumaisc amháin dÃreach" + +#: builtin/rebase.c +#, c-format +msgid "Does not point to a valid commit '%s'" +msgstr "Nà thugann sé in iúl do thiomantas bailà '%s'" + +#: builtin/rebase.c +msgid "HEAD is up to date." +msgstr "Tá HEAD cothrom le dáta." + +#: builtin/rebase.c +#, c-format +msgid "Current branch %s is up to date.\n" +msgstr "Tá an brainse reatha %s cothrom le dáta.\n" + +#: builtin/rebase.c +msgid "HEAD is up to date, rebase forced." +msgstr "Tá HEAD cothrom le dáta, athbhunú éigeantach." + +#: builtin/rebase.c +#, c-format +msgid "Current branch %s is up to date, rebase forced.\n" +msgstr "Tá an brainse reatha %s cothrom le dáta, athbhunú éigeantach.\n" + +#: builtin/rebase.c +msgid "The pre-rebase hook refused to rebase." +msgstr "Dhiúltaigh an crúca réamh-athbhunú a athbhunú." + +#: builtin/rebase.c +#, c-format +msgid "Changes to %s:\n" +msgstr "Athruithe ar %s:\n" + +#: builtin/rebase.c +#, c-format +msgid "Changes from %s to %s:\n" +msgstr "Athruithe ó %s go %s:\n" + +#: builtin/rebase.c +#, c-format +msgid "First, rewinding head to replay your work on top of it...\n" +msgstr "" +"Ar dtús, téann athfhillte chun do chuid oibre a athsheinm ar a bharr...\n" + +#: builtin/rebase.c +msgid "Could not detach HEAD" +msgstr "Nà fhéadfaà CEAD a dhÃcheangal" + +#: builtin/rebase.c +#, c-format +msgid "Fast-forwarded %s to %s.\n" +msgstr "Cuireadh %s ar aghaidh go tapa chuig %s.\n" + +#: builtin/receive-pack.c +msgid "git receive-pack <git-dir>" +msgstr "git receive-pack <git-dir>" + +#: builtin/receive-pack.c +msgid "" +"By default, updating the current branch in a non-bare repository\n" +"is denied, because it will make the index and work tree inconsistent\n" +"with what you pushed, and will require 'git reset --hard' to match\n" +"the work tree to HEAD.\n" +"\n" +"You can set the 'receive.denyCurrentBranch' configuration variable\n" +"to 'ignore' or 'warn' in the remote repository to allow pushing into\n" +"its current branch; however, this is not recommended unless you\n" +"arranged to update its work tree to match what you pushed in some\n" +"other way.\n" +"\n" +"To squelch this message and still keep the default behaviour, set\n" +"'receive.denyCurrentBranch' configuration variable to 'refuse'." +msgstr "" +"De réir réamhshocraithe, nuashonrú an bhrainse reatha i stóras neamh-lom\n" +"diúltaÃtear, toisc go ndéanfaidh sé an t-innéacs agus an crann oibre " +"neamhréireach\n" +"leis an méid a bhrúigh tú, agus beidh 'git reset --hard' ag teastáil uait " +"chun a mheaitseáil\n" +"an crann oibre go HEAD.\n" +"\n" +"Is féidir leat an t-athróg cumraÃochta 'receive.denyCurrentBranch' a shocrú\n" +"chun 'neamhaird' nó 'rabhadh' sa stór iargúlta chun ligean a bhrú isteach\n" +"a bhrainse reatha; áfach, nà mholtar é seo mura bhfuil tú\n" +"socraithe chun a chrann oibre a nuashonrú chun a mheaitseáil ar an méid a " +"bhrú tú isteach\n" +"bealach eile.\n" +"\n" +"Chun an teachtaireacht seo a bhrú agus an t-iompar réamhshocraithe a " +"choinneáil fós, socraigh\n" +"Athróg cumraÃochta 'receive.denyCurrentBranch' go 'refuse'." + +#: builtin/receive-pack.c +msgid "" +"By default, deleting the current branch is denied, because the next\n" +"'git clone' won't result in any file checked out, causing confusion.\n" +"\n" +"You can set 'receive.denyDeleteCurrent' configuration variable to\n" +"'warn' or 'ignore' in the remote repository to allow deleting the\n" +"current branch, with or without a warning message.\n" +"\n" +"To squelch this message, you can set it to 'refuse'." +msgstr "" +"De réir réamhshocraithe, diúltaÃtear an bhrainse reatha a scriosadh, mar an " +"chéad chéad\n" +"Nà bheidh aon chomhad seiceáilte amach mar thoradh ar 'git clone', rud a " +"chruthaÃonn mearbhall.\n" +"\n" +"Is féidir leat athróg cumraÃochta 'receive.denyDeleteCurrent' a shocrú go\n" +"'rabhadh 'nó' neamhaird 'sa stór iargúlta chun cead a scriosadh an\n" +"brainse reatha, le teachtaireacht rabhaidh nó gan é.\n" +"\n" +"Chun an teachtaireacht seo a ghearradh, is féidir leat é a shocrú go 'diúlt'." + +#: builtin/receive-pack.c +msgid "quiet" +msgstr "ciúin" + +#: builtin/receive-pack.c +msgid "you must specify a directory" +msgstr "nà mór duit eolaire a shonrú" + +#: builtin/reflog.c +msgid "git reflog [show] [<log-options>] [<ref>]" +msgstr "<ref>git reflog [taispeáin] [] [<log-options>]" + +#: builtin/reflog.c +msgid "git reflog list" +msgstr "git reflog liosta" + +#: builtin/reflog.c +msgid "" +"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" +" [--rewrite] [--updateref] [--stale-fix]\n" +" [--dry-run | -n] [--verbose] [--all [--single-worktree] | " +"<refs>...]" +msgstr "" +"<time><time>git reflog in éag [--expire=] [--expire-unreachable=]\n" +" [--athscrÃobh] [--updateref] [--stale-fix]\n" +" <refs>[--dry-run | -n] [--verbose] [--all [--one-worktree] |...]" + +#: builtin/reflog.c +msgid "" +"git reflog delete [--rewrite] [--updateref]\n" +" [--dry-run | -n] [--verbose] <ref>@{<specifier>}..." +msgstr "" +"git reflog scrios [--athscrÃobh] [--updateref]\n" +" <ref><specifier>[--driy-run | -n] [--verbose] @ {}..." + +#: builtin/reflog.c +msgid "git reflog exists <ref>" +msgstr "git reflog ann <ref>" + +#: builtin/reflog.c +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "<refs>git reflog titim [--all [--one-worktree] |...]" + +#: builtin/reflog.c +#, c-format +msgid "invalid timestamp '%s' given to '--%s'" +msgstr "stampa ama neamhbhailà '%s' a thugtar do '--%s'" + +#: builtin/reflog.c sequencer.c +#, c-format +msgid "%s does not accept arguments: '%s'" +msgstr "Nà ghlacann %s le hargóintÃ: '%s'" + +#: builtin/reflog.c +msgid "do not actually prune any entries" +msgstr "ná déan aon iontrálacha a ghearradh" + +#: builtin/reflog.c +msgid "" +"rewrite the old SHA1 with the new SHA1 of the entry that now precedes it" +msgstr "" +"athscrÃobh an sean-SHA1 leis an SHA1 nua den iontráil atá roimh ré anois" + +#: builtin/reflog.c +msgid "update the reference to the value of the top reflog entry" +msgstr "an tagairt do luach an iontráil reflog barr a nuashonrú" + +#: builtin/reflog.c +msgid "print extra information on screen" +msgstr "faisnéis bhreise a phriontáil ar an sc" + +#: builtin/reflog.c +msgid "timestamp" +msgstr "stampa ama" + +#: builtin/reflog.c +msgid "prune entries older than the specified time" +msgstr "iontrálacha brónta nÃos sine ná an t-am sonraithe" + +#: builtin/reflog.c +msgid "" +"prune entries older than <time> that are not reachable from the current tip " +"of the branch" +msgstr "" +"nà féidir iontrálacha br <time>ónta nÃos sine ná sin a bhaint amach ó bharr " +"reatha na brainse" + +#: builtin/reflog.c +msgid "prune any reflog entries that point to broken commits" +msgstr "" +"aon iontrálacha reflog a ghearradh a chuireann in iúl do thiomantas briste" + +#: builtin/reflog.c +msgid "process the reflogs of all references" +msgstr "athfhillteacha na dtagairtà go léir a phróiseáil" + +#: builtin/reflog.c +msgid "limits processing to reflogs from the current worktree only" +msgstr "" +"teorann sé leis an bpróiseáil do athfhillteacha ón gcrann oibre reatha amháin" + +#: builtin/reflog.c +#, c-format +msgid "Marking reachable objects..." +msgstr "Rudaà inrochtana a mharcáil..." + +#: builtin/reflog.c +#, c-format +msgid "reflog could not be found: '%s'" +msgstr "nà fhéadfaà reflog a fháil: '%s'" + +#: builtin/reflog.c +msgid "no reflog specified to delete" +msgstr "nÃl aon reflog sonraithe le scriosadh" + +#: builtin/reflog.c +#, c-format +msgid "invalid ref format: %s" +msgstr "formáid tagartha neamhbhailÃ: %s" + +#: builtin/reflog.c +msgid "drop the reflogs of all references" +msgstr "scaoil athbhreithniú na dtagairtà go léir" + +#: builtin/reflog.c +msgid "drop reflogs from the current worktree only" +msgstr "scaoil reflogs ón gcrann oibre reatha amháin" + +#: builtin/reflog.c +msgid "references specified along with --all" +msgstr "tagairtà sonraithe in éineacht le --all" + +#: builtin/refs.c +msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" +msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" + +#: builtin/refs.c +msgid "git refs verify [--strict] [--verbose]" +msgstr "fÃoraÃonn git refs [--strong] [--verbose]" + +#: builtin/refs.c +msgid "specify the reference format to convert to" +msgstr "sonraigh an fhormáid tagartha le tiontú" + +#: builtin/refs.c +msgid "perform a non-destructive dry-run" +msgstr "rith tirim neamh-millteach a dhéanamh" + +#: builtin/refs.c +msgid "drop reflogs entirely during the migration" +msgstr "titim athfhóga go hiomlán le linn na himirce" + +#: builtin/refs.c +msgid "missing --ref-format=<format>" +msgstr "ar iarraidh --ref-format=<format>" + +#: builtin/refs.c +#, c-format +msgid "repository already uses '%s' format" +msgstr "úsáideann stór formáid '%s' cheana féin" + +#: builtin/refs.c +msgid "enable strict checking" +msgstr "cumasú seiceáil docht" + +#: builtin/refs.c +msgid "'git refs verify' takes no arguments" +msgstr "Nà ghlacann 'git refs verify' aon argóintÃ" + +#: builtin/remote.c +msgid "" +"git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" +"mirror=<fetch|push>] <name> <url>" +msgstr "" +"git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--" +"mirror=<fetch|push>] <name> <url>" + +#: builtin/remote.c +msgid "git remote rename [--[no-]progress] <old> <new>" +msgstr "git remote rename [--[no-]progress] <old> <new>" + +#: builtin/remote.c +msgid "git remote remove <name>" +msgstr "git remote remove <name>" + +#: builtin/remote.c +msgid "git remote set-head <name> (-a | --auto | -d | --delete | <branch>)" +msgstr "git remote set-head <name> (-a | --auto | -d | --delete | <branch>)" + +#: builtin/remote.c +msgid "git remote [-v | --verbose] show [-n] <name>" +msgstr "git remote [-v | --verbose] show [-n] <name>" + +#: builtin/remote.c +msgid "git remote prune [-n | --dry-run] <name>" +msgstr "git remote prune [-n | --dry-run] <name>" + +#: builtin/remote.c +msgid "" +"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]" +msgstr "" +"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]" + +#: builtin/remote.c +msgid "git remote set-branches [--add] <name> <branch>..." +msgstr "git remote set-branches [--add] <name> <branch>..." + +#: builtin/remote.c +msgid "git remote get-url [--push] [--all] <name>" +msgstr "git remote get-url [--push] [--all] <name>" + +#: builtin/remote.c +msgid "git remote set-url [--push] <name> <newurl> [<oldurl>]" +msgstr "git remote set-url [--push] <name> <newurl> [<oldurl>]" + +#: builtin/remote.c +msgid "git remote set-url --add <name> <newurl>" +msgstr "git iargúlta set-url --add <name><newurl>" + +#: builtin/remote.c +msgid "git remote set-url --delete <name> <url>" +msgstr "git iargúlta set-url --delete <name><url>" + +#: builtin/remote.c +msgid "git remote add [<options>] <name> <url>" +msgstr "git remote add [<options>] <name> <url>" + +#: builtin/remote.c +msgid "git remote set-branches <name> <branch>..." +msgstr "git remote set-branches <name> <branch>..." + +#: builtin/remote.c +msgid "git remote set-branches --add <name> <branch>..." +msgstr "git remote set-branches --add <name> <branch>..." + +#: builtin/remote.c +msgid "git remote show [<options>] <name>" +msgstr "git remote show [<options>] <name>" + +#: builtin/remote.c +msgid "git remote prune [<options>] <name>" +msgstr "git remote prune [<options>] <name>" + +#: builtin/remote.c +msgid "git remote update [<options>] [<group> | <remote>]..." +msgstr "git remote update [<options>] [<group> | <remote>]..." + +#: builtin/remote.c +#, c-format +msgid "Updating %s" +msgstr "Nuashonrú %s" + +#: builtin/remote.c +#, c-format +msgid "Could not fetch %s" +msgstr "NÃorbh fhéidir %s a fháil" + +#: builtin/remote.c +msgid "" +"--mirror is dangerous and deprecated; please\n" +"\t use --mirror=fetch or --mirror=push instead" +msgstr "" +"--mirror tá scáthán contúirteach agus mÃchuir; le do thoil\n" +" bain úsáid as --mirror=fetch nó --mirror=push ina ionad" + +#: builtin/remote.c +#, c-format +msgid "unknown --mirror argument: %s" +msgstr "argóint --mirror anaithnid: %s" + +#: builtin/remote.c +msgid "fetch the remote branches" +msgstr "faigh na brainsà iargúlta" + +#: builtin/remote.c +msgid "" +"import all tags and associated objects when fetching\n" +"or do not fetch any tag at all (--no-tags)" +msgstr "" +"iompórtáil gach clib agus rudaà gaolmhara agus tú ag tabhairt\n" +"nó ná faigh aon chlib ar chor ar bith (--no-tags)" + +#: builtin/remote.c +msgid "branch(es) to track" +msgstr "brainse (Ã) chun rianú" + +#: builtin/remote.c +msgid "master branch" +msgstr "máistirbhrainse" + +#: builtin/remote.c +msgid "set up remote as a mirror to push to or fetch from" +msgstr "cuir iargúlta ar bun mar scáthán chun brú chuig nó a fháil uaidh" + +#: builtin/remote.c +msgid "specifying a master branch makes no sense with --mirror" +msgstr "nÃl aon chiall ar mháistirbhrainse a shonrú le --mirror" + +#: builtin/remote.c +msgid "specifying branches to track makes sense only with fetch mirrors" +msgstr "nÃÃl ciall le brainsà a shonrú le rianú ach le scátháin faighte" + +#: builtin/remote.c +#, c-format +msgid "remote %s already exists." +msgstr "iargúlta %s ann cheana féin." + +#: builtin/remote.c +#, c-format +msgid "Could not setup master '%s'" +msgstr "Nà raibh an máistir '%s' a shocrú" + +#: builtin/remote.c trailer.c +#, c-format +msgid "more than one %s" +msgstr "nÃos mó ná %s amháin" + +#: builtin/remote.c +#, c-format +msgid "unhandled branch.%s.rebase=%s; assuming 'true'" +msgstr "brainse gan láimhseáil. %s.rebase=%s; ag glacadh leis 'fÃor'" + +#: builtin/remote.c +#, c-format +msgid "Could not get fetch map for refspec %s" +msgstr "NÃorbh fhéidir léarscáil a fháil do refspec %s" + +#: builtin/remote.c +msgid "(matching)" +msgstr "(meaitseáil)" + +#: builtin/remote.c +msgid "(delete)" +msgstr "(scrios)" + +#: builtin/remote.c +#, c-format +msgid "could not set '%s'" +msgstr "nà fhéadfaà '%s' a shocrú" + +#: builtin/remote.c config.c +#, c-format +msgid "could not unset '%s'" +msgstr "nà fhéadfaà '%s' a dhÃshocrú" + +#: builtin/remote.c +#, c-format +msgid "" +"The %s configuration remote.pushDefault in:\n" +"\t%s:%d\n" +"now names the non-existent remote '%s'" +msgstr "" +"An cumraÃocht %s remote.pushDefault i:\n" +" %s: %d\n" +"ainmnÃonn anois an iargúlta nach bhfuil ann '%s'" + +#: builtin/remote.c +#, c-format +msgid "No such remote: '%s'" +msgstr "NÃl aon iargúlta den sórt sin: '%s'" + +#: builtin/remote.c +#, c-format +msgid "Could not rename config section '%s' to '%s'" +msgstr "Nà fhéadfaà an chuid cumraithe '%s' a athainmniú go '%s'" + +#: builtin/remote.c +#, c-format +msgid "" +"Not updating non-default fetch refspec\n" +"\t%s\n" +"\tPlease update the configuration manually if necessary." +msgstr "" +"Gan teacht refspec neamh-réamhshocraithe a nuashonrú\n" +" %s\n" +" Nuashonraigh an chumraÃocht de láimh más gá." + +#: builtin/remote.c +msgid "Renaming remote references" +msgstr "Tagairtà cianda a athainmniú" + +#: builtin/remote.c +#, c-format +msgid "deleting '%s' failed" +msgstr "theip ar '%s' a scriosadh" + +#: builtin/remote.c +#, c-format +msgid "creating '%s' failed" +msgstr "theip ar chruthú '%s'" + +#: builtin/remote.c +msgid "" +"Note: A branch outside the refs/remotes/ hierarchy was not removed;\n" +"to delete it, use:" +msgid_plural "" +"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n" +"to delete them, use:" +msgstr[0] "" +"Nóta: NÃor baineadh brainse lasmuigh den ordlathas refs/remotes/;\n" +"chun é a scriosadh, bain úsáid as:" +msgstr[1] "" +"Nóta: NÃor baineadh roinnt brainsà lasmuigh den ordlathas refs/remotes/;\n" +"chun iad a scriosadh, bain úsáid as:" +msgstr[2] "" +"Nóta: NÃor baineadh roinnt brainsà lasmuigh den ordlathas refs/remotes/;\n" +"chun iad a scriosadh, bain úsáid as:" + +#: builtin/remote.c +#, c-format +msgid "Could not remove config section '%s'" +msgstr "Nà raibh an chuid cumraithe '%s' in ann a bhaint" + +#: builtin/remote.c +#, c-format +msgid " new (next fetch will store in remotes/%s)" +msgstr " nua (stóráilfidh an chéad fhaighteacht eile i iargúlta/%s)" + +#: builtin/remote.c +msgid " tracked" +msgstr " rianaithe" + +#: builtin/remote.c +msgid " skipped" +msgstr " scipeáilte" + +#: builtin/remote.c +msgid " stale (use 'git remote prune' to remove)" +msgstr " seasta (bain úsáid as 'git remote prune' chun a bhaint)" + +#: builtin/remote.c +msgid " ???" +msgstr " ???" + +#: builtin/remote.c +#, c-format +msgid "invalid branch.%s.merge; cannot rebase onto > 1 branch" +msgstr "brainse neamhbhailÃ. %s.merge; nà féidir athbhunú ar> 1 bhrainse" + +#: builtin/remote.c +#, c-format +msgid "rebases interactively onto remote %s" +msgstr "athbhunú go hidirghnÃomhach ar iargúlta %s" + +#: builtin/remote.c +#, c-format +msgid "rebases interactively (with merges) onto remote %s" +msgstr "athbhunú idirghnÃomhach (le cumaisc) ar iargúlta %s" + +#: builtin/remote.c +#, c-format +msgid "rebases onto remote %s" +msgstr "athbhunú ar iargúlta %s" + +#: builtin/remote.c +#, c-format +msgid " merges with remote %s" +msgstr " merges with remote %s" + +#: builtin/remote.c +#, c-format +msgid "merges with remote %s" +msgstr "cumasc le iargúlta %s" + +#: builtin/remote.c +#, c-format +msgid "%-*s and with remote %s\n" +msgstr "%-*s agus le iargúlta %s\n" + +#: builtin/remote.c +msgid "create" +msgstr "cruthú" + +#: builtin/remote.c +msgid "delete" +msgstr "scriosadh" + +#: builtin/remote.c +msgid "up to date" +msgstr "cothrom le dáta" + +#: builtin/remote.c +msgid "fast-forwardable" +msgstr "tapa a sheoladh" + +#: builtin/remote.c +msgid "local out of date" +msgstr "áitiúil as dáta" + +#: builtin/remote.c +#, c-format +msgid " %-*s forces to %-*s (%s)" +msgstr " fórsaà %-*s go %-*s (%s)" + +#: builtin/remote.c +#, c-format +msgid " %-*s pushes to %-*s (%s)" +msgstr " %-*s ag brú go %-*s (%s)" + +#: builtin/remote.c +#, c-format +msgid " %-*s forces to %s" +msgstr " feidhmÃonn %-*s chuig %s" + +#: builtin/remote.c +#, c-format +msgid " %-*s pushes to %s" +msgstr " %-*s ag brú chuig %s" + +#: builtin/remote.c +msgid "do not query remotes" +msgstr "ná fiosraigh iargúlta" + +#: builtin/remote.c +#, c-format +msgid "* remote %s" +msgstr "* iargúlta %s" + +#: builtin/remote.c +#, c-format +msgid " Fetch URL: %s" +msgstr " Faigh URL: %s" + +#. TRANSLATORS: the colon ':' should align +#. with the one in " Fetch URL: %s" +#. translation. +#. +#: builtin/remote.c +#, c-format +msgid " Push URL: %s" +msgstr " Brúigh URL: %s" + +#: builtin/remote.c +msgid "(no URL)" +msgstr "(gan URL)" + +#: builtin/remote.c +#, c-format +msgid " HEAD branch: %s" +msgstr " Brainse CEANN: %s" + +#: builtin/remote.c +msgid "(not queried)" +msgstr "(gan iarraidh)" + +#: builtin/remote.c +msgid "(unknown)" +msgstr "(anaithnid)" + +#: builtin/remote.c +#, c-format +msgid "" +" HEAD branch (remote HEAD is ambiguous, may be one of the following):\n" +msgstr "" +" Brainse HEAD (tá CEAD iargúlta débhrÃoch, d'fhéadfadh a bheith ar cheann " +"de na nithe seo a leanas)\n" + +#: builtin/remote.c +#, c-format +msgid " Remote branch:%s" +msgid_plural " Remote branches:%s" +msgstr[0] " Brainse iargúlta: %s" +msgstr[1] " Brainsà iargúlta:%s" +msgstr[2] " Brainsà iargúlta:%s" + +#: builtin/remote.c +msgid " (status not queried)" +msgstr " (nÃor fiosraÃodh an stádas)" + +#: builtin/remote.c +msgid " Local branch configured for 'git pull':" +msgid_plural " Local branches configured for 'git pull':" +msgstr[0] " Brainse áitiúil cumraithe le haghaidh 'git pull':" +msgstr[1] " Craobhacha áitiúla cumraithe le haghaidh 'git pull':" +msgstr[2] " Craobhacha áitiúla cumraithe le haghaidh 'git pull':" + +#: builtin/remote.c +msgid " Local refs will be mirrored by 'git push'" +msgstr " Déanfar tagairtà áitiúla a léiriú le 'git push'" + +#: builtin/remote.c +#, c-format +msgid " Local ref configured for 'git push'%s:" +msgid_plural " Local refs configured for 'git push'%s:" +msgstr[0] " Tagairt áitiúil cumraithe le haghaidh 'git push'%s:" +msgstr[1] " Tagairtà áitiúla cumraithe le haghaidh 'git push'%s:" +msgstr[2] " Tagairtà áitiúla cumraithe le haghaidh 'git push'%s:" + +#: builtin/remote.c +#, c-format +msgid "'%s/HEAD' is unchanged and points to '%s'\n" +msgstr "NÃl '%s/head' gan athrú agus dÃrÃonn sé chuig '%s'\n" + +#: builtin/remote.c +#, c-format +msgid "'%s/HEAD' has changed from '%s' and now points to '%s'\n" +msgstr "Tá '%s/head' athraithe ó '%s' agus léirÃonn sé anois chuig '%s'\n" + +#: builtin/remote.c +#, c-format +msgid "'%s/HEAD' is now created and points to '%s'\n" +msgstr "CruthaÃtear '%s/head' anois agus léirÃonn sé chuig '%s'\n" + +#: builtin/remote.c +#, c-format +msgid "'%s/HEAD' was detached at '%s' and now points to '%s'\n" +msgstr "Bhà '%s/head' scoite ag '%s' agus dÃrÃonn sé anois chuig '%s'\n" + +#: builtin/remote.c +#, c-format +msgid "" +"'%s/HEAD' used to point to '%s' (which is not a remote branch), but now " +"points to '%s'\n" +msgstr "" +"Úsáidtear '%s/head' chun dÃriú chuig '%s' (nach brainse iargúlta é), ach " +"léirÃonn sé anois chuig '%s'\n" + +#: builtin/remote.c +msgid "set refs/remotes/<name>/HEAD according to remote" +msgstr "socraigh refs/remotes/<name>/HEAD de réir an chianrialtáin" + +#: builtin/remote.c +msgid "delete refs/remotes/<name>/HEAD" +msgstr "scrios refs/remotes/<name>/HEAD" + +#: builtin/remote.c +msgid "Cannot determine remote HEAD" +msgstr "Nà féidir CEAD cianda a chinneadh" + +#: builtin/remote.c +msgid "Multiple remote HEAD branches. Please choose one explicitly with:" +msgstr "" +"Brainsà iomadúla HEAD iargúlta. Roghnaigh ceann go sainráite le do thoil:" + +#: builtin/remote.c +#, c-format +msgid "Could not delete %s" +msgstr "Nà fhéadfaà %s a scriosadh" + +#: builtin/remote.c +#, c-format +msgid "Not a valid ref: %s" +msgstr "Nà tagairt bailÃ: %s" + +#: builtin/remote.c +#, c-format +msgid "Could not set up %s" +msgstr "NÃor féidir %s a chur ar bun" + +#: builtin/remote.c +#, c-format +msgid " %s will become dangling!" +msgstr " Beidh %s ag crochadh!" + +#: builtin/remote.c +#, c-format +msgid " %s has become dangling!" +msgstr " tá %s ag crochadh!" + +#: builtin/remote.c +#, c-format +msgid "Pruning %s" +msgstr "Bearradh %s" + +#: builtin/remote.c +#, c-format +msgid "URL: %s" +msgstr "URL: %s" + +#: builtin/remote.c +#, c-format +msgid " * [would prune] %s" +msgstr " * [bhearna] %s" + +#: builtin/remote.c +#, c-format +msgid " * [pruned] %s" +msgstr " * [gearrtha] %s" + +#: builtin/remote.c +msgid "prune remotes after fetching" +msgstr "iomadáin brónta tar éis a fháil" + +#: builtin/remote.c +#, c-format +msgid "No such remote '%s'" +msgstr "NÃl aon iargúlta '%s' den sórt sin" + +#: builtin/remote.c +msgid "add branch" +msgstr "cuir brainse" + +#: builtin/remote.c +msgid "no remote specified" +msgstr "gan aon iargúlta sonraithe" + +#: builtin/remote.c +msgid "query push URLs rather than fetch URLs" +msgstr "cuir fiosrúcháin ar URLanna brú seachas URLanna aisghabhála" + +#: builtin/remote.c +msgid "return all URLs" +msgstr "gach URL a thabhairt ar ais" + +#: builtin/remote.c +msgid "manipulate push URLs" +msgstr "ionramháil URLanna bhrú" + +#: builtin/remote.c +msgid "add URL" +msgstr "cuir URL leis" + +#: builtin/remote.c +msgid "delete URLs" +msgstr "scrios URLanna" + +#: builtin/remote.c +msgid "--add --delete doesn't make sense" +msgstr "NÃl ciall ag --add --delete" + +#: builtin/remote.c +#, c-format +msgid "Invalid old URL pattern: %s" +msgstr "Sean-phatrún URL neamhbhailÃ: %s" + +#: builtin/remote.c +#, c-format +msgid "No such URL found: %s" +msgstr "NÃor aimsÃodh aon URL den sórt sin: %s" + +#: builtin/remote.c +msgid "Will not delete all non-push URLs" +msgstr "Nà scriosfaidh sé gach URL neamh-bhrú" + +#: builtin/remote.c +msgid "be verbose; must be placed before a subcommand" +msgstr "a bheith inearálta; caithfear é a chur os comhair fo-ordú" + +#: builtin/repack.c +msgid "" +"git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n" +"[--write-midx] [--name-hash-version=<n>]" +msgstr "" +"git athphacáil [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n" +"<n><pack-name>[--fuinneog =] [-- <n>depth=] [--threads=] [--keep- <n>pack " +"=]\n" +"<n>[--write-midx] [--ainm-hash-leagan =]" + +#: builtin/repack.c +msgid "" +"Incremental repacks are incompatible with bitmap indexes. Use\n" +"--no-write-bitmap-index or disable the pack.writeBitmaps configuration." +msgstr "" +"NÃl ath-phacáistà incréideacha comhoiriúnach le hinnéacsanna bitmap. Úsáid\n" +"--no-write-bitmap-index nó dÃchumraÃocht an pack.writeBitmaps a dhÃchumasú." + +#: builtin/repack.c +msgid "could not start pack-objects to repack promisor objects" +msgstr "nà fhéadfaà rudaà pacáiste a thosú chun rudaà gealltanna a athphacáil" + +#: builtin/repack.c +msgid "failed to feed promisor objects to pack-objects" +msgstr "theip ar rudaà gealltanna a bheathú ar rudaà pacáiste" + +#: builtin/repack.c +msgid "repack: Expecting full hex object ID lines only from pack-objects." +msgstr "" +"athphacáil: Ag súil le lÃnte aitheantais réad heicseach iomlána ach ó " +"phacáistÃ." + +#: builtin/repack.c +msgid "could not finish pack-objects to repack promisor objects" +msgstr "" +"nà fhéadfadh sé rudaà pacáiste a chrÃochnú chun rudaà geallta a athphacáil" + +#: builtin/repack.c +#, c-format +msgid "cannot open index for %s" +msgstr "nà féidir innéacs a oscailt do %s" + +#: builtin/repack.c +#, c-format +msgid "pack %s too large to consider in geometric progression" +msgstr "pacáiste %s ró-mhór le breithniú i ddul chun cinn geo" + +#: builtin/repack.c +#, c-format +msgid "pack %s too large to roll up" +msgstr "pacáiste %s ró-mhór le rolladh suas" + +#: builtin/repack.c +#, c-format +msgid "could not open tempfile %s for writing" +msgstr "nà fhéadfaà teachtaireacht %s a oscailt le haghaidh scrÃobh" + +#: builtin/repack.c +msgid "could not close refs snapshot tempfile" +msgstr "nà raibh in ann tempfile snapshot refs a dhúnadh" + +#: builtin/repack.c +#, c-format +msgid "could not remove stale bitmap: %s" +msgstr "nà fhéadfaà bitmap seasta a bhaint: %s" + +#: builtin/repack.c +#, c-format +msgid "pack prefix %s does not begin with objdir %s" +msgstr "nà thosaÃonn réimÃr pacáiste %s le objdir %s" + +#: builtin/repack.c +msgid "pack everything in a single pack" +msgstr "pacáil gach rud i bpacáiste amháin" + +#: builtin/repack.c +msgid "same as -a, and turn unreachable objects loose" +msgstr "" +"mar an gcéanna le -a, agus casadh rudaà nach féidir inrochtana scaoilte" + +#: builtin/repack.c +msgid "same as -a, pack unreachable cruft objects separately" +msgstr "mar an gcéanna le -a, pacáil rudaà cruft neamh-inrochtana ar leithligh" + +#: builtin/repack.c +msgid "approxidate" +msgstr "approxidate" + +#: builtin/repack.c +msgid "with --cruft, expire objects older than this" +msgstr "le --cruft, rachadh in éag rudaà nÃos sine ná seo" + +#: builtin/repack.c +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "le --cruft, nà athphacáil ach pacáistà cruft nÃos lú ná seo" + +#: builtin/repack.c +msgid "remove redundant packs, and run git-prune-packed" +msgstr "bain pacáistà iomarcacha, agus rith git-prune-packed" + +#: builtin/repack.c +msgid "pass --no-reuse-delta to git-pack-objects" +msgstr "pas --no-reuse-delta chuig git-pack-objects" + +#: builtin/repack.c +msgid "pass --no-reuse-object to git-pack-objects" +msgstr "pas --no-reuse-object chuig git-pack-objects" + +#: builtin/repack.c +msgid "" +"specify the name hash version to use for grouping similar objects by path" +msgstr "" +"sonraigh an leagan hash ainm atá le húsáid chun rudaà den chineál céanna a " +"ghrúpáil" + +#: builtin/repack.c +msgid "do not run git-update-server-info" +msgstr "ná reáchtáil git-update-server-info" + +#: builtin/repack.c +msgid "pass --local to git-pack-objects" +msgstr "pas --local go git-pack-objects" + +#: builtin/repack.c +msgid "write bitmap index" +msgstr "scrÃobh innéacs bitmap" + +#: builtin/repack.c +msgid "pass --delta-islands to git-pack-objects" +msgstr "pas --delta-islands chuig git-pack-objects" + +#: builtin/repack.c +msgid "with -A, do not loosen objects older than this" +msgstr "le -A, ná scaoil rudaà nÃos sine ná seo" + +#: builtin/repack.c +msgid "with -a, repack unreachable objects" +msgstr "le -a, athphacáil rudaà neamh-inrochtana" + +#: builtin/repack.c +msgid "size of the window used for delta compression" +msgstr "méid na fuinneoga a úsáidtear le haghaidh comhbhrú delta" + +#: builtin/repack.c +msgid "bytes" +msgstr "beart" + +#: builtin/repack.c +msgid "same as the above, but limit memory size instead of entries count" +msgstr "" +"mar an gcéanna leis an méid thuas, ach teorainn le méid cuimhne in ionad " +"iontrálacha" + +#: builtin/repack.c +msgid "limits the maximum delta depth" +msgstr "teorann sé leis an doimhneacht delta uasta" + +#: builtin/repack.c +msgid "limits the maximum number of threads" +msgstr "teorainn leis an lÃon uasta na snáitheanna" + +#: builtin/repack.c +msgid "maximum size of each packfile" +msgstr "uasmhéid gach pacáiste" + +#: builtin/repack.c +msgid "repack objects in packs marked with .keep" +msgstr "athphacáil rudaà i bpacáistà atá marcáilte le .keep" + +#: builtin/repack.c +msgid "do not repack this pack" +msgstr "ná déan an pacáiste seo a athphacáil" + +#: builtin/repack.c +msgid "find a geometric progression with factor <N>" +msgstr "faigh dul chun cinn geoiméadrach le fachtóir <N>" + +#: builtin/repack.c +msgid "write a multi-pack index of the resulting packs" +msgstr "scrÃobh innéacs il-phacáiste de na pacáistà mar thoradh air" + +#: builtin/repack.c +msgid "pack prefix to store a pack containing filtered out objects" +msgstr "réimÃr pacáiste chun pacáiste ina bhfuil rudaà scagtha amach a stóráil" + +#: builtin/repack.c +msgid "cannot delete packs in a precious-objects repo" +msgstr "nà féidir pacáistà a scriosadh i repo rudaà luachmhara" + +#: builtin/repack.c +#, c-format +msgid "option '%s' can only be used along with '%s'" +msgstr "nà féidir rogha '%s' a úsáid ach amháin in éineacht le '%s'" + +#: builtin/repack.c +msgid "Nothing new to pack." +msgstr "NÃl aon rud nua le pacáil." + +#: builtin/repack.c +#, c-format +msgid "renaming pack to '%s' failed" +msgstr "theip ar phacáiste a athainmniú go '%s'" + +#: builtin/repack.c +#, c-format +msgid "pack-objects did not write a '%s' file for pack %s-%s" +msgstr "nÃor scrÃobh pack-objects comhad '%s' do phacáiste %s-%s" + +#: builtin/repack.c sequencer.c +#, c-format +msgid "could not unlink: %s" +msgstr "nà fhéadfaà dÃcheangal: %s" + +#: builtin/replace.c +msgid "git replace [-f] <object> <replacement>" +msgstr "git athsholáthair [-f] <object><replacement>" + +#: builtin/replace.c +msgid "git replace [-f] --edit <object>" +msgstr "git athsholáthair [-f] --edit <object>" + +#: builtin/replace.c +msgid "git replace [-f] --graft <commit> [<parent>...]" +msgstr "<commit><parent>git athsholáthair [-f] --graft [...]" + +#: builtin/replace.c +msgid "git replace -d <object>..." +msgstr "<object>git athsholáthair -d..." + +#: builtin/replace.c +msgid "git replace [--format=<format>] [-l [<pattern>]]" +msgstr "<pattern>git in ionad [--format =<format>] [-l []]" + +#: builtin/replace.c +#, c-format +msgid "" +"invalid replace format '%s'\n" +"valid formats are 'short', 'medium' and 'long'" +msgstr "" +"formáid athsholáthair neamhbhailà '%s'\n" +"is iad formáidà bailà ná 'gearr', 'meánach' agus 'fada'" + +#: builtin/replace.c +#, c-format +msgid "replace ref '%s' not found" +msgstr "athsholáthair nach bhfuarthas tagairt '%s'" + +#: builtin/replace.c +#, c-format +msgid "Deleted replace ref '%s'" +msgstr "Scriosta in ionad tagairt '%s'" + +#: builtin/replace.c +#, c-format +msgid "'%s' is not a valid ref name" +msgstr "Nà ainm tagartha bailà é '%s'" + +#: builtin/replace.c +#, c-format +msgid "replace ref '%s' already exists" +msgstr "athsholáthar tagairt '%s' atá ann cheana féin" + +#: builtin/replace.c +#, c-format +msgid "" +"Objects must be of the same type.\n" +"'%s' points to a replaced object of type '%s'\n" +"while '%s' points to a replacement object of type '%s'." +msgstr "" +"Caithfidh rudaà a bheith den chineál céanna.\n" +"Tugann '%s' in iúl do réad athsholáthair de chineál '%s'\n" +"agus dÃrÃonn '%s' ar réad athsholáthair de chineál '%s'." + +#: builtin/replace.c +#, c-format +msgid "unable to open %s for writing" +msgstr "nach féidir %s a oscailt le haghaidh scrÃobh" + +#: builtin/replace.c +msgid "cat-file reported failure" +msgstr "teip tuairiscithe ar chomhad cat" + +#: builtin/replace.c +#, c-format +msgid "unable to open %s for reading" +msgstr "nach féidir %s a oscailt le haghaidh léamh" + +#: builtin/replace.c +msgid "unable to spawn mktree" +msgstr "in ann mktree a shannadh" + +#: builtin/replace.c +msgid "unable to read from mktree" +msgstr "in ann léamh ó mktree" + +#: builtin/replace.c +msgid "mktree reported failure" +msgstr "thuairiscigh mktree teip" + +#: builtin/replace.c +msgid "mktree did not return an object name" +msgstr "nÃor thug mktree ainm réad ar ais" + +#: builtin/replace.c +#, c-format +msgid "unable to fstat %s" +msgstr "nà féidir le fstat %s" + +#: builtin/replace.c +msgid "unable to write object to database" +msgstr "in ann réad a scrÃobh chuig bunachar sonraÃ" + +#: builtin/replace.c +#, c-format +msgid "unable to get object type for %s" +msgstr "nach féidir cineál réad a fháil do %s" + +#: builtin/replace.c +msgid "editing object file failed" +msgstr "theip ar eagarthóireacht ar chomhad" + +#: builtin/replace.c +#, c-format +msgid "new object is the same as the old one: '%s'" +msgstr "tá réad nua mar an gcéanna leis an sean-réad: '%s'" + +#: builtin/replace.c +#, c-format +msgid "could not parse %s as a commit" +msgstr "nà fhéadfaà %s a pharsáil mar thiomantas" + +#: builtin/replace.c +#, c-format +msgid "bad mergetag in commit '%s'" +msgstr "cliciú neamhchuspóir i gcomhad '%s'" + +#: builtin/replace.c +#, c-format +msgid "malformed mergetag in commit '%s'" +msgstr "comharthaà mÃfhoirmithe i dtiomantas '%s'" + +#: builtin/replace.c +#, c-format +msgid "" +"original commit '%s' contains mergetag '%s' that is discarded; use --edit " +"instead of --graft" +msgstr "" +"tá mergetag '%s' a dhÃscaoiltear as '%s' bunaidh; bain úsáid as --edit in " +"ionad --graft" + +#: builtin/replace.c +#, c-format +msgid "the original commit '%s' has a gpg signature" +msgstr "tá sÃniú gpg ag an tiomantas bunaidh '%s'" + +#: builtin/replace.c +msgid "the signature will be removed in the replacement commit!" +msgstr "bainfear an sÃniú sa tiomantas athsholáthair!" + +#: builtin/replace.c +#, c-format +msgid "could not write replacement commit for: '%s'" +msgstr "nà fhéadfaà gealltanas athsholáthair a scrÃobh do: '%s'" + +#: builtin/replace.c +#, c-format +msgid "graft for '%s' unnecessary" +msgstr "graft le haghaidh '%s' gan ghá" + +#: builtin/replace.c +#, c-format +msgid "new commit is the same as the old one: '%s'" +msgstr "tá tiomantas nua mar an gcéanna leis an seancheann: '%s'" + +#: builtin/replace.c +#, c-format +msgid "" +"could not convert the following graft(s):\n" +"%s" +msgstr "" +"nà raibh sé in ann an graft (Ã) seo a leanas a thiontú:\n" +"%s" + +#: builtin/replace.c +msgid "list replace refs" +msgstr "liosta athsholáthair refs" + +#: builtin/replace.c +msgid "delete replace refs" +msgstr "scrios athsholáthair refs" + +#: builtin/replace.c +msgid "edit existing object" +msgstr "réad atá ann cheana in eagar" + +#: builtin/replace.c +msgid "change a commit's parents" +msgstr "tuismitheoirà tiomanta a athrú" + +#: builtin/replace.c +msgid "convert existing graft file" +msgstr "tiontaigh an comhad graft atá ann cheana" + +#: builtin/replace.c +msgid "replace the ref if it exists" +msgstr "athsholáthar an tagartha má tá sé ann" + +#: builtin/replace.c +msgid "do not pretty-print contents for --edit" +msgstr "ná déan ábhar álainn a phriontáil le haghaidh --edit" + +#: builtin/replace.c +msgid "use this format" +msgstr "bain úsáid as an bhformáid seo" + +#: builtin/replace.c +msgid "--format cannot be used when not listing" +msgstr "Nà féidir --format a úsáid nuair nach bhfuil sé liostaithe" + +#: builtin/replace.c +msgid "-f only makes sense when writing a replacement" +msgstr "Nà dhéanann -f ciall ach nuair a bhÃonn athsholáthar á scrÃobh" + +#: builtin/replace.c +msgid "--raw only makes sense with --edit" +msgstr "Nà dhéanann --raw ciall ach le --edit" + +#: builtin/replace.c +msgid "-d needs at least one argument" +msgstr "-d teastaÃonn argóint amháin ar a laghad" + +#: builtin/replace.c +msgid "bad number of arguments" +msgstr "droch-lÃon na n-argóintÃ" + +#: builtin/replace.c +msgid "-e needs exactly one argument" +msgstr "TeastaÃonn argóint amháin dÃreach ó -e" + +#: builtin/replace.c +msgid "-g needs at least one argument" +msgstr "TeastaÃonn argóint amháin ar a laghad ó -g" + +#: builtin/replace.c +msgid "--convert-graft-file takes no argument" +msgstr "Nà ghlacann --convert-graft-file aon argóint" + +#: builtin/replace.c +msgid "only one pattern can be given with -l" +msgstr "nà féidir ach patrún amháin a thabhairt le -l" + +#: builtin/replay.c +msgid "need some commits to replay" +msgstr "teastaÃonn roinnt gealltanais chun athsheinm" + +#: builtin/replay.c +msgid "all positive revisions given must be references" +msgstr "caithfidh gach athbhreithniú dearfach a thugtar a bheith ina" + +#: builtin/replay.c +msgid "argument to --advance must be a reference" +msgstr "caithfidh argóint chuig --advance a bheith ina thagairt" + +#: builtin/replay.c +msgid "" +"cannot advance target with multiple sources because ordering would be ill-" +"defined" +msgstr "" +"nà féidir leis an sprioc a chur chun cinn le foinsà iolracha toisc go mbeadh " +"ordú" + +#: builtin/replay.c +msgid "" +"cannot implicitly determine whether this is an --advance or --onto operation" +msgstr "" +"nà féidir a chinneadh go hinneach an oibrÃocht --advance nó --onto é seo" + +#: builtin/replay.c +msgid "" +"cannot advance target with multiple source branches because ordering would " +"be ill-defined" +msgstr "" +"nà féidir leis an sprioc a chur chun cinn le brainsà foinse iolracha mar go " +"mbeadh ordú" + +#: builtin/replay.c +msgid "cannot implicitly determine correct base for --onto" +msgstr "nà féidir leis an mbonn ceart do --onto a chinneadh go hinneach" + +#: builtin/replay.c +msgid "" +"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance " +"<branch>) <revision-range>..." +msgstr "" +"(TURGNAMHACH!) git replay ([--contained] --onto <newbase> | --advance " +"<branch>) <revision-range>..." + +#: builtin/replay.c +msgid "make replay advance given branch" +msgstr "athsheoladh a dhéanamh roimh ré brainse ar leith" + +#: builtin/replay.c +msgid "replay onto given commit" +msgstr "athsheoladh ar thiomantas a thugtar" + +#: builtin/replay.c +msgid "advance all branches contained in revision-range" +msgstr "gach brainse atá sa raon athbhreithnithe a chur chun cinn" + +#: builtin/replay.c +msgid "option --onto or --advance is mandatory" +msgstr "tá rogha --onto nó --advance éigeantach" + +#: builtin/replay.c +#, c-format +msgid "" +"some rev walking options will be overridden as '%s' bit in 'struct rev_info' " +"will be forced" +msgstr "" +"cuirfear roinnt roghanna siúil rev a athshealbhú mar go gcuirfear giotán " +"'%s' i 'struct rev_info' iallach" + +#: builtin/replay.c +msgid "error preparing revisions" +msgstr "earráid ag ullmhú athbhreith" + +#: builtin/replay.c +msgid "replaying down to root commit is not supported yet!" +msgstr "nà thacaÃtear le athsheinm sÃos go dtà tiomantas fréimhe fós!" + +#: builtin/replay.c +msgid "replaying merge commits is not supported yet!" +msgstr "nà thacaÃtear le gealltanna cumaisc athsheinm fós!" + +#: builtin/rerere.c +msgid "" +"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]" +msgstr "" +"git rerere [glan | déan dearmad<pathspec>... | diff | stádas | fágtha | gc]" + +#: builtin/rerere.c +msgid "register clean resolutions in index" +msgstr "rúin glan a chlárú san innéacs" + +#: builtin/rerere.c +msgid "'git rerere forget' without paths is deprecated" +msgstr "Tá 'git rerere dearmad' gan cosáin scothaithe" + +#: builtin/rerere.c +#, c-format +msgid "unable to generate diff for '%s'" +msgstr "nach féidir éagsúlacht a ghiniúint do '%s'" + +#: builtin/reset.c +msgid "" +"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" +msgstr "" +"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" + +#: builtin/reset.c +msgid "git reset [-q] [<tree-ish>] [--] <pathspec>..." +msgstr "git reset [-q] [<tree-ish>] [--] <pathspec>..." + +#: builtin/reset.c +msgid "" +"git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]" +msgstr "" +"git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]" + +#: builtin/reset.c +msgid "git reset --patch [<tree-ish>] [--] [<pathspec>...]" +msgstr "git reset --patch [<tree-ish>] [--] [<pathspec>...]" + +#: builtin/reset.c +msgid "mixed" +msgstr "measctha" + +#: builtin/reset.c +msgid "soft" +msgstr "bog" + +#: builtin/reset.c +msgid "hard" +msgstr "crua" + +#: builtin/reset.c +msgid "merge" +msgstr "cumaisc" + +#: builtin/reset.c +msgid "keep" +msgstr "coinnigh" + +#: builtin/reset.c +msgid "You do not have a valid HEAD." +msgstr "NÃl CEANN bailà agat." + +#: builtin/reset.c +msgid "Failed to find tree of HEAD." +msgstr "Theip ar chrann HEAD a aimsiú." + +#: builtin/reset.c +#, c-format +msgid "Failed to find tree of %s." +msgstr "Theip ar chrann %s a aimsiú." + +#: builtin/reset.c +#, c-format +msgid "HEAD is now at %s" +msgstr "Tá HEAD anois ag %s" + +#: builtin/reset.c +#, c-format +msgid "Cannot do a %s reset in the middle of a merge." +msgstr "Nà féidir athshocrú %s a dhéanamh i lár cumaisc." + +#: builtin/reset.c builtin/stash.c +msgid "be quiet, only report errors" +msgstr "bà ciúin, nà thuairiscigh ach earráidÃ" + +#: builtin/reset.c +msgid "skip refreshing the index after reset" +msgstr "scipeáil an t-innéacs a athnuachan tar éis" + +#: builtin/reset.c +msgid "reset HEAD and index" +msgstr "athshocraigh HEAD agus innéacs" + +#: builtin/reset.c +msgid "reset only HEAD" +msgstr "athshocraigh CEAD amháin" + +#: builtin/reset.c +msgid "reset HEAD, index and working tree" +msgstr "athshocraigh HEAD, innéacs agus crann oibre" + +#: builtin/reset.c +msgid "reset HEAD but keep local changes" +msgstr "athshocraigh HEAD ach coinnigh athruithe áiti" + +#: builtin/reset.c +msgid "record only the fact that removed paths will be added later" +msgstr "" +"nà thaifeadadh ach an fÃric go gcuirfear cosáin bainte leis nÃos déanaÃ" + +#: builtin/reset.c +#, c-format +msgid "Failed to resolve '%s' as a valid revision." +msgstr "Theip ar '%s' a réiteach mar athbhreithniú bailÃ." + +#: builtin/reset.c +#, c-format +msgid "Failed to resolve '%s' as a valid tree." +msgstr "Theip ar '%s' a réiteach mar chrann bailÃ." + +#: builtin/reset.c +msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead." +msgstr "" +"--mixed le cosáin imithe i léig; bain úsáid as 'git reset -- <cosáin>' ina " +"ionad." + +#: builtin/reset.c +#, c-format +msgid "Cannot do %s reset with paths." +msgstr "Nà féidir %s a athshocrú le cosáin." + +#: builtin/reset.c +#, c-format +msgid "%s reset is not allowed in a bare repository" +msgstr "Nà cheadaÃtear athshocrú %s i stóras lom" + +#: builtin/reset.c +msgid "Unstaged changes after reset:" +msgstr "Athruithe gan stáitse tar éis athshocrú:" + +#: builtin/reset.c +#, c-format +msgid "" +"It took %.2f seconds to refresh the index after reset. You can use\n" +"'--no-refresh' to avoid this." +msgstr "" +"Thóg sé %.2f soicind an t-innéacs a athnuachan tar éis athshocrú. Is féidir " +"leat úsáid a bhaint as\n" +"'--no-refresh' chun é seo a sheachaint." + +#: builtin/reset.c +#, c-format +msgid "Could not reset index file to revision '%s'." +msgstr "Nà fhéadfaà comhad innéacs a athshocrú chun athbhreithniú '%s'." + +#: builtin/reset.c +msgid "Could not write new index file." +msgstr "Nà fhéadfaà comhad innéacs nua a scrÃobh." + +#: builtin/rev-list.c +#, c-format +msgid "unable to get disk usage of %s" +msgstr "nach féidir úsáid diosca de %s a fháil" + +#: builtin/rev-list.c +#, c-format +msgid "invalid value for '%s': '%s', the only allowed format is '%s'" +msgstr "luach neamhbhailà do '%s': '%s', is é '%s' an t-aon fhormáid ceadaithe" + +#: builtin/rev-list.c +msgid "-z option used with unsupported option" +msgstr "-z rogha a úsáidtear le rogha gan tacaÃocht" + +#: builtin/rev-list.c +msgid "rev-list does not support display of notes" +msgstr "nà thacaÃonn rev-list le taispeáint nótaÃ" + +#: builtin/rev-list.c +#, c-format +msgid "marked counting and '%s' cannot be used together" +msgstr "comhaireamh marcáilte agus nà féidir '%s' a úsáid le chéile" + +#: builtin/rev-parse.c +msgid "git rev-parse --parseopt [<options>] -- [<args>...]" +msgstr "git rev-parse --parseopt [<options>] -- [<args>...]" + +#: builtin/rev-parse.c +msgid "keep the `--` passed as an arg" +msgstr "coinnigh an `--` a rith mar arg" + +#: builtin/rev-parse.c +msgid "stop parsing after the first non-option argument" +msgstr "stop a pháirseáil tar éis an chéad argóint neamh-rogha" + +#: builtin/rev-parse.c +msgid "output in stuck long form" +msgstr "aschur i bhfoirm fhada greamaithe" + +#: builtin/rev-parse.c +msgid "premature end of input" +msgstr "deireadh roimh ré an ionchuir" + +#: builtin/rev-parse.c +msgid "no usage string given before the `--' separator" +msgstr "gan aon teaghrán úsáide a thugtar roimh an deighilteoir `--'" + +#: builtin/rev-parse.c +msgid "missing opt-spec before option flags" +msgstr "sonraÃocht rogha in easnamh roimh bhratacha roghanna" + +#: builtin/rev-parse.c +msgid "Needed a single revision" +msgstr "TeastaÃonn athbhreithniú amháin" + +#: builtin/rev-parse.c +msgid "" +"git rev-parse --parseopt [<options>] -- [<args>...]\n" +" or: git rev-parse --sq-quote [<arg>...]\n" +" or: git rev-parse [<options>] [<arg>...]\n" +"\n" +"Run \"git rev-parse --parseopt -h\" for more information on the first usage." +msgstr "" +"git rev-parse --parseopt [<options>] -- [<args>...]\n" +" or: git rev-parse --sq-quote [<arg>...]\n" +" or: git rev-parse [<options>] [<arg>...]\n" +"\n" +"Rith “git rev-parse --parseopt -h†le haghaidh tuilleadh faisnéise ar an " +"gcéad úsáid." + +#: builtin/rev-parse.c +msgid "--resolve-git-dir requires an argument" +msgstr "TeastaÃonn argóint ag teastáil ó --resolve-git-dir" + +#: builtin/rev-parse.c +#, c-format +msgid "not a gitdir '%s'" +msgstr "nà ghearr '%s'" + +#: builtin/rev-parse.c +msgid "--git-path requires an argument" +msgstr "TeastaÃonn argóint ag teastáil ó --git-path" + +#: builtin/rev-parse.c +msgid "-n requires an argument" +msgstr "ÉilÃonn -n argóint" + +#: builtin/rev-parse.c +msgid "--path-format requires an argument" +msgstr "ÉilÃonn --path-format argóint" + +#: builtin/rev-parse.c +#, c-format +msgid "unknown argument to --path-format: %s" +msgstr "argóint anaithnid chuig --path-format: %s" + +#: builtin/rev-parse.c +msgid "--default requires an argument" +msgstr "TeastaÃonn argóint ar --default" + +#: builtin/rev-parse.c +msgid "--prefix requires an argument" +msgstr "TeastaÃonn argóint ar --prefix" + +#: builtin/rev-parse.c +msgid "no object format specified" +msgstr "aon fhormáid réada a shonra" + +#: builtin/rev-parse.c +#, c-format +msgid "unsupported object format: %s" +msgstr "formáid réad gan tacaÃocht: %s" + +#: builtin/rev-parse.c +#, c-format +msgid "unknown mode for --abbrev-ref: %s" +msgstr "modh anaithnid do --abbrev-ref: %s" + +#: builtin/rev-parse.c setup.c +msgid "this operation must be run in a work tree" +msgstr "caithfear an oibrÃocht seo a reáchtáil i gcrann oibre" + +#: builtin/rev-parse.c +msgid "Could not read the index" +msgstr "Nà fhéadfaà an t-innéacs a léamh" + +#: builtin/rev-parse.c +#, c-format +msgid "unknown mode for --show-object-format: %s" +msgstr "modh anaithnid do --show-object-format: %s" + +#: builtin/revert.c +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>..." + +#: builtin/revert.c +msgid "git revert (--continue | --skip | --abort | --quit)" +msgstr "git revert (--continue | --skip | --abort | --quit)" + +#: builtin/revert.c +msgid "" +"git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n" +" [-S[<keyid>]] <commit>..." +msgstr "" +"git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n" +" [-S[<keyid>]] <commit>..." + +#: builtin/revert.c +msgid "git cherry-pick (--continue | --skip | --abort | --quit)" +msgstr "git cherry-pick (--continue | --skip | --abort | --quit)" + +#: builtin/revert.c +#, c-format +msgid "option `%s' expects a number greater than zero" +msgstr "tá rogha `%s' ag súil go mbeidh uimhir nÃos mó ná nialas" + +#: builtin/revert.c +#, c-format +msgid "%s: %s cannot be used with %s" +msgstr "%s: Nà féidir %s a úsáid le %s" + +#: builtin/revert.c +msgid "end revert or cherry-pick sequence" +msgstr "aisiompú deiridh nó seicheamh piocadh silÃnÃ" + +#: builtin/revert.c +msgid "resume revert or cherry-pick sequence" +msgstr "athosú ar ais nó seicheamh a phiocadh silÃnÃ" + +#: builtin/revert.c +msgid "cancel revert or cherry-pick sequence" +msgstr "seicheamh aisiompthe nó silÃnà a roghnú a chealú" + +#: builtin/revert.c +msgid "skip current commit and continue" +msgstr "scipeáil tiomantas reatha agus lean ar aghaidh" + +#: builtin/revert.c +msgid "don't automatically commit" +msgstr "ná tiomantas go huathoibrÃoch" + +#: builtin/revert.c +msgid "edit the commit message" +msgstr "athraigh an teachtaireacht tiomanta" + +#: builtin/revert.c +msgid "parent-number" +msgstr "uimhir tuismitheora" + +#: builtin/revert.c +msgid "select mainline parent" +msgstr "roghnaigh tuismitheoir prÃomh" + +#: builtin/revert.c +msgid "merge strategy" +msgstr "straitéis cumaisc" + +#: builtin/revert.c +msgid "option for merge strategy" +msgstr "rogha le haghaidh straitéis cumaisc" + +#: builtin/revert.c +msgid "append commit name" +msgstr "ainm tiomanta a chur leis" + +#: builtin/revert.c +msgid "preserve initially empty commits" +msgstr "gealltanais folamh a chaomhnú ar dt" + +#: builtin/revert.c +msgid "allow commits with empty messages" +msgstr "gealltanna a cheadú le teachtaireachtaà folamh" + +#: builtin/revert.c +msgid "deprecated: use --empty=keep instead" +msgstr "dÃscrÃofa: bain úsáid as --empty=keep ina ionad" + +#: builtin/revert.c +msgid "use the 'reference' format to refer to commits" +msgstr "" +"bain úsáid as an bhformáid 'tagartha' chun tagairt a dhéanamh do ghealltanais" + +#: builtin/revert.c +msgid "revert failed" +msgstr "theip ar ais" + +#: builtin/revert.c +msgid "cherry-pick failed" +msgstr "theip ar an rogha silÃnÃ" + +#: builtin/rm.c +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] [--neamh-mheaitseáilte]\n" +" <file>[--quiet] [--pathspec-ó-comhad = [--pathspec-comhad-nul]]\n" +" [--] [<pathspec>...]" + +#: builtin/rm.c +msgid "" +"the following file has staged content different from both the\n" +"file and the HEAD:" +msgid_plural "" +"the following files have staged content different from both the\n" +"file and the HEAD:" +msgstr[0] "" +"tá ábhar stáitse ag an gcomhad seo a leanas difriúil ón araon\n" +"comhad agus an CEAD:" +msgstr[1] "" +"tá ábhar stáitseáilte difriúil idir an comhad agus\n" +"an CEAD sna comhaid seo a leanas:" +msgstr[2] "" +"tá ábhar stáitseáilte difriúil idir an comhad agus \n" +"an CEAD sna comhaid seo a leanas:" + +#: builtin/rm.c +msgid "" +"\n" +"(use -f to force removal)" +msgstr "" +"\n" +"(bain úsáid as -f chun a chur i bhfeidhm)" + +#: builtin/rm.c +msgid "the following file has changes staged in the index:" +msgid_plural "the following files have changes staged in the index:" +msgstr[0] "tá athruithe céime san innéacs ag an gcomhad seo a leanas:" +msgstr[1] "tá athruithe céimnithe san innéacs sna comhaid seo a leanas:" +msgstr[2] "tá athruithe céimnithe san innéacs sna comhaid seo a leanas:" + +#: builtin/rm.c +msgid "" +"\n" +"(use --cached to keep the file, or -f to force removal)" +msgstr "" +"\n" +"(bain úsáid as --cached chun an comhad a choinneáil, nó -f chun a bhaint a " +"chur i bhfeidhm)" + +#: builtin/rm.c +msgid "the following file has local modifications:" +msgid_plural "the following files have local modifications:" +msgstr[0] "tá modhnuithe áitiúla sa chomhad seo a leanas:" +msgstr[1] "tá modhnuithe áitiúla ar na comhaid seo a leanas:" +msgstr[2] "tá modhnuithe áitiúla ar na comhaid seo a leanas:" + +#: builtin/rm.c +msgid "do not list removed files" +msgstr "ná liostáil comhaid a bhaintear" + +#: builtin/rm.c +msgid "only remove from the index" +msgstr "ach a bhaint as an innéacs" + +#: builtin/rm.c +msgid "override the up-to-date check" +msgstr "an seiceáil cothrom le dáta a chur ar" + +#: builtin/rm.c +msgid "allow recursive removal" +msgstr "cead a bhaint athfhillteach" + +#: builtin/rm.c +msgid "exit with a zero status even if nothing matched" +msgstr "imeacht le stádas nialasach fiú mura bhfuil aon rud comhoiriúnach" + +#: builtin/rm.c +msgid "No pathspec was given. Which files should I remove?" +msgstr "NÃor tugadh aon bhealach. Cé na comhaid ba chóir dom a bhaint?" + +#: builtin/rm.c +msgid "please stage your changes to .gitmodules or stash them to proceed" +msgstr "" +"cuir do chuid athruithe ar .gitmodules nó iad a stóráil chun dul ar aghaidh" + +#: builtin/rm.c +#, c-format +msgid "not removing '%s' recursively without -r" +msgstr "gan '%s' a bhaint go athshlánach gan -r" + +#: builtin/rm.c +#, c-format +msgid "git rm: unable to remove %s" +msgstr "git rm: nà féidir %s a bhaint" + +#: builtin/send-pack.c +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" +" [--[no-]signed | --signed=(true|false|if-asked)]\n" +" [<host>:]<directory> (--all | <ref>...)" + +#: builtin/send-pack.c +msgid "remote name" +msgstr "ainm iargúlta" + +#: builtin/send-pack.c +msgid "push all refs" +msgstr "brúigh gach ceann" + +#: builtin/send-pack.c +msgid "use stateless RPC protocol" +msgstr "prótacal RPC gan stáit a úsáid" + +#: builtin/send-pack.c +msgid "read refs from stdin" +msgstr "léigh refs ó stdin" + +#: builtin/send-pack.c +msgid "print status from remote helper" +msgstr "stádas priontála ó chúntóir cianda" + +#: builtin/shortlog.c +msgid "git shortlog [<options>] [<revision-range>] [[--] <path>...]" +msgstr "git shortlog [<options>] [<revision-range>] [[--]<path>...]" + +#: builtin/shortlog.c +msgid "git log --pretty=short | git shortlog [<options>]" +msgstr "git log --pretty=short | git shortlog [<options>]" + +#: builtin/shortlog.c +msgid "using multiple --group options with stdin is not supported" +msgstr "nà thacaÃtear le roghanna iolracha --group le stdin a úsáid" + +#: builtin/shortlog.c +#, c-format +msgid "using %s with stdin is not supported" +msgstr "nà thacaÃtear le baint úsáide as %s le stdin" + +#: builtin/shortlog.c +#, c-format +msgid "unknown group type: %s" +msgstr "cineál grúpa anaithnid: %s" + +#: builtin/shortlog.c +msgid "group by committer rather than author" +msgstr "grúpa de réir coimiteora seachas údar" + +#: builtin/shortlog.c +msgid "sort output according to the number of commits per author" +msgstr "aschur a shórtáil de réir lÃon na ngealltanais in aghaidh an údair" + +#: builtin/shortlog.c +msgid "suppress commit descriptions, only provides commit count" +msgstr "tuairiscà tiomanta a chur faoi chois, nà sholáthraÃonn" + +#: builtin/shortlog.c +msgid "show the email address of each author" +msgstr "taispeáin seoladh rÃomhphoist gach údair" + +#: builtin/shortlog.c +msgid "<w>[,<i1>[,<i2>]]" +msgstr "<w>[, <i1>[,<i2>]]" + +#: builtin/shortlog.c +msgid "linewrap output" +msgstr "aschur linewrap" + +#: builtin/shortlog.c +msgid "field" +msgstr "réimse" + +#: builtin/shortlog.c +msgid "group by field" +msgstr "grúpa de réir réimse" + +#: builtin/shortlog.c +msgid "too many arguments given outside repository" +msgstr "an iomarca argóintà a thugtar stóráil" + +#: builtin/show-branch.c +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]\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]\n" +" [(<rev> | <glob>)...]" + +#: builtin/show-branch.c +msgid "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]" +msgstr "<ref>git show-branch (-g | --reflog) [= [<n>,]] [--liosta] [<base>]" + +#: builtin/show-branch.c +#, c-format +msgid "ignoring %s; cannot handle more than %d ref" +msgid_plural "ignoring %s; cannot handle more than %d refs" +msgstr[0] "" +"ag déanamh neamhaird de %s; nà féidir nÃos mó ná %d tagairt a láimhseáil" +msgstr[1] "" +"ag déanamh neamhaird de %s; nà féidir nÃos mó ná %d tagairtà a láimhseáil" +msgstr[2] "" +"ag déanamh neamhaird de %s; nà féidir nÃos mó ná %d tagairtà a láimhseáil" + +#: builtin/show-branch.c +#, c-format +msgid "no matching refs with %s" +msgstr "gan aon fhreagraà a mheaitseáil le %s" + +#: builtin/show-branch.c +msgid "show remote-tracking and local branches" +msgstr "taispeáint cianrianú agus brainsà áitiúla" + +#: builtin/show-branch.c +msgid "show remote-tracking branches" +msgstr "taispeáin brainsà cianrianaithe" + +#: builtin/show-branch.c +msgid "color '*!+-' corresponding to the branch" +msgstr "dath '*! +-' a fhreagraÃonn don bhrainse" + +#: builtin/show-branch.c +msgid "show <n> more commits after the common ancestor" +msgstr "taispeáint <n>nÃos mó gealltanais tar éis an sinsear coiteann" + +#: builtin/show-branch.c +msgid "synonym to more=-1" +msgstr "comhchiallach le nÃos mó = -1" + +#: builtin/show-branch.c +msgid "suppress naming strings" +msgstr "teaghráin ainmniúcháin" + +#: builtin/show-branch.c +msgid "include the current branch" +msgstr "san áireamh an bhrainse reatha" + +#: builtin/show-branch.c +msgid "name commits with their object names" +msgstr "geallann ainm lena n-ainmneacha réad" + +#: builtin/show-branch.c +msgid "show possible merge bases" +msgstr "taispeáin bonn cumaisc féidear" + +#: builtin/show-branch.c +msgid "show refs unreachable from any other ref" +msgstr "taispeántais neamh-inrochtana ó aon tagairt eile" + +#: builtin/show-branch.c +msgid "show commits in topological order" +msgstr "gealltanna seó in ord topolaÃoch" + +#: builtin/show-branch.c +msgid "show only commits not on the first branch" +msgstr "seó nà geallann ach ar an gcéad bhrainse" + +#: builtin/show-branch.c +msgid "show merges reachable from only one tip" +msgstr "cumaisc seó inrochtana ó chomhairle amháin" + +#: builtin/show-branch.c +msgid "topologically sort, maintaining date order where possible" +msgstr "a shórtáil topaiceach, ag coinneáil ord dáta nuair is féidir" + +#: builtin/show-branch.c +msgid "<n>[,<base>]" +msgstr "<n>[,<base>]" + +#: builtin/show-branch.c +msgid "show <n> most recent ref-log entries starting at base" +msgstr "taispeáin ion <n>trálacha ref-log is déanaà ag tosú ag an mbonn" + +#: builtin/show-branch.c +msgid "no branches given, and HEAD is not valid" +msgstr "aon bhrainsà a thugtar, agus nÃl HEAD bailÃ" + +#: builtin/show-branch.c +msgid "--reflog option needs one branch name" +msgstr "TeastaÃonn ainm brainse amháin ag teastáil ó rogha --reflog" + +#: builtin/show-branch.c +#, c-format +msgid "only %d entry can be shown at one time." +msgid_plural "only %d entries can be shown at one time." +msgstr[0] "nà féidir ach %d iontráil a thaispeáint ag an am céanna." +msgstr[1] "nà féidir ach %d iontráil a thaispeáint ag an am céanna." +msgstr[2] "nà féidir ach %d iontráil a thaispeáint ag an am céanna." + +#: builtin/show-branch.c +#, c-format +msgid "no such ref %s" +msgstr "aon tagairt den sórt sin %s" + +#: builtin/show-branch.c +#, c-format +msgid "cannot handle more than %d rev." +msgid_plural "cannot handle more than %d revs." +msgstr[0] "nà féidir nÃos mó ná %d luasghéarú a láimhseáil." +msgstr[1] "nà féidir nÃos mó ná %d luasghéarú a láimhseáil." +msgstr[2] "nà féidir nÃos mó ná %d luasghéarú a láimhseáil." + +#: builtin/show-branch.c +#, c-format +msgid "'%s' is not a valid ref." +msgstr "Nà tagairt bailà é '%s'." + +#: builtin/show-branch.c +#, c-format +msgid "cannot find commit %s (%s)" +msgstr "nà féidir teacht ar thiomantas %s (%s)" + +#: builtin/show-index.c +msgid "hash-algorithm" +msgstr "hais-algartam" + +#: builtin/show-index.c +msgid "Unknown hash algorithm" +msgstr "Algartam hash anaithnid" + +#: builtin/show-ref.c +msgid "" +"git show-ref [--head] [-d | --dereference]\n" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" +msgstr "" +"git show-ref [--head] [-d | --dereference]\n" +" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--branches] [--tags]\n" +" [--] [<pattern>...]" + +#: builtin/show-ref.c +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" +" [--] [<ref>...]" + +#: builtin/show-ref.c +msgid "git show-ref --exclude-existing[=<pattern>]" +msgstr "git show-ref --exclude-existing[=<pattern>]" + +#: builtin/show-ref.c +msgid "git show-ref --exists <ref>" +msgstr "git show-ref --exists <ref>" + +#: builtin/show-ref.c +msgid "reference does not exist" +msgstr "nÃl tagairt ann" + +#: builtin/show-ref.c +msgid "failed to look up reference" +msgstr "theip ort tagairt a lorg suas" + +#: builtin/show-ref.c +msgid "only show tags (can be combined with --branches)" +msgstr "" +"taispeáin clibeanna amháin (is féidir iad a chomhcheangal le --branches)" + +#: builtin/show-ref.c +msgid "only show branches (can be combined with --tags)" +msgstr "nà thaispeáin ach brainsà (is féidir iad a chomhcheangal le --tags)" + +#: builtin/show-ref.c +msgid "check for reference existence without resolving" +msgstr "seiceáil chun tagartha a bheith ann gan réiteach" + +#: builtin/show-ref.c +msgid "stricter reference checking, requires exact ref path" +msgstr "seiceáil tagartha nÃos doichte, teastaÃonn cosán tagartha" + +#: builtin/show-ref.c +msgid "show the HEAD reference, even if it would be filtered out" +msgstr "taispeáin tagairt HEAD, fiú dá ndéanfaà é a scagadh amach" + +#: builtin/show-ref.c +msgid "dereference tags into object IDs" +msgstr "clibeanna a dhÃthreorú isteach in IDanna réad" + +#: builtin/show-ref.c +msgid "only show SHA1 hash using <n> digits" +msgstr "nà thaispeáin ach hais SHA1 ag úsáid <n> dhigit" + +#: builtin/show-ref.c +msgid "do not print results to stdout (useful with --verify)" +msgstr "ná priontáil torthaà chuig stdout (úsáideach le --verify)" + +#: builtin/show-ref.c +msgid "show refs from stdin that aren't in local repository" +msgstr "taispeáin airgeanna ó stdin nach bhfuil i stóras áitiúil" + +#: builtin/sparse-checkout.c +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) [<options>]" + +#: builtin/sparse-checkout.c +msgid "this worktree is not sparse" +msgstr "nÃl an crann oibre seo neamhchoitianta" + +#: builtin/sparse-checkout.c +msgid "this worktree is not sparse (sparse-checkout file may not exist)" +msgstr "" +"nÃl an crann oibre seo neamhchoitianta (b'fhéidir nach bhfuil comhad " +"seiceála neamhchoitianta ann)" + +#: builtin/sparse-checkout.c +#, c-format +msgid "" +"directory '%s' contains untracked files, but is not in the sparse-checkout " +"cone" +msgstr "" +"tá comhaid neamhrianaithe ag eolaire '%s', ach nÃl sé sa chón seiceála " +"neamhchoitianta" + +#: builtin/sparse-checkout.c +#, c-format +msgid "failed to remove directory '%s'" +msgstr "theip ar eolaire '%s' a bhaint" + +#: builtin/sparse-checkout.c +msgid "failed to create directory for sparse-checkout file" +msgstr "theip ar eolaire a chruthú do chomhad seiceála neamhchoitianta" + +#: builtin/sparse-checkout.c +#, c-format +msgid "unable to fdopen %s" +msgstr "nach féidir %s a fdophrÃomhachtú" + +#: builtin/sparse-checkout.c +msgid "failed to initialize worktree config" +msgstr "theip orthu cumraÃocht crann oibre a thionscnamh" + +#: builtin/sparse-checkout.c +msgid "failed to modify sparse-index config" +msgstr "theip orthu cumraÃocht innéacs neamhchoitianta a mhodhnú" + +#: builtin/sparse-checkout.c +msgid "initialize the sparse-checkout in cone mode" +msgstr "an tseiceáil neamhchoitianta a thosú i mód cón" + +#: builtin/sparse-checkout.c +msgid "toggle the use of a sparse index" +msgstr "athsholáthar úsáid innéacs neamhchoitianta" + +#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c +#, c-format +msgid "unable to create leading directories of %s" +msgstr "nach féidir eolairà tosaigh de %s a chruthú" + +#: builtin/sparse-checkout.c +#, c-format +msgid "failed to open '%s'" +msgstr "theip ar '%s' a oscailt" + +#: builtin/sparse-checkout.c +#, c-format +msgid "could not normalize path %s" +msgstr "nà fhéadfaà cosán %s a normalú" + +#: builtin/sparse-checkout.c +#, c-format +msgid "unable to unquote C-style string '%s'" +msgstr "nach féidir teaghrán '%s' i stÃl C a dhÃluachan" + +#: builtin/sparse-checkout.c +msgid "unable to load existing sparse-checkout patterns" +msgstr "in ann patrúin seiceála neamhchoitianta atá ann a luchtú" + +#: builtin/sparse-checkout.c +msgid "existing sparse-checkout patterns do not use cone mode" +msgstr "nà úsáideann patrúin seiceála neamhchoitianta atá ann cheana modh cón" + +#: builtin/sparse-checkout.c +msgid "please run from the toplevel directory in non-cone mode" +msgstr "rith ón eolaire topevel le do thoil i mód neamh-chón" + +#: builtin/sparse-checkout.c +msgid "specify directories rather than patterns (no leading slash)" +msgstr "eolairà a shonrú seachas patrúin (gan aon slash tosaigh)" + +#: builtin/sparse-checkout.c +msgid "" +"specify directories rather than patterns. If your directory starts with a " +"'!', pass --skip-checks" +msgstr "" +"eolairà a shonrú seachas patrúin. Má thosaÃonn d'eolaire le '!', pas --skip-" +"checks" + +#: builtin/sparse-checkout.c +msgid "" +"specify directories rather than patterns. If your directory really has any " +"of '*?[]\\' in it, pass --skip-checks" +msgstr "" +"eolairà a shonrú seachas patrúin. Má tá aon cheann de '* ag d'eolaire i " +"ndáirÃre? []\\ 'ann, pas --skip-checks" + +#: builtin/sparse-checkout.c +#, c-format +msgid "" +"'%s' is not a directory; to treat it as a directory anyway, rerun with --" +"skip-checks" +msgstr "" +"Nà eolaire é '%s'; chun é a chóireáil mar eolaire ar aon nós, athrith le --" +"skip-checks" + +#: builtin/sparse-checkout.c +#, c-format +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 "" +"téigh slasc tosaigh roimh chosáin mar '%s' más mian leat comhad amháin " +"(féach FADHBANNA NEAMH-CONE sa lámhleabhar seiceála git-sparse-checkout)." + +#: builtin/sparse-checkout.c +msgid "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)" +msgstr "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)" + +#: builtin/sparse-checkout.c +msgid "" +"skip some sanity checks on the given paths that might give false positives" +msgstr "" +"scipeáil roinnt seiceálacha sláinte ar na cosáin a thugtar a d'fhéadfadh " +"dearfacha bréagacha a" + +#: builtin/sparse-checkout.c +msgid "read patterns from standard in" +msgstr "léigh patrúin ó chaighdeán i" + +#: builtin/sparse-checkout.c +msgid "no sparse-checkout to add to" +msgstr "gan aon seiceáil neamhchoitianta le cur leis" + +#: builtin/sparse-checkout.c +msgid "" +"git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] " +"(--stdin | <patterns>)" +msgstr "" +"git sparse-checkout set [--[no-]cone] [--[no-]sparse-index] [--skip-checks] " +"(--stdin | <patterns>)" + +#: builtin/sparse-checkout.c +msgid "must be in a sparse-checkout to reapply sparsity patterns" +msgstr "" +"caithfidh sé a bheith i seiceáil neamhchoitianta chun patrúin éagsúla a " +"athchur i bhfeidh" + +#: builtin/sparse-checkout.c +msgid "error while refreshing working directory" +msgstr "earráid agus tú ag athnuachan eolaire" + +#: builtin/sparse-checkout.c +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 <file>]" + +#: builtin/sparse-checkout.c +msgid "terminate input and output files by a NUL character" +msgstr "comhaid ionchuir agus aschuir a fhoirceannadh le carachtar NUL" + +#: builtin/sparse-checkout.c +msgid "when used with --rules-file interpret patterns as cone mode patterns" +msgstr "" +"nuair a úsáidtear é le --rules-file patrúin a léirmhÃniú mar phatrúin mód" + +#: builtin/sparse-checkout.c +msgid "use patterns in <file> instead of the current ones." +msgstr "úsáid patrúin in <file>ionad na cinn reatha." + +#: builtin/stash.c +msgid "git stash list [<log-options>]" +msgstr "<log-options>liosta git stash []" + +#: builtin/stash.c +msgid "" +"git stash show [-u | --include-untracked | --only-untracked] [<diff-" +"options>] [<stash>]" +msgstr "" +"git stash show [-u | --include-untracked | --only-untracked] [<diff-" +"options>] [<stash>]" + +#: builtin/stash.c +msgid "git stash drop [-q | --quiet] [<stash>]" +msgstr "git stash drop [-q | --quiet] [<stash>]" + +#: builtin/stash.c +msgid "git stash pop [--index] [-q | --quiet] [<stash>]" +msgstr "git stash pop [--index] [-q | --quiet] [<stash>]" + +#: builtin/stash.c +msgid "git stash apply [--index] [-q | --quiet] [<stash>]" +msgstr "git stash apply [--index] [-q | --quiet] [<stash>]" + +#: builtin/stash.c +msgid "git stash branch <branchname> [<stash>]" +msgstr "git stash branch <branchname> [<stash>]" + +#: builtin/stash.c +msgid "git stash store [(-m | --message) <message>] [-q | --quiet] <commit>" +msgstr "" +"git stash store [(-m | --teachtaireacht)<message>] [-q | --ciúin] <commit>" + +#: builtin/stash.c +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>...]]" +msgstr "" +"git stash [bhrú [-p | --patch] [-S | --stage] [-k | -- [no-] coinneáil " +"innéacs] [-q | --ciúin]\n" +" <message>[-u | --include-untracked] [-a | --all] [(-m | --teachtaireacht)]\n" +" <file>[--pathspec-ó-comhad = [--pathspec-comhad-nul]]\n" +" [--] [<pathspec>...]]" + +#: builtin/stash.c +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] [<message>]" + +#: builtin/stash.c +msgid "git stash create [<message>]" +msgstr "<message>git stash cruthaigh []" + +#: builtin/stash.c +#, c-format +msgid "'%s' is not a stash-like commit" +msgstr "Nà gealltanas cosúil le stash é '%s'" + +#: builtin/stash.c +#, c-format +msgid "Too many revisions specified:%s" +msgstr "SonraÃtear an iomarca athbhreithnithe: %s" + +#: builtin/stash.c +msgid "No stash entries found." +msgstr "NÃor aimsÃodh aon iontrálacha stash." + +#: builtin/stash.c +#, c-format +msgid "%s is not a valid reference" +msgstr "Nà tagairt bailà é %s" + +#: builtin/stash.c +msgid "git stash clear with arguments is unimplemented" +msgstr "nÃl git stash clear le hargóintà neamh-chur i bhfeidhm" + +#: builtin/stash.c +#, c-format +msgid "" +"WARNING: Untracked file in way of tracked file! Renaming\n" +" %s -> %s\n" +" to make room.\n" +msgstr "" +"RABHADH: Comhad neamhrianaithe ar bhealach comhad rianaithe! Athainmniú\n" +" %s -> %s\n" +" chun seomra a dhéanamh.\n" + +#: builtin/stash.c +msgid "cannot apply a stash in the middle of a merge" +msgstr "nà féidir stash a chur i bhfeidhm i lár cumaisc" + +#: builtin/stash.c +#, c-format +msgid "could not generate diff %s^!." +msgstr "nà fhéadfaà diff %s^ a ghiniúint!." + +#: builtin/stash.c +msgid "conflicts in index. Try without --index." +msgstr "coinbhleachtaà in innéacs. Bain triail as gan --index." + +#: builtin/stash.c +msgid "could not save index tree" +msgstr "nà fhéadfadh crann innéacs a shábháil" + +#: builtin/stash.c +#, c-format +msgid "Merging %s with %s" +msgstr "Cumasc %s le %s" + +#: builtin/stash.c +msgid "Index was not unstashed." +msgstr "Nà raibh an t-innéacs gan stashed." + +#: builtin/stash.c +msgid "could not restore untracked files from stash" +msgstr "nà raibh in ann comhaid neamhrianaithe a chur ar ais ó stash" + +#: builtin/stash.c +msgid "attempt to recreate the index" +msgstr "iarracht an t-innéacs a athchruthú" + +#: builtin/stash.c +#, c-format +msgid "Dropped %s (%s)" +msgstr "Scaoil %s (%s)" + +#: builtin/stash.c +#, c-format +msgid "%s: Could not drop stash entry" +msgstr "%s: Nà fhéadfaà iontráil stash a scaoileadh" + +#: builtin/stash.c +#, c-format +msgid "'%s' is not a stash reference" +msgstr "Nà tagairt stash é '%s'" + +#: builtin/stash.c +msgid "The stash entry is kept in case you need it again." +msgstr "CoinnÃtear an iontráil stash ar eagla go dteastaÃonn sé uait arÃs." + +#: builtin/stash.c +msgid "No branch name specified" +msgstr "NÃl aon ainm brainse sonraithe" + +#: builtin/stash.c +msgid "failed to parse tree" +msgstr "theip ar chrann a pháirseáil" + +#: builtin/stash.c +msgid "failed to unpack trees" +msgstr "theip ar chrainn a dhÃphacáil" + +#: builtin/stash.c +msgid "include untracked files in the stash" +msgstr "comhaid neamhrianaithe san áireamh sa stash" + +#: builtin/stash.c +msgid "only show untracked files in the stash" +msgstr "nà thaispeánann ach comhaid neamhrianaithe sa stash" + +#: builtin/stash.c +#, c-format +msgid "Cannot update %s with %s" +msgstr "Nà féidir %s a nuashonrú le %s" + +#: builtin/stash.c +msgid "stash message" +msgstr "teachtaireacht stash" + +#: builtin/stash.c +msgid "\"git stash store\" requires one <commit> argument" +msgstr "<commit>ÉilÃonn “git stash store†argóint amháin" + +#: builtin/stash.c +msgid "No staged changes" +msgstr "Gan aon athruithe céime" + +#: builtin/stash.c +msgid "No changes selected" +msgstr "Gan aon athruithe roghnaithe" + +#: builtin/stash.c +msgid "You do not have the initial commit yet" +msgstr "NÃl an tiomantas tosaigh agat fós" + +#: builtin/stash.c +msgid "Cannot save the current index state" +msgstr "Nà féidir an staid innéacs reatha a shábháil" + +#: builtin/stash.c +msgid "Cannot save the untracked files" +msgstr "Nà féidir na comhaid neamhrianaithe a shábháil" + +#: builtin/stash.c +msgid "Cannot save the current worktree state" +msgstr "Nà féidir an stát crainn oibre reatha a shábháil" + +#: builtin/stash.c +msgid "Cannot save the current staged state" +msgstr "Nà féidir an stát stáitse reatha a shábháil" + +#: builtin/stash.c +msgid "Cannot record working tree state" +msgstr "Nà féidir stát crann oibre a thaifead" + +#: builtin/stash.c +msgid "Can't use --patch and --include-untracked or --all at the same time" +msgstr "" +"Nà féidir --patch agus --include-untracked nó --all a úsáid ag an am céanna" + +#: builtin/stash.c +msgid "Can't use --staged and --include-untracked or --all at the same time" +msgstr "" +"Nà féidir --staged agus --include-untracked nó --all a úsáid ag an am céanna" + +#: builtin/stash.c +msgid "Did you forget to 'git add'?" +msgstr "Ar ndearna tú dearmad 'git add'?" + +#: builtin/stash.c +msgid "No local changes to save" +msgstr "NÃl aon athruithe áitiúla le sábháil" + +#: builtin/stash.c +msgid "Cannot initialize stash" +msgstr "Nà féidir stash a thionscnamh" + +#: builtin/stash.c +msgid "Cannot save the current status" +msgstr "Nà féidir an stádas reatha a shábháil" + +#: builtin/stash.c +#, c-format +msgid "Saved working directory and index state %s" +msgstr "Eolaire oibre shábháilte agus staid innéacs %s" + +#: builtin/stash.c +msgid "Cannot remove worktree changes" +msgstr "Nà féidir athruithe crann oibre a bhaint" + +#: builtin/stash.c +msgid "keep index" +msgstr "coinnigh innéacs" + +#: builtin/stash.c +msgid "stash staged changes only" +msgstr "athruithe céimeádta stash amháin" + +#: builtin/stash.c +msgid "stash in patch mode" +msgstr "stash i mód paiste" + +#: builtin/stash.c +msgid "quiet mode" +msgstr "modh ciúin" + +#: builtin/stash.c +msgid "include untracked files in stash" +msgstr "comhaid neamhrianaithe a chur san áireamh i stash" + +#: builtin/stash.c +msgid "include ignore files" +msgstr "áireamh neamhaird a dhéanamh" + +#: builtin/stripspace.c +msgid "skip and remove all lines starting with comment character" +msgstr "scipeáil agus bain gach lÃne ag tosú le carachtar trácht" + +#: builtin/stripspace.c +msgid "prepend comment character and space to each line" +msgstr "carachtar tráchta agus spás a chur ar fáil chuig gach lÃne" + +#: builtin/submodule--helper.c +#, c-format +msgid "Expecting a full ref name, got %s" +msgstr "Ag súil le hainm tagartha iomlán, fuair %s" + +#: builtin/submodule--helper.c +#, c-format +msgid "could not get a repository handle for submodule '%s'" +msgstr "nà fhéadfaà láimhseáil stór a fháil do fho-mhodúl '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"could not look up configuration '%s'. Assuming this repository is its own " +"authoritative upstream." +msgstr "" +"nà fhéadfaà cumraÃocht '%s' a fheiceáil suas. Ag glacadh leis gurb é an stór " +"seo a údarásach suas sruth féin." + +#: builtin/submodule--helper.c +#, c-format +msgid "No url found for submodule path '%s' in .gitmodules" +msgstr "NÃl aon url le haghaidh cosán fo-mhodúil '%s' i .gitmodules" + +#: builtin/submodule--helper.c +#, c-format +msgid "Entering '%s'\n" +msgstr "Ag iontráil '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"run_command returned non-zero status for %s\n" +"." +msgstr "" +"thug run_command stádas neamh-nialas ar ais do %s.\n" +"." + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"run_command returned non-zero status while recursing in the nested " +"submodules of %s\n" +"." +msgstr "" +"d'fhill run_command stádas neamh-nialasach agus é ag athshlánú sna fo-" +"mhodúil neadaithe de %s\n" +"." + +#: builtin/submodule--helper.c +msgid "suppress output of entering each submodule command" +msgstr "cosc a chur ar aschur gach ordú fo-mhodúil a chur isteach" + +#: builtin/submodule--helper.c +msgid "recurse into nested submodules" +msgstr "athshlánú isteach i bhfo-mhodúil neadaithe" + +#: builtin/submodule--helper.c +msgid "git submodule foreach [--quiet] [--recursive] [--] <command>" +msgstr "git submodule foreach [--quiet] [--recursive] [--] <command>" + +#: builtin/submodule--helper.c +#, c-format +msgid "Failed to register url for submodule path '%s'" +msgstr "Theip ar url a chlárú le haghaidh cosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Submodule '%s' (%s) registered for path '%s'\n" +msgstr "Fo-mhodúl '%s' (%s) cláraithe le haghaidh cosán '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "warning: command update mode suggested for submodule '%s'\n" +msgstr "rabhadh: modh nuashonraithe ordaithe a mholtar don fho-mhodúl '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "Failed to register update mode for submodule path '%s'" +msgstr "Theip ar mhodh nuashonraithe a chlárú do chonair fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +msgid "suppress output for initializing a submodule" +msgstr "aschur a chur faoi chois chun fo-mhodúl a thosú" + +#: builtin/submodule--helper.c +msgid "git submodule init [<options>] [<path>]" +msgstr "git submodule init [<options>] [<path>]" + +#: builtin/submodule--helper.c +#, c-format +msgid "no submodule mapping found in .gitmodules for path '%s'" +msgstr "" +"nÃl aon mhapáil fo-mhodúil le fáil i .gitmodules le haghaidh cosán '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "could not resolve HEAD ref inside the submodule '%s'" +msgstr "nà fhéadfaà tagairt HEAD a réiteach taobh istigh den fho-mhodúl '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "failed to recurse into submodule '%s'" +msgstr "theip ar athshlánú isteach i bhfo-mhodúl '%s'" + +#: builtin/submodule--helper.c +msgid "suppress submodule status output" +msgstr "aschur stádas fo-mhodúil a chur faoi cho" + +#: builtin/submodule--helper.c +msgid "" +"use commit stored in the index instead of the one stored in the submodule " +"HEAD" +msgstr "" +"bain úsáid as tiomantas atá stóráilte san innéacs in ionad an ceann atá " +"stóráilte sa fho-mhodúl HEAD" + +#: builtin/submodule--helper.c +msgid "git submodule status [--quiet] [--cached] [--recursive] [<path>...]" +msgstr "git submodule status [--quiet] [--cached] [--recursive] [<path>...]" + +#: builtin/submodule--helper.c +#, c-format +msgid "* %s %s(blob)->%s(submodule)" +msgstr "* %s %s (blob) -> %s (fo-mhodúl)" + +#: builtin/submodule--helper.c +#, c-format +msgid "* %s %s(submodule)->%s(blob)" +msgstr "* %s %s (fo-mhodúl) -> %s (blob)" + +#: builtin/submodule--helper.c +#, c-format +msgid "%s" +msgstr "%s" + +#: builtin/submodule--helper.c +#, c-format +msgid "couldn't hash object from '%s'" +msgstr "nà fhéadfaà réad hash ó '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "unexpected mode %o" +msgstr "modh gan choinne %o" + +#: builtin/submodule--helper.c +msgid "use the commit stored in the index instead of the submodule HEAD" +msgstr "" +"bain úsáid as an gealltanas atá stóráilte san innéacs in ionad an fho-mhodúl " +"HEAD" + +#: builtin/submodule--helper.c +msgid "compare the commit in the index with that in the submodule HEAD" +msgstr "" +"comparáid a dhéanamh idir an tiomantas san innéacs leis an bhfo-mhodúl HEAD" + +#: builtin/submodule--helper.c +msgid "skip submodules with 'ignore_config' value set to 'all'" +msgstr "scipeáil fo-mhodúil le luach 'ignore_config' socraithe go 'go léir'" + +#: builtin/submodule--helper.c +msgid "limit the summary size" +msgstr "teorainn a chur leis an méid achoimre" + +#: builtin/submodule--helper.c +msgid "git submodule summary [<options>] [<commit>] [--] [<path>]" +msgstr "git achoimre fo-mhodúil [<options>] [<commit>] [--] [<path>]" + +#: builtin/submodule--helper.c +msgid "could not fetch a revision for HEAD" +msgstr "nà fhéadfaà athbhreithniú a fháil do HEAD" + +#: builtin/submodule--helper.c +#, c-format +msgid "Synchronizing submodule url for '%s'\n" +msgstr "Url fo-mhodúil a shioncrónú do '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "failed to register url for submodule path '%s'" +msgstr "theip ar url a chlárú le haghaidh cosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "failed to update remote for submodule '%s'" +msgstr "theip ar iargúlta a nuashonrú do fho-mhodúl '%s'" + +#: builtin/submodule--helper.c +msgid "suppress output of synchronizing submodule url" +msgstr "aschur url fo-mhodúil sioncrónaithe a chur faoi chois" + +#: builtin/submodule--helper.c +msgid "git submodule sync [--quiet] [--recursive] [<path>]" +msgstr "git sioncrónú fo-mhodúil [--quiet] [--recursive] [<path>]" + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"Submodule work tree '%s' contains a .git directory. This will be replaced " +"with a .git file by using absorbgitdirs." +msgstr "" +"Tá eolair .git i gcrann oibre fo-mhodúil '%s'. Cuirfear comhad .git in ionad " +"seo trà absorbgitdirs a úsáid." + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"Submodule work tree '%s' contains local modifications; use '-f' to discard " +"them" +msgstr "" +"Tá modhnuithe áitiúla i gcrann oibre fo-mhodúil '%s'; bain úsáid as '-f' " +"chun iad a dhiúscairt" + +#: builtin/submodule--helper.c +#, c-format +msgid "Cleared directory '%s'\n" +msgstr "Glanadh an eolaire '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "Could not remove submodule work tree '%s'\n" +msgstr "NÃor féidir crann oibre fo-mhodúil '%s' a bhaint\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "could not create empty submodule directory %s" +msgstr "nà fhéadfaà eolaire fo-mhodúil folamh %s a chruthú" + +#: builtin/submodule--helper.c +#, c-format +msgid "Submodule '%s' (%s) unregistered for path '%s'\n" +msgstr "Fo-mhodúl '%s' (%s) neamhchláraithe le haghaidh cosán '%s'\n" + +#: builtin/submodule--helper.c +msgid "remove submodule working trees even if they contain local changes" +msgstr "crainn oibre fo-mhodúil a bhaint fiú má tá athruithe áitiúla iontu" + +#: builtin/submodule--helper.c +msgid "unregister all submodules" +msgstr "gach fo-mhodúl a dhÃchlárú" + +#: builtin/submodule--helper.c +msgid "" +"git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]" +msgstr "" +"git fo-mhodúil deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]" + +#: builtin/submodule--helper.c +msgid "Use '--all' if you really want to deinitialize all submodules" +msgstr "Úsáid '--all' más mian leat gach fo-mhodúl a dhÃthionsú i ndáirÃre" + +#: builtin/submodule--helper.c +msgid "" +"An alternate computed from a superproject's alternate is invalid.\n" +"To allow Git to clone without an alternate in such a case, set\n" +"submodule.alternateErrorStrategy to 'info' or, equivalently, clone with\n" +"'--reference-if-able' instead of '--reference'." +msgstr "" +"Tá malartach arna rÃomh ó mhalartach sárthionscadail neamhbhailÃ.\n" +"Chun ligean Git a chlónú gan malartach i gcás den sórt sin, socraigh\n" +"submodule.alternateErrorStrategy chun 'faisnéis' nó, go coibhéiseach, clónú " +"le\n" +"'--reference-if-able' in ionad '--reference'." + +#: builtin/submodule--helper.c +#, c-format +msgid "could not get a repository handle for gitdir '%s'" +msgstr "nà fhéadfaà láimhseáil stór a fháil do gitdir '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "submodule '%s' cannot add alternate: %s" +msgstr "nà féidir le fo-mhodúl '%s' malartach a chur leis: %s" + +#: builtin/submodule--helper.c +#, c-format +msgid "Value '%s' for submodule.alternateErrorStrategy is not recognized" +msgstr "Luach '%s' le haghaidh submodule.alternateErrorStrategy nà aithnÃtear" + +#: builtin/submodule--helper.c +#, c-format +msgid "Value '%s' for submodule.alternateLocation is not recognized" +msgstr "Luach '%s' le haghaidh submodule.alternateLocation nà aithnÃtear" + +#: builtin/submodule--helper.c submodule.c +#, c-format +msgid "refusing to create/use '%s' in another submodule's git dir" +msgstr "diúltú '%s' a chruthú/úsáid i git dir fo-mhodúil eile" + +#: builtin/submodule--helper.c +#, c-format +msgid "directory not empty: '%s'" +msgstr "eolaire nach folamh: '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "clone of '%s' into submodule path '%s' failed" +msgstr "theip ar chlón '%s' isteach i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "could not get submodule directory for '%s'" +msgstr "nà fhéadfaà eolaire fo-mhodúil a fháil do '%s'" + +#: builtin/submodule--helper.c +msgid "alternative anchor for relative paths" +msgstr "ancaire malartach do chonair choibhneasta" + +#: builtin/submodule--helper.c +msgid "where the new submodule will be cloned to" +msgstr "áit a gclónófar an fo-mhodúl nua" + +#: builtin/submodule--helper.c +msgid "name of the new submodule" +msgstr "ainm an fho-mhodúil nua" + +#: builtin/submodule--helper.c +msgid "url where to clone the submodule from" +msgstr "url cá háit ar féidir an fo-mhodúl a chlónáil" + +#: builtin/submodule--helper.c +msgid "depth for shallow clones" +msgstr "doimhneacht do chlóin éadomhain" + +#: builtin/submodule--helper.c +msgid "force cloning progress" +msgstr "dul chun cinn clónaithe fórsa" + +#: builtin/submodule--helper.c +msgid "disallow cloning into non-empty directory" +msgstr "clónú a dhÃcheadú isteach i eolaire neamh-folamh" + +#: builtin/submodule--helper.c +msgid "" +"git submodule--helper clone [--prefix=<path>] [--quiet] [--reference " +"<repository>] [--name <name>] [--depth <depth>] [--single-branch] [--filter " +"<filter-spec>] --url <url> --path <path>" +msgstr "" +"git submodule--helper clone [--prefix=<path>] [--quiet] [--reference " +"<repository>] [--name <name>] [--depth <depth>] [--single-branch] [--filter " +"<filter-spec>] --url <url> --path <path>" + +#: builtin/submodule--helper.c +#, c-format +msgid "Invalid update mode '%s' configured for submodule path '%s'" +msgstr "" +"Modh nuashonraithe neamhbhailà '%s' cumraithe le haghaidh cosán fo-mhodúil " +"'%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Submodule path '%s' not initialized" +msgstr "NÃor thosaigh cosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +msgid "Maybe you want to use 'update --init'?" +msgstr "B'fhéidir gur mhaith leat 'update --init' a úsáid?" + +#: builtin/submodule--helper.c +#, c-format +msgid "Skipping unmerged submodule %s" +msgstr "Fo-mhodúl neamh-mheánaithe %s a scipeáil" + +#: builtin/submodule--helper.c +#, c-format +msgid "Skipping submodule '%s'" +msgstr "Fo-mhodúl '%s' a scipeáil" + +#: builtin/submodule--helper.c +#, c-format +msgid "cannot clone submodule '%s' without a URL" +msgstr "nà féidir le fo-mhodúl '%s' a chlónú gan URL" + +#: builtin/submodule--helper.c +#, c-format +msgid "Failed to clone '%s'. Retry scheduled" +msgstr "Theip ar chlónáil '%s'. Déan iarracht sceidealta" + +#: builtin/submodule--helper.c +#, c-format +msgid "Failed to clone '%s' a second time, aborting" +msgstr "Theip ar chlónáil '%s' an dara huair, ag cur isteach" + +#: builtin/submodule--helper.c +#, c-format +msgid "Unable to checkout '%s' in submodule path '%s'" +msgstr "Nà féidir '%s' a sheiceáil i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Unable to rebase '%s' in submodule path '%s'" +msgstr "Nà féidir '%s' a athbhunú i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Unable to merge '%s' in submodule path '%s'" +msgstr "Nà féidir '%s' a chumasc i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Execution of '%s %s' failed in submodule path '%s'" +msgstr "Theip ar fhorghnÃomhú '%s %s' i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Submodule path '%s': checked out '%s'\n" +msgstr "Conair fo-mhodúil '%s': seiceáil amach '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "Submodule path '%s': rebased into '%s'\n" +msgstr "Conair fo-mhodúil '%s': athbhunaithe go '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "Submodule path '%s': merged in '%s'\n" +msgstr "Conair fo-mhodúil '%s': cumasc i '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "Submodule path '%s': '%s %s'\n" +msgstr "Conair fo-mhodúil '%s': '%s %s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "Unable to fetch in submodule path '%s'; trying to directly fetch %s:" +msgstr "" +"Nà féidir cosán fo-mhodúil '%s' a fháil; ag iarraidh %s a fháil go dÃreach:" + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"Fetched in submodule path '%s', but it did not contain %s. Direct fetching " +"of that commit failed." +msgstr "" +"Faightear i gcosán fo-mhodúil '%s', ach nà raibh %s ann. Theip ar an " +"tiomantas sin a thógáil go dÃreach." + +#: builtin/submodule--helper.c +#, c-format +msgid "could not initialize submodule at path '%s'" +msgstr "nà fhéadfaà fo-mhodúl a thosú ag cosán '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"Submodule (%s) branch configured to inherit branch from superproject, but " +"the superproject is not on any branch" +msgstr "" +"Brainse fo-mhodúil (%s) atá cumraithe chun brainse a oidhreacht ó " +"sárthionscadal, ach nÃl an sárthionscadal ar aon bhrainse" + +#: builtin/submodule--helper.c +#, c-format +msgid "Unable to find current revision in submodule path '%s'" +msgstr "Nà féidir an t-athbhreithniú reatha a fháil i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Unable to fetch in submodule path '%s'" +msgstr "Nà féidir le cosán fo-mhodúil '%s' a fháil" + +#: builtin/submodule--helper.c +#, c-format +msgid "Unable to find %s revision in submodule path '%s'" +msgstr "Nà féidir athbhreithniú %s a aimsiú i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Failed to recurse into submodule path '%s'" +msgstr "Theip ar athshlánú isteach i gcosán fo-mhodúil '%s'" + +#: builtin/submodule--helper.c +msgid "force checkout updates" +msgstr "nuashonruithe seiceála de" + +#: builtin/submodule--helper.c +msgid "initialize uninitialized submodules before update" +msgstr "fo-mhodúil neamhthosaithe a thosú roimh an nuashonrú" + +#: builtin/submodule--helper.c +msgid "use SHA-1 of submodule's remote tracking branch" +msgstr "úsáid SHA-1 de bhrainse cianrianaithe an fho-mhodúil" + +#: builtin/submodule--helper.c +msgid "traverse submodules recursively" +msgstr "fo-mhodúil a thrasú go athshlánach" + +#: builtin/submodule--helper.c +msgid "don't fetch new objects from the remote site" +msgstr "ná faigh rudaà nua ón suÃomh iargúlta" + +#: builtin/submodule--helper.c +msgid "use the 'checkout' update strategy (default)" +msgstr "úsáid an straitéis nuashonraithe 'tseiceáil' (réamhshocraithe)" + +#: builtin/submodule--helper.c +msgid "use the 'merge' update strategy" +msgstr "úsáid an straitéis nuashonraithe 'cumaisc'" + +#: builtin/submodule--helper.c +msgid "use the 'rebase' update strategy" +msgstr "bain úsáid as an straitéis nuashonraithe 'rebase'" + +#: builtin/submodule--helper.c +msgid "create a shallow clone truncated to the specified number of revisions" +msgstr "" +"clón éadomhain a chruthú a ghearrtar go dtà an lÃon sonraithe athbhreithnithe" + +#: builtin/submodule--helper.c +msgid "parallel jobs" +msgstr "poist chomhthreomhara" + +#: builtin/submodule--helper.c +msgid "whether the initial clone should follow the shallow recommendation" +msgstr "cibé an chóir don chlón tosaigh an moladh éadrom a leanú" + +#: builtin/submodule--helper.c +msgid "don't print cloning progress" +msgstr "ná déan dul chun cinn clónaithe a phriontáil" + +#: builtin/submodule--helper.c +msgid "disallow cloning into non-empty directory, implies --init" +msgstr "" +"clónú a dhÃcheadú isteach i eolaire neamh-folamh, tugann le tuiscint --init" + +#: builtin/submodule--helper.c +msgid "" +"git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] " +"[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-" +"shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] " +"[--] [<path>...]" +msgstr "" +"git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] " +"[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-" +"shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] " +"[--] [<path>...]" + +#: builtin/submodule--helper.c submodule.c +msgid "Failed to resolve HEAD as a valid ref." +msgstr "Theip ar HEAD a réiteach mar thagartha bailÃ." + +#: builtin/submodule--helper.c +msgid "git submodule absorbgitdirs [<options>] [<path>...]" +msgstr "git submodule absorbgitdirs [<options>] [<path>...]" + +#: builtin/submodule--helper.c +msgid "suppress output for setting url of a submodule" +msgstr "aschur a chur faoi chois chun url fo-mhodúil a shocrú" + +#: builtin/submodule--helper.c +msgid "git submodule set-url [--quiet] <path> <newurl>" +msgstr "git submodule set-url [--quiet] <path> <newurl>" + +#: builtin/submodule--helper.c +msgid "set the default tracking branch to master" +msgstr "socraigh an mbrainse rianaithe réamhshocraithe chun" + +#: builtin/submodule--helper.c +msgid "set the default tracking branch" +msgstr "socraigh an brainse rianaithe réamhshoc" + +#: builtin/submodule--helper.c +msgid "git submodule set-branch [-q|--quiet] (-d|--default) <path>" +msgstr "git submodule set-branch [-q|--quiet] (-d|--default) <path>" + +#: builtin/submodule--helper.c +msgid "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>" +msgstr "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>" + +#: builtin/submodule--helper.c +msgid "--branch or --default required" +msgstr "--branch nó --default ag teastáil" + +#: builtin/submodule--helper.c +msgid "print only error messages" +msgstr "teachtaireachtaà earráide amháin a phrion" + +#: builtin/submodule--helper.c +msgid "force creation" +msgstr "cruthú fórsa" + +#: builtin/submodule--helper.c +msgid "show whether the branch would be created" +msgstr "taispeáint an cruthófaà an mbrainse" + +#: builtin/submodule--helper.c +msgid "" +"git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--" +"quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>" +msgstr "" +"git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--" +"quiet] [-t|--track] [-n|--dry-run] <name> <start-oid> <start-name>" + +#: builtin/submodule--helper.c +#, c-format +msgid "creating branch '%s'" +msgstr "ag cruthú brainse '%s'" + +#: builtin/submodule--helper.c +#, c-format +msgid "Adding existing repo at '%s' to the index\n" +msgstr "Ag cur repo atá ann cheana ag '%s' leis an innéacs\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "'%s' already exists and is not a valid git repo" +msgstr "Tá '%s' ann cheana féin agus nà repo git bailà é" + +#: builtin/submodule--helper.c +#, c-format +msgid "A git directory for '%s' is found locally with remote(s):\n" +msgstr "Faightear eolaire git le haghaidh '%s' go háitiúil le cianda(Ã):\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "" +"If you want to reuse this local git directory instead of cloning again from\n" +" %s\n" +"use the '--force' option. If the local git directory is not the correct " +"repo\n" +"or you are unsure what this means choose another name with the '--name' " +"option." +msgstr "" +"Más mian leat an eolaire git áitiúil seo a athúsáid in ionad clónú arÃs ó\n" +" %s\n" +"bain úsáid as an rogha '--force'. Mura bhfuil an t-eolaire git áitiúil an " +"repo ceart\n" +"nó nÃl tú cinnte cad a chiallaÃonn sé seo roghnaigh ainm eile leis an rogha " +"'--name'." + +#: builtin/submodule--helper.c +#, c-format +msgid "Reactivating local git directory for submodule '%s'\n" +msgstr "Eolaire git áitiúil a athghnÃomhachtú do fho-mhodúl '%s'\n" + +#: builtin/submodule--helper.c +#, c-format +msgid "unable to checkout submodule '%s'" +msgstr "nà féidir le fo-mhodúl '%s' a sheiceáil" + +#: builtin/submodule--helper.c +msgid "please make sure that the .gitmodules file is in the working tree" +msgstr "déan cinnte go bhfuil an comhad .gitmodules sa chrann oibre" + +#: builtin/submodule--helper.c +#, c-format +msgid "Failed to add submodule '%s'" +msgstr "Theip ar fho-mhodúl '%s' a chur leis" + +#: builtin/submodule--helper.c +#, c-format +msgid "Failed to register submodule '%s'" +msgstr "Theip ar fho-mhodúl '%s' a chlárú" + +#: builtin/submodule--helper.c +#, c-format +msgid "'%s' already exists in the index" +msgstr "Tá '%s' ann cheana féin san innéacs" + +#: builtin/submodule--helper.c +#, c-format +msgid "'%s' already exists in the index and is not a submodule" +msgstr "Tá '%s' ann cheana féin san innéacs agus nà fo-mhodúl é" + +#: builtin/submodule--helper.c read-cache.c +#, c-format +msgid "'%s' does not have a commit checked out" +msgstr "NÃl tiomantas seiceáilte ag '%s'" + +#: builtin/submodule--helper.c +msgid "branch of repository to add as submodule" +msgstr "brainse an stór le cur mar fho-mhodúl" + +#: builtin/submodule--helper.c +msgid "allow adding an otherwise ignored submodule path" +msgstr "ligean cosán fo-mhodúil a neamhaird a chur leis" + +#: builtin/submodule--helper.c +msgid "borrow the objects from reference repositories" +msgstr "iasacht na rudaà ó stórais tagartha" + +#: builtin/submodule--helper.c +msgid "" +"sets the submodule's name to the given string instead of defaulting to its " +"path" +msgstr "" +"socraÃonn ainm an fho-mhodúil don teaghrán a thugtar in ionad réamhshocrú ar " +"a chosán" + +#: builtin/submodule--helper.c +msgid "git submodule add [<options>] [--] <repository> [<path>]" +msgstr "git submodule add [<options>] [--] <repository> [<path>]" + +#: builtin/submodule--helper.c +msgid "Relative path can only be used from the toplevel of the working tree" +msgstr "Nà féidir cosán coibhneasta a úsáid ach ó bharr an chrainn oibre" + +#: builtin/submodule--helper.c +#, c-format +msgid "repo URL: '%s' must be absolute or begin with ./|../" +msgstr "repo URL: caithfidh '%s' a bheith iomlán nó tosú leis. /| .. /" + +#: builtin/submodule--helper.c +#, c-format +msgid "'%s' is not a valid submodule name" +msgstr "Nà ainm bailà fo-mhodúil é '%s'" + +#: builtin/submodule--helper.c +msgid "git submodule--helper <command>" +msgstr "git submodule--helper <command>" + +#: builtin/symbolic-ref.c +msgid "git symbolic-ref [-m <reason>] <name> <ref>" +msgstr "git symbolic-ref [-m <reason>] <name> <ref>" + +#: builtin/symbolic-ref.c +msgid "git symbolic-ref [-q] [--short] [--no-recurse] <name>" +msgstr "git symbolic-ref [-q] [--short] [--no-recurse] <name>" + +#: builtin/symbolic-ref.c +msgid "git symbolic-ref --delete [-q] <name>" +msgstr "git symbolic-ref --delete [-q] <name>" + +#: builtin/symbolic-ref.c +msgid "suppress error message for non-symbolic (detached) refs" +msgstr "" +"teachtaireacht earráide a chur faoi chois le haghaidh tuairimà neamh-" +"shiombalacha" + +#: builtin/symbolic-ref.c +msgid "delete symbolic ref" +msgstr "scrios tagairt siombalach" + +#: builtin/symbolic-ref.c +msgid "shorten ref output" +msgstr "aschur tagairt a ghiorrú" + +#: builtin/symbolic-ref.c +msgid "recursively dereference (default)" +msgstr "dereference athshlánach (réamhshocraithe)" + +#: builtin/symbolic-ref.c builtin/update-ref.c +msgid "reason" +msgstr "cúis" + +#: builtin/symbolic-ref.c builtin/update-ref.c +msgid "reason of the update" +msgstr "cúis an nuashonraithe" + +#: builtin/tag.c +msgid "" +"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" +" <tagname> [<commit> | <object>]" +msgstr "" +"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n" +" [(--trailer <token>[(=|:)<value>])...]\n" +" <tagname> [<commit> | <object>]" + +#: builtin/tag.c +msgid "git tag -d <tagname>..." +msgstr "git tag -d <tagname>..." + +#: builtin/tag.c +msgid "" +"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 "" +"<commit>tag git [-n [<num>]] -l [--conté] [--no-conté<commit>]\n" +" <options>[--points-ag<object>] [--column [=] | --no-column]\n" +" <key><format>[--create-reflog] [--sort=] [--format =]\n" +" <pattern>[--cumaisc<commit>] [--no-cumaisc] [...<commit>]" + +#: builtin/tag.c +msgid "git tag -v [--format=<format>] <tagname>..." +msgstr "<format><tagname>tag git -v [--format =]..." + +#: builtin/tag.c +#, c-format +msgid "tag '%s' not found." +msgstr "nÃor aimsÃodh tag '%s'." + +#: builtin/tag.c +#, c-format +msgid "Deleted tag '%s' (was %s)\n" +msgstr "Clib scriosta '%s' (bhà %s)\n" + +#: builtin/tag.c +#, c-format +msgid "" +"\n" +"Write a message for tag:\n" +" %s\n" +"Lines starting with '%s' will be ignored.\n" +msgstr "" +"\n" +"ScrÃobh teachtaireacht don chlib:\n" +" %s\n" +"Déanfar neamhaird ar lÃnte a thosaÃonn le '%s'.\n" + +#: builtin/tag.c +#, c-format +msgid "" +"\n" +"Write a message for tag:\n" +" %s\n" +"Lines starting with '%s' will be kept; you may remove them yourself if you " +"want to.\n" +msgstr "" +"\n" +"ScrÃobh teachtaireacht don chlib:\n" +" %s\n" +"Coinneofar lÃnte a thosaÃonn le '%s'; féadfaidh tú iad a bhaint féin más " +"mian leat.\n" + +#: builtin/tag.c +msgid "unable to sign the tag" +msgstr "in ann an chlib a shÃniú" + +#: builtin/tag.c +#, c-format +msgid "" +"You have created a nested tag. The object referred to by your new tag is\n" +"already a tag. If you meant to tag the object that it points to, use:\n" +"\n" +"\tgit tag -f %s %s^{}" +msgstr "" +"Tá clib neadaithe cruthaithe agat. Is é an réad dá dtagraÃonn do chlib nua\n" +"clib cheana féin. Má bhà sé i gceist agat an réad a thugann sé in iúl dó a " +"chlibeáil, bain úsáid as:\n" +"\n" +" clib git -f %s %s^ {}" + +#: builtin/tag.c +msgid "bad object type." +msgstr "droch-chineál réad." + +#: builtin/tag.c +msgid "no tag message?" +msgstr "gan aon teachtaireacht clib?" + +#: builtin/tag.c +#, c-format +msgid "The tag message has been left in %s\n" +msgstr "Tá an teachtaireacht clib fágtha i %s\n" + +#: builtin/tag.c +msgid "list tag names" +msgstr "ainmneacha clibeanna liosta" + +#: builtin/tag.c +msgid "print <n> lines of each tag message" +msgstr "<n>lÃnte priontála de gach teachtaireacht clib" + +#: builtin/tag.c +msgid "delete tags" +msgstr "clibeanna a scriosadh" + +#: builtin/tag.c +msgid "verify tags" +msgstr "clibeanna a fÃorú" + +#: builtin/tag.c +msgid "Tag creation options" +msgstr "Roghanna cruthaithe clibeanna" + +#: builtin/tag.c +msgid "annotated tag, needs a message" +msgstr "clib anótáilte, teastaÃonn teachtaireacht" + +#: builtin/tag.c +msgid "tag message" +msgstr "teachtaireacht tag" + +#: builtin/tag.c +msgid "force edit of tag message" +msgstr "eagarthóireacht fórsa ar theachtaireacht" + +#: builtin/tag.c +msgid "annotated and GPG-signed tag" +msgstr "clib anótáilte agus sÃnithe GPS" + +#: builtin/tag.c +msgid "use another key to sign the tag" +msgstr "bain úsáid as eochair eile chun an chlib a shÃniú" + +#: builtin/tag.c +msgid "replace the tag if exists" +msgstr "athsholáthar an chlib má tá sé ann" + +#: builtin/tag.c builtin/update-ref.c +msgid "create a reflog" +msgstr "cruthaigh reflog" + +#: builtin/tag.c +msgid "Tag listing options" +msgstr "Roghanna liostaithe clibeanna" + +#: builtin/tag.c +msgid "show tag list in columns" +msgstr "taispeáin liosta clibeanna i gcolúin" + +#: builtin/tag.c +msgid "print only tags that contain the commit" +msgstr "clibeanna a phriontáil ach ina bhfuil an tiomantas" + +#: builtin/tag.c +msgid "print only tags that don't contain the commit" +msgstr "clibeanna nach bhfuil an tiomantas a phriontáil ach amháin" + +#: builtin/tag.c +msgid "print only tags that are merged" +msgstr "clibeanna a chumasc amháin a phriontáil" + +#: builtin/tag.c +msgid "print only tags that are not merged" +msgstr "clibeanna nach ndéantar cumaisc a phriontáil ach amháin" + +#: builtin/tag.c +msgid "print only tags of the object" +msgstr "clibeanna den réad amháin a phriontáil" + +#: builtin/tag.c +msgid "could not start 'git column'" +msgstr "nà fhéadfaà 'git column' a thosú" + +#: builtin/tag.c +#, c-format +msgid "the '%s' option is only allowed in list mode" +msgstr "nà cheadaÃtear an rogha '%s' ach i mód liosta" + +#: builtin/tag.c +#, c-format +msgid "'%s' is not a valid tag name." +msgstr "Nà ainm bailà clibeanna é '%s'." + +#: builtin/tag.c +#, c-format +msgid "tag '%s' already exists" +msgstr "tá clib '%s' ann cheana féin" + +#: builtin/tag.c sequencer.c +#, c-format +msgid "Invalid cleanup mode %s" +msgstr "Modh glantacháin neamhbhailà %s" + +#: builtin/tag.c +#, c-format +msgid "Updated tag '%s' (was %s)\n" +msgstr "Clib nuashonraithe '%s' (bhà %s)\n" + +#: builtin/unpack-objects.c +msgid "pack exceeds maximum allowed size" +msgstr "sáraÃonn an pacáiste an méid uasta a" + +#: builtin/unpack-objects.c +msgid "failed to write object in stream" +msgstr "theip ar réad a scrÃobh sa sruth" + +#: builtin/unpack-objects.c +#, c-format +msgid "inflate returned (%d)" +msgstr "inflate ar ais (%d)" + +#: builtin/unpack-objects.c +msgid "invalid blob object from stream" +msgstr "réad blob neamhbhailà ón sruth" + +#: builtin/unpack-objects.c +msgid "Unpacking objects" +msgstr "Rudaà a dhÃphacáil" + +#: builtin/update-index.c +#, c-format +msgid "failed to create directory %s" +msgstr "theip ar eolaire %s a chruthú" + +#: builtin/update-index.c +#, c-format +msgid "failed to delete file %s" +msgstr "theip ar chomhad %s a scriosadh" + +#: builtin/update-index.c +#, c-format +msgid "failed to delete directory %s" +msgstr "theip ar eolaire %s a scriosadh" + +#: builtin/update-index.c +#, c-format +msgid "Testing mtime in '%s' " +msgstr "Tástáil mtime i '%s' " + +#: builtin/update-index.c +msgid "directory stat info does not change after adding a new file" +msgstr "nà athraÃonn eolas stat eolaire tar éis comhad nua a chur leis" + +#: builtin/update-index.c +msgid "directory stat info does not change after adding a new directory" +msgstr "nà athraÃonn eolas stat eolaire tar éis eolaire nua a chur leis" + +#: builtin/update-index.c +msgid "directory stat info changes after updating a file" +msgstr "athraÃonn faisnéis eolaire stat tar éis comhad a nuashonrú" + +#: builtin/update-index.c +msgid "directory stat info changes after adding a file inside subdirectory" +msgstr "" +"athraÃonn eolas stat eolaire tar éis comhad a chur taobh istigh den fho-" +"eolaire" + +#: builtin/update-index.c +msgid "directory stat info does not change after deleting a file" +msgstr "nà athraÃonn eolas stat eolaire tar éis comhad a scriosadh" + +#: builtin/update-index.c +msgid "directory stat info does not change after deleting a directory" +msgstr "nà athraÃonn eolas stat eolaire tar éis eolaire a scriosadh" + +#: builtin/update-index.c +msgid " OK" +msgstr " CEART GO LEOR" + +#: builtin/update-index.c +msgid "git update-index [<options>] [--] [<file>...]" +msgstr "<file>git update-index [<options>] [--] [...]" + +#: builtin/update-index.c +msgid "continue refresh even when index needs update" +msgstr "leanúint ar aghaidh ar aghaidh ag athnuachan fiú nu" + +#: builtin/update-index.c +msgid "refresh: ignore submodules" +msgstr "athnuachan: neamhaird a dhéanamh ar fho" + +#: builtin/update-index.c +msgid "do not ignore new files" +msgstr "ná déan neamhaird de chomhaid nua" + +#: builtin/update-index.c +msgid "let files replace directories and vice-versa" +msgstr "lig do chomhaid eolairà in ionad agus a mhalairt" + +#: builtin/update-index.c +msgid "notice files missing from worktree" +msgstr "fógra comhaid atá ar iarraidh ón gcrann oibre" + +#: builtin/update-index.c +msgid "refresh even if index contains unmerged entries" +msgstr "athnuachan fiú má tá iontrálacha neamh-iontrálacha" + +#: builtin/update-index.c +msgid "refresh stat information" +msgstr "faisnéis stáit a athnuachan" + +#: builtin/update-index.c +msgid "like --refresh, but ignore assume-unchanged setting" +msgstr "cosúil le --refresh, ach déan neamhaird de shuÃomh gan athrú" + +#: builtin/update-index.c +msgid "<mode>,<object>,<path>" +msgstr "<mode>,<object>, <path>" + +#: builtin/update-index.c +msgid "add the specified entry to the index" +msgstr "cuir an iontráil sonraithe leis an innéacs" + +#: builtin/update-index.c +msgid "mark files as \"not changing\"" +msgstr "comhad a mharcáil mar “gan athrúâ€" + +#: builtin/update-index.c +msgid "clear assumed-unchanged bit" +msgstr "giotán soiléir glactha gan athrú" + +#: builtin/update-index.c +msgid "mark files as \"index-only\"" +msgstr "comhad a mharcáil mar “innéacs amháinâ€" + +#: builtin/update-index.c +msgid "clear skip-worktree bit" +msgstr "giotán crainn oibre scipeála soiléir" + +#: builtin/update-index.c +msgid "do not touch index-only entries" +msgstr "ná déan teagmháil le iontrálacha innéacs amháin" + +#: builtin/update-index.c +msgid "add to index only; do not add content to object database" +msgstr "cuir le hinnéacs amháin; ná cuir ábhar le bunachar sonraà réada" + +#: builtin/update-index.c +msgid "remove named paths even if present in worktree" +msgstr "bain cosáin ainmnithe fiú má tá sé i gcrann oibre" + +#: builtin/update-index.c +msgid "with --stdin: input lines are terminated by null bytes" +msgstr "le --stdin: cuirtear deireadh le lÃnte ionchuir le bytes null" + +#: builtin/update-index.c +msgid "read list of paths to be updated from standard input" +msgstr "léigh liosta na gcosáin atá le nuashonrú ó ionchur caighdeánach" + +#: builtin/update-index.c +msgid "add entries from standard input to the index" +msgstr "cuir iontrálacha ón ionchur caighdeánach leis an innéacs" + +#: builtin/update-index.c +msgid "repopulate stages #2 and #3 for the listed paths" +msgstr "céimeanna #2 agus #3 a athdhÃonrú do na cosáin liostaithe" + +#: builtin/update-index.c +msgid "only update entries that differ from HEAD" +msgstr "ach iontrálacha a nuashonrú atá difriúil ó HEAD" + +#: builtin/update-index.c +msgid "ignore files missing from worktree" +msgstr "neamhaird a dhéanamh ar chomhaid atá in easnamh" + +#: builtin/update-index.c +msgid "report actions to standard output" +msgstr "gnÃomhartha a thuairisciú go dtÃ" + +#: builtin/update-index.c +msgid "(for porcelains) forget saved unresolved conflicts" +msgstr "(le haghaidh poircealláin) déan dearmad ar choimhlintà gan réiteach" + +#: builtin/update-index.c +msgid "write index in this format" +msgstr "scrÃobh innéacs san fhormáid seo" + +#: builtin/update-index.c +msgid "report on-disk index format version" +msgstr "leagan formáid innéacs ar dhiosca tuairisc" + +#: builtin/update-index.c +msgid "enable or disable split index" +msgstr "innéacs scoilte a chumasú nó a dh" + +#: builtin/update-index.c +msgid "enable/disable untracked cache" +msgstr "taisce neamhrianaithe a chumasú/a dhÃchumasú" + +#: builtin/update-index.c +msgid "test if the filesystem supports untracked cache" +msgstr "tástáil an dtacaÃonn an córas comhaid le taisce neamhrianaithe" + +#: builtin/update-index.c +msgid "enable untracked cache without testing the filesystem" +msgstr "taisce neamhrianaithe a chumasú gan an córas comhaid a thástáil" + +#: builtin/update-index.c +msgid "write out the index even if is not flagged as changed" +msgstr "" +"scrÃobh amach an t-innéacs fiú mura bhfuil sé brataithe mar a athraÃtear" + +#: builtin/update-index.c +msgid "enable or disable file system monitor" +msgstr "monatóireacht chórais chomhaid a chumasú" + +#: builtin/update-index.c +msgid "mark files as fsmonitor valid" +msgstr "comhad a mharcáil mar fsmonitor bailÃ" + +#: builtin/update-index.c +msgid "clear fsmonitor valid bit" +msgstr "giotán bailà fsmonitor soiléir" + +#: builtin/update-index.c +#, c-format +msgid "%d\n" +msgstr "%d\n" + +#: builtin/update-index.c +#, c-format +msgid "index-version: was %d, set to %d" +msgstr "leagan innéacs: bhà %d, socraithe go %d" + +#: builtin/update-index.c +msgid "" +"core.splitIndex is set to false; remove or change it, if you really want to " +"enable split index" +msgstr "" +"tá core.splitIndex socraithe go bréagach; bain nó athraigh é, más mian leat " +"innéacs scoilte a chumasú i ndáirÃre" + +#: builtin/update-index.c +msgid "" +"core.splitIndex is set to true; remove or change it, if you really want to " +"disable split index" +msgstr "" +"tá core.splitIndex socraithe go fÃor; bain nó athraigh é, más mian leat " +"innéacs scoilte a dhÃchumasú" + +#: builtin/update-index.c +msgid "" +"core.untrackedCache is set to true; remove or change it, if you really want " +"to disable the untracked cache" +msgstr "" +"tá core.untrackedCache go fÃor; bain nó athraigh é, más mian leat an taisce " +"neamhrianaithe a dhÃchumasú" + +#: builtin/update-index.c +msgid "Untracked cache disabled" +msgstr "Taisce neamhrianaithe mÃchumasaithe" + +#: builtin/update-index.c +msgid "" +"core.untrackedCache is set to false; remove or change it, if you really want " +"to enable the untracked cache" +msgstr "" +"tá core.untrackedCache socraithe go bréagach; bain nó athraigh é, más mian " +"leat an taisce neamhrianaithe a chumasú" + +#: builtin/update-index.c +#, c-format +msgid "Untracked cache enabled for '%s'" +msgstr "CumasaÃodh taisce neamhrianaithe do '%s'" + +#: builtin/update-index.c +msgid "core.fsmonitor is unset; set it if you really want to enable fsmonitor" +msgstr "" +"tá core.fsmonitor dÃshocraithe; socraigh é más mian leat fsmonitor a chumasú " +"i ndáirÃre" + +#: builtin/update-index.c +msgid "fsmonitor enabled" +msgstr "fsmonitor cumasaithe" + +#: builtin/update-index.c +msgid "" +"core.fsmonitor is set; remove it if you really want to disable fsmonitor" +msgstr "" +"tá core.fsmonitor socraithe; bain é más mian leat fsmonitor a dhÃchumasú i " +"ndáirÃre" + +#: builtin/update-index.c +msgid "fsmonitor disabled" +msgstr "fsmonitor mÃchumasaithe" + +#: builtin/update-ref.c +msgid "git update-ref [<options>] -d <refname> [<old-oid>]" +msgstr "<refname><old-oid>git update-ref [<options>] -d []" + +#: builtin/update-ref.c +msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" +msgstr "<refname><new-oid><old-oid>git update-ref [<options>] []" + +#: builtin/update-ref.c +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<options>] --stdin [-z] [--batch-updates]" + +#: builtin/update-ref.c +msgid "delete the reference" +msgstr "scrios an tagairt" + +#: builtin/update-ref.c +msgid "update <refname> not the one it points to" +msgstr "nuashon <refname>raigh nà an ceann a thugann sé in iúl" + +#: builtin/update-ref.c +msgid "stdin has NUL-terminated arguments" +msgstr "tá argóintà ag foirceannadh NUL ag stdin" + +#: builtin/update-ref.c +msgid "read updates from stdin" +msgstr "léigh nuashonruithe ó stdin" + +#: builtin/update-ref.c +msgid "batch reference updates" +msgstr "nuashonruithe tagairt baisc" + +#: builtin/update-server-info.c +msgid "update the info files from scratch" +msgstr "nuashonraigh na comhaid faisnéise ón tús" + +#: builtin/upload-pack.c +msgid "" +"git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n" +" [--advertise-refs] <directory>" +msgstr "" +"git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n" +" [--advertise-refs] <directory>" + +#: builtin/upload-pack.c t/helper/test-serve-v2.c +msgid "quit after a single request/response exchange" +msgstr "scor tar éis iarrata/malartú freagartha amháin" + +#: builtin/upload-pack.c +msgid "serve up the info/refs for git-http-backend" +msgstr "freastal suas ar na faisnéise/réimsà le haghaidh git-http-backend" + +#: builtin/upload-pack.c +msgid "do not try <directory>/.git/ if <directory> is no Git directory" +msgstr "" +"ná déan iarracht <directory>/.git/ mura bhfuil aon eolaire G <directory> it " +"ann" + +#: builtin/upload-pack.c +msgid "interrupt transfer after <n> seconds of inactivity" +msgstr "cur isteach ar aistriú tar éis so <n>icind neamhghnÃomhach" + +#: builtin/verify-commit.c +msgid "git verify-commit [-v | --verbose] [--raw] <commit>..." +msgstr "git verify-commit [-v | --verbose] [--raw] <commit>..." + +#: builtin/verify-commit.c +msgid "print commit contents" +msgstr "ábhair tiomanta priontála" + +#: builtin/verify-commit.c builtin/verify-tag.c +msgid "print raw gpg status output" +msgstr "aschur stádas amh-gpg a phriontáil" + +#: builtin/verify-pack.c +msgid "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..." +msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..." + +#: builtin/verify-pack.c +msgid "verbose" +msgstr "eolach" + +#: builtin/verify-pack.c +msgid "show statistics only" +msgstr "taispeáin staitisticà amháin" + +#: builtin/verify-tag.c +msgid "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..." +msgstr "<format><tag>git verify-tag [-v | --verbose] [--format =] [--raw]..." + +#: builtin/verify-tag.c +msgid "print tag contents" +msgstr "ábhar clib priontáil" + +#: builtin/worktree.c +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 <string>]]\n" +" [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]" + +#: builtin/worktree.c +msgid "git worktree list [-v | --porcelain [-z]]" +msgstr "liosta crann oibre git [-v | --poirceallán [-z]]" + +#: builtin/worktree.c +msgid "git worktree lock [--reason <string>] <worktree>" +msgstr "<string>glas crann oibre git [--reason] <worktree>" + +#: builtin/worktree.c +msgid "git worktree move <worktree> <new-path>" +msgstr "gluaiseacht sraith oibre git <worktree><new-path>" + +#: builtin/worktree.c +msgid "git worktree prune [-n] [-v] [--expire <expire>]" +msgstr "<expire>git worktree prun [-n] [-v] [--dul in éag]" + +#: builtin/worktree.c +msgid "git worktree remove [-f] <worktree>" +msgstr "git worktree a bhaint [-f] <worktree>" + +#: builtin/worktree.c +msgid "git worktree repair [<path>...]" +msgstr "deisiú crainn oibre git [<path>...]" + +#: builtin/worktree.c +msgid "git worktree unlock <worktree>" +msgstr "dÃghlasáil git worktree <worktree>" + +#: builtin/worktree.c +msgid "No possible source branch, inferring '--orphan'" +msgstr "NÃl aon bhrainse foinse féideartha, ag tabhairt faoi deara '--orphan'" + +#: builtin/worktree.c +#, 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 "" +"Má bhà i gceist agat crann oibre a chruthú ina bhfuil brainse nua gan " +"breith\n" +"(brainse gan aon ghealltanais) don stór seo, is féidir leat é sin a " +"dhéanamh\n" +"ag baint úsáide as an bhratach --dÃllÃ:\n" +"\n" +" git worktree add --orphan -b %s %s\n" + +#: builtin/worktree.c +#, c-format +msgid "" +"If you meant to create a worktree containing a new unborn branch\n" +"(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 "" +"Má bhà i gceist agat crann oibre a chruthú ina bhfuil brainse nua gan " +"breith\n" +"(brainse gan aon ghealltanais) don stór seo, is féidir leat é sin a " +"dhéanamh\n" +"ag baint úsáide as an --orphan flag:\n" +"\n" +" git worktree add --orphan %s\n" + +#: builtin/worktree.c +#, c-format +msgid "Removing %s/%s: %s" +msgstr "Ag baint %s/%s: %s" + +#: builtin/worktree.c +msgid "report pruned working trees" +msgstr "crainn oibre gearrtha a thuairisciú" + +#: builtin/worktree.c +msgid "expire working trees older than <time>" +msgstr "dul in éag crainn oibre nÃos sine ná <time>" + +#: builtin/worktree.c +#, c-format +msgid "'%s' already exists" +msgstr "Tá '%s' ann cheana féin" + +#: builtin/worktree.c +#, c-format +msgid "unusable worktree destination '%s'" +msgstr "ceann scrÃbe crainn oibre neamhúsáidte '%s'" + +#: builtin/worktree.c +#, 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 "" +"Is crann oibre atá ar iarraidh ach faoi ghlas é '%s';\n" +"bain úsáid as '%s -f 'chun athshealbhú, nó' dÃghlasáil 'agus' bearradh 'nó' " +"bhaint 'chun a ghlanadh" + +#: builtin/worktree.c +#, c-format +msgid "" +"'%s' is a missing but already registered worktree;\n" +"use '%s -f' to override, or 'prune' or 'remove' to clear" +msgstr "" +"Is crann oibre atá ar iarraidh ach cláraithe cheana féin é '%s';\n" +"bain úsáid as '%s -f' chun athshlánú, nó 'bearradh' nó 'bhaint' chun a " +"ghlanadh" + +#: builtin/worktree.c +#, c-format +msgid "failed to copy '%s' to '%s'; sparse-checkout may not work correctly" +msgstr "" +"theip ar '%s' a chóipeáil go '%s'; b'fhéidir nach n-oibreoidh an tseiceáil " +"neamhchoitianta i gceart" + +#: builtin/worktree.c +#, c-format +msgid "failed to copy worktree config from '%s' to '%s'" +msgstr "theip ar chumraÃocht crann oibre a chóipeáil ó '%s' go '%s'" + +#: builtin/worktree.c +#, c-format +msgid "failed to unset '%s' in '%s'" +msgstr "theip ar '%s' a dhÃshocrú i '%s'" + +#: builtin/worktree.c +#, c-format +msgid "could not create directory of '%s'" +msgstr "nà raibh in ann eolaire de '%s' a chruthú" + +#: builtin/worktree.c +msgid "initializing" +msgstr "a thionscnamh" + +#: builtin/worktree.c +#, c-format +msgid "could not find created worktree '%s'" +msgstr "nà raibh an crann oibre cruthaithe '%s' a aimsiú" + +#: builtin/worktree.c +#, c-format +msgid "Preparing worktree (new branch '%s')" +msgstr "Crann oibre a ullmhú (brainse nua '%s')" + +#: builtin/worktree.c +#, c-format +msgid "Preparing worktree (resetting branch '%s'; was at %s)" +msgstr "Ullmhú crann oibre (athshocrú brainse '%s'; bhà ag %s)" + +#: builtin/worktree.c +#, c-format +msgid "Preparing worktree (checking out '%s')" +msgstr "Crann oibre a ullmhú (seiceáil '%s')" + +#: builtin/worktree.c +#, c-format +msgid "unreachable: invalid reference: %s" +msgstr "unrochtana: tagairt neamhbhailÃ: %s" + +#: builtin/worktree.c +#, c-format +msgid "Preparing worktree (detached HEAD %s)" +msgstr "Crann oibre a ullmhú (CEAD scoite %s)" + +#: builtin/worktree.c +#, c-format +msgid "" +"HEAD points to an invalid (or orphaned) reference.\n" +"HEAD path: '%s'\n" +"HEAD contents: '%s'" +msgstr "" +"Tugann HEAD in iúl do thagairt neamhbhailà (nó dÃlleachta).\n" +"Conair CEAD: '%s'\n" +"Ãbhar CEAD: '%s'" + +#: builtin/worktree.c +msgid "" +"No local or remote refs exist despite at least one remote\n" +"present, stopping; use 'add -f' to override or fetch a remote first" +msgstr "" +"NÃl aon réimsà áitiúla ná iargúlta ann in ainneoin cianda amháin ar a " +"laghad\n" +"láthair, ag stopadh; bain úsáid as 'add -f' chun iargúlta a shárú nó a fháil " +"ar dtús" + +#: builtin/worktree.c +msgid "checkout <branch> even if already checked out in other worktree" +msgstr "" +"seiceáil <branch>fiú má tá sé seiceáilte cheana féin i gcrann oibre eile" + +#: builtin/worktree.c +msgid "create a new branch" +msgstr "brainse nua a chruthú" + +#: builtin/worktree.c +msgid "create or reset a branch" +msgstr "brainse a chruthú nó a athshocrú" + +#: builtin/worktree.c +msgid "create unborn branch" +msgstr "cruthú brainse gan breith" + +#: builtin/worktree.c +msgid "populate the new working tree" +msgstr "an crann oibre nua a dhaonrú" + +#: builtin/worktree.c +msgid "keep the new working tree locked" +msgstr "coinnigh an crann oibre nua faoi ghlas" + +#: builtin/worktree.c +msgid "reason for locking" +msgstr "cúis le glasáil" + +#: builtin/worktree.c +msgid "set up tracking mode (see git-branch(1))" +msgstr "modh rianaithe a bhunú (féach git-branch (1))" + +#: builtin/worktree.c +msgid "try to match the new branch name with a remote-tracking branch" +msgstr "" +"déan iarracht ainm nua na brainse a mheaitseáil le brainse cianrianaithe" + +#: builtin/worktree.c +msgid "use relative paths for worktrees" +msgstr "úsáid cosáin choibhneasta do chrainn oibre" + +#: builtin/worktree.c diff.c parse-options.c +#, c-format +msgid "options '%s', '%s', and '%s' cannot be used together" +msgstr "nà féidir roghanna '%s', '%s', agus '%s' a úsáid le chéile" + +#: builtin/worktree.c +#, c-format +msgid "option '%s' and commit-ish cannot be used together" +msgstr "nà féidir rogha '%s' agus comm-ish a úsáid le chéile" + +#: builtin/worktree.c +msgid "added with --lock" +msgstr "cuireadh leis le --lock" + +#: builtin/worktree.c +msgid "--[no-]track can only be used if a new branch is created" +msgstr "Nà féidir --[no-]rian a úsáid ach amháin má chruthaÃtear brainse nua" + +#: builtin/worktree.c +msgid "show extended annotations and reasons, if available" +msgstr "anótaà agus cúiseanna leathnaithe a thaispeáint, má tá sé ar fáil" + +#: builtin/worktree.c +msgid "add 'prunable' annotation to worktrees older than <time>" +msgstr "cuir anótáil 'prunable' le crainn oibre nÃos sine ná <time>" + +#: builtin/worktree.c +msgid "terminate records with a NUL character" +msgstr "deireadh a chur le taifid le carachtar NUL" + +#: builtin/worktree.c +#, c-format +msgid "'%s' is not a working tree" +msgstr "Nà crann oibre é '%s'" + +#: builtin/worktree.c +msgid "The main working tree cannot be locked or unlocked" +msgstr "Nà féidir an prÃomhchrann oibre a ghlasáil nó a dhÃghlasáil" + +#: builtin/worktree.c +#, c-format +msgid "'%s' is already locked, reason: %s" +msgstr "Tá '%s' faoi ghlas cheana féin, cúis: %s" + +#: builtin/worktree.c +#, c-format +msgid "'%s' is already locked" +msgstr "Tá '%s' faoi ghlas cheana féin" + +#: builtin/worktree.c +#, c-format +msgid "'%s' is not locked" +msgstr "NÃl '%s' faoi ghlas" + +#: builtin/worktree.c +msgid "working trees containing submodules cannot be moved or removed" +msgstr "nà féidir crainn oibre ina bhfuil fo-mhodúil a bhogadh ná a bhaint" + +#: builtin/worktree.c +msgid "force move even if worktree is dirty or locked" +msgstr "bogadh fórsa fiú má tá crann oibre salach nó faoi ghlas" + +#: builtin/worktree.c +#, c-format +msgid "'%s' is a main working tree" +msgstr "Is prÃomhchrann oibre é '%s'" + +#: builtin/worktree.c +#, c-format +msgid "could not figure out destination name from '%s'" +msgstr "nà fhéadfaà ainm ceann scrÃbe a fháil amach ó '%s'" + +#: builtin/worktree.c +#, c-format +msgid "" +"cannot move a locked working tree, lock reason: %s\n" +"use 'move -f -f' to override or unlock first" +msgstr "" +"nà féidir crann oibre faoi ghlas a bhogadh, cúis ghlasála: %s\n" +"bain úsáid as 'move -f -f' chun athshárú nó a dhÃghlasáil ar dtús" + +#: builtin/worktree.c +msgid "" +"cannot move a locked working tree;\n" +"use 'move -f -f' to override or unlock first" +msgstr "" +"nà féidir le crann oibre faoi ghlas a bhogadh;\n" +"bain úsáid as 'move -f -f' chun athshárú nó a dhÃghlasáil ar dtús" + +#: builtin/worktree.c +#, c-format +msgid "validation failed, cannot move working tree: %s" +msgstr "theip ar bhailÃochtú, nà féidir crann oibre a bhogadh: %s" + +#: builtin/worktree.c +#, c-format +msgid "failed to move '%s' to '%s'" +msgstr "theip ar '%s' a bhogadh go '%s'" + +#: builtin/worktree.c +#, c-format +msgid "failed to run 'git status' on '%s'" +msgstr "theip ar 'git status' a reáchtáil ar '%s'" + +#: builtin/worktree.c +#, c-format +msgid "'%s' contains modified or untracked files, use --force to delete it" +msgstr "" +"Tá comhaid modhnaithe nó neamhrianaithe i '%s', bain úsáid as --force chun é " +"a scriosadh" + +#: builtin/worktree.c +#, c-format +msgid "failed to run 'git status' on '%s', code %d" +msgstr "theip ar 'git status' a reáchtáil ar '%s', cód %d" + +#: builtin/worktree.c +msgid "force removal even if worktree is dirty or locked" +msgstr "bhaint fórsa fiú má tá crann oibre salach nó faoi ghlas" + +#: builtin/worktree.c +#, c-format +msgid "" +"cannot remove a locked working tree, lock reason: %s\n" +"use 'remove -f -f' to override or unlock first" +msgstr "" +"nà féidir crann oibre faoi ghlas a bhaint, cúis ghlasála: %s\n" +"bain úsáid as 'remove -f -f' chun athshárú nó a dhÃghlasáil ar dtús" + +#: builtin/worktree.c +msgid "" +"cannot remove a locked working tree;\n" +"use 'remove -f -f' to override or unlock first" +msgstr "" +"nà féidir crann oibre faoi ghlas a bhaint;\n" +"bain úsáid as 'remove -f -f' chun athshárú nó a dhÃghlasáil ar dtús" + +#: builtin/worktree.c +#, c-format +msgid "validation failed, cannot remove working tree: %s" +msgstr "theip ar bhailÃochtú, nà féidir crann oibre a bhaint: %s" + +#: builtin/worktree.c +#, c-format +msgid "repair: %s: %s" +msgstr "deisiú: %s: %s" + +#: builtin/worktree.c +#, c-format +msgid "error: %s: %s" +msgstr "earráid: %s: %s" + +#: builtin/write-tree.c +msgid "git write-tree [--missing-ok] [--prefix=<prefix>/]" +msgstr "git write-tree [--missing-ok] [--prefix=<prefix>/]" + +#: builtin/write-tree.c +msgid "<prefix>/" +msgstr "<prefix>/" + +#: builtin/write-tree.c +msgid "write tree object for a subdirectory <prefix>" +msgstr "scrÃobh réad crann le haghaidh fo-eolaire <prefix>" + +#: builtin/write-tree.c +msgid "only useful for debugging" +msgstr "ach úsáideach le haghaidh dÃfhabhtú" + +#: bulk-checkin.c +msgid "core.fsyncMethod = batch is unsupported on this platform" +msgstr "core.fsyncMethod = nà thacaÃtear leis an bhaisc ar an ardán seo" + +#: bundle-uri.c +#, c-format +msgid "could not parse bundle list key %s with value '%s'" +msgstr "nà fhéadfaà eochair liosta beartán %s a pháirseáil le luach '%s'" + +#: bundle-uri.c +#, c-format +msgid "bundle list at '%s' has no mode" +msgstr "nÃl aon mhodh ag liosta beartán ag '%s'" + +#: bundle-uri.c +msgid "failed to create temporary file" +msgstr "theip ar chomhad sealadach a chruthú" + +#: bundle-uri.c +msgid "insufficient capabilities" +msgstr "cumais neamhleor" + +#: bundle-uri.c +#, c-format +msgid "file downloaded from '%s' is not a bundle" +msgstr "nà beartán é an comhad a Ãoslódáladh ó '%s'" + +#: bundle-uri.c +msgid "failed to store maximum creation token" +msgstr "theip ar an comhartha cruthaithe uasta a stórá" + +#: bundle-uri.c +#, c-format +msgid "unrecognized bundle mode from URI '%s'" +msgstr "modh beartán neamhaithnithe ó URI '%s'" + +#: bundle-uri.c +#, c-format +msgid "exceeded bundle URI recursion limit (%d)" +msgstr "sháraigh teorainn athshlánaithe URI beartán (%d)" + +#: bundle-uri.c +#, c-format +msgid "failed to download bundle from URI '%s'" +msgstr "theip ar an mbeartán a Ãoslódáil ó URI '%s'" + +#: bundle-uri.c +#, c-format +msgid "file at URI '%s' is not a bundle or bundle list" +msgstr "comhad ag URI nà beacán nó liosta beartán é '%s'" + +#: bundle-uri.c +#, c-format +msgid "bundle-uri: unexpected argument: '%s'" +msgstr "bundle-uri: argóint gan choinne: '%s'" + +#: bundle-uri.c +msgid "bundle-uri: expected flush after arguments" +msgstr "bundle-uri: súil le sruth tar éis argóintÃ" + +#: bundle-uri.c +msgid "bundle-uri: got an empty line" +msgstr "bundle-uri: got an lÃne folamh" + +#: bundle-uri.c +msgid "bundle-uri: line is not of the form 'key=value'" +msgstr "bundle-uri: nÃl an lÃne den fhoirm 'key=value'" + +#: bundle-uri.c +msgid "bundle-uri: line has empty key or value" +msgstr "bundle-uri: tá eochair nó luach folamh ag lÃne" + +#: bundle.c +#, c-format +msgid "unrecognized bundle hash algorithm: %s" +msgstr "algartam hash beartán gan aithint: %s" + +#: bundle.c +#, c-format +msgid "unknown capability '%s'" +msgstr "cumas anaithnid '%s'" + +#: bundle.c +#, c-format +msgid "'%s' does not look like a v2 or v3 bundle file" +msgstr "NÃl cuma '%s' cosúil le comhad beartán v2 nó v3" + +#: bundle.c +#, c-format +msgid "unrecognized header: %s%s (%d)" +msgstr "ceanntásc gan aithint: %s%s (%d)" + +#: bundle.c +msgid "Repository lacks these prerequisite commits:" +msgstr "NÃl na tiomantas réamhriachtanais seo ag an stór:" + +#: bundle.c +msgid "" +"some prerequisite commits exist in the object store, but are not connected " +"to the repository's history" +msgstr "" +"tá roinnt gealltanais réamhriachtanais ann sa stór réada, ach nÃl siad " +"ceangailte le stair an stór" + +#: bundle.c +#, c-format +msgid "The bundle contains this ref:" +msgid_plural "The bundle contains these %<PRIuMAX> refs:" +msgstr[0] "Tá an tagairt seo sa phacáiste:" +msgstr[1] "Tá na tagairtà %<PRIuMAX> seo sa phacáiste:" +msgstr[2] "Tá na tagairtà %<PRIuMAX> seo sa phacáiste:" + +#: bundle.c +msgid "The bundle records a complete history." +msgstr "Taifeadann an beartán stair iomlán." + +#: bundle.c +#, c-format +msgid "The bundle requires this ref:" +msgid_plural "The bundle requires these %<PRIuMAX> refs:" +msgstr[0] "ÉilÃonn an pacáiste seo an tagairt:" +msgstr[1] "ÉilÃonn an pacáiste seo na tagairtà %<PRIuMAX> seo:" +msgstr[2] "ÉilÃonn an pacáiste seo na tagairtà %<PRIuMAX> seo:" + +#: bundle.c +#, c-format +msgid "The bundle uses this hash algorithm: %s" +msgstr "Úsáideann an beartán an algartam hash seo: %s" + +#: bundle.c +#, c-format +msgid "The bundle uses this filter: %s" +msgstr "Úsáideann an beartán an scagaire seo: %s" + +#: bundle.c +msgid "unable to dup bundle descriptor" +msgstr "nach féidir tuairiscà a chur ar bhearnadh" + +#: bundle.c +msgid "Could not spawn pack-objects" +msgstr "Nà fhéadfaà rudaà pacáiste a shannadh" + +#: bundle.c +msgid "pack-objects died" +msgstr "rudaà pacáiste fuair bás" + +#: bundle.c +#, c-format +msgid "ref '%s' is excluded by the rev-list options" +msgstr "tá ref '%s' eisiata ag na roghanna rev-list" + +#: bundle.c +#, c-format +msgid "unsupported bundle version %d" +msgstr "leagan beartán gan tacaÃocht %d" + +#: bundle.c +#, c-format +msgid "cannot write bundle version %d with algorithm %s" +msgstr "nà féidir leagan beartán %d a scrÃobh le algartam %s" + +#: bundle.c +msgid "Refusing to create empty bundle." +msgstr "Diúltú beartán folamh a chruthú." + +#: bundle.c +#, c-format +msgid "cannot create '%s'" +msgstr "nà féidir '%s' a chruthú" + +#: bundle.c +msgid "index-pack died" +msgstr "fuair an pacáiste innéacs" + +#: cache-tree.c +#, c-format +msgid "directory '%s' is present in index, but not sparse" +msgstr "tá eolaire '%s' i láthair in innéacs, ach nÃl sé neamhchoitianta" + +#: cache-tree.c unpack-trees.c +msgid "corrupted cache-tree has entries not present in index" +msgstr "" +"tá iontrálacha nach bhfuil i láthair san innéacs ag crann cache-crainn " +"truaillte" + +#: cache-tree.c +#, c-format +msgid "%s with flags 0x%x should not be in cache-tree" +msgstr "NÃor chóir go mbeadh %s le bratacha 0x%x i gcrann cache-tree" + +#: cache-tree.c +#, c-format +msgid "bad subtree '%.*s'" +msgstr "droch-fho-chrann '%.*s'" + +#: cache-tree.c +#, c-format +msgid "cache-tree for path %.*s does not match. Expected %s got %s" +msgstr "" +"nà hionann crann-taisce don chonair %.*s. BhÃothas ag súil le %s, ach fuair " +"%s" + +#: chunk-format.c +msgid "terminating chunk id appears earlier than expected" +msgstr "is cosúil le feiceáil id cúince a fhoirceannadh nÃos luaithe" + +#: chunk-format.c +#, c-format +msgid "chunk id %<PRIx32> not %d-byte aligned" +msgstr "id chosc% <PRIx32>nach bhfuil %d-byte ailÃnithe" + +#: chunk-format.c +#, c-format +msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>" +msgstr "fritháireamh pÃosa mÃchuà (Ã)% <PRIx64>agus% <PRIx64>" + +#: chunk-format.c +#, c-format +msgid "duplicate chunk ID %<PRIx32> found" +msgstr "aimsÃodh ID smután dúblach %<PRIx32>" + +#: chunk-format.c +#, c-format +msgid "final chunk has non-zero id %<PRIx32>" +msgstr "tá id neamh-nialasach ag an gcuid deiridh% <PRIx32>" + +#: chunk-format.c +msgid "invalid hash version" +msgstr "leagan hash neamhbhailÃ" + +#: color.c +#, c-format +msgid "invalid color value: %.*s" +msgstr "luach dath neamhbhailÃ: %.*s" + +#: command-list.h +msgid "Add file contents to the index" +msgstr "Cuir ábhar an chomhaid leis an innéacs" + +#: command-list.h +msgid "Apply a series of patches from a mailbox" +msgstr "Cuir sraith paistà i bhfeidhm ó bhosca poist" + +#: command-list.h +msgid "Annotate file lines with commit information" +msgstr "LÃnte comhaid a anótáil le faisnéis tiomanta" + +#: command-list.h +msgid "Apply a patch to files and/or to the index" +msgstr "Cuir paiste i bhfeidhm ar chomhaid agus/nó ar an innéacs" + +#: command-list.h +msgid "Import a GNU Arch repository into Git" +msgstr "Iompórtáil stór GNU Arch isteach i Git" + +#: command-list.h +msgid "Create an archive of files from a named tree" +msgstr "Cruthaigh cartlann comhaid ó chrann ainmnithe" + +#: command-list.h +msgid "Download missing objects in a partial clone" +msgstr "Ãoslódáil rudaà atá in easnamh i gclón pá" + +#: command-list.h +msgid "Use binary search to find the commit that introduced a bug" +msgstr "" +"Úsáid cuardach dénártha chun an gealltanas a thug isteach fabht a fháil" + +#: command-list.h +msgid "Show what revision and author last modified each line of a file" +msgstr "" +"Taispeáin an t-athbhreithniú agus an t-údar a mhodhnaigh gach lÃne de chomhad" + +#: command-list.h +msgid "List, create, or delete branches" +msgstr "Brainsà a liostáil, a chruthú nó a scriosadh" + +#: command-list.h +msgid "Collect information for user to file a bug report" +msgstr "Bailigh faisnéis don úsáideoir chun tuarascáil fabht a chomhdú" + +#: command-list.h +msgid "Move objects and refs by archive" +msgstr "Bogadh rudaà agus scrÃbhinnà de réir cartlann" + +#: command-list.h +msgid "Provide contents or details of repository objects" +msgstr "Ãbhar nó sonraà rudaà stórais a sholáthar" + +#: command-list.h +msgid "Display gitattributes information" +msgstr "Taispeáin faisnéis gitattributs" + +#: command-list.h +msgid "Debug gitignore / exclude files" +msgstr "DÃfhabhtú gitignore/eisiamh comhaid" + +#: command-list.h +msgid "Show canonical names and email addresses of contacts" +msgstr "Taispeáin ainmneacha canónach agus seoltaà rÃomhphoist teagmhál" + +#: command-list.h +msgid "Ensures that a reference name is well formed" +msgstr "CinntÃonn sé go bhfuil ainm tagartha foirmithe go maith" + +#: command-list.h +msgid "Switch branches or restore working tree files" +msgstr "Athraigh brainsà nó cuir comhaid crainn oibre ar ais" + +#: command-list.h +msgid "Copy files from the index to the working tree" +msgstr "Cóipeáil comhaid ón innéacs go dtà an crann oibre" + +#: command-list.h +msgid "Find commits yet to be applied to upstream" +msgstr "Faigh gealltanais nach ndéanfar cur i bhfeidhm fós ar an sruth" + +#: command-list.h +msgid "Apply the changes introduced by some existing commits" +msgstr "" +"Cuir isteach na hathruithe a thug isteach ag roinnt gealltanais atá ann" + +#: command-list.h +msgid "Graphical alternative to git-commit" +msgstr "Rogha eile grafach seachas git-commit" + +#: command-list.h +msgid "Remove untracked files from the working tree" +msgstr "Bain comhaid neamhrianaithe ón gcrann oibre" + +#: command-list.h +msgid "Clone a repository into a new directory" +msgstr "Clóin stór isteach i eolaire nua" + +#: command-list.h +msgid "Display data in columns" +msgstr "Taispeáin sonraà i gcolúin" + +#: command-list.h +msgid "Record changes to the repository" +msgstr "Taifeadadh athruithe ar an stór" + +#: command-list.h +msgid "Write and verify Git commit-graph files" +msgstr "ScrÃobh agus fÃoraigh comhaid choimisi-graf Git" + +#: command-list.h +msgid "Create a new commit object" +msgstr "Cruthaigh réad tiomanta nua" + +#: command-list.h +msgid "Get and set repository or global options" +msgstr "Faigh agus socraigh stór nó roghanna domhanda" + +#: command-list.h +msgid "Count unpacked number of objects and their disk consumption" +msgstr "LÃon rudaà neamhphacáilte a chomhaireamh agus a dtomhaltas" + +#: command-list.h +msgid "Retrieve and store user credentials" +msgstr "Dintiúir úsáideora a aisghabháil agus" + +#: command-list.h +msgid "Helper to temporarily store passwords in memory" +msgstr "Cúntóir chun pasfhocail a stóráil i gcuimhne" + +#: command-list.h +msgid "Helper to store credentials on disk" +msgstr "Cúntóir chun dintiúir a stóráil ar dhios" + +#: command-list.h +msgid "Export a single commit to a CVS checkout" +msgstr "Easpórtáil tiomantas amháin chuig seiceáil CVS" + +#: command-list.h +msgid "Salvage your data out of another SCM people love to hate" +msgstr "" +"Sábháil do chuid sonraà as SCM eile is breá le daoine fuath a thabhairt" + +#: command-list.h +msgid "A CVS server emulator for Git" +msgstr "Aithritheoir freastalaà CVS do Git" + +#: command-list.h +msgid "A really simple server for Git repositories" +msgstr "Freastalaà an-simplà do stórais Git" + +#: command-list.h +msgid "Give an object a human readable name based on an available ref" +msgstr "Tabhair ainm inléite daonna do réad bunaithe ar thagartha atá ar fáil" + +#: command-list.h +msgid "Generate a zip archive of diagnostic information" +msgstr "Cruthaigh cartlann zip faisnéise diagnóiseach" + +#: command-list.h +msgid "Show changes between commits, commit and working tree, etc" +msgstr "Taispeáin athruithe idir gealltanais, tiomantas agus crann oibre, srl" + +#: command-list.h +msgid "Compares files in the working tree and the index" +msgstr "Déanann comparáid idir comhaid sa chrann oibre agus san innéacs" + +#: command-list.h +msgid "Compare a tree to the working tree or index" +msgstr "Déan comparáid idir crann leis an gcrann oibre nó leis an innéacs" + +#: command-list.h +msgid "Compare the content and mode of provided blob pairs" +msgstr "Déan comparáid idir ábhar agus modh na bpéirà blob atá curtha ar fáil" + +#: command-list.h +msgid "Compares the content and mode of blobs found via two tree objects" +msgstr "" +"Déanann comparáid idir ábhar agus modh blobs a fhaightear trà dhá rud crann" + +#: command-list.h +msgid "Show changes using common diff tools" +msgstr "Taispeáin athruithe ag úsáid uirlisà coitianta diff" + +#: command-list.h +msgid "Git data exporter" +msgstr "Easpórtóir sonraà Git" + +#: command-list.h +msgid "Backend for fast Git data importers" +msgstr "Backend d'allmhaireoirà sonraà tapa Git" + +#: command-list.h +msgid "Download objects and refs from another repository" +msgstr "Ãoslódáil rudaà agus réimsà ó stór eile" + +#: command-list.h +msgid "Receive missing objects from another repository" +msgstr "Faigh rudaà atá in easnamh ó stór eile" + +#: command-list.h +msgid "Rewrite branches" +msgstr "Brainsà a athscrÃobh" + +#: command-list.h +msgid "Produce a merge commit message" +msgstr "Teachtaireacht tiomanta cumaisc a chur" + +#: command-list.h +msgid "Output information on each ref" +msgstr "Eolas aschuir ar gach tagairt" + +#: command-list.h +msgid "Run a Git command on a list of repositories" +msgstr "Rith ordú Git ar liosta stórais" + +#: command-list.h +msgid "Prepare patches for e-mail submission" +msgstr "Ullmhaigh paistà le haghaidh aighneachta" + +#: command-list.h +msgid "Verifies the connectivity and validity of the objects in the database" +msgstr "FÃoraÃonn sé nascacht agus bailÃocht na rudaà sa bhunachar sonraÃ" + +#: command-list.h +msgid "Cleanup unnecessary files and optimize the local repository" +msgstr "Glan comhaid gan ghá agus an stór áitiúil a bharrfheabhsú" + +#: command-list.h +msgid "Extract commit ID from an archive created using git-archive" +msgstr "" +"Bain ID tiomanta as cartlann a cruthaÃodh ag baint úsáide as git-archive" + +#: command-list.h +msgid "Print lines matching a pattern" +msgstr "LÃnte priontála a mheaitseálann" + +#: command-list.h +msgid "A portable graphical interface to Git" +msgstr "Comhéadan grafach iniompartha chuig Git" + +#: command-list.h +msgid "Compute object ID and optionally create an object from a file" +msgstr "RÃomh ID réad agus cruthaigh réad ó chomhad go roghnach" + +#: command-list.h +msgid "Display help information about Git" +msgstr "Taispeáin faisnéis chabhrach faoi Git" + +#: command-list.h +msgid "Run git hooks" +msgstr "Rith crúcaà git" + +#: command-list.h +msgid "Server side implementation of Git over HTTP" +msgstr "Cur i bhfeidhm taobh freastalaà Git thar HTTP" + +#: command-list.h +msgid "Download from a remote Git repository via HTTP" +msgstr "Ãoslódáil ó stór iargúlta Git trà HTTP" + +#: command-list.h +msgid "Push objects over HTTP/DAV to another repository" +msgstr "Brúigh rudaà thar HTTP/DAV chuig stór eile" + +#: command-list.h +msgid "Send a collection of patches from stdin to an IMAP folder" +msgstr "Seol bailiúchán paistà ó stdin chuig fillteán IMAP" + +#: command-list.h +msgid "Build pack index file for an existing packed archive" +msgstr "Tóg comhad innéacs pacáiste do chartlann pacáilte atá ann" + +#: command-list.h +msgid "Create an empty Git repository or reinitialize an existing one" +msgstr "Cruthaigh stór Git folamh nó déan ceann atá ann cheana a athionsú" + +#: command-list.h +msgid "Instantly browse your working repository in gitweb" +msgstr "Brabhsáil láithreach do stór oibre i gitweb" + +#: command-list.h +msgid "Add or parse structured information in commit messages" +msgstr "Cuir nó déan faisnéis struchtúrtha i dteachtaireachtaà tiomanta" + +#: command-list.h +msgid "Show commit logs" +msgstr "Taispeáin logaà tiomanta" + +#: command-list.h +msgid "Show information about files in the index and the working tree" +msgstr "Taispeáin faisnéis faoi chomhaid san innéacs agus sa chrann oibre" + +#: command-list.h +msgid "List references in a remote repository" +msgstr "Liostaigh tagairtà i stór iargúlta" + +#: command-list.h +msgid "List the contents of a tree object" +msgstr "Liostaigh ábhar réad crann" + +#: command-list.h +msgid "Extracts patch and authorship from a single e-mail message" +msgstr "Baineann paiste agus údaracht as teachtaireacht rÃomhphoist amháin" + +#: command-list.h +msgid "Simple UNIX mbox splitter program" +msgstr "Clár scoilteora mbox UNIX simplÃ" + +#: command-list.h +msgid "Run tasks to optimize Git repository data" +msgstr "Rith tascanna chun sonraà stór Git a bharrfheabhsú" + +#: command-list.h +msgid "Join two or more development histories together" +msgstr "Bà le dhá stair forbartha nó nÃos mó le chéile" + +#: command-list.h +msgid "Find as good common ancestors as possible for a merge" +msgstr "Faigh sinsear choiteann chomh maith agus is féidir le cumasc" + +#: command-list.h +msgid "Run a three-way file merge" +msgstr "Rith cumasc comhad trà bhealach" + +#: command-list.h +msgid "Run a merge for files needing merging" +msgstr "Reáchtáil cumaisc le haghaidh comhaid a bhfuil gá le cumasc orthu" + +#: command-list.h +msgid "The standard helper program to use with git-merge-index" +msgstr "An clár cúntóra caighdeánach le húsáid le git-merge-index" + +#: command-list.h +msgid "Perform merge without touching index or working tree" +msgstr "Déan cumasc gan teagmháil a dhéanamh le hInnéacs nó crann" + +#: command-list.h +msgid "Run merge conflict resolution tools to resolve merge conflicts" +msgstr "Rith uirlisà réitigh coinbhleachtaà cumaisc chun coinbhleachtaÃ" + +#: command-list.h +msgid "Creates a tag object with extra validation" +msgstr "CruthaÃonn sé réad clibeanna le bailÃochtú breise" + +#: command-list.h +msgid "Build a tree-object from ls-tree formatted text" +msgstr "Tóg réad crann ó théacs formáidithe ls-tree" + +#: command-list.h +msgid "Write and verify multi-pack-indexes" +msgstr "Innéacsanna il-phacáiste a scrÃobh agus a fhÃorú" + +#: command-list.h +msgid "Move or rename a file, a directory, or a symlink" +msgstr "Bogadh nó athainmnigh comhad, eolaire, nó nasc comhsheasmhach" + +#: command-list.h +msgid "Find symbolic names for given revs" +msgstr "Faigh ainmneacha siombalacha do thiomhartha tugtha" + +#: command-list.h +msgid "Add or inspect object notes" +msgstr "Cuir nó iniúchadh nótaà réad" + +#: command-list.h +msgid "Import from and submit to Perforce repositories" +msgstr "Iompórtáil ó stórais Perforce agus cuir isteach chuig" + +#: command-list.h +msgid "Create a packed archive of objects" +msgstr "Cruthaigh cartlann pacáilte rudaÃ" + +#: command-list.h +msgid "Find redundant pack files" +msgstr "Faigh comhaid pacáiste iomarcacha" + +#: command-list.h +msgid "Pack heads and tags for efficient repository access" +msgstr "Ceannanna agus clibeanna pacála le haghaidh rochtain éifeachtach" + +#: command-list.h +msgid "Compute unique ID for a patch" +msgstr "RÃomh ID uathúil le haghaidh paiste" + +#: command-list.h +msgid "Prune all unreachable objects from the object database" +msgstr "" +"Déan gach rud nach féidir inrochtana a ghearradh ón mbunachar sonraà réad" + +#: command-list.h +msgid "Remove extra objects that are already in pack files" +msgstr "Bain rudaà breise atá i gcomhaid pacáiste cheana féin" + +#: command-list.h +msgid "Fetch from and integrate with another repository or a local branch" +msgstr "Faigh ó stór eile nó brainse áitiúil agus comhtháthú leis" + +#: command-list.h +msgid "Update remote refs along with associated objects" +msgstr "Nuashonraigh iargúlta mar aon le rudaà gaolmhara" + +#: command-list.h +msgid "Applies a quilt patchset onto the current branch" +msgstr "Cuireann paistset cuilte i bhfeidhm ar an mbrainse reatha" + +#: command-list.h +msgid "Compare two commit ranges (e.g. two versions of a branch)" +msgstr "Déan comparáid idir dhá raon tiomanta (e.g. dhá leagan de bhrainse)" + +#: command-list.h +msgid "Reads tree information into the index" +msgstr "Léann faisnéis crainn isteach san innéacs" + +#: command-list.h +msgid "Reapply commits on top of another base tip" +msgstr "Déan gealltanna a athchur i bhfeidhm ar bharr leid bonn eile" + +#: command-list.h +msgid "Receive what is pushed into the repository" +msgstr "Faigh an méid a bhrúitear isteach sa stór" + +#: command-list.h +msgid "Manage reflog information" +msgstr "Bainistigh faisnéis reflog" + +#: command-list.h +msgid "Low-level access to refs" +msgstr "Rochtain ar leibhéal Ãseal ar réimsÃ" + +#: command-list.h +msgid "Manage set of tracked repositories" +msgstr "Bainistigh sraith stórais rianaithe" + +#: command-list.h +msgid "Pack unpacked objects in a repository" +msgstr "Pacáil rudaà neamhphacáilte i stóras" + +#: command-list.h +msgid "Create, list, delete refs to replace objects" +msgstr "Cruthaigh, liostáil, scrios scrÃobh chun rudaà a athsholáthar" + +#: command-list.h +msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too" +msgstr "" +"TURGNAMHACH: Tiomann athsheoladh ar bhonn nua, oibrÃonn sé le repos lom " +"freisin" + +#: command-list.h +msgid "Generates a summary of pending changes" +msgstr "Gineann achoimre ar athruithe ar feitheamh" + +#: command-list.h +msgid "Reuse recorded resolution of conflicted merges" +msgstr "Réiteach taifeadta ar chumaisc coinbhleachta a athúsáid" + +#: command-list.h +msgid "Reset current HEAD to the specified state" +msgstr "Athshocraigh HEAD reatha go dtà an stát sonraithe" + +#: command-list.h +msgid "Restore working tree files" +msgstr "Athchóirigh comhaid crann oibre" + +#: command-list.h +msgid "Lists commit objects in reverse chronological order" +msgstr "Tiomann liostaà rudaà in ord croineolaÃoch droim" + +#: command-list.h +msgid "Pick out and massage parameters" +msgstr "Paraiméadair a roghnú agus massage" + +#: command-list.h +msgid "Revert some existing commits" +msgstr "Cuir roinnt gealltanais atá ann cheana ar ais" + +#: command-list.h +msgid "Remove files from the working tree and from the index" +msgstr "Bain comhaid ón gcrann oibre agus ón innéacs" + +#: command-list.h +msgid "Send a collection of patches as emails" +msgstr "Seol bailiúchán paistà mar rÃomhphoist" + +#: command-list.h +msgid "Push objects over Git protocol to another repository" +msgstr "Brúigh rudaà thar phrótacal Git chuig stór eile" + +#: command-list.h +msgid "Git's i18n setup code for shell scripts" +msgstr "Cód socraithe i18n Git le haghaidh scripteanna blaosc" + +#: command-list.h +msgid "Common Git shell script setup code" +msgstr "Cód socraithe script bhlaosc Git coitianta" + +#: command-list.h +msgid "Restricted login shell for Git-only SSH access" +msgstr "Blaosc logála isteach srianta le haghaidh rochtain SSH GIT amháin" + +#: command-list.h +msgid "Summarize 'git log' output" +msgstr "Achoimre ar aschur 'git log'" + +#: command-list.h +msgid "Show various types of objects" +msgstr "Taispeáin cineálacha éagsúla rudaÃ" + +#: command-list.h +msgid "Show branches and their commits" +msgstr "Taispeáin brainsà agus a ngealltanais" + +#: command-list.h +msgid "Show packed archive index" +msgstr "Taispeáin an t-innéacs cartlainne" + +#: command-list.h +msgid "List references in a local repository" +msgstr "Liostaigh tagairtà i stóras áitiúil" + +#: command-list.h +msgid "Reduce your working tree to a subset of tracked files" +msgstr "Laghdaigh do chrann oibre go fo-thacar de chomhaid rianaithe" + +#: command-list.h +msgid "Add file contents to the staging area" +msgstr "Cuir ábhar an chomhaid leis an limistéar stáitse" + +#: command-list.h +msgid "Stash the changes in a dirty working directory away" +msgstr "Stóráil na hathruithe in eolaire oibre salach ar shiúl" + +#: command-list.h +msgid "Show the working tree status" +msgstr "Taispeáin stádas an chrann oibre" + +#: command-list.h +msgid "Remove unnecessary whitespace" +msgstr "Bain spás bán gan ghá" + +#: command-list.h +msgid "Initialize, update or inspect submodules" +msgstr "Fo-mhodúil a thionscnamh, a nuashonrú nó a" + +#: command-list.h +msgid "Bidirectional operation between a Subversion repository and Git" +msgstr "Oibriú déthreorach idir stór Subversion agus Git" + +#: command-list.h +msgid "Switch branches" +msgstr "Athraigh brainsÃ" + +#: command-list.h +msgid "Read, modify and delete symbolic refs" +msgstr "Léigh, modhnaigh agus scriosadh taiscéalaà siombalacha" + +#: command-list.h +msgid "Create, list, delete or verify a tag object signed with GPG" +msgstr "Cruthaigh, liostáil, scrios nó fÃorú réad clibeanna sÃnithe le GPG" + +#: command-list.h +msgid "Creates a temporary file with a blob's contents" +msgstr "CruthaÃonn sé comhad sealadach le hábhar blob" + +#: command-list.h +msgid "Unpack objects from a packed archive" +msgstr "DÃphacáil rudaà ó chartlann pacáilte" + +#: command-list.h +msgid "Register file contents in the working tree to the index" +msgstr "Cláraigh ábhar an chomhaid sa chrann oibre chuig an innéacs" + +#: command-list.h +msgid "Update the object name stored in a ref safely" +msgstr "Nuashonraigh ainm an réad atá stóráilte i dtagairt go sá" + +#: command-list.h +msgid "Update auxiliary info file to help dumb servers" +msgstr "Nuashonraigh comhad faisnéise cúnta chun cabhrú le freastalaithe" + +#: command-list.h +msgid "Send archive back to git-archive" +msgstr "Seol cartlann ar ais chuig git-archive" + +#: command-list.h +msgid "Send objects packed back to git-fetch-pack" +msgstr "Seol rudaà pacáilte ar ais chuig git-fetch-pack" + +#: command-list.h +msgid "Show a Git logical variable" +msgstr "Taispeáin athróg loighciúil Git" + +#: command-list.h +msgid "Check the GPG signature of commits" +msgstr "Seiceáil sÃniú GPG na ngealltanais" + +#: command-list.h +msgid "Validate packed Git archive files" +msgstr "BailÃochtú comhaid cartlainne Git pacáilte" + +#: command-list.h +msgid "Check the GPG signature of tags" +msgstr "Seiceáil sÃniú GPG na gclibeanna" + +#: command-list.h +msgid "Display version information about Git" +msgstr "Taispeáin faisnéis leagan faoi Git" + +#: command-list.h +msgid "Show logs with differences each commit introduces" +msgstr "Taispeáin logaà le difrÃochtaà a thugann gach tiomantas" + +#: command-list.h +msgid "Manage multiple working trees" +msgstr "Bainistigh iliomad crainn oibre" + +#: command-list.h +msgid "Create a tree object from the current index" +msgstr "Cruthaigh réad crann ón innéacs reatha" + +#: command-list.h +msgid "Defining attributes per path" +msgstr "SainmhÃniú tréithe in aghaidh an" + +#: command-list.h +msgid "Git command-line interface and conventions" +msgstr "Comhéadan agus coinbhinsiúin lÃne ordaithe Git" + +#: command-list.h +msgid "A Git core tutorial for developers" +msgstr "Teagaisc lárnach Git d'fhorbróirÃ" + +#: command-list.h +msgid "Providing usernames and passwords to Git" +msgstr "Ainmneacha úsáideora agus pasfhocail a sholáthar do" + +#: command-list.h +msgid "Git for CVS users" +msgstr "Git d'úsáideoirà CVS" + +#: command-list.h +msgid "Tweaking diff output" +msgstr "Aschur difriúil a athrú" + +#: command-list.h +msgid "A useful minimum set of commands for Everyday Git" +msgstr "Sraith Ãosta úsáideach orduithe do Everyday Git" + +#: command-list.h +msgid "Frequently asked questions about using Git" +msgstr "Ceisteanna coitianta faoi úsáid Git" + +#: command-list.h +msgid "The bundle file format" +msgstr "An formáid comhaid beartán" + +#: command-list.h +msgid "Chunk-based file formats" +msgstr "Formáidà comhaid bunaithe ar bhunús" + +#: command-list.h +msgid "Git commit-graph format" +msgstr "Formáid comh-graph Git" + +#: command-list.h +msgid "Git index format" +msgstr "Formáid innéacs Git" + +#: command-list.h +msgid "Git pack format" +msgstr "Formáid pacáiste Git" + +#: command-list.h +msgid "Git cryptographic signature formats" +msgstr "Formáidà sÃnithe cripteagrafach Git" + +#: command-list.h +msgid "A Git Glossary" +msgstr "Gloclóir Git" + +#: command-list.h +msgid "Hooks used by Git" +msgstr "Crúcaà a úsáideann Git" + +#: command-list.h +msgid "Specifies intentionally untracked files to ignore" +msgstr "SonraÃonn sé comhaid neamhrianaithe de ghnó le neamhaird" + +#: command-list.h +msgid "The Git repository browser" +msgstr "Brabhsálaà stór Git" + +#: command-list.h +msgid "Map author/committer names and/or E-Mail addresses" +msgstr "Léarscáil ainmneacha údar/coistà agus/nó seoltaà rÃ" + +#: command-list.h +msgid "Defining submodule properties" +msgstr "AirÃonna fomhodúil a shainiú" + +#: command-list.h +msgid "Git namespaces" +msgstr "Spásanna ainmneacha Git" + +#: command-list.h +msgid "Protocol v0 and v1 capabilities" +msgstr "Cumais Prótacal v0 agus v1" + +#: command-list.h +msgid "Things common to various protocols" +msgstr "Rudaà coitianta le prótacail éagsúla" + +#: command-list.h +msgid "Git HTTP-based protocols" +msgstr "Prótacail Git HTTP bunaithe" + +#: command-list.h +msgid "How packs are transferred over-the-wire" +msgstr "Conas a aistrÃtear pacáistà thar an sreang" + +#: command-list.h +msgid "Git Wire Protocol, Version 2" +msgstr "Prótacal Wire Git, Leagan 2" + +#: command-list.h +msgid "Helper programs to interact with remote repositories" +msgstr "Cláir chúntóirà chun idirghnÃomhú le stórálaÃ" + +#: command-list.h +msgid "Git Repository Layout" +msgstr "Leagan Amach Stórála Git" + +#: command-list.h +msgid "Specifying revisions and ranges for Git" +msgstr "Athbhreithnithe agus raonta a shonrú do Git" + +#: command-list.h +msgid "Mounting one repository inside another" +msgstr "Stóra amháin a chur isteach taobh istigh de cheann" + +#: command-list.h +msgid "A tutorial introduction to Git" +msgstr "Réamhrá teagaisc ar Git" + +#: command-list.h +msgid "A tutorial introduction to Git: part two" +msgstr "Réamhrá teagaisc ar Git: cuid a dara" + +#: command-list.h +msgid "Git web interface (web frontend to Git repositories)" +msgstr "Comhéadan gréasáin Git (tosaigh gréasáin chuig stórais Git)" + +#: command-list.h +msgid "An overview of recommended workflows with Git" +msgstr "Forbhreathnú ar shreafaà oibre a mholtar le Git" + +#: command-list.h +msgid "A tool for managing large Git repositories" +msgstr "Uirlis chun stórtha móra Git a bhainistiú" + +#: commit-graph.c +msgid "commit-graph file is too small" +msgstr "tá comhad coimit-graph ró-bheag" + +#: commit-graph.c +msgid "commit-graph oid fanout chunk is wrong size" +msgstr "tá an méid mÃcheart ar an smután fanout oid commit-graph" + +#: commit-graph.c +msgid "commit-graph fanout values out of order" +msgstr "luachanna fanout choimisi-graph as ord" + +#: commit-graph.c +msgid "commit-graph OID lookup chunk is the wrong size" +msgstr "tá an méid mÃcheart ar an smután cuardaigh OID commit-graph" + +#: commit-graph.c +msgid "commit-graph commit data chunk is wrong size" +msgstr "tá méid mÃcheart ar an smután sonraà commit commit-graph" + +#: commit-graph.c +msgid "commit-graph generations chunk is wrong size" +msgstr "is méid mÃcheart é an pÃosa glúine ghlúin chomhghraif" + +#: commit-graph.c +msgid "commit-graph changed-path index chunk is too small" +msgstr "tá pÃosa innéacs cosáin athraithe coimisithe ró-bheag" + +#: commit-graph.c +#, c-format +msgid "" +"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-" +"graph file" +msgstr "" +"ag neamhaird a dhéanamh den smután róbheag den chonair athraithe (%<PRIuMAX> " +"< %<PRIuMAX>) i gcomhad commit-graph" + +#: commit-graph.c +#, c-format +msgid "commit-graph signature %X does not match signature %X" +msgstr "nà mheaitseálann sÃniú gráf coimiteach %X sÃniú %X" + +#: commit-graph.c +#, c-format +msgid "commit-graph version %X does not match version %X" +msgstr "nà hionann leagan %X den commit-graph agus leagan %X" + +#: commit-graph.c +#, c-format +msgid "commit-graph hash version %X does not match version %X" +msgstr "nà hionann leagan %X den hais commit-graph agus leagan %X" + +#: commit-graph.c +#, c-format +msgid "commit-graph file is too small to hold %u chunks" +msgstr "tá comhad comh-graph ró-bheag chun codanna %u a choinneáil" + +#: commit-graph.c +msgid "commit-graph required OID fanout chunk missing or corrupted" +msgstr "teastaÃonn gráf coimisiúnaithe OID ar iarraidh nó truaillithe" + +#: commit-graph.c +msgid "commit-graph required OID lookup chunk missing or corrupted" +msgstr "teastaÃonn pÃosa cuardaigh OID atá ar iarraidh nó truaillithe" + +#: commit-graph.c +msgid "commit-graph required commit data chunk missing or corrupted" +msgstr "" +"gráf choimisiúnaithe riachtanach a thabhairt do chuid sonraà atá ar iarraidh " +"nó" + +#: commit-graph.c +#, c-format +msgid "" +"disabling Bloom filters for commit-graph layer '%s' due to incompatible " +"settings" +msgstr "" +"scagairà Bloom a dhÃchumasú le haghaidh ciseal coimit-graf '%s' mar gheall " +"ar shuÃomhanna neamh-chomho" + +#: commit-graph.c +msgid "commit-graph has no base graphs chunk" +msgstr "nÃl aon phÃosa graif bunghraif ag commit-graph" + +#: commit-graph.c +msgid "commit-graph base graphs chunk is too small" +msgstr "tá an pÃosa graif bonn coimisi-graf ró-bheag" + +#: commit-graph.c +msgid "commit-graph chain does not match" +msgstr "nà mheaitseálann slabhra graf coimisiúnaithe" + +#: commit-graph.c +#, c-format +msgid "commit count in base graph too high: %<PRIuMAX>" +msgstr "lÃon tiomanta i mbonngraf ró-ard:%<PRIuMAX>" + +#: commit-graph.c +msgid "commit-graph chain file too small" +msgstr "comhad slabhra commit-graph ró-bheag" + +#: commit-graph.c +#, c-format +msgid "invalid commit-graph chain: line '%s' not a hash" +msgstr "slabhra coimit-graf neamhbhailÃ: nà hash é lÃne '%s'" + +#: commit-graph.c +msgid "unable to find all commit-graph files" +msgstr "nach féidir gach comhad gráf coimisiúnaithe a fháil" + +#: commit-graph.c +msgid "invalid commit position. commit-graph is likely corrupt" +msgstr "post tiomanta neamhbhailÃ. Is dócha go bhfuil graf coimite truaillithe" + +#: commit-graph.c +#, c-format +msgid "could not find commit %s" +msgstr "nà raibh sé in ann teacht ar thiomantas %s" + +#: commit-graph.c +msgid "commit-graph requires overflow generation data but has none" +msgstr "teastaÃonn sonraà giniúna ró-shreabhadh ach nÃl aon cheann acu" + +#: commit-graph.c +msgid "commit-graph overflow generation data is too small" +msgstr "tá sonraà giniúna ró-shreabha tiomnaithe-graif róbheag" + +#: commit-graph.c +msgid "commit-graph extra-edges pointer out of bounds" +msgstr "léirÃonn imill shrea-ghraif choimisiúin amach as teorainneacha" + +#: commit-graph.c +msgid "Loading known commits in commit graph" +msgstr "Gealltanna aitheanta a luchtú i ngraf tiomanta" + +#: commit-graph.c +msgid "Expanding reachable commits in commit graph" +msgstr "Gealltanais inrochtana a leathnú sa ghraf tiomanta" + +#: commit-graph.c +msgid "Clearing commit marks in commit graph" +msgstr "Marcanna tiomanta a ghlanadh sa ghraf tiom" + +#: commit-graph.c +msgid "Computing commit graph topological levels" +msgstr "Tiomann rÃomhaireacht leibhéil topaic" + +#: commit-graph.c +msgid "Computing commit graph generation numbers" +msgstr "Tiomann an rÃomhaireacht uimhreacha" + +#: commit-graph.c +msgid "Computing commit changed paths Bloom filters" +msgstr "Déanann rÃomhaireacht cosáin athraithe a" + +#: commit-graph.c +msgid "Collecting referenced commits" +msgstr "Gealltanna tagartha a bhailiú" + +#: commit-graph.c +#, c-format +msgid "Finding commits for commit graph in %<PRIuMAX> pack" +msgid_plural "Finding commits for commit graph in %<PRIuMAX> packs" +msgstr[0] "Ag aimsiú tiomantais don ghraf tiomantais sa phacáiste %<PRIuMAX>" +msgstr[1] "Ag aimsiú tiomantais don ghraf tiomantais i bpacáistà %<PRIuMAX>" +msgstr[2] "Ag aimsiú tiomantais don ghraf tiomantais i bpacáistà %<PRIuMAX>" + +#: commit-graph.c +#, c-format +msgid "error adding pack %s" +msgstr "earráid ag cur pacáiste %s" + +#: commit-graph.c +#, c-format +msgid "error opening index for %s" +msgstr "innéacs oscailte earráide do %s" + +#: commit-graph.c +msgid "Finding commits for commit graph among packed objects" +msgstr "Tiomantas a aimsiú maidir le graf tiomanta i measc rudaà pacá" + +#: commit-graph.c +msgid "Finding extra edges in commit graph" +msgstr "Imill bhreise a aimsiú i ngraf tiomanta" + +#: commit-graph.c +msgid "failed to write correct number of base graph ids" +msgstr "theip orthu lÃon ceart na n-idà graif bonn a scrÃobh" + +#: commit-graph.c +msgid "unable to create temporary graph layer" +msgstr "in ann ciseal graf sealadach a chruthú" + +#: commit-graph.c midx-write.c +#, c-format +msgid "unable to adjust shared permissions for '%s'" +msgstr "nach féidir ceadanna roinnte a choigeartú do '%s'" + +#: commit-graph.c +#, c-format +msgid "Writing out commit graph in %d pass" +msgid_plural "Writing out commit graph in %d passes" +msgstr[0] "Ag scrÃobh amach graf tiomantais i %d pas" +msgstr[1] "Ag scrÃobh amach graf tiomantais i %d pas" +msgstr[2] "Ag scrÃobh amach graf tiomantais i %d pas" + +#: commit-graph.c +msgid "unable to open commit-graph chain file" +msgstr "nach féidir comhad slabhra coimis-graf a oscailt" + +#: commit-graph.c +msgid "failed to rename base commit-graph file" +msgstr "theip ar an gcomhad gráf bunchoiste a athainmniú" + +#: commit-graph.c +msgid "failed to rename temporary commit-graph file" +msgstr "theip ar chomhad gráf choiste sealadach a athainmniú" + +#: commit-graph.c +#, c-format +msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits" +msgstr "nà féidir graif a chumasc le %<PRIuMAX>, %<PRIuMAX> tiomantais" + +#: commit-graph.c +#, c-format +msgid "cannot merge graph %s, too many commits: %<PRIuMAX>" +msgstr "nà féidir graf %s a chumasc, an iomarca tiomantais: %<PRIuMAX>" + +#: commit-graph.c +msgid "Scanning merged commits" +msgstr "Tiomanta cumaisc ag scanadh" + +#: commit-graph.c +msgid "Merging commit-graph" +msgstr "Graf coiste a chumasc" + +#: commit-graph.c +msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled" +msgstr "" +"ag iarraidh graf coimite a scrÃobh, ach tá 'core.commitGraph' dÃchumasaithe" + +#: commit-graph.c +#, c-format +msgid "" +"attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " +"(%d) is not supported" +msgstr "" +"ag iarraidh commit-graph a scrÃobh, ach tá 'commitGraph.changedPathsVersion' " +"(%d) nà thacaÃtear leis" + +#: commit-graph.c +msgid "too many commits to write graph" +msgstr "an iomarca gealltanais graf a scrÃobh" + +#: commit-graph.c +msgid "the commit-graph file has incorrect checksum and is likely corrupt" +msgstr "" +"tá seicsum mÃcheart ag an gcomhad graf coimite agus is dócha go bhfuil sé " +"truaillithe" + +#: commit-graph.c +#, c-format +msgid "commit-graph has incorrect OID order: %s then %s" +msgstr "tá ordú OID mÃcheart ag commit-graph: %s ansin %s" + +#: commit-graph.c +#, c-format +msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u" +msgstr "tá luach fanout mÃcheart ag commit-graph: fanout [%d] = %u! = %u" + +#: commit-graph.c +#, c-format +msgid "failed to parse commit %s from commit-graph" +msgstr "theip ar thiomantas %s a pharsáil ó ghraif choimisiúnaithe" + +#: commit-graph.c +#, c-format +msgid "failed to parse commit %s from object database for commit-graph" +msgstr "" +"theip ar thiomantas %s a pharsáil ó bhunachar sonraà réad le haghaidh graf " +"coimite" + +#: commit-graph.c +#, c-format +msgid "root tree OID for commit %s in commit-graph is %s != %s" +msgstr "" +"crann fréimhe Is é OID do thiomantas %s sa ghraf tiomantais ná %s != %s" + +#: commit-graph.c +#, c-format +msgid "commit-graph parent list for commit %s is too long" +msgstr "tá liosta tuismitheoirà comh-graph do thiomantas %s rófhada" + +#: commit-graph.c +#, c-format +msgid "commit-graph parent for %s is %s != %s" +msgstr "is é an tuismitheoir comh-graph do %s ná %s! = %s" + +#: commit-graph.c +#, c-format +msgid "commit-graph parent list for commit %s terminates early" +msgstr "" +"foirceannann liosta tuismitheora commit-graph le haghaidh commit %s go luath" + +#: commit-graph.c +#, c-format +msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>" +msgstr "" +"is é giniúint commit-graph le haghaidh commit %s %<PRIuMAX> < %<PRIuMAX>" + +#: commit-graph.c +#, c-format +msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>" +msgstr "" +"is é dáta tiomantais don tiomantas %s i commit-graph %<PRIuMAX> != %<PRIuMAX>" + +#: commit-graph.c +#, c-format +msgid "" +"commit-graph has both zero and non-zero generations (e.g., commits '%s' and " +"'%s')" +msgstr "" +"tá glúine nialasach agus neamh-nialasach ag comh-graph (e.g., geallann sé " +"'%s' agus '%s')" + +#: commit-graph.c +msgid "Verifying commits in commit graph" +msgstr "Gealltanna a fhÃorú i ngraf tiomanta" + +#: commit-reach.c sequencer.c +#, c-format +msgid "could not parse commit %s" +msgstr "nà fhéadfaà a pharsáil a dhéanamh ar thiomantas %s" + +#: commit.c +#, c-format +msgid "%s %s is not a commit!" +msgstr "Nà gealltanas é %s %s!" + +#: commit.c +msgid "" +"Support for <GIT_DIR>/info/grafts is deprecated\n" +"and will be removed in a future Git version.\n" +"\n" +"Please use \"git replace --convert-graft-file\"\n" +"to convert the grafts into replace refs.\n" +"\n" +"Turn this message off by running\n" +"\"git config set advice.graftFileDeprecated false\"" +msgstr "" +"Tá tacaÃocht d' <GIT_DIR>/info/grafts imithe\n" +"agus bainfear é i leagan Git amach anseo.\n" +"\n" +"Úsáid le do thoil “git replace --convert-graft-fileâ€\n" +"chun na grafts a thiontú ina ionad refs.\n" +"\n" +"Cas an teachtaireacht seo as trà rith\n" +"“git config socraigh advice.graftFileDeprecated bréagachâ€" + +#: commit.c +#, c-format +msgid "commit %s exists in commit-graph but not in the object database" +msgstr "tá comhad %s ann sa choimit-graph ach nÃl sa bhunachar sonraà réad" + +#: commit.c +#, c-format +msgid "Commit %s has an untrusted GPG signature, allegedly by %s." +msgstr "Tá sÃniú GPG neamhiontaofa ag Commit %s, a lÃomhnaÃtear ag %s." + +#: commit.c +#, c-format +msgid "Commit %s has a bad GPG signature allegedly by %s." +msgstr "Tá droch-shÃniú GPG ag Commit %s a lÃomhnaÃtear ag %s." + +#: commit.c +#, c-format +msgid "Commit %s does not have a GPG signature." +msgstr "NÃl sÃniú GPG ag Teacht %s." + +#: commit.c +#, c-format +msgid "Commit %s has a good GPG signature by %s\n" +msgstr "Tá sÃniú maith GPG ag Teacht %s le %s\n" + +#: commit.c +msgid "" +"Warning: commit message did not conform to UTF-8.\n" +"You may want to amend it after fixing the message, or set the config\n" +"variable i18n.commitEncoding to the encoding your project uses.\n" +msgstr "" +"Rabhadh: nÃor chomhlÃon teachtaireacht tiomanta le UTF-8.\n" +"B'fhéidir gur mhaith leat é a leasú tar éis an teachtaireacht a shocrú, nó " +"an cumraÃocht a shocrú\n" +"athróg i18N.CommitEncoding don ionchódú a úsáideann do thionscadal.\n" + +#: compat/compiler.h +msgid "no compiler information available\n" +msgstr "nÃl aon fhaisnéis tiomsaitheora ar fáil\n" + +#: compat/compiler.h +msgid "no libc information available\n" +msgstr "nÃl aon fhaisnéis libc ar fáil\n" + +#: compat/disk.h +#, c-format +msgid "could not determine free disk size for '%s'" +msgstr "nà fhéadfaà méid diosca saor in aisce a chinneadh do '%s'" + +#: compat/disk.h +#, c-format +msgid "could not get info for '%s'" +msgstr "nà fhéadfaà faisnéis a fháil do '%s'" + +#: compat/fsmonitor/fsm-health-win32.c +#, c-format +msgid "[GLE %ld] health thread could not open '%ls'" +msgstr "[GLE %ld] nà fhéadfadh snáithe sláinte '%ls' a oscailt" + +#: compat/fsmonitor/fsm-health-win32.c +#, c-format +msgid "[GLE %ld] health thread getting BHFI for '%ls'" +msgstr "[GLE %ld] snáithe sláinte ag fáil BHFI do '%ls'" + +#: compat/fsmonitor/fsm-health-win32.c compat/fsmonitor/fsm-listen-win32.c +#, c-format +msgid "could not convert to wide characters: '%s'" +msgstr "nà raibh sé in ann tiontú go carachtair leathan: '%s'" + +#: compat/fsmonitor/fsm-health-win32.c +#, c-format +msgid "BHFI changed '%ls'" +msgstr "Athraigh BHFI '%ls'" + +#: compat/fsmonitor/fsm-health-win32.c +#, c-format +msgid "unhandled case in 'has_worktree_moved': %d" +msgstr "cás neamh-láimhseáilte i 'has_worktree_moved': %d" + +#: compat/fsmonitor/fsm-health-win32.c +#, c-format +msgid "health thread wait failed [GLE %ld]" +msgstr "theip ar fanacht snáithe sláinte [GLE %ld]" + +#: compat/fsmonitor/fsm-ipc-darwin.c +#, c-format +msgid "Invalid path: %s" +msgstr "Conair neamhbhailÃ: %s" + +#: compat/fsmonitor/fsm-listen-darwin.c +msgid "Unable to create FSEventStream." +msgstr "Nà féidir FSeventStream a chruthú." + +#: compat/fsmonitor/fsm-listen-darwin.c +msgid "Failed to start the FSEventStream" +msgstr "Theip ar an FSevenStream a thosú" + +#: compat/fsmonitor/fsm-listen-win32.c +#, c-format +msgid "[GLE %ld] could not convert path to UTF-8: '%.*ls'" +msgstr "[GLE %ld] nÃorbh fhéidir an cosán a thiontú go UTF-8: '%.*ls'" + +#: compat/fsmonitor/fsm-listen-win32.c +#, c-format +msgid "[GLE %ld] could not watch '%s'" +msgstr "Nà raibh [GLE %ld] in ann féachaint ar '%s'" + +#: compat/fsmonitor/fsm-listen-win32.c +#, c-format +msgid "[GLE %ld] could not get longname of '%s'" +msgstr "Nà raibh [GLE %ld] in ann ainm fadainm '%s' a fháil" + +#: compat/fsmonitor/fsm-listen-win32.c +#, c-format +msgid "ReadDirectoryChangedW failed on '%s' [GLE %ld]" +msgstr "Theip ar ReadDirectoryChangedW ar '%s' [GLE %ld]" + +#: compat/fsmonitor/fsm-listen-win32.c +#, c-format +msgid "GetOverlappedResult failed on '%s' [GLE %ld]" +msgstr "Theip ar getOverlappedResult ar '%s' [GLE %ld]" + +#: compat/fsmonitor/fsm-listen-win32.c +#, c-format +msgid "could not read directory changes [GLE %ld]" +msgstr "nà fhéadfaà athruithe eolaire a léamh [GLE %ld]" + +#: compat/fsmonitor/fsm-path-utils-darwin.c +#, c-format +msgid "opendir('%s') failed" +msgstr "theip ar opendir ('%s')" + +#: compat/fsmonitor/fsm-path-utils-darwin.c +#, c-format +msgid "lstat('%s') failed" +msgstr "theip ar lstat ('%s')" + +#: compat/fsmonitor/fsm-path-utils-darwin.c +#, c-format +msgid "strbuf_readlink('%s') failed" +msgstr "theip ar strbuf_readlink ('%s')" + +#: compat/fsmonitor/fsm-path-utils-darwin.c +#, c-format +msgid "closedir('%s') failed" +msgstr "theip ar closedir ('%s')" + +#: compat/fsmonitor/fsm-path-utils-win32.c +#, c-format +msgid "[GLE %ld] unable to open for read '%ls'" +msgstr "[GLE %ld] nach féidir é a oscailt le haghaidh léamh '%ls'" + +#: compat/fsmonitor/fsm-path-utils-win32.c +#, c-format +msgid "[GLE %ld] unable to get protocol information for '%ls'" +msgstr "[GLE %ld] in ann faisnéis phrótacail a fháil do '%ls'" + +#: compat/mingw.c +#, c-format +msgid "failed to copy SID (%ld)" +msgstr "theip ar SID (%ld) a chóipeáil" + +#: compat/mingw.c +#, c-format +msgid "failed to get owner for '%s' (%ld)" +msgstr "theip ar úinéir a fháil do '%s' (%ld)" + +#: compat/obstack.c +msgid "memory exhausted" +msgstr "cuimhne Ãdithe" + +#: compat/regex/regcomp.c +msgid "Success" +msgstr "Rath" + +#: compat/regex/regcomp.c +msgid "No match" +msgstr "Gan aon mheaitseáil" + +#: compat/regex/regcomp.c +msgid "Invalid regular expression" +msgstr "Léiriú rialta nebhailÃ" + +#: compat/regex/regcomp.c +msgid "Invalid collation character" +msgstr "Carachtar comparáide neamhbhailÃ" + +#: compat/regex/regcomp.c +msgid "Invalid character class name" +msgstr "Ainm ranga carachtar neamhbhailÃ" + +#: compat/regex/regcomp.c +msgid "Trailing backslash" +msgstr "Cúlbhraith rianaithe" + +#: compat/regex/regcomp.c +msgid "Invalid back reference" +msgstr "Tagairt cúil neamhbhailÃ" + +#: compat/regex/regcomp.c +msgid "Unmatched [ or [^" +msgstr "Gan chomhoiriúnú [nó [^" + +#: compat/regex/regcomp.c +msgid "Unmatched ( or \\(" +msgstr "Gan chomhoiriúnú (nó\\ (" + +#: compat/regex/regcomp.c +msgid "Unmatched \\{" +msgstr "Gan comhoiriúnú\\ {" + +#: compat/regex/regcomp.c +msgid "Invalid content of \\{\\}" +msgstr "Ãbhar neamhbhailà de\\ {\\}" + +#: compat/regex/regcomp.c +msgid "Invalid range end" +msgstr "Deireadh raon neamhbhailÃ" + +#: compat/regex/regcomp.c +msgid "Memory exhausted" +msgstr "Cuimhne Ãdithe" + +#: compat/regex/regcomp.c +msgid "Invalid preceding regular expression" +msgstr "Léiriú rialta neamhbhailÃ" + +#: compat/regex/regcomp.c +msgid "Premature end of regular expression" +msgstr "Deireadh roimh am an léirithe rialta" + +#: compat/regex/regcomp.c +msgid "Regular expression too big" +msgstr "Léiriú rialta ró-mhór" + +#: compat/regex/regcomp.c +msgid "Unmatched ) or \\)" +msgstr "Gan chomhoiriúnú) nó\\)" + +#: compat/regex/regcomp.c +msgid "No previous regular expression" +msgstr "Gan aon léiriú rialta roimhe seo" + +#: compat/simple-ipc/ipc-unix-socket.c compat/simple-ipc/ipc-win32.c +msgid "could not send IPC command" +msgstr "nà fhéadfaà ordú IPC a sheoladh" + +#: compat/simple-ipc/ipc-unix-socket.c compat/simple-ipc/ipc-win32.c +msgid "could not read IPC response" +msgstr "nà raibh sé in ann freagra IPC a léamh" + +#: compat/simple-ipc/ipc-unix-socket.c +#, c-format +msgid "could not start accept_thread '%s'" +msgstr "nà fhéadfaà tosú accept_thread '%s'" + +#: compat/simple-ipc/ipc-unix-socket.c +#, c-format +msgid "could not start worker[0] for '%s'" +msgstr "nà fhéadfaà oibrà [0] a thosú le haghaidh '%s'" + +#: compat/simple-ipc/ipc-win32.c +#, c-format +msgid "ConnectNamedPipe failed for '%s' (%lu)" +msgstr "Theip ar ConnectNamedPipe le haghaidh '%s' (%lu)" + +#: compat/simple-ipc/ipc-win32.c +#, c-format +msgid "could not create fd from pipe for '%s'" +msgstr "nà fhéadfaà fd a chruthú ó phÃopa do '%s'" + +#: compat/simple-ipc/ipc-win32.c +#, c-format +msgid "could not start thread[0] for '%s'" +msgstr "nà fhéadfaà snáithe [0] a thosú le haghaidh '%s'" + +#: compat/simple-ipc/ipc-win32.c +#, c-format +msgid "wait for hEvent failed for '%s'" +msgstr "fanacht go dtà Theip ar feadh '%s'" + +#: compat/terminal.c +msgid "cannot resume in the background, please use 'fg' to resume" +msgstr "nà féidir atosú sa chúlra, bain úsáid as 'fg' le do thoil chun atosú" + +#: compat/terminal.c +msgid "cannot restore terminal settings" +msgstr "nà féidir le socruithe teirminéil" + +#: config.c +#, c-format +msgid "" +"exceeded maximum include depth (%d) while including\n" +"\t%s\n" +"from\n" +"\t%s\n" +"This might be due to circular includes." +msgstr "" +"sháraigh an uasmhéid san áireamh doimhneacht (%d) agus\n" +" %s\n" +"ó\n" +" %s\n" +"D'fhéadfadh sé seo a bheith mar gheall ar áireamh ciorclach." + +#: config.c +#, c-format +msgid "could not expand include path '%s'" +msgstr "nà fhéadfaà leathnú san áireamh cosán '%s'" + +#: config.c +msgid "relative config includes must come from files" +msgstr "folaÃonn cumraÃocht choibhneasta caithfidh teacht ó chomh" + +#: config.c +msgid "relative config include conditionals must come from files" +msgstr "nà mór coinnÃollacha a theacht ó chomhaid i gcumraÃocht choibhneasta" + +#: config.c +msgid "" +"remote URLs cannot be configured in file directly or indirectly included by " +"includeIf.hasconfig:remote.*.url" +msgstr "" +"nà féidir URLanna iargúlta a chumrú i gcomhad san áireamh go dÃreach nó go " +"hindÃreach ag includeIf.hasconfig:remote.*.url" + +#: config.c +#, c-format +msgid "invalid config format: %s" +msgstr "formáid cumraÃochta neamhbhailÃ: %s" + +#: config.c +#, c-format +msgid "missing environment variable name for configuration '%.*s'" +msgstr "ainm athróg comhshaoil atá in easnamh do chumraÃocht '%.*s'" + +#: config.c +#, c-format +msgid "missing environment variable '%s' for configuration '%.*s'" +msgstr "athróg comhshaoil in easnamh '%s' le haghaidh cumraÃocht '%.*s'" + +#: config.c +#, c-format +msgid "key does not contain a section: %s" +msgstr "nÃl rannán ag eochair: %s" + +#: config.c +#, c-format +msgid "key does not contain variable name: %s" +msgstr "nÃl ainm athraitheach sa eochair: %s" + +#: config.c sequencer.c +#, c-format +msgid "invalid key: %s" +msgstr "eochair neamhbhailÃ: %s" + +#: config.c +#, c-format +msgid "invalid key (newline): %s" +msgstr "eochair neamhbhailà (lÃne nua): %s" + +#: config.c +msgid "empty config key" +msgstr "eochair cumraÃochta folamh" + +#: config.c +#, c-format +msgid "bogus config parameter: %s" +msgstr "paraiméadar cumraÃochta bréagach: %s" + +#: config.c +#, c-format +msgid "bogus format in %s" +msgstr "formáid bhréagach i %s" + +#: config.c +#, c-format +msgid "bogus count in %s" +msgstr "comhaireamh bréagach i %s" + +#: config.c +#, c-format +msgid "too many entries in %s" +msgstr "an iomarca iontrálacha i %s" + +#: config.c +#, c-format +msgid "missing config key %s" +msgstr "eochair chumraithe %s in easnamh" + +#: config.c +#, c-format +msgid "missing config value %s" +msgstr "luach cumraÃochta %s ar iarraidh" + +#: config.c +#, c-format +msgid "bad config line %d in blob %s" +msgstr "droch-lÃne cumraÃochta %d i mblob %s" + +#: config.c +#, c-format +msgid "bad config line %d in file %s" +msgstr "droch-lÃne cumraÃochta %d i gcomhad %s" + +#: config.c +#, c-format +msgid "bad config line %d in standard input" +msgstr "droch-lÃne cumraÃochta %d i ionchur caighdeánach" + +#: config.c +#, c-format +msgid "bad config line %d in submodule-blob %s" +msgstr "droch-lÃne cumraÃochta %d i bhfo-modul-blob %s" + +#: config.c +#, c-format +msgid "bad config line %d in command line %s" +msgstr "droch-lÃne cumraÃochta %d i lÃne ordaithe %s" + +#: config.c +#, c-format +msgid "bad config line %d in %s" +msgstr "droch-lÃne cumraÃochta %d i %s" + +#: config.c +msgid "out of range" +msgstr "lasmuigh den raon" + +#: config.c +msgid "invalid unit" +msgstr "aonad neamhbhailÃ" + +#: config.c +#, c-format +msgid "bad numeric config value '%s' for '%s': %s" +msgstr "droch-luach cumraÃochta uimhriúil '%s' do '%s': %s" + +#: config.c +#, c-format +msgid "bad numeric config value '%s' for '%s' in blob %s: %s" +msgstr "droch-luach cumraÃochta uimhriúil '%s' do '%s' i mblob %s: %s" + +#: config.c +#, c-format +msgid "bad numeric config value '%s' for '%s' in file %s: %s" +msgstr "droch-luach cumraÃochta uimhriúil '%s' do '%s' i gcomhad %s: %s" + +#: config.c +#, c-format +msgid "bad numeric config value '%s' for '%s' in standard input: %s" +msgstr "" +"droch-luach cumraÃochta uimhriúil '%s' do '%s' in ionchur caighdeánach: %s" + +#: config.c +#, c-format +msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s" +msgstr "droch-luach cumraÃochta uimhriúil '%s' do '%s' i bhfo-mhodúl %s: %s" + +#: config.c +#, c-format +msgid "bad numeric config value '%s' for '%s' in command line %s: %s" +msgstr "droch-luach cumraÃochta uimhriúil '%s' do '%s' i lÃne ordaithe %s: %s" + +#: config.c +#, c-format +msgid "bad numeric config value '%s' for '%s' in %s: %s" +msgstr "droch-luach cumraÃochta uimhriúil '%s' do '%s' i %s: %s" + +#: config.c +#, c-format +msgid "invalid value for variable %s" +msgstr "luach neamhbhailà don athróg %s" + +#: config.c +#, c-format +msgid "ignoring unknown core.fsync component '%s'" +msgstr "neamhaird a dhéanamh ar chomhpháirt core.fsync anaithnid '%s'" + +#: config.c +#, c-format +msgid "bad boolean config value '%s' for '%s'" +msgstr "droch-luach cumraÃochta boolean '%s' do '%s'" + +#: config.c +#, c-format +msgid "failed to expand user dir in: '%s'" +msgstr "theip ar dir an úsáideora a leathnú i: '%s'" + +#: config.c +#, c-format +msgid "'%s' for '%s' is not a valid timestamp" +msgstr "Nà stampa ama bailà é '%s' do '%s'" + +#: config.c +#, c-format +msgid "abbrev length out of range: %d" +msgstr "fad a ghiorrú lasmuigh den raon: %d" + +#: config.c +#, c-format +msgid "bad zlib compression level %d" +msgstr "droch-leibhéal comhbhrúite zlib %d" + +#: config.c +#, c-format +msgid "%s cannot contain newline" +msgstr "Nà féidir le lÃne nua a bheith ag %s" + +#: config.c +#, c-format +msgid "%s must have at least one character" +msgstr "Nà mór carachtar amháin ar a laghad a bheith ag %s" + +#: config.c +#, c-format +msgid "ignoring unknown core.fsyncMethod value '%s'" +msgstr "neamhaird a dhéanamh ar luach core.fsyncMethod anaithnid '%s'" + +#: config.c +msgid "core.fsyncObjectFiles is deprecated; use core.fsync instead" +msgstr "" +"tá core.fsyncObjectFiles dÃscothaithe; bain úsáid as core.fsync ina ionad" + +#: config.c +#, c-format +msgid "invalid mode for object creation: %s" +msgstr "modh neamhbhailà chun réad a chruthú: %s" + +#: config.c +#, c-format +msgid "malformed value for %s" +msgstr "luach mÃfhoirmithe do %s" + +#: config.c +#, c-format +msgid "malformed value for %s: %s" +msgstr "luach mÃfhoirmithe do %s: %s" + +#: config.c +msgid "must be one of nothing, matching, simple, upstream or current" +msgstr "" +"caithfidh sé a bheith ar cheann de rud ar bith, meaitseálach, simplÃ, suas " +"srutha nó reatha" + +#: config.c +#, c-format +msgid "unable to load config blob object '%s'" +msgstr "nach féidir réad blob cumraithe '%s' a luchtú" + +#: config.c +#, c-format +msgid "reference '%s' does not point to a blob" +msgstr "nà thugann tagairt '%s' in iúl do bhlob" + +#: config.c +#, c-format +msgid "unable to resolve config blob '%s'" +msgstr "in ann clob config '%s' a réiteach" + +#: config.c +msgid "unable to parse command-line config" +msgstr "nach féidir cumraÃocht lÃne ordaithe a pháirseáil" + +#: config.c +msgid "unknown error occurred while reading the configuration files" +msgstr "tharla earráid anaithnid agus na comhaid cumraÃochta á léamh" + +#: config.c +#, c-format +msgid "Invalid %s: '%s'" +msgstr "%s neamhbhailÃ: '%s'" + +#: config.c +#, c-format +msgid "splitIndex.maxPercentChange value '%d' should be between 0 and 100" +msgstr "splitIndex.maxPercentChange value '%d' bheith idir 0 agus 100" + +#: config.c +#, c-format +msgid "unable to parse '%s' from command-line config" +msgstr "nà féidir '%s' a pháirseáil ó chumraÃocht lÃne ordaithe" + +#: config.c +#, c-format +msgid "bad config variable '%s' in file '%s' at line %d" +msgstr "droch-athróg cumraithe '%s' sa chomhad '%s' ag lÃne %d" + +#: config.c +#, c-format +msgid "invalid section name '%s'" +msgstr "ainm rannán neamhbhailà '%s'" + +#: config.c +#, c-format +msgid "%s has multiple values" +msgstr "Tá luachanna iolracha ag %s" + +#: config.c +#, c-format +msgid "failed to write new configuration file %s" +msgstr "theip ar chomhad cumraÃochta nua %s a scrÃobh" + +#: config.c +#, c-format +msgid "no multi-line comment allowed: '%s'" +msgstr "nÃl aon trácht illÃne ceadaithe: '%s'" + +#: config.c +#, c-format +msgid "could not lock config file %s" +msgstr "nà fhéadfaà comhad cumraÃochta %s a ghlasáil" + +#: config.c +#, c-format +msgid "opening %s" +msgstr "oscailt %s" + +#: config.c +#, c-format +msgid "invalid config file %s" +msgstr "comhad cumraithe neamhbhailà %s" + +#: config.c +#, c-format +msgid "fstat on %s failed" +msgstr "theip ar fstat ar %s" + +#: config.c +#, c-format +msgid "unable to mmap '%s'%s" +msgstr "nà féidir le '%s'%s a mmapáil" + +#: config.c +#, c-format +msgid "chmod on %s failed" +msgstr "theip ar chmod ar %s" + +#: config.c +#, c-format +msgid "could not write config file %s" +msgstr "nà fhéadfaà comhad cumraithe %s a scrÃobh" + +#: config.c +#, c-format +msgid "could not set '%s' to '%s'" +msgstr "nà fhéadfaà '%s' a shocrú go '%s'" + +#: config.c +#, c-format +msgid "invalid section name: %s" +msgstr "ainm rannán neamhbhailÃ: %s" + +#: config.c +#, c-format +msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>" +msgstr "diúltú oibriú le lÃne rófhada i '%s' ar lÃne%<PRIuMAX>" + +#: config.c +#, c-format +msgid "missing value for '%s'" +msgstr "luach ar iarraidh do '%s'" + +#: connect.c +msgid "the remote end hung up upon initial contact" +msgstr "crochadh an deireadh iargúlta ar an teagmháil tosaigh" + +#: connect.c +msgid "" +"Could not read from remote repository.\n" +"\n" +"Please make sure you have the correct access rights\n" +"and the repository exists." +msgstr "" +"Nà fhéadfaà léamh ó stór iargúlta.\n" +"\n" +"Déan cinnte go bhfuil na cearta rochtana cearta agat\n" +"agus tá an stór ann." + +#: connect.c +#, c-format +msgid "server doesn't support '%s'" +msgstr "nà thacaÃonn freastalaà le '%s'" + +#: connect.c +#, c-format +msgid "server doesn't support feature '%s'" +msgstr "nà thacaÃonn freastalaà le gné '%s'" + +#: connect.c +msgid "expected flush after capabilities" +msgstr "súil le sruth tar éis cumais" + +#: connect.c +#, c-format +msgid "ignoring capabilities after first line '%s'" +msgstr "neamhaird a dhéanamh ar chumais tar éis an chéad lÃne '%s'" + +#: connect.c +msgid "protocol error: unexpected capabilities^{}" +msgstr "earráid prótacal: cumais gan choinne ^ {}" + +#: connect.c +#, c-format +msgid "protocol error: expected shallow sha-1, got '%s'" +msgstr "earráid prótacal: táthar ag súil le sha-1 éadrom, fuair '%s'" + +#: connect.c +msgid "repository on the other end cannot be shallow" +msgstr "nà féidir stór ar an gceann eile a bheith éadrom" + +#: connect.c +msgid "invalid packet" +msgstr "pacáiste neamhbhail" + +#: connect.c +#, c-format +msgid "protocol error: unexpected '%s'" +msgstr "earráid prótacal: '%s' gan choinne" + +#: connect.c +#, c-format +msgid "unknown object format '%s' specified by server" +msgstr "formáid réad anaithnid '%s' arna shonrú ag freastalaÃ" + +#: connect.c +#, c-format +msgid "error on bundle-uri response line %d: %s" +msgstr "earráid ar lÃne freagartha cumhachta %d: %s" + +#: connect.c +msgid "expected flush after bundle-uri listing" +msgstr "súil le sruth tar éis liostú bundle-uri" + +#: connect.c +msgid "expected response end packet after ref listing" +msgstr "pacáiste deiridh freagartha a bhfuiltear ag súil leis" + +#: connect.c +#, c-format +msgid "invalid ls-refs response: %s" +msgstr "freagra neamhbhailà ls-refs: %s" + +#: connect.c +msgid "expected flush after ref listing" +msgstr "súil le sruth tar éis liostú tagartha" + +#: connect.c +#, c-format +msgid "protocol '%s' is not supported" +msgstr "nà thacaÃtear le prótacal '%s'" + +#: connect.c +msgid "unable to set SO_KEEPALIVE on socket" +msgstr "in ann SO_KEEPALIVE a shocrú ar an soicéad" + +#: connect.c +#, c-format +msgid "Looking up %s ... " +msgstr "Ag féachaint suas %s... " + +#: connect.c +#, c-format +msgid "unable to look up %s (port %s) (%s)" +msgstr "nach féidir a lorg suas %s (port %s) (%s)" + +#. TRANSLATORS: this is the end of "Looking up %s ... " +#: connect.c +#, c-format +msgid "" +"done.\n" +"Connecting to %s (port %s) ... " +msgstr "" +"déanta.\n" +"Ag nascadh le %s (port %s)... " + +#: connect.c +#, c-format +msgid "" +"unable to connect to %s:\n" +"%s" +msgstr "" +"nà féidir a nascadh le %s:\n" +"%s" + +#. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... " +#: connect.c +msgid "done." +msgstr "déanta." + +#: connect.c +#, c-format +msgid "unable to look up %s (%s)" +msgstr "nach féidir a lorg suas %s (%s)" + +#: connect.c +#, c-format +msgid "unknown port %s" +msgstr "port anaithnid %s" + +#: connect.c +#, c-format +msgid "strange hostname '%s' blocked" +msgstr "ainm óstach aisteach '%s' blocáilte" + +#: connect.c +#, c-format +msgid "strange port '%s' blocked" +msgstr "cosc ar chalafort aisteach '%s'" + +#: connect.c +#, c-format +msgid "cannot start proxy %s" +msgstr "nà féidir le seachfhreastalaà %s" + +#: connect.c +msgid "no path specified; see 'git help pull' for valid url syntax" +msgstr "" +"nÃl aon chosán sonraithe; féach 'git help pull' le haghaidh comhréireachta " +"bailà url" + +#: connect.c +msgid "newline is forbidden in git:// hosts and repo paths" +msgstr "tá cosc ​​ar lÃne nua in óstaigh git:// agus cosáin stórais" + +#: connect.c +msgid "ssh variant 'simple' does not support -4" +msgstr "nà thacaÃonn leagan ssh 'simplÃ' le -4" + +#: connect.c +msgid "ssh variant 'simple' does not support -6" +msgstr "nà thacaÃonn leagan ssh 'simplÃ' le -6" + +#: connect.c +msgid "ssh variant 'simple' does not support setting port" +msgstr "nà thacaÃonn leagan ssh 'simplÃ' le port socrú" + +#: connect.c +#, c-format +msgid "strange pathname '%s' blocked" +msgstr "cosc ar ainm cosán aisteach '%s'" + +#: connect.c +msgid "unable to fork" +msgstr "in ann a fhorc" + +#: connected.c +msgid "Could not run 'git rev-list'" +msgstr "Nà fhéadfaà 'git rev-list' a reáchtáil" + +#: connected.c +msgid "failed write to rev-list" +msgstr "theip ar scrÃobh chuig rev-list" + +#: connected.c +msgid "failed to close rev-list's stdin" +msgstr "theip orthu stdin rev-list a dhúnadh" + +#: convert.c +#, c-format +msgid "illegal crlf_action %d" +msgstr "crlf_action mÃdhleathach %d" + +#: convert.c +#, c-format +msgid "CRLF would be replaced by LF in %s" +msgstr "Bheadh LF in ionad CRLF i %s" + +#: convert.c +#, c-format +msgid "" +"in the working copy of '%s', CRLF will be replaced by LF the next time Git " +"touches it" +msgstr "" +"sa chóip oibre de '%s', cuirfear LF in ionad CRLF an chéad uair eile a " +"théann Git leis" + +#: convert.c +#, c-format +msgid "LF would be replaced by CRLF in %s" +msgstr "Bheadh CRLF in ionad LF i %s" + +#: convert.c +#, c-format +msgid "" +"in the working copy of '%s', LF will be replaced by CRLF the next time Git " +"touches it" +msgstr "" +"sa chóip oibre de '%s', cuirfear CRLF in ionad LF an chéad uair eile a " +"théann Git leis" + +#: convert.c +#, c-format +msgid "BOM is prohibited in '%s' if encoded as %s" +msgstr "Tá cosc ar BOM i '%s' má tá sé ionchódaithe mar %s" + +#: convert.c +#, c-format +msgid "" +"The file '%s' contains a byte order mark (BOM). Please use UTF-%.*s as " +"working-tree-encoding." +msgstr "" +"Tá marc ordaithe beart (BOM) sa chomhad '%s'. Bain úsáid as UTF-%.*s mar " +"ionchódú crann oibre le do thoil." + +#: convert.c +#, c-format +msgid "BOM is required in '%s' if encoded as %s" +msgstr "Tá BOM ag teastáil i '%s' má tá sé ionchódaithe mar %s" + +#: convert.c +#, c-format +msgid "" +"The file '%s' is missing a byte order mark (BOM). Please use UTF-%sBE or UTF-" +"%sLE (depending on the byte order) as working-tree-encoding." +msgstr "" +"Tá marc ordaithe beart (BOM) ar iarraidh sa chomhad '%s'. Bain úsáid as UTF-" +"%sBE nó UTF-%sLE (ag brath ar ord na mbeart) mar ionchódú crann oibre." + +#: convert.c +#, c-format +msgid "failed to encode '%s' from %s to %s" +msgstr "theip ar '%s' a ionchódú ó %s go %s" + +#: convert.c +#, c-format +msgid "encoding '%s' from %s to %s and back is not the same" +msgstr "ionchódú '%s' ó %s go %s agus nÃl sé mar an gcéanna ar ais" + +#: convert.c +#, c-format +msgid "cannot fork to run external filter '%s'" +msgstr "nà féidir forc chun scagaire seachtrach '%s' a reáchtáil" + +#: convert.c +#, c-format +msgid "cannot feed the input to external filter '%s'" +msgstr "nà féidir leis an ionchur a bheathú chuig scagaire seachtrach '%s'" + +#: convert.c +#, c-format +msgid "external filter '%s' failed %d" +msgstr "theip ar scagaire seachtrach '%s' %d" + +#: convert.c +#, c-format +msgid "read from external filter '%s' failed" +msgstr "theip ar léamh ó scagaire seachtrach '%s'" + +#: convert.c +#, c-format +msgid "external filter '%s' failed" +msgstr "theip ar scagaire seachtrach '%s'" + +#: convert.c +msgid "unexpected filter type" +msgstr "cineál scagaire gan choinne" + +#: convert.c +msgid "path name too long for external filter" +msgstr "ainm cosáin rófhada le haghaidh scagaire seachtrach" + +#: convert.c +#, c-format +msgid "" +"external filter '%s' is not available anymore although not all paths have " +"been filtered" +msgstr "" +"nÃl an scagaire seachtrach '%s' ar fáil a thuilleadh cé nach bhfuil na " +"cosáin uile scagtha" + +#: convert.c +msgid "true/false are no valid working-tree-encodings" +msgstr "nÃl aon ionchódaithe bailà crainn oibre fÃor-bhréagach" + +#: convert.c +#, c-format +msgid "%s: clean filter '%s' failed" +msgstr "%s: theip ar scagaire glan '%s'" + +#: convert.c +#, c-format +msgid "%s: smudge filter %s failed" +msgstr "%s: theip ar scagaire smudge %s" + +#: credential.c +#, c-format +msgid "skipping credential lookup for key: credential.%s" +msgstr "cuardach creidiúnaithe a scipeáil le haghaidh eochair: creidiúnas. %s" + +#: credential.c +msgid "refusing to work with credential missing host field" +msgstr "diúltú oibriú le réimse óstach creidiúnaithe atá ar" + +#: credential.c +msgid "refusing to work with credential missing protocol field" +msgstr "diúltú oibriú le réimse prótacal ar iarraidh creidiú" + +#: credential.c +#, c-format +msgid "url contains a newline in its %s component: %s" +msgstr "tá lÃne nua ina chomhpháirt %s ag url: %s" + +#: credential.c +#, c-format +msgid "url has no scheme: %s" +msgstr "nÃl aon scéim ag url: %s" + +#: credential.c +#, c-format +msgid "credential url cannot be parsed: %s" +msgstr "nà féidir url creidiúnaithe a pháirseáil: %s" + +#: daemon.c +#, c-format +msgid "invalid timeout '%s', expecting a non-negative integer" +msgstr "ama neamhbhailà '%s', ag súil le sláimhir neamh-dhiúltach" + +#: daemon.c +#, c-format +msgid "invalid init-timeout '%s', expecting a non-negative integer" +msgstr "ama init-time '%s' neamhbhailÃ, ag súil le sláimhir neamh-dhiúltach" + +#: daemon.c +#, c-format +msgid "invalid max-connections '%s', expecting an integer" +msgstr "naisc uasta neamhbhailà '%s', ag súil le sláimhir" + +#: date.c +msgid "in the future" +msgstr "sa todhchaÃ" + +#: date.c +#, c-format +msgid "%<PRIuMAX> second ago" +msgid_plural "%<PRIuMAX> seconds ago" +msgstr[0] "%<PRIuMAX> soicind ó shin" +msgstr[1] "%<PRIuMAX> soicind ó shin" +msgstr[2] "%<PRIuMAX> soicind ó shin" + +#: date.c +#, c-format +msgid "%<PRIuMAX> minute ago" +msgid_plural "%<PRIuMAX> minutes ago" +msgstr[0] "%<PRIuMAX> nóiméad ó shin" +msgstr[1] "%<PRIuMAX> nóiméad ó shin" +msgstr[2] "%<PRIuMAX> nóiméad ó shin" + +#: date.c +#, c-format +msgid "%<PRIuMAX> hour ago" +msgid_plural "%<PRIuMAX> hours ago" +msgstr[0] "%<PRIuMAX> uair an chloig ó shin" +msgstr[1] "%<PRIuMAX> uair an chloig ó shin" +msgstr[2] "%<PRIuMAX> uair an chloig ó shin" + +#: date.c +#, c-format +msgid "%<PRIuMAX> day ago" +msgid_plural "%<PRIuMAX> days ago" +msgstr[0] "%<PRIuMAX> lá ó shin" +msgstr[1] "%<PRIuMAX> lá ó shin" +msgstr[2] "%<PRIuMAX> lá ó shin" + +#: date.c +#, c-format +msgid "%<PRIuMAX> week ago" +msgid_plural "%<PRIuMAX> weeks ago" +msgstr[0] "%<PRIuMAX> seachtain ó shin" +msgstr[1] "%<PRIuMAX> seachtain ó shin" +msgstr[2] "%<PRIuMAX> seachtain ó shin" + +#: date.c +#, c-format +msgid "%<PRIuMAX> month ago" +msgid_plural "%<PRIuMAX> months ago" +msgstr[0] "%<PRIuMAX> mà ó shin" +msgstr[1] "%<PRIuMAX> mà ó shin" +msgstr[2] "%<PRIuMAX> mà ó shin" + +#: date.c +#, c-format +msgid "%<PRIuMAX> year" +msgid_plural "%<PRIuMAX> years" +msgstr[0] "%<PRIuMAX> bliain" +msgstr[1] "%<PRIuMAX> bliain" +msgstr[2] "%<PRIuMAX> bliain" + +#. TRANSLATORS: "%s" is "<n> years" +#: date.c +#, c-format +msgid "%s, %<PRIuMAX> month ago" +msgid_plural "%s, %<PRIuMAX> months ago" +msgstr[0] "%s, %<PRIuMAX> mà ó shin" +msgstr[1] "%s, %<PRIuMAX> mà ó shin" +msgstr[2] "%s, %<PRIuMAX> mà ó shin" + +#: date.c +#, c-format +msgid "%<PRIuMAX> year ago" +msgid_plural "%<PRIuMAX> years ago" +msgstr[0] "%<PRIuMAX> bliain ó shin" +msgstr[1] "%<PRIuMAX> bliain ó shin" +msgstr[2] "%<PRIuMAX> bliain ó shin" + +#: delta-islands.c +msgid "Propagating island marks" +msgstr "Marcanna oileáin a iomadú" + +#: delta-islands.c +#, c-format +msgid "bad tree object %s" +msgstr "réad droch-chrann %s" + +#: delta-islands.c +#, c-format +msgid "failed to load island regex for '%s': %s" +msgstr "theip ar an oileán regex a luchtú do '%s': %s" + +#: delta-islands.c +#, c-format +msgid "island regex from config has too many capture groups (max=%d)" +msgstr "tá an iomarca grúpaà gabhála ag an oileán regex ó config (max = %d)" + +#: delta-islands.c +#, c-format +msgid "Marked %d islands, done.\n" +msgstr "Oileáin %d marcáilte, déanta.\n" + +#: diagnose.c +#, c-format +msgid "invalid --%s value '%s'" +msgstr "neamhbhailà --%s luach '%s'" + +#: diagnose.c +#, c-format +msgid "could not archive missing directory '%s'" +msgstr "nà fhéadfaà eolaire '%s' in easnamh a chartlannú" + +#: diagnose.c dir.c +#, c-format +msgid "could not open directory '%s'" +msgstr "nà raibh in ann eolaire '%s' a oscailt" + +#: diagnose.c +#, c-format +msgid "skipping '%s', which is neither file nor directory" +msgstr "ag scipeáil '%s', nach comhad ná eolaire" + +#: diagnose.c +msgid "could not duplicate stdout" +msgstr "nà fhéadfaà stdout a dhúbailt" + +#: diagnose.c +#, c-format +msgid "could not add directory '%s' to archiver" +msgstr "nà fhéadfaà eolaire '%s' a chur leis an gcartlann" + +#: diagnose.c +msgid "failed to write archive" +msgstr "theip ar chartlann a scrÃobh" + +#: diff-lib.c +msgid "--merge-base does not work with ranges" +msgstr "nà oibrÃonn --merge-base le raonta" + +#: diff-lib.c +msgid "unable to get HEAD" +msgstr "in ann HEAD a fháil" + +#: diff-lib.c +msgid "no merge base found" +msgstr "nÃl aon bhonn cumaisc le fáil" + +#: diff-lib.c +msgid "multiple merge bases found" +msgstr "fuarthas bonn cumaisc iolr" + +#: diff-no-index.c +msgid "cannot compare stdin to a directory" +msgstr "nà féidir stdin a chur i gcomparáid le eolaire" + +#: diff-no-index.c +msgid "cannot compare a named pipe to a directory" +msgstr "nà féidir pÃopa ainmnithe a chur i gcomparáid le eolaire" + +#: diff-no-index.c +msgid "git diff --no-index [<options>] <path> <path>" +msgstr "git diff --no-index [<options>] <path> <path>" + +#: diff-no-index.c +msgid "" +"Not a git repository. Use --no-index to compare two paths outside a working " +"tree" +msgstr "" +"Nà stór git. Úsáid --no-index chun dhá chosán a chur i gcomparáid lasmuigh " +"de chrann oibre" + +#: diff.c +#, c-format +msgid " Failed to parse dirstat cut-off percentage '%s'\n" +msgstr " Theip ar chéatadán scoir dirstat '%s' a pharsáil\n" + +#: diff.c +#, c-format +msgid " Unknown dirstat parameter '%s'\n" +msgstr " Paraiméadar dirstat anaithnid '%s'\n" + +#: diff.c +msgid "" +"color moved setting must be one of 'no', 'default', 'blocks', 'zebra', " +"'dimmed-zebra', 'plain'" +msgstr "" +"caithfidh socrú dath a bhogadh a bheith ar cheann de 'nÃl', " +"'réamhshocraithe', 'bloic', 'zebra', 'dimmed-zebra', 'simplÃ'" + +#: diff.c +#, 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 "" +"modh dath-gluaisea-ws anaithnid '%s', is iad na luachanna féideartha " +"'neamhaird-spas-athrú', 'neamhaird a dhéanamh ar spás-at-eol', 'neamhaird a " +"dhéanamh ar uile-spás', 'ligead-indentation-change'" + +#: diff.c +msgid "" +"color-moved-ws: allow-indentation-change cannot be combined with other " +"whitespace modes" +msgstr "" +"dath-moved-ws: nà féidir athrú ligead-ionchur a chomhcheangal le modhanna " +"spás bán eile" + +#: diff.c +#, c-format +msgid "Unknown value for 'diff.submodule' config variable: '%s'" +msgstr "Luach anaithnid d'athróg cumraithe 'diff.submodule': '%s'" + +#: diff.c merge-ort.c transport.c +#, c-format +msgid "unknown value for config '%s': %s" +msgstr "luach anaithnid do chumraÃocht '%s': %s" + +#: diff.c +#, c-format +msgid "" +"Found errors in 'diff.dirstat' config variable:\n" +"%s" +msgstr "" +"Earráidà aimsithe in athróg config 'diff.dirstat':\n" +"%s" + +#: diff.c +#, c-format +msgid "external diff died, stopping at %s" +msgstr "fuair diff seachtrach bás, ag stopadh ag %s" + +#: diff.c +msgid "--follow requires exactly one pathspec" +msgstr "TeastaÃonn --follow go dÃreach cosán amháin" + +#: diff.c +#, c-format +msgid "pathspec magic not supported by --follow: %s" +msgstr "draÃocht pathspec nach dtacaÃonn --follow: %s" + +#: diff.c parse-options.c +#, c-format +msgid "options '%s', '%s', '%s', and '%s' cannot be used together" +msgstr "nà féidir roghanna '%s', '%s', '%s', agus '%s' a úsáid le chéile" + +#: diff.c +#, c-format +msgid "options '%s' and '%s' cannot be used together, use '%s' with '%s'" +msgstr "" +"nà féidir roghanna '%s' agus '%s' a úsáid le chéile, bain úsáid as '%s' le " +"'%s'" + +#: diff.c +#, c-format +msgid "" +"options '%s' and '%s' cannot be used together, use '%s' with '%s' and '%s'" +msgstr "" +"nà féidir roghanna '%s' agus '%s' a úsáid le chéile, bain úsáid as '%s' le " +"'%s' agus '%s'" + +#: diff.c +#, c-format +msgid "invalid --stat value: %s" +msgstr "luach --stat neamhbhailÃ: %s" + +#: diff.c parse-options.c +#, c-format +msgid "%s expects a numerical value" +msgstr "Tá %s ag súil le luach uimhriúil" + +#: diff.c +#, c-format +msgid "" +"Failed to parse --dirstat/-X option parameter:\n" +"%s" +msgstr "" +"Theip ar pharaiméadar rogha --dirstat/-X a pháirseáil:\n" +"%s" + +#: diff.c +#, c-format +msgid "unknown change class '%c' in --diff-filter=%s" +msgstr "aicme athraithe anaithnid '%c' i --diff-filter=%s" + +#: diff.c +#, c-format +msgid "unknown value after ws-error-highlight=%.*s" +msgstr "luach anaithnid tar éis ws-error-highlight =%.*s" + +#: diff.c +#, c-format +msgid "unable to resolve '%s'" +msgstr "nach féidir '%s' a réiteach" + +#: diff.c +#, c-format +msgid "%s expects <n>/<m> form" +msgstr "Tá %s ag súil le<n>/fo <m>irm" + +#: diff.c +#, c-format +msgid "%s expects a character, got '%s'" +msgstr "Tá %s ag súil le carachtar, fuair '%s'" + +#: diff.c +#, c-format +msgid "bad --color-moved argument: %s" +msgstr "argóint lochtach --color-moved: %s" + +#: diff.c +#, c-format +msgid "invalid mode '%s' in --color-moved-ws" +msgstr "modh neamhbhailà '%s' i --color-moved-ws" + +#: diff.c +#, c-format +msgid "invalid argument to %s" +msgstr "argóint neamhbhailà chuig %s" + +#: diff.c +#, c-format +msgid "invalid regex given to -I: '%s'" +msgstr "regex neamhbhailà a thugtar do -I: '%s'" + +#: diff.c +msgid "-G requires a non-empty argument" +msgstr "ÉilÃonn -G argóint neamh-folamh" + +#: diff.c +msgid "-S requires a non-empty argument" +msgstr "ÉilÃonn -S argóint neamh-folamh" + +#: diff.c +#, c-format +msgid "failed to parse --submodule option parameter: '%s'" +msgstr "theip ar pharaiméadar rogha --submodule a pháirseáil: '%s'" + +#: diff.c +#, c-format +msgid "bad --word-diff argument: %s" +msgstr "argóint olc --word-diff: %s" + +#: diff.c +msgid "Diff output format options" +msgstr "Roghanna formáid aschuir diff" + +#: diff.c +msgid "generate patch" +msgstr "paiste a ghiniúint" + +#: diff.c +msgid "<n>" +msgstr "<n>" + +#: diff.c +msgid "generate diffs with <n> lines context" +msgstr "difrÃochtaà a ghiniúint le comhthéacs <n>lÃn" + +#: diff.c +msgid "generate the diff in raw format" +msgstr "giniúint an diff i bhformáid amh" + +#: diff.c +msgid "synonym for '-p --raw'" +msgstr "comhchiallach do '-p --raw'" + +#: diff.c +msgid "synonym for '-p --stat'" +msgstr "comhchiallach do '-p --stat'" + +#: diff.c +msgid "machine friendly --stat" +msgstr "cairdiúil le meaisÃn --stat" + +#: diff.c +msgid "output only the last line of --stat" +msgstr "aschur ach an lÃne dheireanach de --stat" + +#: diff.c +msgid "<param1>,<param2>..." +msgstr "<param1>,<param2>..." + +#: diff.c +msgid "" +"output the distribution of relative amount of changes for each sub-directory" +msgstr "aschur dáileadh méid coibhneasta na n-athruithe do gach fo-eolaire" + +#: diff.c +msgid "synonym for --dirstat=cumulative" +msgstr "comhchiallach do --dirstat=cumulative" + +#: diff.c +msgid "synonym for --dirstat=files,<param1>,<param2>..." +msgstr "comhchiallaigh le haghaidh --dirstat=files,<param1>,<param2>..." + +#: diff.c +msgid "warn if changes introduce conflict markers or whitespace errors" +msgstr "" +"rabhadh má thugann athruithe marcóirà coinbhleachta nó earráidà spás bán " +"isteach" + +#: diff.c +msgid "condensed summary such as creations, renames and mode changes" +msgstr "" +"achoimre chomhdhlúite mar chruthúcháin, athainmneacha agus athruithe mó" + +#: diff.c +msgid "show only names of changed files" +msgstr "taispeáint ach ainmneacha comhaid athraithe" + +#: diff.c +msgid "show only names and status of changed files" +msgstr "taispeáint ach ainmneacha agus stádas na gcomhaid athraithe" + +#: diff.c +msgid "<width>[,<name-width>[,<count>]]" +msgstr "<width>[, <name-width>[,<count>]]" + +#: diff.c +msgid "generate diffstat" +msgstr "diffstat a ghiniúint" + +#: diff.c +msgid "<width>" +msgstr "<width>" + +#: diff.c +msgid "generate diffstat with a given width" +msgstr "diffstat a ghiniúint le leithead ar leith" + +#: diff.c +msgid "generate diffstat with a given name width" +msgstr "diffstat a ghiniúint le leithead ainm ar leith" + +#: diff.c +msgid "generate diffstat with a given graph width" +msgstr "diffstat a ghiniúint le leithead graf ar leith" + +#: diff.c +msgid "<count>" +msgstr "<count>" + +#: diff.c +msgid "generate diffstat with limited lines" +msgstr "diffstat a ghiniúint le lÃnte teoranta" + +#: diff.c +msgid "generate compact summary in diffstat" +msgstr "achoimre dlúth a ghiniúint i diffstat" + +#: diff.c +msgid "output a binary diff that can be applied" +msgstr "aschur diff dénártha is féidir a chur i bhfeidhm" + +#: diff.c +msgid "show full pre- and post-image object names on the \"index\" lines" +msgstr "" +"taispeáint ainmneacha réad réad réamh-Ãomhá iomlána ar na lÃnte “innéacsâ€" + +#: diff.c +msgid "show colored diff" +msgstr "taispeáin éagsúlacht daite" + +#: diff.c +msgid "<kind>" +msgstr "<kind>" + +#: diff.c +msgid "" +"highlight whitespace errors in the 'context', 'old' or 'new' lines in the " +"diff" +msgstr "" +"aird a tharraingt ar earráidà spás bán sna lÃnte 'comhthéacs', 'sean' nó " +"'nua' sa diff" + +#: diff.c +msgid "" +"do not munge pathnames and use NULs as output field terminators in --raw or " +"--numstat" +msgstr "" +"ná cuir ainmneacha cosáin agus bain úsáid as NULanna mar chrÃochnóirà réimse " +"aschuir i --raw nó --numstat" + +#: diff.c +msgid "<prefix>" +msgstr "<prefix>" + +#: diff.c +msgid "show the given source prefix instead of \"a/\"" +msgstr "taispeáint an réimÃr foinse a thugtar in ionad “a/â€" + +#: diff.c +msgid "show the given destination prefix instead of \"b/\"" +msgstr "taispeáin an réimÃr ceann scrÃbe tugtha in ionad “b/â€" + +#: diff.c +msgid "prepend an additional prefix to every line of output" +msgstr "réimÃr bhreise a chur ar fáil do gach lÃne aschuir" + +#: diff.c +msgid "do not show any source or destination prefix" +msgstr "ná taispeáin aon réimÃr foinse nó ceann scrÃbe" + +#: diff.c +msgid "use default prefixes a/ and b/" +msgstr "bain úsáid as réamhshocraithe a/ agus b/" + +#: diff.c +msgid "show context between diff hunks up to the specified number of lines" +msgstr "" +"comhthéacs a thaispeáint idir diff hunks suas go dtà an lÃon sonraithe lÃnte" + +#: diff.c +msgid "<char>" +msgstr "<char>" + +#: diff.c +msgid "specify the character to indicate a new line instead of '+'" +msgstr "sonraigh an carachtar chun lÃne nua a léiriú in ionad '+'" + +#: diff.c +msgid "specify the character to indicate an old line instead of '-'" +msgstr "sonraigh an carachtar chun sean-lÃne a chur in iúl in ionad '-'" + +#: diff.c +msgid "specify the character to indicate a context instead of ' '" +msgstr "sonraigh an carachtar chun comhthéacs in ionad '' a chur in iúl" + +#: diff.c +msgid "Diff rename options" +msgstr "Roghanna athainmnithe Diff" + +#: diff.c +msgid "<n>[/<m>]" +msgstr "<n>[/<m>]" + +#: diff.c +msgid "break complete rewrite changes into pairs of delete and create" +msgstr "" +"athruithe iomlána athscrÃobh a bhriseadh i bpéirà scrios agus cruthaigh" + +#: diff.c +msgid "detect renames" +msgstr "athainmneacha a bhrath" + +#: diff.c +msgid "omit the preimage for deletes" +msgstr "fág an réamhÃomhá le haghaidh scriosadh" + +#: diff.c +msgid "detect copies" +msgstr "cóipà a bhrath" + +#: diff.c +msgid "use unmodified files as source to find copies" +msgstr "úsáid comhaid neamh-mhodhnaithe mar fhoinse chun cóipeanna a fháil" + +#: diff.c +msgid "disable rename detection" +msgstr "dÃchumasaigh braite athainmnithe" + +#: diff.c +msgid "use empty blobs as rename source" +msgstr "bain úsáid as blobs folamh mar fhoinse athainmnithe" + +#: diff.c +msgid "continue listing the history of a file beyond renames" +msgstr "leanúint ar aghaidh ag liostáil stair chomhaid thar athainmneacha" + +#: diff.c +msgid "" +"prevent rename/copy detection if the number of rename/copy targets exceeds " +"given limit" +msgstr "" +"cosc a chur ar athainmniú/braite cóipeála má sháraÃonn lÃon na spriocanna " +"athainmniúcháin/cóipeála" + +#: diff.c +msgid "Diff algorithm options" +msgstr "Roghanna algartam Diff" + +#: diff.c +msgid "produce the smallest possible diff" +msgstr "an difrÃocht is lú is féidir a tháirgeadh" + +#: diff.c +msgid "ignore whitespace when comparing lines" +msgstr "neamhaird a dhéanamh ar spás bán agus tú ag comparáid" + +#: diff.c +msgid "ignore changes in amount of whitespace" +msgstr "neamhaird a dhéanamh ar athruithe i méid an spás bán" + +#: diff.c +msgid "ignore changes in whitespace at EOL" +msgstr "neamhaird a dhéanamh ar athruithe i spás bán ag EOL" + +#: diff.c +msgid "ignore carrier-return at the end of line" +msgstr "neamhaird a dhéanamh ar thuairisceán iompróra ag deireadh na lÃne" + +#: diff.c +msgid "ignore changes whose lines are all blank" +msgstr "neamhaird a dhéanamh ar athruithe atá a lÃnte bán" + +#: diff.c +msgid "<regex>" +msgstr "<regex>" + +#: diff.c +msgid "ignore changes whose all lines match <regex>" +msgstr "neamhaird a dhéanamh ar athruithe a mheaitseann <regex>" + +#: diff.c +msgid "heuristic to shift diff hunk boundaries for easy reading" +msgstr "heuristic chun teorainneacha éagsúla a aistriú le haghaidh léamh éasca" + +#: diff.c +msgid "generate diff using the \"patience diff\" algorithm" +msgstr "diff a ghiniúint ag baint úsáide as an algartam “diff foighneâ€" + +#: diff.c +msgid "generate diff using the \"histogram diff\" algorithm" +msgstr "diff a ghiniúint ag baint úsáide as an algartam “diff histogramâ€" + +#: diff.c +msgid "<text>" +msgstr "<text>" + +#: diff.c +msgid "generate diff using the \"anchored diff\" algorithm" +msgstr "diff a ghiniúint ag baint úsáide as an algartam “diff ancáraitheâ€" + +#: diff.c +msgid "<mode>" +msgstr "<mode>" + +#: diff.c +msgid "show word diff, using <mode> to delimit changed words" +msgstr "" +"taispeáint diff focal, ag baint úsáide as focail <mode>athraithe a theorannú" + +#: diff.c +msgid "use <regex> to decide what a word is" +msgstr "bain úsáid <regex>as chun cinneadh a dhéanamh cad é focal" + +#: diff.c +msgid "equivalent to --word-diff=color --word-diff-regex=<regex>" +msgstr "coibhéiseach le --word-diff=color --word-diff-regex=<regex>" + +#: diff.c +msgid "moved lines of code are colored differently" +msgstr "tá lÃnte cóid bogadh daite difriúil" + +#: diff.c +msgid "how white spaces are ignored in --color-moved" +msgstr "conas a dhéantar neamhaird de spásanna bána i --color-moved" + +#: diff.c +msgid "Other diff options" +msgstr "Roghanna diff eile" + +#: diff.c +msgid "when run from subdir, exclude changes outside and show relative paths" +msgstr "" +"nuair a bheidh á rith ó subdir, eisiamh athruithe lasmuigh agus taispeáin " +"coibhneasta" + +#: diff.c +msgid "treat all files as text" +msgstr "déileáil le gach comhad mar théacs" + +#: diff.c +msgid "swap two inputs, reverse the diff" +msgstr "dhá ionchur a mhalartú, an diff a aisiompú" + +#: diff.c +msgid "exit with 1 if there were differences, 0 otherwise" +msgstr "imeacht le 1 má bhà difrÃochtaà ann, 0 ar shlà eile" + +#: diff.c +msgid "disable all output of the program" +msgstr "dÃchumasú gach aschur an chláir" + +#: diff.c +msgid "allow an external diff helper to be executed" +msgstr "ligean do chúntóir diff seachtrach a fhorghnÃomhú" + +#: diff.c +msgid "run external text conversion filters when comparing binary files" +msgstr "reáchtáil scagairà tiontaithe téacs seachtracha agus comhaid" + +#: diff.c +msgid "<when>" +msgstr "<when>" + +#: diff.c +msgid "ignore changes to submodules in the diff generation" +msgstr "neamhaird a dhéanamh ar athruithe ar fho-mhodúil sa ghiniúint diff" + +#: diff.c +msgid "<format>" +msgstr "<format>" + +#: diff.c +msgid "specify how differences in submodules are shown" +msgstr "sonraigh conas a thaispeántar na difrÃochtaà i bhfo-" + +#: diff.c +msgid "hide 'git add -N' entries from the index" +msgstr "folaigh iontrálacha 'git add -N' ón innéacs" + +#: diff.c +msgid "treat 'git add -N' entries as real in the index" +msgstr "déileáil le hiontrálacha 'git add -N' mar atá fÃor san innéacs" + +#: diff.c +msgid "<string>" +msgstr "<string>" + +#: diff.c +msgid "" +"look for differences that change the number of occurrences of the specified " +"string" +msgstr "" +"cuardaigh difrÃochtaà a athraÃonn lÃon na n-imeachtaà sa sreang sonraithe" + +#: diff.c +msgid "" +"look for differences that change the number of occurrences of the specified " +"regex" +msgstr "" +"cuardaigh difrÃochtaà a athraÃonn lÃon na n-imeachtaà sa regex sonraithe" + +#: diff.c +msgid "show all changes in the changeset with -S or -G" +msgstr "taispeáint na hathruithe go léir sa tacar athraithe le -S nó -G" + +#: diff.c +msgid "treat <string> in -S as extended POSIX regular expression" +msgstr "caitheamh <string>le -S mar léiriú rialta POSIX leathnaithe" + +#: diff.c +msgid "control the order in which files appear in the output" +msgstr "rialú an t-ord ina bhfuil comhaid le feiceáil san aschur" + +#: diff.c +msgid "<path>" +msgstr "<path>" + +#: diff.c +msgid "show the change in the specified path first" +msgstr "taispeáin an t-athrú ar an gcosán sonraithe ar dtús" + +#: diff.c +msgid "skip the output to the specified path" +msgstr "scipeáil an t-aschur chuig an gcosán sonraithe" + +#: diff.c +msgid "<object-id>" +msgstr "<object-id>" + +#: diff.c +msgid "" +"look for differences that change the number of occurrences of the specified " +"object" +msgstr "cuardaigh difrÃochtaà a athraÃonn lÃon na n-earraà den réad sonraithe" + +#: diff.c +msgid "[(A|C|D|M|R|T|U|X|B)...[*]]" +msgstr "[(A|C|D|M|R|T|U|X|B)... [*]]" + +#: diff.c +msgid "select files by diff type" +msgstr "roghnaigh comhaid de réir cineál diff" + +#: diff.c +msgid "<file>" +msgstr "<file>" + +#: diff.c +msgid "output to a specific file" +msgstr "aschur chuig comhad ar leith" + +#: diff.c +msgid "exhaustive rename detection was skipped due to too many files." +msgstr "" +"scipeánadh braite athainmnithe uileghabhálach mar gheall ar an iomarca " +"comhaid." + +#: diff.c +msgid "only found copies from modified paths due to too many files." +msgstr "" +"nà bhfuarthas ach cóipeanna ó chosáin modhnaithe mar gheall ar an iomarca " +"comhaid." + +#: diff.c +#, c-format +msgid "" +"you may want to set your %s variable to at least %d and retry the command." +msgstr "" +"b'fhéidir gur mhaith leat d'athróg %s a shocrú go %d ar a laghad agus " +"iarracht a dhéanamh arÃs ar an ordú." + +#: diffcore-order.c +#, c-format +msgid "failed to read orderfile '%s'" +msgstr "theip ar chomhad ordaithe '%s' a léamh" + +#: diffcore-rename.c +msgid "Performing inexact rename detection" +msgstr "Braite athainmnithe mÃchruinn a dhéanamh" + +#: diffcore-rotate.c +#, c-format +msgid "No such path '%s' in the diff" +msgstr "NÃl aon chosán den sórt sin '%s' sa diff" + +#: dir.c +#, c-format +msgid "pathspec '%s' did not match any file(s) known to git" +msgstr "nÃor mheaitseáil pathspec '%s' aon chomhad (Ã) ar eolas ag git" + +#: dir.c +#, c-format +msgid "unrecognized pattern: '%s'" +msgstr "patrún gan aithint: '%s'" + +#: dir.c +#, c-format +msgid "unrecognized negative pattern: '%s'" +msgstr "patrún diúltach gan aithint: '%s'" + +#: dir.c +#, c-format +msgid "your sparse-checkout file may have issues: pattern '%s' is repeated" +msgstr "" +"d'fhéadfadh fadhbanna a bheith ag do chomhad seiceála neamhchoitianta: " +"déantar patrún '%s' arÃs eile" + +#: dir.c +msgid "disabling cone pattern matching" +msgstr "meaitseáil patrún cón a dhÃchumas" + +#: dir.c +#, c-format +msgid "cannot use %s as an exclude file" +msgstr "nà féidir %s a úsáid mar chomhad eisiata" + +#: dir.c +msgid "failed to get kernel name and information" +msgstr "theip ar ainm eithne agus faisnéis a fháil" + +#: dir.c +msgid "untracked cache is disabled on this system or location" +msgstr "" +"tá taisce neamhrianaithe dÃchumasaithe ar an gcóras nó ar an suÃomh seo" + +#: dir.c +msgid "" +"No directory name could be guessed.\n" +"Please specify a directory on the command line" +msgstr "" +"Nà fhéadfaà aon ainm eolaire a thuairim.\n" +"Sonraigh eolaire ar an lÃne ordaithe le do thoil" + +#: dir.c +#, c-format +msgid "index file corrupt in repo %s" +msgstr "comhad innéacs truaillithe i repo %s" + +#: dir.c +#, c-format +msgid "could not create directories for %s" +msgstr "nà fhéadfaà eolairà a chruthú do %s" + +#: dir.c +#, c-format +msgid "could not migrate git directory from '%s' to '%s'" +msgstr "nà fhéadfaà eolaire git a aistriú ó '%s' go '%s'" + +#: editor.c +#, c-format +msgid "hint: Waiting for your editor to close the file...%c" +msgstr "leid: Ag fanacht go ndúnfaidh d'eagarthóir an comhad... %c" + +#: editor.c sequencer.c wrapper.c +#, c-format +msgid "could not write to '%s'" +msgstr "nà fhéadfaà scrÃobh chuig '%s'" + +#: editor.c +#, c-format +msgid "could not edit '%s'" +msgstr "nà fhéadfaà '%s' a chur in eagar" + +#: entry.c +msgid "Filtering content" +msgstr "Ãbhar scagadh" + +#: entry.c +#, c-format +msgid "could not stat file '%s'" +msgstr "nà fhéadfaà an comhad '%s' a statú" + +#: environment.c +#, c-format +msgid "bad git namespace path \"%s\"" +msgstr "cosán spás ainmneacha git go dona “%sâ€" + +#: exec-cmd.c +#, c-format +msgid "too many args to run %s" +msgstr "an iomarca args chun %s a rith" + +#: fetch-pack.c +#, c-format +msgid "" +"You are attempting to fetch %s, which is in the commit graph file but not in " +"the object database.\n" +"This is probably due to repo corruption.\n" +"If you are attempting to repair this repo corruption by refetching the " +"missing object, use 'git fetch --refetch' with the missing object." +msgstr "" +"Tá tú ag iarraidh %s a fháil, atá sa chomhad graf tiomanta ach nach bhfuil " +"sa bhunachar sonraà réada.\n" +"Is dócha go bhfuil sé seo mar gheall ar éilliú repo.\n" +"Má tá tú ag iarraidh an éilliú repo seo a dheisiú trÃd an réad atá in " +"easnamh a athghabháil, bain úsáid as 'git fetch --refetch' leis an réad atá " +"ar iarraidh." + +#: fetch-pack.c +msgid "git fetch-pack: expected shallow list" +msgstr "git fetch-pack: liosta éadomhain a bhfuiltear ag súil leis" + +#: fetch-pack.c +msgid "git fetch-pack: expected a flush packet after shallow list" +msgstr "" +"git fetch-pack: bhÃothas ag súil le paicéad sruthán tar éis liosta éadrom" + +#: fetch-pack.c +msgid "git fetch-pack: expected ACK/NAK, got a flush packet" +msgstr "git fetch-pack: ag súil le ACK/NAK, fuair sé paicéad sruthán" + +#: fetch-pack.c +#, c-format +msgid "git fetch-pack: expected ACK/NAK, got '%s'" +msgstr "git fetch-pack: ag súil le ACK/NAK, fuair '%s'" + +#: fetch-pack.c +msgid "unable to write to remote" +msgstr "in ann scrÃobh chuig iargúlta" + +#: fetch-pack.c +msgid "Server supports filter" +msgstr "TacaÃonn freastalaà le sc" + +#: fetch-pack.c +#, c-format +msgid "invalid shallow line: %s" +msgstr "lÃne éadomhain neamhbhailÃ: %s" + +#: fetch-pack.c +#, c-format +msgid "invalid unshallow line: %s" +msgstr "lÃne neamhéadrom neamhbhailÃ: %s" + +#: fetch-pack.c +#, c-format +msgid "object not found: %s" +msgstr "nÃor aimsÃodh réad: %s" + +#: fetch-pack.c +#, c-format +msgid "error in object: %s" +msgstr "earráid i réad: %s" + +#: fetch-pack.c +#, c-format +msgid "no shallow found: %s" +msgstr "nÃl aon éadrom aimsithe: %s" + +#: fetch-pack.c +#, c-format +msgid "expected shallow/unshallow, got %s" +msgstr "bhÃothas ag súil leis Ãol/neamhéadrom, fuair %s" + +#: fetch-pack.c +#, c-format +msgid "got %s %d %s" +msgstr "fuair %s %d %s" + +#: fetch-pack.c +#, c-format +msgid "invalid commit %s" +msgstr "tiomantas neamhbhailà %s" + +#: fetch-pack.c +msgid "giving up" +msgstr "tabhairt suas" + +#: fetch-pack.c progress.h +msgid "done" +msgstr "déanta" + +#: fetch-pack.c +#, c-format +msgid "got %s (%d) %s" +msgstr "fuair %s (%d) %s" + +#: fetch-pack.c +#, c-format +msgid "Marking %s as complete" +msgstr "Mharcáil %s mar iomlán" + +#: fetch-pack.c +#, c-format +msgid "already have %s (%s)" +msgstr "tá %s ann cheana féin (%s)" + +#: fetch-pack.c +msgid "fetch-pack: unable to fork off sideband demultiplexer" +msgstr "pacáiste tarchuir: nà féidir le démultiplexer banna taobh a fhorc" + +#: fetch-pack.c +msgid "protocol error: bad pack header" +msgstr "earráid prótacal: ceanntásc an phacá" + +#: fetch-pack.c +#, c-format +msgid "fetch-pack: unable to fork off %s" +msgstr "fetch-pack: nà féidir %s a fhorc" + +#: fetch-pack.c +msgid "fetch-pack: invalid index-pack output" +msgstr "fetch-pack: aschur pacáiste innéacs-neamhbhailÃ" + +#: fetch-pack.c +#, c-format +msgid "%s failed" +msgstr "Theip ar %s" + +#: fetch-pack.c +msgid "error in sideband demultiplexer" +msgstr "earráid i demultiplexer taobhbanna" + +#: fetch-pack.c +#, c-format +msgid "Server version is %.*s" +msgstr "Is é leagan freastalaà %.*s" + +#: fetch-pack.c +#, c-format +msgid "Server supports %s" +msgstr "TacaÃonn freastalaà le %s" + +#: fetch-pack.c +msgid "Server does not support shallow clients" +msgstr "Nà thacaÃonn freastalaà le cliaint éadrom" + +#: fetch-pack.c +msgid "Server does not support --shallow-since" +msgstr "Nà thacaÃonn freastalaà le --shallow-since" + +#: fetch-pack.c +msgid "Server does not support --shallow-exclude" +msgstr "Nà thacaÃonn freastalaà le --shallow-exclude" + +#: fetch-pack.c +msgid "Server does not support --deepen" +msgstr "Nà thacaÃonn freastalaà le --deepen" + +#: fetch-pack.c +msgid "Server does not support this repository's object format" +msgstr "Nà thacaÃonn freastalaà le formáid réad an stór seo" + +#: fetch-pack.c +msgid "no common commits" +msgstr "gan aon gealltanais choiteann" + +#: fetch-pack.c +msgid "git fetch-pack: fetch failed." +msgstr "git fetch-pack: theip ar fáil." + +#: fetch-pack.c +#, c-format +msgid "mismatched algorithms: client %s; server %s" +msgstr "halgartaim mÃchomhoiriúnach: cliant %s; freastalaà %s" + +#: fetch-pack.c +#, c-format +msgid "the server does not support algorithm '%s'" +msgstr "nà thacaÃonn an freastalaà algartam '%s'" + +#: fetch-pack.c +msgid "Server does not support shallow requests" +msgstr "Nà thacaÃonn an freastalaà le hiarratais" + +#: fetch-pack.c +msgid "unable to write request to remote" +msgstr "in ann iarratas a scrÃobh chuig iargúlta" + +#: fetch-pack.c +#, c-format +msgid "expected '%s', received '%s'" +msgstr "bhÃothas ag súil le '%s', fuarthas '%s'" + +#: fetch-pack.c +#, c-format +msgid "expected '%s'" +msgstr "ag súil le '%s'" + +#: fetch-pack.c +#, c-format +msgid "unexpected acknowledgment line: '%s'" +msgstr "lÃne admhaithe gan choinne: '%s'" + +#: fetch-pack.c +#, c-format +msgid "error processing acks: %d" +msgstr "earráidà próiseála earráide: %d" + +#. TRANSLATORS: The parameter will be 'ready', a protocol +#. keyword. +#. +#: fetch-pack.c +#, c-format +msgid "expected packfile to be sent after '%s'" +msgstr "táthar ag súil go seolfar pacáid tar éis '%s'" + +#. TRANSLATORS: The parameter will be 'ready', a protocol +#. keyword. +#. +#: fetch-pack.c +#, c-format +msgid "expected no other sections to be sent after no '%s'" +msgstr "" +"bhÃothas ag súil nach gcuirfear aon chuid eile a sheoladh tar éis gan '%s'" + +#: fetch-pack.c +#, c-format +msgid "error processing shallow info: %d" +msgstr "earráid ag próiseáil faisnéis éadrom: %d" + +#: fetch-pack.c +#, c-format +msgid "expected wanted-ref, got '%s'" +msgstr "bhÃothas ag súil leis an tagairt a theastaigh, fuair '%s'" + +#: fetch-pack.c +#, c-format +msgid "unexpected wanted-ref: '%s'" +msgstr "gan choinne wanted-ref: '%s'" + +#: fetch-pack.c +#, c-format +msgid "error processing wanted refs: %d" +msgstr "próiseáil earráidà a theastaÃonn referens: %d" + +#: fetch-pack.c +msgid "git fetch-pack: expected response end packet" +msgstr "git fetch-pack: paicéad deiridh freagartha ag súil leis" + +#: fetch-pack.c +msgid "no matching remote head" +msgstr "gan ceann iargúlta meaitseála" + +#: fetch-pack.c +msgid "unexpected 'ready' from remote" +msgstr "gan choinne 'réidh' ó iargúlta" + +#: fetch-pack.c +#, c-format +msgid "no such remote ref %s" +msgstr "aon tagairt iargúlta den sórt sin %s" + +#: fetch-pack.c +#, c-format +msgid "Server does not allow request for unadvertised object %s" +msgstr "Nà cheadaÃonn freastalaà iarraidh ar réad neamhfhógraithe %s" + +#: fsmonitor-ipc.c +#, c-format +msgid "fsmonitor_ipc__send_query: invalid path '%s'" +msgstr "fsmonitor_ipc__send_query: cosán neamhbhailà '%s'" + +#: fsmonitor-ipc.c +#, c-format +msgid "fsmonitor_ipc__send_query: unspecified error on '%s'" +msgstr "fsmonitor_ipc__send_query: earráid neamhshonraithe ar '%s'" + +#: fsmonitor-ipc.c +msgid "fsmonitor--daemon is not running" +msgstr "nÃl fsmonitor--daemon ag rith" + +#: fsmonitor-ipc.c +#, c-format +msgid "could not send '%s' command to fsmonitor--daemon" +msgstr "nà fhéadfaà ordú '%s' a sheoladh chuig fsmonitor--daemon" + +#: fsmonitor-settings.c +#, c-format +msgid "bare repository '%s' is incompatible with fsmonitor" +msgstr "nÃl stór lom '%s' neamhoiriúnach le fsmonitor" + +#: fsmonitor-settings.c +#, c-format +msgid "repository '%s' is incompatible with fsmonitor due to errors" +msgstr "tá stór '%s' neamh-chomhoiriúnach le fsmonitor de bharr earráidÃ" + +#: fsmonitor-settings.c +#, c-format +msgid "remote repository '%s' is incompatible with fsmonitor" +msgstr "nÃl stór iargúlta '%s' neamhoiriúnach le fsmonitor" + +#: fsmonitor-settings.c +#, c-format +msgid "virtual repository '%s' is incompatible with fsmonitor" +msgstr "nÃl stór fÃorúil '%s' neamhoiriúnach le fsmonitor" + +#: fsmonitor-settings.c +#, c-format +msgid "" +"socket directory '%s' is incompatible with fsmonitor due to lack of Unix " +"sockets support" +msgstr "" +"tá eolaire soicéad '%s' neamhoiriúnach le fsmonitor mar gheall ar easpa " +"tacaÃochta soicéid Unix" + +#: git.c +msgid "" +"git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" +" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" +msgstr "" +"git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n" +" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" +"lazy-fetch]\n" +" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" +" [--work-tree=<path>] [--namespace=<name>] [--config-" +"env=<name>=<envvar>]\n" +" <command> [<args>]" + +#: git.c +msgid "" +"'git help -a' and 'git help -g' list available subcommands and some\n" +"concept guides. See 'git help <command>' or 'git help <concept>'\n" +"to read about a specific subcommand or concept.\n" +"See 'git help git' for an overview of the system." +msgstr "" +"LiostaÃonn 'git help -a' agus 'git help -g' fo-orduithe atá ar fáil agus " +"roinnt\n" +"treoracha coincheap. <concept>Féach 'git cabhr <command>'nó 'git cabhr'\n" +"léamh faoi fho-ordú nó coincheap ar leith.\n" +"Féach 'git help git' le haghaidh forbhreathnú ar an gcóras." + +#: git.c help.c +#, c-format +msgid "unsupported command listing type '%s'" +msgstr "cineál liostaithe ordaithe gan tacaÃocht '%s'" + +#: git.c +#, c-format +msgid "no directory given for '%s' option\n" +msgstr "nÃl aon eolaire tugtha do rogha '%s'\n" + +#: git.c +#, c-format +msgid "no namespace given for --namespace\n" +msgstr "aon spás ainmneacha a thugtar do --namespace\n" + +#: git.c +#, c-format +msgid "-c expects a configuration string\n" +msgstr "-c ag súil le teaghrán cumraÃochta\n" + +#: git.c +#, c-format +msgid "no config key given for --config-env\n" +msgstr "nÃl aon eochair chumraithe tugtha do --config-env\n" + +#: git.c +#, c-format +msgid "no attribute source given for --attr-source\n" +msgstr "nÃor tugadh foinse tréith do --attr-source\n" + +#: git.c +#, c-format +msgid "unknown option: %s\n" +msgstr "rogha anaithnid: %s\n" + +#: git.c +#, c-format +msgid "while expanding alias '%s': '%s'" +msgstr "agus ainm '%s' á leathnú: '%s'" + +#: git.c +#, c-format +msgid "" +"alias '%s' changes environment variables.\n" +"You can use '!git' in the alias to do this" +msgstr "" +"athraÃonn alias '%s' athróga comhshaoil.\n" +"Is féidir leat úsáid a bhaint as '!git' san alias chun é seo a dhéanamh" + +#: git.c +#, c-format +msgid "empty alias for %s" +msgstr "alias folamh do %s" + +#: git.c +#, c-format +msgid "recursive alias: %s" +msgstr "ainm athfhillteach: %s" + +#: git.c +msgid "write failure on standard output" +msgstr "teip scrÃobh ar aschur caighdeánach" + +#: git.c +msgid "unknown write failure on standard output" +msgstr "teip scrÃbhneoireachta anaithnid ar aschur" + +#: git.c +msgid "close failed on standard output" +msgstr "theip ar dhún ar aschur caighdeánach" + +#: git.c +#, c-format +msgid "alias loop detected: expansion of '%s' does not terminate:%s" +msgstr "aimsÃodh lúb alias: nà chuirtear deireadh le leathnú '%s': %s" + +#: git.c +#, c-format +msgid "cannot handle %s as a builtin" +msgstr "nà féidir %s a láimhseáil mar thógáil" + +#: git.c +#, c-format +msgid "" +"usage: %s\n" +"\n" +msgstr "" +"úsáid: %s\n" +"\n" + +#: git.c +#, c-format +msgid "expansion of alias '%s' failed; '%s' is not a git command\n" +msgstr "theip ar leathnú an leasainm '%s'; nà ordú git é '%s'\n" + +#: git.c +#, c-format +msgid "failed to run command '%s': %s\n" +msgstr "theip ort an t-ordú '%s' a reáchtáil: %s\n" + +#: gpg-interface.c +msgid "could not create temporary file" +msgstr "nà fhéadfaà comhad sealadach a chruthú" + +#: gpg-interface.c +#, c-format +msgid "failed writing detached signature to '%s'" +msgstr "theip ar shÃniú scoite a scrÃobh chuig '%s'" + +#: gpg-interface.c +msgid "" +"gpg.ssh.allowedSignersFile needs to be configured and exist for ssh " +"signature verification" +msgstr "" +"nà mór gpg.ssh.allowedSignersFile a chumrú agus a bheith ann le haghaidh " +"fÃorú sÃnithe ssh" + +#: gpg-interface.c +msgid "" +"ssh-keygen -Y find-principals/verify is needed for ssh signature " +"verification (available in openssh version 8.2p1+)" +msgstr "" +"tá gá le ssh-keygen -Y aimsithe/fÃorú le haghaidh fÃorú sÃnithe ssh (ar fáil " +"i leagan openssh 8.2p1 +)" + +#: gpg-interface.c +#, c-format +msgid "ssh signing revocation file configured but not found: %s" +msgstr "comhad cúlghairm sÃnithe ssh cumraithe ach nÃor aimsÃodh: %s" + +#: gpg-interface.c +#, c-format +msgid "bad/incompatible signature '%s'" +msgstr "sÃniú droch-/neamhchomhoiriúnach '%s'" + +#: gpg-interface.c +#, c-format +msgid "failed to get the ssh fingerprint for key '%s'" +msgstr "theip ar mhéarloirg ssh a fháil don eochair '%s'" + +#: gpg-interface.c +msgid "" +"either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured" +msgstr "is gá user.signingkey nó gpg.ssh.defaultKeyCommand a chumrú" + +#: gpg-interface.c +#, c-format +msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s" +msgstr "" +"d’éirigh le gpg.ssh.defaultKeyCommand ach nÃor tugadh aon eochracha ar ais: " +"%s %s" + +#: gpg-interface.c +#, c-format +msgid "gpg.ssh.defaultKeyCommand failed: %s %s" +msgstr "theip ar gpg.ssh.defaultKeyCommand: %s %s" + +#: gpg-interface.c +#, c-format +msgid "" +"gpg failed to sign the data:\n" +"%s" +msgstr "" +"theip ar gpg na sonraà a shÃniú:\n" +"%s" + +#: gpg-interface.c +msgid "user.signingKey needs to be set for ssh signing" +msgstr "nà mór user.signingKey a shocrú le haghaidh sÃniú ssh" + +#: gpg-interface.c +#, c-format +msgid "failed writing ssh signing key to '%s'" +msgstr "theip ar an eochair sÃnithe ssh a scrÃobh chuig '%s'" + +#: gpg-interface.c +#, c-format +msgid "failed writing ssh signing key buffer to '%s'" +msgstr "theip ar scrÃobh ssh a shÃniú maolán eochair chuig '%s'" + +#: gpg-interface.c +msgid "" +"ssh-keygen -Y sign is needed for ssh signing (available in openssh version " +"8.2p1+)" +msgstr "" +"ssh-keygen -Y comhartha ag teastáil le haghaidh sÃniú ssh (ar fáil i leagan " +"openssh 8.2p1+)" + +#: gpg-interface.c +#, c-format +msgid "failed reading ssh signing data buffer from '%s'" +msgstr "theip ar mhaolán sonraà sÃnithe ssh a léamh ó '%s'" + +#: graph.c +#, c-format +msgid "ignored invalid color '%.*s' in log.graphColors" +msgstr "neamhaird ar dhath neamhbhailà '%.*s' i log.graphColors" + +#: grep.c +msgid "" +"given pattern contains NULL byte (via -f <file>). This is only supported " +"with -P under PCRE v2" +msgstr "" +"tá byte NULL (trà -f<file>) i bpatrún tugtha. Nà thacaÃtear leis seo ach le " +"-P faoi PCRE v2" + +#: grep.c +#, c-format +msgid "'%s': unable to read %s" +msgstr "'%s': nà féidir %s a léamh" + +#: grep.c +#, c-format +msgid "'%s': short read" +msgstr "'%s': léamh gearr" + +#: help.c +msgid "start a working area (see also: git help tutorial)" +msgstr "tús a chur le limistéar oibre (féach freisin: teagaisc cabhrach git)" + +#: help.c +msgid "work on the current change (see also: git help everyday)" +msgstr "obair ar an athrú reatha (féach freisin: git help gach lá)" + +#: help.c +msgid "examine the history and state (see also: git help revisions)" +msgstr "" +"scrúdú a dhéanamh ar an stair agus an stát (féach freisin: athbhreithnithe " +"cabhrach git)" + +#: help.c +msgid "grow, mark and tweak your common history" +msgstr "do stair choiteann a fhás, a mharcáil agus a athrú" + +#: help.c +msgid "collaborate (see also: git help workflows)" +msgstr "comhoibriú (féach freisin: sreafaà oibre cabhrach git)" + +#: help.c +msgid "Main Porcelain Commands" +msgstr "PrÃomh-Orduithe Poirce" + +#: help.c +msgid "Ancillary Commands / Manipulators" +msgstr "Orduithe Coimhdeachta/IonramhálaÃ" + +#: help.c +msgid "Ancillary Commands / Interrogators" +msgstr "Orduithe Coimhdeacha/CeisteoirÃ" + +#: help.c +msgid "Interacting with Others" +msgstr "IdirghnÃomhú le daoine eile" + +#: help.c +msgid "Low-level Commands / Manipulators" +msgstr "Orduithe Ãsealleibhéil/Ionramhálaithe" + +#: help.c +msgid "Low-level Commands / Interrogators" +msgstr "Orduithe Ãsealleibhéil/ceisteoirÃ" + +#: help.c +msgid "Low-level Commands / Syncing Repositories" +msgstr "Orduithe Leibhéal Ãseal/Stóráin Sioncrónaithe" + +#: help.c +msgid "Low-level Commands / Internal Helpers" +msgstr "Orduithe Leibhéal Ãseal/Cúntóirà Inmheánacha" + +#: help.c +msgid "User-facing repository, command and file interfaces" +msgstr "Comhéadain stór, ordaithe agus comhad atá os comhair úsáideora" + +#: help.c +msgid "Developer-facing file formats, protocols and other interfaces" +msgstr "" +"Formáidà comhaid, prótacail agus comhéadain eile atá os comhair an fhorbróra" + +#: help.c +#, c-format +msgid "available git commands in '%s'" +msgstr "orduithe git atá ar fáil i '%s'" + +#: help.c +msgid "git commands available from elsewhere on your $PATH" +msgstr "orduithe git ar fáil ó áiteanna eile ar do $PATH" + +#: help.c +msgid "These are common Git commands used in various situations:" +msgstr "Seo orduithe coitianta Git a úsáidtear i gcásanna éagsúla:" + +#: help.c +msgid "The Git concept guides are:" +msgstr "Is iad na treoracha coincheap Git:" + +#: help.c +msgid "User-facing repository, command and file interfaces:" +msgstr "Stóráil, ordaithe agus comhéadain comhad atá os comhair úsáideora:" + +#: help.c +msgid "File formats, protocols and other developer interfaces:" +msgstr "Formáidà comhaid, prótacail agus comhéadain forbróra eile:" + +#: help.c +msgid "External commands" +msgstr "Orduithe seachtracha" + +#: help.c +msgid "Command aliases" +msgstr "Ainmneacha ordaithe" + +#: help.c +msgid "See 'git help <command>' to read about a specific subcommand" +msgstr "Féach 'git help <command>'chun léamh faoi fho-ordú ar leith" + +#: help.c +#, 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 "" +"Is cosúil gur ordú git é '%s', ach nà raibh muid\n" +"in ann é a fhorghnÃomhú. B'fhéidir go bhfuil git-%s briste?" + +#: help.c +#, c-format +msgid "git: '%s' is not a git command. See 'git --help'." +msgstr "git: Nà ordú git é '%s'. Féach 'git --help'." + +#: help.c +msgid "Uh oh. Your system reports no Git commands at all." +msgstr "" +"Ó, a Dhia. Nà thuairiscÃonn do chóras aon orduithe Git ar chor ar bith." + +#: help.c +#, c-format +msgid "WARNING: You called a Git command named '%s', which does not exist." +msgstr "RABHADH: Ghlaoigh tú ordú Git darb ainm '%s', nach bhfuil ann." + +#: help.c +#, c-format +msgid "Continuing under the assumption that you meant '%s'." +msgstr "Ag leanúint faoin toimhde gur chiallaigh tú '%s'." + +#: help.c +#, c-format +msgid "Run '%s' instead [y/N]? " +msgstr "Rith '%s' ina ionad sin [y/N]? " + +#: help.c +#, c-format +msgid "Continuing in %0.1f seconds, assuming that you meant '%s'." +msgstr "" +"Ag leanúint ar aghaidh i %0.1f soicind, ag glacadh leis gur chiallaigh tú " +"'%s'." + +#: help.c +msgid "" +"\n" +"The most similar command is" +msgid_plural "" +"\n" +"The most similar commands are" +msgstr[0] "" +"\n" +"Is é an t-ordú is cosúla ná" +msgstr[1] "" +"\n" +"Is iad na horduithe is cosúla ná" +msgstr[2] "" +"\n" +"Is iad na horduithe is cosúla ná" + +#: help.c +msgid "git version [--build-options]" +msgstr "leagan git [--build-options]" + +#: help.c +#, c-format +msgid "%s: %s - %s" +msgstr "%s: %s - %s" + +#: help.c +msgid "" +"\n" +"Did you mean this?" +msgid_plural "" +"\n" +"Did you mean one of these?" +msgstr[0] "" +"\n" +"An raibh sé seo i gceist agat?" +msgstr[1] "" +"\n" +"An raibh ceann acu seo i gceist agat?" +msgstr[2] "" +"\n" +"An raibh ceann acu seo i gceist agat?" + +#: hook.c +#, c-format +msgid "" +"The '%s' hook was ignored because it's not set as executable.\n" +"You can disable this warning with `git config set advice.ignoredHook false`." +msgstr "" +"Rinneadh neamhaird ar an gcroca '%s' toisc nach bhfuil sé socraithe mar " +"infheidhmithe.\n" +"Is féidir leat an rabhadh seo a dhÃchumasú le `git config set " +"advice.ignoredHook false `." + +#: http-fetch.c +msgid "not a git repository" +msgstr "nà stór git" + +#: http-fetch.c +#, c-format +msgid "argument to --packfile must be a valid hash (got '%s')" +msgstr "" +"caithfidh argóint chuig --packfile a bheith ina hash bailà (fuair '%s')" + +#: http.c +#, c-format +msgid "negative value for http.postBuffer; defaulting to %d" +msgstr "luach diúltach do http.postBuffer; réamhshocraithe go %d" + +#: http.c +msgid "Delegation control is not supported with cURL < 7.22.0" +msgstr "Nà thacaÃtear le cURL <7.22.0 le rialú tarscaireachta" + +#: http.c +msgid "Unknown value for http.proactiveauth" +msgstr "Luach anaithnid do http.proactiveauth" + +#: http.c parse.c +#, c-format +msgid "failed to parse %s" +msgstr "theip ar %s a pharsáil" + +#: http.c +#, c-format +msgid "Unsupported SSL backend '%s'. Supported SSL backends:" +msgstr "'%s' cúltaca SSL gan tacaÃocht. Cúltaca SSL tacaithe:" + +#: http.c +#, c-format +msgid "Could not set SSL backend to '%s': cURL was built without SSL backends" +msgstr "NÃor féidir cúltaca SSL a shocrú go '%s': Tógadh cURL gan cúltaca SSL" + +#: http.c +#, c-format +msgid "Could not set SSL backend to '%s': already set" +msgstr "NÃorbh fhéidir cúltaca SSL a shocrú go '%s': socraithe cheana féin" + +#: http.c +msgid "refusing to read cookies from http.cookiefile '-'" +msgstr "diúltú fianáin a léamh ó http.cookiefile '-'" + +#: http.c +msgid "ignoring http.savecookies for empty http.cookiefile" +msgstr "" +"neamhaird a dhéanamh ar http.savecookies le haghaidh http.cookiefile folamh" + +#: http.c +#, c-format +msgid "" +"unable to update url base from redirection:\n" +" asked for: %s\n" +" redirect: %s" +msgstr "" +"in ann bonn url a nuashonrú ó atreorú:\n" +" iarrtha ar: %s\n" +" atreorú: %s" + +#: ident.c +msgid "Author identity unknown\n" +msgstr "Céannacht an údair anaithnid\n" + +#: ident.c +msgid "Committer identity unknown\n" +msgstr "Céannacht an chomórtais anaithnid\n" + +#: ident.c +msgid "" +"\n" +"*** Please tell me who you are.\n" +"\n" +"Run\n" +"\n" +" git config --global user.email \"you@example.com\"\n" +" git config --global user.name \"Your Name\"\n" +"\n" +"to set your account's default identity.\n" +"Omit --global to set the identity only in this repository.\n" +"\n" +msgstr "" +"\n" +"*** Inis dom cé tú féin, le do thoil.\n" +"\n" +"Rith\n" +"\n" +" git config --global user.email \"you@example.comâ€\n" +" git config --global user.name “Do Ainmâ€\n" +"\n" +"chun féiniúlacht réamhshocraithe do chuntais a shocrú.\n" +"Fág --global chun an aitheantas a shocrú sa stór seo amháin.\n" + +#: ident.c +msgid "no email was given and auto-detection is disabled" +msgstr "nÃor tugadh aon rÃomhphost agus tá brath uathoibrÃoch faoi" + +#: ident.c +#, c-format +msgid "unable to auto-detect email address (got '%s')" +msgstr "in ann seoladh rÃomhphoist a bhrath go huathoibrÃoch (fuair '%s')" + +#: ident.c +msgid "no name was given and auto-detection is disabled" +msgstr "nà tugadh aon ainm agus tá brath uathoibrÃoch faoi dhÃchum" + +#: ident.c +#, c-format +msgid "unable to auto-detect name (got '%s')" +msgstr "nà féidir ainm a bhrath go huathoibrÃoch (fuair '%s')" + +#: ident.c +#, c-format +msgid "empty ident name (for <%s>) not allowed" +msgstr "ainm ident folamh (le haghaidh <%s>) nach gceadaÃtear" + +#: ident.c +#, c-format +msgid "name consists only of disallowed characters: %s" +msgstr "nà chuimsÃonn ainm ach carachtair neamh-cheadaithe: %s" + +#: list-objects-filter-options.c +msgid "expected 'tree:<depth>'" +msgstr "<depth>'crann ag súil leis: '" + +#: list-objects-filter-options.c +msgid "sparse:path filters support has been dropped" +msgstr "neamhchoitianta: tá tacaÃocht scagairà cosáin titim" + +#: list-objects-filter-options.c +#, c-format +msgid "'%s' for 'object:type=<type>' is not a valid object type" +msgstr "<type>Nà cineál réad bailà é '%s' le haghaidh 'object:type='" + +#: list-objects-filter-options.c +#, c-format +msgid "invalid filter-spec '%s'" +msgstr "scagaire neamhbhailà '%s'" + +#: list-objects-filter-options.c +#, c-format +msgid "must escape char in sub-filter-spec: '%c'" +msgstr "nà mór don char a éalú i sub-filter-spec: '%c'" + +#: list-objects-filter-options.c +msgid "expected something after combine:" +msgstr "ag súil le rud éigin tar éis an chomhcheangail:" + +#: list-objects-filter-options.c +msgid "multiple filter-specs cannot be combined" +msgstr "nà féidir ilshonraÃochtaà scagaire a chomhcheangal" + +#: list-objects-filter-options.c +msgid "unable to upgrade repository format to support partial clone" +msgstr "in ann formáid stórais a uasghrádú chun tacú le clón páirteach" + +#: list-objects-filter-options.h +msgid "args" +msgstr "args" + +#: list-objects-filter-options.h +msgid "object filtering" +msgstr "scagadh réad" + +#: list-objects-filter.c +#, c-format +msgid "unable to access sparse blob in '%s'" +msgstr "nà féidir rochtain a fháil ar bhlob neamhchoitianta i '%s'" + +#: list-objects-filter.c +#, c-format +msgid "unable to parse sparse filter data in %s" +msgstr "nach féidir sonraà scagaire neamhchoitianta a pháirseáil i %s" + +#: list-objects.c +#, c-format +msgid "entry '%s' in tree %s has tree mode, but is not a tree" +msgstr "tá modh crann ag iontráil '%s' i gcrann %s, ach nà crann Ã" + +#: list-objects.c +#, c-format +msgid "entry '%s' in tree %s has blob mode, but is not a blob" +msgstr "tá modh blob ag iontráil '%s' i gcrann %s, ach nà blob Ã" + +#: list-objects.c +#, c-format +msgid "unable to load root tree for commit %s" +msgstr "nach féidir crann fréimhe a luchtú le haghaidh tiomanta %s" + +#: lockfile.c +#, c-format +msgid "" +"Unable to create '%s.lock': %s.\n" +"\n" +"Another git process seems to be running in this repository, e.g.\n" +"an editor opened by 'git commit'. Please make sure all processes\n" +"are terminated then try again. If it still fails, a git process\n" +"may have crashed in this repository earlier:\n" +"remove the file manually to continue." +msgstr "" +"Nà féidir '%s.lock' a chruthú: %s.\n" +"\n" +"Is cosúil go bhfuil próiseas git eile ag rith sa stór seo, e.g.\n" +"eagarthóir a osclaÃodh ag 'git commit'. Déan cinnte le do thoil gach " +"próiseas\n" +"foirceanntar ansin déan iarracht arÃs. Má theipeann air fós, próiseas git\n" +"d'fhéadfadh go mbeadh sé titim sa stór seo nÃos luaithe:\n" +"bain an comhad de láimh chun leanúint ar aghaidh." + +#: lockfile.c +#, c-format +msgid "Unable to create '%s.lock': %s" +msgstr "Nà féidir '%s.lock' a chruthú: %s" + +#: log-tree.c +msgid "unable to create temporary object directory" +msgstr "in ann eolaire réad sealadach a chruthú" + +#: loose.c +#, c-format +msgid "could not write loose object index %s" +msgstr "nà fhéadfaà innéacs réad scaoilte %s a scrÃ" + +#: loose.c +#, c-format +msgid "failed to write loose object index %s" +msgstr "theip ar innéacs réad scaoilte %s a scrÃobh" + +#: ls-refs.c +#, c-format +msgid "unexpected line: '%s'" +msgstr "lÃne gan choinne: '%s'" + +#: ls-refs.c +msgid "expected flush after ls-refs arguments" +msgstr "súil le sruth tar éis argóintà ls-refs" + +#: mailinfo.c +msgid "quoted CRLF detected" +msgstr "braithÃodh CRLF a luaitear" + +#: mem-pool.c strbuf.c wrapper.c +#, c-format +msgid "unable to format message: %s" +msgstr "nach féidir teachtaireacht a fhormáidiú: %s" + +#: merge-ll.c +#, c-format +msgid "invalid marker-size '%s', expecting an integer" +msgstr "méid marcóra neamhbhailà '%s', ag súil le sláimhir" + +#: merge-ort-wrappers.c +#, c-format +msgid "Could not parse object '%s'" +msgstr "Nà fhéadfaà réad '%s' a pháirseáil" + +#: merge-ort.c +#, c-format +msgid "Failed to merge submodule %s (not checked out)" +msgstr "Theip ar fho-mhodúl %s a chumasc (nÃor seiceáiltear amach)" + +#: merge-ort.c +#, c-format +msgid "Failed to merge submodule %s (no merge base)" +msgstr "Theip ar fho-mhodúl %s a chumasc (gan aon bhonn cumaisc)" + +#: merge-ort.c +#, c-format +msgid "Failed to merge submodule %s (commits not present)" +msgstr "Theip ar fho-mhodúl %s a chumasc (nÃl gealltanas ann)" + +#: merge-ort.c +#, c-format +msgid "error: failed to merge submodule %s (repository corrupt)" +msgstr "earráid: theip ar fho-mhodúl %s a chumasc (stór truaillithe)" + +#: merge-ort.c +#, c-format +msgid "Failed to merge submodule %s (commits don't follow merge-base)" +msgstr "Theip ar fho-mhodúl %s a chumasc (nà leanann gealltanna cumaisc bonn)" + +#: merge-ort.c +#, c-format +msgid "Note: Fast-forwarding submodule %s to %s" +msgstr "Nóta: Fo-mhodúl %s a chur ar aghaidh go tapa chuig %s" + +#: merge-ort.c +#, c-format +msgid "Failed to merge submodule %s" +msgstr "Theip ar fho-mhodúl %s a chumasc" + +#: merge-ort.c +#, c-format +msgid "" +"Failed to merge submodule %s, but a possible merge resolution exists: %s" +msgstr "" +"Theip ar fho-mhodúl %s a chumasc, ach tá réiteach cumaisc féideartha ann: %s" + +#: merge-ort.c +#, c-format +msgid "" +"Failed to merge submodule %s, but multiple possible merges exist:\n" +"%s" +msgstr "" +"Theip ar fho-mhodúl %s a chumasc, ach tá go leor cumaisc féideartha ann:\n" +"%s" + +#: merge-ort.c +#, c-format +msgid "error: failed to execute internal merge for %s" +msgstr "earráid: theip ar chumasc inmheánach a chur i gcrÃch le haghaidh %s" + +#: merge-ort.c +#, c-format +msgid "error: unable to add %s to database" +msgstr "earráid: nà féidir %s a chur leis an mbunachar sonraÃ" + +#: merge-ort.c +#, c-format +msgid "Auto-merging %s" +msgstr "Cumaisc uathoibrÃoch %s" + +#: merge-ort.c +#, c-format +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 "" +"COIMHLINT (athainmniú intuigthe dir): Comhad/dir atá ann cheana ag %s i " +"mbealach athainmniú eolaire intuigthe ag cur na cosáin seo a leanas ann: %s." + +#: merge-ort.c +#, 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 "" +"CONFLICT (athainmniú intuigthe): Nà féidir nÃos mó ná cosán amháin a mhapáil " +"chuig %s; rinne athainmneacha eolaire intuigthe iarracht na cosáin seo a " +"chur ann: %s" + +#: merge-ort.c +#, c-format +msgid "" +"CONFLICT (directory rename split): Unclear where to rename %s to; it was " +"renamed to multiple other directories, with no destination getting a " +"majority of the files." +msgstr "" +"CONFLICT (scoilt athainmniú eolaire): NÃl soiléir cá háit le %s a " +"athainmniú; athainmnÃodh é go eolairà éagsúla eile, gan aon cheann scrÃbe a " +"fháil tromlach na gcomhaid." + +#: merge-ort.c +#, c-format +msgid "" +"WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was " +"renamed." +msgstr "" +"RABHADH: Seachaint %s a chur i bhfeidhm -> %s a athainmniú go %s, toisc gur " +"athainmnÃodh %s féin." + +#: merge-ort.c +#, c-format +msgid "" +"Path updated: %s added in %s inside a directory that was renamed in %s; " +"moving it to %s." +msgstr "" +"Conair nuashonraithe: Cuireadh %s isteach i %s taobh istigh de eolaire a " +"athainmnÃodh i %s; ag bogadh é go %s." + +#: merge-ort.c +#, c-format +msgid "" +"Path updated: %s renamed to %s in %s, inside a directory that was renamed in " +"%s; moving it to %s." +msgstr "" +"Conair nuashonraithe: AthainmnÃodh %s go %s i %s, taobh istigh de eolaire a " +"athainmnÃodh i %s; é ag bogadh go %s." + +#: merge-ort.c +#, 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 "" +"COIMHLINT (suÃomh comhaid): Cuireadh %s isteach i %s taobh istigh de eolaire " +"a athainmnÃodh i %s, rud a thugann le tuiscint gur cheart é a aistriú go %s " +"b'fhéidir." + +#: merge-ort.c +#, c-format +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 "" +"COIMHLINT (suÃomh comhaid): AthainmnÃodh %s go %s i %s, taobh istigh de " +"eolaire a athainmnÃodh i %s, ag moladh gur cheart é a aistriú go %s " +"b'fhéidir." + +#: merge-ort.c +#, c-format +msgid "CONFLICT (rename/rename): %s renamed to %s in %s and to %s in %s." +msgstr "" +"COIMHLINT (athainmniú/athainmniú): AthainmnÃodh %s go %s i %s agus go %s i " +"%s." + +#: merge-ort.c +#, c-format +msgid "" +"CONFLICT (rename involved in collision): rename of %s -> %s has content " +"conflicts AND collides with another path; this may result in nested conflict " +"markers." +msgstr "" +"COIMHLINT (athainmniú a bhaineann le imbhualadh): athainmnigh %s -> tá " +"coinbhleachtaà ábhair ag %s AGUS imbhuaileann sé le cosán eile; d'fhéadfadh " +"marcóirà coinbhleachta neadaithe a bheith mar thoradh air seo." + +#: merge-ort.c +#, c-format +msgid "CONFLICT (rename/delete): %s renamed to %s in %s, but deleted in %s." +msgstr "" +"COIMHLINT (athainmniú/scrios): AthainmnÃodh %s go %s i %s, ach scriosadh é i " +"%s." + +#: merge-ort.c +#, c-format +msgid "error: cannot read object %s" +msgstr "earráid: nà féidir réad %s a léamh" + +#: merge-ort.c +#, c-format +msgid "error: object %s is not a blob" +msgstr "earráid: nà blob é réad %s" + +#: merge-ort.c +#, c-format +msgid "" +"CONFLICT (file/directory): directory in the way of %s from %s; moving it to " +"%s instead." +msgstr "" +"CONFLICT (comhad/eolaire): eolaire ar bhealach %s ó %s; é a bhogadh go %s " +"ina ionad." + +#: merge-ort.c +#, c-format +msgid "" +"CONFLICT (distinct types): %s had different types on each side; renamed both " +"of them so each can be recorded somewhere." +msgstr "" +"COIMHLINT (cineálacha ar leith): Bhà cineálacha difriúla ag %s ar gach " +"taobh; athainmnÃodh an dá cheann ionas gur féidir gach ceann a thaifeadadh " +"áit éigin." + +#: merge-ort.c +#, c-format +msgid "" +"CONFLICT (distinct types): %s had different types on each side; renamed one " +"of them so each can be recorded somewhere." +msgstr "" +"COIMHLINT (cineálacha ar leith): Bhà cineálacha difriúla ag %s ar gach " +"taobh; athainmnÃodh ceann acu ionas gur féidir gach ceann a thaifeadadh áit " +"éigin." + +#: merge-ort.c +msgid "content" +msgstr "ábhar" + +#: merge-ort.c +msgid "add/add" +msgstr "cuirte/cuir leis" + +#: merge-ort.c +msgid "submodule" +msgstr "fo-mhodúl" + +#: merge-ort.c +#, c-format +msgid "CONFLICT (%s): Merge conflict in %s" +msgstr "COIMHLINT (%s): Cumaisc coinbhleacht i %s" + +#: merge-ort.c +#, c-format +msgid "" +"CONFLICT (modify/delete): %s deleted in %s and modified in %s. Version %s " +"of %s left in tree." +msgstr "" +"CONFLICT (modhnó/scriosadh): Scriosta %s i %s agus modhnaithe i %s. Tá " +"leagan %s de %s fágtha sa chrann." + +#. 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" +#. +#: merge-ort.c +#, 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 "" +" - téigh go dtà an fo-mhodúl (%s), agus cumasc an tiomantas %s\n" +" nó nuashonraigh chuig tiomantas atá ann cheana féin a bhfuil na " +"hathruithe sin cumasctha aige.\n" + +#: merge-ort.c +#, c-format +msgid "" +"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 "" +"Faoi láthair nà thacaÃonn cumasc athfhillteach le fo-mhodúil ach le cásanna " +"mÃbhá\n" +"Láimhseáil le cumasc gach fo-mhodúl coimhlinte de láimh le do thoil.\n" +"Is féidir é seo a chur i gcrÃch leis na céimeanna seo a leanas:\n" +"%s - teacht ar ais chuig superproject agus rith:\n" +"\n" +" git add %s\n" +"\n" +" chun an cumasc thuas nó nuashonrú a thaifead\n" +" - aon choimhlintà eile sa superproject a réiteach\n" +" - an t-innéacs mar thoradh air a thiomnú sa sárthionscadal\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. +#. +#: merge-ort.c +#, c-format +msgid "collecting merge info failed for trees %s, %s, %s" +msgstr "theip ar fhaisnéis chumaisc a bhailiú do chrainn %s, %s, %s" + +#: merge.c +msgid "failed to read the cache" +msgstr "theip ar an taisce a léamh" + +#: midx-write.c +#, c-format +msgid "failed to add packfile '%s'" +msgstr "theip ar chomhad pacáiste '%s' a chur leis" + +#: midx-write.c +#, c-format +msgid "failed to open pack-index '%s'" +msgstr "theip ar innéacs pacáiste '%s' a oscailt" + +#: midx-write.c +#, c-format +msgid "failed to locate object %d in packfile" +msgstr "theip ar réad %d a aimsiú i packfile" + +#: midx-write.c +msgid "cannot store reverse index file" +msgstr "nà féidir comhad innéacs droim a stóráil" + +#: midx-write.c +#, c-format +msgid "could not parse line: %s" +msgstr "nà fhéadfaà lÃne a pháirseáil: %s" + +#: midx-write.c +#, c-format +msgid "malformed line: %s" +msgstr "lÃne mhÃfhoirmithe: %s" + +#: midx-write.c +msgid "could not load pack" +msgstr "nà fhéadfaà pacáiste a luchtú" + +#: midx-write.c +#, c-format +msgid "could not open index for %s" +msgstr "nà raibh in ann innéacs a oscailt do %s" + +#: midx-write.c +#, c-format +msgid "unable to link '%s' to '%s'" +msgstr "nà féidir '%s' a nascadh le '%s'" + +#: midx-write.c midx.c +#, c-format +msgid "failed to clear multi-pack-index at %s" +msgstr "theip ar innéacs il-phacáiste a ghlanadh ag %s" + +#: midx-write.c +msgid "ignoring existing multi-pack-index; checksum mismatch" +msgstr "" +"neamhaird a dhéanamh ar innéacs il-phacáiste atá ann cheana; mÃmheaitseáil" + +#: midx-write.c +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "nà fhéadfaà innéacs droim a luchtú do MIDX %s" + +#: midx-write.c +msgid "Adding packfiles to multi-pack-index" +msgstr "Comhaid pacáiste a chur le hinnéacs il-phacáiste" + +#: midx-write.c +#, c-format +msgid "unknown preferred pack: '%s'" +msgstr "pacáiste roghnaithe anaithnid: '%s'" + +#: midx-write.c +#, c-format +msgid "cannot select preferred pack %s with no objects" +msgstr "nà féidir pacáiste roghnaithe %s a roghnú gan aon rudaÃ" + +#: midx-write.c +#, c-format +msgid "did not see pack-file %s to drop" +msgstr "nÃor chonaic sé pacáist-chomhad %s le scaoileadh" + +#: midx-write.c +#, c-format +msgid "preferred pack '%s' is expired" +msgstr "tá an pacáiste roghnaithe '%s' in éag" + +#: midx-write.c +msgid "no pack files to index." +msgstr "gan aon phacáiste comhaid le hinnéacs." + +#: midx-write.c +msgid "refusing to write multi-pack .bitmap without any objects" +msgstr "diúltú a scrÃobh il-pacáiste.bitmap gan aon rudaÃ" + +#: midx-write.c +msgid "unable to create temporary MIDX layer" +msgstr "in ann ciseal MIDX sealadach a chruthú" + +#: midx-write.c +msgid "could not write multi-pack bitmap" +msgstr "nà fhéadfaà bitmap il-phacáiste a scrÃobh" + +#: midx-write.c +msgid "unable to open multi-pack-index chain file" +msgstr "in ann comhad slabhra in-innéacs il-phacáiste a oscailt" + +#: midx-write.c +msgid "unable to rename new multi-pack-index layer" +msgstr "in ann ciseal innéacs ilphacáiste nua a athainmniú" + +#: midx-write.c +msgid "could not write multi-pack-index" +msgstr "nà fhéadfaà innéacs il-phacáiste a scrÃobh" + +#: midx-write.c +msgid "cannot expire packs from an incremental multi-pack-index" +msgstr "" +"nà féidir le pacáistà a chur in éag ó innéacs ilphacáiste incriminteach" + +#: midx-write.c +msgid "Counting referenced objects" +msgstr "Rud tagartha a chomhaireamh" + +#: midx-write.c +msgid "Finding and deleting unreferenced packfiles" +msgstr "Comhaid pacáiste gan tagairt a aimsiú agus a scriosadh" + +#: midx-write.c +msgid "cannot repack an incremental multi-pack-index" +msgstr "nà féidir le hinnéacs ilphacáiste incriminteach a athphacáil" + +#: midx-write.c +msgid "could not start pack-objects" +msgstr "nà fhéadfaà pacáiste-rudaà a thosú" + +#: midx-write.c +msgid "could not finish pack-objects" +msgstr "nà raibh sé in ann pacáistà a chrÃochnú" + +#: midx.c +msgid "multi-pack-index OID fanout is of the wrong size" +msgstr "tá fanout OID ilphacáiste den mhéid mÃcheart" + +#: midx.c +#, c-format +msgid "" +"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]" +msgstr "fanout oid as ord: fanout [%d] =% <PRIx32>>% <PRIx32>= fanout [%d]" + +#: midx.c +msgid "multi-pack-index OID lookup chunk is the wrong size" +msgstr "tá an méid mÃcheart ar an smután cuardaigh OID innéacs ilphacáiste" + +#: midx.c +msgid "multi-pack-index object offset chunk is the wrong size" +msgstr "" +"tá an méid mÃcheart ar an smután fritháireamh réada innéacs ilphacáiste" + +#: midx.c +#, c-format +msgid "multi-pack-index file %s is too small" +msgstr "tá comhad in-innéacs ilphacáiste %s ró-bheag" + +#: midx.c +#, c-format +msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x" +msgstr "nà mheaitseálann sÃniú innéacs il-phacáiste 0x%08x sÃniú 0x%08x" + +#: midx.c +#, c-format +msgid "multi-pack-index version %d not recognized" +msgstr "nà aithnÃtear leagan innéacs il-phacáiste %d" + +#: midx.c +#, c-format +msgid "multi-pack-index hash version %u does not match version %u" +msgstr "nà hionann leagan %u den hais innéacs ilphacáiste agus leagan %u" + +#: midx.c +msgid "multi-pack-index required pack-name chunk missing or corrupted" +msgstr "" +"innéacs il-phacáiste teastaÃonn pÃosa ainm pacáiste ar iarraidh nó " +"truaillithe" + +#: midx.c +msgid "multi-pack-index required OID fanout chunk missing or corrupted" +msgstr "" +"teastaÃonn innéacs il-phacáiste le pÃosa fanout OID atá ar iarraidh nó " +"truaillithe" + +#: midx.c +msgid "multi-pack-index required OID lookup chunk missing or corrupted" +msgstr "" +"teastaÃonn innéacs ilphacáiste cuardaigh OID atá ar iarraidh nó truaillithe" + +#: midx.c +msgid "multi-pack-index required object offsets chunk missing or corrupted" +msgstr "" +"smután fritháireamh réada riachtanach innéacs ilphacáiste ar iarraidh nó " +"truaillithe" + +#: midx.c +msgid "multi-pack-index pack-name chunk is too short" +msgstr "tá pÃosa ainm pacáiste innéacs il-phacáiste ró-ghearr" + +#: midx.c +#, c-format +msgid "multi-pack-index pack names out of order: '%s' before '%s'" +msgstr "ainmneacha pacáiste in-innéacs il-phacáiste as ord: '%s' roimh '%s'" + +#: midx.c +msgid "multi-pack-index chain file too small" +msgstr "comhad slabhra in-innéacs il-phacáiste ró-bheag" + +#: midx.c +#, c-format +msgid "pack count in base MIDX too high: %<PRIuMAX>" +msgstr "lÃon pacáiste i mbonn MIDX ró-ard:%<PRIuMAX>" + +#: midx.c +#, c-format +msgid "object count in base MIDX too high: %<PRIuMAX>" +msgstr "lÃon rudaà i mbonn MIDX ró-ard:%<PRIuMAX>" + +#: midx.c +#, c-format +msgid "invalid multi-pack-index chain: line '%s' not a hash" +msgstr "slabhra innéacs il-phacáiste neamhbhailÃ: nà hash é lÃne '%s'" + +#: midx.c +msgid "unable to find all multi-pack index files" +msgstr "in ann gach comhad innéacs il-phacáiste a fháil" + +#: midx.c +msgid "invalid MIDX object position, MIDX is likely corrupt" +msgstr "suÃomh réad MIDX neamhbhailÃ, is dócha go bhfuil MIDX truaillithe" + +#: midx.c +#, c-format +msgid "bad pack-int-id: %u (%u total packs)" +msgstr "bad pack-int-id: %u (pacáistà iomlána %u)" + +#: midx.c +msgid "MIDX does not contain the BTMP chunk" +msgstr "NÃl an pÃosa BTMP i MIDX" + +#: midx.c +#, c-format +msgid "could not load bitmapped pack %<PRIu32>" +msgstr "nà fhéadfaà pacáiste bitmapped a luchtú% <PRIu32>" + +#: midx.c +msgid "multi-pack-index stores a 64-bit offset, but off_t is too small" +msgstr "" +"stórálann innéacs il-phacáiste fritháireamh 64-giotán, ach tá off_t ró-bheag" + +#: midx.c +msgid "multi-pack-index large offset out of bounds" +msgstr "innéacs il-phacáiste fhritháireamh mór as teorainneacha" + +#: midx.c +msgid "multi-pack-index file exists, but failed to parse" +msgstr "tá comhad in-innéacs il-phacáiste ann, ach theip air a pháirseáil" + +#: midx.c +msgid "incorrect checksum" +msgstr "seiceáil mÃcheart" + +#: midx.c +msgid "Looking for referenced packfiles" +msgstr "Ag lorg comhaid pacáiste tagartha" + +#: midx.c +msgid "the midx contains no oid" +msgstr "nÃl aon oid sa midx" + +#: midx.c +msgid "Verifying OID order in multi-pack-index" +msgstr "Ordú OID a fhÃorú in innéacs il-phacáiste" + +#: midx.c +#, c-format +msgid "oid lookup out of order: oid[%d] = %s >= %s = oid[%d]" +msgstr "cuardach oid as ord: oid [%d] = %s >= %s = oid [%d]" + +#: midx.c +msgid "Sorting objects by packfile" +msgstr "Rudaà a shórtáil de réir pacáiste" + +#: midx.c +msgid "Verifying object offsets" +msgstr "Athshraith réada a fhÃorú" + +#: midx.c +#, c-format +msgid "failed to load pack entry for oid[%d] = %s" +msgstr "theip ar iontráil pacáiste a luchtú do oid [%d] = %s" + +#: midx.c +#, c-format +msgid "failed to load pack-index for packfile %s" +msgstr "theip ar innéacs pacáiste a luchtú do phacáiste %s" + +#: midx.c +#, c-format +msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>" +msgstr "" +"fritháireamh réada mÃcheart le haghaidh oid[%d] = %s: %<PRIx64> != %<PRIx64>" + +#: name-hash.c +#, c-format +msgid "unable to create lazy_dir thread: %s" +msgstr "nach féidir snáithe lazy_dir a chruthú: %s" + +#: name-hash.c +#, c-format +msgid "unable to create lazy_name thread: %s" +msgstr "nach féidir snáithe lazy_name a chruthú: %s" + +#: name-hash.c +#, c-format +msgid "unable to join lazy_name thread: %s" +msgstr "nà féidir teacht le snáithe lazy_name: %s" + +#: notes-merge.c +#, c-format +msgid "" +"You have not concluded your previous notes merge (%s exists).\n" +"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 "" +"NÃor chrÃochnaigh tú do chuid nótaà roimhe seo a chumasc (%s ann).\n" +"Le do thoil, bain úsáid as 'git notes merge --commit 'nó 'git notes merge --" +"abort' chun an cumasc roimhe seo a cheangail/deireadh a chur leis sula " +"dtosaÃonn tú le cumasc nótaà nua." + +#: notes-merge.c +#, c-format +msgid "You have not concluded your notes merge (%s exists)." +msgstr "NÃor chrÃochnaigh tú do chuid nótaà a chumasc (%s ann)." + +#: notes-utils.c +msgid "Cannot commit uninitialized/unreferenced notes tree" +msgstr "Nà féidir crann nótaà neamhthionsaithe/gan tagairt a dhéanamh" + +#: notes-utils.c +#, c-format +msgid "Bad notes.rewriteMode value: '%s'" +msgstr "Luach lochtach notes.rewriteMode: '%s'" + +#: notes-utils.c +#, c-format +msgid "Refusing to rewrite notes in %s (outside of refs/notes/)" +msgstr "Diúltú nótaà a athscrÃobh i %s (lasmuigh de refs/notes/)" + +#. TRANSLATORS: The first %s is the name of +#. the environment variable, the second %s is +#. its value. +#. +#: notes-utils.c +#, c-format +msgid "Bad %s value: '%s'" +msgstr "Droch-luach %s: '%s'" + +#: object-file-convert.c +msgid "failed to decode tree entry" +msgstr "theip ar iontráil crann a dhÃchódú" + +#: object-file-convert.c +#, c-format +msgid "failed to map tree entry for %s" +msgstr "theip ar iontráil crann a mhapáil do %s" + +#: object-file-convert.c +#, c-format +msgid "bad %s in commit" +msgstr "droch %s i dtiomantas" + +#: object-file-convert.c +#, c-format +msgid "unable to map %s %s in commit object" +msgstr "nach féidir %s %s a mhapáil i réad tiomanta" + +#: object-file-convert.c +#, c-format +msgid "Failed to convert object from %s to %s" +msgstr "Theip ar réad a thiontú ó %s go %s" + +#: object-file.c +#, c-format +msgid "object file %s is empty" +msgstr "tá comhad réad %s folamh" + +#: object-file.c +#, c-format +msgid "corrupt loose object '%s'" +msgstr "réad scaoilte truaillithe '%s'" + +#: object-file.c +#, c-format +msgid "garbage at end of loose object '%s'" +msgstr "truflais ag deireadh réad scaoilte '%s'" + +#: object-file.c +#, c-format +msgid "unable to open loose object %s" +msgstr "nach féidir réad scaoilte %s a oscailt" + +#: object-file.c +#, c-format +msgid "unable to parse %s header" +msgstr "nach féidir ceannteideal %s a pháirseáil" + +#: object-file.c +msgid "invalid object type" +msgstr "cineál réad neamhbhailÃ" + +#: object-file.c +#, c-format +msgid "unable to unpack %s header" +msgstr "nà féidir ceannteideal %s a dhÃphacáil" + +#: object-file.c +#, c-format +msgid "header for %s too long, exceeds %d bytes" +msgstr "ceannteideal do %s rófhada, nÃos mó ná %d bytes" + +#: object-file.c +#, c-format +msgid "loose object %s (stored in %s) is corrupt" +msgstr "tá réad scaoilte %s (stóráilte i %s) truaillithe" + +#: object-file.c +#, c-format +msgid "unable to open %s" +msgstr "nà féidir %s a oscailt" + +#: object-file.c +#, c-format +msgid "files '%s' and '%s' differ in contents" +msgstr "tá difrÃocht idir comhaid '%s' agus '%s' in ábhar" + +#: object-file.c +#, c-format +msgid "unable to write file %s" +msgstr "nach féidir comhad %s a scrÃobh" + +#: object-file.c +#, c-format +msgid "unable to write repeatedly vanishing file %s" +msgstr "in ann comhad %s atá ag imeacht arÃs agus arÃs eile a scrÃobh" + +#: object-file.c +#, c-format +msgid "unable to set permission to '%s'" +msgstr "nach féidir cead a shocrú do '%s'" + +#: object-file.c +msgid "error when closing loose object file" +msgstr "earráid agus comhad réad scaoilte á ndú" + +#: object-file.c +#, c-format +msgid "insufficient permission for adding an object to repository database %s" +msgstr "cead neamhleor chun réad a chur le bunachar sonraà stórais %s" + +#: object-file.c +msgid "unable to create temporary file" +msgstr "in ann comhad sealadach a chruthú" + +#: object-file.c +msgid "unable to write loose object file" +msgstr "in ann comhad réad scaoilte a scrÃobh" + +#: object-file.c +#, c-format +msgid "unable to deflate new object %s (%d)" +msgstr "nach féidir réad nua %s a dhÃoslagadh (%d)" + +#: object-file.c +#, c-format +msgid "deflateEnd on object %s failed (%d)" +msgstr "theip ar deflateEnd ar réad %s (%d)" + +#: object-file.c +#, c-format +msgid "confused by unstable object source data for %s" +msgstr "mearbhall de bharr sonraà foinse réada éagobhsaà do %s" + +#: object-file.c +#, c-format +msgid "write stream object %ld != %<PRIuMAX>" +msgstr "scrÃobh réad srutha %ld! =%<PRIuMAX>" + +#: object-file.c +#, c-format +msgid "unable to stream deflate new object (%d)" +msgstr "nach féidir réad nua a dhÃscaoileadh a shruthlú (%d)" + +#: object-file.c +#, c-format +msgid "deflateEnd on stream object failed (%d)" +msgstr "theip ar réad srutha DeflateEnd (%d)" + +#: object-file.c +#, c-format +msgid "unable to create directory %s" +msgstr "nach féidir eolaire %s a chruthú" + +#: object-file.c +#, c-format +msgid "cannot read object for %s" +msgstr "nà féidir réad a léamh do %s" + +#: object-file.c +#, c-format +msgid "cannot map object %s to %s" +msgstr "nà féidir réad %s a mhapáil go %s" + +#: object-file.c +#, c-format +msgid "object fails fsck: %s" +msgstr "teipeann ar réad fsck: %s" + +#: object-file.c +msgid "refusing to create malformed object" +msgstr "diúltú réad mÃfhoirmithe a chruthú" + +#: object-file.c +#, c-format +msgid "read error while indexing %s" +msgstr "earráid léite agus %s á innéacsú" + +#: object-file.c +#, c-format +msgid "short read while indexing %s" +msgstr "léamh gearr agus %s á innéacsú" + +#: object-file.c +#, c-format +msgid "%s: failed to insert into database" +msgstr "%s: theip ort a chur isteach sa bhunachar sonraÃ" + +#: object-file.c +#, c-format +msgid "%s: unsupported file type" +msgstr "%s: cineál comhaid gan tacaÃocht" + +#: object-file.c +#, c-format +msgid "hash mismatch for %s (expected %s)" +msgstr "neamhoiriúnú hash do %s (súil leis %s)" + +#: object-file.c +#, c-format +msgid "unable to mmap %s" +msgstr "nach féidir %s a mmapáil" + +#: object-file.c +#, c-format +msgid "unable to unpack header of %s" +msgstr "nach féidir ceanntásc %s a dhÃphacáil" + +#: object-file.c +#, c-format +msgid "unable to parse header of %s" +msgstr "nach féidir ceannteideal %s a pháirseáil" + +#: object-file.c +#, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "nà féidir cineál a pharsáil ó cheanntásc '%s' de %s" + +#: object-file.c +#, c-format +msgid "unable to unpack contents of %s" +msgstr "nach féidir ábhar %s a dhÃphacáil" + +#. TRANSLATORS: This is a line of ambiguous object +#. output shown when we cannot look up or parse the +#. object in question. E.g. "deadbeef [bad object]". +#. +#: object-name.c +#, c-format +msgid "%s [bad object]" +msgstr "%s [droch-réad]" + +#. TRANSLATORS: This is a line of ambiguous commit +#. object output. E.g.: +#. * +#. "deadbeef commit 2021-01-01 - Some Commit Message" +#. +#: object-name.c +#, c-format +msgid "%s commit %s - %s" +msgstr "Déanann %s tiomanta %s - %s" + +#. TRANSLATORS: This is a line of ambiguous +#. tag object output. E.g.: +#. * +#. "deadbeef tag 2022-01-01 - Some Tag Message" +#. * +#. The second argument is the YYYY-MM-DD found +#. in the tag. +#. * +#. The third argument is the "tag" string +#. from object.c. +#. +#: object-name.c +#, c-format +msgid "%s tag %s - %s" +msgstr "Clib %s %s - %s" + +#. TRANSLATORS: This is a line of ambiguous +#. tag object output where we couldn't parse +#. the tag itself. E.g.: +#. * +#. "deadbeef [bad tag, could not parse it]" +#. +#: object-name.c +#, c-format +msgid "%s [bad tag, could not parse it]" +msgstr "%s [droch-chlib, nà fhéadfaà é a pháirseáil]" + +#. TRANSLATORS: This is a line of ambiguous <type> +#. object output. E.g. "deadbeef tree". +#. +#: object-name.c +#, c-format +msgid "%s tree" +msgstr "%s crann" + +#. TRANSLATORS: This is a line of ambiguous <type> +#. object output. E.g. "deadbeef blob". +#. +#: object-name.c +#, c-format +msgid "%s blob" +msgstr "%s blob" + +#: object-name.c +#, c-format +msgid "short object ID %s is ambiguous" +msgstr "tá ID réad gairid %s débhrÃoch" + +#. TRANSLATORS: The argument is the list of ambiguous +#. objects composed in show_ambiguous_object(). See +#. its "TRANSLATORS" comments for details. +#. +#: object-name.c +#, c-format +msgid "" +"The candidates are:\n" +"%s" +msgstr "" +"Is iad na hiarrthóirÃ:\n" +"%s" + +#: object-name.c +msgid "" +"Git normally never creates a ref that ends with 40 hex characters\n" +"because it will be ignored when you just specify 40-hex. These refs\n" +"may be created by mistake. For example,\n" +"\n" +" git switch -c $br $(git rev-parse ...)\n" +"\n" +"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n" +"examine these refs and maybe delete them. Turn this message off by\n" +"running \"git config set advice.objectNameWarning false\"" +msgstr "" +"De ghnáth nà chruthaÃonn Git tagartha riamh a chrÃochnaÃonn le 40 carachtar\n" +"toisc go ndéanfar neamhaird air nuair a shonraÃonn tú ach 40-hex. Na " +"hiarratais seo\n" +"d'fhéadfaà a chruthú trà dhearmad. Mar shampla,\n" +"\n" +" git switch -c $br $(git rev-parse ...)\n" +"\n" +"áit a bhfuil “$br†folamh ar bhealach éigin agus cruthaÃtear tagairt 40-hex. " +"Le do thoil\n" +"scrúdú a dhéanamh ar na haifeanna seo agus b'fhéidir iad a scriosadh. Cas an " +"teachtaireacht seo as\n" +"ag rith \"git config set advice.objectNameWarning false\"" + +#: object-name.c +#, c-format +msgid "log for '%.*s' only goes back to %s" +msgstr "nà théann logáil le haghaidh '%.*s' ach ar ais go %s" + +#: object-name.c +#, c-format +msgid "log for '%.*s' only has %d entries" +msgstr "nÃl ach iontráil i logáil le haghaidh '%.*s' ach %d ceann" + +#: object-name.c +#, c-format +msgid "path '%s' exists on disk, but not in '%.*s'" +msgstr "tá cosán '%s' ann ar an diosca, ach nà i '%.*s'" + +#: object-name.c +#, c-format +msgid "" +"path '%s' exists, but not '%s'\n" +"hint: Did you mean '%.*s:%s' aka '%.*s:./%s'?" +msgstr "" +"tá an cosán '%s' ann, ach nÃl '%s' ann\n" +"leid: An raibh tú i gceist agat '%.*s:%s' aka '%.*s:./%s'?" + +#: object-name.c +#, c-format +msgid "path '%s' does not exist in '%.*s'" +msgstr "nÃl cosán '%s' ann i '%.*s'" + +#: object-name.c +#, c-format +msgid "" +"path '%s' is in the index, but not at stage %d\n" +"hint: Did you mean ':%d:%s'?" +msgstr "" +"tá cosán '%s' san innéacs, ach nà ag céim %d\n" +"leid: An raibh i gceist agat ': %d: %s'?" + +#: object-name.c +#, c-format +msgid "" +"path '%s' is in the index, but not '%s'\n" +"hint: Did you mean ':%d:%s' aka ':%d:./%s'?" +msgstr "" +"tá an conair '%s' san innéacs, ach nà '%s'\n" +"leideanna: an é ':%d:%s' a bhà i gceist agat, nó ':%d:./%s'?" + +#: object-name.c +#, c-format +msgid "path '%s' exists on disk, but not in the index" +msgstr "tá cosán '%s' ann ar an diosca, ach nà san innéacs" + +#: object-name.c +#, c-format +msgid "path '%s' does not exist (neither on disk nor in the index)" +msgstr "nÃl cosán '%s' ann (nà ar an diosca ná san innéacs)" + +#: object-name.c +msgid "relative path syntax can't be used outside working tree" +msgstr "" +"nà féidir comhréir cosáin choibhneasta a úsáid lasmuigh de chrann oibre" + +#: object-name.c +#, c-format +msgid "<object>:<path> required, only <object> '%s' given" +msgstr "<object>: ri <path>achtanach, nà <object>thugtar ach '%s'" + +#: object-name.c +#, c-format +msgid "invalid object name '%.*s'." +msgstr "ainm réada neamhbhailà '%.*s'." + +#: object-store.c +#, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "nÃl an eolaire réada %s ann; seiceáil .git/objects/info/alternates" + +#: object-store.c +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "nach féidir cosán réad malartach a normalú: %s" + +#: object-store.c +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s: neamhaird a dhéanamh ar stórais rudaà malartacha, neadú ró-" + +#: object-store.c +msgid "unable to fdopen alternates lockfile" +msgstr "in ann comhad glasála malartacha a fdopen" + +#: object-store.c +msgid "unable to read alternates file" +msgstr "in ann comhad malartach a léamh" + +#: object-store.c +msgid "unable to move new alternates file into place" +msgstr "in ann comhad malartacha nua a bhogadh isteach" + +#: object-store.c +#, c-format +msgid "path '%s' does not exist" +msgstr "nÃl cosán '%s' ann" + +#: object-store.c +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "nà thacaÃtear le stór tagartha '%s' mar sheiceáil nasctha go fóill." + +#: object-store.c +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "nà stór áitiúil é stór tagartha '%s'." + +#: object-store.c +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "tá stóras tagartha '%s' éadomhain" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "tá stór tagartha '%s' grapháilte" + +#: object-store.c +#, c-format +msgid "could not find object directory matching %s" +msgstr "nà fhéadfaà eolaire réada a fháil a mheaitseáil %s" + +#: object-store.c +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "lÃne neamhbhailà agus tú ag paráil iarmhairtà malartacha: %s" + +#: object-store.c +#, c-format +msgid "replacement %s not found for %s" +msgstr "nach bhfuarthas %s a athsholáthar do %s" + +#: object-store.c +#, c-format +msgid "packed object %s (stored in %s) is corrupt" +msgstr "tá réad pacáilte %s (stóráilte i %s) truaillithe" + +#: object-store.c +#, c-format +msgid "missing mapping of %s to %s" +msgstr "mapáil atá in easnamh de %s go %s" + +#: object-store.c +#, c-format +msgid "%s is not a valid '%s' object" +msgstr "Nà réad bailà '%s' é %s '" + +#: object.c +#, c-format +msgid "invalid object type \"%s\"" +msgstr "cineál réad neamhbhailà “%sâ€" + +#: object.c +#, c-format +msgid "object %s is a %s, not a %s" +msgstr "is %s é réad %s, nà %s" + +#: object.c +#, c-format +msgid "object %s has unknown type id %d" +msgstr "réad %s tá cineál ID anaithnid %d aige" + +#: object.c +#, c-format +msgid "unable to parse object: %s" +msgstr "nach féidir réad a pháirseáil: %s" + +#: object.c +#, c-format +msgid "hash mismatch %s" +msgstr "neamhoiriúnú hash %s" + +#: pack-bitmap-write.c +#, c-format +msgid "duplicate entry when writing bitmap index: %s" +msgstr "iontráil dúblach agus innéacs bitmap á scrÃobh: %s" + +#: pack-bitmap-write.c +#, c-format +msgid "attempted to store non-selected commit: '%s'" +msgstr "rinne iarracht tiomantas neamh-roghnaithe a stóráil: '%s'" + +#: pack-bitmap-write.c +msgid "too many pseudo-merges" +msgstr "an iomarca bréag-chumaisc" + +#: pack-bitmap-write.c +msgid "trying to write commit not in index" +msgstr "ag iarraidh tiomantas a scrÃobh nà in innéacs" + +#: pack-bitmap.c +msgid "failed to load bitmap index (corrupted?)" +msgstr "theip ar innéacs bitmap a luchtú (truaillithe?)" + +#: pack-bitmap.c +msgid "corrupted bitmap index (too small)" +msgstr "innéacs bitmap truaillithe (ró-bheag)" + +#: pack-bitmap.c +msgid "corrupted bitmap index file (wrong header)" +msgstr "comhad innéacs bitmap truaillithe (ceanntásc mÃcheart)" + +#: pack-bitmap.c +#, c-format +msgid "unsupported version '%d' for bitmap index file" +msgstr "leagan gan tacaÃocht '%d' do chomhad innéacs bitmap" + +#: pack-bitmap.c +msgid "corrupted bitmap index file (too short to fit hash cache)" +msgstr "" +"comhad innéacs bitmap truaillithe (róghearr chun taisce hash a fheistiú)" + +#: pack-bitmap.c +msgid "corrupted bitmap index file (too short to fit lookup table)" +msgstr "" +"comhad innéacs bitmap truaillithe (róghearr chun tábla cuardaigh a fheistiú)" + +#: pack-bitmap.c +msgid "" +"corrupted bitmap index file (too short to fit pseudo-merge table header)" +msgstr "" +"comhad innéacs bitmap truaillithe (ró-ghearr chun ceannteideal tábla bréag-" +"chumasc a fheistiú)" + +#: pack-bitmap.c +msgid "corrupted bitmap index file (too short to fit pseudo-merge table)" +msgstr "" +"comhad innéacs bitmap truaillithe (ró-ghearr chun tábla bréag-chumasc a " +"fheistiú)" + +#: pack-bitmap.c +msgid "corrupted bitmap index file, pseudo-merge table too short" +msgstr "comhad innéacs bitmap truaillithe, tábla bréag-chumasc ró-ghearr" + +#: pack-bitmap.c +#, c-format +msgid "duplicate entry in bitmap index: '%s'" +msgstr "iontráil dúblach in innéacs bitmap: '%s'" + +#: pack-bitmap.c +#, c-format +msgid "corrupt ewah bitmap: truncated header for entry %d" +msgstr "bitmap ewah truaillithe: ceannteideal gearrtha le haghaidh iontráil %d" + +#: pack-bitmap.c +#, c-format +msgid "corrupt ewah bitmap: commit index %u out of range" +msgstr "bitmap ewah truaillithe: innéacs tiomanta %u lasmuigh den raon" + +#: pack-bitmap.c +msgid "corrupted bitmap pack index" +msgstr "innéacs pacáiste bitmap truaillte" + +#: pack-bitmap.c +msgid "invalid XOR offset in bitmap pack index" +msgstr "fritháireamh XOR neamhbhailà in innéacs pacáiste bitmap" + +#: pack-bitmap.c +msgid "cannot fstat bitmap file" +msgstr "nà féidir comhad bitmap fstat" + +#: pack-bitmap.c +msgid "checksum doesn't match in MIDX and bitmap" +msgstr "nà mheaitseálann seicsum i MIDX agus bitmap" + +#: pack-bitmap.c +msgid "multi-pack bitmap is missing required reverse index" +msgstr "tá an t-innéacs droim riachtanach in easnamh ilphacáiste" + +#: pack-bitmap.c +#, c-format +msgid "could not open pack %s" +msgstr "nà fhéadfaà pacáiste %s a oscailt" + +#: pack-bitmap.c +msgid "corrupt bitmap lookup table: triplet position out of index" +msgstr "tábla cuardaigh bitmap truaillithe: suÃomh triplet as innéacs" + +#: pack-bitmap.c +msgid "corrupt bitmap lookup table: xor chain exceeds entry count" +msgstr "tábla cuardaigh bitmap truaillithe: sáraÃonn slabhra xor lÃon iontrála" + +#: pack-bitmap.c +#, c-format +msgid "corrupt bitmap lookup table: commit index %u out of range" +msgstr "" +"tábla cuardaigh bitmap truaillithe: innéacs tiomanta %u lasmuigh den raon" + +#: pack-bitmap.c +#, c-format +msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\"" +msgstr "" +"bitmap ewah truaillithe: ceannteideal gearrtha le haghaidh bitmap de " +"thiomantas “%sâ€" + +#: pack-bitmap.c +#, c-format +msgid "unable to load pack: '%s', disabling pack-reuse" +msgstr "in ann pacáiste a luchtú: '%s', athúsáid pacáiste a dhÃchumasú" + +#: pack-bitmap.c +msgid "unable to compute preferred pack, disabling pack-reuse" +msgstr "in ann pacáiste roghnaithe a rÃomh, athúsáid pacáiste a dhÃchumasú" + +#: pack-bitmap.c +#, c-format +msgid "object '%s' not found in type bitmaps" +msgstr "nÃor aimsÃodh réad '%s' i gcineál bitmaps" + +#: pack-bitmap.c +#, c-format +msgid "object '%s' does not have a unique type" +msgstr "nÃl cineál uathúil ag réad '%s'" + +#: pack-bitmap.c +#, c-format +msgid "object '%s': real type '%s', expected: '%s'" +msgstr "réad '%s': fÃor-chineál '%s', ag súil leis: '%s'" + +#: pack-bitmap.c +#, c-format +msgid "object not in bitmap: '%s'" +msgstr "réad nach bhfuil i mbitmap: '%s'" + +#: pack-bitmap.c +msgid "failed to load bitmap indexes" +msgstr "theip ar innéacsanna bitmap a luchtú" + +#: pack-bitmap.c +msgid "you must specify exactly one commit to test" +msgstr "nà mór duit tiomantas amháin a shonrú go dÃreach chun tástáil" + +#: pack-bitmap.c +#, c-format +msgid "commit '%s' doesn't have an indexed bitmap" +msgstr "cumann nach bhfuil bitmap innéacsaithe ag '%s'" + +#: pack-bitmap.c +msgid "mismatch in bitmap results" +msgstr "mÃmheaitseáil i dtorthaà bitmap" + +#: pack-bitmap.c +#, c-format +msgid "pseudo-merge index out of range (%<PRIu32> >= %<PRIuMAX>)" +msgstr "innéacs bréag-chumaisc lasmuigh den raon (%<PRIu32> >= %<PRIuMAX>)" + +#: pack-bitmap.c +#, c-format +msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>" +msgstr "" +"nà raibh '%s' in ann teacht i bpacáiste '%s' ag fhritháireamh%<PRIuMAX>" + +#: pack-bitmap.c +#, c-format +msgid "unable to get disk usage of '%s'" +msgstr "nà féidir úsáid diosca a fháil de '%s'" + +#: pack-bitmap.c +#, c-format +msgid "bitmap file '%s' has invalid checksum" +msgstr "tá seicsum neamhbhailà ag comhad bitmap '%s'" + +#: pack-mtimes.c +#, c-format +msgid "mtimes file %s is too small" +msgstr "tá comhad mtimes %s ró-bheag" + +#: pack-mtimes.c +#, c-format +msgid "mtimes file %s has unknown signature" +msgstr "tá sÃniú anaithnid ag comhad mtimes %s" + +#: pack-mtimes.c +#, c-format +msgid "mtimes file %s has unsupported version %<PRIu32>" +msgstr "tá leagan neamh-tacaithe ag comhad mtimes %s% <PRIu32>" + +#: pack-mtimes.c +#, c-format +msgid "mtimes file %s has unsupported hash id %<PRIu32>" +msgstr "tá id hash neamh-tacaithe ag comhad %s mtimes% <PRIu32>" + +#: pack-mtimes.c +#, c-format +msgid "mtimes file %s is corrupt" +msgstr "tá comhad mtimes %s truaillithe" + +#: pack-revindex.c +#, c-format +msgid "reverse-index file %s is too small" +msgstr "tá comhad innéacs droim %s róbheag" + +#: pack-revindex.c +#, c-format +msgid "reverse-index file %s is corrupt" +msgstr "tá comhad innéacs droim %s truaillithe" + +#: pack-revindex.c +#, c-format +msgid "reverse-index file %s has unknown signature" +msgstr "tá sÃniú anaithnid ag comhad innéacs droim %s" + +#: pack-revindex.c +#, c-format +msgid "reverse-index file %s has unsupported version %<PRIu32>" +msgstr "tá leagan neamh-tacaithe ag comhad innéacs droim %s% <PRIu32>" + +#: pack-revindex.c +#, c-format +msgid "reverse-index file %s has unsupported hash id %<PRIu32>" +msgstr "tá id hash neamh-tacaithe ag comhad innéacs droim %s% <PRIu32>" + +#: pack-revindex.c +msgid "invalid checksum" +msgstr "seiceáil neamhbhailÃ" + +#: pack-revindex.c +#, c-format +msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>" +msgstr "" +"suÃomh innéacs-athraithe neamhbhailà ag %<PRIu64>: %<PRIu32> != %<PRIu32>" + +#: pack-revindex.c +msgid "multi-pack-index reverse-index chunk is the wrong size" +msgstr "tá smután droim ar ais-innéacs il-phacáiste ar an méid mÃcheart" + +#: pack-revindex.c +msgid "could not determine preferred pack" +msgstr "nà fhéadfaà pacáiste is fearr a chinneadh" + +#: pack-write.c +msgid "cannot both write and verify reverse index" +msgstr "nà féidir innéacs droim a scrÃobh agus a fhÃorú" + +#: pack-write.c +#, c-format +msgid "could not stat: %s" +msgstr "nà fhéadfaà stat: %s" + +#: pack-write.c +#, c-format +msgid "failed to make %s readable" +msgstr "theip ar %s a dhéanamh inléite" + +#: pack-write.c +#, c-format +msgid "could not write '%s' promisor file" +msgstr "nà fhéadfaà comhad gealltanais '%s' a scrÃobh" + +#: packfile.c +msgid "offset before end of packfile (broken .idx?)" +msgstr "fhritháireamh roimh dheireadh an phackfile (.idx briste?)" + +#: packfile.c +#, c-format +msgid "packfile %s cannot be mapped%s" +msgstr "nà féidir comhaid pacáiste %s a mhapáil %s" + +#: packfile.c +#, c-format +msgid "offset before start of pack index for %s (corrupt index?)" +msgstr "" +"fhritháireamh roimh thús an innéacs pacáiste do %s (innéacs truaillithe?)" + +#: packfile.c +#, c-format +msgid "offset beyond end of pack index for %s (truncated index?)" +msgstr "" +"fhritháireamh thar dheireadh an innéacs pacáiste do %s (innéacs gearrtha?)" + +#: parse-options-cb.c +#, c-format +msgid "malformed expiration date '%s'" +msgstr "dáta éaga mÃfhoirmithe '%s'" + +#: parse-options-cb.c +#, c-format +msgid "option `%s' expects \"always\", \"auto\", or \"never\"" +msgstr "tá rogha `%s' ag súil le “i gcónaÃâ€, “uathoibrÃochâ€, nó “riamhâ€" + +#: parse-options-cb.c +#, c-format +msgid "malformed object name '%s'" +msgstr "ainm réad mÃfhoirmithe '%s'" + +#: parse-options-cb.c +#, c-format +msgid "option `%s' expects \"%s\" or \"%s\"" +msgstr "tá rogha `%s' ag súil le “%s†nó “%sâ€" + +#: parse-options.c +#, c-format +msgid "%s requires a value" +msgstr "TeastaÃonn luach ó %s" + +#: parse-options.c +#, c-format +msgid "%s takes no value" +msgstr "Nà ghlacann %s aon luach" + +#: parse-options.c +#, c-format +msgid "%s isn't available" +msgstr "NÃl %s ar fáil" + +#: parse-options.c +#, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "luach %s do %s nach bhfuil sa raon [%<PRIdMAX>,%<PRIdMAX>]" + +#: parse-options.c +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "Tá %s ag súil le luach sláireach le iarmhÃr roghnach k/m/g" + +#: parse-options.c +#, c-format +msgid "%s expects a non-negative integer value with an optional k/m/g suffix" +msgstr "" +"Tá %s ag súil le luach sláimhir neamh-dhiúltach le iarmhÃr roghnach k/m/g" + +#: parse-options.c +#, c-format +msgid "ambiguous option: %s (could be --%s%s or --%s%s)" +msgstr "rogha débhrÃoch: %s (d'fhéadfadh a bheith --%s%s nó --%s%s)" + +#: parse-options.c +#, c-format +msgid "did you mean `--%s` (with two dashes)?" +msgstr "an raibh i gceist agat `--%s` (le dhá shraith)?" + +#: parse-options.c +#, c-format +msgid "alias of --%s" +msgstr "alias de --%s" + +#: parse-options.c +msgid "need a subcommand" +msgstr "fo-ordú ag teastáil" + +#: parse-options.c +#, c-format +msgid "unknown option `%s'" +msgstr "rogha anaithnid `%s'" + +#: parse-options.c +#, c-format +msgid "unknown switch `%c'" +msgstr "lasc anaithnid `%c'" + +#: parse-options.c +#, c-format +msgid "unknown non-ascii option in string: `%s'" +msgstr "rogha neamh-ascii anaithnid i sreang: `%s'" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the long form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[=<%s>]" +msgstr "[=<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string +#. stands for an optional value given to a command +#. line option in the short form, and "<>" is there +#. as a convention to signal that it is a +#. placeholder (i.e. the user should substitute it +#. with the real value). If your language uses a +#. different convention, you can change "<%s>" part +#. to match yours, e.g. it might use "|%s|" instead, +#. or if the alphabet is different enough it may use +#. "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid "[<%s>]" +msgstr "[<%s>]" + +#. TRANSLATORS: The "<%s>" part of this string stands for a +#. value given to a command line option, and "<>" is there +#. as a convention to signal that it is a placeholder +#. (i.e. the user should substitute it with the real value). +#. If your language uses a different convention, you can +#. change "<%s>" part to match yours, e.g. it might use +#. "|%s|" instead, or if the alphabet is different enough it +#. may use "%s" without any placeholder signal. Most +#. translations leave this message as is. +#. +#: parse-options.c +#, c-format +msgid " <%s>" +msgstr " <%s>" + +#: parse-options.c +msgid "..." +msgstr "..." + +#: parse-options.c +#, c-format +msgid "usage: %s" +msgstr "úsáid: %s" + +#. TRANSLATORS: the colon here should align with the +#. one in "usage: %s" translation. +#. +#: parse-options.c +#, c-format +msgid " or: %s" +msgstr " nó: %s" + +#. TRANSLATORS: You should only need to translate this format +#. string if your language is a RTL language (e.g. Arabic, +#. Hebrew etc.), not if it's a LTR language (e.g. German, +#. Russian, Chinese etc.). +#. * +#. When a translated usage string has an embedded "\n" it's +#. because options have wrapped to the next line. The line +#. after the "\n" will then be padded to align with the +#. command name, such as N_("git cmd [opt]\n<8 +#. spaces>[opt2]"), where the 8 spaces are the same length as +#. "git cmd ". +#. * +#. This format string prints out that already-translated +#. line. The "%*s" is whitespace padding to account for the +#. padding at the start of the line that we add in this +#. function. The "%s" is a line in the (hopefully already +#. translated) N_() usage string, which contained embedded +#. newlines before we split it up. +#. +#: parse-options.c +#, c-format +msgid "%*s%s" +msgstr "%*s%s" + +#: parse-options.c +#, c-format +msgid " %s" +msgstr " %s" + +#: parse-options.c +msgid "-NUM" +msgstr "-NUMBER" + +#: parse-options.c +#, c-format +msgid "opposite of --no-%s" +msgstr "os coinne de --no-%s" + +#: parse-options.h +msgid "expiry-date" +msgstr "dáta éaga" + +#: parse-options.h +msgid "no-op (backward compatibility)" +msgstr "no-op (comhoiriúnacht ar chúl)" + +#: parse-options.h +msgid "be more verbose" +msgstr "a bheith nÃos inbhreithnithe" + +#: parse-options.h +msgid "be more quiet" +msgstr "a bheith nÃos ciúine" + +#: parse-options.h +msgid "use <n> digits to display object names" +msgstr "úsáid dhigit <n>à chun ainmneacha réada a thaispe" + +#: parse-options.h +msgid "prefixed path to initial superproject" +msgstr "cosán réamhshocraithe chuig an superproject tosaigh" + +#: parse-options.h +msgid "how to strip spaces and #comments from message" +msgstr "conas spásanna agus #comments a scriosadh ó theachtaireacht" + +#: parse-options.h +msgid "read pathspec from file" +msgstr "léigh pathspec ón gcomhad" + +#: parse-options.h +msgid "" +"with --pathspec-from-file, pathspec elements are separated with NUL character" +msgstr "" +"le --pathspec-from-file, déantar eilimintà pathspec scartha le carachtar NUL" + +#: parse.c +#, c-format +msgid "bad boolean environment value '%s' for '%s'" +msgstr "droch-luach timpeallachta boolean '%s' do '%s'" + +#: path-walk.c +#, c-format +msgid "failed to walk children of tree %s: not found" +msgstr "theip ar pháistà crann %s a shiúl: nÃor aimsÃodh" + +#: path-walk.c +#, c-format +msgid "failed to find object %s" +msgstr "theip ar réad %s a aimsiú" + +#: path-walk.c +#, c-format +msgid "failed to find tag %s" +msgstr "theip ar chlib %s a aimsiú" + +#: path-walk.c +msgid "failed to setup revision walk" +msgstr "theip orthu siúlóid athbhreithnithe" + +#: path.c +#, c-format +msgid "Could not make %s writable by group" +msgstr "Nà fhéadfaà %s a dhéanamh inscrÃofa de réir grúpa" + +#: pathspec.c +msgid "Escape character '\\' not allowed as last character in attr value" +msgstr "" +"Nà cheadaÃtear carachtar éalaithe '\\' mar charachtar deireanach i luach attr" + +#: pathspec.c +msgid "Only one 'attr:' specification is allowed." +msgstr "Nà cheadaÃtear ach sonraÃocht 'attr: 'amháin." + +#: pathspec.c +msgid "attr spec must not be empty" +msgstr "nà chóir go mbeadh sonraÃocht attr folamh" + +#: pathspec.c +#, c-format +msgid "invalid attribute name %s" +msgstr "ainm tréithe neamhbhailà %s" + +#: pathspec.c +msgid "global 'glob' and 'noglob' pathspec settings are incompatible" +msgstr "nÃl socruithe pathspec domhanda 'glob' agus 'noglob' neamhoiriúnach" + +#: pathspec.c +msgid "" +"global 'literal' pathspec setting is incompatible with all other global " +"pathspec settings" +msgstr "" +"nÃl suÃomh cosáin domhanda 'litriúil' gan luà le gach socruithe beatháin " +"domhanda eile" + +#: pathspec.c +msgid "invalid parameter for pathspec magic 'prefix'" +msgstr "paraiméadar neamhbhailà do 'réimÃr' draÃochta pathspec" + +#: pathspec.c +#, c-format +msgid "Invalid pathspec magic '%.*s' in '%s'" +msgstr "DraÃocht pathspec neamhbhailà '%.*s' i '%s'" + +#: pathspec.c +#, c-format +msgid "Missing ')' at the end of pathspec magic in '%s'" +msgstr "Ar iarraidh ')' ag deireadh draÃochta pathspec i '%s'" + +#: pathspec.c +#, c-format +msgid "Unimplemented pathspec magic '%c' in '%s'" +msgstr "DraÃocht pathspec neamh-chur i bhfeidhm '%c' i '%s'" + +#: pathspec.c +#, c-format +msgid "%s: 'literal' and 'glob' are incompatible" +msgstr "%s: NÃl 'literal' agus 'glob' neamhoiriúnach" + +#: pathspec.c +#, c-format +msgid "'%s' is outside the directory tree" +msgstr "Tá '%s' lasmuigh den chrann eolaire" + +#: pathspec.c +#, c-format +msgid "%s: '%s' is outside repository at '%s'" +msgstr "%s: Tá '%s' an stór lasmuigh ag '%s'" + +#: pathspec.c +#, c-format +msgid "'%s' (mnemonic: '%c')" +msgstr "'%s' (mnemonic: '%c')" + +#: pathspec.c +#, c-format +msgid "%s: pathspec magic not supported by this command: %s" +msgstr "%s: nach dtacaÃonn an t-ordú seo le draÃocht pathspec: %s" + +#: pathspec.c +#, c-format +msgid "pathspec '%s' is beyond a symbolic link" +msgstr "tá pathspec '%s' thar nasc siombalach" + +#: pathspec.c +#, c-format +msgid "line is badly quoted: %s" +msgstr "tá an lÃne luaite go dona: %s" + +#: pkt-line.c +msgid "unable to write flush packet" +msgstr "in ann pacáiste srutháin a scrÃobh" + +#: pkt-line.c +msgid "unable to write delim packet" +msgstr "in ann pacáiste delim a scrÃobh" + +#: pkt-line.c +msgid "unable to write response end packet" +msgstr "in ann pacáiste deiridh freagartha a scrÃobh" + +#: pkt-line.c +msgid "flush packet write failed" +msgstr "theip ar scrÃobh paicéad sru" + +#: pkt-line.c +msgid "protocol error: impossibly long line" +msgstr "earráid prótacal: lÃne fhada dodhéanta" + +#: pkt-line.c +msgid "packet write with format failed" +msgstr "theip ar scrÃobh pacáiste le formáid" + +#: pkt-line.c +msgid "packet write failed - data exceeds max packet size" +msgstr "theip ar scrÃobh paicéad - sáraÃonn sonraà méid uasta an" + +#: pkt-line.c +#, c-format +msgid "packet write failed: %s" +msgstr "theip ar scrÃobh pacáiste: %s" + +#: pkt-line.c +msgid "read error" +msgstr "earráid léigh" + +#: pkt-line.c +msgid "the remote end hung up unexpectedly" +msgstr "crochadh an deireadh iargúlta suas gan choinne" + +#: pkt-line.c +#, c-format +msgid "protocol error: bad line length character: %.4s" +msgstr "earráid prótacal: carachtar fad droch-lÃne: %.4s" + +#: pkt-line.c +#, c-format +msgid "protocol error: bad line length %d" +msgstr "earráid prótacal: fad droch-lÃne %d" + +#: pkt-line.c sideband.c +#, c-format +msgid "remote error: %s" +msgstr "earráid iargúlta: %s" + +#: preload-index.c +msgid "Refreshing index" +msgstr "Innéacs athnuachana" + +#: preload-index.c +#, c-format +msgid "unable to create threaded lstat: %s" +msgstr "nach féidir lstat snáithithe a chruthú: %s" + +#: pretty.c +msgid "unable to parse --pretty format" +msgstr "in ann formáid --pretty a pháirseáil" + +#: promisor-remote.c +msgid "lazy fetching disabled; some objects may not be available" +msgstr "" +"tarraingt leisciúil mÃchumasaithe; b'fhéidir nach mbeidh roinnt rudaà ar fáil" + +#: promisor-remote.c +msgid "promisor-remote: unable to fork off fetch subprocess" +msgstr "gealltó-iargúlta: nà féidir leis an bhfophróiseas faighte a fhorc" + +#: promisor-remote.c +msgid "promisor-remote: could not write to fetch subprocess" +msgstr "gealltó-iargúlta: nà fhéadfaà scrÃobh chun fophróiseas a fháil" + +#: promisor-remote.c +msgid "promisor-remote: could not close stdin to fetch subprocess" +msgstr "gealltó-iargúlta: nà fhéadfaà stdin a dhúnadh chun fophróiseas a fháil" + +#: promisor-remote.c +#, c-format +msgid "promisor remote name cannot begin with '/': %s" +msgstr "nà féidir ainm iargúlta gealltanaà tosú le '/': %s" + +#: promisor-remote.c +#, c-format +msgid "could not fetch %s from promisor remote" +msgstr "nà fhéadfaà %s a fháil ó iargúlta gealltanach" + +#: promisor-remote.c +#, c-format +msgid "no or empty URL advertised for remote '%s'" +msgstr "nÃl aon URL nó folamh fógraithe le haghaidh iargúlta '%s'" + +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "iargúlta ar a dtugtar '%s' ach le URL '%s' in ionad '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown '%s' value for '%s' config option" +msgstr "luach '%s' anaithnid do rogha cumraithe '%s'" + +#: promisor-remote.c +#, c-format +msgid "unknown element '%s' from remote info" +msgstr "eilimint anaithnid '%s' ó fhaisnéis iargúlta" + +#: promisor-remote.c +#, c-format +msgid "accepted promisor remote '%s' not found" +msgstr "nár aimsÃodh gealltanas iargúlta '%s'" + +#: protocol-caps.c +msgid "object-info: expected flush after arguments" +msgstr "ear-eolas: súil le sruth tar éis argóintÃ" + +#: prune-packed.c +msgid "Removing duplicate objects" +msgstr "Rudaà dúblacha a bhaint" + +#: pseudo-merge.c +#, c-format +msgid "failed to load pseudo-merge regex for %s: '%s'" +msgstr "theip ar régex bréag-cumaisc a luchtú do %s: '%s'" + +#: pseudo-merge.c +#, c-format +msgid "%s must be non-negative, using default" +msgstr "Nà mór %s a bheith neamh-dhiúltach, ag baint úsáide as" + +#: pseudo-merge.c +#, c-format +msgid "%s must be between 0 and 1, using default" +msgstr "Caithfidh %s a bheith idir 0 agus 1, ag baint úsáide as réamhshocrú" + +#: pseudo-merge.c +#, c-format +msgid "%s must be positive, using default" +msgstr "Caithfidh %s a bheith dearfach, ag úsáid réamhshocraithe" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' missing required pattern" +msgstr "grúpa bréagchumaisc '%s' ar iarraidh patrún riachtanach" + +#: pseudo-merge.c +#, c-format +msgid "pseudo-merge group '%s' has unstable threshold before stable one" +msgstr "tá tairseach éagobhsaà ag an ngrúpa bréagchumaisc '%s' roimh cheann" + +#: pseudo-merge.c +#, c-format +msgid "" +"pseudo-merge regex from config has too many capture groups (max=%<PRIuMAX>)" +msgstr "" +"tá an iomarca grúpaà gabhála sa regex pseudo-merge ón chumraÃocht " +"(uasmhéid=%<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge read out-of-bounds (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "" +"léamh sÃnte cumaisc bhréige lasmuigh de theorainneacha (%<PRIuMAX> >= " +"%<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge entry is too short (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "tá an iontráil shÃnte chumaisc ró-ghearr (%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not find pseudo-merge for commit %s at offset %<PRIuMAX>" +msgstr "" +"nà fhéadfaà a aimsiú bréag-chumasc do thiomantas %s ag " +"fhritháireamh%<PRIuMAX>" + +#: pseudo-merge.c +#, c-format +msgid "extended pseudo-merge lookup out-of-bounds (%<PRIu32> >= %<PRIu32>)" +msgstr "" +"cuardach sÃnte cumaisc bhréige lasmuigh de theorainneacha (%<PRIu32> >= " +"%<PRIu32>)" + +#: pseudo-merge.c +#, c-format +msgid "out-of-bounds read: (%<PRIuMAX> >= %<PRIuMAX>)" +msgstr "léamh lasmuigh de theorainneacha: (%<PRIuMAX> >= %<PRIuMAX>)" + +#: pseudo-merge.c +#, c-format +msgid "could not read extended pseudo-merge table for commit %s" +msgstr "" +"nà fhéadfaà tábla bréag-chumaisc leathnaithe a léamh le haghaidh tiomanta %s" + +#: range-diff.c +msgid "could not start `log`" +msgstr "nà fhéadfaà 'log' a thosú" + +#: range-diff.c +msgid "could not read `log` output" +msgstr "nà raibh in ann aschur `log` a léamh" + +#: range-diff.c sequencer.c +#, c-format +msgid "could not parse commit '%s'" +msgstr "nà fhéadfaà gealladh '%s' a pháirseáil" + +#: range-diff.c +#, c-format +msgid "" +"could not parse first line of `log` output: did not start with 'commit ': " +"'%s'" +msgstr "" +"nà raibh sé in ann an chéad lÃne d'aschur `log` a pháirseáil: nÃor thosaigh " +"sé le 'commit': '%s'" + +#: range-diff.c +#, c-format +msgid "could not parse git header '%.*s'" +msgstr "nÃorbh fhéidir ceanntásc git a pharsáil '%.*s'" + +#: range-diff.c +msgid "failed to generate diff" +msgstr "theip ar éagsúlacht a ghiniúint" + +#: range-diff.c +#, c-format +msgid "could not parse log for '%s'" +msgstr "nà raibh in ann logáil a pháirseáil le haghaidh '%s'" + +#: reachable.c +#, c-format +msgid "invalid extra cruft tip: '%s'" +msgstr "tip cruft bhreise neamhbhailÃ: '%s'" + +#: reachable.c +msgid "unable to enumerate additional recent objects" +msgstr "in ann rudaà breise le déanaà a áireamh" + +#: read-cache.c +#, c-format +msgid "will not add file alias '%s' ('%s' already exists in index)" +msgstr "" +"nà chuirfidh sé alias comhad '%s' leis (tá '%s' ann cheana féin san innéacs)" + +#: read-cache.c +msgid "cannot create an empty blob in the object database" +msgstr "nà féidir le blob folamh a chruthú sa bhunachar sonraà réad" + +#: read-cache.c +#, c-format +msgid "%s: can only add regular files, symbolic links or git-directories" +msgstr "" +"%s: nà féidir ach comhaid rialta, naisc siombalacha nó eolairà git-eolairà a " +"chur leis" + +#: read-cache.c +#, c-format +msgid "unable to index file '%s'" +msgstr "nà féidir an comhad '%s' a innéacsú" + +#: read-cache.c +#, c-format +msgid "unable to add '%s' to index" +msgstr "nà féidir '%s' a chur leis an innéacs" + +#: read-cache.c +#, c-format +msgid "'%s' appears as both a file and as a directory" +msgstr "Tá '%s' le feiceáil mar chomhad agus mar eolaire" + +#: read-cache.c +msgid "Refresh index" +msgstr "Innéacs athnuachan" + +#: read-cache.c +#, c-format +msgid "" +"index.version set, but the value is invalid.\n" +"Using version %i" +msgstr "" +"index.version socraithe, ach tá an luach neamhbhailÃ.\n" +"Ag baint úsáide as leagan %i" + +#: read-cache.c +#, c-format +msgid "" +"GIT_INDEX_VERSION set, but the value is invalid.\n" +"Using version %i" +msgstr "" +"socraigh GIT_INDEX_VERSION, ach tá an luach neamhbhailÃ.\n" +"Ag baint úsáide as leagan %i" + +#: read-cache.c +#, c-format +msgid "bad signature 0x%08x" +msgstr "droch-shÃniú 0x%08x" + +#: read-cache.c +#, c-format +msgid "bad index version %d" +msgstr "leagan innéacs droch%d" + +#: read-cache.c +msgid "bad index file sha1 signature" +msgstr "comhad innéacs droch-sha1 sÃniú" + +#: read-cache.c +#, c-format +msgid "index uses %.4s extension, which we do not understand" +msgstr "úsáideann innéacs sÃneadh %.4s, nach dtuigimid" + +#: read-cache.c +#, c-format +msgid "ignoring %.4s extension" +msgstr "neamhaird a dhéanamh le sÃneadh %.4s" + +#: read-cache.c +#, c-format +msgid "unknown index entry format 0x%08x" +msgstr "formáid iontrála innéacs anaithnid 0x%08x" + +#: read-cache.c +#, c-format +msgid "malformed name field in the index, near path '%s'" +msgstr "réimse ainm mhÃfhoirmithe san innéacs, in aice le cosán '%s'" + +#: read-cache.c +msgid "unordered stage entries in index" +msgstr "iontrálacha céime neamh-ordaithe san innéacs" + +#: read-cache.c +#, c-format +msgid "multiple stage entries for merged file '%s'" +msgstr "iontrálacha ilchéime do chomhad cumaisc '%s'" + +#: read-cache.c +#, c-format +msgid "unordered stage entries for '%s'" +msgstr "iontrálacha stáitse neamh-ordaithe do '%s'" + +#: read-cache.c +#, c-format +msgid "unable to create load_cache_entries thread: %s" +msgstr "nà féidir an snáithe load_cache_entries a chruthú: %s" + +#: read-cache.c +#, c-format +msgid "unable to join load_cache_entries thread: %s" +msgstr "nà féidir teacht le snáithe load_cache_entries thread: %s" + +#: read-cache.c +#, c-format +msgid "%s: index file open failed" +msgstr "%s: theip ar oscailt comhad innéacs" + +#: read-cache.c +#, c-format +msgid "%s: cannot stat the open index" +msgstr "%s: nà féidir an t-innéacs oscailte a stáit" + +#: read-cache.c +#, c-format +msgid "%s: index file smaller than expected" +msgstr "%s: comhad innéacs nÃos lú ná mar a bhà súil leis" + +#: read-cache.c +#, c-format +msgid "%s: unable to map index file%s" +msgstr "%s: nà féidir comhad innéacs %s a mhapáil" + +#: read-cache.c +#, c-format +msgid "unable to create load_index_extensions thread: %s" +msgstr "nach féidir snáithe load_index_extensions a chruthú: %s" + +#: read-cache.c +#, c-format +msgid "unable to join load_index_extensions thread: %s" +msgstr "nà féidir teacht le snáithe load_index_extensions: %s" + +#: read-cache.c +#, c-format +msgid "could not freshen shared index '%s'" +msgstr "nà raibh in ann innéacs roinnte '%s' a athnuachan" + +#: read-cache.c +#, c-format +msgid "broken index, expect %s in %s, got %s" +msgstr "innéacs briste, súil le %s i %s, fuair %s" + +#: read-cache.c +msgid "cannot write split index for a sparse index" +msgstr "nà féidir innéacs scoilte a scrÃobh le haghaidh innéacs neall" + +#: read-cache.c +msgid "failed to convert to a sparse-index" +msgstr "theip ar thiontú go innéacs neamhchoitianta" + +#: read-cache.c +#, c-format +msgid "unable to open git dir: %s" +msgstr "in ann git dir a oscailt: %s" + +#: read-cache.c +#, c-format +msgid "unable to unlink: %s" +msgstr "nach féidir dÃnasc a dhéanamh: %s" + +#: read-cache.c +#, c-format +msgid "cannot fix permission bits on '%s'" +msgstr "nà féidir giotáin ceada a shocrú ar '%s'" + +#: read-cache.c +#, c-format +msgid "%s: cannot drop to stage #0" +msgstr "%s: nà féidir titim go dtà céim #0" + +#: read-cache.c +#, c-format +msgid "unexpected diff status %c" +msgstr "stádas diff gan choinne %c" + +#: read-cache.c +#, c-format +msgid "remove '%s'\n" +msgstr "bain '%s'\n" + +#: rebase-interactive.c +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 "" +"Is féidir leat é seo a shocrú le 'git rebase --edit-todo' agus ansin 'git " +"rebase --continue' a rith.\n" +"Nó is féidir leat an rebase a chur le 'git rebase --abort'.\n" + +#: rebase-interactive.c +#, c-format +msgid "" +"unrecognized setting %s for option rebase.missingCommitsCheck. Ignoring." +msgstr "" +"socrú neamhaithnithe %s le haghaidh rogha rebase.missingCommitsCheck. " +"Neamhaird a dhéanamh." + +#: rebase-interactive.c +msgid "" +"\n" +"Commands:\n" +"p, pick <commit> = use commit\n" +"r, reword <commit> = use commit, but edit the commit message\n" +"e, edit <commit> = use commit, but stop for amending\n" +"s, squash <commit> = use commit, but meld into previous commit\n" +"f, fixup [-C | -c] <commit> = like \"squash\" but keep only the previous\n" +" commit's log message, unless -C is used, in which case\n" +" keep only this commit's message; -c is same as -C but\n" +" opens the editor\n" +"x, exec <command> = run command (the rest of the line) using shell\n" +"b, break = stop here (continue rebase later with 'git rebase --continue')\n" +"d, drop <commit> = remove commit\n" +"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" +"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 "" +"\n" +"Orduithe:\n" +"p, pioc <commit>= úsáid tiomantas\n" +"r, athfhocal <commit>= bain úsáid as tiomantas, ach cuir an teachtaireacht " +"tiomanta in eagar\n" +"e, eagarthóire <commit>acht = tiomantas a úsáid, ach stop le haghaidh leasú\n" +"s, squash <commit>= gealltanas a úsáid, ach cuir isteach i dtiomantas roimhe " +"seo\n" +"f, fixup [-C | -c] <commit>= cosúil le “squash†ach nà choinnigh ach an " +"ceann roimhe seo\n" +" teachtaireacht logála commit, mura n-úsáidtear -C, sa " +"chás sin\n" +" coinnigh ach teachtaireacht an tiomanta seo; tá -c mar an " +"gcéanna le -C ach\n" +" osclaÃonn an t-eagarthóir\n" +"x, exec <command>= ordú reáchtáil (an chuid eile den lÃne) ag baint úsáide " +"as bhlaosc\n" +"b, briseadh = stad anseo (lean ar aghaidh ar rebase nÃos déanaà le 'git " +"rebase --continue')\n" +"d, titim <commit>= bain tiomantas\n" +"l, lipéad <label>= lipéad CEAD reatha le hainm\n" +"t, athshocraigh <label>= athshocraigh HEAD go lipéad\n" +"<oneline>m, cumaisc [-C <commit>| -c<commit>] <label>[#]\n" +" tiomantas cumaisc a chruthú ag baint úsáide as an tiomantas cumaisc\n" +" teachtaireacht (nó an t-aonlÃne, mura raibh aon chomhcheangal " +"cumaisc bunaidh\n" +" sonraithe); bain úsáid as -c chun an teachtai <commit>reacht " +"tiomanta a athfhocal\n" +"<ref>u, update-ref <ref>= rianú sealbhóir áite chun an a nuashonrú\n" +" chuig an bpost seo sna gealltanais nua. Is <ref>é\n" +" nuashonraithe ag deireadh an athbhunaithe\n" +"\n" +"Is féidir na lÃnte seo a athordú; déantar iad a fhorghnÃomhú ó bharr go " +"bun.\n" + +#: rebase-interactive.c +#, c-format +msgid "Rebase %s onto %s (%d command)" +msgid_plural "Rebase %s onto %s (%d commands)" +msgstr[0] "Athbhunú %s ar %s (ordú %d)" +msgstr[1] "Athbhunú %s ar %s (%d orduithe)" +msgstr[2] "Athbhunú %s ar %s (%d orduithe)" + +#: rebase-interactive.c +msgid "" +"\n" +"Do not remove any line. Use 'drop' explicitly to remove a commit.\n" +msgstr "" +"\n" +"Ná bain aon lÃne. Bain úsáid as 'drop' go sainráite chun tiomantas a " +"bhaint.\n" + +#: rebase-interactive.c +msgid "" +"\n" +"If you remove a line here THAT COMMIT WILL BE LOST.\n" +msgstr "" +"\n" +"Má bhaineann tú lÃne anseo CAILLFIDH AN TIOMANTAS.\n" + +#: rebase-interactive.c +msgid "" +"\n" +"You are editing the todo file of an ongoing interactive rebase.\n" +"To continue rebase after editing, run:\n" +" git rebase --continue\n" +"\n" +msgstr "" +"\n" +"Tá tú ag eagarthóireacht ar chomhad todo de athbhunú idirghnÃomhach " +"leanúnach.\n" +"Chun leanúint ar aghaidh ag athbhunú tar éis eagarthóireachta,\n" +" git rebase --continue\n" +"\n" + +#: rebase-interactive.c +msgid "" +"\n" +"However, if you remove everything, the rebase will be aborted.\n" +"\n" +msgstr "" +"\n" +"Mar sin féin, má bhaineann tú gach rud, cuirfear deireadh leis an athbhunú.\n" + +#: rebase-interactive.c +#, c-format +msgid "could not write '%s'." +msgstr "nà fhéadfaà '%s' a scrÃobh." + +#: rebase-interactive.c +#, c-format +msgid "" +"Warning: some commits may have been dropped accidentally.\n" +"Dropped commits (newer to older):\n" +msgstr "" +"Rabhadh: b'fhéidir gur titim roinnt gealltanna de thaisme.\n" +"Gealltanna titim (nÃos nuaà go nÃos sine):\n" + +#: rebase-interactive.c +#, c-format +msgid "" +"To avoid this message, use \"drop\" to explicitly remove a commit.\n" +"\n" +"Use 'git config rebase.missingCommitsCheck' to change the level of " +"warnings.\n" +"The possible behaviours are: ignore, warn, error.\n" +"\n" +msgstr "" +"Chun an teachtaireacht seo a sheachaint, bain úsáid as “titim†chun " +"tiomantas a bhaint go sainráite.\n" +"\n" +"Úsáid 'git config rebase.missingCommitsCheck' chun leibhéal na rabhaidh a " +"athrú.\n" +"Is iad na hiompraÃochtaà féideartha: neamhaird a dhéanamh, rabhadh, " +"earráid.\n" + +#: rebase.c +#, c-format +msgid "%s: 'preserve' superseded by 'merges'" +msgstr "%s: cuireadh 'caomhnú' in ionad 'le' cumaisc '" + +#: ref-filter.c wt-status.c +msgid "gone" +msgstr "imithe" + +#: ref-filter.c +#, c-format +msgid "ahead %d" +msgstr "ar aghaidh %d" + +#: ref-filter.c +#, c-format +msgid "behind %d" +msgstr "taobh thiar de %d" + +#: ref-filter.c +#, c-format +msgid "ahead %d, behind %d" +msgstr "tosaigh %d, taobh thiar de %d" + +#: ref-filter.c +#, c-format +msgid "%%(%.*s) does not take arguments" +msgstr "%%(%.*s) nà ghlacann argóintÃ" + +#: ref-filter.c +#, c-format +msgid "unrecognized %%(%.*s) argument: %s" +msgstr "neamhaithnithe %%(%.*s) argóint: %s" + +#: ref-filter.c +#, c-format +msgid "expected format: %%(color:<color>)" +msgstr "formáid ionchais: %%(color:<dath>)" + +#: ref-filter.c +#, c-format +msgid "unrecognized color: %%(color:%s)" +msgstr "dath gan aithint: %%(color:%s)" + +#: ref-filter.c +#, c-format +msgid "Integer value expected refname:lstrip=%s" +msgstr "Luach sláimhir a bhfuiltear ag súil leis refname:lstrip=%s" + +#: ref-filter.c +#, c-format +msgid "Integer value expected refname:rstrip=%s" +msgstr "Luach sláimhir a bhfuiltear ag súil leis refname:rstrip=%s" + +#: ref-filter.c +#, c-format +msgid "expected %%(trailers:key=<value>)" +msgstr "ionchasach %%(trailers:key=<value>)" + +#: ref-filter.c +#, c-format +msgid "unknown %%(trailers) argument: %s" +msgstr "argóint %%(trailers) anaithnid: %s" + +#: ref-filter.c +#, c-format +msgid "positive value expected contents:lines=%s" +msgstr "ábhar ag súil le luach dearfach:lines=%s" + +#: ref-filter.c +#, c-format +msgid "argument expected for %s" +msgstr "argóint ag súil le haghaidh %s" + +#: ref-filter.c +#, c-format +msgid "positive value expected %s=%s" +msgstr "luach dearfach a bhfuiltear ag súil leis %s=%s" + +#: ref-filter.c +#, c-format +msgid "cannot fully parse %s=%s" +msgstr "nà féidir %s=%s a pháirseáil go hiomlán" + +#: ref-filter.c +#, c-format +msgid "value expected %s=" +msgstr "luach ag súil leis %s=" + +#: ref-filter.c +#, c-format +msgid "positive value expected '%s' in %%(%s)" +msgstr "luach dearfach a bhÃothas ag súil le '%s' i %%(%s)" + +#: ref-filter.c +#, c-format +msgid "expected format: %%(align:<width>,<position>)" +msgstr "ionchasach formáid: %%(align:<width>,<position>)" + +#: ref-filter.c +#, c-format +msgid "unrecognized position:%s" +msgstr "suÃomh gan aithint:%s" + +#: ref-filter.c +#, c-format +msgid "unrecognized width:%s" +msgstr "leithead gan aithint:%s" + +#: ref-filter.c +#, c-format +msgid "unrecognized %%(%s) argument: %s" +msgstr "argóint %%(%s) gan aitheantas: %s" + +#: ref-filter.c +#, c-format +msgid "positive width expected with the %%(align) atom" +msgstr "leithead dearfach a bhÃothas ag súil leis leis an adamh %%(align)" + +#: ref-filter.c +#, c-format +msgid "expected format: %%(ahead-behind:<committish>)" +msgstr "formáid ionchais: %%(ahead-behind:<committish>)" + +#: ref-filter.c +#, c-format +msgid "expected format: %%(is-base:<committish>)" +msgstr "formáid ionchais: %%(is-base:<committish>)" + +#: ref-filter.c +#, c-format +msgid "malformed field name: %.*s" +msgstr "ainm réimse mÃfhoirmithe: %.*s" + +#: ref-filter.c +#, c-format +msgid "unknown field name: %.*s" +msgstr "ainm réimse anaithnid: %.*s" + +#: ref-filter.c +#, c-format +msgid "" +"not a git repository, but the field '%.*s' requires access to object data" +msgstr "" +"nà stórlann git é, ach éilÃonn an réimse '%.*s' rochtain ar shonraà réada" + +#: ref-filter.c +#, c-format +msgid "format: %%(%s) atom used without a %%(%s) atom" +msgstr "formáid: %%(%s) adaim a úsáidtear gan adaim %%(%s)" + +#: ref-filter.c +#, c-format +msgid "format: %%(then) atom used more than once" +msgstr "formáid: %%(then) adaim a úsáidtear nÃos mó ná uair amháin" + +#: ref-filter.c +#, c-format +msgid "format: %%(then) atom used after %%(else)" +msgstr "formáid: %%(then) adaim a úsáidtear tar éis %%(else)" + +#: ref-filter.c +#, c-format +msgid "format: %%(else) atom used more than once" +msgstr "formáid: %%(else) adaim a úsáidtear nÃos mó ná uair amháin" + +#: ref-filter.c +#, c-format +msgid "format: %%(end) atom used without corresponding atom" +msgstr "formáid: %%(end) adaim a úsáidtear gan adaim chomhfhreagrach" + +#: ref-filter.c +#, c-format +msgid "malformed format string %s" +msgstr "teaghrán formáid mhÃfhoirmithe %s" + +#: ref-filter.c +#, c-format +msgid "this command reject atom %%(%.*s)" +msgstr "diúltú an t-ordú seo adamh %%(%.*s)" + +#: ref-filter.c +#, c-format +msgid "--format=%.*s cannot be used with --python, --shell, --tcl" +msgstr "--format=%.*s nà féidir é a úsáid le --python, --shell, --tcl" + +#: ref-filter.c +msgid "failed to run 'describe'" +msgstr "theip ar 'cur sÃos' a rith" + +#: ref-filter.c +#, c-format +msgid "(no branch, rebasing %s)" +msgstr "(gan aon bhrainse, athbhunú %s)" + +#: ref-filter.c +#, c-format +msgid "(no branch, rebasing detached HEAD %s)" +msgstr "(gan aon bhrainse, athbhunú CEAD scoite %s)" + +#: ref-filter.c +#, c-format +msgid "(no branch, bisect started on %s)" +msgstr "(gan aon bhrainse, thosaigh bisect ar %s)" + +#: ref-filter.c +#, c-format +msgid "(HEAD detached at %s)" +msgstr "(HEAD scoite ag %s)" + +#: ref-filter.c +#, c-format +msgid "(HEAD detached from %s)" +msgstr "(CEAD scoite ó %s)" + +#: ref-filter.c +msgid "(no branch)" +msgstr "(gan aon bhrainse)" + +#: ref-filter.c +#, c-format +msgid "missing object %s for %s" +msgstr "réad atá ar iarraidh %s do %s" + +#: ref-filter.c +#, c-format +msgid "parse_object_buffer failed on %s for %s" +msgstr "theip ar parse_object_buffer ar %s do %s" + +#: ref-filter.c +#, c-format +msgid "malformed object at '%s'" +msgstr "réad mÃfhoirmithe ag '%s'" + +#: ref-filter.c +#, c-format +msgid "ignoring ref with broken name %s" +msgstr "neamhaird a dhéanamh ar tagairt le ainm briste %s" + +#: ref-filter.c refs.c +#, c-format +msgid "ignoring broken ref %s" +msgstr "ag déanamh neamhaird ar thagairt briste %s" + +#: ref-filter.c +#, c-format +msgid "format: %%(end) atom missing" +msgstr "formáid :%%(end) ataim ar iarraidh" + +#: ref-filter.c +#, c-format +msgid "malformed object name %s" +msgstr "ainm réad mÃfhoirmithe %s" + +#: ref-filter.c +#, c-format +msgid "option `%s' must point to a commit" +msgstr "caithfidh rogha `%s' a chur in iúl do thiomantas" + +#: ref-filter.h +msgid "key" +msgstr "eochair" + +#: ref-filter.h +msgid "field name to sort on" +msgstr "ainm réimse le sórtáil" + +#: ref-filter.h +msgid "exclude refs which match pattern" +msgstr "a eisiamh iarmhairtà a mheaitseálann patrún" + +#: reflog.c +#, c-format +msgid "not a reflog: %s" +msgstr "nà athbhreithniú: %s" + +#: reflog.c +#, c-format +msgid "no reflog for '%s'" +msgstr "gan aon athbhreithniú do '%s'" + +#: refs.c +#, c-format +msgid "%s does not point to a valid object!" +msgstr "Nà thugann %s in iúl go réad bailÃ!" + +#: refs.c +#, c-format +msgid "" +"Using '%s' as the name for the initial branch. This default branch name\n" +"is subject to change. To configure the initial branch name to use in all\n" +"of your new repositories, which will suppress this warning, call:\n" +"\n" +"\tgit config --global init.defaultBranch <name>\n" +"\n" +"Names commonly chosen instead of 'master' are 'main', 'trunk' and\n" +"'development'. The just-created branch can be renamed via this command:\n" +"\n" +"\tgit branch -m <name>\n" +msgstr "" +"Ag baint úsáide as '%s' mar ainm don bhrainse tosaigh. An ainm brainse " +"réamhshocraithe\n" +"tá sé faoi réir athraithe. Chun an t-ainm brainse tosaigh a chumrú le húsáid " +"i ngach\n" +"de do stór nua, a chuirfidh an rabhadh seo a chur faoi chois, glaoigh ar:\n" +"\n" +"\tgit config --global init.defaultBranch <name>\n" +"\n" +"Is iad na hainmneacha a roghnaÃtear go coitianta in ionad 'máistir' prÃomh " +"',' stoc 'agus\n" +"'forbair'. Is féidir an brainse atá dÃreach cruthaithe a athainmniú trÃd an " +"ordú seo:\n" +"\n" +"\tgit branch -m <name>\n" + +#: refs.c +#, c-format +msgid "could not retrieve `%s`" +msgstr "nà fhéadfaà `%s` a aisghabháil" + +#: refs.c +#, c-format +msgid "invalid branch name: %s = %s" +msgstr "ainm brainse neamhbhailÃ: %s = %s" + +#: refs.c +#, c-format +msgid "ignoring dangling symref %s" +msgstr "ag déanamh neamhaird ar shiomtref crochta %s" + +#: refs.c +#, c-format +msgid "log for ref %s has gap after %s" +msgstr "tá bearna ag logáil le haghaidh tagairt %s tar éis %s" + +#: refs.c +#, c-format +msgid "log for ref %s unexpectedly ended on %s" +msgstr "chrÃochnaigh logáil le haghaidh tagairt %s gan choinne ar %s" + +#: refs.c +#, c-format +msgid "log for %s is empty" +msgstr "tá logáil le haghaidh %s folamh" + +#: refs.c +#, c-format +msgid "refusing to update reflog for pseudoref '%s'" +msgstr "diúltú reflog a nuashonrú do pseudoref '%s'" + +#: refs.c +#, c-format +msgid "refusing to update pseudoref '%s'" +msgstr "diúltú pseudoref '%s' a nuashonrú" + +#: refs.c +#, c-format +msgid "refusing to update reflog with bad name '%s'" +msgstr "diúltú reflog a nuashonrú le droch-ainm '%s'" + +#: refs.c +#, c-format +msgid "refusing to update ref with bad name '%s'" +msgstr "diúltú tagairt a nuashonrú le droch-ainm '%s'" + +#: refs.c +msgid "refusing to force and skip creation of reflog" +msgstr "diúltú cruthú reflog a chur i bhfeidhm agus a scipeáil" + +#: refs.c +#, c-format +msgid "update_ref failed for ref '%s': %s" +msgstr "theip ar update_ref le haghaidh tagairt '%s': %s" + +#: refs.c +#, c-format +msgid "multiple updates for ref '%s' not allowed" +msgstr "nà cheadaÃtear nuashonruithe iolracha le haghaidh tagairt '%s'" + +#: refs.c +msgid "ref updates forbidden inside quarantine environment" +msgstr "nuashonruithe ref toirmiscthe laistigh de" + +#: refs.c +msgid "ref updates aborted by hook" +msgstr "nuashonruithe tagartha a chuirtear deireadh leis" + +#: refs.c +#, c-format +msgid "'%s' exists; cannot create '%s'" +msgstr "Tá '%s' ann; nà féidir '%s' a chruthú" + +#: refs.c +#, c-format +msgid "cannot process '%s' and '%s' at the same time" +msgstr "nà féidir '%s' agus '%s' a phróiseáil ag an am céanna" + +#: refs.c +#, c-format +msgid "could not delete reference %s: %s" +msgstr "nà fhéadfaà tagairt %s a scriosadh: %s" + +#: refs.c +#, c-format +msgid "could not delete references: %s" +msgstr "nà fhéadfaà tagairtà a scriosadh: %s" + +#: refs.c +#, c-format +msgid "Finished dry-run migration of refs, the result can be found at '%s'\n" +msgstr "" +"Imirce tirim crÃochnaithe na n-iarmhairc, is féidir an toradh a fháil ag " +"'%s'\n" + +#: refs.c +#, c-format +msgid "could not remove temporary migration directory '%s'" +msgstr "nà fhéadfaà eolaire imirce sealadach '%s' a bhaint" + +#: refs.c +#, c-format +msgid "migrated refs can be found at '%s'" +msgstr "is féidir airgeanna imirceacha a fháil ag '%s'" + +#: refs/files-backend.c refs/reftable-backend.c +#, c-format +msgid "" +"cannot lock ref '%s': expected symref with target '%s': but is a regular ref" +msgstr "" +"nà féidir tagairt '%s' a ghlasáil: ag súil le symref le sprioc '%s': ach is " +"tagairt rialta é" + +#: refs/files-backend.c +#, c-format +msgid "cannot read ref file '%s'" +msgstr "nà féidir comhad tagartha '%s' a léamh" + +#: refs/files-backend.c +#, c-format +msgid "cannot open directory %s" +msgstr "nà féidir eolaire %s a oscailt" + +#: refs/files-backend.c +msgid "Checking references consistency" +msgstr "Comhsheasmhacht tagairtÃ" + +#: refs/packed-backend.c +#, c-format +msgid "unable to open '%s'" +msgstr "nà féidir '%s' a oscailt" + +#: refs/reftable-backend.c +#, c-format +msgid "refname is dangerous: %s" +msgstr "tá refname contúirteach: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write ref '%s' with nonexistent object %s" +msgstr "ag iarraidh tagairt '%s' a scrÃobh le réad nach bhfuil %s ann" + +#: refs/reftable-backend.c +#, c-format +msgid "trying to write non-commit object %s to branch '%s'" +msgstr "ag iarraidh réad neamh-thiomanta %s a scrÃobh chuig brainse '%s'" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for 'HEAD' (including one via its referent '%s') are not " +"allowed" +msgstr "" +"nà cheadaÃtear nuashonruithe iolracha do 'HEAD' (lena n-áirÃtear ceann trÃd " +"an tagairt '%s')" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': unable to resolve reference '%s'" +msgstr "nà féidir tagairt '%s' a ghlasáil: nà féidir tagairt '%s' a réiteach" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': error reading reference" +msgstr "nà féidir tagairt '%s' a ghlasáil: earráid ag léamh tagairt" + +#: refs/reftable-backend.c +#, c-format +msgid "" +"multiple updates for '%s' (including one via symref '%s') are not allowed" +msgstr "" +"nà cheadaÃtear nuashonruithe iolracha do '%s' (lena n-áirÃtear ceann trà " +"symref '%s')" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference already exists" +msgstr "nà féidir tagairt '%s' a ghlasáil: tá tagairt ann cheana féin" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': reference is missing but expected %s" +msgstr "" +"nà féidir tagairt '%s' a ghlasáil: tá tagairt ar iarraidh ach táthar ag súil " +"leis %s" + +#: refs/reftable-backend.c +#, c-format +msgid "cannot lock ref '%s': is at %s but expected %s" +msgstr "" +"nà féidir tagairt '%s' a ghlasáil: tá sé ag %s ach táthar ag súil leis %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction prepare: %s" +msgstr "athfhabhtaithe: ullmhú idirbheart: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "reftable: transaction failure: %s" +msgstr "athfhabhtaithe: teip ar idirbheart: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "unable to compact stack: %s" +msgstr "nach féidir cruach a dhlúthú: %s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s not found" +msgstr "nà aimsÃodh refname %s" + +#: refs/reftable-backend.c +#, c-format +msgid "refname %s is a symbolic ref, copying it is not supported" +msgstr "rs tagairt siombalach é refname %s, nà thacaÃtear leis a chóipeáil" + +#: refspec.c +#, c-format +msgid "pattern '%s' has no '*'" +msgstr "nÃl aon '*' ag patrún '%s'" + +#: refspec.c +#, c-format +msgid "replacement '%s' has no '*'" +msgstr "nÃl aon '*' ag athsholáthar '%s'" + +#: remote-curl.c +#, c-format +msgid "invalid quoting in push-option value: '%s'" +msgstr "luachan neamhbhailà i luach brú rogha: '%s'" + +#: remote-curl.c +#, c-format +msgid "unknown value for object-format: %s" +msgstr "luach anaithnid d'fhormáid réad: %s" + +#: remote-curl.c +#, c-format +msgid "%sinfo/refs not valid: is this a git repository?" +msgstr "NÃl %sinfo/refs bailÃ: an stór git é seo?" + +#: remote-curl.c +msgid "invalid server response; expected service, got flush packet" +msgstr "freagra freastalaà neamhbhailÃ; seirbhÃs a bhÃothas ag súil" + +#: remote-curl.c +#, c-format +msgid "invalid server response; got '%s'" +msgstr "freagra freastalaà neamhbhailÃ; fuair '%s'" + +#: remote-curl.c +#, c-format +msgid "repository '%s' not found" +msgstr "nÃor aimsÃodh stór '%s'" + +#: remote-curl.c +#, c-format +msgid "Authentication failed for '%s'" +msgstr "Theip ar fhÃordheimhniú do '%s'" + +#: remote-curl.c +#, c-format +msgid "unable to access '%s' with http.pinnedPubkey configuration: %s" +msgstr "nà féidir rochtain a fháil ar '%s' le cumraÃocht http.pinnedPubkey: %s" + +#: remote-curl.c +#, c-format +msgid "unable to access '%s': %s" +msgstr "nà féidir teacht ar '%s': %s" + +#: remote-curl.c +#, c-format +msgid "redirecting to %s" +msgstr "atreorú chuig %s" + +#: remote-curl.c +msgid "shouldn't have EOF when not gentle on EOF" +msgstr "nÃor chóir go mbeadh EOF ann nuair nach bhfuil sé miline ar EOF" + +#: remote-curl.c +msgid "remote server sent unexpected response end packet" +msgstr "sheol freastalaà iargúlta paicéad deiridh" + +#: remote-curl.c +msgid "unable to rewind rpc post data - try increasing http.postBuffer" +msgstr "" +"nach féidir sonraà post rpc a athfhillt - déan iarracht http.postBuffer a " +"mhéadú" + +#: remote-curl.c +#, c-format +msgid "remote-curl: bad line length character: %.4s" +msgstr "iargúlta: carachtar fad droch-lÃne: %.4s" + +#: remote-curl.c +msgid "remote-curl: unexpected response end packet" +msgstr "iargúlta: paicéad deiridh freagartha gan choinne" + +#: remote-curl.c +#, c-format +msgid "RPC failed; %s" +msgstr "Theip ar RPC; %s" + +#: remote-curl.c +msgid "cannot handle pushes this big" +msgstr "nà féidir brú mór seo a láimhseáil" + +#: remote-curl.c +#, c-format +msgid "cannot deflate request; zlib deflate error %d" +msgstr "nà féidir iarratas a dhÃscaoileadh; earráid dÃfhabhtaithe zlib %d" + +#: remote-curl.c +#, c-format +msgid "cannot deflate request; zlib end error %d" +msgstr "nà féidir iarratas a dhÃscaoileadh; earráid deiridh zlib %d" + +#: remote-curl.c +#, c-format +msgid "%d bytes of length header were received" +msgstr "Fuarthas %d bytes de cheanntásc fad" + +#: remote-curl.c +#, c-format +msgid "%d bytes of body are still expected" +msgstr "Táthar ag súil fós ag súil le %d bytes den chorp" + +#: remote-curl.c +msgid "dumb http transport does not support shallow capabilities" +msgstr "nà thacaÃonn iompar HTTP dumb le cumais éadomhain" + +#: remote-curl.c +msgid "fetch failed." +msgstr "theip ar fáil." + +#: remote-curl.c +msgid "cannot fetch by sha1 over smart http" +msgstr "nà féidir le sha1 a fháil thar http cliste" + +#: remote-curl.c +#, c-format +msgid "protocol error: expected sha/ref, got '%s'" +msgstr "earráid prótacal: súil le sha/ref, fuair '%s'" + +#: remote-curl.c +#, c-format +msgid "http transport does not support %s" +msgstr "nà thacaÃonn iompar http le %s" + +#: remote-curl.c +msgid "protocol error: expected '<url> <path>', missing space" +msgstr "earráid prótacal: súil leis '<url><path>', spás in easnamh" + +#: remote-curl.c +#, c-format +msgid "failed to download file at URL '%s'" +msgstr "theip ar an comhad a Ãoslódáil ag URL '%s'" + +#: remote-curl.c +msgid "git-http-push failed" +msgstr "theip ar git-http-push" + +#: remote-curl.c +msgid "remote-curl: usage: git remote-curl <remote> [<url>]" +msgstr "<remote><url>remote-curl: úsáid: git remote-curl []" + +#: remote-curl.c +msgid "remote-curl: error reading command stream from git" +msgstr "remote-curl: earráid ag léamh sruth ordaithe ó git" + +#: remote-curl.c +msgid "remote-curl: fetch attempted without a local repo" +msgstr "remote-curl: iarracht a fháil gan repo áitiúil" + +#: remote-curl.c +#, c-format +msgid "remote-curl: unknown command '%s' from git" +msgstr "remote-curl: ordú anaithnid '%s' ó git" + +#: remote.c +#, c-format +msgid "" +"reading remote from \"%s/%s\", which is nominated for removal.\n" +"\n" +"If you still use the \"remotes/\" directory it is recommended to\n" +"migrate to config-based remotes:\n" +"\n" +"\tgit remote rename %s %s\n" +"\n" +"If you cannot, please let us know why you still need to use it by\n" +"sending an e-mail to <git@vger.kernel.org>." +msgstr "" +"léamh iargúlta ó \"%s/%s\", atá ainmnithe lena bhaint.\n" +"\n" +"Má úsáideann tú an eolaire “iargúlta/†fós moltar\n" +"aistriú chuig iargúlta bunaithe ar chumraÃocht:\n" +"\n" +" git iargúlta a athainmniú %s %s\n" +"\n" +"Mura féidir leat, cuir in iúl dúinn le do thoil cén fáth a gcaithfidh tú\n" +"é a úsáid fós trà rÃomhphost a sheoladh chuig <git@vger.kernel.org>." + +#: remote.c +#, c-format +msgid "config remote shorthand cannot begin with '/': %s" +msgstr "nà féidir le '/' tosú le gearrthánach iargúlta config: %s" + +#: remote.c +msgid "more than one receivepack given, using the first" +msgstr "" +"nÃos mó ná pacáiste glacadóra amháin a thugtar, ag baint úsáide as an gcéad" + +#: remote.c +msgid "more than one uploadpack given, using the first" +msgstr "" +"nÃos mó ná pacáiste uaslódála amháin tugtha, ag baint úsáide as an gcéad" + +#: remote.c +#, c-format +msgid "unrecognized followRemoteHEAD value '%s' ignored" +msgstr "neamhaird a dhéanamh ar luach FollowRemoteHead '%s' gan aithint" + +#: remote.c +#, c-format +msgid "unrecognized value transfer.credentialsInUrl: '%s'" +msgstr "aistriú luacha transfer.credentialsInUrl: '%s'" + +#: remote.c +#, c-format +msgid "URL '%s' uses plaintext credentials" +msgstr "Úsáideann URL '%s' dhintiúir téacs simplÃ" + +#: remote.c +#, c-format +msgid "Cannot fetch both %s and %s to %s" +msgstr "Nà féidir %s agus %s a fháil chuig %s" + +#: remote.c +#, c-format +msgid "%s usually tracks %s, not %s" +msgstr "Is gnách go rianann %s %s, nà %s" + +#: remote.c +#, c-format +msgid "%s tracks both %s and %s" +msgstr "Rianann %s %s agus %s araon" + +#: remote.c +#, c-format +msgid "src refspec %s does not match any" +msgstr "src refspec %s nà mheaitseálann aon" + +#: remote.c +#, c-format +msgid "src refspec %s matches more than one" +msgstr "meaitseálann src refspec %s nÃos mó ná ceann amháin" + +#. TRANSLATORS: "matches '%s'%" is the <dst> part of "git push +#. <remote> <src>:<dst>" push, and "being pushed ('%s')" is +#. the <src>. +#. +#: remote.c +#, c-format +msgid "" +"The destination you provided is not a full refname (i.e.,\n" +"starting with \"refs/\"). We tried to guess what you meant by:\n" +"\n" +"- Looking for a ref that matches '%s' on the remote side.\n" +"- Checking if the <src> being pushed ('%s')\n" +" is a ref in \"refs/{heads,tags}/\". If so we add a corresponding\n" +" refs/{heads,tags}/ prefix on the remote side.\n" +"\n" +"Neither worked, so we gave up. You must fully qualify the ref." +msgstr "" +"Nà ainm athainmnithe iomlán é an ceann scrÃbe a sholáthair tú (i.e., \n" +"ag tosú le \"refs/\"). Rinneamar iarracht buille faoi thuairim a thabhairt " +"faoi cad a bhà i gceist agat le:\n" +"\n" +"- Ag lorg tagartha a mheaitseálann '%s' ar an taobh iargúlta.\n" +"- Ag seiceáil an bhfuil an <src> atá á bhrú ('%s') ina thagairt \n" +" i \"refs/{heads,tags}/\". Más ea, cuirimid réimÃr comhfhreagrach r\n" +" efs/{heads,tags}/ leis ar an taobh iargúlta.\n" +"\n" +"NÃor oibrigh ceachtar acu, mar sin thugamar suas. Caithfidh tú an tagairt a " +"cháiliú go hiomlán." + +#: remote.c +#, c-format +msgid "" +"The <src> part of the refspec is a commit object.\n" +"Did you mean to create a new branch by pushing to\n" +"'%s:refs/heads/%s'?" +msgstr "" +"Is <src>réad tiomanta à an chuid den refspec.\n" +"An raibh i gceist agat brainse nua a chruthú trà bhrú chuig\n" +"'%s:refs/heads/%s'?" + +#: remote.c +#, c-format +msgid "" +"The <src> part of the refspec is a tag object.\n" +"Did you mean to create a new tag by pushing to\n" +"'%s:refs/tags/%s'?" +msgstr "" +"Is <src>réad clibeanna é an chuid den refspec.\n" +"An raibh i gceist agat clib nua a chruthú trà bhrú chuig\n" +"'%s:refs/tags/%s'?" + +#: remote.c +#, c-format +msgid "" +"The <src> part of the refspec is a tree object.\n" +"Did you mean to tag a new tree by pushing to\n" +"'%s:refs/tags/%s'?" +msgstr "" +"Is <src>réad crann à an chuid den refspec.\n" +"An raibh sé i gceist agat crann nua a chlibeáil trà bhrú chuig\n" +"'%s:refs/tags/%s'?" + +#: remote.c +#, c-format +msgid "" +"The <src> part of the refspec is a blob object.\n" +"Did you mean to tag a new blob by pushing to\n" +"'%s:refs/tags/%s'?" +msgstr "" +"Is <src>réad blob é an chuid den refspec.\n" +"An raibh sé i gceist agat blob nua a chlibeáil trà bhrú chuig\n" +"'%s:refs/tags/%s'?" + +#: remote.c +#, c-format +msgid "%s cannot be resolved to branch" +msgstr "Nà féidir %s a réiteach chuig an mbrainse" + +#: remote.c +#, c-format +msgid "unable to delete '%s': remote ref does not exist" +msgstr "nà féidir '%s' a scriosadh: nÃl tagairt iargúlta ann" + +#: remote.c +#, c-format +msgid "dst refspec %s matches more than one" +msgstr "meaitseálann dst refspec %s nÃos mó ná ceann amháin" + +#: remote.c +#, c-format +msgid "dst ref %s receives from more than one src" +msgstr "faigheann dst ref %s ó nÃos mó ná src amháin" + +#: remote.c +msgid "HEAD does not point to a branch" +msgstr "Nà chuireann HEAD in iúl do bhrainse" + +#: remote.c +#, c-format +msgid "no such branch: '%s'" +msgstr "aon bhrainse den sórt sin: '%s'" + +#: remote.c +#, c-format +msgid "no upstream configured for branch '%s'" +msgstr "nÃl aon chumrú suas srutha le haghaidh brainse '%s'" + +#: remote.c +#, c-format +msgid "upstream branch '%s' not stored as a remote-tracking branch" +msgstr "brainse suas srutha '%s' nach stóráiltear mar bhrainse cianrianaithe" + +#: remote.c +#, c-format +msgid "push destination '%s' on remote '%s' has no local tracking branch" +msgstr "" +"nÃl aon bhrainse rianaithe áitiúil ag ceann scrÃbe brúite '%s' ar iargúlta " +"'%s'" + +#: remote.c +#, c-format +msgid "branch '%s' has no remote for pushing" +msgstr "nÃl aon iargúlta ag brainse '%s' chun brú" + +#: remote.c +#, c-format +msgid "push refspecs for '%s' do not include '%s'" +msgstr "nà chuimsÃonn '%s' brú refspections do '%s'" + +#: remote.c +msgid "push has no destination (push.default is 'nothing')" +msgstr "nÃl aon cheann scrÃbe ag brú (is é 'rud ar bith' push.default)" + +#: remote.c +msgid "cannot resolve 'simple' push to a single destination" +msgstr "nà féidir brú 'simplÃ' a réiteach chuig ceann scrÃbe amháin" + +#: remote.c +#, c-format +msgid "couldn't find remote ref %s" +msgstr "nà raibh in ann tagairt iargúlta %s a fháil" + +#: remote.c +#, c-format +msgid "* Ignoring funny ref '%s' locally" +msgstr "* Ag neamhaird den tagairt ghreannmhar '%s' go háitiúil" + +#: remote.c +#, c-format +msgid "Your branch is based on '%s', but the upstream is gone.\n" +msgstr "Tá do bhrainse bunaithe ar '%s', ach tá an suas sruth imithe.\n" + +#: remote.c +msgid " (use \"git branch --unset-upstream\" to fixup)\n" +msgstr " (bain úsáid as \"git branch --unset-upstream\" chun é a dheisiú)\n" + +#: remote.c +#, c-format +msgid "Your branch is up to date with '%s'.\n" +msgstr "Tá do bhrainse cothrom le dáta le '%s'.\n" + +#: remote.c +#, c-format +msgid "Your branch and '%s' refer to different commits.\n" +msgstr "TagraÃonn do bhrainse agus '%s' do thiomnuithe difriúla.\n" + +#: remote.c +#, c-format +msgid " (use \"%s\" for details)\n" +msgstr " (bain úsáid as \"%s\" le haghaidh sonraÃ)\n" + +#: remote.c +#, c-format +msgid "Your branch is ahead of '%s' by %d commit.\n" +msgid_plural "Your branch is ahead of '%s' by %d commits.\n" +msgstr[0] "Tá do bhrainse chun tosaigh ar '%s' le tiomantas %d.\n" +msgstr[1] "Tá do bhrainse chun tosaigh ar '%s' le tiomantais %d.\n" +msgstr[2] "Tá do bhrainse chun tosaigh ar '%s' le tiomantais %d.\n" + +#: remote.c +msgid " (use \"git push\" to publish your local commits)\n" +msgstr " (bain úsáid as “git push†chun do thiomanta áitiúla a fhoilsiú)\n" + +#: remote.c +#, c-format +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] "" +"Tá do bhrainse taobh thiar de '%s' faoi %d tiomantas, agus is féidir é a " +"luasghéarú ar aghaidh.\n" +msgstr[1] "" +"Tá do bhrainse taobh thiar de '%s' faoi %d tiomnuithe, agus is féidir é a " +"luasghéarú ar aghaidh.\n" +msgstr[2] "" +"Tá do bhrainse taobh thiar de '%s' faoi %d tiomnuithe, agus is féidir é a " +"luasghéarú ar aghaidh.\n" + +#: remote.c +msgid " (use \"git pull\" to update your local branch)\n" +msgstr " (bain úsáid as “git pull†chun do bhrainse áitiúil a nuashonrú)\n" + +#: remote.c +#, c-format +msgid "" +"Your branch and '%s' have diverged,\n" +"and have %d and %d different commit each, respectively.\n" +msgid_plural "" +"Your branch and '%s' have diverged,\n" +"and have %d and %d different commits each, respectively.\n" +msgstr[0] "" +"Tá do bhrainse agus '%s' scartha óna chéile,\n" +"agus tá %d agus %d tiomnú difriúil acu faoi seach.\n" +msgstr[1] "" +"Tá do bhrainse agus '%s' scartha óna chéile,\n" +"agus tá %d agus %d tiomnuithe difriúla acu faoi seach.\n" +msgstr[2] "" +"Tá do bhrainse agus '%s' scartha óna chéile,\n" +"agus tá %d agus %d tiomnuithe difriúla acu faoi seach.\n" + +#: remote.c +msgid "" +" (use \"git pull\" if you want to integrate the remote branch with yours)\n" +msgstr "" +" (bain úsáid as “git pull†más mian leat an brainse iargúlta a chomhtháthú " +"le leatsa)\n" + +#: remote.c +#, c-format +msgid "cannot parse expected object name '%s'" +msgstr "nà féidir ainm réad a bhfuil súil leis '%s' a pharsáil" + +#: remote.c +#, c-format +msgid "cannot strip one component off url '%s'" +msgstr "nà féidir comhpháirt amháin a bhaint as url '%s'" + +#: replace-object.c +#, c-format +msgid "bad replace ref name: %s" +msgstr "droch-ainm tagartha athsholáthair: %s" + +#: replace-object.c +#, c-format +msgid "duplicate replace ref: %s" +msgstr "athsholáthar dúblach tagairt: %s" + +#: replace-object.c +#, c-format +msgid "replace depth too high for object %s" +msgstr "doimhneacht ró-ard a chur in ionad do réad %s" + +#: rerere.c +msgid "corrupt MERGE_RR" +msgstr "truaillithe MERGE_RR" + +#: rerere.c +msgid "unable to write rerere record" +msgstr "in ann taifead a scrÃobh arÃs" + +#: rerere.c +#, c-format +msgid "there were errors while writing '%s' (%s)" +msgstr "bhà earráidà ann agus tú ag scrÃobh '%s' (%s)" + +#: rerere.c +#, c-format +msgid "could not parse conflict hunks in '%s'" +msgstr "nà fhéadfaà coimhlint a pharsáil i '%s'" + +#: rerere.c +#, c-format +msgid "failed utime() on '%s'" +msgstr "theip ar utime () ar '%s'" + +#: rerere.c +#, c-format +msgid "writing '%s' failed" +msgstr "theip ar scrÃobh '%s'" + +#: rerere.c +#, c-format +msgid "Staged '%s' using previous resolution." +msgstr "'%s 'céim ag baint úsáide as réiteach roimhe seo." + +#: rerere.c +#, c-format +msgid "Recorded resolution for '%s'." +msgstr "Réiteach taifeadta le haghaidh '%s'." + +#: rerere.c +#, c-format +msgid "Resolved '%s' using previous resolution." +msgstr "Réitigh '%s' ag úsáid réiteach roimhe seo." + +#: rerere.c +#, c-format +msgid "cannot unlink stray '%s'" +msgstr "nà féidir le '%s' a dhÃnascadh" + +#: rerere.c +#, c-format +msgid "Recorded preimage for '%s'" +msgstr "RéamhÃomhá taifeadta do '%s'" + +#: rerere.c +#, c-format +msgid "failed to update conflicted state in '%s'" +msgstr "theip ar an stát coinbhleachta a nuashonrú i '%s'" + +#: rerere.c +#, c-format +msgid "no remembered resolution for '%s'" +msgstr "nÃl aon réiteach cuimhne ar '%s'" + +#: rerere.c +#, c-format +msgid "Updated preimage for '%s'" +msgstr "RéamhÃomhá nuashonraithe do '%s'" + +#: rerere.c +#, c-format +msgid "Forgot resolution for '%s'\n" +msgstr "Déan dearmad dearmad ar réiteach '%s'\n" + +#: rerere.c +msgid "unable to open rr-cache directory" +msgstr "in ann eolaire rr-cache a oscailt" + +#: rerere.h +msgid "update the index with reused conflict resolution if possible" +msgstr "an t-innéacs a nuashonrú le réiteach coinbhleachta a athúsáidtear" + +#: reset.c +msgid "could not determine HEAD revision" +msgstr "nà raibh sé in ann athbhreithniú HEAD" + +#: reset.c sequencer.c +#, c-format +msgid "failed to find tree of %s" +msgstr "theip ar chrann %s a aimsiú" + +#: revision.c +#, c-format +msgid "unsupported section for hidden refs: %s" +msgstr "rannán gan tacaÃocht do thaifeanna i bhfolach: %s" + +#: revision.c +msgid "--exclude-hidden= passed more than once" +msgstr "--exclude-hidden= rith nÃos mó ná uair amháin" + +#: revision.c +#, c-format +msgid "resolve-undo records `%s` which is missing" +msgstr "taifid réitigh a chealú `%s` atá ar iarraidh" + +#: revision.c +#, c-format +msgid "%s exists but is a symbolic ref" +msgstr "Tá %s ann ach is tagairt siombalach é" + +#: revision.c +msgid "" +"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD or REBASE_HEAD" +msgstr "" +"TeastaÃonn --merge ceann de na pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, " +"REVERT_HEAD nó REBASE_HEAD" + +#: revision.c +#, c-format +msgid "could not get commit for --ancestry-path argument %s" +msgstr "nà fhéadfaà tiomantas a fháil le haghaidh argóint --ancestry-path %s" + +#: revision.c +msgid "--unpacked=<packfile> no longer supported" +msgstr "--unpacked=<packfile> nà thacaÃtear leis a thuilleadh" + +#: revision.c +#, c-format +msgid "invalid option '%s' in --stdin mode" +msgstr "rogha neamhbhailà '%s' i mód --stdin" + +#: revision.c +msgid "your current branch appears to be broken" +msgstr "is cosúil go bhfuil do bhrainse reatha briste" + +#: revision.c +#, c-format +msgid "your current branch '%s' does not have any commits yet" +msgstr "nÃl aon gealltanais fós ag do bhrainse reatha '%s'" + +#: revision.c +msgid "object filtering requires --objects" +msgstr "teastaÃonn scagadh réad --objects" + +#: revision.c +msgid "-L does not yet support diff formats besides -p and -s" +msgstr "Nà thacaÃonn -L le formáidà diff fós seachas -p agus -s" + +#: run-command.c +#, c-format +msgid "cannot create async thread: %s" +msgstr "nà féidir snáithe async a chruthú: %s" + +#: scalar.c worktree.c +#, c-format +msgid "'%s' does not exist" +msgstr "NÃl '%s' ann" + +#: scalar.c +#, c-format +msgid "could not switch to '%s'" +msgstr "nà fhéadfaà aistriú go '%s'" + +#: scalar.c +msgid "need a working directory" +msgstr "teastaÃonn eolaire oibre" + +#: scalar.c +msgid "Scalar enlistments require a worktree" +msgstr "TeastaÃonn crann oibre ó liostú scalar" + +#: scalar.c +#, c-format +msgid "could not configure %s=%s" +msgstr "nà fhéadfaà %s=%s a chumrú" + +#: scalar.c +msgid "could not configure log.excludeDecoration" +msgstr "nà fhéadfaà log.excludeDecoration a chumrú" + +#: scalar.c +msgid "could not add enlistment" +msgstr "nà fhéadfaà liostú a chur leis" + +#: scalar.c +msgid "could not set recommended config" +msgstr "nà fhéadfaà cumraÃocht mholta a shocrú" + +#: scalar.c +msgid "could not toggle maintenance" +msgstr "nÃorbh fhéidir cothabháil a athrú" + +#: scalar.c +msgid "could not start the FSMonitor daemon" +msgstr "nà fhéadfaà an daemon FSMonitor a thosú" + +#: scalar.c +msgid "could not turn off maintenance" +msgstr "nà fhéadfadh cothabháil a mhúchadh" + +#: scalar.c +msgid "could not remove enlistment" +msgstr "nà fhéadfaà liostú a bhaint" + +#: scalar.c +#, c-format +msgid "remote HEAD is not a branch: '%.*s'" +msgstr "nà brainse é iargúlta HEAD: '%.*s" + +#: scalar.c +msgid "failed to get default branch name from remote; using local default" +msgstr "" +"theip ar ainm brainse réamhshocraithe a fháil ó iargúlta; ag baint úsáide as" + +#: scalar.c +msgid "failed to get default branch name" +msgstr "theip ort ainm brainse réamhshocraithe a fháil" + +#: scalar.c +msgid "failed to unregister repository" +msgstr "theip ar stór a dhÃchlárú" + +#: scalar.c +msgid "failed to stop the FSMonitor daemon" +msgstr "theip ar an daemon FSMonitor a stopadh" + +#: scalar.c +msgid "failed to delete enlistment directory" +msgstr "theip ar eolaire liostála a scriosadh" + +#: scalar.c +msgid "branch to checkout after clone" +msgstr "brainse chun an tseiceáil tar éis clóin" + +#: scalar.c +msgid "when cloning, create full working directory" +msgstr "agus tú ag clónú, cruthaigh eolaire oibre iomlán" + +#: scalar.c +msgid "only download metadata for the branch that will be checked out" +msgstr "meiteashonraà a Ãoslódáil ach don bhrainse a sheiceálfar" + +#: scalar.c +msgid "create repository within 'src' directory" +msgstr "cruthaigh stór laistigh de eolaire 'src'" + +#: scalar.c +msgid "specify if tags should be fetched during clone" +msgstr "sonraigh an gcaithfear clibeanna a fháil le linn clóin" + +#: scalar.c +msgid "specify if background maintenance should be enabled" +msgstr "sonraigh an bhfuil cothabháil chúlra le cumasú" + +#: scalar.c +msgid "" +"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" +msgstr "" +"clón scálach [--single-branch] [--branch <prÃomhbhrainse>] [--full-clone]\n" +"[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<liostáil>]" + +#: scalar.c +#, c-format +msgid "cannot deduce worktree name from '%s'" +msgstr "nà féidir ainm crann oibre a bhaint as '%s'" + +#: scalar.c +#, c-format +msgid "directory '%s' exists already" +msgstr "tá eolaire '%s' ann cheana féin" + +#: scalar.c +#, c-format +msgid "failed to get default branch for '%s'" +msgstr "theip ar bhrainse réamhshocraithe a fháil do '%s'" + +#: scalar.c +#, c-format +msgid "could not configure remote in '%s'" +msgstr "nà fhéadfaà iargúlta a chumrú i '%s'" + +#: scalar.c +#, c-format +msgid "could not disable tags in '%s'" +msgstr "nà fhéadfaà clibeanna a dhÃchumasú i '%s'" + +#: scalar.c +#, c-format +msgid "could not configure '%s'" +msgstr "nà fhéadfaà '%s' a chumrú" + +#: scalar.c +msgid "partial clone failed; attempting full clone" +msgstr "theip ar chlón páirteach; iarracht clón iomlán" + +#: scalar.c +msgid "could not configure for full clone" +msgstr "nà fhéadfaà a chumrú le haghaidh clón iomlán" + +#: scalar.c +msgid "scalar diagnose [<enlistment>]" +msgstr "<enlistment>diagnóis scalar []" + +#: scalar.c +msgid "`scalar list` does not take arguments" +msgstr "Nà ghlacann `liosta scalar` argóintÃ" + +#: scalar.c +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "clár scálach [--[gan-]chothabháil] [<liostáil>]" + +#: scalar.c +msgid "reconfigure all registered enlistments" +msgstr "gach liostáil cláraithe a athchumrú" + +#: scalar.c +msgid "(enable|disable|keep)" +msgstr "(cumasaigh|dÃchumasaigh|coinnigh)" + +#: scalar.c +msgid "signal how to adjust background maintenance" +msgstr "comhartha a thabhairt maidir le conas cothabháil chúlra a choigeartú" + +#: scalar.c +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" + +#: scalar.c +msgid "--all or <enlistment>, but not both" +msgstr "--all nó <enlistment>, ach nà an dá cheann" + +#: scalar.c +#, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "mód anaithnid don rogha --maintenance: %s" + +#: scalar.c +#, c-format +msgid "could not remove stale scalar.repo '%s'" +msgstr "nà fhéadfaà scalar.repo '%s' a bhaint as scalar.repo" + +#: scalar.c +#, c-format +msgid "removed stale scalar.repo '%s'" +msgstr "bainte scale scalar.repo '%s'" + +#: scalar.c +#, c-format +msgid "repository at '%s' has different owner" +msgstr "tá úinéir difriúil ag an stórlann ag '%s'" + +#: scalar.c +#, c-format +msgid "repository at '%s' has a format issue" +msgstr "tá ceist formáide ag stór ag '%s'" + +#: scalar.c +#, c-format +msgid "repository not found in '%s'" +msgstr "nà bhfuarthas stór i '%s'" + +#: scalar.c +#, c-format +msgid "" +"to unregister this repository from Scalar, run\n" +"\tgit config --global --unset --fixed-value scalar.repo \"%s\"" +msgstr "" +"chun an stór seo a dhÃchlárú ó Scalar, reáchtáil\n" +" git config --global --unset --fixed-value scalar.repo “%sâ€" + +#: scalar.c +msgid "" +"scalar run <task> [<enlistment>]\n" +"Tasks:\n" +msgstr "" +"rith scalar <tasc> [<liostáil>]\n" +"Tascanna:\n" + +#: scalar.c +#, c-format +msgid "no such task: '%s'" +msgstr "gan aon tasc den sórt sin: '%s'" + +#: scalar.c +msgid "scalar unregister [<enlistment>]" +msgstr "<enlistment>scálar dÃchlárú []" + +#: scalar.c +msgid "scalar delete <enlistment>" +msgstr "scriosadh scalar <enlistment>" + +#: scalar.c +msgid "refusing to delete current working directory" +msgstr "diúltú eolaire oibre reatha a scriosadh" + +#: scalar.c +msgid "include Git version" +msgstr "leagan Git san áireamh" + +#: scalar.c +msgid "include Git's build options" +msgstr "áireamh roghanna tógála Git" + +#: scalar.c +msgid "scalar verbose [-v | --verbose] [--build-options]" +msgstr "scalar verbose [-v | --verbose] [--build-options]" + +#: scalar.c +msgid "-C requires a <directory>" +msgstr "ÉilÃonn -C a <directory>" + +#: scalar.c +#, c-format +msgid "could not change to '%s'" +msgstr "nà fhéadfaà athrú go '%s'" + +#: scalar.c +msgid "-c requires a <key>=<value> argument" +msgstr "<value>ÉilÃonn -c a <key>= argóint" + +#: scalar.c +msgid "" +"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n" +"\n" +"Commands:\n" +msgstr "" +"scalar [-C <eolaire>] [-c <eochair>=<luach>] <ordú> [<roghanna>]\n" +"\n" +"Orduithe:\n" + +#: send-pack.c +msgid "unexpected flush packet while reading remote unpack status" +msgstr "paicéad srutháin gan choinne agus stádas dÃphacála iargúlta" + +#: send-pack.c +#, c-format +msgid "unable to parse remote unpack status: %s" +msgstr "nach féidir stádas iargúlta dÃphacáil a pháirseáil: %s" + +#: send-pack.c +#, c-format +msgid "remote unpack failed: %s" +msgstr "theip ar dhÃphacáil iargúlta: %s" + +#: send-pack.c +msgid "failed to sign the push certificate" +msgstr "theip ar an deimhniú brú a shÃniú" + +#: send-pack.c +msgid "send-pack: unable to fork off fetch subprocess" +msgstr "pacáiste seolta: nà féidir leis an bhfophróiseas faighte a fhorc" + +#: send-pack.c +msgid "push negotiation failed; proceeding anyway with push" +msgstr "theip ar chaibidlÃocht brú; dul ar aghaidh ar aon nós" + +#: send-pack.c +msgid "the receiving end does not support this repository's hash algorithm" +msgstr "nà thacaÃonn an deireadh glacadh le halgartam hash an stór seo" + +#: send-pack.c +msgid "the receiving end does not support --signed push" +msgstr "nà thacaÃonn an deireadh glacadh le brú --signed" + +#: send-pack.c +msgid "" +"not sending a push certificate since the receiving end does not support --" +"signed push" +msgstr "" +"nÃl teastas brú á sheoladh ós rud é nach dtacaÃonn an taobh glactha le --" +"signed brúigh" + +#: send-pack.c +msgid "the receiving end does not support --atomic push" +msgstr "nà thacaÃonn an deireadh glacadh le brú --atomic" + +#: send-pack.c +msgid "the receiving end does not support push options" +msgstr "nà thacaÃonn an deireadh glacadh le roghanna brú" + +#: sequencer.c +#, c-format +msgid "invalid commit message cleanup mode '%s'" +msgstr "modh glantacháin teachtaireachta tiomanta neamhbhailà '%s'" + +#: sequencer.c +#, c-format +msgid "could not delete '%s'" +msgstr "nà fhéadfaà '%s' a scriosadh" + +#: sequencer.c +msgid "revert" +msgstr "filleadh" + +#: sequencer.c +msgid "cherry-pick" +msgstr "pioc silÃnÃ" + +#: sequencer.c +msgid "rebase" +msgstr "athbhunú" + +#: sequencer.c +#, c-format +msgid "unknown action: %d" +msgstr "gnÃomh anaithnid: %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 "" +"Réiteach na coinbhleachtaà go léir de láimh, marcáil iad mar réiteach\n" +"“git add/rm <conflicted_files>“, ansin rith “git rebase --continueâ€.\n" +"Ina áit sin is féidir leat an tiomantas seo a scipeáil: rith “git rebase --" +"skipâ€.\n" +"Chun abordú agus dul ar ais go dtà an stát roimh “git rebaseâ€, reáchtáil " +"“git rebase --abortâ€." + +#: sequencer.c +msgid "" +"after resolving the conflicts, mark the corrected paths\n" +"with 'git add <paths>' or 'git rm <paths>'" +msgstr "" +"tar éis na coinbhleachtaà a réiteach, marcáil na cosáin cearta\n" +"<paths>le 'git add <paths>'nó 'git rm'" + +#: sequencer.c +msgid "" +"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\"." +msgstr "" +"Tar éis na coinbhleachtaà a réiteach, marcáil iad le\n" +"“git add/rm <pathspec>“, ansin rith\n" +"\"git cherry-pick --continue\".\n" +"Is féidir leat an tiomantas seo a scipeáil ina ionad sin le \"git cherry-" +"pick --skip\n" +"Chun abordú agus dul ar ais go dtà an stát roimh “git cherry-pickâ€,\n" +"reáchtáil “git cherry-pick --abortâ€." + +#: sequencer.c +msgid "" +"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\"." +msgstr "" +"Tar éis na coinbhleachtaà a réiteach, marcáil iad le\n" +"“git add/rm <pathspec>“, ansin rith\n" +"“git ar ais --continue ar aghaidhâ€.\n" +"Ina áit sin is féidir leat an tiomantas seo a scipeáil le “git revert --" +"skipâ€.\n" +"Chun deireadh a chur leis agus dul ar ais go dtà an stát roimh “git " +"revertâ€,\n" +"reáchtáil “git revert --abortâ€." + +#: sequencer.c +#, c-format +msgid "could not lock '%s'" +msgstr "nà fhéadfaà '%s' a ghlasáil" + +#: sequencer.c +#, c-format +msgid "could not write eol to '%s'" +msgstr "nà fhéadfaà eol a scrÃobh chuig '%s'" + +#: sequencer.c +#, c-format +msgid "failed to finalize '%s'" +msgstr "theip ar '%s' a chur i gcrÃch" + +#: sequencer.c +#, c-format +msgid "your local changes would be overwritten by %s." +msgstr "d'athruithe áitiúla a fhorscrÃobhadh ag %s." + +#: sequencer.c +msgid "commit your changes or stash them to proceed." +msgstr "do chuid athruithe a dhéanamh nó iad a stóráil chun dul ar aghaidh." + +#. TRANSLATORS: %s will be "revert", "cherry-pick" or +#. "rebase". +#. +#: sequencer.c +#, c-format +msgid "%s: Unable to write new index file" +msgstr "%s: Nà féidir comhad innéacs nua a scrÃobh" + +#: sequencer.c +msgid "unable to update cache tree" +msgstr "in ann crann taisce a nuashonrú" + +#: sequencer.c +msgid "could not resolve HEAD commit" +msgstr "nà fhéadfaà tiomantas HEAD a réiteach" + +#: sequencer.c +#, c-format +msgid "no key present in '%.*s'" +msgstr "nÃl aon eochair i láthair i '%.*s" + +#: sequencer.c +#, c-format +msgid "unable to dequote value of '%s'" +msgstr "nach féidir luach '%s' a dhÃchur" + +#: sequencer.c +msgid "'GIT_AUTHOR_NAME' already given" +msgstr "'GIT_AUTHOR_NAME' tugtha cheana féin" + +#: sequencer.c +msgid "'GIT_AUTHOR_EMAIL' already given" +msgstr "'GIT_AUTHOR_EMAIL' tugtha cheana féin" + +#: sequencer.c +msgid "'GIT_AUTHOR_DATE' already given" +msgstr "'GIT_AUTHOR_DATE' tugtha cheana féin" + +#: sequencer.c +#, c-format +msgid "unknown variable '%s'" +msgstr "athróg anaithnid '%s'" + +#: sequencer.c +msgid "missing 'GIT_AUTHOR_NAME'" +msgstr "ar iarraidh 'GIT_AUTHOR_NAME'" + +#: sequencer.c +msgid "missing 'GIT_AUTHOR_EMAIL'" +msgstr "ar iarraidh 'GIT_AUTHOR_EMAIL'" + +#: sequencer.c +msgid "missing 'GIT_AUTHOR_DATE'" +msgstr "ar iarraidh 'GIT_AUTHOR_DATE'" + +#: sequencer.c +#, c-format +msgid "" +"you have staged changes in your working tree\n" +"If these changes are meant to be squashed into the previous commit, run:\n" +"\n" +" git commit --amend %s\n" +"\n" +"If they are meant to go into a new commit, run:\n" +"\n" +" git commit %s\n" +"\n" +"In both cases, once you're done, continue with:\n" +"\n" +" git rebase --continue\n" +msgstr "" +"tá athruithe céime agat i do chrann oibre\n" +"Má tá na hathruithe seo i gceist a chur isteach sa tiomantas roimhe seo, " +"reáchtáil:\n" +"\n" +" git commit --amend %s\n" +"\n" +"Má tá siad i gceist dul i dtiomantas nua, reáchtáil:\n" +"\n" +" git commit %s\n" +"\n" +"Sa dá chás, nuair a bheidh tú déanta, lean ar aghaidh leis:\n" +"\n" +" git rebase --continue\n" + +#: sequencer.c +msgid "'prepare-commit-msg' hook failed" +msgstr "Theip ar chroà 'prepar-chommit-msg'" + +#: sequencer.c +msgid "" +"Your name and email address were configured automatically based\n" +"on your username and hostname. Please check that they are accurate.\n" +"You can suppress this message by setting them explicitly. Run the\n" +"following command and follow the instructions in your editor to edit\n" +"your configuration file:\n" +"\n" +" git config --global --edit\n" +"\n" +"After doing this, you may fix the identity used for this commit with:\n" +"\n" +" git commit --amend --reset-author\n" +msgstr "" +"CumraÃodh d'ainm agus do sheoladh rÃomhphoist bunaithe go huath\n" +"ar d'ainm úsáideora agus d'ainm óstach. Seiceáil le do thoil go bhfuil siad " +"cruinn.\n" +"Is féidir leat an teachtaireacht seo a chosc trà iad a shocrú go sainráite. " +"Rith an\n" +"ag leanúint an t-ordú agus lean na treoracha i d'eagarthóir chun a chur in " +"eagar\n" +"do chomhad cumraÃochta:\n" +"\n" +" git config --global --edit\n" +"\n" +"Tar éis duit é seo a dhéanamh, féadfaidh tú an aitheantas a úsáidtear don " +"tiomantas seo a shocrú le:\n" +"\n" +" git commit --amend --reset-author\n" + +#: sequencer.c +msgid "" +"Your name and email address were configured automatically based\n" +"on your username and hostname. Please check that they are accurate.\n" +"You can suppress this message by setting them explicitly:\n" +"\n" +" git config --global user.name \"Your Name\"\n" +" git config --global user.email you@example.com\n" +"\n" +"After doing this, you may fix the identity used for this commit with:\n" +"\n" +" git commit --amend --reset-author\n" +msgstr "" +"CumraÃodh d'ainm agus do sheoladh rÃomhphoist bunaithe go huath\n" +"ar d'ainm úsáideora agus d'ainm óstach. Seiceáil le do thoil go bhfuil siad " +"cruinn.\n" +"Is féidir leat an teachtaireacht seo a chosc trà iad a shocrú go sainráite:\n" +"\n" +" git config --global user.name \"Your Name\"\n" +" git config --global user.email you@example.com\n" +"\n" +"Tar éis duit é seo a dhéanamh, féadfaidh tú an aitheantas a úsáidtear don " +"tiomantas seo a shocrú le:\n" +"\n" +" git commit --amend --reset-author\n" + +#: sequencer.c +msgid "couldn't look up newly created commit" +msgstr "nà fhéadfadh sé gealltanas nua-chruthaithe a fheiceáil" + +#: sequencer.c +msgid "could not parse newly created commit" +msgstr "nà fhéadfadh sé gealltanas nua-chruthaithe a pháirsÃ" + +#: sequencer.c +msgid "unable to resolve HEAD after creating commit" +msgstr "in ann HEAD a réiteach tar éis tiomantas a chruthú" + +#: sequencer.c +msgid "detached HEAD" +msgstr "scoite CEANN" + +#: sequencer.c +msgid " (root-commit)" +msgstr " (fréamh-thiomantas)" + +#: sequencer.c +msgid "could not parse HEAD" +msgstr "nà fhéadfaà HEAD a pháirseáil" + +#: sequencer.c +#, c-format +msgid "HEAD %s is not a commit!" +msgstr "Nà gealltanas é HEAD %s!" + +#: sequencer.c +msgid "unable to parse commit author" +msgstr "nà féidir leis an údar tiomanta a pharsáil" + +#: sequencer.c +#, c-format +msgid "unable to read commit message from '%s'" +msgstr "nach féidir teachtaireacht tiomanta ó '%s' a léamh" + +#: sequencer.c +#, c-format +msgid "invalid author identity '%s'" +msgstr "aitheantas údair neamhbhailà '%s'" + +#: sequencer.c +msgid "corrupt author: missing date information" +msgstr "údar truaillithe: faisnéis dáta in easnamh" + +#: sequencer.c +#, c-format +msgid "could not update %s" +msgstr "nà fhéadfaà %s a nuashonrú" + +#: sequencer.c +#, c-format +msgid "could not parse parent commit %s" +msgstr "nà fhéadfaà tuismitheoir tiomantas %s a pharsáil" + +#: sequencer.c +#, c-format +msgid "unknown command: %d" +msgstr "ordú anaithnid: %d" + +#: sequencer.c +msgid "This is the 1st commit message:" +msgstr "Seo an chéad teachtaireacht tiomanta:" + +#: sequencer.c +#, c-format +msgid "This is the commit message #%d:" +msgstr "Seo an teachtaireacht tiomanta #%d:" + +#: sequencer.c +msgid "The 1st commit message will be skipped:" +msgstr "Scaipfear an chéad teachtaireacht tiomanta:" + +#: sequencer.c +#, c-format +msgid "The commit message #%d will be skipped:" +msgstr "Scaipfear an teachtaireacht tiomanta #%d:" + +#: sequencer.c +#, c-format +msgid "This is a combination of %d commits." +msgstr "Is meascán de ghealltanais %d é seo." + +#: sequencer.c +#, c-format +msgid "cannot write '%s'" +msgstr "nà féidir '%s' a scrÃobh" + +#: sequencer.c +msgid "need a HEAD to fixup" +msgstr "teastaÃonn CEAD ag teastáil chun socrú" + +#: sequencer.c +msgid "could not read HEAD" +msgstr "nà raibh in ann HEAD a léamh" + +#: sequencer.c +msgid "could not read HEAD's commit message" +msgstr "nà raibh sé in ann teachtaireacht tiomanta HEAD a léamh" + +#: sequencer.c +#, c-format +msgid "could not read commit message of %s" +msgstr "nà raibh sé in ann teachtaireacht tiomanta %s a léamh" + +#: sequencer.c +msgid "your index file is unmerged." +msgstr "tá do chomhad innéacs neamh-chumasaithe." + +#: sequencer.c +msgid "cannot fixup root commit" +msgstr "nà féidir le déanamh fréimhe a shocrú" + +#: sequencer.c +#, c-format +msgid "commit %s is a merge but no -m option was given." +msgstr "cumasc é tiomnú %s ach nÃor tugadh rogha -m." + +#: sequencer.c +#, c-format +msgid "commit %s does not have parent %d" +msgstr "commiteáil %s nÃl tuismitheoir %d aige" + +#: sequencer.c +#, c-format +msgid "cannot get commit message for %s" +msgstr "nà féidir teachtaireacht tiomanta a fháil do %s" + +#. TRANSLATORS: The first %s will be a "todo" command like +#. "revert" or "pick", the second %s a SHA1. +#: sequencer.c +#, c-format +msgid "%s: cannot parse parent commit %s" +msgstr "%s: nà féidir le tuismitheoir tiomantas %s a pharsáil" + +#: sequencer.c +#, c-format +msgid "could not revert %s... %s" +msgstr "nà raibh ann %s a chur ar ais... %s" + +#: sequencer.c +#, c-format +msgid "could not apply %s... %s" +msgstr "nà fhéadfaà %s a chur i bhfeidhm... %s" + +#: sequencer.c +#, c-format +msgid "dropping %s %s -- patch contents already upstream\n" +msgstr "scaoileadh %s %s -- ábhar paiste suas an sruth cheana féin\n" + +#: sequencer.c +#, c-format +msgid "git %s: failed to read the index" +msgstr "git %s: theip ar an t-innéacs a léamh" + +#: sequencer.c +#, c-format +msgid "git %s: failed to refresh the index" +msgstr "git %s: theip ar an t-innéacs a athnuachan" + +#: sequencer.c +#, c-format +msgid "'%s' is not a valid label" +msgstr "Nà lipéad bailà é '%s'" + +#: sequencer.c +#, c-format +msgid "'%s' is not a valid refname" +msgstr "Nà athainm bailà é '%s'" + +#: sequencer.c +#, c-format +msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s" +msgstr "teastaÃonn athainm iomlán cáilithe uasghabháilte e.g. refs/heads/%s" + +#: sequencer.c +#, c-format +msgid "'%s' does not accept merge commits" +msgstr "Nà ghlacann '%s' le gealltanais cumaisc" + +#. TRANSLATORS: 'pick' and 'merge -C' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'pick' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit." +msgstr "" +"Nà ghlacann 'pick' tiomantas cumaisc. Dá mbeadh tú ag iarraidh\n" +"athsheinn an cumaisc, bain úsáid as 'cumaisc -C' ar an tiomantas." + +#. TRANSLATORS: 'reword' and 'merge -c' should not be +#. translated. +#. +#: sequencer.c +msgid "" +"'reword' does not take a merge commit. If you wanted to\n" +"replay the merge and reword the commit message, use\n" +"'merge -c' on the commit" +msgstr "" +"Nà ghlacann 'athfhoil' tiomantas cumaisc. Dá mbeadh tú ag iarraidh\n" +"athsheinn an teachtaireacht thiomanta a chumasc agus athfhocal, bain úsáid " +"as\n" +"'cumaisc -c' ar an tiomantas" + +#. TRANSLATORS: 'edit', 'merge -C' and 'break' should +#. not be translated. +#. +#: sequencer.c +msgid "" +"'edit' does not take a merge commit. If you wanted to\n" +"replay the merge, use 'merge -C' on the commit, and then\n" +"'break' to give the control back to you so that you can\n" +"do 'git commit --amend && git rebase --continue'." +msgstr "" +"Nà ghlacann 'eagarthó' tiomantas cumaisc. Dá mbeadh tú ag iarraidh\n" +"athsheinn an cumaisc, bain úsáid as 'cumaisc -C' ar an tiomantas, agus " +"ansin\n" +"'brise' chun an rialú a thabhairt ar ais duit ionas gur féidir leat\n" +"déan 'git commit --amend && git rebase --continue'." + +#: sequencer.c +msgid "cannot squash merge commit into another commit" +msgstr "nà féidir le squash tiomantas a chumasc i dtiomantas eile" + +#: sequencer.c +#, c-format +msgid "invalid command '%.*s'" +msgstr "ordú neamhbhailà '%.*s" + +#: sequencer.c +#, c-format +msgid "missing arguments for %s" +msgstr "argóintà atá in easnamh do %s" + +#: sequencer.c +#, c-format +msgid "could not parse '%s'" +msgstr "nà fhéadfaà '%s' a pháirseáil" + +#: sequencer.c +#, c-format +msgid "invalid line %d: %.*s" +msgstr "lÃne neamhbhailà %d: %.*s" + +#: sequencer.c +#, c-format +msgid "cannot '%s' without a previous commit" +msgstr "nà féidir '%s' gan gealltanas roimhe seo" + +#: sequencer.c +msgid "cancelling a cherry picking in progress" +msgstr "piocadh silÃnà atá ar siúl a chur ar ceal" + +#: sequencer.c +msgid "cancelling a revert in progress" +msgstr "filleadh atá ar siúl a chealú" + +#: sequencer.c +msgid "please fix this using 'git rebase --edit-todo'." +msgstr "" +"déan é seo a shocrú le do thoil ag baint úsáide as 'git rebase --edit-todo'." + +#: sequencer.c +#, c-format +msgid "unusable instruction sheet: '%s'" +msgstr "bileog treoracha neamhúsáidte: '%s'" + +#: sequencer.c +msgid "no commits parsed." +msgstr "nÃl aon gealltanais paráilsithe." + +#: sequencer.c +msgid "cannot cherry-pick during a revert." +msgstr "nà féidir le silÃnà a phiocadh le linn filleadh." + +#: sequencer.c +msgid "cannot revert during a cherry-pick." +msgstr "nà féidir filleadh ar ais le linn pioc silÃnÃ." + +#: sequencer.c +msgid "unusable squash-onto" +msgstr "squash-on neamhúsáidte" + +#: sequencer.c +#, c-format +msgid "malformed options sheet: '%s'" +msgstr "bileog roghanna mÃfhoirmithe: '%s'" + +#: sequencer.c +msgid "empty commit set passed" +msgstr "rith tacar tiomanta folamh" + +#: sequencer.c +msgid "revert is already in progress" +msgstr "tá filleadh ar siúl cheana féin" + +#: sequencer.c +#, c-format +msgid "try \"git revert (--continue | %s--abort | --quit)\"" +msgstr "bain triail as “git revert (--continue | %s--abort | --quit)â€" + +#: sequencer.c +msgid "cherry-pick is already in progress" +msgstr "tá pioc silÃnà ar siúl cheana féin" + +#: sequencer.c +#, c-format +msgid "try \"git cherry-pick (--continue | %s--abort | --quit)\"" +msgstr "bain triail as “git cherry-pick (--continue | %s--abort | --quit)â€" + +#: sequencer.c +#, c-format +msgid "could not create sequencer directory '%s'" +msgstr "nà fhéadfaà eolaire seicheamhach '%s' a chruthú" + +#: sequencer.c +msgid "no cherry-pick or revert in progress" +msgstr "nÃl aon phiocadh silÃnà nó filleadh ar siúl ar siúl" + +#: sequencer.c +msgid "cannot resolve HEAD" +msgstr "nà féidir le HEAD a réiteach" + +#: sequencer.c +msgid "cannot abort from a branch yet to be born" +msgstr "nà féidir éirà as brainse nach rugadh fós" + +#: sequencer.c +#, c-format +msgid "cannot read '%s': %s" +msgstr "nà féidir '%s' a léamh: %s" + +#: sequencer.c +msgid "unexpected end of file" +msgstr "deireadh gan choinne an chomhaid" + +#: sequencer.c +#, c-format +msgid "stored pre-cherry-pick HEAD file '%s' is corrupt" +msgstr "tá comhad HEAD réamh-phiocadh silÃnà stóráilte '%s' truaillithe" + +#: sequencer.c +msgid "You seem to have moved HEAD. Not rewinding, check your HEAD!" +msgstr "Is cosúil gur bhogadh tú CEANN. Gan athfhillte, seiceáil do CHEANN!" + +#: sequencer.c +msgid "no revert in progress" +msgstr "nÃl aon fhilleadh ar siúl" + +#: sequencer.c +msgid "no cherry-pick in progress" +msgstr "nÃl aon phiocadh silÃnà ar siúl" + +#: sequencer.c +msgid "failed to skip the commit" +msgstr "theip ar an gealltanas a scipeáil" + +#: sequencer.c +msgid "there is nothing to skip" +msgstr "nÃl aon rud le scipeáil" + +#: sequencer.c +#, c-format +msgid "" +"have you committed already?\n" +"try \"git %s --continue\"" +msgstr "" +"an ndearna tú tiomanta cheana féin?\n" +"bain triail as “git %s --continueâ€" + +#: sequencer.c +msgid "cannot read HEAD" +msgstr "nà féidir le HEAD a léamh" + +#: sequencer.c +msgid "could not write commit message file" +msgstr "nà raibh sé in ann comhad teachtaireachta tiomanta a" + +#: sequencer.c +#, c-format +msgid "" +"You can amend the commit now, with\n" +"\n" +" git commit --amend %s\n" +"\n" +"Once you are satisfied with your changes, run\n" +"\n" +" git rebase --continue\n" +msgstr "" +"Féadfaidh tú an gealltanas a leasú anois, le\n" +"\n" +" git commit --amend %s\n" +"\n" +"Nuair a bheidh tú sásta le d'athruithe, rith\n" +"\n" +" git rebase --continue\n" + +#: sequencer.c +#, c-format +msgid "Could not apply %s... %.*s" +msgstr "NÃorbh fhéidir iarratas a dhéanamh %s... %.*s" + +#: sequencer.c +#, c-format +msgid "Could not merge %.*s" +msgstr "NÃorbh fhéidir cumasc %.*s" + +#: sequencer.c +#, c-format +msgid "Executing: %s\n" +msgstr "ForghnÃomhú: %s\n" + +#: sequencer.c +#, c-format +msgid "" +"execution failed: %s\n" +"%sYou can fix the problem, and then run\n" +"\n" +" git rebase --continue\n" +"\n" +msgstr "" +"theip ar fhorghnÃomhú: %s\n" +"%sIs féidir leat an fhadhb a shocrú, agus ansin rith\n" +"\n" +" git rebase --continue\n" + +#: sequencer.c +msgid "and made changes to the index and/or the working tree.\n" +msgstr "agus rinne siad athruithe ar an innéacs agus/nó ar an gcrann oibre.\n" + +#: sequencer.c +#, c-format +msgid "" +"execution succeeded: %s\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 "" +"d'éirigh leis an bhforghnÃomhú: %s\n" +"ach d'fhág sé athruithe ar an innéacs agus/nó ar an gcrann oibre.\n" +"Déan do chuid athruithe a dhéanamh nó a stóráil, agus ansin rith\n" +"\n" +" git rebase --continue\n" +"\n" + +#: sequencer.c +#, c-format +msgid "illegal label name: '%.*s'" +msgstr "ainm lipéid neamhdhleathach: '%.*s'" + +#: sequencer.c +#, c-format +msgid "could not resolve '%s'" +msgstr "nà fhéadfaà '%s' a réiteach" + +#: sequencer.c +msgid "writing fake root commit" +msgstr "tiomantas fréamh bréige a scrÃobh" + +#: sequencer.c +msgid "writing squash-onto" +msgstr "scrÃobh squash-on" + +#: sequencer.c +msgid "cannot merge without a current revision" +msgstr "nà féidir a chumasc gan athbhreithniú reatha" + +#: sequencer.c +#, c-format +msgid "unable to parse '%.*s'" +msgstr "nach féidir le parsáil a dhéanamh '%.*s" + +#: sequencer.c +#, c-format +msgid "nothing to merge: '%.*s'" +msgstr "nÃl aon rud le cumasc: '%.*s'" + +#: sequencer.c +msgid "octopus merge cannot be executed on top of a [new root]" +msgstr "nà féidir cumaisc ochtair a fhorghnÃomhú ar bharr [fréamh nua]" + +#: sequencer.c +#, c-format +msgid "could not get commit message of '%s'" +msgstr "nà fhéadfaà teachtaireacht tiomanta de '%s' a fháil" + +#: sequencer.c +#, c-format +msgid "could not even attempt to merge '%.*s'" +msgstr "nÃorbh fhéidir fiú iarracht a dhéanamh '%.*s' a chumasc" + +#: sequencer.c +msgid "merge: Unable to write new index file" +msgstr "cumaisc: Nà féidir comhad innéacs nua a scrÃobh" + +#: sequencer.c +#, c-format +msgid "" +"another 'rebase' process appears to be running; '%s.lock' already exists" +msgstr "" +"is cosúil go bhfuil próiseas 'rebase' eile ag rith; tá '%s.lock' ann cheana " +"féin" + +#: sequencer.c +#, c-format +msgid "" +"Updated the following refs with %s:\n" +"%s" +msgstr "" +"NuashonraÃodh na hifrÃochtaà seo a leanas le %s:\n" +"%s" + +#: sequencer.c +#, c-format +msgid "" +"Failed to update the following refs with %s:\n" +"%s" +msgstr "" +"Theip ar na hiarratais seo a leanas a nuashonrú le %s:\n" +"%s" + +#: sequencer.c +msgid "Cannot autostash" +msgstr "Nà féidir uathoibriú" + +#: sequencer.c +#, c-format +msgid "Unexpected stash response: '%s'" +msgstr "Freagra stash gan choinne: '%s'" + +#: sequencer.c +#, c-format +msgid "Could not create directory for '%s'" +msgstr "Nà fhéadfaà eolaire a chruthú do '%s'" + +#: sequencer.c +#, c-format +msgid "Created autostash: %s\n" +msgstr "Autostash cruthaithe: %s\n" + +#: sequencer.c +msgid "could not reset --hard" +msgstr "nà fhéadfaà athshocrú --hard" + +#: sequencer.c +#, c-format +msgid "Applied autostash.\n" +msgstr "Autostash feidhmithe.\n" + +#: sequencer.c +#, c-format +msgid "cannot store %s" +msgstr "nà féidir %s a stóráil" + +#: sequencer.c +#, c-format +msgid "" +"%s\n" +"Your changes are safe in the stash.\n" +"You can run \"git stash pop\" or \"git stash drop\" at any time.\n" +msgstr "" +"%s\n" +"Tá do chuid athruithe sábháilte sa stóras.\n" +"Is féidir leat \"git stash pop\" nó \"git stash drop\" a rith ag am ar " +"bith.\n" + +#: sequencer.c +msgid "Applying autostash resulted in conflicts." +msgstr "Bhà coinbhleachtaà mar thoradh ar autostash i bhfeidhm." + +#: sequencer.c +msgid "Autostash exists; creating a new stash entry." +msgstr "Tá Autostash ann; ag cruthú iontráil nua stash." + +#: sequencer.c +msgid "autostash reference is a symref" +msgstr "is é tagairt autostash ina symref" + +#: sequencer.c +msgid "could not detach HEAD" +msgstr "nà fhéadfadh CEAD a dhÃcheangal" + +#: sequencer.c +#, c-format +msgid "Stopped at HEAD\n" +msgstr "Stopadh ag HEAD\n" + +#: sequencer.c +#, c-format +msgid "Stopped at %s\n" +msgstr "Stop ag %s\n" + +#: sequencer.c +#, c-format +msgid "" +"Could not execute the todo command\n" +"\n" +" %.*s\n" +"It has been rescheduled; To edit the command before continuing, please\n" +"edit the todo list first:\n" +"\n" +" git rebase --edit-todo\n" +" git rebase --continue\n" +msgstr "" +"Nà fhéadfaà an t-ordú todo a fhorghnÃomhú\n" +"\n" +" %.*s\n" +"Tá sé athsceidealaithe; Chun an t-ordú a chur in eagar sula leanann tú ar " +"aghaidh, le do thoil\n" +"cuir an liosta todo in eagar ar dtús:\n" +"\n" +" git rebase --edit-todo\n" +" git rebase --continue\n" + +#: sequencer.c +#, c-format +msgid "Stopped at %s... %.*s\n" +msgstr "Stopadh ag %s... %.*s\n" + +#: sequencer.c +#, c-format +msgid "Rebasing (%d/%d)%s" +msgstr "Ag athbhunú (%d/%d) %s" + +#: sequencer.c +#, c-format +msgid "unknown command %d" +msgstr "ordú anaithnid %d" + +#: sequencer.c +msgid "could not read orig-head" +msgstr "nà raibh sé in ann ceann orig-head a léamh" + +#: sequencer.c +msgid "could not read 'onto'" +msgstr "nà fhéadfaà 'ar' léamh" + +#: sequencer.c +#, c-format +msgid "could not update HEAD to %s" +msgstr "nà fhéadfaà HEAD a nuashonrú go %s" + +#: sequencer.c +#, c-format +msgid "Successfully rebased and updated %s.\n" +msgstr "Athbhunaithe agus nuashonraithe %s go rathúil.\n" + +#: sequencer.c +msgid "cannot rebase: You have unstaged changes." +msgstr "nà féidir athbhunú: Tá athruithe gan stáitse agat." + +#: sequencer.c +msgid "cannot amend non-existing commit" +msgstr "nà féidir gealltanas nach bhfuil ann a leasú" + +#: sequencer.c +#, c-format +msgid "invalid file: '%s'" +msgstr "comhad neamhbhailÃ: '%s'" + +#: sequencer.c +#, c-format +msgid "invalid contents: '%s'" +msgstr "ábhar neamhbhailÃ: '%s'" + +#: sequencer.c +msgid "" +"\n" +"You have uncommitted changes in your working tree. Please, commit them\n" +"first and then run 'git rebase --continue' again." +msgstr "" +"\n" +"Tá athruithe neamhthiomanta agat i do chrann oibre. Le do thoil, tiomnaigh " +"iad\n" +"ar dtús agus ansin rith 'git rebase --continue' arÃs." + +#: sequencer.c +#, c-format +msgid "could not write file: '%s'" +msgstr "nà fhéadfaà comhad a scrÃobh: '%s'" + +#: sequencer.c +msgid "could not remove CHERRY_PICK_HEAD" +msgstr "nà fhéadfaà CHERRY_PICK_HEAD a bhaint" + +#: sequencer.c +msgid "could not commit staged changes." +msgstr "nà fhéadfadh athruithe stáitse a dhéanamh." + +#: sequencer.c +#, c-format +msgid "%s: can't cherry-pick a %s" +msgstr "%s: nà féidir %s a roghnú silÃnÃ" + +#: sequencer.c +#, c-format +msgid "%s: bad revision" +msgstr "%s: droch-athbhreithniú" + +#: sequencer.c +msgid "can't revert as initial commit" +msgstr "nà féidir teacht ar ais mar thiomantas tosaigh" + +#: sequencer.c +#, c-format +msgid "skipped previously applied commit %s" +msgstr "scipeáil tiomantas %s a cuireadh i bhfeidhm" + +#: sequencer.c +msgid "use --reapply-cherry-picks to include skipped commits" +msgstr "" +"bain úsáid as --reapply-cherry-picks chun gealltanais scipeáilte a áireamh" + +#: sequencer.c +msgid "make_script: unhandled options" +msgstr "make_script: roghanna neamh-láimhseáilte" + +#: sequencer.c +msgid "make_script: error preparing revisions" +msgstr "make_script: earráid ag ullmhú athbhreithnithe" + +#: sequencer.c +msgid "nothing to do" +msgstr "aon rud le déanamh" + +#: sequencer.c +msgid "could not skip unnecessary pick commands" +msgstr "nà fhéadfadh orduithe pioc gan ghá a scipeáil" + +#: sequencer.c +msgid "the script was already rearranged." +msgstr "athshocraÃodh an script cheana féin." + +#: sequencer.c +#, c-format +msgid "update-refs file at '%s' is invalid" +msgstr "tá comhad update-refs ag '%s' neamhbhailÃ" + +#: setup.c +#, c-format +msgid "'%s' is outside repository at '%s'" +msgstr "Tá '%s' an stór lasmuigh ag '%s'" + +#: setup.c +#, c-format +msgid "" +"%s: no such path in the working tree.\n" +"Use 'git <command> -- <path>...' to specify paths that do not exist locally." +msgstr "" +"%s: nÃl aon chosán den sórt sin sa chrann oibre.\n" +"Úsáid 'git <command>--<path>... 'chun cosáin nach bhfuil ann go háitiúil a " +"shonrú." + +#: setup.c +#, c-format +msgid "" +"ambiguous argument '%s': unknown revision or path not in the working tree.\n" +"Use '--' to separate paths from revisions, like this:\n" +"'git <command> [<revision>...] -- [<file>...]'" +msgstr "" +"argóint débhrÃoch '%s': athbhreithniú anaithnid nó cosán nach bhfuil sa " +"chrann oibre.\n" +"Úsáid '--' chun cosáin a scaradh ó athbhreithnithe, mar seo:\n" +"'git <command>[<revision>...] -- [<file>...] '" + +#: setup.c +#, c-format +msgid "option '%s' must come before non-option arguments" +msgstr "caithfidh rogha '%s' teacht roimh argóintà neamh-rogha" + +#: setup.c +#, c-format +msgid "" +"ambiguous argument '%s': both revision and filename\n" +"Use '--' to separate paths from revisions, like this:\n" +"'git <command> [<revision>...] -- [<file>...]'" +msgstr "" +"argóint débhrÃoch '%s': athbhreithniú agus ainm comhaid araon\n" +"Úsáid '--' chun cosáin a scaradh ó athbhreithnithe, mar seo:\n" +"'git <command>[<revision>...] -- [<file>...] '" + +#: setup.c +msgid "unable to set up work tree using invalid config" +msgstr "" +"in ann crann oibre a chur ar bun ag baint úsáide as cumraÃocht nebhailÃ" + +#: setup.c +#, c-format +msgid "'%s' already specified as '%s'" +msgstr "'%s' sonraithe cheana féin mar '%s'" + +#: setup.c +#, c-format +msgid "Expected git repo version <= %d, found %d" +msgstr "Leagan repo git ag súil leis <= %d, aimsÃodh %d" + +#: setup.c +msgid "unknown repository extension found:" +msgid_plural "unknown repository extensions found:" +msgstr[0] "sÃneadh stórais anaithnid aimsithe:" +msgstr[1] "sÃntà stórais anaithnide aimsithe:" +msgstr[2] "sÃntà stórais anaithnide aimsithe:" + +#: setup.c +msgid "repo version is 0, but v1-only extension found:" +msgid_plural "repo version is 0, but v1-only extensions found:" +msgstr[0] "is é leagan repo 0, ach fuarthas sÃneadh v1 amháin:" +msgstr[1] "is é 0 an leagan den stór, ach fuarthas sÃntà v1 amháin:" +msgstr[2] "is é 0 an leagan den stór, ach fuarthas sÃntà v1 amháin:" + +#: setup.c +#, c-format +msgid "error opening '%s'" +msgstr "earráid ag oscailt '%s'" + +#: setup.c +#, c-format +msgid "too large to be a .git file: '%s'" +msgstr "ró-mhór le bheith ina chomhad .git: '%s'" + +#: setup.c +#, c-format +msgid "error reading %s" +msgstr "earráid ag léamh %s" + +#: setup.c +#, c-format +msgid "invalid gitfile format: %s" +msgstr "formáid gitfile neamhbhailÃ: %s" + +#: setup.c +#, c-format +msgid "no path in gitfile: %s" +msgstr "gan aon chosán i gitfile: %s" + +#: setup.c +#, c-format +msgid "not a git repository: %s" +msgstr "nà stór git: %s" + +#: setup.c +#, c-format +msgid "'$%s' too big" +msgstr "'$%s' ró-mhór" + +#: setup.c +#, c-format +msgid "not a git repository: '%s'" +msgstr "nà stór git: '%s'" + +#: setup.c +#, c-format +msgid "cannot chdir to '%s'" +msgstr "nà féidir teacht ar '%s'" + +#: setup.c +msgid "cannot come back to cwd" +msgstr "nà féidir teacht ar ais chuig cwd" + +#: setup.c +#, c-format +msgid "failed to stat '%*s%s%s'" +msgstr "theip ar '%*s%s%s' a thaispeáint" + +#: setup.c +#, c-format +msgid "safe.directory '%s' not absolute" +msgstr "nÃl safe.directory '%s' iomlán" + +#: setup.c +#, c-format +msgid "" +"detected dubious ownership in repository at '%s'\n" +"%sTo add an exception for this directory, call:\n" +"\n" +"\tgit config --global --add safe.directory %s" +msgstr "" +"braitheadh ​​úinéireacht amhrasach sa stórlann ag '%s'\n" +"%sChun eisceacht a chur leis an eolaire seo, glaoigh ar:\n" +"\n" +"git config --global --add safe.directory %s" + +#: setup.c +msgid "Unable to read current working directory" +msgstr "Nà féidir eolaire oibre reatha a léamh" + +#: setup.c +#, c-format +msgid "cannot change to '%s'" +msgstr "nà féidir athrú go '%s'" + +#: setup.c +#, c-format +msgid "not a git repository (or any of the parent directories): %s" +msgstr "nà stór git (nó aon cheann de na tuismitheoireolairÃ): %s" + +#: setup.c +#, 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 "" +"nà stór git (nó aon thuismitheoir suas go dtà an pointe gléasta %s)\n" +"Stopadh ag teorainn an chórais chomhaid (nÃl GIT_DISCOVERY_ACROSS_FILESYSTEM " +"socraithe)." + +#: setup.c +#, c-format +msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')" +msgstr "nà féidir stór lom '%s' a úsáid (safe.bareRepository is '%s')" + +#: setup.c +#, c-format +msgid "" +"problem with core.sharedRepository filemode value (0%.3o).\n" +"The owner of files must always have read and write permissions." +msgstr "" +"fadhb le luach mód comhaid core.sharedRepository (0%.3o).\n" +"Nà mór ceadanna léite agus scrÃbhneoireachta a bheith ag úinéir na gcomhad i " +"gcónaÃ." + +#: setup.c +msgid "fork failed" +msgstr "theip ar fhorc" + +#: setup.c +msgid "setsid failed" +msgstr "theip ar setsid" + +#: setup.c +#, c-format +msgid "cannot stat template '%s'" +msgstr "nà féidir teacht ar theimpléad '%s'" + +#: setup.c +#, c-format +msgid "cannot opendir '%s'" +msgstr "nà féidir '%s' a oscailt" + +#: setup.c +#, c-format +msgid "cannot readlink '%s'" +msgstr "nà féidir nasc '%s' a léamh" + +#: setup.c +#, c-format +msgid "cannot symlink '%s' '%s'" +msgstr "nà féidir '%s' '' %s 'a nascadh" + +#: setup.c +#, c-format +msgid "cannot copy '%s' to '%s'" +msgstr "nà féidir '%s' a chóipeáil chuig '%s'" + +#: setup.c +#, c-format +msgid "ignoring template %s" +msgstr "ag neamhaird den teimpléad %s" + +#: setup.c +#, c-format +msgid "templates not found in %s" +msgstr "teimpléid gan aimsiú i %s" + +#: setup.c +#, c-format +msgid "not copying templates from '%s': %s" +msgstr "gan teimpléid a chóipeáil ó '%s': %s" + +#: setup.c +#, c-format +msgid "invalid initial branch name: '%s'" +msgstr "ainm brainse tosaigh neamhbhailÃ: '%s'" + +#: setup.c +#, c-format +msgid "re-init: ignored --initial-branch=%s" +msgstr "ath-init: neamhaird a dhéanamh ar --initial-branch=%s" + +#: setup.c +#, c-format +msgid "unable to handle file type %d" +msgstr "in ann cineál comhad %d a láimhseáil" + +#: setup.c +#, c-format +msgid "unable to move %s to %s" +msgstr "nach féidir %s a bhogadh go %s" + +#: setup.c +msgid "attempt to reinitialize repository with different hash" +msgstr "iarracht a dhéanamh stór a aththionsú le hash difriúil" + +#: setup.c +msgid "" +"attempt to reinitialize repository with different reference storage format" +msgstr "" +"iarracht a dhéanamh stór a aththionsú le formáid stórála tagartha difriúil" + +#: setup.c +#, c-format +msgid "%s already exists" +msgstr "Tá %s ann cheana féin" + +#: setup.c +#, c-format +msgid "Reinitialized existing shared Git repository in %s%s\n" +msgstr "Stórlann Git roinnte atá ann cheana a athsheoladh i %s%s\n" + +#: setup.c +#, c-format +msgid "Reinitialized existing Git repository in %s%s\n" +msgstr "AththionscnaÃodh stór Git atá ann cheana i %s%s\n" + +#: setup.c +#, c-format +msgid "Initialized empty shared Git repository in %s%s\n" +msgstr "Stórlann Git roinnte folamh tosaithe i %s%s\n" + +#: setup.c +#, c-format +msgid "Initialized empty Git repository in %s%s\n" +msgstr "Stórlann Git folamh tosaithe i %s%s\n" + +#: sparse-index.c +#, c-format +msgid "index entry is a directory, but not sparse (%08x)" +msgstr "is eolaire é iontráil innéacs, ach nà neamhchoitianta (%08x)" + +#: split-index.c +msgid "cannot use split index with a sparse index" +msgstr "nà féidir innéacs scoilte a úsáid le hinnéacs neamhchoitianta" + +#. 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 "fhormáid olc %s: nà thosaÃonn eilimint '%s' le '('" + +#. 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 "droch-fhormáid %s: nà chrÃochnaÃonn eilimint '%s' i ')'" + +#. TRANSLATORS: %s is a command like "ls-tree". +#: strbuf.c +#, c-format +msgid "bad %s format: %%%.*s" +msgstr "fhormáid %s olc: %%%.*s" + +#. TRANSLATORS: IEC 80000-13:2008 gibibyte +#: strbuf.c +#, c-format +msgid "%u.%2.2u GiB" +msgstr "%u.%2.2u GiB" + +#. TRANSLATORS: IEC 80000-13:2008 gibibyte/second +#: strbuf.c +#, c-format +msgid "%u.%2.2u GiB/s" +msgstr "%u.%2.2u GiB/s" + +#. TRANSLATORS: IEC 80000-13:2008 mebibyte +#: strbuf.c +#, c-format +msgid "%u.%2.2u MiB" +msgstr "%u.%2.2u MiB" + +#. TRANSLATORS: IEC 80000-13:2008 mebibyte/second +#: strbuf.c +#, c-format +msgid "%u.%2.2u MiB/s" +msgstr "%u.%2.2u MiB/s" + +#. TRANSLATORS: IEC 80000-13:2008 kibibyte +#: strbuf.c +#, c-format +msgid "%u.%2.2u KiB" +msgstr "%u.%2.2u KiB" + +#. TRANSLATORS: IEC 80000-13:2008 kibibyte/second +#: strbuf.c +#, c-format +msgid "%u.%2.2u KiB/s" +msgstr "%u.%2.2u KiB/s" + +#. TRANSLATORS: IEC 80000-13:2008 byte +#: strbuf.c +#, c-format +msgid "%u byte" +msgid_plural "%u bytes" +msgstr[0] "%u beart" +msgstr[1] "%u beart" +msgstr[2] "%u beart" + +#. TRANSLATORS: IEC 80000-13:2008 byte/second +#: strbuf.c +#, c-format +msgid "%u byte/s" +msgid_plural "%u bytes/s" +msgstr[0] "%u beart/s" +msgstr[1] "%u beart/s" +msgstr[2] "%u beart/s" + +#: submodule-config.c +#, c-format +msgid "ignoring suspicious submodule name: %s" +msgstr "ag déanamh neamhaird d'ainm fo-mhodúil amhrasach: %s" + +#: submodule-config.c +msgid "negative values not allowed for submodule.fetchJobs" +msgstr "luachanna diúltacha nach gceadaÃtear le haghaidh submodule.fetchJobs" + +#: submodule-config.c +#, c-format +msgid "ignoring '%s' which may be interpreted as a command-line option: %s" +msgstr "" +"neamhaird a dhéanamh ar '%s' ar féidir a léirmhÃniú mar rogha lÃne ordaithe: " +"%s" + +#: submodule-config.c +#, c-format +msgid "Could not update .gitmodules entry %s" +msgstr "Nà fhéadfaà iontráil.gitmodules %s a nuashonrú" + +#: submodule.c +msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" +msgstr "" +"Nà féidir .gitmodules neamh-chumhdaithe a athrú, coinbhleachtaà cumaisc a " +"réiteach" + +#: submodule.c +#, c-format +msgid "Could not find section in .gitmodules where path=%s" +msgstr "" +"NÃorbh fhéidir an rannóg a aimsiú i .gitmodules áit a bhfuil an cosán = %s" + +#: submodule.c +#, c-format +msgid "Could not remove .gitmodules entry for %s" +msgstr "Nà fhéadfaà iontráil.gitmodules a bhaint do %s" + +#: submodule.c +msgid "staging updated .gitmodules failed" +msgstr "theip ar stáisiú nuashonraithe .gitmodules" + +#: submodule.c +#, c-format +msgid "in unpopulated submodule '%s'" +msgstr "i bhfo-mhodúl neamhdhaonra '%s'" + +#: submodule.c +#, c-format +msgid "Pathspec '%s' is in submodule '%.*s'" +msgstr "Tá pathspec '%s' i bhfo-mhodúl '%.*s" + +#: submodule.c +#, c-format +msgid "bad --ignore-submodules argument: %s" +msgstr "argóint olc --ignore-submodules: %s" + +#: submodule.c +#, c-format +msgid "" +"Submodule in commit %s at path: '%s' collides with a submodule named the " +"same. Skipping it." +msgstr "" +"Fo-mhodúl i dtiomantas %s ag an gcosán: imbhuaileann '%s' le fo-mhodúl darb " +"ainm mar an gcéanna. Ag scipeáil é." + +#: submodule.c +#, c-format +msgid "submodule entry '%s' (%s) is a %s, not a commit" +msgstr "is %s é iontráil an fhomhodúil '%s' (%s), nà tiomnú" + +#: submodule.c +#, c-format +msgid "" +"Could not run 'git rev-list <commits> --not --remotes -n 1' command in " +"submodule %s" +msgstr "" +"Nà raibh an t-ordú 'git rev-list <commits>--not --remotes -n 1' a reáchtáil " +"i bhfo-mhodúl %s" + +#: submodule.c +#, c-format +msgid "process for submodule '%s' failed" +msgstr "theip ar phróiseas le haghaidh fo-mhodúl '%s'" + +#: submodule.c +#, c-format +msgid "Pushing submodule '%s'\n" +msgstr "Ag brú an fho-mhodúil '%s'\n" + +#: submodule.c +#, c-format +msgid "Unable to push submodule '%s'\n" +msgstr "Nà féidir an fho-mhodúl '%s' a bhrú\n" + +#: submodule.c +#, c-format +msgid "Fetching submodule %s%s\n" +msgstr "Ag fáil fo-mhodúl %s%s\n" + +#: submodule.c +#, c-format +msgid "Could not access submodule '%s'\n" +msgstr "NÃorbh fhéidir rochtain a fháil ar fho-mhodúl '%s'\n" + +#: submodule.c +#, c-format +msgid "Could not access submodule '%s' at commit %s\n" +msgstr "NÃorbh fhéidir rochtain a fháil ar fho-mhodúl '%s' ag tiomantas %s\n" + +#: submodule.c +#, c-format +msgid "Fetching submodule %s%s at commit %s\n" +msgstr "Ag fáil fo-mhodúl %s%s ag an tiomnú %s\n" + +#: submodule.c +#, c-format +msgid "" +"Errors during submodule fetch:\n" +"%s" +msgstr "" +"Earráidà le linn teacht fo-mhodúil:\n" +"%s" + +#: submodule.c +#, c-format +msgid "'%s' not recognized as a git repository" +msgstr "Nà aithnÃtear '%s' mar stór git" + +#: submodule.c +#, c-format +msgid "Could not run 'git status --porcelain=2' in submodule %s" +msgstr "Nà féidir 'git status --porcelain=2' a reáchtáil i bhfo-mhodúl %s" + +#: submodule.c +#, c-format +msgid "'git status --porcelain=2' failed in submodule %s" +msgstr "Theip ar 'git status --porcelain=2' i bhfo-mhodúl %s" + +#: submodule.c +#, c-format +msgid "could not start 'git status' in submodule '%s'" +msgstr "nà fhéadfaà 'git status' a thosú i bhfo-mhodúl '%s'" + +#: submodule.c +#, c-format +msgid "could not run 'git status' in submodule '%s'" +msgstr "nà fhéadfaà 'git status' a reáchtáil i bhfo-mhodúl '%s'" + +#: submodule.c +#, c-format +msgid "Could not unset core.worktree setting in submodule '%s'" +msgstr "Nà fhéadfaà socrú core.worktree a dhÃshocrú i bhfo-mhodúl '%s'" + +#: submodule.c +#, c-format +msgid "could not recurse into submodule '%s'" +msgstr "nà fhéadfaà athshlánú isteach i bhfo-mhodúl '%s'" + +#: submodule.c +msgid "could not reset submodule index" +msgstr "nà fhéadfadh innéacs fo-mhodúil a athshocrú" + +#: submodule.c +#, c-format +msgid "submodule '%s' has dirty index" +msgstr "tá innéacs salach ag fo-mhodúl '%s'" + +#: submodule.c +#, c-format +msgid "Submodule '%s' could not be updated." +msgstr "Nà fhéadfaà fo-mhodúl '%s' a nuashonrú." + +#: submodule.c +#, c-format +msgid "submodule git dir '%s' is inside git dir '%.*s'" +msgstr "tá fo-mhodúl git dir '%s' taobh istigh de git dir '%.*s" + +#: submodule.c +#, c-format +msgid "expected '%.*s' in submodule path '%s' not to be a symbolic link" +msgstr "" +"ag súil leis '%.*s' i gcosán fo-mhodúil '%s' gan a bheith ina nasc siombalach" + +#: submodule.c +#, c-format +msgid "expected submodule path '%s' not to be a symbolic link" +msgstr "ag súil nach mbeidh cosán fo-mhodúil '%s' ina nasc siombalach" + +#: submodule.c +#, c-format +msgid "" +"relocate_gitdir for submodule '%s' with more than one worktree not supported" +msgstr "" +"relocate_gitdir le haghaidh fo-mhodúil '%s' le nÃos mó ná crann oibre amháin " +"nach dtacaÃtear leis" + +#: submodule.c +#, c-format +msgid "could not lookup name for submodule '%s'" +msgstr "nà fhéadfaà ainm a lorg don fho-mhodúl '%s'" + +#: submodule.c +#, c-format +msgid "refusing to move '%s' into an existing git dir" +msgstr "diúltú '%s' a bhogadh isteach i git dir atá ann cheana" + +#: submodule.c +#, c-format +msgid "" +"Migrating git directory of '%s%s' from\n" +"'%s' to\n" +"'%s'\n" +msgstr "" +"Ag aistriú eolaire git de '%s%s' ó\n" +"'%s' go\n" +"'%s'\n" + +#: submodule.c +msgid "could not start ls-files in .." +msgstr "nà fhéadfaà ls-files a thosú i.." + +#: submodule.c +#, c-format +msgid "ls-tree returned unexpected return code %d" +msgstr "d’fhill an crann ls cód fillte gan choinne %d" + +#: symlinks.c +#, c-format +msgid "failed to lstat '%s'" +msgstr "theip ar lstat '%s'" + +#: t/helper/test-bundle-uri.c +msgid "no remote configured to get bundle URIs from" +msgstr "gan aon iargúlta cumraithe chun URIs beartán a fháil ó" + +#: t/helper/test-bundle-uri.c +msgid "could not get the bundle-uri list" +msgstr "nà raibh in ann an liosta bundle-uri a fháil" + +#: t/helper/test-cache-tree.c +msgid "test-tool cache-tree <options> (control|prime|update)" +msgstr "test-tool cache-tree <options> (control|prime|update)" + +#: t/helper/test-cache-tree.c +msgid "clear the cache tree before each iteration" +msgstr "glan an crann taisce roimh gach athrú" + +#: t/helper/test-cache-tree.c +msgid "number of entries in the cache tree to invalidate (default 0)" +msgstr "" +"lÃon na n-iontrálacha sa chrann taisce le neamhbhailà (réamhshocraithe 0)" + +#: t/helper/test-pack-deltas.c +msgid "the number of objects to write" +msgstr "lÃon na rudaà le scrÃobh" + +#: t/helper/test-path-walk.c +msgid "test-tool path-walk <options> -- <revision-options>" +msgstr "test-tool path-walk <options> -- <revision-options>" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of blob objects" +msgstr "cuimsiú rudaà blob a thógáil" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of commit objects" +msgstr "toggle áireamh rudaà tiomanta" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tag objects" +msgstr "cuimsiú rudaà clibeanna a thosc" + +#: t/helper/test-path-walk.c +msgid "toggle inclusion of tree objects" +msgstr "cuimsiú rudaà crann a thógáil" + +#: t/helper/test-path-walk.c +msgid "toggle pruning of uninteresting paths" +msgstr "bearradh cosáin neamh-spéisiúla a thosú" + +#: t/helper/test-path-walk.c +msgid "read a pattern list over stdin" +msgstr "léigh liosta patrún thar stdin" + +#: t/helper/test-reach.c +#, c-format +msgid "commit %s is not marked reachable" +msgstr "nach bhfuil comhordú %s marcáilte inrochtana" + +#: t/helper/test-reach.c +msgid "too many commits marked reachable" +msgstr "an iomarca gealltanais atá marcáilte inrochtana" + +#: t/helper/test-read-midx.c +msgid "could not determine MIDX preferred pack" +msgstr "nà fhéadfaà pacáiste is fearr MIDX a chinneadh" + +#: t/helper/test-serve-v2.c +msgid "test-tool serve-v2 [<options>]" +msgstr "test-tool serve-v2 [<options>]" + +#: t/helper/test-serve-v2.c +msgid "exit immediately after advertising capabilities" +msgstr "imeacht dÃreach tar éis cumais fógraÃochta" + +#: t/helper/test-simple-ipc.c +msgid "test-helper simple-ipc is-active [<name>] [<options>]" +msgstr "<name><options>tá cúntóir tástála simple-ipc gnÃomhach [] []" + +#: t/helper/test-simple-ipc.c +msgid "test-helper simple-ipc run-daemon [<name>] [<threads>]" +msgstr "<name><threads>cúntóir tástála simple-ipc run-daemon [] []" + +#: t/helper/test-simple-ipc.c +msgid "test-helper simple-ipc start-daemon [<name>] [<threads>] [<max-wait>]" +msgstr "" +"<name><threads><max-wait>cúntóir tástála simple-ipc tosaigh daemon [] [] []" + +#: t/helper/test-simple-ipc.c +msgid "test-helper simple-ipc stop-daemon [<name>] [<max-wait>]" +msgstr "<name><max-wait>cúntóir tástála simple-ipc stad-daemon [] []" + +#: t/helper/test-simple-ipc.c +msgid "test-helper simple-ipc send [<name>] [<token>]" +msgstr "<name><token>cúntóir tástála simple-ipc seol [] []" + +#: t/helper/test-simple-ipc.c +msgid "test-helper simple-ipc sendbytes [<name>] [<bytecount>] [<byte>]" +msgstr "<name><bytecount><byte>test-helper simple-ipc sendbytes [] [] []" + +#: t/helper/test-simple-ipc.c +msgid "" +"test-helper simple-ipc multiple [<name>] [<threads>] [<bytecount>] " +"[<batchsize>]" +msgstr "" +"test-helper simple-ipc multiple [<name>] [<threads>] [<bytecount>] " +"[<batchsize>]" + +#: t/helper/test-simple-ipc.c +msgid "name or pathname of unix domain socket" +msgstr "ainm nó ainm cosán soicéad fearainn unix" + +#: t/helper/test-simple-ipc.c +msgid "named-pipe name" +msgstr "ainm pÃopa ainmnithe" + +#: t/helper/test-simple-ipc.c +msgid "number of threads in server thread pool" +msgstr "lÃon na snáitheanna i linn snáithe freastalaÃ" + +#: t/helper/test-simple-ipc.c +msgid "seconds to wait for daemon to start or stop" +msgstr "soicind chun fanacht go dtosóidh nó stopfaidh an daemon" + +#: t/helper/test-simple-ipc.c +msgid "number of bytes" +msgstr "lÃon na mbetaÃ" + +#: t/helper/test-simple-ipc.c +msgid "number of requests per thread" +msgstr "lÃon iarratais in aghaidh an snáithe" + +#: t/helper/test-simple-ipc.c +msgid "byte" +msgstr "bith" + +#: t/helper/test-simple-ipc.c +msgid "ballast character" +msgstr "carachtar balasta" + +#: t/helper/test-simple-ipc.c +msgid "token" +msgstr "comhartha" + +#: t/helper/test-simple-ipc.c +msgid "command token to send to the server" +msgstr "comhartha ordaithe le seoladh chuig an bhfreastalaÃ" + +#: t/unit-tests/unit-test.c +msgid "unit-test [<options>]" +msgstr "unit-test [<options>]" + +#: t/unit-tests/unit-test.c +msgid "immediately exit upon the first failed test" +msgstr "imeacht láithreach ar an gcéad tástáil theip" + +#: t/unit-tests/unit-test.c +msgid "suite[::test]" +msgstr "suite [::test]" + +#: t/unit-tests/unit-test.c +msgid "run only test suite or individual test <suite[::test]>" +msgstr "reáchtáil ach sraith tástála nó tástáil aonair <suite [::test] >" + +#: t/unit-tests/unit-test.c +msgid "suite" +msgstr "svuÃt" + +#: t/unit-tests/unit-test.c +msgid "exclude test suite <suite>" +msgstr "sraith tástála a eisiamh <suite>" + +#: trailer.c +#, c-format +msgid "running trailer command '%s' failed" +msgstr "theip ar an ordú leantóir '%s' a rith" + +#: trailer.c +#, c-format +msgid "unknown value '%s' for key '%s'" +msgstr "luach anaithnid '%s' don eochair '%s'" + +#: trailer.c +#, c-format +msgid "empty trailer token in trailer '%.*s'" +msgstr "comhartha leantóra folamh i leantóir '%.*s'" + +#: transport-helper.c +msgid "full write to remote helper failed" +msgstr "theip ar scrÃobh iomlán chuig cianchúntóir" + +#: transport-helper.c +#, c-format +msgid "unable to find remote helper for '%s'" +msgstr "in ann cúntóir iargúlta a aimsiú do '%s'" + +#: transport-helper.c +msgid "can't dup helper output fd" +msgstr "nà féidir le aschur cúntóra fd a dhéanamh" + +#: transport-helper.c +#, c-format +msgid "" +"unknown mandatory capability %s; this remote helper probably needs newer " +"version of Git" +msgstr "" +"cumas éigeantach anaithnid %s; is dócha go mbeidh leagan nÃos nuaà de Git ag " +"teastáil ó" + +#: transport-helper.c +msgid "this remote helper should implement refspec capability" +msgstr "ba cheart go gcuirfeadh an cúntóir cianda seo cumas refspec" + +#: transport-helper.c +#, c-format +msgid "%s unexpectedly said: '%s'" +msgstr "Dúirt %s gan choinne: '%s'" + +#: transport-helper.c +#, c-format +msgid "%s also locked %s" +msgstr "Glas %s freisin %s" + +#: transport-helper.c +msgid "couldn't run fast-import" +msgstr "nà raibh in ann allmhairiú tapa a reá" + +#: transport-helper.c +msgid "error while running fast-import" +msgstr "earráid agus iompórtáil tapa á rith" + +#: transport-helper.c +#, c-format +msgid "could not read ref %s" +msgstr "nà raibh in ann tagairt %s a léamh" + +#: transport-helper.c +#, c-format +msgid "unknown response to connect: %s" +msgstr "freagra anaithnid chun nascadh: %s" + +#: transport-helper.c +msgid "setting remote service path not supported by protocol" +msgstr "cosán seirbhÃse iargúlta a shocrú nach dtacaÃonn" + +#: transport-helper.c +msgid "invalid remote service path" +msgstr "cosán seirbhÃse iargúlta" + +#: transport-helper.c +#, c-format +msgid "can't connect to subservice %s" +msgstr "nà féidir nasc a dhéanamh le fo-sheirbhÃs %s" + +#: transport-helper.c transport.c +msgid "--negotiate-only requires protocol v2" +msgstr "--negotiate-only ag teastáil prótacal v2" + +#: transport-helper.c +msgid "'option' without a matching 'ok/error' directive" +msgstr "'roghan' gan treoir 'ok/earráid' a mheaitseáil" + +#: transport-helper.c +#, c-format +msgid "expected ok/error, helper said '%s'" +msgstr "súil le ok/earráid, dúirt an cúntóir '%s'" + +#: transport-helper.c +#, c-format +msgid "helper reported unexpected status of %s" +msgstr "thuairiscigh cúntóir stádas gan choinne %s" + +#: transport-helper.c +#, c-format +msgid "helper %s does not support dry-run" +msgstr "nà thacaÃonn cúntóir %s le rith tirim" + +#: transport-helper.c +#, c-format +msgid "helper %s does not support --signed" +msgstr "nà thacaÃonn cúntóir %s le --signed" + +#: transport-helper.c +#, c-format +msgid "helper %s does not support --signed=if-asked" +msgstr "nà thacaÃonn cúntóir %s le --signed=if-iarrtha" + +#: transport-helper.c +#, c-format +msgid "helper %s does not support --atomic" +msgstr "nà thacaÃonn cúntóir %s le --atomic" + +#: transport-helper.c +#, c-format +msgid "helper %s does not support --%s" +msgstr "nà thacaÃonn cúntóir %s le --%s" + +#: transport-helper.c +#, c-format +msgid "helper %s does not support 'push-option'" +msgstr "nà thacaÃonn cúntóir %s le 'push-rogha'" + +#: transport-helper.c +msgid "remote-helper doesn't support push; refspec needed" +msgstr "nà thacaÃonn cúntóir iargúlta le brú; teastaÃonn refspec" + +#: transport-helper.c +#, c-format +msgid "helper %s does not support '--force'" +msgstr "nà thacaÃonn cúntóir %s le '--force'" + +#: transport-helper.c +msgid "couldn't run fast-export" +msgstr "nà raibh sé in ann onnmhairiú tapa a" + +#: transport-helper.c +msgid "error while running fast-export" +msgstr "earráid agus easpórtáil tapa á rith" + +#: transport-helper.c +#, c-format +msgid "" +"No refs in common and none specified; doing nothing.\n" +"Perhaps you should specify a branch.\n" +msgstr "" +"NÃl aon réimsà i gcoiteann agus nÃl aon cheann sonraithe; nà dhéanann aon " +"rud.\n" +"B'fhéidir gur chóir duit brainse a shonrú.\n" + +#: transport-helper.c +#, c-format +msgid "unsupported object format '%s'" +msgstr "formáid réad gan tacaÃocht '%s'" + +#: transport-helper.c +#, c-format +msgid "malformed response in ref list: %s" +msgstr "freagra mÃfhoirmithe sa liosta tagartha: %s" + +#: transport-helper.c +#, c-format +msgid "read(%s) failed" +msgstr "theip ar léamh (%s)" + +#: transport-helper.c +#, c-format +msgid "write(%s) failed" +msgstr "theip ar scrÃobh (%s)" + +#: transport-helper.c +#, c-format +msgid "%s thread failed" +msgstr "Theip ar snáithe %s" + +#: transport-helper.c +#, c-format +msgid "%s thread failed to join: %s" +msgstr "Theip ar shnáithe %s a bheith páirteach: %s" + +#: transport-helper.c +#, c-format +msgid "can't start thread for copying data: %s" +msgstr "nà féidir snáithe a thosú chun sonraà a chóipeáil: %s" + +#: transport-helper.c +#, c-format +msgid "%s process failed to wait" +msgstr "Theip ar phróiseas %s fanacht" + +#: transport-helper.c +#, c-format +msgid "%s process failed" +msgstr "Theip ar phróiseas %s" + +#: transport-helper.c +msgid "can't start thread for copying data" +msgstr "nà féidir snáithe a thosú chun sonraà a chóipe" + +#: transport.c +#, c-format +msgid "Would set upstream of '%s' to '%s' of '%s'\n" +msgstr "Socródh sé suas sruth de '%s' go '%s' de '%s'\n" + +#: transport.c +#, c-format +msgid "could not read bundle '%s'" +msgstr "nà fhéadfaà beartán '%s' a léamh" + +#: transport.c +#, c-format +msgid "transport: invalid depth option '%s'" +msgstr "iompar: rogha doimhneachta neamhbhailà '%s'" + +#: transport.c +msgid "see protocol.version in 'git help config' for more details" +msgstr "" +"féach protocol.version in 'git help config' le haghaidh tuilleadh sonraÃ" + +#: transport.c +msgid "server options require protocol version 2 or later" +msgstr "teastaÃonn leagan prótacal 2 nó nÃos déanaà ó roghanna" + +#: transport.c +msgid "server does not support wait-for-done" +msgstr "nà thacaÃonn freastalaà le fanacht le déanamh" + +#: transport.c +msgid "could not parse transport.color.* config" +msgstr "nà fhéadfaà transport.color.* config a pháirseáil" + +#: transport.c +msgid "support for protocol v2 not implemented yet" +msgstr "tacaÃocht do phrótacal v2 nach bhfuil curtha i bhfeidhm" + +#: transport.c +#, c-format +msgid "transport '%s' not allowed" +msgstr "nà cheadaÃtear iompar '%s'" + +#: transport.c +msgid "git-over-rsync is no longer supported" +msgstr "nà thacaÃtear le git-over-rsync a thuilleadh" + +#: transport.c +#, c-format +msgid "" +"The following submodule paths contain changes that can\n" +"not be found on any remote:\n" +msgstr "" +"Tá athruithe ar féidir leis na cosáin fo-mhodúil seo a leanas\n" +"nach bhfuil le fáil ar aon iargúlta:\n" + +#: transport.c +#, c-format +msgid "" +"\n" +"Please try\n" +"\n" +"\tgit push --recurse-submodules=on-demand\n" +"\n" +"or cd to the path and use\n" +"\n" +"\tgit push\n" +"\n" +"to push them to a remote.\n" +"\n" +msgstr "" +"\n" +"Déan iarracht\n" +"\n" +"\tgit push --recurse-submodules=on-demand\n" +"\n" +"nó cd chuig an gcosán agus úsáid\n" +"\n" +" Brúigh git\n" +"\n" +"chun iad a bhrú chuig iargúlta.\n" + +#: transport.c +msgid "Aborting." +msgstr "Ag gearradh." + +#: transport.c +msgid "failed to push all needed submodules" +msgstr "theip ar gach fo-mhodúl riachtanach a bhrú" + +#: transport.c +msgid "bundle-uri operation not supported by protocol" +msgstr "oibrÃocht bundle-uri nach dtacaÃonn prótacal" + +#: transport.c +msgid "could not retrieve server-advertised bundle-uri list" +msgstr "nà fhéadfaà liosta bundle-uri a fógraÃodh ag freastalaà a aisghab" + +#: transport.c +msgid "operation not supported by protocol" +msgstr "oibriú nach dtacaÃonn prótacal" + +#: tree-walk.c +msgid "too-short tree object" +msgstr "réad crann ró-ghearr" + +#: tree-walk.c +msgid "malformed mode in tree entry" +msgstr "modh mÃfhoirmithe i iontráil crann" + +#: tree-walk.c +msgid "empty filename in tree entry" +msgstr "ainm comhaid folamh i iontráil crann" + +#: tree-walk.c +msgid "too-short tree file" +msgstr "comhad crann ró-ghearr" + +#: unpack-trees.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by checkout:\n" +"%%sPlease commit your changes or stash them before you switch branches." +msgstr "" +"Déanfaà d'athruithe áitiúla ar na comhaid seo a leanas a fhorscrÃobh trà " +"sheiceáil:\n" +"%%sDéan d'athruithe nó déan iad a stóráil sula n-athraÃonn tú brainsÃ." + +#: unpack-trees.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by checkout:\n" +"%%s" +msgstr "" +"Déanfaà d'athruithe áitiúla ar na comhaid seo a leanas a fhorscrÃobh trà " +"sheiceáil:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by merge:\n" +"%%sPlease commit your changes or stash them before you merge." +msgstr "" +"Déanfaà d'athruithe áitiúla ar na comhaid seo a leanas a fhorscrÃobh trà " +"chumasc:\n" +"%%sDo chuid athruithe a dhéanamh nó cuir isteach iad sula ndéanann tú a " +"chumasc." + +#: unpack-trees.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by merge:\n" +"%%s" +msgstr "" +"Déanfaà d'athruithe áitiúla ar na comhaid seo a leanas a fhorscrÃobh trà " +"chumasc:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by %s:\n" +"%%sPlease commit your changes or stash them before you %s." +msgstr "" +"Déanfadh %s d'athruithe áitiúla ar na comhaid seo a leanas a fhorscrÃobh:\n" +"%%sDéan do chuid athruithe nó iad a stóráil os comhair %s." + +#: unpack-trees.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by %s:\n" +"%%s" +msgstr "" +"Déanfadh %s d'athruithe áitiúla ar na comhaid seo a leanas a fhorscrÃobh:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"Updating the following directories would lose untracked files in them:\n" +"%s" +msgstr "" +"Chaillfeadh na n-eolairà seo a leanas a nuashonrú comhaid gan rianú iontu:\n" +"%s" + +#: unpack-trees.c +#, c-format +msgid "" +"Refusing to remove the current working directory:\n" +"%s" +msgstr "" +"Diúltú an eolaire oibre reatha a bhaint:\n" +"%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be removed by checkout:\n" +"%%sPlease move or remove them before you switch branches." +msgstr "" +"Bainfà na comhaid crann oibre gan rianú seo a leanas trà sheiceáil:\n" +"%%sBogadh nó bain iad sula n-athraÃonn tú brainsÃ." + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be removed by checkout:\n" +"%%s" +msgstr "" +"Bainfà na comhaid crann oibre gan rianú seo a leanas trà sheiceáil:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be removed by merge:\n" +"%%sPlease move or remove them before you merge." +msgstr "" +"Bainfà na comhaid crann oibre gan rianú seo a leanas trà chumasc:\n" +"%%sDo thoil bog nó bain iad sula ndéanann tú a chumasc." + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be removed by merge:\n" +"%%s" +msgstr "" +"Bainfà na comhaid crann oibre gan rianú seo a leanas trà chumasc:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be removed by %s:\n" +"%%sPlease move or remove them before you %s." +msgstr "" +"Bainfà %s na comhaid crann oibre neamhrianaithe seo a leanas:\n" +"%%sDo thoil bog nó bain iad roimh %s." + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be removed by %s:\n" +"%%s" +msgstr "" +"Bainfà %s na comhaid crann oibre neamhrianaithe seo a leanas:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by " +"checkout:\n" +"%%sPlease move or remove them before you switch branches." +msgstr "" +"Déanfaà na comhaid crann oibre neamhrianaithe seo a leanas a fhorscrÃobh trà " +"sheiceáil:\n" +"%%sBogadh nó bain iad sula n-athraÃonn tú brainsÃ." + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by " +"checkout:\n" +"%%s" +msgstr "" +"Déanfaà na comhaid crann oibre neamhrianaithe seo a leanas a fhorscrÃobh trà " +"sheiceáil:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by merge:\n" +"%%sPlease move or remove them before you merge." +msgstr "" +"Déanfaà na comhaid crann oibre neamhrianaithe seo a leanas a fhorscrÃobh trà " +"chumasc:\n" +"%%sDo thoil bog nó bain iad sula ndéanann tú cumasc." + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by merge:\n" +"%%s" +msgstr "" +"Déanfaà na comhaid crann oibre neamhrianaithe seo a leanas a fhorscrÃobh trà " +"chumasc:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by %s:\n" +"%%sPlease move or remove them before you %s." +msgstr "" +"Bheadh %s na comhaid crann oibre neamhrianaithe seo a leanas a fhorscrÃobh:\n" +"%%sDo thoil bog nó bain iad roimh %s." + +#: unpack-trees.c +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by %s:\n" +"%%s" +msgstr "" +"Bheadh %s na comhaid crann oibre neamhrianaithe seo a leanas a fhorscrÃobh:\n" +"%%s" + +#: unpack-trees.c +#, c-format +msgid "Entry '%s' overlaps with '%s'. Cannot bind." +msgstr "Tá iontráil '%s' ag forluà le '%s'. Nà féidir ceangal a dhéanamh." + +#: unpack-trees.c +#, c-format +msgid "" +"Cannot update submodule:\n" +"%s" +msgstr "" +"Nà féidir fo-mhodúl a nuashonrú:\n" +"%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following paths are not up to date and were left despite sparse " +"patterns:\n" +"%s" +msgstr "" +"NÃl na cosáin seo a leanas cothrom le dáta agus fágadh iad in ainneoin " +"patrúin neamhchoitianta:\n" +"%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following paths are unmerged and were left despite sparse patterns:\n" +"%s" +msgstr "" +"Tá na cosáin seo a leanas gan chumasc agus fágadh iad in ainneoin patrúin " +"neamhchoitianta:\n" +"%s" + +#: unpack-trees.c +#, c-format +msgid "" +"The following paths were already present and thus not updated despite sparse " +"patterns:\n" +"%s" +msgstr "" +"Bhà na cosáin seo a leanas i láthair cheana féin agus dá bhrà sin nÃor " +"nuashonraÃodh in ainneoin\n" +"%s" + +#: unpack-trees.c +#, c-format +msgid "Aborting\n" +msgstr "Gearradh\n" + +#: unpack-trees.c +#, c-format +msgid "" +"After fixing the above paths, you may want to run `git sparse-checkout " +"reapply`.\n" +msgstr "" +"Tar éis duit na cosáin thuas a shocrú, b'fhéidir gur mhaith leat `git sparse-" +"checkout reapply` a reáchtáil.\n" + +#: unpack-trees.c +msgid "Updating files" +msgstr "Comhad a nuashonrú" + +#: unpack-trees.c +msgid "" +"the following paths have collided (e.g. case-sensitive paths\n" +"on a case-insensitive filesystem) and only one from the same\n" +"colliding group is in the working tree:\n" +msgstr "" +"bhuail na cosáin seo a leanas (e.g. cosáin cás-Ãogair\n" +"ar chóras comhaid cás-neamh-Ãogair) agus ach ceann amháin ón gcéanna\n" +"tá grúpa imbhuailte sa chrann oibre:\n" + +#: unpack-trees.c +msgid "Updating index flags" +msgstr "Nuashonrú bratacha innéacs" + +#: unpack-trees.c +#, c-format +msgid "worktree and untracked commit have duplicate entries: %s" +msgstr "" +"tá iontrálacha dúbailte ag crann oibre agus tiomantas neamhrianaithe: %s" + +#: upload-pack.c +msgid "expected flush after fetch arguments" +msgstr "súil le sruth tar éis argóintà a fháil" + +#: urlmatch.c +msgid "invalid URL scheme name or missing '://' suffix" +msgstr "ainm scéime URL neamhbhailà nó iarmhÃr ': //' in easnamh" + +#: urlmatch.c +#, c-format +msgid "invalid %XX escape sequence" +msgstr "seicheamh éalaithe %XX neamhbhailÃ" + +#: urlmatch.c +msgid "missing host and scheme is not 'file:'" +msgstr "nà 'comhad: 'à an óstach agus an scéim atá in easnamh:" + +#: urlmatch.c +msgid "a 'file:' URL may not have a port number" +msgstr "b'fhéidir nach mbeadh uimhir chalafoirt ag URL 'file: '" + +#: urlmatch.c +msgid "invalid characters in host name" +msgstr "carachtair neamhbhailà in ainm ósta" + +#: urlmatch.c +msgid "invalid port number" +msgstr "uimhir phort neamhbhail" + +#: urlmatch.c +msgid "invalid '..' path segment" +msgstr "deighleog cosáin '..' neamhbhailÃ" + +#: usage.c +#, c-format +msgid "error: unable to format message: %s\n" +msgstr "earráid: nà féidir teachtaireacht a fhormáidiú: %s\n" + +#: usage.c +msgid "usage: " +msgstr "úsáid: " + +#: usage.c +msgid "fatal: " +msgstr "marfach: " + +#: usage.c +msgid "error: " +msgstr "earráid: " + +#: usage.c +msgid "warning: " +msgstr "rabhadh: " + +#: version.c +#, c-format +msgid "uname() failed with error '%s' (%d)\n" +msgstr "theip ar uname () le earráid '%s' (%d)\n" + +#: walker.c +msgid "Fetching objects" +msgstr "Rudaà a fháil" + +#: worktree.c +#, c-format +msgid "'%s' at main working tree is not the repository directory" +msgstr "Nà hé '%s' ag an bprÃomhchrann oibre an eolaire stórais" + +#: worktree.c +#, c-format +msgid "'%s' file does not contain absolute path to the working tree location" +msgstr "NÃl cosán iomlán chuig suÃomh an chrainn oibre i gcomhad '%s'" + +#: worktree.c +#, c-format +msgid "'%s' is not a .git file, error code %d" +msgstr "Nà comhad .git é '%s', cód earráide %d" + +#: worktree.c +#, c-format +msgid "'%s' does not point back to '%s'" +msgstr "Nà dhÃrÃonn '%s' ar ais chuig '%s'" + +#: worktree.c +msgid "not a directory" +msgstr "nà eolaire" + +#: worktree.c +msgid ".git is not a file" +msgstr "Nà comhad é .git" + +#: worktree.c +msgid ".git file broken" +msgstr "comhad .git briste" + +#: worktree.c +msgid ".git file incorrect" +msgstr "comhad .git mÃcheart" + +#: worktree.c +msgid ".git file absolute/relative path mismatch" +msgstr "comhad .git neamhoiriúnú iomlán/coibhneasta coibhneasta" + +#: worktree.c +msgid "not a valid path" +msgstr "nà cosán bailÃ" + +#: worktree.c +msgid "unable to locate repository; .git is not a file" +msgstr "in ann stór a aimsiú; nà comhad é .git" + +#: worktree.c +msgid "unable to locate repository; .git file does not reference a repository" +msgstr "in ann stór a aimsiú; nà thagann comhad .git tagairt do stór" + +#: worktree.c +msgid "unable to locate repository; .git file broken" +msgstr "in ann stór a aimsiú; comhad .git briste" + +#: worktree.c +msgid "gitdir unreadable" +msgstr "gitdir unreadable" + +#: worktree.c +msgid "gitdir absolute/relative path mismatch" +msgstr "mÃmheaitseáil cosán iomlán/coibhneasta gitdir" + +#: worktree.c +msgid "gitdir incorrect" +msgstr "gitdir mÃcheart" + +#: worktree.c +msgid "not a valid directory" +msgstr "nà eolaire bailÃ" + +#: worktree.c +msgid "gitdir file does not exist" +msgstr "nÃl comhad gitdir ann" + +#: worktree.c +#, c-format +msgid "unable to read gitdir file (%s)" +msgstr "nach féidir comhad gitdir a léamh (%s)" + +#: worktree.c +#, c-format +msgid "short read (expected %<PRIuMAX> bytes, read %<PRIuMAX>)" +msgstr "léamh gearr (súil leis%<PRIuMAX>bytes, léithe%<PRIuMAX>)" + +#: worktree.c +msgid "invalid gitdir file" +msgstr "comhad gitdir neamhbhailÃ" + +#: worktree.c +msgid "gitdir file points to non-existent location" +msgstr "pointeálann comhad gitdir chuig suÃomh nach bhfuil ann" + +#: worktree.c +#, c-format +msgid "unable to set %s in '%s'" +msgstr "nach féidir %s a shocrú i '%s'" + +#: worktree.c +#, c-format +msgid "unable to unset %s in '%s'" +msgstr "nach féidir %s a dhÃshocrú i '%s'" + +#: worktree.c +msgid "failed to set extensions.worktreeConfig setting" +msgstr "theip ar shocrú extensions.worktreeConfig" + +#: worktree.c +msgid "unable to upgrade repository format to support relative worktrees" +msgstr "in ann formáid stórais a uasghrádú chun tacú le crainn oibre coibh" + +#: worktree.c +msgid "unable to set extensions.relativeWorktrees setting" +msgstr "nà féidir an socrú extensions.relativeWorktrees a shocrú" + +#: wrapper.c +#, c-format +msgid "could not setenv '%s'" +msgstr "nà fhéadfaà '%s' a shocrú" + +#: wrapper.c +#, c-format +msgid "unable to create '%s'" +msgstr "nà féidir '%s' a chruthú" + +#: wrapper.c +#, c-format +msgid "could not open '%s' for reading and writing" +msgstr "nà fhéadfaà '%s' a oscailt le haghaidh léamh agus scrÃbhneoireachta" + +#: wrapper.c +#, c-format +msgid "unable to access '%s'" +msgstr "nà féidir rochtain a fháil ar '%s'" + +#: wrapper.c +msgid "unable to get current working directory" +msgstr "in ann eolaire oibre reatha a fháil" + +#: wrapper.c +msgid "unable to get random bytes" +msgstr "in ann bétaà randamacha a fháil" + +#: wrapper.c +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "ag iarraidh mmapáil %<PRIuMAX> thar theorainn %<PRIuMAX>" + +#: wrapper.c +#, c-format +msgid "mmap failed%s" +msgstr "theip ar mmap %s" + +#: wt-status.c +msgid "Unmerged paths:" +msgstr "Cosáin neamh-chumasaithe:" + +#: wt-status.c +msgid " (use \"git restore --staged <file>...\" to unstage)" +msgstr "" +" (bain úsáid as “git restore --staged <comhad>...†chun an stáitse a dhÃchur)" + +#: wt-status.c +#, c-format +msgid " (use \"git restore --source=%s --staged <file>...\" to unstage)" +msgstr "" +" (bain úsáid as \"git restore --source=%s --staged <comhad>...\" chun an " +"stáitse a dhÃ-ardú)" + +#: wt-status.c +msgid " (use \"git rm --cached <file>...\" to unstage)" +msgstr "" +" (bain úsáid as “git rm --cached <comhad>...†chun an stáitse a dhÃchur)" + +#: wt-status.c +msgid " (use \"git add <file>...\" to mark resolution)" +msgstr " (bain úsáid as “git add <comhad>...†chun réiteach a mharcáil)" + +#: wt-status.c +msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)" +msgstr "" +" (bain úsáid \"git add/rm <comhad>...\" de réir mar is cuà chun réiteach a " +"mharcáil)" + +#: wt-status.c +msgid " (use \"git rm <file>...\" to mark resolution)" +msgstr " (bain úsáid as “git rm <comhad>...†chun réiteach a mharcáil)" + +#: wt-status.c +msgid "Changes to be committed:" +msgstr "Athruithe atá le déanamh:" + +#: wt-status.c +msgid "Changes not staged for commit:" +msgstr "Athruithe nach ndearnadh a chur ar stáitse le haghaidh tiomantais:" + +#: wt-status.c +msgid " (use \"git add <file>...\" to update what will be committed)" +msgstr "" +" (bain úsáid as “git add <comhad>...†chun an méid a bheidh tiomanta a " +"nuashonrú)" + +#: wt-status.c +msgid " (use \"git add/rm <file>...\" to update what will be committed)" +msgstr "" +" (bain úsáid as “git add/rm <comhad>...†chun an méid a bheidh tiomanta a " +"nuashonrú)" + +#: wt-status.c +msgid "" +" (use \"git restore <file>...\" to discard changes in working directory)" +msgstr "" +" (bain úsáid as “git restore <comhad>...†chun athruithe ar eolaire oibre a " +"dhiúscairt)" + +#: wt-status.c +msgid " (commit or discard the untracked or modified content in submodules)" +msgstr "" +" (an t-ábhar neamhrianaithe nó modhnaithe i bhfo-mhodúil a thiomsú nó a " +"dhiúscairt)" + +#: wt-status.c +#, c-format +msgid " (use \"git %s <file>...\" to include in what will be committed)" +msgstr "" +" (bain úsáid as “git %s <comhad>...†chun an méid a bheidh tiomanta san " +"áireamh)" + +#: wt-status.c +msgid "both deleted:" +msgstr "scriosta an dá cheann:" + +#: wt-status.c +msgid "added by us:" +msgstr "curtha leis againn:" + +#: wt-status.c +msgid "deleted by them:" +msgstr "scriosta ag siad:" + +#: wt-status.c +msgid "added by them:" +msgstr "a chuir siad leis:" + +#: wt-status.c +msgid "deleted by us:" +msgstr "scriosta againn:" + +#: wt-status.c +msgid "both added:" +msgstr "chuir an bheirt leis:" + +#: wt-status.c +msgid "both modified:" +msgstr "an dá cheann modhnaithe:" + +#: wt-status.c +msgid "new file:" +msgstr "comhad nua:" + +#: wt-status.c +msgid "copied:" +msgstr "cóipeáilte:" + +#: wt-status.c +msgid "deleted:" +msgstr "scriosta:" + +#: wt-status.c +msgid "modified:" +msgstr "modhnaithe:" + +#: wt-status.c +msgid "renamed:" +msgstr "athainmnithe:" + +#: wt-status.c +msgid "typechange:" +msgstr "cineál cineál:" + +#: wt-status.c +msgid "unknown:" +msgstr "anaithnid:" + +#: wt-status.c +msgid "unmerged:" +msgstr "gan chumasc:" + +#: wt-status.c +msgid "new commits, " +msgstr "tiomantais nua, " + +#: wt-status.c +msgid "modified content, " +msgstr "ábhar modhnaithe, " + +#: wt-status.c +msgid "untracked content, " +msgstr "ábhar neamhrianaithe, " + +#: wt-status.c +#, c-format +msgid "Your stash currently has %d entry" +msgid_plural "Your stash currently has %d entries" +msgstr[0] "Tá %d iontráil i do stash faoi láthair" +msgstr[1] "Tá %d iontrálacha ar do stash faoi láthair" +msgstr[2] "Tá %d iontrálacha ar do stash faoi láthair" + +#: wt-status.c +msgid "Submodules changed but not updated:" +msgstr "Fo-mhodúil athraithe ach gan nuashonrú:" + +#: wt-status.c +msgid "Submodule changes to be committed:" +msgstr "Athruithe fo-mhodúil atá le tiomantas:" + +#: wt-status.c +msgid "" +"Do not modify or remove the line above.\n" +"Everything below it will be ignored." +msgstr "" +"Ná déan an lÃne thuas a mhodhnú ná a bhaint.\n" +"Déanfar neamhaird ar gach rud thÃos é." + +#: wt-status.c +#, c-format +msgid "" +"\n" +"It took %.2f seconds to compute the branch ahead/behind values.\n" +"You can use '--no-ahead-behind' to avoid this.\n" +msgstr "" +"\n" +"Thóg sé %.2f soicind chun luachanna na brainse chun tosaigh/taobh thiar a " +"rÃomh.\n" +"Is féidir leat '--no-ahead-behind' a úsáid chun seo a sheachaint.\n" + +#: wt-status.c +msgid "You have unmerged paths." +msgstr "Tá cosáin neamh-chumasaithe agat." + +#: wt-status.c +msgid " (fix conflicts and run \"git commit\")" +msgstr " (coinbhleachtaà a shocrú agus reáchtáil “git commitâ€)" + +#: wt-status.c +msgid " (use \"git merge --abort\" to abort the merge)" +msgstr "" +" (bain úsáid as “git merge --abort†chun an cumaisc a chur ar deireadh)" + +#: wt-status.c +msgid "All conflicts fixed but you are still merging." +msgstr "SocraÃodh gach coinbhleacht ach tá tú fós ag cumasc." + +#: wt-status.c +msgid " (use \"git commit\" to conclude merge)" +msgstr " (bain úsáid as “git commit†chun cumasc a thabhairt i gcrÃch)" + +#: wt-status.c +msgid "You are in the middle of an am session." +msgstr "Tá tú i lár seisiún am." + +#: wt-status.c +msgid "The current patch is empty." +msgstr "Tá an paiste reatha folamh." + +#: wt-status.c +msgid " (fix conflicts and then run \"git am --continue\")" +msgstr " (déan coinbhleachtaà a shocrú agus ansin rith “git am --continueâ€)" + +#: wt-status.c +msgid " (use \"git am --skip\" to skip this patch)" +msgstr " (bain úsáid as “git am --skip†chun an paiste seo a scipeáil)" + +#: wt-status.c +msgid "" +" (use \"git am --allow-empty\" to record this patch as an empty commit)" +msgstr "" +" (bain úsáid as “git am --allow-empty†chun an paiste seo a thaifeadadh mar " +"thiomantas folamh)" + +#: wt-status.c +msgid " (use \"git am --abort\" to restore the original branch)" +msgstr "" +" (bain úsáid as “git am --abort†chun an bhrainse bunaidh a chur ar ais)" + +#: wt-status.c +msgid "git-rebase-todo is missing." +msgstr "tá git-rebase-todo ar iarraidh." + +#: wt-status.c +msgid "No commands done." +msgstr "NÃl aon orduithe déanta." + +#: wt-status.c +#, c-format +msgid "Last command done (%<PRIuMAX> command done):" +msgid_plural "Last commands done (%<PRIuMAX> commands done):" +msgstr[0] "An chéad ordú eile le déanamh (%<PRIuMAX>ordú atá fágtha):" +msgstr[1] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):" +msgstr[2] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):" + +#: wt-status.c +#, c-format +msgid " (see more in file %s)" +msgstr " (féach tuilleadh i gcomhad %s)" + +#: wt-status.c +msgid "No commands remaining." +msgstr "NÃl aon orduithe fágtha." + +#: wt-status.c +#, c-format +msgid "Next command to do (%<PRIuMAX> remaining command):" +msgid_plural "Next commands to do (%<PRIuMAX> remaining commands):" +msgstr[0] "An chéad ordú eile le déanamh (%<PRIuMAX> an t-ordú atá fágtha):" +msgstr[1] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):" +msgstr[2] "Na chéad orduithe eile le déanamh (%<PRIuMAX> orduithe atá fágtha):" + +#: wt-status.c +msgid " (use \"git rebase --edit-todo\" to view and edit)" +msgstr "" +" (bain úsáid as “git rebase --edit-todo†chun féachaint agus eagar a chur in " +"eagar)" + +#: wt-status.c +#, c-format +msgid "You are currently rebasing branch '%s' on '%s'." +msgstr "Tá tú ag athbhunú brainse '%s' faoi láthair ar '%s'." + +#: wt-status.c +msgid "You are currently rebasing." +msgstr "Tá tú ag athbhunú faoi láthair." + +#: wt-status.c +msgid " (fix conflicts and then run \"git rebase --continue\")" +msgstr "" +" (déan coinbhleachtaà a shocrú agus ansin rith “git rebase --continueâ€)" + +#: wt-status.c +msgid " (use \"git rebase --skip\" to skip this patch)" +msgstr " (bain úsáid as “git rebase --skip†chun an paiste seo a scipeáil)" + +#: wt-status.c +msgid " (use \"git rebase --abort\" to check out the original branch)" +msgstr "" +" (bain úsáid as “git rebase --abort†chun an bhrainse bunaidh a sheiceáil)" + +#: wt-status.c +msgid " (all conflicts fixed: run \"git rebase --continue\")" +msgstr " (gach coinbhleacht socraithe: reáchtáil “git rebase --continueâ€)" + +#: wt-status.c +#, c-format +msgid "" +"You are currently splitting a commit while rebasing branch '%s' on '%s'." +msgstr "" +"Tá tiomantas á roinnt agat faoi láthair agus tú ag athbhunú brainse '%s' ar " +"'%s'." + +#: wt-status.c +msgid "You are currently splitting a commit during a rebase." +msgstr "Tá tú ag roinnt tiomantas faoi láthair le linn athbhunaithe." + +#: wt-status.c +msgid " (Once your working directory is clean, run \"git rebase --continue\")" +msgstr "" +" (Nuair a bheidh d'eolaire oibre glan, reáchtáil “git rebase --continueâ€)" + +#: wt-status.c +#, c-format +msgid "You are currently editing a commit while rebasing branch '%s' on '%s'." +msgstr "" +"Tá tú ag eagarthóireacht faoi láthair agus tú ag athbhunú brainse '%s' ar " +"'%s'." + +#: wt-status.c +msgid "You are currently editing a commit during a rebase." +msgstr "Tá tú ag eagarthóireacht tiomanta faoi láthair le linn athbhunaithe." + +#: wt-status.c +msgid " (use \"git commit --amend\" to amend the current commit)" +msgstr " (bain úsáid as “git commit --amend†chun an tiomantas reatha a leasú)" + +#: wt-status.c +msgid "" +" (use \"git rebase --continue\" once you are satisfied with your changes)" +msgstr "" +" (bain úsáid as “git rebase --continue†nuair a bheidh tú sásta le " +"d'athruithe)" + +#: wt-status.c +msgid "Cherry-pick currently in progress." +msgstr "Cherry-pick atá ar siúl faoi láthair." + +#: wt-status.c +#, c-format +msgid "You are currently cherry-picking commit %s." +msgstr "Tá tiomantas %s ag piocadh silÃnà faoi láthair." + +#: wt-status.c +msgid " (fix conflicts and run \"git cherry-pick --continue\")" +msgstr " (coinbhleachtaà a shocrú agus reáchtáil “git cherry-pick --continueâ€)" + +#: wt-status.c +msgid " (run \"git cherry-pick --continue\" to continue)" +msgstr " (reáchtáil “git cherry-pick --continue †chun leanúint ar aghaidh)" + +#: wt-status.c +msgid " (all conflicts fixed: run \"git cherry-pick --continue\")" +msgstr " (gach coinbhleacht socraithe: reáchtáil “git cherry-pick --continueâ€)" + +#: wt-status.c +msgid " (use \"git cherry-pick --skip\" to skip this patch)" +msgstr "" +" (bain úsáid as “git cherry-pick --skip†chun an paiste seo a scipeáil)" + +#: wt-status.c +msgid " (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)" +msgstr "" +" (bain úsáid as “git cherry-pick --abort†chun an oibrÃocht pioc silÃnà a " +"chealú)" + +#: wt-status.c +msgid "Revert currently in progress." +msgstr "Ar ais atá ar siúl faoi láthair." + +#: wt-status.c +#, c-format +msgid "You are currently reverting commit %s." +msgstr "Tá tiomantas %s á chur ar ais faoi láthair." + +#: wt-status.c +msgid " (fix conflicts and run \"git revert --continue\")" +msgstr " (déan coinbhleachtaà a shocrú agus rith “git revert --continueâ€)" + +#: wt-status.c +msgid " (run \"git revert --continue\" to continue)" +msgstr " (reáchtáil “git revert --continue†chun leanúint ar aghaidh)" + +#: wt-status.c +msgid " (all conflicts fixed: run \"git revert --continue\")" +msgstr " (gach coinbhleacht socraithe: reáchtáil “git revert --continueâ€)" + +#: wt-status.c +msgid " (use \"git revert --skip\" to skip this patch)" +msgstr " (bain úsáid as “git revert --skip†chun an paiste seo a scipeáil)" + +#: wt-status.c +msgid " (use \"git revert --abort\" to cancel the revert operation)" +msgstr "" +" (bain úsáid as “git revert --abort†chun an oibrÃocht aisghabhála a chealú)" + +#: wt-status.c +#, c-format +msgid "You are currently bisecting, started from branch '%s'." +msgstr "Tá tú ag déileáil faoi láthair, tosaigh tú ó bhrainse '%s'." + +#: wt-status.c +msgid "You are currently bisecting." +msgstr "Tá tú ag déileáil faoi láthair." + +#: wt-status.c +msgid " (use \"git bisect reset\" to get back to the original branch)" +msgstr "" +" (bain úsáid as “git bisect reset†chun filleadh ar an mbrainse bunaidh)" + +#: wt-status.c +msgid "You are in a sparse checkout." +msgstr "Tá tú i seiceáil neamhchoitianta." + +#: wt-status.c +#, c-format +msgid "You are in a sparse checkout with %d%% of tracked files present." +msgstr "" +"Tá tú i seiceáil neamhchoitianta le %d%% de na comhaid rianaithe i láthair." + +#: wt-status.c +msgid "On branch " +msgstr "Ar bhrainse " + +#: wt-status.c +msgid "interactive rebase in progress; onto " +msgstr "athbhunú idirghnÃomhach atá ar siúl; ar " + +#: wt-status.c +msgid "rebase in progress; onto " +msgstr "athbhunú atá ar siúl; ar " + +#: wt-status.c +msgid "HEAD detached at " +msgstr "HEAD scoite ag " + +#: wt-status.c +msgid "HEAD detached from " +msgstr "CEANN scartha ó " + +#: wt-status.c +msgid "Not currently on any branch." +msgstr "NÃl sé ar aon bhrainse faoi láthair." + +#: wt-status.c +msgid "Initial commit" +msgstr "Tiomantas tosaigh" + +#: wt-status.c +msgid "No commits yet" +msgstr "NÃl aon gealltanais fós" + +#: wt-status.c +msgid "Untracked files" +msgstr "Comhaid neamhrianaithe" + +#: wt-status.c +msgid "Ignored files" +msgstr "Comhaid neamhaird" + +#: wt-status.c +#, c-format +msgid "" +"It took %.2f seconds to enumerate untracked files,\n" +"but the results were cached, and subsequent runs may be faster." +msgstr "" +"Thóg sé %.2f soicind comhaid gan rianú a áireamh,\n" +"ach cuireadh na torthaà a chosc, agus d'fhéadfadh rith ina dhiaidh sin a " +"bheith nÃos gasta." + +#: wt-status.c +#, c-format +msgid "It took %.2f seconds to enumerate untracked files." +msgstr "Thóg sé %.2f soicind comhaid gan rianú a áireamh." + +#: wt-status.c +msgid "See 'git help status' for information on how to improve this." +msgstr "" +"Féach 'git help status' le haghaidh faisnéise maidir le conas é seo a " +"fheabhsú." + +#: wt-status.c +#, c-format +msgid "Untracked files not listed%s" +msgstr "Comhaid neamhrianaithe nár liostaÃodh %s" + +#: wt-status.c +msgid " (use -u option to show untracked files)" +msgstr " (bain úsáid as an rogha -u chun comhaid neamhrianaithe a thaispeáint)" + +#: wt-status.c +msgid "No changes" +msgstr "Gan aon athruithe" + +#: wt-status.c +#, c-format +msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" +msgstr "" +"nÃl aon athruithe curtha le tiomantas (bain úsáid as “git add†agus/nó “git " +"commit -aâ€)\n" + +#: wt-status.c +#, c-format +msgid "no changes added to commit\n" +msgstr "nÃl aon athruithe curtha le tiomantas\n" + +#: wt-status.c +#, c-format +msgid "" +"nothing added to commit but untracked files present (use \"git add\" to " +"track)\n" +msgstr "" +"nà chuirtear aon rud le tiomantas ach comhaid neamhrianaithe i láthair (bain " +"úsáid as “git add†chun rianú)\n" + +#: wt-status.c +#, c-format +msgid "nothing added to commit but untracked files present\n" +msgstr "nà chuir aon rud le tiomantas ach comhaid neamhrianaithe i láthair\n" + +#: wt-status.c +#, c-format +msgid "nothing to commit (create/copy files and use \"git add\" to track)\n" +msgstr "" +"aon rud le tiomantas (comhaid a chruthú/cóipeáil agus bain úsáid as “git " +"add†chun rianú)\n" + +#: wt-status.c +#, c-format +msgid "nothing to commit\n" +msgstr "aon rud le tiomantas\n" + +#: wt-status.c +#, c-format +msgid "nothing to commit (use -u to show untracked files)\n" +msgstr "" +"aon rud le tiomantas (bain úsáid as -u chun comhaid neamhrianaithe a " +"thaispeáint)\n" + +#: wt-status.c +#, c-format +msgid "nothing to commit, working tree clean\n" +msgstr "aon rud le tiomantas, crann oibre glan\n" + +#: wt-status.c +msgid "No commits yet on " +msgstr "NÃl aon gealltanas ar aghaidh go fóill " + +#: wt-status.c +msgid "HEAD (no branch)" +msgstr "CEAD (gan aon bhrainse)" + +#: wt-status.c +msgid "different" +msgstr "difriúil" + +#: wt-status.c +msgid "behind " +msgstr "taobh thiar " + +#: wt-status.c +msgid "ahead " +msgstr "chun tosaigh " + +#. TRANSLATORS: the action is e.g. "pull with rebase" +#: wt-status.c +#, c-format +msgid "cannot %s: You have unstaged changes." +msgstr "nà féidir %s: Tá athruithe gan stáitse agat." + +#: wt-status.c +msgid "additionally, your index contains uncommitted changes." +msgstr "ina theannta sin, tá athruithe neamhthiomanta i d'innéacs." + +#: wt-status.c +#, c-format +msgid "cannot %s: Your index contains uncommitted changes." +msgstr "nà féidir %s: Tá athruithe neamhthiomanta ag d'innéacs." + +#: xdiff-interface.c +#, c-format +msgid "unknown style '%s' given for '%s'" +msgstr "stÃl anaithnid '%s' a thugtar do '%s'" + +#: git-merge-octopus.sh git-merge-resolve.sh +msgid "" +"Error: Your local changes to the following files would be overwritten by " +"merge" +msgstr "" +"Earráid: Déanfaà d'athruithe áitiúla ar na comhaid seo a leanas a " +"fhorscrÃobh trà chumasc" + +#: git-merge-octopus.sh +msgid "Automated merge did not work." +msgstr "NÃor oibrigh cumaisc uathoibrithe." + +#: git-merge-octopus.sh +msgid "Should not be doing an octopus." +msgstr "NÃor chóir go mbeadh sé ag déanamh ochtair." + +#: git-merge-octopus.sh +#, sh-format +msgid "Unable to find common commit with $pretty_name" +msgstr "Nà féidir tiomantas coiteann a fháil le $pretty_name" + +#: git-merge-octopus.sh +#, sh-format +msgid "Already up to date with $pretty_name" +msgstr "Cothrom le dáta cheana féin le $pretty_name" + +#: git-merge-octopus.sh +#, sh-format +msgid "Fast-forwarding to: $pretty_name" +msgstr "Seoladh go tapa chuig: $pretty_name" + +#: git-merge-octopus.sh +#, sh-format +msgid "Trying simple merge with $pretty_name" +msgstr "Ag iarraidh cumasc simplà le $pretty_name" + +#: git-merge-octopus.sh +msgid "Simple merge did not work, trying automatic merge." +msgstr "" +"NÃor oibrigh an cumasc simplÃ, táim ag iarraidh cumasc uathoibrÃoch a " +"dhéanamh." + +#: git-sh-setup.sh +#, sh-format +msgid "usage: $dashless $USAGE" +msgstr "úsáid: $dashless $USAGE" + +#: git-sh-setup.sh +#, sh-format +msgid "Cannot chdir to $cdup, the toplevel of the working tree" +msgstr "Nà féidir a chdir go $cdup, barr an chrainn oibre" + +#: git-sh-setup.sh +#, sh-format +msgid "fatal: $program_name cannot be used without a working tree." +msgstr "marfach: nà féidir $program_name a úsáid gan crann oibre." + +#: git-sh-setup.sh +msgid "Cannot rewrite branches: You have unstaged changes." +msgstr "Nà féidir brainsà a athscrÃobh: Tá athruithe gan stáitse agat." + +#: git-sh-setup.sh +#, sh-format +msgid "Cannot $action: You have unstaged changes." +msgstr "Nà féidir $action: Tá athruithe gan stáitse agat." + +#: git-sh-setup.sh +#, sh-format +msgid "Cannot $action: Your index contains uncommitted changes." +msgstr "Nà féidir $action: Tá athruithe neamhthiomanta i d'innéacs." + +#: git-sh-setup.sh +msgid "Additionally, your index contains uncommitted changes." +msgstr "Ina theannta sin, tá athruithe neamhthiomanta i d'innéacs." + +#: git-sh-setup.sh +msgid "You need to run this command from the toplevel of the working tree." +msgstr "Nà mór duit an t-ordú seo a reáchtáil ó bharr an chrainn oibre." + +#: git-sh-setup.sh +msgid "Unable to determine absolute path of git directory" +msgstr "Nà féidir cosán iomlán eolaire git a chinneadh" + +#: git-send-email.perl +msgid "local zone differs from GMT by a non-minute interval\n" +msgstr "tá eatramh neamh-nóiméid difriúil ón gcrios áitiúil\n" + +#: git-send-email.perl +msgid "local time offset greater than or equal to 24 hours\n" +msgstr "" +"fritháireamh ama áitiúil atá nÃos mó ná nó cothrom le 24 uair an chloig\n" + +#: git-send-email.perl +#, perl-format +msgid "fatal: command '%s' died with exit code %d" +msgstr "marfach: fuair an t-ordú '%s' bás le cód imeachta %d" + +#: git-send-email.perl +msgid "the editor exited uncleanly, aborting everything" +msgstr "d’imigh an t-eagarthóir go neamhghlan, ag cur deireadh le gach rud" + +#: git-send-email.perl +#, perl-format +msgid "" +"'%s' contains an intermediate version of the email you were composing.\n" +msgstr "Tá leagan idirmheánach den rÃomhphost a bhà á scrÃobh agat i '%s'.\n" + +#: git-send-email.perl +#, perl-format +msgid "'%s.final' contains the composed email.\n" +msgstr "CuimsÃonn '%s.final' an rÃomhphost comhdhéanta.\n" + +#: git-send-email.perl +msgid "--dump-aliases incompatible with other options\n" +msgstr "--dump-aliases neamhoiriúnach le roghanna eile\n" + +#: git-send-email.perl +msgid "--dump-aliases and --translate-aliases are mutually exclusive\n" +msgstr "Tá --dump-aliases agus --translate-aliases frithpháirteach\n" + +#: git-send-email.perl +msgid "" +"fatal: found configuration options for 'sendmail'\n" +"git-send-email is configured with the sendemail.* options - note the 'e'.\n" +"Set sendemail.forbidSendmailVariables to false to disable this check.\n" +msgstr "" +"marfach: aimsÃodh roghanna cumraÃochta do 'sendmail'\n" +"Tá git-send-email cumraithe leis na roghanna sendemail.* - tabhair faoi " +"deara an 'e'.\n" +"Socraigh sendemail.forbidSendmailVariables go bréagach chun an seiceáil seo " +"a dhÃchumasú.\n" + +#: git-send-email.perl +msgid "Cannot run git format-patch from outside a repository\n" +msgstr "Nà féidir git format-patch a rith ó lasmuigh de stórlann\n" + +#: git-send-email.perl +msgid "" +"`batch-size` and `relogin` must be specified together (via command-line or " +"configuration option)\n" +msgstr "" +"Caithfear `méid baisce' agus `athlogán' a shonrú le chéile (trà lÃne " +"ordaithe nó rogha cumraÃochta)\n" + +#: git-send-email.perl +#, perl-format +msgid "Unknown --suppress-cc field: '%s'\n" +msgstr "Réimse anaithnid --suppress-cc: '%s'\n" + +#: git-send-email.perl +#, perl-format +msgid "Unknown --confirm setting: '%s'\n" +msgstr "Socrú --confirm anaithnid: '%s'\n" + +#: git-send-email.perl +#, perl-format +msgid "warning: sendmail alias with quotes is not supported: %s\n" +msgstr "rabhadh: nà thacaÃtear le alias sendmail le luachana: %s\n" + +#: git-send-email.perl +#, perl-format +msgid "warning: `:include:` not supported: %s\n" +msgstr "rabhadh: `:include: `nÃl tacaÃocht: %s\n" + +#: git-send-email.perl +#, perl-format +msgid "warning: `/file` or `|pipe` redirection not supported: %s\n" +msgstr "rabhadh: Nà thacaÃtear le hathreorú `/comhad` nó `|pÃopa`: %s\n" + +#: git-send-email.perl +#, perl-format +msgid "warning: sendmail line is not recognized: %s\n" +msgstr "rabhadh: nà aithnÃtear lÃne sendmail: %s\n" + +#: git-send-email.perl +#, perl-format +msgid "" +"File '%s' exists but it could also be the range of commits\n" +"to produce patches for. Please disambiguate by...\n" +"\n" +" * Saying \"./%s\" if you mean a file; or\n" +" * Giving --format-patch option if you mean a range.\n" +msgstr "" +"Tá comhad '%s' ann ach d'fhéadfadh sé a bheith ina raon na dtiomanta " +"freisin\n" +"chun paistà a tháirgeadh le haghaidh. Déan dÃbhrÃochnú le do thoil le do " +"thoil\n" +"\n" +" * Ag ráâ€. /%s†má tá comhad i gceist agat; nó\n" +" * Rogha --format-patch a thabhairt má tá raon i gceist agat.\n" + +#: git-send-email.perl +#, perl-format +msgid "Failed to opendir %s: %s" +msgstr "Theip ar %s a oscailt: %s" + +#: git-send-email.perl +msgid "" +"\n" +"No patch files specified!\n" +"\n" +msgstr "" +"\n" +"NÃl aon chomhaid paiste sonraithe!\n" +"\n" + +#: git-send-email.perl +#, perl-format +msgid "No subject line in %s?" +msgstr "NÃl aon lÃne ábhair i %s?" + +#: git-send-email.perl +#, perl-format +msgid "Failed to open for writing %s: %s" +msgstr "Theip ar oscailt le haghaidh scrÃbhneoireachta %s: %s" + +#: git-send-email.perl +msgid "" +"Lines beginning in \"GIT:\" will be removed.\n" +"Consider including an overall diffstat or table of contents\n" +"for the patch you are writing.\n" +"\n" +"Clear the body content if you don't wish to send a summary.\n" +msgstr "" +"Bainfear lÃnte a thosaÃonn i “GIT:â€.\n" +"Smaoinigh ar diffstat foriomlán nó tábla ábhair a áireamh\n" +"don phaiste atá á scrÃobh agat.\n" +"\n" +"Glan ábhar an choirp mura dteastaÃonn uait achoimre a sheoladh.\n" + +#: git-send-email.perl +#, perl-format +msgid "Failed to open %s.final: %s" +msgstr "Theip ar %s.final a oscailt: %s" + +#: git-send-email.perl +#, perl-format +msgid "Failed to open %s: %s" +msgstr "Theip ar %s a oscailt: %s" + +#: git-send-email.perl +msgid "Summary email is empty, skipping it\n" +msgstr "Tá rÃomhphost achoimre folamh, ag scipeáil é\n" + +#. TRANSLATORS: please keep [y/N] as is. +#: git-send-email.perl +#, perl-format +msgid "Are you sure you want to use <%s> [y/N]? " +msgstr "An bhfuil tú cinnte gur mhaith leat <%s> [Y/n] a úsáid? " + +#: git-send-email.perl +msgid "" +"The following files are 8bit, but do not declare a Content-Transfer-" +"Encoding.\n" +msgstr "" +"Is iad na comhaid seo a leanas 8bit, ach ná dearbhaÃonn siad Ionchódú " +"Aistrithe Ãbhar.\n" + +#: git-send-email.perl +msgid "Which 8bit encoding should I declare [UTF-8]? " +msgstr "Cén ionchódú 8 giotán ba chóir dom a dhearbhú [UTF-8]? " + +#: git-send-email.perl +#, perl-format +msgid "" +"Refusing to send because the patch\n" +"\t%s\n" +"has the template subject '*** SUBJECT HERE ***'. Pass --force if you really " +"want to send.\n" +msgstr "" +"Diúltú a sheoladh mar gheall ar an paiste\n" +"\t%s\n" +"tá an teimpléad faoi réir an ábhair '*** ÃBHAR ANSEO ***'. Pasáil --force " +"más mian leat a sheoladh i ndáirÃre.\n" + +#: git-send-email.perl +msgid "To whom should the emails be sent (if anyone)?" +msgstr "Cé chuige ba chóir na rÃomhphoist a sheoladh (más duine ar bith)?" + +#: git-send-email.perl +#, perl-format +msgid "fatal: alias '%s' expands to itself\n" +msgstr "marfach: leathnaÃonn alias '%s' chuige féin\n" + +#: git-send-email.perl +msgid "Message-ID to be used as In-Reply-To for the first email (if any)? " +msgstr "" +"Aitheantas an Teachtaireachta le húsáid mar In-Reply-To don chéad rÃomhphost " +"(más ann dó)? " + +#: git-send-email.perl +#, perl-format +msgid "error: unable to extract a valid address from: %s\n" +msgstr "earráid: nà féidir seoladh bailà a bhaint as: %s\n" + +#. TRANSLATORS: Make sure to include [q] [d] [e] in your +#. translation. The program will only accept English input +#. at this point. +#: git-send-email.perl +msgid "What to do with this address? ([q]uit|[d]rop|[e]dit): " +msgstr "Cad atá le déanamh leis an seoladh seo? ([q]uit|[d]rop|[e]dit): " + +#: git-send-email.perl +#, perl-format +msgid "CA path \"%s\" does not exist" +msgstr "NÃl cosán CA “%s†ann" + +#: git-send-email.perl +msgid "" +" The Cc list above has been expanded by additional\n" +" addresses found in the patch commit message. By default\n" +" send-email prompts before sending whenever this occurs.\n" +" This behavior is controlled by the sendemail.confirm\n" +" configuration setting.\n" +"\n" +" For additional information, run 'git send-email --help'.\n" +" To retain the current behavior, but squelch this message,\n" +" run 'git config --global sendemail.confirm auto'.\n" +"\n" +msgstr "" +" LeathnaÃodh an liosta Cc thuas trà bhreise\n" +" seoltaà a fhaightear sa teachtaireacht tiomanta paiste. De réir " +"réamhshocraithe\n" +" spreagann rÃomhphost a sheoladh sula seoltar aon uair a tharlaÃonn sé " +"seo.\n" +" Tá an t-iompar seo á rialú ag an sendemail.confirm\n" +" socrú cumraÃochta.\n" +"\n" +" Le haghaidh faisnéise breise, reáchtáil 'git send-email --help'.\n" +" Chun an t-iompar reatha a choinneáil, ach an teachtaireacht seo a " +"scriosadh,\n" +" reáchtáil 'git config --global sendemail.confirm auto'.\n" + +#. TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your +#. translation. The program will only accept English input +#. at this point. +#: git-send-email.perl +msgid "Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): " +msgstr "" +"An bhfuil tú ag iarraidh an rÃomhphost seo a sheoladh? ([y]es|[n]o|[e]dit|" +"[q]uit|[a]ll): " + +#: git-send-email.perl +msgid "Send this email reply required" +msgstr "Seol an freagra rÃomhphoist riachtanach" + +#: git-send-email.perl +msgid "The required SMTP server is not properly defined." +msgstr "NÃl an freastalaà SMTP riachtanach sainmhÃnithe i gceart." + +#: git-send-email.perl +#, perl-format +msgid "Server does not support STARTTLS! %s" +msgstr "Nà thacaÃonn freastalaà le STARTTLS! %s" + +#: git-send-email.perl +#, perl-format +msgid "STARTTLS failed! %s" +msgstr "Theip ar STARTTLS! %s" + +#: git-send-email.perl +msgid "Unable to initialize SMTP properly. Check config and use --smtp-debug." +msgstr "" +"Nà féidir SMTP a thionscnamh i gceart. Seiceáil configà agus bain úsáid as --" +"smtp-debug." + +#: git-send-email.perl +#, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Athshannaigh Outlook ID teachtaireachta chuig: %s\n" + +#: git-send-email.perl +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "" +"Rabhadh: Nà fhéadfaà teachtaireachtaà ID a aisghabháil ó fhreagairt " +"freastalaÃ.\n" + +#: git-send-email.perl +#, perl-format +msgid "Failed to send %s\n" +msgstr "Theip ar %s a sheoladh\n" + +#: git-send-email.perl +#, perl-format +msgid "Dry-Sent %s" +msgstr "Seoladh tirim %s" + +#: git-send-email.perl +#, perl-format +msgid "Sent %s" +msgstr "Seoladh %s" + +#: git-send-email.perl +msgid "Dry-OK. Log says:" +msgstr "Tirim-ceart go leor. Log deir:" + +#: git-send-email.perl +msgid "OK. Log says:" +msgstr "CEART GO LEOR. Log deir:" + +#: git-send-email.perl +msgid "Result: " +msgstr "Toradh: " + +#: git-send-email.perl +msgid "Result: OK" +msgstr "Toradh: Ceart go leor" + +#: git-send-email.perl +#, perl-format +msgid "can't open file %s" +msgstr "nà féidir comhad %s a oscailt" + +#: git-send-email.perl +#, perl-format +msgid "(mbox) Adding cc: %s from line '%s'\n" +msgstr "(mbox) Ag cur cc: %s ó lÃne '%s'\n" + +#: git-send-email.perl +#, perl-format +msgid "(mbox) Adding to: %s from line '%s'\n" +msgstr "(mbox) Ag cur le: %s ó lÃne '%s'\n" + +#: git-send-email.perl +#, perl-format +msgid "(non-mbox) Adding cc: %s from line '%s'\n" +msgstr "(non-mbox) Ag cur cc: %s ó lÃne '%s'\n" + +#: git-send-email.perl +#, perl-format +msgid "(body) Adding cc: %s from line '%s'\n" +msgstr "(corp) Ag cur cc: %s ó lÃne '%s'\n" + +#: git-send-email.perl +#, perl-format +msgid "(%s) Could not execute '%s'" +msgstr "(%s) Nà raibh '%s' in ann a fhorghnÃomhú" + +#: git-send-email.perl +#, perl-format +msgid "(%s) Malformed output from '%s'" +msgstr "(%s) Aschur mÃfheidhmithe ó '%s'" + +#: git-send-email.perl +#, perl-format +msgid "(%s) failed to close pipe to '%s'" +msgstr "Theip ar (%s) pÃopa a dhúnadh chuig '%s'" + +#: git-send-email.perl +#, perl-format +msgid "(%s) Adding %s: %s from: '%s'\n" +msgstr "(%s) Ag cur %s leis: %s ó: '%s'\n" + +#: git-send-email.perl +msgid "cannot send message as 7bit" +msgstr "nà féidir teachtaireacht a sheoladh mar 7bit" + +#: git-send-email.perl +msgid "invalid transfer encoding" +msgstr "ionchódú aistrithe bailÃ" + +#: git-send-email.perl +#, perl-format +msgid "" +"fatal: %s: rejected by %s hook\n" +"%s\n" +"warning: no patches were sent\n" +msgstr "" +"marfach: %s: dhiúltaithe ag %s hook\n" +"%s\n" +"rabhadh: nÃor seoladh aon phaistÃ\n" + +#: git-send-email.perl +#, perl-format +msgid "unable to open %s: %s\n" +msgstr "nach féidir %s a oscailt: %s\n" + +#: git-send-email.perl +#, perl-format +msgid "" +"fatal: %s:%d is longer than 998 characters\n" +"warning: no patches were sent\n" +msgstr "" +"marfach: %s: %d nÃos faide ná 998 carachtar\n" +"rabhadh: nÃor seoladh aon phaistÃ\n" + +#: git-send-email.perl +#, perl-format +msgid "Skipping %s with backup suffix '%s'.\n" +msgstr "Scaipeáil %s le hiarmhÃr cúltaca '%s'.\n" + +#. TRANSLATORS: please keep "[y|N]" as is. +#: git-send-email.perl +#, perl-format +msgid "Do you really want to send %s? [y|N]: " +msgstr "An bhfuil tú ag iarraidh %s a sheoladh i ndáirÃre? [y|N]: " + +#~ msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" +#~ msgstr "git cat-file (-t | -s) [--leis-cineál gan eolas] <object>" + +#~ msgid "allow -s and -t to work with broken/corrupt objects" +#~ msgstr "ligean do -s agus -t oibriú le rudaà briste/truaillithe" + +#, c-format +#~ msgid "%s: object is of unknown type '%s': %s" +#~ msgstr "%s: tá réad de chineál anaithnid '%s': %s" + +#, c-format +#~ msgid "unable to read '%s'" +#~ msgstr "nà féidir '%s' a léamh" @@ -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: 2025-03-05 22:57+0000\n" -"PO-Revision-Date: 2025-03-09 17:44+0700\n" +"POT-Creation-Date: 2025-05-27 22:57+0000\n" +"PO-Revision-Date: 2025-06-07 08:26+0700\n" "Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n" "Language-Team: Indonesian\n" "Language: id\n" @@ -951,10 +951,9 @@ msgstr "opsi abai spasi putih tidak dikenal '%s'" #: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c #: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c #: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c -#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-list.c -#: builtin/rev-parse.c builtin/show-branch.c builtin/stash.c -#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c -#: range-diff.c revision.c +#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-parse.c +#: builtin/show-branch.c builtin/stash.c builtin/submodule--helper.c +#: builtin/tag.c builtin/worktree.c parse-options.c range-diff.c revision.c #, c-format msgid "options '%s' and '%s' cannot be used together" msgstr "Opsi '%s' dan '%s' tidak dapat digunakan bersamaan" @@ -1857,7 +1856,7 @@ msgstr "" msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "--attr-source atau GIT_ATTR_SOURCE jelek" -#: attr.c read-cache.c +#: attr.c read-cache.c refs/packed-backend.c #, c-format msgid "unable to stat '%s'" msgstr "tidak dapat men-stat '%s'" @@ -2703,7 +2702,7 @@ msgstr "jalankan secara interaktif" msgid "bypass pre-applypatch and applypatch-msg hooks" msgstr "lewati kail pre-applypatch dan applypatch-msg" -#: builtin/am.c +#: builtin/am.c builtin/cat-file.c msgid "historical option -- no-op" msgstr "opsi bersejarah -- no-op" @@ -4022,7 +4021,7 @@ msgstr "Perlu sebuah repositori untuk membongkar bundel." msgid "Unbundling objects" msgstr "Membongkar bundel objek" -#: builtin/cat-file.c merge-recursive.c +#: builtin/cat-file.c #, c-format msgid "cannot read object %s '%s'" msgstr "tidak dapat membaca objek %s '%s'" @@ -4059,12 +4058,8 @@ msgid "git cat-file <type> <object>" msgstr "git cat-file <tipe> <objek>" #: builtin/cat-file.c -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e | -p) <objek>" - -#: builtin/cat-file.c -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t | -s) [--allow-unknown-type] <objek>" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <objek>" #: builtin/cat-file.c msgid "" @@ -4111,10 +4106,6 @@ msgstr "perlihatkan tipe objek (salah satu dari 'blob', 'commit', 'tag', ...)" msgid "show object size" msgstr "perlihatkan ukuran objek" -#: builtin/cat-file.c -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "perbolehkan -s dan -t bekerja dengan objek rusak" - #: builtin/cat-file.c builtin/log.c msgid "use mail map file" msgstr "gunakan berkas peta surat" @@ -4190,6 +4181,15 @@ msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "gunakan <jalur> untuk (--textconv | --filters); tidak dengan 'batch'" #: builtin/cat-file.c +msgid "objects filter only supported in batch mode" +msgstr "penyaring objek hanya didukung di mode kelompok" + +#: builtin/cat-file.c +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "penyaring objek tidak didukung: '%s'" + +#: builtin/cat-file.c #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "'%s=<%s>' butuh '%s' atau '%s'" @@ -7029,6 +7029,64 @@ msgstr "sebutkan akhiran format strftime untuk nama berkas" msgid "specify the content of the diagnostic archive" msgstr "sebutkan isi arsip diagnostik" +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse mode: %s" +msgstr "tidak dapat menguraikan mode: %s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse object id: %s" +msgstr "tidak dapat menguraikan id objek: %s" + +#: builtin/diff-pairs.c +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<opsi diff>]" + +#: builtin/diff-pairs.c builtin/log.c builtin/replay.c builtin/shortlog.c +#: bundle.c +#, c-format +msgid "unrecognized argument: %s" +msgstr "argumen tidak dikenal: %s" + +#: builtin/diff-pairs.c +msgid "working without -z is not supported" +msgstr "bekerja tanpa -z tidak didukung" + +#: builtin/diff-pairs.c +msgid "pathspec arguments not supported" +msgstr "argumen spek jalur tidak didukung" + +#: builtin/diff-pairs.c +msgid "revision arguments not allowed" +msgstr "argumen revisi tidak diperbolehkan" + +#: builtin/diff-pairs.c +msgid "invalid raw diff input" +msgstr "masukan diff mentah tidak valid" + +#: builtin/diff-pairs.c +msgid "tree objects not supported" +msgstr "objek pohon tidak didukung" + +#: builtin/diff-pairs.c +msgid "got EOF while reading path" +msgstr "dapat EOF ketika membaca jalur" + +#: builtin/diff-pairs.c +msgid "got EOF while reading destination path" +msgstr "dapat EOF ketika membaca jalur tujuan" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "tidak dapat menguraikan nilai penamaan ulang/salin : %s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unknown diff status: %c" +msgstr "status diff tidak dikenal: %c" + #: builtin/diff-tree.c msgid "--merge-base only works with two commits" msgstr "--merge-base hanya bekerja dengan dua komit" @@ -7210,6 +7268,10 @@ msgid "select handling of signed tags" msgstr "pilih penanganan tag bertandatangan" #: builtin/fast-export.c +msgid "select handling of signed commits" +msgstr "pilih penanganan komit bertandatangan" + +#: builtin/fast-export.c msgid "select handling of tags that tag filtered objects" msgstr "pilih penanganan tag yang men-tag objek tersaring" @@ -7472,7 +7534,7 @@ msgstr "opsi \"%s\" nilai \"%s\" tidak valid untuk %s" msgid "option \"%s\" is ignored for %s" msgstr "opsi \"%s\" diabaikan untuk %s" -#: builtin/fetch.c object-file.c +#: builtin/fetch.c object-store.c #, c-format msgid "%s is not a valid object" msgstr "%s bukan sebuah objek valid" @@ -8024,11 +8086,6 @@ msgstr "%s: objek rusak atau hilang: %s" #: builtin/fsck.c #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: objek bertipe tidak dikenal '%s': %s" - -#: builtin/fsck.c -#, c-format msgid "%s: object could not be parsed: %s" msgstr "%s: objek tidak dapat diuraikan: %s" @@ -8100,11 +8157,15 @@ msgid "invalid rev-index for pack '%s'" msgstr "indeks balik tidak valid untuk pak '%s'" #: builtin/fsck.c +msgid "Checking ref database" +msgstr "Memeriksa basis referensi" + +#: builtin/fsck.c 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>...]" +" [--[no-]name-objects] [--[no-]references] [<object>...]" msgstr "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" @@ -8159,6 +8220,10 @@ msgstr "perlihatkan perkembangan" msgid "show verbose names for reachable objects" msgstr "perlihatkan nama lantung untuk objek yang dapat dicapai" +#: builtin/fsck.c +msgid "check reference database consistency" +msgstr "Memeriksa konsistensi basis data referensi" + #: builtin/fsck.c builtin/index-pack.c msgid "Checking objects" msgstr "Memeriksa objek" @@ -9612,11 +9677,6 @@ msgstr "" "lacak evolusi rentang baris <awal>,<akhir> atau fungsi :<nama fungsi> dalam " "<berkas>" -#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c -#, c-format -msgid "unrecognized argument: %s" -msgstr "argumen tidak dikenal: %s" - #: builtin/log.c msgid "-L<range>:<file> cannot be used with pathspec" msgstr "-L<rentang>:<berkas> tidak dapat digunakan dengan spek jalur" @@ -10464,6 +10524,10 @@ msgid "also show informational/conflict messages" msgstr "perlihatkan juga pesan informasi/konflik" #: builtin/merge-tree.c +msgid "suppress all output; only exit status wanted" +msgstr "redam semua keluaran; hanya status keluar yang diinginkan" + +#: builtin/merge-tree.c msgid "list filenames without modes/oids/stages" msgstr "daftar nama berkas tanpa mode/oid/tahap" @@ -10624,7 +10688,7 @@ msgstr "read-tree gagal" msgid "Already up to date. (nothing to squash)" msgstr "Sudah diperbarui. (tidak ada yang bisa dilumat)" -#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c msgid "Already up to date." msgstr "Sudah terbaru." @@ -10648,7 +10712,7 @@ msgstr "'%s' tidak menunjuk pada sebuah komit" msgid "Bad branch.%s.mergeoptions string: %s" msgstr "Untai branch.%s.mergeoptions jelek: %s" -#: builtin/merge.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c msgid "Unable to write index." msgstr "Tidak dapat menulis indeks." @@ -10809,7 +10873,7 @@ msgstr "Hanya bisa menggabungkan tepantnya satu komit ke kepala kosong" msgid "Updating %s..%s\n" msgstr "Memperbarui %s..%s\n" -#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c #, c-format msgid "" "Your local changes to the following files would be overwritten by merge:\n" @@ -10976,8 +11040,12 @@ msgstr "" "sebuah batch yang lebih besar dari ukuran ini" #: builtin/mv.c -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<opsi>] <sumber>... <tujuan>" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <sumber> <tujuan>" + +#: builtin/mv.c +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] <sumber> <direktori tujuan>" #: builtin/mv.c #, c-format @@ -11067,6 +11135,11 @@ msgstr "%s, source=%s, destination=%s" #: builtin/mv.c #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "tidak dapat memindahkan baik '%s' dan direktori induknya '%s'" + +#: builtin/mv.c +#, c-format msgid "Renaming %s to %s\n" msgstr "Mengganti nama %s ke %s\n" @@ -12241,6 +12314,11 @@ msgstr "" msgid "unable to access commit %s" msgstr "Tidak dapat mengakses komit %s" +#: builtin/pull.c refspec.c +#, c-format +msgid "invalid refspec '%s'" +msgstr "spek referensi tidak valid '%s'" + #: builtin/pull.c msgid "ignoring --verify-signatures for rebase" msgstr "mengabaikan --verify-signatures untuk pendasaran ulang" @@ -13389,6 +13467,10 @@ msgid "git reflog exists <ref>" msgstr "git reflog exists <referensi>" #: builtin/reflog.c +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktee] | <referensi>...]" + +#: builtin/reflog.c #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "stempel waktu tidak valid '%s' diberikan ke '--%s'" @@ -13450,8 +13532,8 @@ msgstr "Menandai objek yang bisa dicapai..." #: builtin/reflog.c #, c-format -msgid "%s points nowhere!" -msgstr "%s tidak menunjuk ke apapun!" +msgid "reflog could not be found: '%s'" +msgstr "tidak dapat menemukan log referensi: '%s'" #: builtin/reflog.c msgid "no reflog specified to delete" @@ -13462,6 +13544,18 @@ msgstr "tidak ada log referensi yang disebutkan untuk dihapus" msgid "invalid ref format: %s" msgstr "format referensi tidak valid: %s" +#: builtin/reflog.c +msgid "drop the reflogs of all references" +msgstr "jatuhkan log referensi semua referensi" + +#: builtin/reflog.c +msgid "drop reflogs from the current worktree only" +msgstr "hanya jatuhkan log referensi dari pohon kerja saat ini" + +#: builtin/reflog.c +msgid "references specified along with --all" +msgstr "referensi yang dirincikan bersamaan dengan --all" + #: builtin/refs.c msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" @@ -14152,6 +14246,10 @@ msgid "with --cruft, expire objects older than this" msgstr "dengan --cruft, kadaluarsakan objek yang lebih tua dari ini" #: builtin/repack.c +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "dengan --cruft, hanya pak ulang pak sampah yang lebih kecil dari ini" + +#: builtin/repack.c msgid "remove redundant packs, and run git-prune-packed" msgstr "hapus pak berlebihan, dan jalankan git-prune-packed" @@ -14759,6 +14857,10 @@ msgstr "" "nilai tidak valid untuk '%s': '%s', format yang diperbolehkan hanyalah '%s'" #: builtin/rev-list.c +msgid "-z option used with unsupported option" +msgstr "osi -z digunakan dengan opsi yang tidak didukung" + +#: builtin/rev-list.c msgid "rev-list does not support display of notes" msgstr "rev-list tidak mendukung penampilan catatan" @@ -17082,8 +17184,8 @@ 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]" -msgstr "git update-ref [<opsi>] --stdin [-z]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<opsi>] --stdin [-z] [--batch-updates]" #: builtin/update-ref.c msgid "delete the reference" @@ -17101,6 +17203,10 @@ msgstr "stdin punya argumen yang diakhiri dengan NUL" msgid "read updates from stdin" msgstr "baca pembaruan dari masukan standar" +#: builtin/update-ref.c +msgid "batch reference updates" +msgstr "kelompokkan pembaruan referensi" + #: builtin/update-server-info.c msgid "update the info files from scratch" msgstr "perbarui berkas info dari awal" @@ -17961,6 +18067,10 @@ msgid "Compare a tree to the working tree or index" msgstr "Bandingkan pohon kepada pohon kerja atau indeks" #: command-list.h +msgid "Compare the content and mode of provided blob pairs" +msgstr "Bandingkan isi dan mode pasangan blob yang disediakan" + +#: command-list.h msgid "Compares the content and mode of blobs found via two tree objects" msgstr "Bandingkan isi dan mode blob yang ditemukan lewat dua objek pohon" @@ -20127,7 +20237,7 @@ msgstr "" msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "Nilai tidak dikenal untuk variabel konfigurasi 'diff.submodule': '%s'" -#: diff.c merge-recursive.c transport.c +#: diff.c merge-ort.c transport.c #, c-format msgid "unknown value for config '%s': %s" msgstr "nilai tidak dikenal untuk konfigurasi '%s': %s" @@ -21587,6 +21697,11 @@ msgstr "Kontrol delegasi tidak didukung oleh cURL < 7.22.0" msgid "Unknown value for http.proactiveauth" msgstr "nilai tidak dikenal untuk http.proactiveauth" +#: http.c parse.c +#, c-format +msgid "failed to parse %s" +msgstr "gagal menguraikan %s" + #: http.c #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" @@ -21814,7 +21929,12 @@ msgstr "tidak dapat memformat pesan: %s" msgid "invalid marker-size '%s', expecting an integer" msgstr "marker-size '%s' tidak valid, bilangan bulat diharapkan" -#: merge-ort.c merge-recursive.c +#: merge-ort-wrappers.c +#, c-format +msgid "Could not parse object '%s'" +msgstr "Tidak dapat menguraikan objek '%s'" + +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Gagal menggabungkan submodul %s (tidak di-checkout)" @@ -21824,7 +21944,7 @@ msgstr "Gagal menggabungkan submodul %s (tidak di-checkout)" msgid "Failed to merge submodule %s (no merge base)" msgstr "Gagal menggabungkan submodul %s (tidak ada dasar penggabungan)" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (commits not present)" msgstr "Gagal menggabungkan submodul %s (komit tidak ada)" @@ -21834,7 +21954,7 @@ msgstr "Gagal menggabungkan submodul %s (komit tidak ada)" msgid "error: failed to merge submodule %s (repository corrupt)" msgstr "kesalahan: gagal menggabungkan submodul %s (repositori rusak)" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" @@ -21878,12 +21998,12 @@ msgstr "kesalahan: gagal menjalankan penggabungan internal untuk %s" msgid "error: unable to add %s to database" msgstr "kesalahan: tidak dapat menambahkan %s ke basis data" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Auto-merging %s" msgstr "Menggabungkan otomatis %s" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (implicit dir rename): Existing file/dir at %s in the way of " @@ -21892,7 +22012,7 @@ msgstr "" "KONFLIK (penamaan ulang direktori implisit): Berkas/direktori yang sudah ada " "pada %s saat penamaan ulang direktori menempatkan jalur berikut di sana: %s." -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (implicit dir rename): Cannot map more than one path to %s; " @@ -21913,7 +22033,7 @@ msgstr "" "ulang %s; itu dinamai ulang ke banyak direktori lainnya, dengan tiada tujuan " "mendapatkan mayoritas berkas." -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was " @@ -21922,7 +22042,7 @@ msgstr "" "PERINGATAN: Menghindari menerapkan penamaan ulang %s -> %s ke %s, karena %s-" "nya sendiri dinamai ulang." -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "Path updated: %s added in %s inside a directory that was renamed in %s; " @@ -21931,7 +22051,7 @@ msgstr "" "Jalur diperbarui: %s menambahkan %s di dalam sebuah direktori yang dinamai " "ulang di %s; memindahkan ke %s." -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "Path updated: %s renamed to %s in %s, inside a directory that was renamed in " @@ -21940,7 +22060,7 @@ msgstr "" "Jalur diperbarui: %s dinamai ulang ke %s di %s, di dalam sebuah direktori " "yang dinamai ulang di %s; memindahkan ke %s." -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (file location): %s added in %s inside a directory that was renamed " @@ -21949,7 +22069,7 @@ msgstr "" "KONFLIK (lokasi berkas): %s menambahkan %s di dalam sebuah direktori yang " "dinamai ulang di %s, menyarankan mungkin dipindahkan ke %s." -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (file location): %s renamed to %s in %s, inside a directory that " @@ -22020,19 +22140,19 @@ msgstr "" "KONFLIK (tipe berbeda): %s punya tipe berbeda pada setiap sisi; salah " "satunya dinamai ulang sehingga masing-masing dapat direkam di suatu tempat." -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "content" msgstr "konten" -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "add/add" msgstr "penambahan/penambahan" -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "submodule" msgstr "submodul" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "CONFLICT (%s): Merge conflict in %s" msgstr "KONFLIK (%s): Konflik penggabungan di %s" @@ -22096,325 +22216,6 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "pengumpulan info penggabungan gagal untuk pohon %s, %s, dan %s" -#: merge-recursive.c -msgid "(bad commit)\n" -msgstr "(komit jelek)\n" - -#: merge-recursive.c -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "add_cacheinfo gagal untuk jalur '%s'; penggabungan dibatalkan." - -#: merge-recursive.c -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "" -"add_cacheinfo gagal menyegarkan untuk jalur '%s'; penggabungan dibatalkan." - -#: merge-recursive.c -#, c-format -msgid "failed to create path '%s'%s" -msgstr "gagal membuat jalur '%s'%s" - -#: merge-recursive.c -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Menghapus %s untuk membuat ruang untuk subdirektori\n" - -#: merge-recursive.c -msgid ": perhaps a D/F conflict?" -msgstr ": mungkin konflik direktori/berkas?" - -#: merge-recursive.c -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "menolak menghilangkan berkas tak terlacak pada '%s'" - -#: merge-recursive.c -#, c-format -msgid "blob expected for %s '%s'" -msgstr "blob diharapkan untuk %s '%s'" - -#: merge-recursive.c -#, c-format -msgid "failed to open '%s': %s" -msgstr "gagal membuka '%s': %s" - -#: merge-recursive.c -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "gagal menautkan simbolik '%s': %s" - -#: merge-recursive.c -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "tidak tahu apa yang dilakukan dengan %06o %s '%s'" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Gagal menggabungkan submodul %s (repositori rusak)" - -#: merge-recursive.c -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "Memaju-cepat submodul %s ke komit berikut:" - -#: merge-recursive.c -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "Memaju-cepat submodul %s" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"Gagal menggabungkan submodul %s (penggabungan komit berikutnya tidak " -"ditemukan)" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Gagal menggabungkan submodul %s (bukan maju-cepat)" - -#: merge-recursive.c -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Sebuah resolusi penggabungan yang mungkin ditemukan untuk submodul:\n" - -#: merge-recursive.c -#, 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 "" -"Jika benar, cukup misalkan tambahkan ke indeks dengan menggunakan:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"yang akan menerima saran ini.\n" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "Gagal menggabungkan submodul %s (banyak penggabungan ditemukan)" - -#: merge-recursive.c -msgid "failed to execute internal merge" -msgstr "gagal menjalankan penggabungan internal" - -#: merge-recursive.c -#, c-format -msgid "unable to add %s to database" -msgstr "tidak dapat menambahkan %s ke basis data" - -#: merge-recursive.c -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "" -"Kesalahan: Menolak menghilangkan berkas tak terlacak pada %s; menulis ke %s " -"sebagai gantinya." - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"KONFLIK (%s/penghapusan): %s dihapus di %s dan %s di %s. Versi %s dari %s " -"ditinggalkan di dalam pohon." - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"KONFLIK (%s/penghapusan): %s dihapus di %s dan %s ke %s di %s. Versi %s dari " -"%s ditinggalkan di dalam pohon." - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"KONFLIK (%s/penghapusan): %s dihapus di %s dan %s di %s. Versi %s dari %s " -"ditinggalkan di dalam pohon pada %s." - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"KONFLIK (%s/penghapusan): %s dihapus di %s dan %s ke %s di %s. Versi %s dari " -"%s ditinggalkan di dalam pohon pada %s." - -#: merge-recursive.c -msgid "rename" -msgstr "penamaan ulang" - -#: merge-recursive.c -msgid "renamed" -msgstr "dinamai ulang" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "Menolak menghilangkan berkas kotor pada %s" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "" -"Menolak menghilangkan berkas tak terlacak pada %s, bahkan jika itu berjalan." - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"KONFLIK (penamaan ulang/penambahan): Penamaan ulang %s-%s di %s. %s " -"ditambahkan di %s" - -#: merge-recursive.c -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "" -"%s adalah sebuah direktori dalam %s menambahkan sebagai %s sebagai gantinya" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "" -"Menolak menghilangkan berkas tak terlacak pada %s; menambahkan sebagai %s " -"sebagai gantinya" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"KONFLIK (penamaan ulang/penamaan ulang): Penamaan ulang \"%s\"->\"%s\" di " -"dalam cabang \"%s\" penamaan ulang \"%s\"->\"%s\" di \"%s\"%s" - -#: merge-recursive.c -msgid " (left unresolved)" -msgstr " dibiarkan tak diselesaikan" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"KONFLIK (penamaan ulang/penamaan ulang): Penamaan ulang %s->%s di %s. " -"Penamaan ulang %s->%s di %s" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"KONFLIK (pemecahan penamaan ulang direktori): Tidak jelas dimana untuk " -"menempatkan %s karena direktori %s dinamai ulang ke banyak direktori " -"lainnya, dengan tidak ada tujuan yang mendapatkan mayoritas berkas." - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"KONFLIK (penamaan ulang/penamaan ulang): Penamaan ulang direktori %s->%s di " -"%s. Penamaan ulang %s->%s di %s" - -#: merge-recursive.c -#, c-format -msgid "cannot read object %s" -msgstr "tidak dapat membaca objek %s" - -#: merge-recursive.c -#, c-format -msgid "object %s is not a blob" -msgstr "objek %s bukanlah sebuah blob" - -#: merge-recursive.c -msgid "modify" -msgstr "ubah" - -#: merge-recursive.c -msgid "modified" -msgstr "diubah" - -#: merge-recursive.c -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "%s dilewatkan (digabungkan sama seperti yang ada)" - -#: merge-recursive.c -#, c-format -msgid "Adding as %s instead" -msgstr "Menambahkan sebagai %s sebagai gantinya" - -#: merge-recursive.c -#, c-format -msgid "Removing %s" -msgstr "Menghapus %s" - -#: merge-recursive.c -msgid "file/directory" -msgstr "berkas/direktori" - -#: merge-recursive.c -msgid "directory/file" -msgstr "direktori/berkas" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"KONFLIK (%s): Ada direktori dengan nama %s di %s. Menambahakn %s sebagai %s" - -#: merge-recursive.c -#, c-format -msgid "Adding %s" -msgstr "Menambahkan %s" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "KONFLIK (penambahan/penambahan): Konflik penggabungan di %s" - -#: merge-recursive.c -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "penggabungan pohon %s dan %s gagal" - -#: merge-recursive.c -msgid "Merging:" -msgstr "Menggabungkan:" - -#: merge-recursive.c -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "%u leluhur umum ditemukan:" -msgstr[1] "%u leluhur umum ditemukan:" - -#: merge-recursive.c -msgid "merge returned no commit" -msgstr "penggabungan tidak mengembalikan komit" - -#: merge-recursive.c -#, c-format -msgid "Could not parse object '%s'" -msgstr "Tidak dapat menguraikan objek '%s'" - #: merge.c msgid "failed to read the cache" msgstr "gagal membaca tembolok" @@ -22468,14 +22269,15 @@ msgid "failed to clear multi-pack-index at %s" msgstr "gagal membersihkan indeks multipak pada %s" #: midx-write.c -msgid "cannot write incremental MIDX with bitmap" -msgstr "tidak dapat menulis MIDX tambahan dengan bitmap" - -#: midx-write.c msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "abaikan indeks multipak yang sudah ada; checksum tidak cocok" #: midx-write.c +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "tidak dapat memuat indeks balik untuk MIDX %s" + +#: midx-write.c msgid "Adding packfiles to multi-pack-index" msgstr "Menambahkan berkas pak ke indeks multipak" @@ -22797,79 +22599,6 @@ 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" -msgstr "direktori objek %s tidak ada; periksa .git/objects/info/alternates" - -#: object-file.c -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "tidak dapat menormalisasikan jalur objek alternatif: %s" - -#: object-file.c -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s: mengabaikan penyimpanan objek alternatif, bersarang terlalu dalam" - -#: object-file.c -msgid "unable to fdopen alternates lockfile" -msgstr "tidak dapat men-fdopen berkas kunci alternatif" - -#: object-file.c -msgid "unable to read alternates file" -msgstr "tidak dapat membaca berkas alternatif" - -#: object-file.c -msgid "unable to move new alternates file into place" -msgstr "tidak dapat memindahkan berkas alternatif baru ke tempatnya" - -#: object-file.c -#, c-format -msgid "path '%s' does not exist" -msgstr "jalur '%s' tidak ada" - -#: object-file.c -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "" -"repositori referensi '%s' sebagai sebuah checkout tertaut belum didukung." - -#: object-file.c -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "repositori referensi '%s' bukan sebuah repositori lokal" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "repositori referensi '%s' dangkal" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "repositori referensi '%s' cangkok" - -#: object-file.c -#, c-format -msgid "could not find object directory matching %s" -msgstr "tidak dapat menemukan direktori objek yang cocok dengan %s" - -#: object-file.c -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "baris tidak valid saat menguraikan referensi alternatif: %s" - -#: object-file.c -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "mencoba men-mmap %<PRIuMAX> di atas batas %<PRIuMAX>" - -#: object-file.c -#, c-format -msgid "mmap failed%s" -msgstr "mmap gagal%s" - -#: object-file.c -#, c-format msgid "object file %s is empty" msgstr "berkas objek %s kosong" @@ -22914,21 +22643,6 @@ msgstr "objek longgar %s (disimpan di %s) rusak" #: object-file.c #, c-format -msgid "replacement %s not found for %s" -msgstr "pengganti %s tidak ditemukan untuk %s" - -#: object-file.c -#, c-format -msgid "packed object %s (stored in %s) is corrupt" -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 open %s" msgstr "tidak dapat membuka %s" @@ -23047,11 +22761,6 @@ msgstr "%s: tipe berkas tidak didukung" #: object-file.c #, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s bukan sebuah objek '%s' valid" - -#: object-file.c -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "hash tidak cocok untuk %s (diharapkan %s)" @@ -23072,6 +22781,11 @@ msgstr "tidak dapat menguraikan kepala %s" #: object-file.c #, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "tidak dapat menguraikan tipe dari kepala '%s' dari '%s'" + +#: object-file.c +#, c-format msgid "unable to unpack contents of %s" msgstr "tidak dapat membongkar isi %s" @@ -23248,6 +22962,89 @@ msgstr "<objek>:<jalur> diperlukan, hanya <objek> '%s' diberikan" msgid "invalid object name '%.*s'." msgstr "nama objek tidak valid '%.*s'." +#: object-store.c +#, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "direktori objek %s tidak ada; periksa .git/objects/info/alternates" + +#: object-store.c +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "tidak dapat menormalisasikan jalur objek alternatif: %s" + +#: object-store.c +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s: mengabaikan penyimpanan objek alternatif, bersarang terlalu dalam" + +#: object-store.c +msgid "unable to fdopen alternates lockfile" +msgstr "tidak dapat men-fdopen berkas kunci alternatif" + +#: object-store.c +msgid "unable to read alternates file" +msgstr "tidak dapat membaca berkas alternatif" + +#: object-store.c +msgid "unable to move new alternates file into place" +msgstr "tidak dapat memindahkan berkas alternatif baru ke tempatnya" + +#: object-store.c +#, c-format +msgid "path '%s' does not exist" +msgstr "jalur '%s' tidak ada" + +#: object-store.c +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "" +"repositori referensi '%s' sebagai sebuah checkout tertaut belum didukung." + +#: object-store.c +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "repositori referensi '%s' bukan sebuah repositori lokal" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "repositori referensi '%s' dangkal" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "repositori referensi '%s' cangkok" + +#: object-store.c +#, c-format +msgid "could not find object directory matching %s" +msgstr "tidak dapat menemukan direktori objek yang cocok dengan %s" + +#: object-store.c +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "baris tidak valid saat menguraikan referensi alternatif: %s" + +#: object-store.c +#, c-format +msgid "replacement %s not found for %s" +msgstr "pengganti %s tidak ditemukan untuk %s" + +#: object-store.c +#, c-format +msgid "packed object %s (stored in %s) is corrupt" +msgstr "objek terpak %s (disimpan di %s) rusak" + +#: object-store.c +#, c-format +msgid "missing mapping of %s to %s" +msgstr "pemetaan %s ke %s hilang" + +#: object-store.c +#, c-format +msgid "%s is not a valid '%s' object" +msgstr "%s bukan sebuah objek '%s' valid" + #: object.c #, c-format msgid "invalid object type \"%s\"" @@ -23601,6 +23398,16 @@ msgstr "%s tidak ada" #: parse-options.c #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "nilai %s untuk %s di luar rentang [%<PRIdMAX>,%<PRIdMAX>]" + +#: parse-options.c +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s mengharapkan nilai bilangan bulat dengan akhiran opsional k/m/g" + +#: parse-options.c +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "" "%s mengharapkan nilai bilangan bulat non negatif dengan akhiran opsional k/m/" @@ -23787,11 +23594,6 @@ msgstr "" msgid "bad boolean environment value '%s' for '%s'" msgstr "nilai lingkungan boolean '%s' jelek untuk '%s'" -#: parse.c -#, c-format -msgid "failed to parse %s" -msgstr "gagal menguraikan %s" - #: path-walk.c #, c-format msgid "failed to walk children of tree %s: not found" @@ -23999,8 +23801,13 @@ msgstr "tidak dapat mengambil %s dari remote penjanji" #: promisor-remote.c #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "remote yang terkenal bernama '%s' tapi dengan url '%s' daripada '%s'" +msgid "no or empty URL advertised for remote '%s'" +msgstr "tidak ada URL atau URL kosong yang diiklankan untuk remote '%s'" + +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "remote yang terkenal bernama '%s' tapi dengan URL '%s' daripada '%s'" #: promisor-remote.c #, c-format @@ -24931,6 +24738,11 @@ msgstr "tidak dapat membuka direktori %s" msgid "Checking references consistency" msgstr "Memeriksa konsistensi referensi" +#: refs/packed-backend.c +#, c-format +msgid "unable to open '%s'" +msgstr "tidak dapat membuka '%s'" + #: refs/reftable-backend.c #, c-format msgid "refname is dangerous: %s" @@ -25016,11 +24828,6 @@ msgstr "nama referensi %s simbolik, menyalinnya tidak didukung" #: refspec.c #, c-format -msgid "invalid refspec '%s'" -msgstr "spek referensi tidak valid '%s'" - -#: refspec.c -#, c-format msgid "pattern '%s' has no '*'" msgstr "pola '%s' tidak mempunyai '*'" @@ -25688,8 +25495,8 @@ msgid "could not set recommended config" msgstr "tidak dapat menyetel konfigurasi yang direkomendasikan" #: scalar.c -msgid "could not turn on maintenance" -msgstr "tidak dapat mengaktifkan pemeliharaan" +msgid "could not toggle maintenance" +msgstr "tidak dapat mengalihkan pemeliharaan" #: scalar.c msgid "could not start the FSMonitor daemon" @@ -25747,15 +25554,19 @@ msgstr "salin repositori di dalam direktori 'src'" #: scalar.c msgid "specify if tags should be fetched during clone" -msgstr "rincikan jikan tag hendak diambil selama kloning" +msgstr "rincikan jika tag hendak diambil selama kloning" + +#: scalar.c +msgid "specify if background maintenance should be enabled" +msgstr "rincikan jika pemeliharaan balik layar hendak diaktifkan" #: scalar.c msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <cabang utama>] [--full-clone]\n" -"\t[--[-no-]src] [--[no-]tags] <url> [<pendaftaran>]" +"\t[--[-no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<pendaftaran>]" #: scalar.c #, c-format @@ -25804,16 +25615,28 @@ msgid "`scalar list` does not take arguments" msgstr "`scalar list` tidak mengambil argumen" #: scalar.c -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<pendaftaran>]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [<pendaftaran>]" #: scalar.c msgid "reconfigure all registered enlistments" msgstr "konfigurasi ulang semua pendaftaran yang terdaftar" #: scalar.c -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all | <pendaftaran>]" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +#: scalar.c +msgid "signal how to adjust background maintenance" +msgstr "beri sinyal bagaimana pemeliharaan balik layar diatur" + +#: scalar.c +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<pendaftaran>]" #: scalar.c msgid "--all or <enlistment>, but not both" @@ -25821,6 +25644,11 @@ msgstr "--all atau <pendaftaran>, tetapi bukan kedua-duanya" #: scalar.c #, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "mode untuk --maintenance tidak dikenal: %s" + +#: scalar.c +#, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "tidak dapat menghapus scalar.repo basi '%s'" @@ -27560,6 +27388,10 @@ msgstr "bersihkan pohon tembolok sebelum setiap iterasi" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "jumlah entri di dalam pohon tembolok untuk dinirvalidasi (asali 0)" +#: t/helper/test-pack-deltas.c +msgid "the number of objects to write" +msgstr "jumlah objek tertulis yang ditulis" + #: t/helper/test-path-walk.c msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk <opsi> -- <opsi revisi>" @@ -28503,6 +28335,16 @@ msgstr "tidak dapat mendapatkan direktori kerja saat ini" msgid "unable to get random bytes" msgstr "tidak dapat mendapatkan bita acak" +#: wrapper.c +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "mencoba men-mmap %<PRIuMAX> di atas batas %<PRIuMAX>" + +#: wrapper.c +#, c-format +msgid "mmap failed%s" +msgstr "mmap gagal%s" + #: wt-status.c msgid "Unmerged paths:" msgstr "Jalur yang tak tergabung:" @@ -29421,6 +29263,15 @@ msgstr "" #: git-send-email.perl #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook memberikan ulang Message-ID ke: %s\n" + +#: git-send-email.perl +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "Peringatan: Tidak dapat mengambil Message-ID dari respons peladen.\n" + +#: git-send-email.perl +#, perl-format msgid "Failed to send %s\n" msgstr "Gagal mengirim %s\n" @@ -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: 2025-03-11 15:01+0300\n" -"PO-Revision-Date: 2025-03-11 15:00+0300\n" +"POT-Creation-Date: 2025-05-29 11:02+0300\n" +"PO-Revision-Date: 2025-05-29 12:00+0300\n" "Last-Translator: Emir SARI <emir_sari@icloud.com>\n" "Language-Team: Turkish (https://github.com/bitigchi/git-po/)\n" "Language: tr\n" @@ -3333,11 +3333,8 @@ msgstr "yalnızca bir toplu iÅŸ seçeneÄŸi belirtilebilir" msgid "git cat-file <type> <object>" msgstr "git cat-file <tür> <nesne>" -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e | -p) <nesne>" - -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t | -s) [--allow-unknown-type] <nesne>" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <nesne>" msgid "" "git cat-file (--textconv | --filters)\n" @@ -3352,10 +3349,9 @@ msgid "" " [--buffer] [--follow-symlinks] [--unordered]\n" " [--textconv | --filters] [-Z]" msgstr "" -"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" -"objects]\n" -" [--buffer] [--follow-symlinks] [--unordered]\n" -" [--textconv | --filters] [-Z]" +"git cat-file (--batch | --batch-check | --batch-command)\n" +" [--batch-all-objects] [--buffer] [--follow-symlinks]\n" +" [--unordered] [--textconv | --filters] [-Z]" msgid "Check object existence or emit object contents" msgstr "Nesne varlığını denetle veya nesne içeriÄŸini yay" @@ -3375,9 +3371,6 @@ msgstr "nesne türünü göster (türler: 'blob', 'tree', 'commit', 'tag', ...)" msgid "show object size" msgstr "nesne boyutunu göster" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "-s ve -t'nin bozuk/hasarlı nesnelerle çalışmasına izin ver" - msgid "use mail map file" msgstr "posta eÅŸlem dosyasını kullan" @@ -3435,6 +3428,13 @@ msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "" "(--textconv | --filters) için bir <yol> kullan; ancak 'batch' ile deÄŸil" +msgid "objects filter only supported in batch mode" +msgstr "nesneler süzgeci yalnızca toplu iÅŸ kipinde desteklenir" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "nesne süzgeci desteklenmiyor: '%s'" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "'%s=<%s>' için '%s' veya '%s' gerekiyor" @@ -5695,6 +5695,50 @@ msgstr "dosya adı için bir strftime biçimli ek belirtin" msgid "specify the content of the diagnostic archive" msgstr "tanı arÅŸivinin içeriÄŸini belirtin" +#, c-format +msgid "unable to parse mode: %s" +msgstr "kip ayrıştırılamıyor: %s" + +#, c-format +msgid "unable to parse object id: %s" +msgstr "nesne kimliÄŸi ayrıştırılamıyor: %s" + +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<diff-seçenekleri>]" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "tanımlanamayan argüman: %s" + +msgid "working without -z is not supported" +msgstr "-z olmadan çalışma desteklenmiyor" + +msgid "pathspec arguments not supported" +msgstr "yol belirteci argümanları desteklenmiyor" + +msgid "revision arguments not allowed" +msgstr "revizyon argümanlarına izin verilmiyor" + +msgid "invalid raw diff input" +msgstr "geçersiz ham diff giriÅŸi" + +msgid "tree objects not supported" +msgstr "aÄŸaç nesneleri desteklenmiyor" + +msgid "got EOF while reading path" +msgstr "yol okunurken dosya sonu alındı" + +msgid "got EOF while reading destination path" +msgstr "hedef yol okunurken dosya sonu alındı" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "yeniden adlandır/kopyala puanı ayrıştırılamıyor: %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "bilinmeyen diff durumu: %c" + msgid "--merge-base only works with two commits" msgstr "--merge-base yalnızca iki iÅŸleme ile kullanılabilir" @@ -5837,6 +5881,9 @@ msgstr "<n> nesneden sonra ilerlemeyi göster" msgid "select handling of signed tags" msgstr "imzalanan etiketlerin nasıl ele alınacağını seçin" +msgid "select handling of signed commits" +msgstr "imzalanan iÅŸlemelerin nasıl ele alınacağını seçin" + msgid "select handling of tags that tag filtered objects" msgstr "nesnelerce süzülen etiketlerin nasıl ele alınacağını seçin" @@ -6478,10 +6525,6 @@ msgid "%s: object corrupt or missing: %s" msgstr "%s: nesne hasarlı veya kayıp: %s" #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: nesne bilinmeyen bir türde: '%s': %s" - -#, c-format msgid "%s: object could not be parsed: %s" msgstr "%s: nesne ayrıştırılamadı: %s" @@ -6538,16 +6581,19 @@ msgstr "'%s' paketi için rev-index yüklenemiyor" msgid "invalid rev-index for pack '%s'" msgstr "'%s' paketi için geçersiz rev-index" +msgid "Checking ref database" +msgstr "BaÅŸvuru günlüğü denetleniyor" + 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>...]" +" [--[no-]name-objects] [--[no-]references] [<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] [<nesne>...]" +" [--[no-]name-objects] [--[no-]references] [<nesne>...]" msgid "show unreachable objects" msgstr "ulaşılamayan nesneleri göster" @@ -6585,6 +6631,9 @@ msgstr "ilerlemeyi göster" msgid "show verbose names for reachable objects" msgstr "ulaşılabilir nesneler için ayrıntılı adları göster" +msgid "check reference database consistency" +msgstr "baÅŸvuru veritabanı tutarlılığını denetle" + msgid "Checking objects" msgstr "Nesneler denetleniyor" @@ -7726,10 +7775,6 @@ msgstr "" "<dosya> içindeki <baÅŸlangıç>,<bitiÅŸ> satır eriminin veya :<iÅŸlevadı> " "iÅŸlevinin evrimini izle" -#, c-format -msgid "unrecognized argument: %s" -msgstr "tanımlanamayan argüman: %s" - msgid "-L<range>:<file> cannot be used with pathspec" msgstr "-L<erim>:<dosya>, yol belirteci ile kullanılamıyor" @@ -8373,6 +8418,9 @@ msgstr "yalnızca bir önemsiz birleÅŸtirme yap" msgid "also show informational/conflict messages" msgstr "ayrıcı bilgi/çakışma iletilerini göster" +msgid "suppress all output; only exit status wanted" +msgstr "tüm çıktıyı sustur; yalnızca çıkış durumu istenir" + msgid "list filenames without modes/oids/stages" msgstr "kipi/oid'si/hazırlığı olmayan dosya adlarını listele" @@ -8772,8 +8820,11 @@ msgstr "" "yeniden paketleme sırasında daha küçük boyutlu paket dosyalarını bu boyuttan " "daha büyük bir toplu iÅŸ olarak toplayın" -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<seçenekler>] <kaynak>... <hedef>" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <kaynak> <hedef>" + +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] <kaynak>... <hedef-dizin>" #, c-format msgid "Directory %s is in index and no submodule?" @@ -8844,6 +8895,10 @@ msgid "%s, source=%s, destination=%s" msgstr "%s, kaynak=%s, hedef:%s" #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "hem '%s' ve onun üst dizini '%s' taşınamıyor" + +#, c-format msgid "Renaming %s to %s\n" msgstr "%s, %s olarak yeniden adlandırılıyor\n" @@ -9763,6 +9818,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "%s iÅŸlemesine eriÅŸilemedi" +#, c-format +msgid "invalid refspec '%s'" +msgstr "geçersiz baÅŸvuru belirteci '%s'" + msgid "ignoring --verify-signatures for rebase" msgstr "yeniden temellendirme için --verify-signatures yok sayılıyor" @@ -10721,6 +10780,9 @@ msgstr "" msgid "git reflog exists <ref>" msgstr "git reflog exists <baÅŸvuru>" +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktree] | <baÅŸvurular>...]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "geçersiz zaman damgası '%s', '--%s' argümanına verildi" @@ -10770,8 +10832,8 @@ msgid "Marking reachable objects..." msgstr "Ulaşılabilir nesneler imleniyor..." #, c-format -msgid "%s points nowhere!" -msgstr "%s hiçbir yere iÅŸaret etmiyor!" +msgid "reflog could not be found: '%s'" +msgstr "baÅŸvuru günlüğü bulunamadı: '%s'" msgid "no reflog specified to delete" msgstr "silmek için bir baÅŸvuru günlüğü belirtilmedi" @@ -10780,6 +10842,15 @@ msgstr "silmek için bir baÅŸvuru günlüğü belirtilmedi" msgid "invalid ref format: %s" msgstr "geçersiz baÅŸvuru biçimi: %s" +msgid "drop the reflogs of all references" +msgstr "tüm baÅŸvuruların baÅŸvuru günlüklerini bırak" + +msgid "drop reflogs from the current worktree only" +msgstr "yalnızca geçerli çalışma aÄŸacından olan baÅŸvuru günlüklerini bırak" + +msgid "references specified along with --all" +msgstr "--all ile belirtilmiÅŸ baÅŸvurular" + msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=<biçim> [--no-reflog] [--dry-run]" @@ -11333,6 +11404,9 @@ msgstr "yaklaşık tarih" msgid "with --cruft, expire objects older than this" msgstr "--cruft ile bundan daha eski nesneleri yürürlükten kaldır" +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "--cruft ile yalnızca bundan daha küçük paketleri yeniden paketle" + msgid "remove redundant packs, and run git-prune-packed" msgstr "gereksiz paketleri kaldır ve 'git-prune-packed' çalıştır" @@ -11809,6 +11883,9 @@ msgstr "%s ögesinin disk kullanımı alınamıyor" msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "'%s' için geçersiz deÄŸer: '%s', tek izin verilen biçim '%s'" +msgid "-z option used with unsupported option" +msgstr "-z seçeneÄŸi desteklenmeyen seçenekle kullanıldı" + msgid "rev-list does not support display of notes" msgstr "rev-list not görüntülemesini desteklemiyor" @@ -13652,8 +13729,8 @@ msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" msgstr "" "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]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<seçenekler>] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "baÅŸvuruyu sil" @@ -13667,6 +13744,9 @@ msgstr "stdin'de NUL ile sonlandırılan argümanlar var" msgid "read updates from stdin" msgstr "güncellemeleri stdin'den oku" +msgid "batch reference updates" +msgstr "toplu baÅŸvuru güncellemeleri" + msgid "update the info files from scratch" msgstr "bilgi dosyalarını en baÅŸtan güncelle" @@ -14236,10 +14316,10 @@ msgid "Download missing objects in a partial clone" msgstr "Eksik nesneleri kısımsal bir klonda indir" msgid "Use binary search to find the commit that introduced a bug" -msgstr "Hatalara neden olan iÅŸlemeyi bulmada ikili arama kullan" +msgstr "Hatalara neden olan iÅŸlemeyi ikili aramayla bul" msgid "Show what revision and author last modified each line of a file" -msgstr "Dosya satırlarını son deÄŸiÅŸtiren revizyon/yazarı göster" +msgstr "Dosya satırına son elleyen revizyonu/yazarı göster" msgid "List, create, or delete branches" msgstr "Dal oluÅŸtur, sil veya listele" @@ -14266,7 +14346,7 @@ msgid "Ensures that a reference name is well formed" msgstr "Bir baÅŸvuru adının düzgünce oluÅŸturulduÄŸundan emin ol" msgid "Switch branches or restore working tree files" -msgstr "Dal deÄŸiÅŸtir veya çalışma aÄŸacını eski haline geri getir" +msgstr "Dal deÄŸiÅŸtir/çalışma aÄŸacını eski haline geri getir" msgid "Copy files from the index to the working tree" msgstr "Dosyaları indeksten çalışma aÄŸacına kopyala" @@ -14275,7 +14355,7 @@ msgid "Find commits yet to be applied to upstream" msgstr "Henüz üstkaynaÄŸa uygulanmayan iÅŸlemeleri bul" msgid "Apply the changes introduced by some existing commits" -msgstr "Mevcut bazı iÅŸlemelerin getirdiÄŸi deÄŸiÅŸiklikleri uygula" +msgstr "Bazı iÅŸlemelerin getirdiÄŸi deÄŸiÅŸiklikleri uygula" msgid "Graphical alternative to git-commit" msgstr "git-commit için grafik tabanlı alternatif" @@ -14308,7 +14388,7 @@ msgid "Retrieve and store user credentials" msgstr "Kullanıcı yetkilerini al ve depola" msgid "Helper to temporarily store passwords in memory" -msgstr "Parolaları geçici olarak bellekte saklamak için yardımcı" +msgstr "Parolaları geçicide bellekte saklamak için yardımcı" msgid "Helper to store credentials on disk" msgstr "Yetkileri diskte saklamak için yardımcı" @@ -14326,7 +14406,7 @@ msgid "A really simple server for Git repositories" msgstr "Git depoları için gerçekten yalın bir sunucu" msgid "Give an object a human readable name based on an available ref" -msgstr "Uygun bir baÅŸvuruyu temel alıp nesneye okunabilir ad ver" +msgstr "Uygun bir baÅŸvuru temeliyle nesneye okunabilir ad ver" msgid "Generate a zip archive of diagnostic information" msgstr "Tanı bilgisinin bir zip arÅŸivini oluÅŸtur" @@ -14340,8 +14420,12 @@ msgstr "İndeksteki ve çalışma aÄŸacındaki dosyaları sıkıştır" msgid "Compare a tree to the working tree or index" msgstr "Bir aÄŸacı çalışma aÄŸacı veya indeks ile karşılaÅŸtır" +msgid "Compare the content and mode of provided blob pairs" +msgstr "İkili çiftinin içeriÄŸini ve kipini kıyasla" + msgid "Compares the content and mode of blobs found via two tree objects" -msgstr "İki aÄŸaç nesnesiyle bulunan ikililerin içerik/kipini karşılaÅŸtır" +msgstr "" +"İki aÄŸaç nesnesiyle bulunan ikililerin içeriÄŸini ve kipini karşılaÅŸtırır" msgid "Show changes using common diff tools" msgstr "DeÄŸiÅŸiklikleri yaygın diff araçlarıyla göster" @@ -14374,13 +14458,13 @@ msgid "Prepare patches for e-mail submission" msgstr "E-posta teslimi için yamaları hazırla" msgid "Verifies the connectivity and validity of the objects in the database" -msgstr "Veritab. nesnelerin baÄŸlanırlığını ve geçerliliÄŸini sına" +msgstr "Veri nesnesinin baÄŸlanırlığını ve geçerliliÄŸini sına" msgid "Cleanup unnecessary files and optimize the local repository" msgstr "Gereksiz dosyaları temizle ve yerel depoyu eniyile" msgid "Extract commit ID from an archive created using git-archive" -msgstr "İşleme iletisini bir git-archive arÅŸivinden çıkartıp al" +msgstr "İşleme iletisini git-archive arÅŸivinden çıkarıp al" msgid "Print lines matching a pattern" msgstr "Bir dizgi ile eÅŸleÅŸen satırları yazdır" @@ -14389,7 +14473,7 @@ msgid "A portable graphical interface to Git" msgstr "Git için taşınabilir bir grafik arabirim" msgid "Compute object ID and optionally create an object from a file" -msgstr "Nesne kimliÄŸini hesapla/dosyadan isteÄŸe baÄŸlı nesne oluÅŸtur" +msgstr "Nesne kimliÄŸini hesapla-isteÄŸe baÄŸlı nesne oluÅŸtur" msgid "Display help information about Git" msgstr "Git yardım bilgisini görüntüle" @@ -14407,13 +14491,13 @@ msgid "Push objects over HTTP/DAV to another repository" msgstr "Nesneleri HTTP/DAV üzerinden baÅŸka bir depoya it" msgid "Send a collection of patches from stdin to an IMAP folder" -msgstr "stdin'den bir IMAP klasörüne bir yama derlemesi gönder" +msgstr "stdin'den bir IMAP klasörüne yama derlemesi gönder" msgid "Build pack index file for an existing packed archive" -msgstr "Mevcut paketli bir arÅŸiv için paket indeks dosyası yap" +msgstr "Paketli bir arÅŸiv için paket indeks dosyası yap" msgid "Create an empty Git repository or reinitialize an existing one" -msgstr "BoÅŸ bir Git deposu oluÅŸtur veya olanı yeniden ilklendir" +msgstr "BoÅŸ Git deposu oluÅŸtur veya olanı yeniden ilklendir" msgid "Instantly browse your working repository in gitweb" msgstr "gitweb'deki çalışma deposuna anında göz at" @@ -14446,7 +14530,7 @@ msgid "Join two or more development histories together" msgstr "İki veya daha fazla geliÅŸtirme geçmiÅŸini birleÅŸtir" msgid "Find as good common ancestors as possible for a merge" -msgstr "BirleÅŸtirme için olabildiÄŸince en iyi ortak ataları bul" +msgstr "BirleÅŸtirme için olabildiÄŸince en iyi ortak atayı bul" msgid "Run a three-way file merge" msgstr "Bir 3 yönlü dosya birleÅŸtirmesi çalıştır" @@ -14473,7 +14557,7 @@ msgid "Write and verify multi-pack-indexes" msgstr "multi-pack-index doÄŸrula ve yaz" msgid "Move or rename a file, a directory, or a symlink" -msgstr "Dosya, dizin veya sembolik baÄŸları taşı/yeniden adlandır" +msgstr "Dosya, dizin, sembolik baÄŸları taşı/yeniden adlandır" msgid "Find symbolic names for given revs" msgstr "Verilen revizyonlar için sembolik adları bul" @@ -14491,7 +14575,7 @@ msgid "Find redundant pack files" msgstr "Gereksiz paket dosyalarını bul" msgid "Pack heads and tags for efficient repository access" -msgstr "Etkili depo eriÅŸimi için dal uçları ve etiketler paketle" +msgstr "Tez depo eriÅŸimi için dal uçları ve etiketler paketle" msgid "Compute unique ID for a patch" msgstr "Bir yama için eÅŸi olmayan numara hesapla" @@ -14500,13 +14584,13 @@ msgid "Prune all unreachable objects from the object database" msgstr "Ulaşılamayan tüm nesneleri nesne veritabanından buda" msgid "Remove extra objects that are already in pack files" -msgstr "Halihazırda paket dosyalarında olan ek nesneleri kaldır" +msgstr "Halihazırda paket dosyalarındaki ek nesneleri kaldır" msgid "Fetch from and integrate with another repository or a local branch" msgstr "BaÅŸka bir depo veya yerel daldan getir ve tümleÅŸtir" msgid "Update remote refs along with associated objects" -msgstr "İliÅŸkin nesnelerle birlikte uzak baÅŸvuruları da güncelle" +msgstr "İliÅŸkin nesneleri ve uzak baÅŸvuruları güncelle" msgid "Applies a quilt patchset onto the current branch" msgstr "Geçerli dala bir \"Quilt\" yama seti uygula" @@ -14536,17 +14620,16 @@ msgid "Pack unpacked objects in a repository" msgstr "Bir depodaki paketlenmemiÅŸ nesneleri paketle" msgid "Create, list, delete refs to replace objects" -msgstr "Nesne deÄŸiÅŸtirmek için baÅŸvurular oluÅŸtur, sil, listele" +msgstr "Nesne deÄŸiÅŸtirmek için baÅŸvuru oluÅŸtur, sil, listele" msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too" -msgstr "" -"DENEYSEL: İşlemeleri yeni temelde yeniden oynat, çıplak depolarla da çalışır" +msgstr "DENEYSEL: İşlemeleri yeni temelde oynat, çıplak depolarla çalışır" msgid "Generates a summary of pending changes" msgstr "Bekleyen deÄŸiÅŸikliklerin bir özetini çıkart" msgid "Reuse recorded resolution of conflicted merges" -msgstr "Çakışan birleÅŸtirmelerin kayıtlı çözümlerini yen. kullan" +msgstr "Çakışmaların kayıtlı çözümlerini yeniden kullan" msgid "Reset current HEAD to the specified state" msgstr "Geçerli HEAD'i belirtilen duruma sıfırla" @@ -14597,7 +14680,7 @@ msgid "List references in a local repository" msgstr "Yerel bir depodaki baÅŸvuruları listele" msgid "Reduce your working tree to a subset of tracked files" -msgstr "Çalışma aÄŸacını izlenen dosyaların alt kümesine küçült" +msgstr "Çalışma aÄŸacını izlenen dosyanın alt kümesine küçült" msgid "Add file contents to the staging area" msgstr "Dosya içeriÄŸini hazırlama alanına ekle" @@ -14615,7 +14698,7 @@ msgid "Initialize, update or inspect submodules" msgstr "Altmodülleri ilklendir, güncelle veya incele" msgid "Bidirectional operation between a Subversion repository and Git" -msgstr "Bir Subversion ve Git deposu arasında iki yönlü iÅŸlemler" +msgstr "Subversion ve Git arasında iki yönlü iÅŸlemler" msgid "Switch branches" msgstr "Dal deÄŸiÅŸtir" @@ -14624,10 +14707,10 @@ msgid "Read, modify and delete symbolic refs" msgstr "Sembolik baÅŸvuruları oku, düzenle ve sil" msgid "Create, list, delete or verify a tag object signed with GPG" -msgstr "GPG imzalı bir etiket oluÅŸtur, sil, listele veya doÄŸrula" +msgstr "GPG imzalı etiket oluÅŸtur, sil, listele, doÄŸrula" msgid "Creates a temporary file with a blob's contents" -msgstr "Bir ikili nesnenin içeriÄŸi ile geçici bir dosya oluÅŸtur" +msgstr "İkili nesnenin içeriÄŸi ile geçici bir dosya oluÅŸtur" msgid "Unpack objects from a packed archive" msgstr "PaketlenmiÅŸ bir arÅŸivden nesneleri çıkar" @@ -14636,11 +14719,10 @@ msgid "Register file contents in the working tree to the index" msgstr "Çalışma aÄŸacındaki dosya içeriÄŸini indekse kaydet" msgid "Update the object name stored in a ref safely" -msgstr "Güvenlice bir baÅŸvuruda depolanan nesne adını güncelle" +msgstr "Güvenlice baÅŸvuruda depolanan nesne adını güncelle" msgid "Update auxiliary info file to help dumb servers" -msgstr "" -"Programlanamayan sunuculara destek için yardımcı veri dosyasını güncelle" +msgstr "Aptal sunuculara destek için ek bilgiyi güncelle" msgid "Send archive back to git-archive" msgstr "ArÅŸivi git-archive'e geri gönder" @@ -14679,7 +14761,7 @@ msgid "Git command-line interface and conventions" msgstr "Git komut satırı arabirimi ve kuralları" msgid "A Git core tutorial for developers" -msgstr "GeliÅŸtiriciler için Git çekirdeÄŸi eÄŸitmeni" +msgstr "GeliÅŸtiriciler için Git çekirdek öğreticisi" msgid "Providing usernames and passwords to Git" msgstr "Git'e kullanıcı adları ve parolalar belirt" @@ -14715,7 +14797,7 @@ msgid "Git cryptographic signature formats" msgstr "Git kriptografik imza biçimleri" msgid "A Git Glossary" -msgstr "Git Kavram Dizini" +msgstr "Bir Git kavram dizini" msgid "Hooks used by Git" msgstr "Git tarafından kullanılan kancalar" @@ -14727,7 +14809,7 @@ msgid "The Git repository browser" msgstr "Git depo tarayıcısı" msgid "Map author/committer names and/or E-Mail addresses" -msgstr "Yazar/İşleyici adlarını ve/veya e-posta adreslerini eÅŸlemle" +msgstr "Yazar/İşleyici adını, e-posta adreslerini eÅŸlemle" msgid "Defining submodule properties" msgstr "Altmodül özelliklerini tanımlama" @@ -14763,10 +14845,10 @@ msgid "Mounting one repository inside another" msgstr "Bir depoyu bir baÅŸkasının içine baÄŸlama" msgid "A tutorial introduction to Git" -msgstr "Git'e GiriÅŸ" +msgstr "Git'e giriÅŸ için bir öğretici" msgid "A tutorial introduction to Git: part two" -msgstr "Git'e GiriÅŸ: Bölüm 2" +msgstr "Git'e giriÅŸ için bir öğretici: Bölüm 2" msgid "Git web interface (web frontend to Git repositories)" msgstr "Git web arabirimi (Git depoları için web ön ucu)" @@ -16858,12 +16940,10 @@ msgid "" msgstr "" "git [-v | --version] [-h | --help] [-C <yol>] [-c <ad>=<deÄŸer>]\n" " [--exec-path[=<yol>]] [--html-path] [--man-path] [--info-path]\n" -" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-" -"lazy-fetch]\n" -" [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n" -" [--work-tree=<path>] [--namespace=<ad>] [--config-env=<ad>=<çevre-" -"deÄŸiÅŸkeni>]\n" -" <komut> [<argümanlar>]" +" [-p | --paginate | -P | --no-pager] [--no-replace-objects]\n" +" [--no-lazy-fetch] [--no-optional-locks] [--no-advice] [--bare]\n" +" [--git-dir=<yol>] [--work-tree=<yol>] [--namespace=<ad>]\n" +" [--config-env=<ad>=<çevre-deÄŸiÅŸkeni>] <komut> [<argümanlar>]" msgid "" "'git help -a' and 'git help -g' list available subcommands and some\n" @@ -17221,6 +17301,10 @@ msgid "Unknown value for http.proactiveauth" msgstr "http.proactiveauth için bilinmeyen deÄŸer" #, c-format +msgid "failed to parse %s" +msgstr "%s ayrıştırılamadı" + +#, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Desteklenmeyen SSL arka ucu '%s'. Desteklenen SSL arka uçları:" @@ -17410,6 +17494,10 @@ msgid "invalid marker-size '%s', expecting an integer" msgstr "geçersiz imleyici boyutu '%s', bir tamsayı bekleniyor" #, c-format +msgid "Could not parse object '%s'" +msgstr "'%s' nesnesi ayrıştırılamadı" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "%s altmodülü birleÅŸtirilemedi (çıkış yapılmadı)" @@ -17654,268 +17742,6 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "ÅŸu aÄŸaçlar için birleÅŸtirme bilgisi toplama baÅŸarısız: %s, %s, %s" -msgid "(bad commit)\n" -msgstr "(hatalı iÅŸleme)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "" -"add_cacheinfo '%s' yolu için baÅŸarısız oldu; birleÅŸtirme iptal ediliyor." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "add_cacheinfo '%s' yolu için yenilenemedi; birleÅŸtirme iptal ediliyor." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "'%s'%s yolu oluÅŸturulamadı" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Altdizine yer açmak için %s kaldırılıyor\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": bir D/F çakışması olabilir mi?" - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "'%s' konumundaki izlenmeyen dosyayı kaybetme reddediliyor" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "%s '%s' için ikili nesne bekleniyordu" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "'%s' açılamadı: %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "'%s' için sembolik baÄŸ oluÅŸturulamadı: %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "ÅŸununla ne yapılacağı bilinmiyor: %06o %s '%s'" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "%s altmodülü birleÅŸtirilemedi (depo hasarlı)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "%s altmodülü ÅŸu iÅŸlemeye ileri sarılıyor:" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "%s altmodülü ileri sarılıyor" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"%s altmodülü birleÅŸtirilemedi (iÅŸlemeleri takip eden birleÅŸtirme bulunamadı)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "%s altmodülü birleÅŸtirilemedi (ileri sarım deÄŸil)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Åžu altmodül için olası bir birleÅŸtirme çözümü bulundu:\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 "" -"EÄŸer bu doÄŸruysa yalnızca indekse ekleyin, örneÄŸin:\n" -"\n" -"\tgit update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"komutu bu öneriyi kabul edecektir.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "%s altmodülü birleÅŸtirilemedi (birden çok birleÅŸtirme bulundu)" - -msgid "failed to execute internal merge" -msgstr "iç birleÅŸtirme yürütülemedi" - -#, c-format -msgid "unable to add %s to database" -msgstr "%s veritabanına eklenemiyor" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "" -"Hata: %s konumundaki izlenmeyen dosyayı kaybetme reddediliyor, bunun yerine " -"%s konumuna yazılacak." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"ÇAKIÅžMA (%s/silme): %s silindi (%s içinde) ve %s (%s içinde). %s (%s) sürümü " -"aÄŸaçta bırakıldı." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"ÇAKIÅžMA (%s/silme): %s silindi (%s içinde) ve %s ÅŸuraya: %s (%s içinde). %s " -"(%s) sürümü aÄŸaçta bırakıldı." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"ÇAKIÅžMA (%s/silme): %s silindi (%s içinde) ve %s (%s içinde). %s (%s) sürümü " -"aÄŸaçta %s konumunda bırakıldı." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"ÇAKIÅžMA (%s/silme): %s silindi (%s içinde) ve %s ÅŸuraya: %s (%s içinde). %s " -"(%s) sürümü aÄŸaçta %s konumunda bırakıldı." - -msgid "rename" -msgstr "yeniden adlandır" - -msgid "renamed" -msgstr "yeniden adlandırıldı" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "%s konumundaki kirli dosyayı kaybetme reddediliyor" - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "" -"Engel olduÄŸu halde %s konumundaki izlenmeyen dosyayı kaybetme reddediliyor." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"ÇAKIÅžMA (yeniden adlandır/ekle): %s->%s olarak adlandırıldı (%s içinde). %s " -"eklendi (%s içinde)" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s bir dizin (%s içinde), bunun yerine %s olarak ekleniyor" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "" -"%s konumundaki izlenmeyen dosyayı kaybetme reddediliyor, bunun yerine %s " -"olarak ekleniyor" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"ÇAKIÅžMA (y. adlandır/y. adlandır): \"%s\"->\"%s\" olarak adlandır (\"%s\" " -"dalında), \"%s\"->\"%s\" olarak adlandır (\"%s\"%s içinde)" - -msgid " (left unresolved)" -msgstr " (çözülmeden bırakıldı)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"ÇAKIÅžMA (y. adlandır/y. adlandır): %s->%s olarak adlandır (%s içinde). %s-" -">%s olarak adlandır (%s içinde)" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"ÇAKIÅžMA: (dizin yeniden adlandırma ayrılması): %s ögesinin nereye " -"yerleÅŸtirileceÄŸi belirsiz; çünkü %s dizini birden çok baÅŸka dizine yeniden " -"adlandırılırken hiçbir hedef dosyaların büyük çoÄŸunluÄŸunu almadı." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"ÇAKIÅžMA (y. adlandır/y. adlandır): Dizini %s->%s olarak adlandır (%s " -"içinde). Dizini %s->%s olarak adlandır (%s içinde)" - -#, c-format -msgid "cannot read object %s" -msgstr "%s nesnesi okunamıyor" - -#, c-format -msgid "object %s is not a blob" -msgstr "%s nesnesi ikili bir nesne deÄŸil" - -msgid "modify" -msgstr "deÄŸiÅŸtir" - -msgid "modified" -msgstr "deÄŸiÅŸtirilmiÅŸ" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "%s atlandı (var olan ile aynı biçimde birleÅŸtirildi)" - -#, c-format -msgid "Adding as %s instead" -msgstr "Bunun yerine %s olarak ekleniyor" - -#, c-format -msgid "Removing %s" -msgstr "%s kaldırılıyor" - -msgid "file/directory" -msgstr "dosya/dizin" - -msgid "directory/file" -msgstr "dizin/dosya" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"ÇAKIÅžMA (%s): %s adıyla bir dizin var (%s içinde). %s, %s olarak ekleniyor" - -#, c-format -msgid "Adding %s" -msgstr "%s ekleniyor" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "ÇAKIÅžMA (ekle/ekle): %s içinde birleÅŸtirme çakışması" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "%s ve %s aÄŸaçlarının birleÅŸtirilmesi baÅŸarısız" - -msgid "Merging:" -msgstr "BirleÅŸtiriliyor:" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "%u ortak ata bulundu:" -msgstr[1] "%u ortak ata bulundu:" - -msgid "merge returned no commit" -msgstr "birleÅŸtirme herhangi bir iÅŸleme döndürmedi" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "'%s' nesnesi ayrıştırılamadı" - msgid "failed to read the cache" msgstr "önbellek okunamadı" @@ -17957,12 +17783,13 @@ msgstr "'%s', '%s' ile baÄŸlantılanamıyor" msgid "failed to clear multi-pack-index at %s" msgstr "multi-pack-index %s konumunda temizlenemedi" -msgid "cannot write incremental MIDX with bitmap" -msgstr "biteÅŸlem ile artımlı MIDX yazılamıyor" - msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "var olan multi-pack-index yok sayılıyor; saÄŸlama toplamı uyumsuzluÄŸu" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "MIDX %s için ters indeks yüklenemedi" + msgid "Adding packfiles to multi-pack-index" msgstr "Paket dosyaları multi-pack-index'e ekleniyor" @@ -18214,64 +18041,6 @@ 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" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "alternatif nesne yolu olaÄŸanlaÅŸtırılamıyor: %s" - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s: alternatif nesne depoları yok sayılıyor, iç içe geçme pek derin" - -msgid "unable to fdopen alternates lockfile" -msgstr "alternatifler kilit dosyası fdopen yapılamıyor" - -msgid "unable to read alternates file" -msgstr "alternatifler dosyası okunamıyor" - -msgid "unable to move new alternates file into place" -msgstr "yeni alternatifler dosyası yerine taşınamıyor" - -#, c-format -msgid "path '%s' does not exist" -msgstr "'%s' diye bir yol yok" - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "" -"BaÄŸlantı yapılmış çıkış olarak '%s' baÅŸvuru deposu henüz desteklenmiyor." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "BaÅŸvuru deposu '%s' yerel bir depo deÄŸil." - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "baÅŸvuru deposu '%s' sığ" - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "baÅŸvuru deposu '%s' aşılı" - -#, c-format -msgid "could not find object directory matching %s" -msgstr "'%s' ile eÅŸleÅŸen nesne dizini bulunamadı" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "alternatif baÅŸvurular ayrıştırılırken geçersiz satır: %s" - -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "%<PRIuMAX>, %<PRIuMAX> sınırı üzerinden mmap yapılmaya çalışılıyor" - -#, c-format -msgid "mmap failed%s" -msgstr "mmap baÅŸarısız%s" - -#, c-format msgid "object file %s is empty" msgstr "nesne dosyası %s boÅŸ" @@ -18307,18 +18076,6 @@ msgid "loose object %s (stored in %s) is corrupt" msgstr "%s gevÅŸek nesnesi (%s içinde depolanıyor) hasarlı" #, c-format -msgid "replacement %s not found for %s" -msgstr "%s yedeÄŸi %s için bulunamadı" - -#, c-format -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 open %s" msgstr "%s açılamıyor" @@ -18411,10 +18168,6 @@ msgid "%s: unsupported file type" msgstr "%s: desteklenmeyen dosya türü" #, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s geçerli bir '%s' nesnesi deÄŸil" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "%s için saÄŸlama uyuÅŸmazlığı (%s bekleniyordu)" @@ -18431,6 +18184,10 @@ msgid "unable to parse header of %s" msgstr "%s üstbilgisi ayrıştırılamıyor" #, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "%s ögesinin '%s' üstbilgisinden tür ayrıştırılamıyor" + +#, c-format msgid "unable to unpack contents of %s" msgstr "%s içeriÄŸi açılamıyor" @@ -18588,6 +18345,72 @@ msgid "invalid object name '%.*s'." msgstr "geçersiz nesne adı: '%.*s'." #, 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" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "alternatif nesne yolu olaÄŸanlaÅŸtırılamıyor: %s" + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s: alternatif nesne depoları yok sayılıyor, iç içe geçme pek derin" + +msgid "unable to fdopen alternates lockfile" +msgstr "alternatifler kilit dosyası fdopen yapılamıyor" + +msgid "unable to read alternates file" +msgstr "alternatifler dosyası okunamıyor" + +msgid "unable to move new alternates file into place" +msgstr "yeni alternatifler dosyası yerine taşınamıyor" + +#, c-format +msgid "path '%s' does not exist" +msgstr "'%s' diye bir yol yok" + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "" +"BaÄŸlantı yapılmış çıkış olarak '%s' baÅŸvuru deposu henüz desteklenmiyor." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "BaÅŸvuru deposu '%s' yerel bir depo deÄŸil." + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "baÅŸvuru deposu '%s' sığ" + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "baÅŸvuru deposu '%s' aşılı" + +#, c-format +msgid "could not find object directory matching %s" +msgstr "'%s' ile eÅŸleÅŸen nesne dizini bulunamadı" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "alternatif baÅŸvurular ayrıştırılırken geçersiz satır: %s" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "%s yedeÄŸi %s için bulunamadı" + +#, c-format +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 "%s is not a valid '%s' object" +msgstr "%s geçerli bir '%s' nesnesi deÄŸil" + +#, c-format msgid "invalid object type \"%s\"" msgstr "geçersiz nesne türü \"%s\"" @@ -18866,6 +18689,14 @@ msgid "%s isn't available" msgstr "%s kullanılabilir deÄŸil" #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "%s deÄŸeri, %s için, [%<PRIdMAX>, %<PRIdMAX>] eriminde deÄŸil" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s bir tamsayı bekliyor, isteÄŸe baÄŸlı k/m/g eki ile" + +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "%s negatif olmayan bir tamsayı bekliyor, isteÄŸe baÄŸlı k/m/g eki ile" @@ -19024,10 +18855,6 @@ msgid "bad boolean environment value '%s' for '%s'" msgstr "hatalı Boole çevre deÄŸeri '%s', '%s' için" #, c-format -msgid "failed to parse %s" -msgstr "%s ayrıştırılamadı" - -#, c-format msgid "failed to walk children of tree %s: not found" msgstr "%s aÄŸacının alt ögeleri yürütülemedi: bulunamadı" @@ -19186,8 +19013,12 @@ msgid "could not fetch %s from promisor remote" msgstr "vaatçi uzak konumundan %s getirilemedi" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "bilinen uzak konum adı '%s'; ancak url'si '%s'; '%s' olmalı" +msgid "no or empty URL advertised for remote '%s'" +msgstr "'%s' uzak konumu için olmayan veya boÅŸ URL saÄŸlandı" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "bilinen uzak konum adı '%s'; ancak URL'si '%s'; '%s' olmalı" #, c-format msgid "unknown '%s' value for '%s' config option" @@ -19953,6 +19784,10 @@ msgid "Checking references consistency" msgstr "BaÅŸvuruların tutarlılığı denetleniyor" #, c-format +msgid "unable to open '%s'" +msgstr "'%s' açılamıyor" + +#, c-format msgid "refname is dangerous: %s" msgstr "baÅŸvuru adı tehlikeli: %s" @@ -20020,10 +19855,6 @@ msgid "refname %s is a symbolic ref, copying it is not supported" msgstr "baÅŸvuru adı %s bir sembolik baÄŸ, onu kopyalamak desteklenmiyor" #, c-format -msgid "invalid refspec '%s'" -msgstr "geçersiz baÅŸvuru belirteci '%s'" - -#, c-format msgid "pattern '%s' has no '*'" msgstr "'%s' dizgisinde '*' yok" @@ -20568,8 +20399,8 @@ msgstr "gönüllü yazılma eklenemedi" msgid "could not set recommended config" msgstr "önerilen yapılandırma ayarlanamadı" -msgid "could not turn on maintenance" -msgstr "bakım ayarı açılamadı" +msgid "could not toggle maintenance" +msgstr "bakım devreye alınamadı/devreden çıkarılamadı" msgid "could not start the FSMonitor daemon" msgstr "FSMonitor ardalan süreci baÅŸlatılamadı" @@ -20615,12 +20446,15 @@ msgstr "'src' dizininde depo oluÅŸtur" msgid "specify if tags should be fetched during clone" msgstr "etiketlerin klonlama sırasında getirilip getirilmeyeceÄŸini belirt" +msgid "specify if background maintenance should be enabled" +msgstr "arka plan bakımı etkinleÅŸtirilmesi gerekirse belirt" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <ana-dal>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<listeleme>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<gönüllü-kayıt>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -20653,22 +20487,36 @@ msgid "could not configure for full clone" msgstr "tam klonlama için yapılandırılamadı" msgid "scalar diagnose [<enlistment>]" -msgstr "scalar diagnose [<gönüllükayıt>]" +msgstr "scalar diagnose [<gönüllü-kayıt>]" msgid "`scalar list` does not take arguments" msgstr "'scalar list' argüman almıyor" -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<gönüllükayıt>]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [<gönüllü-kayıt>]" msgid "reconfigure all registered enlistments" msgstr "tüm kaydı yapılmış gönüllü kayıtları yeniden yapılandır" -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all | <gönüllükayıt>]" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +msgid "signal how to adjust background maintenance" +msgstr "arka plan bakımının nasıl ayarlanacağını sinyalle" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)]\n" +" [--all | <gönüllü-kayıt>]" msgid "--all or <enlistment>, but not both" -msgstr "--all veya <gönüllükayıt>; ancak ikisi deÄŸil" +msgstr "--all veya <gönüllü-kayıt>; ancak ikisi deÄŸil" + +#, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "--maintenance seçeneÄŸi için bilinmeyen kip: %s" #, c-format msgid "could not remove stale scalar.repo '%s'" @@ -22095,6 +21943,9 @@ msgstr "her bir yinelemeden önce önbellek aÄŸacını temizle" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "önbellek aÄŸacındaki geçersizleÅŸtirilecek girdi sayısı (öntanımlı 0)" +msgid "the number of objects to write" +msgstr "yazılacak nesnelerin sayısı" + msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk <seçenekler> -- <revizyon-seçenekleri>" @@ -22862,6 +22713,14 @@ msgstr "geçerli çalışma dizini alınamıyor" msgid "unable to get random bytes" msgstr "rastgele baytlar alınamıyor" +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "%<PRIuMAX>, %<PRIuMAX> sınırı üzerinden mmap yapılmaya çalışılıyor" + +#, c-format +msgid "mmap failed%s" +msgstr "mmap baÅŸarısız%s" + msgid "Unmerged paths:" msgstr "BirleÅŸtirilmemiÅŸ yollar:" @@ -23596,6 +23455,13 @@ msgstr "" "yapın." #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook, Message-ID'yi ÅŸuna yeniden atadı: %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "Uyarı: Sunucu yanıtından Message-ID alınamadı.\n" + +#, perl-format msgid "Failed to send %s\n" msgstr "%s gönderilemedi\n" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: Git v2.46\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-03-09 15:40-0700\n" -"PO-Revision-Date: 2025-03-09 16:53-0700\n" +"POT-Creation-Date: 2025-06-07 16:24-0700\n" +"PO-Revision-Date: 2025-06-03 18:43-0700\n" "Last-Translator: Kateryna Golovanova <kate@kgthreads.com>\n" "Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n" "Language: uk\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" -"X-Generator: Poedit 3.5\n" +"X-Generator: Poedit 3.6\n" #, c-format msgid "Huh (%s)?" @@ -3304,11 +3304,8 @@ msgstr "можна вказати лише одну групову опцію" msgid "git cat-file <type> <object>" msgstr "git cat-file <тип> <об’єкт>" -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e | -p) <об’єкт>" - -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t | -s) [--allow-unknown-type] <об’єкт>" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <об’єкт>" msgid "" "git cat-file (--textconv | --filters)\n" @@ -3348,9 +3345,6 @@ msgstr "" msgid "show object size" msgstr "показати розмір об’єкта" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "дозволити -s та -t працювати з пошкодженими/зіпÑованими об’єктами" - msgid "use mail map file" msgstr "викориÑтовувати файл відповідноÑті поштових адреÑ" @@ -3406,6 +3400,13 @@ msgstr "blob|дерево" msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "викориÑтати <шлÑÑ…> Ð´Ð»Ñ (--textconv | --filters); не з \"batch\"" +msgid "objects filter only supported in batch mode" +msgstr "фільтр об’єктів підтримуєтьÑÑ Ð»Ð¸ÑˆÐµ в пакетному режимі" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "Ñ„Ñ–Ð»ÑŒÑ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±â€™Ñ”ÐºÑ‚Ñ–Ð² не підтримуєтьÑÑ: \"%s\"" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "\"%s=<%s>\" потребує \"%s\" або \"%s\"" @@ -5699,6 +5700,50 @@ msgstr "вказати ÑÑƒÑ„Ñ–ÐºÑ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ñƒ strftime Ð´Ð»Ñ Ð½Ð°Ð·Ð²Ð¸ Ñ„ msgid "specify the content of the diagnostic archive" msgstr "вказати вміÑÑ‚ архіву діагноÑтики" +#, c-format +msgid "unable to parse mode: %s" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ режим: %s" + +#, c-format +msgid "unable to parse object id: %s" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ ідентифікатор об’єкта: %s" + +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<опціі-різниці>]" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "нерозпізнаний аргумент: %s" + +msgid "working without -z is not supported" +msgstr "робота без -z не підтримуєтьÑÑ" + +msgid "pathspec arguments not supported" +msgstr "аргументи Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡Ð½Ð¸ÐºÐ° шлÑху не підтримуютьÑÑ" + +msgid "revision arguments not allowed" +msgstr "аргументи ревізії не дозволені" + +msgid "invalid raw diff input" +msgstr "невірне Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ñ€Ð¾Ð±Ð»ÐµÐ½Ð¾Ñ— різниці" + +msgid "tree objects not supported" +msgstr "об’єкти дерева не підтримуютьÑÑ" + +msgid "got EOF while reading path" +msgstr "отримано EOF під Ñ‡Ð°Ñ Ð·Ñ‡Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ»Ñху" + +msgid "got EOF while reading destination path" +msgstr "отримано EOF під Ñ‡Ð°Ñ Ð·Ñ‡Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ»Ñху призначеннÑ" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ оцінку перейменуваннÑ/копіюваннÑ: %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "невідомий ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ñ–Ð·Ð½Ð¸Ñ†Ñ–: %c" + msgid "--merge-base only works with two commits" msgstr "--merge-base працює лише з двома комітами" @@ -5839,6 +5884,9 @@ msgstr "показати Ð¿Ñ€Ð¾Ð³Ñ€ÐµÑ Ð¿Ñ–ÑÐ»Ñ <н> обʼєктів" msgid "select handling of signed tags" msgstr "вибрати обробку підпиÑаних тегів" +msgid "select handling of signed commits" +msgstr "вибрати обробку підпиÑаних комітів" + msgid "select handling of tags that tag filtered objects" msgstr "вибрати обробку тегів, Ñкими позначено відфільтровані обʼєкти" @@ -6488,10 +6536,6 @@ msgid "%s: object corrupt or missing: %s" msgstr "%s: об’єкт пошкоджений або відÑутній: %s" #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: об’єкт невідомого типу \"%s\": %s" - -#, c-format msgid "%s: object could not be parsed: %s" msgstr "%s: неможливо розібрати об’єкт: %s" @@ -6548,16 +6592,19 @@ msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ rev-index Ð´Ð»Ñ Ð¿Ð°ÐºÑƒÐ½Ðº msgid "invalid rev-index for pack '%s'" msgstr "неприпуÑтимий rev-index Ð´Ð»Ñ \"%s\"" +msgid "Checking ref database" +msgstr "Перевірка бази даних поÑилань" + 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>...]" +" [--[no-]name-objects] [--[no-]references] [<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] [<обʼєкт>...]" +" [--[no-]name-objects] [--[no-]references] [<об’єкт>...]" msgid "show unreachable objects" msgstr "показати недоÑÑжні об’єкти" @@ -6595,6 +6642,9 @@ msgstr "показувати прогреÑ" msgid "show verbose names for reachable objects" msgstr "показувати докладні назви Ð´Ð»Ñ Ð´Ð¾Ñтупних об’єктів" +msgid "check reference database consistency" +msgstr "перевірити базу даних поÑилань" + msgid "Checking objects" msgstr "Перевірка обʼєктів" @@ -7748,10 +7798,6 @@ msgstr "" "проÑтежити еволюцію діапазону Ñ€Ñдків <початок>,<кінець> або функції :<назва-" "функції> в <файлі>" -#, c-format -msgid "unrecognized argument: %s" -msgstr "нерозпізнаний аргумент: %s" - msgid "-L<range>:<file> cannot be used with pathspec" msgstr "-L<діапазон>:<файл> не можна викориÑтовувати з визначником шлÑху" @@ -8408,6 +8454,9 @@ msgstr "зробити лише тривіальне злиттÑ" msgid "also show informational/conflict messages" msgstr "також показувати інформаційні/конфліктні повідомленнÑ" +msgid "suppress all output; only exit status wanted" +msgstr "приховати веÑÑŒ вивід; потрібен лише ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð¸Ñ…Ð¾Ð´Ñƒ" + msgid "list filenames without modes/oids/stages" msgstr "вивеÑти назви файлів без режимів/oid/Ñтадій" @@ -8812,8 +8861,11 @@ msgstr "" "під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ¿Ð°ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð±Ð¸Ñ€Ð°Ñ‚Ð¸ пакувальні файли меншого розміру в партію, " "більшу за цей розмір" -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<опції>] <джерело>... <призначеннÑ>" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <джерело> <призначеннÑ>" + +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] <джерело>... <директоріÑ-призначеннÑ>" #, c-format msgid "Directory %s is in index and no submodule?" @@ -8884,6 +8936,11 @@ msgid "%s, source=%s, destination=%s" msgstr "%s, джерело=%s, призначеннÑ=%s" #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "" +"неможливо перенеÑти Ñк \"%s\", так Ñ– його батьківÑьку директорію \"%s\"" + +#, c-format msgid "Renaming %s to %s\n" msgstr "ÐŸÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ %s на %s\n" @@ -9809,6 +9866,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ доÑтуп до коміту %s" +#, c-format +msgid "invalid refspec '%s'" +msgstr "неприпуÑтимий визначник поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" + msgid "ignoring --verify-signatures for rebase" msgstr "Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ --verify-signatures Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ±Ð°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ" @@ -10175,7 +10236,7 @@ msgstr "" "\n" "а потім виконайте надÑиланнÑ, викориÑтовуючи назву віддаленого Ñховища\n" "\n" -" git push <ім'Ñ>\n" +" git push <імʼÑ>\n" msgid "--all can't be combined with refspecs" msgstr "--all не можна комбінувати з визначниками поÑилань" @@ -10792,6 +10853,9 @@ msgstr "" msgid "git reflog exists <ref>" msgstr "git reflog exists <поÑиланнÑ>" +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktree] | <поÑиланнÑ>...]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "неприпуÑтима позначка чаÑу \"%s\" передана до \"--%s\"" @@ -10840,8 +10904,8 @@ msgid "Marking reachable objects..." msgstr "ÐŸÐ¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾ÑÑжних обʼєктів..." #, c-format -msgid "%s points nowhere!" -msgstr "%s вказує в нікуди!" +msgid "reflog could not be found: '%s'" +msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ журнал поÑилань: \"%s\"" msgid "no reflog specified to delete" msgstr "не вказано журнал поÑилань Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ" @@ -10850,6 +10914,15 @@ msgstr "не вказано журнал поÑилань Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð msgid "invalid ref format: %s" msgstr "неприпуÑтимий формат поÑиланнÑ: %s" +msgid "drop the reflogs of all references" +msgstr "видалити журнали Ð´Ð»Ñ Ð²ÑÑ–Ñ… поÑилань" + +msgid "drop reflogs from the current worktree only" +msgstr "видалÑти журнали поÑилань лише з поточного робочого дерева" + +msgid "references specified along with --all" +msgstr "поÑиланнÑ, вказані разом з --all" + msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=<формат> [--no-reflog] [--dry-run]" @@ -11412,6 +11485,9 @@ msgstr "приблизна дата" msgid "with --cruft, expire objects older than this" msgstr "з --cruft видалити обʼєкти, Ñтаріші за цей термін" +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "з параметром --cruft, перепакувати лише марні пакунки, менші за цей розмір" + msgid "remove redundant packs, and run git-prune-packed" msgstr "видалити зайві пакунки Ñ– запуÑтити git-prune-packed" @@ -11890,6 +11966,9 @@ msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "" "неприпуÑтиме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ \"%s\": \"%s\", єдиним допуÑтимим форматом Ñ” \"%s\"" +msgid "-z option used with unsupported option" +msgstr "ÐžÐ¿Ñ†Ñ–Ñ -z викориÑтовуєтьÑÑ Ð· непідтримуваною опцією" + msgid "rev-list does not support display of notes" msgstr "rev-list не підтримує Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð¾Ñ‚Ð°Ñ‚Ð¾Ðº" @@ -13771,8 +13850,8 @@ msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]" msgstr "" "git update-ref [<опції>] <назва-поÑиланнÑ> <новий-oid> [<Ñтарий-oid>]" -msgid "git update-ref [<options>] --stdin [-z]" -msgstr "git update-ref [<опції>] --stdin [-z]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<опції>] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "видалити поÑиланнÑ" @@ -13786,6 +13865,9 @@ msgstr "stdin має аргументи, що закінчуютьÑÑ NUL" msgid "read updates from stdin" msgstr "читати Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð· stdin" +msgid "batch reference updates" +msgstr "пакетне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ñилань" + msgid "update the info files from scratch" msgstr "оновити інформаційні файли з чиÑтого аркуша" @@ -14475,6 +14557,9 @@ msgstr "Порівнює файли в робочому дереві та інд msgid "Compare a tree to the working tree or index" msgstr "ПорівнÑти дерево з робочим деревом або індекÑом" +msgid "Compare the content and mode of provided blob pairs" +msgstr "ПорівнÑйте вміÑÑ‚ Ñ– режим наданих blob пар" + msgid "Compares the content and mode of blobs found via two tree objects" msgstr "" "Порівнює вміÑÑ‚ та режим blob обʼєктів, знайдених у двох обʼєктах дерева" @@ -17376,6 +17461,10 @@ msgid "Unknown value for http.proactiveauth" msgstr "Ðевідоме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ http.proactiveauth" #, c-format +msgid "failed to parse %s" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ %s" + +#, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Ðепідтримуваний SSL обробник \"%s\". Підтримувані SSL обробники:" @@ -17565,6 +17654,10 @@ msgid "invalid marker-size '%s', expecting an integer" msgstr "неправильний розмір маркера \"%s\", очікуєтьÑÑ Ñ‡Ð¸Ñло" #, c-format +msgid "Could not parse object '%s'" +msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ обʼєкт \"%s\"" + +#, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Ðе вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (не активне)" @@ -17805,267 +17898,6 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "Ð·Ð±Ð¸Ñ€Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— про Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ вдалоÑÑ Ð´Ð»Ñ Ð´ÐµÑ€ÐµÐ² %s, %s, %s" -msgid "(bad commit)\n" -msgstr "(невірний коміт)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "невдала Ñпроба add_cacheinfo Ð´Ð»Ñ ÑˆÐ»Ñху \"%s\"; Ð¿ÐµÑ€ÐµÑ€Ð¸Ð²Ð°Ð½Ð½Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "" -"процеÑу add_cacheinfo не вдалоÑÑ Ð·Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑˆÐ»Ñху \"%s\"; " -"Ð¿ÐµÑ€ÐµÑ€Ð¸Ð²Ð°Ð½Ð½Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "не вдалоÑÑ Ñтворити шлÑÑ… \"%s\"%s" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ %s, щоб звільнити міÑце Ð´Ð»Ñ Ð¿Ñ–Ð´Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ñ–Ñ—\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": можливо, D/F конфлікт?" - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "відмовлено у втраті невідÑтежуваного файла \"%s\"" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "blob очікуєтьÑÑ Ð´Ð»Ñ %s \"%s\"" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ \"%s\": %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "не вдалоÑÑ Ð·Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ Ñимвольне поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "не знаю, що робити з %06o %s \"%s\"" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Ðе вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (Ñховище пошкоджено)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "ÐŸÐµÑ€ÐµÐ¼Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ %s вперед до наÑтупного коміту:" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "ÐŸÐµÑ€ÐµÐ¼Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ %s вперед" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ð°Ñтупних комітів не знайдено)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ñ‚Ð°Ñ‚Ð¸ вперед)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Знайдено можливе Ð²Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð½Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¼Ð¾Ð´ÑƒÐ»Ñ:\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" -"викориÑтавши:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"Ñкий прийме цю пропозицію.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (знайдено більше одного злиттÑ)" - -msgid "failed to execute internal merge" -msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ внутрішнє злиттÑ" - -#, c-format -msgid "unable to add %s to database" -msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %s до бази даних" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "" -"Помилка: відмовлено у втраті невідÑтежуваного файла %s; натоміÑть запиÑуємо " -"до %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"КОÐФЛІКТ (%s/видалено): %s видалено в %s та %s в %s. ВерÑÑ–ÑŽ %s з %s залишено " -"в дереві." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"КОÐФЛІКТ (%s/видалено): %s видалено в %s Ñ– %s в %s в %s. ВерÑÑ–ÑŽ %s з %s " -"залишено у дереві." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"КОÐФЛІКТ (%s/видалено): %s видалено в %s Ñ– %s в %s. ВерÑÑ–ÑŽ %s з %s залишено " -"у дереві в %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"КОÐФЛІКТ (%s/видалено): %s видалено в %s Ñ– %s в %s в %s. ВерÑÑ–ÑŽ %s з %s " -"залишено в дереві в %s." - -msgid "rename" -msgstr "перейменувати" - -msgid "renamed" -msgstr "перейменовано" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "Відмовлено у втраті брудного файла %s" - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "" -"Відмовлено у втраті невідÑтежуваного файла %s, не дивлÑчиÑÑŒ на те, що він " -"знаходитьÑÑ Ð½Ð° шлÑху." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"КОÐФЛІКТ (перейменовано/додано): перейменовано %s->%s в %s. Додано %s в %s" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s Ñ” директорією в %s, натоміÑть додаємо Ñк %s" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "Відмовлено у втраті невідÑтежуваного файла %s; натоміÑть додаємо Ñк %s" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"КОÐФЛІКТ (перейменовано/перейменовано): перейменовано \"%s\"->\"%s\" у гілці " -"\"%s\" перейменовано \"%s\"->\"%s\" у \"%s\"%s" - -msgid " (left unresolved)" -msgstr " (залишилоÑÑ Ð½ÐµÑ€Ð¾Ð·Ð²Ê¼Ñзаним)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"КОÐФЛІКТ (перейменовано/перейменовано): перейменовано %s->%s в %s. " -"Перейменовано %s->%s в %s" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"КОÐФЛІКТ (розбіжніÑть під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ñ–Ñ—): ÐеÑÑно, куди " -"поміÑтити %s, оÑкільки директорію %s було перейменовано в кілька інших " -"директорій, жодна з Ñких не отримала більшоÑті файлів." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"КОÐФЛІКТ (перейменовано/перейменовано): перейменовано директорію %s->%s в " -"%s. Перейменовано директорію %s->%s в %s" - -#, c-format -msgid "cannot read object %s" -msgstr "неможливо прочитати обʼєкт %s" - -#, c-format -msgid "object %s is not a blob" -msgstr "обʼєкт %s не Ñ” blob" - -msgid "modify" -msgstr "змінити" - -msgid "modified" -msgstr "змінено" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "Пропущено %s (злите - те Ñаме, що й Ñ–Ñнуюче)" - -#, c-format -msgid "Adding as %s instead" -msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñк %s заміÑть цього" - -#, c-format -msgid "Removing %s" -msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ %s" - -msgid "file/directory" -msgstr "файл/директоріÑ" - -msgid "directory/file" -msgstr "директоріÑ/файл" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "КОÐФЛІКТ (%s): в %s Ñ–Ñнує Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ñ–Ñ Ð· іменем %s. Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %s Ñк %s" - -#, c-format -msgid "Adding %s" -msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %s" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "КОÐФЛІКТ (додано/додано): Конфлікт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñƒ %s" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "не вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ дерева %s та %s" - -msgid "Merging:" -msgstr "ЗлиттÑ:" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "знайшли %u Ñпільного предка:" -msgstr[1] "знайшли %u Ñпільних предків:" -msgstr[2] "знайшли %u Ñпільних предків:" - -msgid "merge returned no commit" -msgstr "Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ повернуло коміт" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ обʼєкт \"%s\"" - msgid "failed to read the cache" msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ кеш" @@ -18107,13 +17939,14 @@ msgstr "не вдалоÑÑ Ð·Ð²Ê¼Ñзати \"%s\" з \"%s\"" msgid "failed to clear multi-pack-index at %s" msgstr "не вдалоÑÑ Ð¾Ñ‡Ð¸Ñтити multi-pack-index при %s" -msgid "cannot write incremental MIDX with bitmap" -msgstr "неможливо запиÑати інкрементний MIDX з bitmap" - msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "" "Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ñнуючого multi-pack-index; невідповідніÑть контрольних Ñум" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ зворотний Ñ–Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ MIDX %s" + msgid "Adding packfiles to multi-pack-index" msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÑ–Ð² до multi-pack-index" @@ -18370,65 +18203,6 @@ 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" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "не вдалоÑÑ Ð½Ð¾Ñ€Ð¼Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ шлÑÑ… запозиченого обʼєкта: %s" - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "" -"%s: Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ñ–Ñць Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¾Ð·Ð¸Ñ‡ÐµÐ½Ð¸Ñ… об’єктів, надто глибока " -"вкладеніÑть" - -msgid "unable to fdopen alternates lockfile" -msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ fdopen Ð´Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¾Ð·Ð¸Ñ‡ÐµÐ½Ð¸Ñ… обʼєктів" - -msgid "unable to read alternates file" -msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл запозичених обʼєктів" - -msgid "unable to move new alternates file into place" -msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñтити файл нових запозичених обʼєктів на міÑце" - -#, c-format -msgid "path '%s' does not exist" -msgstr "шлÑÑ… \"%s\" не Ñ–Ñнує" - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñховище \"%s\" Ñк повʼÑзане поки що не підтримуєтьÑÑ." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "Ñховище поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" не Ñ” локальним Ñховищем." - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "Ñховище поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" Ñ” неглибоким" - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "Ñховище поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" прищеплено" - -#, c-format -msgid "could not find object directory matching %s" -msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ директорію обʼєктів, що відповідає %s" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "неприпуÑтимий Ñ€Ñдок при розбиранні поÑилань запозичених обʼєктів: %s" - -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "Ñпроба виконати mmap %<PRIuMAX> за межею %<PRIuMAX>" - -#, c-format -msgid "mmap failed%s" -msgstr "Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ mmap не вдалаÑÑ%s" - -#, c-format msgid "object file %s is empty" msgstr "обʼєктний файл %s порожній" @@ -18464,18 +18238,6 @@ msgid "loose object %s (stored in %s) is corrupt" msgstr "вільний обʼєкт %s (що зберігаєтьÑÑ Ñƒ %s) пошкоджено" #, c-format -msgid "replacement %s not found for %s" -msgstr "заміна %s не знайдена Ð´Ð»Ñ %s" - -#, c-format -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 open %s" msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ %s" @@ -18568,10 +18330,6 @@ msgid "%s: unsupported file type" msgstr "%s: непідтримуваний тип файлу" #, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s не Ñ” допуÑтимим \"%s\" обʼєктом" - -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "невідповідніÑть хешу Ð´Ð»Ñ %s (очікувалоÑÑŒ %s)" @@ -18588,6 +18346,10 @@ msgid "unable to parse header of %s" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ заголовок %s" #, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ тип з заголовка \"%s\" в %s" + +#, c-format msgid "unable to unpack contents of %s" msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð°ÐºÑƒÐ²Ð°Ñ‚Ð¸ вміÑÑ‚ %s" @@ -18748,6 +18510,73 @@ msgid "invalid object name '%.*s'." msgstr "неприпуÑтима назва обʼєкта \"%.*s\"." #, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ñ–Ñ Ð¾Ð±â€™Ñ”ÐºÑ‚Ð° %s не Ñ–Ñнує; перевірте .git/objects/info/alternates" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "не вдалоÑÑ Ð½Ð¾Ñ€Ð¼Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ шлÑÑ… запозиченого обʼєкта: %s" + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "" +"%s: Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ñ–Ñць Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¾Ð·Ð¸Ñ‡ÐµÐ½Ð¸Ñ… об’єктів, надто глибока " +"вкладеніÑть" + +msgid "unable to fdopen alternates lockfile" +msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ fdopen Ð´Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¾Ð·Ð¸Ñ‡ÐµÐ½Ð¸Ñ… обʼєктів" + +msgid "unable to read alternates file" +msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл запозичених обʼєктів" + +msgid "unable to move new alternates file into place" +msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñтити файл нових запозичених обʼєктів на міÑце" + +#, c-format +msgid "path '%s' does not exist" +msgstr "шлÑÑ… \"%s\" не Ñ–Ñнує" + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñховище \"%s\" Ñк повʼÑзане поки що не підтримуєтьÑÑ." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "Ñховище поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" не Ñ” локальним Ñховищем." + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "Ñховище поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" Ñ” неглибоким" + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "Ñховище поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" прищеплено" + +#, c-format +msgid "could not find object directory matching %s" +msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ директорію обʼєктів, що відповідає %s" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "неприпуÑтимий Ñ€Ñдок при розбиранні поÑилань запозичених обʼєктів: %s" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "заміна %s не знайдена Ð´Ð»Ñ %s" + +#, c-format +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 "%s is not a valid '%s' object" +msgstr "%s не Ñ” допуÑтимим \"%s\" обʼєктом" + +#, c-format msgid "invalid object type \"%s\"" msgstr "неприпуÑтимий тип обʼєкту \"%s\"" @@ -19034,6 +18863,14 @@ msgid "%s isn't available" msgstr "%s недоÑтупний" #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ %s Ð´Ð»Ñ %s не в діапазоні [%<PRIdMAX>,%<PRIdMAX>]" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s очікує ціле Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð· необовʼÑзковим ÑуфікÑом k/m/g" + +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "%s очікує невід'ємне ціле Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð· опціональним ÑуфікÑом k/m/g" @@ -19193,10 +19030,6 @@ msgid "bad boolean environment value '%s' for '%s'" msgstr "невірне булеве Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¾Ñ‚Ð¾Ñ‡ÐµÐ½Ð½Ñ \"%s\" Ð´Ð»Ñ \"%s\"" #, c-format -msgid "failed to parse %s" -msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ %s" - -#, c-format msgid "failed to walk children of tree %s: not found" msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ð¹Ñ‚Ð¸ дочірні елементи дерева %s: не знайдено" @@ -19361,8 +19194,14 @@ msgid "could not fetch %s from promisor remote" msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ %s з віддаленого promisor" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "відоме віддалене Ñховище з імʼÑм \"%s\" має URL \"%s\" заміÑть \"%s\"" +msgid "no or empty URL advertised for remote '%s'" +msgstr "відÑутній або пуÑтий обіцÑний URL Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ \"%s\"" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "" +"відоме віддалене Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð· імʼÑм \"%s\", але з URL-адреÑою \"%s\" " +"заміÑть \"%s\"" #, c-format msgid "unknown '%s' value for '%s' config option" @@ -20128,6 +19967,10 @@ msgid "Checking references consistency" msgstr "Перевірка ÑÐ¿Ñ–Ð²Ð¿Ð°Ð´Ñ–Ð½Ð½Ñ Ð¿Ð¾Ñилань" #, c-format +msgid "unable to open '%s'" +msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ \"%s\"" + +#, c-format msgid "refname is dangerous: %s" msgstr "refname Ñ” небезпечним: %s" @@ -20201,10 +20044,6 @@ msgstr "" "назва поÑÐ¸Ð»Ð°Ð½Ð½Ñ %s Ñ” Ñимвольним поÑиланнÑм, ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñкого не підтримуєтьÑÑ" #, c-format -msgid "invalid refspec '%s'" -msgstr "неприпуÑтимий визначник поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\"" - -#, c-format msgid "pattern '%s' has no '*'" msgstr "шаблон \"%s\" не має \"*\"" @@ -20360,7 +20199,7 @@ msgstr "" #, c-format msgid "config remote shorthand cannot begin with '/': %s" -msgstr "Ñкорочене ім'Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ñ— конфігураціі не може починатиÑÑ Ð· \"/\": %s" +msgstr "Ñкорочене Ñ–Ð¼Ê¼Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ñ— конфігураціі не може починатиÑÑ Ð· \"/\": %s" msgid "more than one receivepack given, using the first" msgstr "надано більше одного пакунка Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ, викориÑтано перший" @@ -20766,8 +20605,8 @@ msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ кореневу директорію Ð msgid "could not set recommended config" msgstr "не вдалоÑÑ Ð²Ñтановити рекомендовану конфігурацію" -msgid "could not turn on maintenance" -msgstr "не вдалоÑÑ Ð²Ð²Ñ–Ð¼ÐºÐ½ÑƒÑ‚Ð¸ технічне обÑлуговуваннÑ" +msgid "could not toggle maintenance" +msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡Ð¸Ñ‚Ð¸ обÑлуговуваннÑ" msgid "could not start the FSMonitor daemon" msgstr "не вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити FSMonitor демон" @@ -20815,12 +20654,16 @@ msgstr "Ñтворити Ñховище в директорії \"src\"" msgid "specify if tags should be fetched during clone" msgstr "вказати, чи потрібно отримувати теги під Ñ‡Ð°Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ" +msgid "specify if background maintenance should be enabled" +msgstr "вказати, чи потрібно ввімкнути фонове обÑлуговуваннÑ" + msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" -"scalar clone [--single-branch] [--branch <головна-гілка>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <URL-адреÑа> [<коренева-директоріÑ-проекту>]" +"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<коренева-" +"директоріÑ-проекту>]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -20858,19 +20701,33 @@ msgstr "scalar diagnose [<коренева-директоріÑ-проекту>] msgid "`scalar list` does not take arguments" msgstr "\"scalar list\" не приймає аргументів" -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<коренева-директоріÑ-проекту>]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [<коренева-директоріÑ-проекту>]" msgid "reconfigure all registered enlistments" msgstr "переналаштувати вÑÑ– зареєÑтровані кореневі директорії проекту" -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all | <коренева-директоріÑ-проекту>]" +msgid "(enable|disable|keep)" +msgstr "(увімкнути|вимкнути|зберегти)" + +msgid "signal how to adjust background maintenance" +msgstr "повідомити про те, Ñк налаштувати фонове обÑлуговуваннÑ" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | <коренева-" +"директоріÑ-проекту>]" msgid "--all or <enlistment>, but not both" msgstr "--all або <коренева-директоріÑ-проекту>, але не обидва" #, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "невідомий режим Ð´Ð»Ñ Ð¾Ð¿Ñ†Ñ–Ñ— --maintenance: %s" + +#, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "неможливо видалити заÑтаріле scalar.repo \"%s\"" @@ -22323,6 +22180,9 @@ msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "" "кількіÑть запиÑів у дереві кешу, Ñкі потрібно анулювати (за замовчуваннÑм 0)" +msgid "the number of objects to write" +msgstr "кількіÑть об’єктів Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу" + msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk <опції> -- <опції-ревізії>." @@ -23105,6 +22965,14 @@ msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ поточну робочу Ð msgid "unable to get random bytes" msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ випадкові байти" +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "Ñпроба виконати mmap %<PRIuMAX> за межею %<PRIuMAX>" + +#, c-format +msgid "mmap failed%s" +msgstr "Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ mmap не вдалаÑÑ%s" + msgid "Unmerged paths:" msgstr "Ðе злиті шлÑхи:" @@ -23861,6 +23729,13 @@ msgstr "" "ÑкориÑтайтеÑÑŒ --smtp-debug." #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook перепризначив Message-ID на: %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "ПопередженнÑ: Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ Message-ID з відповіді Ñервера.\n" + +#, perl-format msgid "Failed to send %s\n" msgstr "Ðе вдалоÑÑ Ð½Ð°Ð´Ñ–Ñлати %s\n" diff --git a/po/zh_CN.po b/po/zh_CN.po index 5cde4011e7..139ae331dc 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -155,8 +155,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-03-09 20:34+0800\n" -"PO-Revision-Date: 2025-03-12 14:47+0800\n" +"POT-Creation-Date: 2025-06-08 20:30+0800\n" +"PO-Revision-Date: 2025-06-12 14:50+0800\n" "Last-Translator: Teng Long <dyroneteng@gmail.com>\n" "Language-Team: GitHub <https://github.com/dyrone/git/>\n" "Language: zh_CN\n" @@ -1075,10 +1075,9 @@ msgstr "未能识别的空白å—符忽略选项 '%s'" #: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c #: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c #: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c -#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-list.c -#: builtin/rev-parse.c builtin/show-branch.c builtin/stash.c -#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c -#: range-diff.c revision.c +#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-parse.c +#: builtin/show-branch.c builtin/stash.c builtin/submodule--helper.c +#: builtin/tag.c builtin/worktree.c parse-options.c range-diff.c revision.c #, c-format msgid "options '%s' and '%s' cannot be used together" msgstr "选项 '%s' å’Œ '%s' ä¸èƒ½åŒæ—¶ä½¿ç”¨" @@ -1965,7 +1964,7 @@ msgstr "æ— æ³•åœ¨æ²¡æœ‰ä»“åº“çš„æƒ…å†µä¸‹ä½¿ç”¨ --attr-source 或 GIT_ATTR_SOURC msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "错误的 --attr-source 或 GIT_ATTR_SOURCE" -#: attr.c read-cache.c +#: attr.c read-cache.c refs/packed-backend.c #, c-format msgid "unable to stat '%s'" msgstr "æ— æ³•å¯¹ %s 执行 stat" @@ -2777,7 +2776,7 @@ msgstr "ä»¥äº¤äº’å¼æ–¹å¼è¿è¡Œ" msgid "bypass pre-applypatch and applypatch-msg hooks" msgstr "绕过 pre-applypatch å’Œ applypatch-msg é’©å" -#: builtin/am.c +#: builtin/am.c builtin/cat-file.c msgid "historical option -- no-op" msgstr "è€çš„傿•° —— æ— ä½œç”¨" @@ -4084,7 +4083,7 @@ msgstr "需è¦ä¸€ä¸ªä»“库æ¥è§£å¼€å½’档包。" msgid "Unbundling objects" msgstr "解包对象ä¸" -#: builtin/cat-file.c merge-recursive.c +#: builtin/cat-file.c #, c-format msgid "cannot read object %s '%s'" msgstr "ä¸èƒ½è¯»å–对象 %s '%s'" @@ -4121,12 +4120,8 @@ msgid "git cat-file <type> <object>" msgstr "git cat-file <类型> <对象>" #: builtin/cat-file.c -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e | -p) <对象>" - -#: builtin/cat-file.c -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t | -s) [--allow-unknown-type] <对象>" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <对象>" #: builtin/cat-file.c msgid "" @@ -4172,10 +4167,6 @@ msgstr "显示对象的类型('blob'ã€'tree'ã€'commit'ã€'tag'……其ä¸ä¹ msgid "show object size" msgstr "显示对象大å°" -#: builtin/cat-file.c -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "å…许 -s å’Œ -t 对æŸå的对象生效" - #: builtin/cat-file.c builtin/log.c msgid "use mail map file" msgstr "ä½¿ç”¨é‚®ä»¶æ˜ å°„æ–‡ä»¶" @@ -4247,6 +4238,15 @@ msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "(--textconv | --filters) 使用 <路径>ï¼›è€Œä¸æ˜¯ 'batch'" #: builtin/cat-file.c +msgid "objects filter only supported in batch mode" +msgstr "å¯¹è±¡è¿‡æ»¤å™¨åªæ”¯æŒæ‰¹å¤„ç†æ¨¡å¼" + +#: builtin/cat-file.c +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "䏿”¯æŒå¯¹è±¡è¿‡æ»¤å™¨ï¼š'%s'" + +#: builtin/cat-file.c #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "'%s=<%s>' éœ€è¦ '%s' 或 '%s'" @@ -5952,7 +5952,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" @@ -7038,6 +7038,64 @@ msgstr "指定文件的 strftime æ ¼å¼åŽç¼€" msgid "specify the content of the diagnostic archive" msgstr "指定诊æ–ä¿¡æ¯å½’档包的内容" +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse mode: %s" +msgstr "ä¸èƒ½è§£æžæ¨¡å¼ï¼š%s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse object id: %s" +msgstr "ä¸èƒ½è§£æžå¯¹è±¡ID:%s" + +#: builtin/diff-pairs.c +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<差异选项>]" + +#: builtin/diff-pairs.c builtin/log.c builtin/replay.c builtin/shortlog.c +#: bundle.c +#, c-format +msgid "unrecognized argument: %s" +msgstr "æœªè¯†åˆ«çš„å‚æ•°ï¼š%s" + +#: builtin/diff-pairs.c +msgid "working without -z is not supported" +msgstr "䏿”¯æŒåœ¨ä¸å¸¦ -z 傿•°çš„æƒ…况下工作" + +#: builtin/diff-pairs.c +msgid "pathspec arguments not supported" +msgstr "䏿”¯æŒè·¯å¾„è§„æ ¼å‚æ•°" + +#: builtin/diff-pairs.c +msgid "revision arguments not allowed" +msgstr "䏿”¯æŒç‰ˆæœ¬å‚æ•°" + +#: builtin/diff-pairs.c +msgid "invalid raw diff input" +msgstr "æ— æ•ˆçš„åŽŸå§‹ diff 输入" + +#: builtin/diff-pairs.c +msgid "tree objects not supported" +msgstr "䏿”¯æŒæ ‘对象" + +#: builtin/diff-pairs.c +msgid "got EOF while reading path" +msgstr "读å–路径时é‡åˆ°æ–‡ä»¶ç»“æŸ" + +#: builtin/diff-pairs.c +msgid "got EOF while reading destination path" +msgstr "读å–ç›®æ ‡è·¯å¾„æ—¶é‡åˆ°æ–‡ä»¶ç»“æŸ" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "æ— æ³•è§£æžé‡å‘½å/å¤åˆ¶åˆ†æ•°ï¼š%s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unknown diff status: %c" +msgstr "未知的差异状æ€ï¼š%c" + #: builtin/diff-tree.c msgid "--merge-base only works with two commits" msgstr "--merge-base 仅适用于两个æäº¤" @@ -7215,6 +7273,10 @@ msgid "select handling of signed tags" msgstr "选择如何处ç†ç¾åæ ‡ç¾" #: builtin/fast-export.c +msgid "select handling of signed commits" +msgstr "选择如何处ç†å·²ç¾åæäº¤" + +#: builtin/fast-export.c msgid "select handling of tags that tag filtered objects" msgstr "é€‰æ‹©å½“æ ‡ç¾æŒ‡å‘è¢«è¿‡æ»¤å¯¹è±¡æ—¶è¯¥æ ‡ç¾çš„å¤„ç†æ–¹å¼" @@ -7474,7 +7536,7 @@ msgstr "选项 \"%s\" 的值 \"%s\" 对于 %s æ˜¯æ— æ•ˆçš„" msgid "option \"%s\" is ignored for %s" msgstr "选项 \"%s\" 为 %s 所忽略" -#: builtin/fetch.c object-file.c +#: builtin/fetch.c object-store.c #, c-format msgid "%s is not a valid object" msgstr "%s 䏿˜¯ä¸€ä¸ªæœ‰æ•ˆçš„对象" @@ -8013,11 +8075,6 @@ msgstr "%s:对象æŸå或丢失:%s" #: builtin/fsck.c #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s:对象有未知的类型 '%s': %s" - -#: builtin/fsck.c -#, c-format msgid "%s: object could not be parsed: %s" msgstr "%s:ä¸èƒ½è§£æžå¯¹è±¡ï¼š%s" @@ -8089,16 +8146,20 @@ msgid "invalid rev-index for pack '%s'" msgstr "包文件 '%s' çš„åå‘ç´¢å¼•æ–‡ä»¶æ— æ•ˆ" #: builtin/fsck.c +msgid "Checking ref database" +msgstr "æ£åœ¨æ£€æŸ¥å¼•用数æ®åº“" + +#: builtin/fsck.c 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>...]" +" [--[no-]name-objects] [--[no-]references] [<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] [<对象>...]" +" [--[no-]name-objects] [--[no-]references] [<对象>...]" #: builtin/fsck.c msgid "show unreachable objects" @@ -8148,6 +8209,10 @@ msgstr "显示进度" msgid "show verbose names for reachable objects" msgstr "显示å¯è¾¾å¯¹è±¡çš„详细åç§°" +#: builtin/fsck.c +msgid "check reference database consistency" +msgstr "检查引用数æ®åº“一致性" + #: builtin/fsck.c builtin/index-pack.c msgid "Checking objects" msgstr "æ£åœ¨æ£€æŸ¥å¯¹è±¡" @@ -9580,11 +9645,6 @@ msgid "" "<file>" msgstr "跟踪 <文件> ä¸ <开始>,<结æŸ> 范围内的行或函数 :<函数å> 的演å˜" -#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c -#, c-format -msgid "unrecognized argument: %s" -msgstr "æœªèƒ½è¯†åˆ«çš„å‚æ•°ï¼š%s" - #: builtin/log.c msgid "-L<range>:<file> cannot be used with pathspec" msgstr "-L<范围>:<文件> ä¸èƒ½å’Œè·¯å¾„表达å¼å…±ç”¨" @@ -9602,7 +9662,7 @@ msgstr "git show %s: æŸå的文件" #: builtin/log.c #, c-format msgid "could not read object %s" -msgstr "ä¸èƒ½è¯»å–对象 %s" +msgstr "æ— æ³•è¯»å–对象 %s" #: builtin/log.c #, c-format @@ -10420,6 +10480,10 @@ msgid "also show informational/conflict messages" msgstr "åŒæ—¶æ˜¾ç¤ºé¢å¤–ä¿¡æ¯/å†²çªæ¶ˆæ¯" #: builtin/merge-tree.c +msgid "suppress all output; only exit status wanted" +msgstr "抑制所有输出;åªä¿ç•™é€€å‡ºçжæ€" + +#: builtin/merge-tree.c msgid "list filenames without modes/oids/stages" msgstr "列出没有模å¼/对象 ID/æš‚å˜çš„æ–‡ä»¶å" @@ -10580,7 +10644,7 @@ msgstr "è¯»å–æ ‘失败" msgid "Already up to date. (nothing to squash)" msgstr "å·²ç»æ˜¯æœ€æ–°çš„ã€‚ï¼ˆæ— å¯æŒ¤åŽ‹ï¼‰" -#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c msgid "Already up to date." msgstr "å·²ç»æ˜¯æœ€æ–°çš„。" @@ -10604,7 +10668,7 @@ msgstr "'%s' 没有指å‘一个æäº¤" msgid "Bad branch.%s.mergeoptions string: %s" msgstr "åçš„ branch.%s.mergeoptions å—符串:%s" -#: builtin/merge.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c msgid "Unable to write index." msgstr "ä¸èƒ½å†™å…¥ç´¢å¼•。" @@ -10760,7 +10824,7 @@ msgstr "åªèƒ½å°†ä¸€ä¸ªæäº¤åˆå¹¶åˆ°ç©ºåˆ†æ”¯ä¸Š" msgid "Updating %s..%s\n" msgstr "æ›´æ–° %s..%s\n" -#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c #, c-format msgid "" "Your local changes to the following files would be overwritten by merge:\n" @@ -10922,8 +10986,12 @@ msgid "" msgstr "在 repack 期间,将较å°å°ºå¯¸çš„包文件收集到大于æ¤å¤§å°çš„æ‰¹æ¬¡ä¸" #: builtin/mv.c -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<选项>] <æº>... <ç›®æ ‡>" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <æº> <ç›®æ ‡>" + +#: builtin/mv.c +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] <æº>... <ç›®æ ‡ç›®å½•>" #: builtin/mv.c #, c-format @@ -11013,6 +11081,11 @@ msgstr "%s,æº=%sï¼Œç›®æ ‡=%s" #: builtin/mv.c #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "ä¸èƒ½åŒæ—¶ç§»åЍ '%s' åŠå…¶çˆ¶ç›®å½• '%s'" + +#: builtin/mv.c +#, c-format msgid "Renaming %s to %s\n" msgstr "é‡å‘½å %s 至 %s\n" @@ -12151,6 +12224,11 @@ msgstr "" msgid "unable to access commit %s" msgstr "æ— æ³•è®¿é—®æäº¤ %s" +#: builtin/pull.c refspec.c +#, c-format +msgid "invalid refspec '%s'" +msgstr "æ— æ•ˆçš„å¼•ç”¨è§„æ ¼ï¼š'%s'" + #: builtin/pull.c msgid "ignoring --verify-signatures for rebase" msgstr "为å˜åŸºæ“作忽略 --verify-signatures" @@ -13255,6 +13333,10 @@ msgid "git reflog exists <ref>" msgstr "git reflog exists <引用>" #: builtin/reflog.c +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktree] | <引用>...]" + +#: builtin/reflog.c #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "ç»™ '--%2$s' 的时间戳 '%1$s' æ— æ•ˆ" @@ -13314,8 +13396,8 @@ msgstr "æ£åœ¨æ ‡è®°å¯è¾¾å¯¹è±¡..." #: builtin/reflog.c #, c-format -msgid "%s points nowhere!" -msgstr "%s 指å‘ä¸å˜åœ¨ï¼" +msgid "reflog could not be found: '%s'" +msgstr "æ— æ³•æ‰¾åˆ°å¼•ç”¨æ—¥å¿—ï¼š'%s'" #: builtin/reflog.c msgid "no reflog specified to delete" @@ -13326,6 +13408,18 @@ msgstr "未指定è¦åˆ 除的引用日志" msgid "invalid ref format: %s" msgstr "æ— æ•ˆçš„å¼•ç”¨æ ¼å¼ï¼š%s" +#: builtin/reflog.c +msgid "drop the reflogs of all references" +msgstr "丢弃所有引用的引用日志" + +#: builtin/reflog.c +msgid "drop reflogs from the current worktree only" +msgstr "仅从当å‰å·¥ä½œåŒºä¸ä¸¢å¼ƒå¼•用日志" + +#: builtin/reflog.c +msgid "references specified along with --all" +msgstr "--all 选项ä¸èƒ½ä¸Žå…·ä½“å¼•ç”¨åŒæ—¶ä½¿ç”¨" + #: builtin/refs.c msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=<æ ¼å¼> [--no-reflog] [--dry-run]" @@ -14006,6 +14100,10 @@ msgid "with --cruft, expire objects older than this" msgstr "使用 --cruft,使早于给定时间的对象过期" #: builtin/repack.c +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "使用 --cruft æ—¶ï¼Œä»…é‡æ–°æ‰“包å°äºŽæ¤å¤§å°çš„废弃包文件" + +#: builtin/repack.c msgid "remove redundant packs, and run git-prune-packed" msgstr "åˆ é™¤å¤šä½™çš„åŒ…ï¼Œè¿è¡Œ git-prune-packed" @@ -14597,6 +14695,10 @@ msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "'%s' çš„å€¼æ— æ•ˆï¼š'%s',唯一å…è®¸çš„æ ¼å¼æ˜¯ '%s'" #: builtin/rev-list.c +msgid "-z option used with unsupported option" +msgstr "-z é€‰é¡¹ä¸Žä¸æ”¯æŒçš„é€‰é¡¹åŒæ—¶ä½¿ç”¨" + +#: builtin/rev-list.c msgid "rev-list does not support display of notes" msgstr "rev-list 䏿”¯æŒæ˜¾ç¤ºæ³¨è§£" @@ -16865,8 +16967,8 @@ 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]" -msgstr "git update-ref [<选项>] --stdin [-z]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<选项>] --stdin [-z] [--batch-updates]" #: builtin/update-ref.c msgid "delete the reference" @@ -16884,6 +16986,10 @@ msgstr "æ ‡å‡†è¾“å…¥æœ‰ä»¥ NUL å—符终æ¢çš„傿•°" msgid "read updates from stdin" msgstr "ä»Žæ ‡å‡†è¾“å…¥è¯»å–æ›´æ–°" +#: builtin/update-ref.c +msgid "batch reference updates" +msgstr "批é‡å¼•用更新" + #: builtin/update-server-info.c msgid "update the info files from scratch" msgstr "从头开始更新文件信æ¯" @@ -17730,6 +17836,10 @@ msgid "Compare a tree to the working tree or index" msgstr "å°†ä¸€ä¸ªæ ‘å’Œå·¥ä½œåŒºæˆ–ç´¢å¼•åšæ¯”较" #: command-list.h +msgid "Compare the content and mode of provided blob pairs" +msgstr "比较æä¾›çš„ blob 对的内容和模å¼" + +#: command-list.h msgid "Compares the content and mode of blobs found via two tree objects" msgstr "æ¯”è¾ƒä¸¤ä¸ªæ ‘å¯¹è±¡çš„æ–‡ä»¶å†…å®¹å’Œæ¨¡å¼" @@ -19861,7 +19971,7 @@ msgstr "color-moved-ws:allow-indentation-change ä¸èƒ½ä¸Žå…¶å®ƒç©ºç™½å—符模 msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "é…ç½®å˜é‡ 'diff.submodule' 未知的å–值:'%s'" -#: diff.c merge-recursive.c transport.c +#: diff.c merge-ort.c transport.c #, c-format msgid "unknown value for config '%s': %s" msgstr "é…ç½® '%s' 未知的å–值:%s" @@ -21288,6 +21398,11 @@ msgstr "䏿”¯æŒå§”æ‰˜æŽ§åˆ¶ï¼Œå› ä¸º cURL < 7.22.0" msgid "Unknown value for http.proactiveauth" msgstr "http.proactiveauth 为未知å–值" +#: http.c parse.c +#, c-format +msgid "failed to parse %s" +msgstr "æ— æ³•è§£æž %s" + #: http.c #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" @@ -21512,7 +21627,12 @@ msgstr "æ— æ³•æ ¼å¼åŒ–消æ¯ï¼š%s" msgid "invalid marker-size '%s', expecting an integer" msgstr "æ— æ•ˆçš„æ ‡è®°å¤§å° '%s',应为一个整数" -#: merge-ort.c merge-recursive.c +#: merge-ort-wrappers.c +#, c-format +msgid "Could not parse object '%s'" +msgstr "ä¸èƒ½è§£æžå¯¹è±¡ '%s'" + +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "æ— æ³•åˆå¹¶å模组 %s (没有检出)" @@ -21522,7 +21642,7 @@ msgstr "æ— æ³•åˆå¹¶å模组 %s (没有检出)" msgid "Failed to merge submodule %s (no merge base)" msgstr "æ— æ³•åˆå¹¶å模组 %s (没有åˆå¹¶åŸºçº¿ï¼‰" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (commits not present)" msgstr "æ— æ³•åˆå¹¶å模组 %s(æäº¤ä¸å˜åœ¨ï¼‰" @@ -21532,7 +21652,7 @@ msgstr "æ— æ³•åˆå¹¶å模组 %s(æäº¤ä¸å˜åœ¨ï¼‰" msgid "error: failed to merge submodule %s (repository corrupt)" msgstr "é”™è¯¯ï¼šæ— æ³•åˆå¹¶å模组 %s(仓库æŸå)" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "æ— æ³•åˆå¹¶å模组 %s (æäº¤æœªè·Ÿéšåˆå¹¶åŸºçº¿ï¼‰" @@ -21572,12 +21692,12 @@ msgstr "é”™è¯¯ï¼šæ— æ³•ä¸º %s 执行内部åˆå¹¶" msgid "error: unable to add %s to database" msgstr "错误:ä¸èƒ½æ·»åŠ %s 至对象库" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Auto-merging %s" msgstr "自动åˆå¹¶ %s" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (implicit dir rename): Existing file/dir at %s in the way of " @@ -21586,7 +21706,7 @@ msgstr "" "冲çªï¼ˆéšå¼ç›®å½•é‡å‘½å):处于éšå¼ç›®å½•é‡å‘½åçš„çŽ°å˜æ–‡ä»¶/目录 %s,将以下路径放" "在:%s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (implicit dir rename): Cannot map more than one path to %s; " @@ -21605,14 +21725,14 @@ msgstr "" "冲çªï¼ˆåˆ†å‰²çš„目录é‡å‘½åï¼‰ï¼šä¸æ¸…楚é‡å‘½å %s åˆ°å“ªé‡Œï¼Œå› ä¸ºå®ƒè¢«é‡å‘½å到多个其他目" "录ä¸ï¼Œæ²¡æœ‰ä¸€ä¸ªç›®æ ‡ç›®å½•ä¸åŒ…å«å¤šæ•°æ–‡ä»¶ã€‚" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was " "renamed." msgstr "è¦å‘Šï¼šé¿å…应用 %s -> %s çš„é‡å‘½å到 %sï¼Œå› ä¸º %s 本身已被é‡å‘½å。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "Path updated: %s added in %s inside a directory that was renamed in %s; " @@ -21620,7 +21740,7 @@ msgid "" msgstr "" "路径已更新:%s æ·»åŠ åˆ° %s,ä½äºŽä¸€ä¸ªè¢«é‡å‘½å到 %s 的目录ä¸ï¼Œå°†å…¶ç§»åŠ¨åˆ° %s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "Path updated: %s renamed to %s in %s, inside a directory that was renamed in " @@ -21629,7 +21749,7 @@ msgstr "" "路径已更新:%1$s é‡å‘½å为 %3$s ä¸çš„ %2$s,而该目录被é‡å‘½å到 %4$s ä¸ï¼Œå°†å…¶ç§»" "动到 %5$s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (file location): %s added in %s inside a directory that was renamed " @@ -21638,7 +21758,7 @@ msgstr "" "冲çªï¼ˆæ–‡ä»¶ä½ç½®ï¼‰ï¼š%s æ·»åŠ åˆ° %s,ä½äºŽä¸€ä¸ªè¢«é‡å‘½å为 %s 的目录ä¸ï¼Œå»ºè®®å°†å…¶ç§»åЍ" "到 %s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (file location): %s renamed to %s in %s, inside a directory that " @@ -21703,19 +21823,19 @@ msgstr "" "冲çªï¼ˆä¸åŒç±»åž‹ï¼‰ï¼š%s 在两侧有ä¸åŒçš„类型,将其ä¸ä¹‹ä¸€é‡å‘½å以便它们能记录在ä¸åŒ" "ä½ç½®ã€‚" -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "content" msgstr "内容" -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "add/add" msgstr "æ·»åŠ /æ·»åŠ " -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "submodule" msgstr "忍¡ç»„" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "CONFLICT (%s): Merge conflict in %s" msgstr "冲çªï¼ˆ%s):åˆå¹¶å†²çªäºŽ %s" @@ -21777,312 +21897,6 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "æ— æ³•æ”¶é›†æ ‘ %sã€%sã€%s çš„åˆå¹¶ä¿¡æ¯" -#: merge-recursive.c -msgid "(bad commit)\n" -msgstr "(åæäº¤ï¼‰\n" - -#: merge-recursive.c -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "add_cacheinfo 对路径 '%s' 执行失败,åˆå¹¶ç»ˆæ¢ã€‚" - -#: merge-recursive.c -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "add_cacheinfo æ— æ³•åˆ·æ–°è·¯å¾„ '%s',åˆå¹¶ç»ˆæ¢ã€‚" - -#: merge-recursive.c -#, c-format -msgid "failed to create path '%s'%s" -msgstr "æ— æ³•åˆ›å»ºè·¯å¾„ '%s'%s" - -#: merge-recursive.c -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "åˆ é™¤ %s 以便为å目录留出空间\n" - -#: merge-recursive.c -msgid ": perhaps a D/F conflict?" -msgstr ":å¯èƒ½æ˜¯ä¸€ä¸ªç›®å½•/文件冲çªï¼Ÿ" - -#: merge-recursive.c -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "æ‹’ç»ä¸¢å¼ƒ '%s' ä¸çš„æœªè·Ÿè¸ªæ–‡ä»¶" - -#: merge-recursive.c -#, c-format -msgid "blob expected for %s '%s'" -msgstr "%s '%s' 应为数æ®å¯¹è±¡" - -#: merge-recursive.c -#, c-format -msgid "failed to open '%s': %s" -msgstr "æ— æ³•æ‰“å¼€ '%s':%s" - -#: merge-recursive.c -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "æ— æ³•åˆ›å»ºç¬¦å·é“¾æŽ¥ '%s':%s" - -#: merge-recursive.c -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "ä¸çŸ¥é“å¦‚ä½•å¤„ç† %06o %s '%s'" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "æ— æ³•åˆå¹¶å模组 %s(仓库æŸå)" - -#: merge-recursive.c -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "忍¡ç»„ %s 快进到如下æäº¤ï¼š" - -#: merge-recursive.c -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "å¿«è¿›åæ¨¡ç»„ %s" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "æ— æ³•åˆå¹¶å模组 %s (没å‘现åˆå¹¶è·Ÿéšçš„æäº¤ï¼‰" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "æ— æ³•åˆå¹¶å模组 %s(éžå¿«è¿›ï¼‰" - -#: merge-recursive.c -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "æ‰¾åˆ°åæ¨¡ç»„的一个å¯èƒ½çš„åˆå¹¶æ–¹æ¡ˆï¼š\n" - -#: merge-recursive.c -#, 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" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"ä»¥æŽ¥å—æ¤å»ºè®®ã€‚\n" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "æ— æ³•åˆå¹¶å模组 %s (å‘现多个åˆå¹¶ï¼‰" - -#: merge-recursive.c -msgid "failed to execute internal merge" -msgstr "æ— æ³•æ‰§è¡Œå†…éƒ¨åˆå¹¶" - -#: merge-recursive.c -#, c-format -msgid "unable to add %s to database" -msgstr "ä¸èƒ½æ·»åŠ %s 至对象库" - -#: merge-recursive.c -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "错误:拒ç»ä¸¢å¤±æœªè·Ÿè¸ªæ–‡ä»¶ '%s',而是写入 %s。" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"冲çªï¼ˆ%1$s/åˆ é™¤ï¼‰ï¼š%2$s 在 %3$s ä¸è¢«åˆ 除,在 %5$s ä¸è¢« %4$s。%7$s çš„ %6$s 版" -"本被ä¿ç•™ã€‚" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"冲çªï¼ˆ%1$s/åˆ é™¤ï¼‰ï¼š%2$s 在 %3$s ä¸è¢«åˆ 除,在 %6$s ä¸çš„ %5$s 被 %4$s。%8$s çš„ " -"%7$s 版本被ä¿ç•™ã€‚" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"冲çªï¼ˆ%1$s/åˆ é™¤ï¼‰ï¼š%2$s 在 %3$s ä¸è¢«åˆ 除,在 %5$s ä¸è¢« %4$s。%7$s çš„ %6$s 版" -"本ä¿ç•™åœ¨ %8$s ä¸ã€‚" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"冲çªï¼ˆ%1$s/åˆ é™¤ï¼‰ï¼š%2$s 在 %3$s ä¸è¢«åˆ 除,在 %6$s ä¸çš„ %5$s 被 %4$s。%8$s çš„ " -"%7$s 版本ä¿ç•™åœ¨ %9$s ä¸ã€‚" - -#: merge-recursive.c -msgid "rename" -msgstr "é‡å‘½å" - -#: merge-recursive.c -msgid "renamed" -msgstr "é‡å‘½å" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "æ‹’ç»ä¸¢å¤±è„文件 '%s'" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "æ‹’ç»åœ¨ '%s' 处失去未跟踪文件,å³ä½¿å®ƒå˜åœ¨äºŽé‡å‘½åä¸ã€‚" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "冲çªï¼ˆé‡å‘½å/æ·»åŠ ï¼‰ï¼šåœ¨ %3$s ä¸é‡å‘½å %1$s->%2$s。在 %5$s 䏿·»åŠ %4$s" - -#: merge-recursive.c -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s 是 %s ä¸çš„一个目录而以 %s 为åè¢«æ·»åŠ " - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "æ‹’ç»ä¸¢å¤±æœªè·Ÿè¸ªæ–‡ä»¶ '%s'ï¼Œè€Œæ˜¯æ·»åŠ ä¸º %s" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"冲çªï¼ˆé‡å‘½å/é‡å‘½å):在分支 \"%3$s\" ä¸é‡å‘½å \"%1$s\"->\"%2$s\",在分支 " -"\"%6$s\" ä¸é‡å‘½å \"%4$s\"->\"%5$s\"%7$s" - -#: merge-recursive.c -msgid " (left unresolved)" -msgstr "(留下未解决)" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"冲çªï¼ˆé‡å‘½å/é‡å‘½å):在 %3$s ä¸é‡å‘½å %1$s->%2$s,在 %6$s ä¸é‡å‘½å %4$s-" -">%5$s" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"冲çªï¼ˆåˆ†å‰²çš„目录é‡å‘½åï¼‰ï¼šä¸æ¸…楚 %s åº”è¯¥æ”¾åœ¨å“ªé‡Œï¼Œå› ä¸ºç›®å½• %s 被é‡å‘½å到多个" -"其它目录,没有目录包å«å¤§éƒ¨åˆ†æ–‡ä»¶ã€‚" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"冲çªï¼ˆé‡å‘½å/é‡å‘½å):在 %3$s ä¸é‡å‘½å目录 %1$s->%2$s,在 %6$s ä¸é‡å‘½å目录 " -"%4$s->%5$s" - -#: merge-recursive.c -#, c-format -msgid "cannot read object %s" -msgstr "ä¸èƒ½è¯»å–对象 %s" - -#: merge-recursive.c -#, c-format -msgid "object %s is not a blob" -msgstr "对象 %s 䏿˜¯ä¸€ä¸ªæ•°æ®å¯¹è±¡" - -#: merge-recursive.c -msgid "modify" -msgstr "修改" - -#: merge-recursive.c -msgid "modified" -msgstr "修改" - -#: merge-recursive.c -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "略过 %s(已ç»åšè¿‡ç›¸åŒåˆå¹¶ï¼‰" - -#: merge-recursive.c -#, c-format -msgid "Adding as %s instead" -msgstr "而是以 %s ä¸ºåæ·»åŠ " - -#: merge-recursive.c -#, c-format -msgid "Removing %s" -msgstr "åˆ é™¤ %s" - -#: merge-recursive.c -msgid "file/directory" -msgstr "文件/目录" - -#: merge-recursive.c -msgid "directory/file" -msgstr "目录/文件" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "冲çªï¼ˆ%1$s):在 %3$s 䏿œ‰ä¸€ä¸ªå为 %2$s 的目录。以 %5$s ä¸ºåæ·»åŠ %4$s" - -#: merge-recursive.c -#, c-format -msgid "Adding %s" -msgstr "æ·»åŠ %s" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "冲çªï¼ˆadd/add):åˆå¹¶å†²çªäºŽ %s" - -#: merge-recursive.c -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "æ— æ³•åˆå¹¶æ ‘ %s å’Œ %s" - -#: merge-recursive.c -msgid "Merging:" -msgstr "åˆå¹¶ï¼š" - -#: merge-recursive.c -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "å‘现 %u 个共åŒç¥–先:" -msgstr[1] "å‘现 %u 个共åŒç¥–先:" - -#: merge-recursive.c -msgid "merge returned no commit" -msgstr "åˆå¹¶æœªè¿”回æäº¤" - -#: merge-recursive.c -#, c-format -msgid "Could not parse object '%s'" -msgstr "ä¸èƒ½è§£æžå¯¹è±¡ '%s'" - #: merge.c msgid "failed to read the cache" msgstr "æ— æ³•è¯»å–缓å˜" @@ -22136,14 +21950,15 @@ msgid "failed to clear multi-pack-index at %s" msgstr "æ— æ³•æ¸…ç†ä½äºŽ %s 的多包索引" #: midx-write.c -msgid "cannot write incremental MIDX with bitmap" -msgstr "æ— æ³•ä½¿ç”¨ä½å›¾å†™å…¥å¢žé‡ MIDX" - -#: midx-write.c msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "忽略已å˜åœ¨çš„å¤šåŒ…ç´¢å¼•ï¼Œæ ¡éªŒç ä¸åŒ¹é…" #: midx-write.c +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "æ— æ³•åŠ è½½å¤šåŒ…ç´¢å¼• %s çš„åå‘索引" + +#: midx-write.c msgid "Adding packfiles to multi-pack-index" msgstr "æ·»åŠ åŒ…æ–‡ä»¶åˆ°å¤šåŒ…ç´¢å¼•" @@ -22459,78 +22274,6 @@ msgstr "æ— æ³•å°†å¯¹è±¡ä»Ž %s 转æ¢ä¸º %s" #: object-file.c #, c-format -msgid "object directory %s does not exist; check .git/objects/info/alternates" -msgstr "对象目录 %s ä¸å˜åœ¨ï¼Œæ£€æŸ¥ .git/objects/info/alternates" - -#: object-file.c -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "æ— æ³•è§„èŒƒåŒ–å¤‡ç”¨å¯¹è±¡è·¯å¾„ï¼š%s" - -#: object-file.c -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s:忽略备用对象库,嵌套太深" - -#: object-file.c -msgid "unable to fdopen alternates lockfile" -msgstr "æ— æ³• fdopen 替æ¢é”文件" - -#: object-file.c -msgid "unable to read alternates file" -msgstr "æ— æ³•è¯»å–æ›¿ä»£æ–‡ä»¶" - -#: object-file.c -msgid "unable to move new alternates file into place" -msgstr "æ— æ³•å°†æ–°çš„å¤‡ç”¨æ–‡ä»¶ç§»åŠ¨åˆ°ä½" - -#: object-file.c -#, c-format -msgid "path '%s' does not exist" -msgstr "路径 '%s' ä¸å˜åœ¨" - -#: object-file.c -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "å°šä¸æ”¯æŒå°†å‚考仓库 '%s' 作为一个链接检出。" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "å‚考仓库 '%s' 䏿˜¯ä¸€ä¸ªæœ¬åœ°ä»“库。" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "å‚考仓库 '%s' 是一个浅克隆" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "å‚考仓库 '%s' 已被移æ¤" - -#: object-file.c -#, c-format -msgid "could not find object directory matching %s" -msgstr "æ— æ³•æ‰¾åˆ°å’Œ %s 匹é…的对象目录" - -#: object-file.c -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "è§£æžå¤‡ç”¨å¼•ç”¨æ—¶æ— æ•ˆçš„è¡Œï¼š%s" - -#: object-file.c -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "å°è¯• mmap %<PRIuMAX>,超过了最大值 %<PRIuMAX>" - -#: object-file.c -#, c-format -msgid "mmap failed%s" -msgstr "mmap 失败%s" - -#: object-file.c -#, c-format msgid "object file %s is empty" msgstr "对象文件 %s 为空" @@ -22575,21 +22318,6 @@ msgstr "æ¾æ•£å¯¹è±¡ %s(ä¿å˜åœ¨ %s)已æŸå" #: object-file.c #, c-format -msgid "replacement %s not found for %s" -msgstr "找ä¸åˆ° %2$s 的替代 %1$s" - -#: object-file.c -#, c-format -msgid "packed object %s (stored in %s) is corrupt" -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 open %s" msgstr "ä¸èƒ½æ‰“å¼€ %s" @@ -22706,11 +22434,6 @@ msgstr "%sï¼šä¸æ”¯æŒçš„æ–‡ä»¶ç±»åž‹" #: object-file.c #, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s 䏿˜¯ä¸€ä¸ªæœ‰æ•ˆçš„ '%s' 对象" - -#: object-file.c -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "%s 的哈希值ä¸åŒ¹é…(预期 %s)" @@ -22731,6 +22454,11 @@ msgstr "æ— æ³•è§£æž %s 的头部" #: object-file.c #, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "æ— æ³•ä»Ž %s 的包头 '%s' ä¸è§£æžç±»åž‹" + +#: object-file.c +#, c-format msgid "unable to unpack contents of %s" msgstr "æ— æ³•è§£åŽ‹ç¼© %s 的内容" @@ -22906,6 +22634,88 @@ msgstr "éœ€è¦ <对象>:<路径>,åªç»™å‡ºäº† <对象> '%s'" msgid "invalid object name '%.*s'." msgstr "æ— æ•ˆçš„å¯¹è±¡å '%.*s'。" +#: object-store.c +#, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "对象目录 %s ä¸å˜åœ¨ï¼Œæ£€æŸ¥ .git/objects/info/alternates" + +#: object-store.c +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "æ— æ³•è§„èŒƒåŒ–å¤‡ç”¨å¯¹è±¡è·¯å¾„ï¼š%s" + +#: object-store.c +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s:忽略备用对象库,嵌套太深" + +#: object-store.c +msgid "unable to fdopen alternates lockfile" +msgstr "æ— æ³• fdopen alternates çš„é”æ–‡ä»¶" + +#: object-store.c +msgid "unable to read alternates file" +msgstr "æ— æ³•è¯»å– alternates 文件" + +#: object-store.c +msgid "unable to move new alternates file into place" +msgstr "æ— æ³•å°†æ–°çš„ alternates 文件移动到ä½" + +#: object-store.c +#, c-format +msgid "path '%s' does not exist" +msgstr "路径 '%s' ä¸å˜åœ¨" + +#: object-store.c +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "å°šä¸æ”¯æŒå°†å‚考仓库 '%s' 作为链接检出。" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "å‚考仓库 '%s' 䏿˜¯æœ¬åœ°ä»“库。" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "å‚考仓库 '%s' 是浅克隆" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "å‚考仓库 '%s' 已被移æ¤" + +#: object-store.c +#, c-format +msgid "could not find object directory matching %s" +msgstr "æ— æ³•æ‰¾åˆ°å’Œ %s 匹é…的对象目录" + +#: object-store.c +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "è§£æžå¤‡ç”¨å¼•用时é‡åˆ°æ— 效的行:%s" + +#: object-store.c +#, c-format +msgid "replacement %s not found for %s" +msgstr "找ä¸åˆ° %2$s 的替代 %1$s" + +#: object-store.c +#, c-format +msgid "packed object %s (stored in %s) is corrupt" +msgstr "打包对象 %s(ä¿å˜åœ¨ %s)已æŸå" + +#: object-store.c +#, c-format +msgid "missing mapping of %s to %s" +msgstr "缺少 %s 到 %s çš„æ˜ å°„" + +#: object-store.c +#, c-format +msgid "%s is not a valid '%s' object" +msgstr "%s 䏿˜¯æœ‰æ•ˆçš„ '%s' 对象" + #: object.c #, c-format msgid "invalid object type \"%s\"" @@ -23253,6 +23063,16 @@ msgstr "%s ä¸å¯ç”¨" #: parse-options.c #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "%2$s 的值 %1$s ä¸åœ¨èŒƒå›´ [%3$<PRIdMAX>,%4$<PRIdMAX>] 内" + +#: parse-options.c +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s 期望一个带å¯é€‰ k/m/g åŽç¼€çš„æ•´æ•°" + +#: parse-options.c +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "%s 期望一个éžè´Ÿæ•´æ•°å’Œä¸€ä¸ªå¯é€‰çš„ k/m/g åŽç¼€" @@ -23437,11 +23257,6 @@ msgstr "使用 --pathspec-from-file,路径表达å¼ç”¨ç©ºå—符分隔" msgid "bad boolean environment value '%s' for '%s'" msgstr "对于 '%2$s' 的错误的布尔环境å–值 '%1$s'" -#: parse.c -#, c-format -msgid "failed to parse %s" -msgstr "æ— æ³•è§£æž %s" - #: path-walk.c #, c-format msgid "failed to walk children of tree %s: not found" @@ -23644,8 +23459,13 @@ msgstr "æ— æ³•ä»Žæ‰¿è¯ºè€…è¿œç¨‹èŽ·å– %s" #: promisor-remote.c #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "已知远程å称为 '%s',但 url 为 '%s' è€Œä¸æ˜¯ '%s'" +msgid "no or empty URL advertised for remote '%s'" +msgstr "远程 '%s' çš„ URL 没有公布或为空" + +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "已知远程å称为 '%s',但 URL 是 '%s' è€Œéž '%s'" #: promisor-remote.c #, c-format @@ -24546,6 +24366,11 @@ msgstr "æ— æ³•æ‰“å¼€ç›®å½• %s" msgid "Checking references consistency" msgstr "æ£åœ¨æ£€æŸ¥å¼•用一致性" +#: refs/packed-backend.c +#, c-format +msgid "unable to open '%s'" +msgstr "æ— æ³•æ‰“å¼€ '%s'" + #: refs/reftable-backend.c #, c-format msgid "refname is dangerous: %s" @@ -24626,11 +24451,6 @@ msgstr "引用å %s 是一个符å·å¼•ç”¨ï¼Œä¸æ”¯æŒå¤åˆ¶" #: refspec.c #, c-format -msgid "invalid refspec '%s'" -msgstr "æ— æ•ˆçš„å¼•ç”¨è§„æ ¼ï¼š'%s'" - -#: refspec.c -#, c-format msgid "pattern '%s' has no '*'" msgstr "æ¨¡å¼ '%s' 没有 '*'" @@ -25286,8 +25106,8 @@ msgid "could not set recommended config" msgstr "æ— æ³•è®¾ç½®æŽ¨èçš„é…ç½®" #: scalar.c -msgid "could not turn on maintenance" -msgstr "æ— æ³•æ‰“å¼€ç»´æŠ¤æ¨¡å¼" +msgid "could not toggle maintenance" +msgstr "æ— æ³•åˆ‡æ¢ç»´æŠ¤æ¨¡å¼" #: scalar.c msgid "could not start the FSMonitor daemon" @@ -25347,12 +25167,16 @@ msgid "specify if tags should be fetched during clone" msgstr "å¦‚è‹¥åº”åœ¨å…‹éš†æœŸé—´èŽ·å–æ ‡ç¾åˆ™æŒ‡å®š" #: scalar.c +msgid "specify if background maintenance should be enabled" +msgstr "指定是å¦å¯ç”¨åŽå°ç»´æŠ¤" + +#: scalar.c msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<登记>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<登记>]" #: scalar.c #, c-format @@ -25401,16 +25225,27 @@ msgid "`scalar list` does not take arguments" msgstr "`scalar list` ä¸å¸¦å‚æ•°" #: scalar.c -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<登记>]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [<登记>]" #: scalar.c msgid "reconfigure all registered enlistments" msgstr "釿–°é…置所有注册的登记" #: scalar.c -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all | <登记>]" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +#: scalar.c +msgid "signal how to adjust background maintenance" +msgstr "指定如何调整åŽå°ç»´æŠ¤" + +#: scalar.c +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | <登记>]" #: scalar.c msgid "--all or <enlistment>, but not both" @@ -25418,6 +25253,11 @@ msgstr "--all 或者 <登记>ï¼Œè€Œä¸æ˜¯ä¸¤ä¸ªä¸€èµ·" #: scalar.c #, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "--maintenance é€‰é¡¹çš„æ¨¡å¼æœªçŸ¥ï¼š%s" + +#: scalar.c +#, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "æ— æ³•åˆ é™¤è¿‡æœŸçš„ scalar.repo '%s'" @@ -27123,6 +26963,10 @@ msgstr "åœ¨æ¯æ¬¡è¿ä»£å‰æ¸…é™¤ç¼“å˜æ ‘" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "ç¼“å˜æ ‘䏿— 效化的æ¡ç›®æ•°é‡ï¼ˆé»˜è®¤ 0)" +#: t/helper/test-pack-deltas.c +msgid "the number of objects to write" +msgstr "写入对象的数é‡" + #: t/helper/test-path-walk.c msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk <选项> -- <版本选项>" @@ -28051,6 +27895,16 @@ msgstr "ä¸èƒ½èŽ·å–当å‰å·¥ä½œç›®å½•" msgid "unable to get random bytes" msgstr "æ— æ³•èŽ·å–éšæœºå—节" +#: wrapper.c +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "å°è¯•å†…å˜æ˜ å°„(mmap) %<PRIuMAX>,超过了最大值 %<PRIuMAX>" + +#: wrapper.c +#, c-format +msgid "mmap failed%s" +msgstr "mmap 失败%s" + #: wt-status.c msgid "Unmerged paths:" msgstr "未åˆå¹¶çš„路径:" @@ -28971,6 +28825,15 @@ msgstr "æ— æ³•æ£ç¡®åœ°åˆå§‹åŒ– SMTP。检查é…置并使用 --smtp-debug。" #: git-send-email.perl #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook 釿–°åˆ†é…了 Message-ID 为:%s\n" + +#: git-send-email.perl +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "è¦å‘Šï¼šæ— 法从æœåС噍å“应ä¸èŽ·å– Message-ID。\n" + +#: git-send-email.perl +#, perl-format msgid "Failed to send %s\n" msgstr "æ— æ³•å‘é€ %s\n" diff --git a/po/zh_TW.po b/po/zh_TW.po index aa74d6537a..4fcbb71f8b 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -30,8 +30,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n" -"POT-Creation-Date: 2025-03-09 10:39+0800\n" -"PO-Revision-Date: 2025-03-09 10:52+0800\n" +"POT-Creation-Date: 2025-06-12 22:09+0800\n" +"PO-Revision-Date: 2025-06-12 22:25+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" @@ -40,7 +40,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 3.5\n" +"X-Generator: Poedit 3.6\n" "X-ZhConverter: ç¹åŒ–姬 dict-f4bc617e-r910 @ 2019/11/16 20:23:12 | https://" "zhconvert.org\n" @@ -954,10 +954,9 @@ msgstr "空白å—元忽略é¸é …「%sã€ä¸èªè˜" #: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c #: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c #: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c -#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-list.c -#: builtin/rev-parse.c builtin/show-branch.c builtin/stash.c -#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c -#: range-diff.c revision.c +#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-parse.c +#: builtin/show-branch.c builtin/stash.c builtin/submodule--helper.c +#: builtin/tag.c builtin/worktree.c parse-options.c range-diff.c revision.c #, c-format msgid "options '%s' and '%s' cannot be used together" msgstr "ç„¡æ³•åŒæ™‚使用「%sã€å’Œã€Œ%sã€é¸é …" @@ -1838,7 +1837,7 @@ msgstr "沒有版本庫無法使用 --attr-source 或 GIT_ATTR_SOURCE" msgid "bad --attr-source or GIT_ATTR_SOURCE" msgstr "無效的 --attr-source 或 GIT_ATTR_SOURCE" -#: attr.c read-cache.c +#: attr.c read-cache.c refs/packed-backend.c #, c-format msgid "unable to stat '%s'" msgstr "無法統計「%sã€" @@ -2655,7 +2654,7 @@ msgstr "互動å¼åŸ·è¡Œ" msgid "bypass pre-applypatch and applypatch-msg hooks" msgstr "ç¹žéŽ pre-applypatch å’Œ applypatch-msg 掛鉤" -#: builtin/am.c +#: builtin/am.c builtin/cat-file.c msgid "historical option -- no-op" msgstr "æ·å²éºç•™é¸é …——無作用" @@ -3237,7 +3236,7 @@ msgstr "å¼·åˆ¶é¡¯ç¤ºé€²åº¦å ±å‘Š" #: builtin/blame.c msgid "show output score for blame entries" -msgstr "顯示溯æºé …目的輸出得分" +msgstr "顯示溯æºé …目的輸出分數" #: builtin/blame.c msgid "show original filename (Default: auto)" @@ -3702,8 +3701,8 @@ msgstr "HEAD 指標ä¸åœ¨ /refs/heads ä¸ï¼" #: builtin/branch.c msgid "" -"branch with --recurse-submodules can only be used if submodule." -"propagateBranches is enabled" +"branch with --recurse-submodules can only be used if " +"submodule.propagateBranches is enabled" msgstr "" "有 --recurse-submodules 的分支,åªèƒ½åœ¨å•Ÿç”¨ submodule.propagateBranches 時使用" @@ -3967,7 +3966,7 @@ msgstr "需è¦ç‰ˆæœ¬åº«æ‰èƒ½æ‹†åˆ†å¥—件包。" msgid "Unbundling objects" msgstr "æ£åœ¨æ‹†åˆ†ç‰©ä»¶" -#: builtin/cat-file.c merge-recursive.c +#: builtin/cat-file.c #, c-format msgid "cannot read object %s '%s'" msgstr "無法讀å–物件 %s「%sã€" @@ -4004,12 +4003,9 @@ msgid "git cat-file <type> <object>" msgstr "git cat-file <type> <object>" #: builtin/cat-file.c -msgid "git cat-file (-e | -p) <object>" -msgstr "git cat-file (-e | -p) <object>" - -#: builtin/cat-file.c -msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" -msgstr "git cat-file (-t | -s) [--allow-unknown-type] <object>" +#| msgid "git cat-file (-e | -p) <object>" +msgid "git cat-file (-e | -p | -t | -s) <object>" +msgstr "git cat-file (-e | -p | -t | -s) <object>" #: builtin/cat-file.c msgid "" @@ -4056,10 +4052,6 @@ msgstr "" msgid "show object size" msgstr "顯示物件大å°" -#: builtin/cat-file.c -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "å…許 -s å’Œ -t å°æå£žçš„ç‰©ä»¶ç”Ÿæ•ˆ" - #: builtin/cat-file.c builtin/log.c msgid "use mail map file" msgstr "ä½¿ç”¨ä¿¡ä»¶æ˜ å°„æª”æ¡ˆ" @@ -4131,6 +4123,15 @@ msgid "use a <path> for (--textconv | --filters); Not with 'batch'" msgstr "請在 (--textconv | --filters) 使用 <path>,而éžã€Œbatchã€" #: builtin/cat-file.c +msgid "objects filter only supported in batch mode" +msgstr "ç‰©ä»¶éŽæ¿¾å™¨åƒ…æ”¯æ´æ‰¹æ¬¡æ¨¡å¼" + +#: builtin/cat-file.c +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "䏿”¯æ´çš„ç‰©ä»¶éŽæ¿¾å™¨ï¼šã€Œ%sã€" + +#: builtin/cat-file.c #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "「%s=<%s>ã€éœ€è¦ã€Œ%sã€æˆ–「%sã€" @@ -5642,17 +5643,6 @@ msgid "git commit-tree: failed to read" msgstr "git commit-tree:讀å–失敗" #: builtin/commit.c -#| msgid "" -#| "git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n" -#| " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" -#| "reword):]<commit>]\n" -#| " [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n" -#| " [--allow-empty-message] [--no-verify] [-e] [--" -#| "author=<author>]\n" -#| " [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n" -#| " [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n" -#| " [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n" -#| " [--] [<pathspec>...]" msgid "" "git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n" " [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|" @@ -6933,6 +6923,65 @@ msgstr "請指定檔案å稱的 strftime æ ¼å¼å¾Œç¶´" msgid "specify the content of the diagnostic archive" msgstr "指定診斷å°å˜æª”的內容" +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse mode: %s" +msgstr "ç„¡æ³•è§£æžæ¨¡å¼ï¼š%s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse object id: %s" +msgstr "無法解æžç‰©ä»¶ ID:%s" + +#: builtin/diff-pairs.c +#| msgid "git repack [<options>]" +msgid "git diff-pairs -z [<diff-options>]" +msgstr "git diff-pairs -z [<diff-options>]" + +#: builtin/diff-pairs.c builtin/log.c builtin/replay.c builtin/shortlog.c +#: bundle.c +#, c-format +msgid "unrecognized argument: %s" +msgstr "ä¸èªè˜çš„引數:%s" + +#: builtin/diff-pairs.c +msgid "working without -z is not supported" +msgstr "䏿”¯æ´åœ¨ç„¡ -z 的情æ³ä¸‹é‹ä½œ" + +#: builtin/diff-pairs.c +msgid "pathspec arguments not supported" +msgstr "䏿”¯æ´è·¯å¾‘è¦æ ¼å¼•數" + +#: builtin/diff-pairs.c +msgid "revision arguments not allowed" +msgstr "ä¸å…許有修訂版本引數" + +#: builtin/diff-pairs.c +msgid "invalid raw diff input" +msgstr "無效的原始 diff 輸入" + +#: builtin/diff-pairs.c +msgid "tree objects not supported" +msgstr "䏿”¯æ´æ¨¹ç‹€ç‰©ä»¶" + +#: builtin/diff-pairs.c +msgid "got EOF while reading path" +msgstr "讀å–路徑時é‡åˆ° EOF" + +#: builtin/diff-pairs.c +msgid "got EOF while reading destination path" +msgstr "讀å–目的地路徑時é‡åˆ° EOF" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "無法解æžé‡æ–°å‘½å/複製分數:%s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unknown diff status: %c" +msgstr "éžé 期的 diff 狀態:%c" + #: builtin/diff-tree.c msgid "--merge-base only works with two commits" msgstr "--merge-base åªå° 2 個以上的æäº¤æœ‰ç”¨" @@ -7110,6 +7159,10 @@ msgid "select handling of signed tags" msgstr "鏿“‡å¦‚何處ç†ç°½å標籤" #: builtin/fast-export.c +msgid "select handling of signed commits" +msgstr "鏿“‡å¦‚何處ç†ç°½åæäº¤" + +#: builtin/fast-export.c msgid "select handling of tags that tag filtered objects" msgstr "鏿“‡ç•¶æ¨™ç±¤æŒ‡å‘è¢«éŽæ¿¾ç‰©ä»¶æ™‚è©²æ¨™ç±¤çš„è™•ç†æ–¹å¼" @@ -7369,7 +7422,7 @@ msgstr "é¸é …「%sã€çš„值「%sã€å° %s 無效" msgid "option \"%s\" is ignored for %s" msgstr "é¸é …「%sã€è¢« %s 忽略" -#: builtin/fetch.c object-file.c +#: builtin/fetch.c object-store.c #, c-format msgid "%s is not a valid object" msgstr "%s 䏿˜¯ä¸€å€‹æœ‰æ•ˆçš„物件" @@ -7636,8 +7689,8 @@ msgstr "通訊å”å®šä¸æ”¯æ´ --negotiate-onlyã€‚çµæŸ" #: builtin/fetch.c msgid "" -"--filter can only be used with the remote configured in extensions." -"partialclone" +"--filter can only be used with the remote configured in " +"extensions.partialclone" msgstr "åªå¯ä»¥å°‡ --filter 用於在 extensions.partialclone ä¸è¨å®šçš„é 端版本庫" #: builtin/fetch.c @@ -7912,11 +7965,6 @@ msgstr "%s:物件æå£žæˆ–éºå¤±ï¼š%s" #: builtin/fsck.c #, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s:物件屬於「%sã€æœªçŸ¥é¡žåž‹ï¼š%s" - -#: builtin/fsck.c -#, c-format msgid "%s: object could not be parsed: %s" msgstr "%s:ä¸èƒ½è§£æžç‰©ä»¶ï¼š%s" @@ -7988,16 +8036,25 @@ msgid "invalid rev-index for pack '%s'" msgstr "「%sã€å°è£çš„修訂版索引 (rev-index) 無效" #: builtin/fsck.c +msgid "Checking ref database" +msgstr "æ£åœ¨æª¢æŸ¥å¼•用資料庫" + +#: builtin/fsck.c +#| 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>...]" 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>...]" +" [--[no-]name-objects] [--[no-]references] [<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] [<object>...]" +" [--[no-]name-objects] [--[no-]references] [<object>...]" #: builtin/fsck.c msgid "show unreachable objects" @@ -8047,6 +8104,10 @@ msgstr "顯示進度" msgid "show verbose names for reachable objects" msgstr "顯示å¯ä»¥å–得物件的詳細å稱" +#: builtin/fsck.c +msgid "check reference database consistency" +msgstr "æ£åœ¨æª¢æŸ¥è³‡æ–™åº«ä¸€è‡´æ€§" + #: builtin/fsck.c builtin/index-pack.c msgid "Checking objects" msgstr "æ£åœ¨æª¢æŸ¥ç‰©ä»¶" @@ -8221,7 +8282,7 @@ msgstr "ç¨ç«‹å°è£ç„¡å¼•用物件" #: builtin/gc.c builtin/repack.c msgid "with --cruft, limit the size of new cruft packs" -msgstr "æé… --cruft,é™åˆ¶æ–°å»¢æ£„å°è£çš„大å°" +msgstr "æé… --cruft,é™åˆ¶æ–°ç„¡ç”¨åŒ…的大å°" #: builtin/gc.c msgid "be more thorough (increased runtime)" @@ -8732,7 +8793,7 @@ msgstr "組åˆç”¨ -e åƒæ•¸è¨å®šçš„æ¨¡å¼" #: builtin/grep.c msgid "indicate hit with exit status without output" -msgstr "ä¸è¼¸å‡ºï¼Œè€Œç”¨é›¢é–‹ç¢¼æ¨™è¨˜å‘½ä¸ç‹€æ…‹" +msgstr "ä¸è¼¸å‡ºï¼Œè€Œç”¨çµæŸç‹€æ…‹ç¢¼æ¨™è¨˜å‘½ä¸ç‹€æ…‹" #: builtin/grep.c msgid "show only matches from files that match all patterns" @@ -9473,11 +9534,6 @@ msgid "" "<file>" msgstr "追蹤 <é–‹å§‹>,<çµæŸ> 範åœä¸æ©«åˆ—或 <檔案> ä¸> :<函數å稱> 的變化å²" -#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c -#, c-format -msgid "unrecognized argument: %s" -msgstr "ä¸èªè˜çš„引數:%s" - #: builtin/log.c msgid "-L<range>:<file> cannot be used with pathspec" msgstr "-L<範åœ>:<檔案> å’Œ pathspec ä¸èƒ½åŒæ™‚使用" @@ -10310,6 +10366,10 @@ msgid "also show informational/conflict messages" msgstr "亦顯示資訊性或è¡çªè¨Šæ¯" #: builtin/merge-tree.c +msgid "suppress all output; only exit status wanted" +msgstr "éš±è—æ‰€æœ‰è¼¸å‡ºï¼Œåªéœ€è¦çµæŸç‹€æ…‹ç¢¼" + +#: builtin/merge-tree.c msgid "list filenames without modes/oids/stages" msgstr "列出檔å,但ä¸é™„åŠ modes/oids/stages" @@ -10471,7 +10531,7 @@ msgstr "è®€å–æ¨¹å¤±æ•—" msgid "Already up to date. (nothing to squash)" msgstr "已經是最新的。(無需壓縮 (squash))" -#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c msgid "Already up to date." msgstr "已經是最新的。" @@ -10495,7 +10555,7 @@ msgstr "'%s' 沒有指å‘一個æäº¤" msgid "Bad branch.%s.mergeoptions string: %s" msgstr "壞的 branch.%s.mergeoptions å—串:%s" -#: builtin/merge.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c msgid "Unable to write index." msgstr "ä¸èƒ½å¯«å…¥ç´¢å¼•。" @@ -10651,7 +10711,7 @@ msgstr "åªèƒ½å°‡ä¸€å€‹æäº¤åˆä¸¦åˆ°ç©ºåˆ†æ”¯ä¸Š" msgid "Updating %s..%s\n" msgstr "æ›´æ–° %s..%s\n" -#: builtin/merge.c merge-ort-wrappers.c merge-recursive.c +#: builtin/merge.c merge-ort-wrappers.c #, c-format msgid "" "Your local changes to the following files would be overwritten by merge:\n" @@ -10813,8 +10873,14 @@ msgid "" msgstr "在 repack 期間,將較å°å°ºå¯¸çš„包檔案收集到大於æ¤å¤§å°çš„æ‰¹æ¬¡ä¸" #: builtin/mv.c -msgid "git mv [<options>] <source>... <destination>" -msgstr "git mv [<é¸é …>] <來æº>... <目的地>" +#| msgid "git mv [<options>] <source>... <destination>" +msgid "git mv [-v] [-f] [-n] [-k] <source> <destination>" +msgstr "git mv [-v] [-f] [-n] [-k] <source> <destination>" + +#: builtin/mv.c +#| msgid "git mv [<options>] <source>... <destination>" +msgid "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" +msgstr "git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>" #: builtin/mv.c #, c-format @@ -10904,6 +10970,11 @@ msgstr "%s,來æº=%s,目的地=%s" #: builtin/mv.c #, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "ç„¡æ³•åŒæ™‚移動「%sã€å’Œå…¶ä¸Šå±¤ç›®éŒ„「%sã€" + +#: builtin/mv.c +#, c-format msgid "Renaming %s to %s\n" msgstr "釿–°å‘½å %s 至 %s\n" @@ -11534,15 +11605,15 @@ msgstr "無法å˜å–å°åŒ…檔案 %s" #: builtin/pack-objects.c msgid "Enumerating cruft objects" -msgstr "æ£åœ¨æžšèˆ‰å»¢æ£„物件" +msgstr "æ£åœ¨æžšèˆ‰ç„¡ç”¨ç‰©ä»¶" #: builtin/pack-objects.c msgid "unable to add cruft objects" -msgstr "ç„¡æ³•åŠ å…¥å»¢æ£„ç‰©ä»¶" +msgstr "ç„¡æ³•åŠ å…¥ç„¡ç”¨ç‰©ä»¶" #: builtin/pack-objects.c msgid "Traversing cruft objects" -msgstr "æ£åœ¨éæ·å»¢æ£„物件" +msgstr "æ£åœ¨éæ·ç„¡ç”¨ç‰©ä»¶" #: builtin/pack-objects.c #, c-format @@ -11564,7 +11635,7 @@ msgstr "" #: builtin/pack-objects.c reachable.c msgid "could not load cruft pack .mtimes" -msgstr "無法載入廢棄å°åŒ… .mtimes" +msgstr "無法載入無用包 .mtimes" #: builtin/pack-objects.c msgid "cannot open pack index" @@ -11709,11 +11780,11 @@ msgstr "將比æä¾› <時間> 新的無法å˜å–的物件解包" #: builtin/pack-objects.c msgid "create a cruft pack" -msgstr "建立廢棄å°åŒ…" +msgstr "建立無用包" #: builtin/pack-objects.c msgid "expire cruft objects older than <time>" -msgstr "將早於 <time> 的廢棄物件è¨ç‚ºéŽæœŸ" +msgstr "將早於 <time> 的無用物件è¨ç‚ºéŽæœŸ" #: builtin/pack-objects.c msgid "use the sparse reachability algorithm" @@ -12043,6 +12114,11 @@ msgstr "" msgid "unable to access commit %s" msgstr "無法å˜å–æäº¤ %s" +#: builtin/pull.c refspec.c +#, c-format +msgid "invalid refspec '%s'" +msgstr "ç„¡æ•ˆçš„å¼•ç”¨è¦æ ¼ï¼šã€Œ%sã€" + #: builtin/pull.c msgid "ignoring --verify-signatures for rebase" msgstr "為é‡å®šåŸºåº•動作忽略 --verify-signatures" @@ -13150,6 +13226,10 @@ msgid "git reflog exists <ref>" msgstr "git reflog exists <引用>" #: builtin/reflog.c +msgid "git reflog drop [--all [--single-worktree] | <refs>...]" +msgstr "git reflog drop [--all [--single-worktree] | <refs>...]" + +#: builtin/reflog.c #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "傳入「--%sã€çš„æ™‚間戳「%sã€ç„¡æ•ˆ" @@ -13209,8 +13289,8 @@ msgstr "æ£åœ¨æ¨™è¨˜å¯ä»¥å–得物件..." #: builtin/reflog.c #, c-format -msgid "%s points nowhere!" -msgstr "%s 指å‘ä¸å˜åœ¨ï¼" +msgid "reflog could not be found: '%s'" +msgstr "找ä¸åˆ°å¼•用日誌:「%sã€" #: builtin/reflog.c msgid "no reflog specified to delete" @@ -13221,8 +13301,19 @@ msgstr "未指定è¦åˆªé™¤çš„引用日誌" msgid "invalid ref format: %s" msgstr "ç„¡æ•ˆçš„å¼•ç”¨æ ¼å¼ï¼š%s" +#: builtin/reflog.c +msgid "drop the reflogs of all references" +msgstr "æ¨æ£„所有引用的引用日誌" + +#: builtin/reflog.c +msgid "drop reflogs from the current worktree only" +msgstr "åªæ¨æ£„ç›®å‰å·¥ä½œç›®éŒ„的引用日誌" + +#: builtin/reflog.c +msgid "references specified along with --all" +msgstr "åŒæ™‚指定åƒç…§å’Œ --all 引數" + #: builtin/refs.c -#| msgid "git refs migrate --ref-format=<format> [--dry-run]" msgid "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]" @@ -13890,7 +13981,7 @@ msgstr "å’Œ -a 相åŒï¼Œä¸¦å°‡ç„¡æ³•å–得的物件è¨ç‚ºé¬†æ•£ç‰©ä»¶" #: builtin/repack.c msgid "same as -a, pack unreachable cruft objects separately" -msgstr "å’Œ -a 相åŒï¼Œæœƒç¨ç«‹å°è£ç„¡æ³•å˜å–的廢棄物件" +msgstr "å’Œ -a 相åŒï¼Œæœƒç¨ç«‹å°è£ç„¡æ³•å˜å–的無用物件" #: builtin/repack.c msgid "approxidate" @@ -13898,7 +13989,11 @@ msgstr "近似日期" #: builtin/repack.c msgid "with --cruft, expire objects older than this" -msgstr "æé… --cruft 會將早於æ¤çš„ç‰©ä»¶æ¨™ç‚ºéŽæœŸ" +msgstr "æé… --cruft,會將早於æ¤çš„ç‰©ä»¶æ¨™ç‚ºéŽæœŸ" + +#: builtin/repack.c +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "æé… --cruftï¼Œåƒ…é‡æ–°æ‰“åŒ…å°æ–¼æ¤å¤§å°çš„無用包" #: builtin/repack.c msgid "remove redundant packs, and run git-prune-packed" @@ -14494,6 +14589,10 @@ msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "「%sã€çš„æ•¸å€¼ç„¡æ•ˆï¼šã€Œ%sã€ï¼Œå”¯ä¸€å…è¨±çš„æ ¼å¼æ˜¯ã€Œ%sã€" #: builtin/rev-list.c +msgid "-z option used with unsupported option" +msgstr "-z é¸é …èˆ‡ä¸æ”¯æ´çš„é¸é …一起使用" + +#: builtin/rev-list.c msgid "rev-list does not support display of notes" msgstr "rev-list 䏿”¯æ´é¡¯ç¤ºè¨»è§£" @@ -16757,8 +16856,9 @@ 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]" -msgstr "git update-ref [<é¸é …>] --stdin [-z]" +#| msgid "git update-ref [<options>] --stdin [-z]" +msgid "git update-ref [<options>] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [<options>] --stdin [-z] [--batch-updates]" #: builtin/update-ref.c msgid "delete the reference" @@ -16776,6 +16876,10 @@ msgstr "標準輸入有以 NUL å—元終æ¢çš„åƒæ•¸" msgid "read updates from stdin" msgstr "å¾žæ¨™æº–è¼¸å…¥è®€å–æ›´æ–°" +#: builtin/update-ref.c +msgid "batch reference updates" +msgstr "批次引用更新" + #: builtin/update-server-info.c msgid "update the info files from scratch" msgstr "從é 開始更新檔案訊æ¯" @@ -17620,6 +17724,10 @@ msgid "Compare a tree to the working tree or index" msgstr "å°‡ä¸€å€‹æ¨¹å’Œå·¥ä½œå€æˆ–ç´¢å¼•åšæ¯”較" #: command-list.h +msgid "Compare the content and mode of provided blob pairs" +msgstr "比較指定的兩個資料物件的內容和模å¼" + +#: command-list.h msgid "Compares the content and mode of blobs found via two tree objects" msgstr "比較兩個樹狀物件的檔案內容和模å¼" @@ -18858,8 +18966,8 @@ msgid "" "remote URLs cannot be configured in file directly or indirectly included by " "includeIf.hasconfig:remote.*.url" msgstr "" -"無法在檔案è¨å®šé 端 URL,無論是直接或間接é€éŽ includeIf.hasconfig:remote.*." -"url 引入" +"無法在檔案è¨å®šé 端 URL,無論是直接或間接é€éŽ " +"includeIf.hasconfig:remote.*.url 引入" #: config.c #, c-format @@ -19738,7 +19846,7 @@ msgstr "color-moved-ws:allow-indentation-change ä¸èƒ½èˆ‡å…¶å®ƒç©ºç™½å—元模 msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "è¨å®šè®Šæ•¸ 'diff.submodule' 未知的å–值:'%s'" -#: diff.c merge-recursive.c transport.c +#: diff.c merge-ort.c transport.c #, c-format msgid "unknown value for config '%s': %s" msgstr "è¨å®š '%s' çš„å–值未知:%s" @@ -21163,6 +21271,11 @@ msgstr "䏿”¯æ´å§”è¨—æŽ§åˆ¶ï¼Œå› ç‚º cURL < 7.22.0" msgid "Unknown value for http.proactiveauth" msgstr "http.proactiveauth 的值未知" +#: http.c parse.c +#, c-format +msgid "failed to parse %s" +msgstr "è§£æž %s 失敗" + #: http.c #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" @@ -21388,7 +21501,12 @@ msgstr "ç„¡æ³•æ ¼å¼åŒ–訊æ¯ï¼š%s" msgid "invalid marker-size '%s', expecting an integer" msgstr "無效的 marker-size「%sã€ï¼Œæ‡‰ç‚ºæ•´æ•¸" -#: merge-ort.c merge-recursive.c +#: merge-ort-wrappers.c +#, c-format +msgid "Could not parse object '%s'" +msgstr "無法解æžç‰©ä»¶ã€Œ%sã€" + +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "無法åˆä½µå模組 %s (沒有簽出)" @@ -21398,7 +21516,7 @@ msgstr "無法åˆä½µå模組 %s (沒有簽出)" msgid "Failed to merge submodule %s (no merge base)" msgstr "無法åˆä½µ %s 忍¡çµ„(沒有åˆä½µåŸºåº•)" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (commits not present)" msgstr "無法åˆä½µå模組 %s(æäº¤ä¸å˜åœ¨ï¼‰" @@ -21408,7 +21526,7 @@ msgstr "無法åˆä½µå模組 %s(æäº¤ä¸å˜åœ¨ï¼‰" msgid "error: failed to merge submodule %s (repository corrupt)" msgstr "錯誤:無法åˆä½µå模組 %s (版本庫æå£žï¼‰" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "無法åˆä½µå模組 %s (æäº¤æœªè·Ÿéš¨åˆä½µåŸºç¤Žï¼‰" @@ -21448,12 +21566,12 @@ msgstr "éŒ¯èª¤ï¼šç„¡æ³•å° %s 執行內部åˆä½µ" msgid "error: unable to add %s to database" msgstr "錯誤:無法將 %s åŠ é€²è³‡æ–™åº«" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "Auto-merging %s" msgstr "自動åˆä½µ %s" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (implicit dir rename): Existing file/dir at %s in the way of " @@ -21462,7 +21580,7 @@ msgstr "" "è¡çªï¼ˆéš±å¼ç›®éŒ„釿–°å‘½å):處於隱å¼ç›®éŒ„釿–°å‘½åçš„ç¾å˜æª”案/目錄 %s,將以下路徑" "放在:%s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (implicit dir rename): Cannot map more than one path to %s; " @@ -21481,14 +21599,14 @@ msgstr "" "è¡çªï¼ˆåˆ†å‰²çš„ç›®éŒ„é‡æ–°å‘½å):未知 %s 釿–°å‘½åçš„ä½ç½®ã€‚å®ƒè¢«é‡æ–°å‘½å為多個其他目" "錄,但沒有目的地å–å¾—éŽåŠæª”案。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was " "renamed." msgstr "è¦å‘Šï¼šé¿å…套用 %s -> %s çš„é‡æ–°å‘½å到 %sï¼Œå› ç‚º %s æœ¬èº«å·²è¢«é‡æ–°å‘½å。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "Path updated: %s added in %s inside a directory that was renamed in %s; " @@ -21496,7 +21614,7 @@ msgid "" msgstr "" "路徑已更新:%s 新增到 %sï¼Œä½æ–¼ä¸€å€‹è¢«é‡æ–°å‘½å到 %s 的目錄ä¸ï¼Œå°‡å…¶ç§»å‹•到 %s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "Path updated: %s renamed to %s in %s, inside a directory that was renamed in " @@ -21505,7 +21623,7 @@ msgstr "" "路徑已更新:%1$s 釿–°å‘½å為 %3$s ä¸çš„ %2$sï¼Œè€Œè©²ç›®éŒ„è¢«é‡æ–°å‘½å到 %4$s ä¸ï¼Œå°‡" "其移動到 %5$s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (file location): %s added in %s inside a directory that was renamed " @@ -21514,7 +21632,7 @@ msgstr "" "è¡çªï¼ˆæª”案ä½ç½®ï¼‰ï¼š%s 新增到 %sï¼Œä½æ–¼ä¸€å€‹è¢«é‡æ–°å‘½å為 %s 的目錄ä¸ï¼Œå»ºè°å°‡å…¶ç§»" "動到 %s。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "" "CONFLICT (file location): %s renamed to %s in %s, inside a directory that " @@ -21581,19 +21699,19 @@ msgstr "" "è¡çªï¼ˆé¡žåž‹æœ‰ç•°ï¼‰ï¼šå…©æ–¹çš„ %s 類型皆ä¸åŒã€‚å·²ç¶“é‡æ–°å‘½åå…¶ä¸ä¸€å€‹ä¾†æºï¼Œé€™æ¨£å°±å¯ä»¥" "分別記錄這兩方檔案。" -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "content" msgstr "內容" -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "add/add" msgstr "新增/新增" -#: merge-ort.c merge-recursive.c +#: merge-ort.c msgid "submodule" msgstr "忍¡çµ„" -#: merge-ort.c merge-recursive.c +#: merge-ort.c #, c-format msgid "CONFLICT (%s): Merge conflict in %s" msgstr "è¡çªï¼ˆ%s):åˆä½µè¡çªæ–¼ %s" @@ -21655,312 +21773,6 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "%s, %s, %s 樹的åˆä½µè³‡è¨Šæ”¶é›†å¤±æ•—" -#: merge-recursive.c -msgid "(bad commit)\n" -msgstr "(壞æäº¤ï¼‰\n" - -#: merge-recursive.c -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "add_cacheinfo å°è·¯å¾‘ '%s' 執行失敗,åˆä½µçµ‚æ¢ã€‚" - -#: merge-recursive.c -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "add_cacheinfo ç„¡æ³•é‡æ–°æ•´ç†è·¯å¾‘ '%s',åˆä½µçµ‚æ¢ã€‚" - -#: merge-recursive.c -#, c-format -msgid "failed to create path '%s'%s" -msgstr "建立路徑 '%s'%s 失敗" - -#: merge-recursive.c -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "刪除 %s 以便為å目錄留出空間\n" - -#: merge-recursive.c -msgid ": perhaps a D/F conflict?" -msgstr ":å¯èƒ½æ˜¯ä¸€å€‹ç›®éŒ„/檔案è¡çªï¼Ÿ" - -#: merge-recursive.c -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "æ‹’çµ•æ¨æ£„ '%s' ä¸çš„æœªè¿½è¹¤æª”案" - -#: merge-recursive.c -#, c-format -msgid "blob expected for %s '%s'" -msgstr "%s '%s' 應為資料物件" - -#: merge-recursive.c -#, c-format -msgid "failed to open '%s': %s" -msgstr "開啟 '%s' 失敗:%s" - -#: merge-recursive.c -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "å»ºç«‹ç¬¦è™Ÿé€£çµ '%s' 失敗:%s" - -#: merge-recursive.c -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "ä¸çŸ¥é“å¦‚ä½•è™•ç† %06o %s '%s'" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "無法åˆä½µå模組 %s (版本庫æå£žï¼‰" - -#: merge-recursive.c -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "忍¡çµ„ %s 快轉到如下æäº¤ï¼š" - -#: merge-recursive.c -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "å¿«è½‰åæ¨¡çµ„ %s" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "無法åˆä½µå模組 %s (找ä¸åˆ°åˆä½µè·Ÿéš¨çš„æäº¤ï¼‰" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "無法åˆä½µå模組 %s(éžå¿«è½‰ï¼‰" - -#: merge-recursive.c -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "æ‰¾åˆ°åæ¨¡çµ„的一個å¯èƒ½çš„åˆä½µæ–¹æ¡ˆï¼š\n" - -#: merge-recursive.c -#, 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" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"æŽ¥å—æœ¬å»ºè°ã€‚\n" - -#: merge-recursive.c -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "無法åˆä½µå模組 %s (發ç¾å¤šå€‹åˆä½µï¼‰" - -#: merge-recursive.c -msgid "failed to execute internal merge" -msgstr "無法執行內部åˆä½µ" - -#: merge-recursive.c -#, c-format -msgid "unable to add %s to database" -msgstr "無法將 %s åŠ é€²è³‡æ–™åº«" - -#: merge-recursive.c -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "錯誤:拒絕éºå¤±æœªè¿½è¹¤æª”案 '%s',而是寫入 %s。" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %5$s ä¸è¢« %4$s。%7$s çš„ %6$s 版" -"本被ä¿ç•™ã€‚" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %6$s ä¸çš„ %5$s 被 %4$s。%8$s çš„ " -"%7$s 版本被ä¿ç•™ã€‚" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %5$s ä¸è¢« %4$s。%7$s çš„ %6$s 版" -"本ä¿ç•™åœ¨ %8$s ä¸ã€‚" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %6$s ä¸çš„ %5$s 被 %4$s。%8$s çš„ " -"%7$s 版本ä¿ç•™åœ¨ %9$s ä¸ã€‚" - -#: merge-recursive.c -msgid "rename" -msgstr "釿–°å‘½å" - -#: merge-recursive.c -msgid "renamed" -msgstr "已釿–°å‘½å" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "拒絕éºå¤±é«’檔案 '%s'" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "拒絕在 '%s' 處失去未追蹤檔案,å³ä½¿å®ƒå˜åœ¨æ–¼é‡æ–°å‘½åä¸ã€‚" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"è¡çªï¼ˆé‡æ–°å‘½å/新增):在 %3$s ä¸é‡æ–°å‘½å %1$s->%2$s。在 %5$s 䏿–°å¢ž %4$s" - -#: merge-recursive.c -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s 是 %s ä¸çš„一個目錄而已 %s 為å被新增" - -#: merge-recursive.c -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "拒絕éºå¤±æœªè¿½è¹¤æª”案 '%s',而是新增為 %s" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"è¡çªï¼ˆé‡æ–°å‘½å/釿–°å‘½å):在分支 \"%3$s\" ä¸é‡æ–°å‘½å \"%1$s\"->\"%2$s\",在" -"分支 \"%6$s\" ä¸é‡æ–°å‘½å \"%4$s\"->\"%5$s\"%7$s" - -#: merge-recursive.c -msgid " (left unresolved)" -msgstr " (留下未解決)" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"è¡çªï¼ˆé‡æ–°å‘½å/釿–°å‘½å):在 %3$s ä¸é‡æ–°å‘½å %1$s->%2$s,在 %6$s ä¸é‡æ–°å‘½å " -"%4$s->%5$s" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"è¡çªï¼ˆåˆ†å‰²çš„ç›®éŒ„é‡æ–°å‘½åï¼‰ï¼šä¸æ¸…楚 %s æ‡‰è©²æ”¾åœ¨å“ªè£¡ï¼Œå› ç‚ºç›®éŒ„ %s è¢«é‡æ–°å‘½å到" -"多個其它目錄,沒有目錄包å«å¤§éƒ¨åˆ†æª”案。" - -#: merge-recursive.c -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"è¡çªï¼ˆé‡æ–°å‘½å/釿–°å‘½å):在 %3$s ä¸é‡æ–°å‘½å目錄 %1$s->%2$s,在 %6$s ä¸é‡æ–°" -"命å目錄 %4$s->%5$s" - -#: merge-recursive.c -#, c-format -msgid "cannot read object %s" -msgstr "ä¸èƒ½è®€å–物件 %s" - -#: merge-recursive.c -#, c-format -msgid "object %s is not a blob" -msgstr "物件 %s 䏿˜¯ä¸€å€‹è³‡æ–™ç‰©ä»¶" - -#: merge-recursive.c -msgid "modify" -msgstr "修改" - -#: merge-recursive.c -msgid "modified" -msgstr "修改" - -#: merge-recursive.c -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "ç•¥éŽ %s(已經åšéŽç›¸åŒåˆä½µï¼‰" - -#: merge-recursive.c -#, c-format -msgid "Adding as %s instead" -msgstr "而是以 %s ç‚ºåæ–°å¢ž" - -#: merge-recursive.c -#, c-format -msgid "Removing %s" -msgstr "刪除 %s" - -#: merge-recursive.c -msgid "file/directory" -msgstr "檔案/目錄" - -#: merge-recursive.c -msgid "directory/file" -msgstr "目錄/檔案" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "è¡çªï¼ˆ%1$s):在 %3$s 䏿œ‰ä¸€å€‹å為 %2$s 的目錄。以 %5$s ç‚ºåæ–°å¢ž %4$s" - -#: merge-recursive.c -#, c-format -msgid "Adding %s" -msgstr "新增 %s" - -#: merge-recursive.c -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "è¡çªï¼ˆadd/add):åˆä½µè¡çªæ–¼ %s" - -#: merge-recursive.c -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "無法åˆä½µæ¨¹ %s å’Œ %s" - -#: merge-recursive.c -msgid "Merging:" -msgstr "åˆä½µï¼š" - -#: merge-recursive.c -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "ç™¼ç¾ %u 個共åŒç¥–先:" - -#: merge-recursive.c -msgid "merge returned no commit" -msgstr "åˆä½µæœªè¿”回æäº¤" - -#: merge-recursive.c -#, c-format -msgid "Could not parse object '%s'" -msgstr "無法解æžç‰©ä»¶ã€Œ%sã€" - #: merge.c msgid "failed to read the cache" msgstr "讀å–å¿«å–失敗" @@ -22014,14 +21826,15 @@ msgid "failed to clear multi-pack-index at %s" msgstr "清ç†ä½æ–¼ %s 的多包索引失敗" #: midx-write.c -msgid "cannot write incremental MIDX with bitmap" -msgstr "無法寫入有ä½åœ–çš„å¢žé‡ MIDX" - -#: midx-write.c msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "å¿½ç•¥ç¾æœ‰çš„多包索引:總和檢查碼ä¸ç¬¦" #: midx-write.c +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "無法載入 MIDX %s çš„åå‘索引" + +#: midx-write.c msgid "Adding packfiles to multi-pack-index" msgstr "æ£åœ¨æ–°å¢ž packfile 至多包索引" @@ -22337,78 +22150,6 @@ msgstr "無法將物件從 %s 轉æ›ç‚º %s" #: object-file.c #, c-format -msgid "object directory %s does not exist; check .git/objects/info/alternates" -msgstr "物件目錄 %s ä¸å˜åœ¨ï¼Œæª¢æŸ¥ .git/objects/info/alternates" - -#: object-file.c -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "無法è¦ç¯„化備用物件路徑:%s" - -#: object-file.c -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s:忽略備用物件庫,嵌套太深" - -#: object-file.c -msgid "unable to fdopen alternates lockfile" -msgstr "無法 fdopen å–代鎖檔案" - -#: object-file.c -msgid "unable to read alternates file" -msgstr "ç„¡æ³•è®€å–æ›¿ä»£æª”案" - -#: object-file.c -msgid "unable to move new alternates file into place" -msgstr "無法將新的替代檔案移動到ä½" - -#: object-file.c -#, c-format -msgid "path '%s' does not exist" -msgstr "路徑 '%s' ä¸å˜åœ¨" - -#: object-file.c -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "å°šä¸æ”¯æ´å°‡å¼•用版本庫 '%s' 作為一個連çµç°½å‡ºã€‚" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "引用版本庫 '%s' 䏿˜¯ä¸€å€‹æœ¬æ©Ÿç‰ˆæœ¬åº«ã€‚" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "引用版本庫 '%s' 是一個淺複製" - -#: object-file.c -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "引用版本庫 '%s' 已被移æ¤" - -#: object-file.c -#, c-format -msgid "could not find object directory matching %s" -msgstr "找ä¸åˆ°ç¬¦åˆ %s 的物件目錄" - -#: object-file.c -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "è§£æžå‚™ç”¨å¼•用時無效的行:%s" - -#: object-file.c -#, c-format -msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" -msgstr "嘗試 mmap %<PRIuMAX>,超éŽäº†æœ€å¤§å€¼ %<PRIuMAX>" - -#: object-file.c -#, c-format -msgid "mmap failed%s" -msgstr "mmap 失敗%s" - -#: object-file.c -#, c-format msgid "object file %s is empty" msgstr "物件檔案 %s 為空" @@ -22453,21 +22194,6 @@ msgstr "鬆散物件 %s(儲å˜åœ¨ %s)已æå£ž" #: object-file.c #, c-format -msgid "replacement %s not found for %s" -msgstr "找ä¸åˆ° %2$s 的替代 %1$s" - -#: object-file.c -#, c-format -msgid "packed object %s (stored in %s) is corrupt" -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 open %s" msgstr "ä¸èƒ½é–‹å•Ÿ %s" @@ -22584,11 +22310,6 @@ msgstr "%sï¼šä¸æ”¯æ´çš„æª”案類型" #: object-file.c #, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s 䏿˜¯ä¸€å€‹æœ‰æ•ˆçš„ '%s' 物件" - -#: object-file.c -#, c-format msgid "hash mismatch for %s (expected %s)" msgstr "%s 的雜湊值ä¸ç¬¦åˆï¼ˆé 期 %s)" @@ -22609,6 +22330,11 @@ msgstr "ç„¡æ³•è§£æž %s çš„é 部" #: object-file.c #, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "無法從 %2$s 的標é 「%1$sã€è§£æžé¡žåž‹" + +#: object-file.c +#, c-format msgid "unable to unpack contents of %s" msgstr "無法解壓縮 %s 的內容" @@ -22785,6 +22511,88 @@ msgstr "éœ€è¦æŒ‡å®š <object>:<path>,å»åªæŒ‡å®š <object>「%sã€" msgid "invalid object name '%.*s'." msgstr "'%.*s' 物件å稱無效。" +#: object-store.c +#, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "物件目錄 %s ä¸å˜åœ¨ï¼Œæª¢æŸ¥ .git/objects/info/alternates" + +#: object-store.c +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "無法è¦ç¯„化備用物件路徑:%s" + +#: object-store.c +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s:忽略備用物件庫,嵌套太深" + +#: object-store.c +msgid "unable to fdopen alternates lockfile" +msgstr "無法 fdopen å–代鎖檔案" + +#: object-store.c +msgid "unable to read alternates file" +msgstr "ç„¡æ³•è®€å–æ›¿ä»£æª”案" + +#: object-store.c +msgid "unable to move new alternates file into place" +msgstr "無法將新的替代檔案移動到ä½" + +#: object-store.c +#, c-format +msgid "path '%s' does not exist" +msgstr "路徑 '%s' ä¸å˜åœ¨" + +#: object-store.c +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "å°šä¸æ”¯æ´å°‡å¼•用版本庫 '%s' 作為一個連çµç°½å‡ºã€‚" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "引用版本庫 '%s' 䏿˜¯ä¸€å€‹æœ¬æ©Ÿç‰ˆæœ¬åº«ã€‚" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "引用版本庫 '%s' 是一個淺複製" + +#: object-store.c +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "引用版本庫 '%s' 已被移æ¤" + +#: object-store.c +#, c-format +msgid "could not find object directory matching %s" +msgstr "找ä¸åˆ°ç¬¦åˆ %s 的物件目錄" + +#: object-store.c +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "è§£æžå‚™ç”¨å¼•用時無效的行:%s" + +#: object-store.c +#, c-format +msgid "replacement %s not found for %s" +msgstr "找ä¸åˆ° %2$s 的替代 %1$s" + +#: object-store.c +#, c-format +msgid "packed object %s (stored in %s) is corrupt" +msgstr "打包物件 %s(儲å˜åœ¨ %s)已æå£ž" + +#: object-store.c +#, c-format +msgid "missing mapping of %s to %s" +msgstr "缺少 %s 到 %s çš„æ˜ å°„" + +#: object-store.c +#, c-format +msgid "%s is not a valid '%s' object" +msgstr "%s 䏿˜¯ä¸€å€‹æœ‰æ•ˆçš„ '%s' 物件" + #: object.c #, c-format msgid "invalid object type \"%s\"" @@ -23132,6 +22940,16 @@ msgstr "%s ä¸å¯ç”¨" #: parse-options.c #, c-format +msgid "value %s for %s not in range [%<PRIdMAX>,%<PRIdMAX>]" +msgstr "%2$s 的數值 %1$s ä¸åœ¨ [%3$<PRIdMAX>,%4$<PRIdMAX>] 範åœå…§" + +#: parse-options.c +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s æœŸæœ›ç‚ºä¸€å€‹é¸æ“‡æ€§å¸¶æœ‰ k/m/g 後綴的整數值" + +#: parse-options.c +#, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "%s 期望一個éžè² 整數和一個å¯é¸çš„ k/m/g 後綴" @@ -23316,11 +23134,6 @@ msgstr "如使用 --pathspec-from-file,則 <è·¯å¾‘è¦æ ¼> 元件會使用 NUL msgid "bad boolean environment value '%s' for '%s'" msgstr "「%2$sã€çš„「%1$sã€å¸ƒæž—環境值無效" -#: parse.c -#, c-format -msgid "failed to parse %s" -msgstr "è§£æž %s 失敗" - #: path-walk.c #, c-format msgid "failed to walk children of tree %s: not found" @@ -23523,7 +23336,12 @@ msgstr "無法從承諾者é ç«¯æŠ“å– %s" #: promisor-remote.c #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgid "no or empty URL advertised for remote '%s'" +msgstr "é 端「%sã€æœªå…¬ä½ˆ URL 或 URL 空白" + +#: promisor-remote.c +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" msgstr "已知有é 端å為「%sã€ï¼Œä½†å…¶ URL 為「%sã€è€Œéžã€Œ%sã€" #: promisor-remote.c @@ -23652,7 +23470,7 @@ msgstr "無法解æžã€Œ%sã€çš„æ—¥èªŒ" #: reachable.c #, c-format msgid "invalid extra cruft tip: '%s'" -msgstr "無效的é¡å¤–廢棄æäº¤ä¿®è¨‚版:「%sã€" +msgstr "無效的é¡å¤–無用æäº¤ä¿®è¨‚版:「%sã€" #: reachable.c msgid "unable to enumerate additional recent objects" @@ -24425,6 +24243,11 @@ msgstr "無法開啟 %s 目錄" msgid "Checking references consistency" msgstr "æ£åœ¨æª¢æŸ¥å¼•用一致性" +#: refs/packed-backend.c +#, c-format +msgid "unable to open '%s'" +msgstr "無法開啟「%sã€" + #: refs/reftable-backend.c #, c-format msgid "refname is dangerous: %s" @@ -24505,11 +24328,6 @@ msgstr "引用å稱 %s æ˜¯ç¬¦è™Ÿå¼•ç”¨ï¼Œä¸æ”¯æ´è¤‡è£½" #: refspec.c #, c-format -msgid "invalid refspec '%s'" -msgstr "ç„¡æ•ˆçš„å¼•ç”¨è¦æ ¼ï¼šã€Œ%sã€" - -#: refspec.c -#, c-format msgid "pattern '%s' has no '*'" msgstr "ç¬¦åˆæ¨¡å¼ã€Œ%sã€ä¸æ²’有「*ã€" @@ -25164,8 +24982,8 @@ msgid "could not set recommended config" msgstr "無法è¨å®šå»ºè°çµ„æ…‹" #: scalar.c -msgid "could not turn on maintenance" -msgstr "無法開啟ç¶è·æ¨¡å¼" +msgid "could not toggle maintenance" +msgstr "無法切æ›ç¶è·æ¨¡å¼" #: scalar.c msgid "could not start the FSMonitor daemon" @@ -25225,12 +25043,19 @@ msgid "specify if tags should be fetched during clone" msgstr "指定是å¦è¦åœ¨è¤‡è£½éšŽæ®µæŠ“å–æ¨™ç±¤" #: scalar.c +msgid "specify if background maintenance should be enabled" +msgstr "指定是å¦è¦å•Ÿç”¨èƒŒæ™¯ç¶è·æ¨¡å¼" + +#: scalar.c +#| msgid "" +#| "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" +#| "\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" msgid "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" msgstr "" "scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]" #: scalar.c #, c-format @@ -25279,16 +25104,31 @@ msgid "`scalar list` does not take arguments" msgstr "`scalar list` 未å–引數" #: scalar.c -msgid "scalar register [<enlistment>]" -msgstr "scalar register [<enlistment>]" +#| msgid "scalar register [<enlistment>]" +msgid "scalar register [--[no-]maintenance] [<enlistment>]" +msgstr "scalar register [--[no-]maintenance] [<enlistment>]" #: scalar.c msgid "reconfigure all registered enlistments" msgstr "釿–°è¨å®šæ‰€æœ‰è¨»å†Šçš„編列åå–®" #: scalar.c -msgid "scalar reconfigure [--all | <enlistment>]" -msgstr "scalar reconfigure [--all | <enlistment>]" +#| msgid "enable/disable untracked cache" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +#: scalar.c +msgid "signal how to adjust background maintenance" +msgstr "指示調整背景ç¶è·æ¨¡å¼çš„æ–¹å¼" + +#: scalar.c +#| msgid "scalar reconfigure [--all | <enlistment>]" +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"<enlistment>]" #: scalar.c msgid "--all or <enlistment>, but not both" @@ -25296,6 +25136,11 @@ msgstr "--all 或 <enlistment> 但ä¸èƒ½å‚³å…¥å…©è€…" #: scalar.c #, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "--maintenance é¸é …的值無效:%s" + +#: scalar.c +#, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "ç„¡æ³•ç§»é™¤éŽæ™‚çš„ scalar.repo「%sã€" @@ -27003,6 +26848,10 @@ msgstr "æ¯æ¬¡è¿ä»£å‰æ¸…é™¤å¿«å–æ¨¹ç‹€ç‰©ä»¶" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "åœ¨å¿«å–æ¨¹ç‹€ç‰©ä»¶ä¸ï¼Œè¦ä½¿å¤±æ•ˆçš„é …ç›®æ•¸é‡ï¼ˆé è¨å€¼ç‚º 0)" +#: t/helper/test-pack-deltas.c +msgid "the number of objects to write" +msgstr "è¦å¯«å…¥çš„物件數é‡" + #: t/helper/test-path-walk.c msgid "test-tool path-walk <options> -- <revision-options>" msgstr "test-tool path-walk <options> -- <revision-options>" @@ -27931,6 +27780,16 @@ msgstr "ä¸èƒ½å–å¾—ç›®å‰å·¥ä½œç›®éŒ„" msgid "unable to get random bytes" msgstr "無法å–得隨機ä½å…ƒçµ„" +#: wrapper.c +#, c-format +msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>" +msgstr "嘗試 mmap %<PRIuMAX>,超éŽäº†æœ€å¤§å€¼ %<PRIuMAX>" + +#: wrapper.c +#, c-format +msgid "mmap failed%s" +msgstr "mmap 失敗%s" + #: wt-status.c msgid "Unmerged paths:" msgstr "未åˆä½µçš„路徑:" @@ -28851,6 +28710,15 @@ msgstr "無法æ£ç¢ºåœ°åˆå§‹åŒ– SMTP。檢查è¨å®šä¸¦ä½¿ç”¨ --smtp-debug。" #: git-send-email.perl #, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook å°‡ Message-ID 釿–°æŒ‡æ´¾ç‚ºï¼š%s\n" + +#: git-send-email.perl +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "è¦å‘Šï¼šç„¡æ³•從伺æœå™¨å›žæ‡‰ä¸å–å¾— Message-ID。\n" + +#: git-send-email.perl +#, perl-format msgid "Failed to send %s\n" msgstr "ç„¡æ³•å‚³é€ %s\n" @@ -28969,6 +28837,272 @@ msgstr "ç•¥éŽ %s å«å‚™ä»½å¾Œç¶´ '%s'。\n" msgid "Do you really want to send %s? [y|N]: " msgstr "您真的è¦å‚³é€ %s?[y|N]: " +#~ msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>" +#~ msgstr "git cat-file (-t | -s) [--allow-unknown-type] <object>" + +#~ msgid "allow -s and -t to work with broken/corrupt objects" +#~ msgstr "å…許 -s å’Œ -t å°æå£žçš„ç‰©ä»¶ç”Ÿæ•ˆ" + +#, c-format +#~ msgid "%s: object is of unknown type '%s': %s" +#~ msgstr "%s:物件屬於「%sã€æœªçŸ¥é¡žåž‹ï¼š%s" + +#, c-format +#~ msgid "%s points nowhere!" +#~ msgstr "%s 指å‘ä¸å˜åœ¨ï¼" + +#~ msgid "(bad commit)\n" +#~ msgstr "(壞æäº¤ï¼‰\n" + +#, c-format +#~ msgid "add_cacheinfo failed for path '%s'; merge aborting." +#~ msgstr "add_cacheinfo å°è·¯å¾‘ '%s' 執行失敗,åˆä½µçµ‚æ¢ã€‚" + +#, c-format +#~ msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." +#~ msgstr "add_cacheinfo ç„¡æ³•é‡æ–°æ•´ç†è·¯å¾‘ '%s',åˆä½µçµ‚æ¢ã€‚" + +#, c-format +#~ msgid "failed to create path '%s'%s" +#~ msgstr "建立路徑 '%s'%s 失敗" + +#, c-format +#~ msgid "Removing %s to make room for subdirectory\n" +#~ msgstr "刪除 %s 以便為å目錄留出空間\n" + +#~ msgid ": perhaps a D/F conflict?" +#~ msgstr ":å¯èƒ½æ˜¯ä¸€å€‹ç›®éŒ„/檔案è¡çªï¼Ÿ" + +#, c-format +#~ msgid "refusing to lose untracked file at '%s'" +#~ msgstr "æ‹’çµ•æ¨æ£„ '%s' ä¸çš„æœªè¿½è¹¤æª”案" + +#, c-format +#~ msgid "blob expected for %s '%s'" +#~ msgstr "%s '%s' 應為資料物件" + +#, c-format +#~ msgid "failed to open '%s': %s" +#~ msgstr "開啟 '%s' 失敗:%s" + +#, c-format +#~ msgid "failed to symlink '%s': %s" +#~ msgstr "å»ºç«‹ç¬¦è™Ÿé€£çµ '%s' 失敗:%s" + +#, c-format +#~ msgid "do not know what to do with %06o %s '%s'" +#~ msgstr "ä¸çŸ¥é“å¦‚ä½•è™•ç† %06o %s '%s'" + +#, c-format +#~ msgid "Failed to merge submodule %s (repository corrupt)" +#~ msgstr "無法åˆä½µå模組 %s (版本庫æå£žï¼‰" + +#, c-format +#~ msgid "Fast-forwarding submodule %s to the following commit:" +#~ msgstr "忍¡çµ„ %s 快轉到如下æäº¤ï¼š" + +#, c-format +#~ msgid "Fast-forwarding submodule %s" +#~ msgstr "å¿«è½‰åæ¨¡çµ„ %s" + +#, c-format +#~ msgid "Failed to merge submodule %s (merge following commits not found)" +#~ msgstr "無法åˆä½µå模組 %s (找ä¸åˆ°åˆä½µè·Ÿéš¨çš„æäº¤ï¼‰" + +#, c-format +#~ msgid "Failed to merge submodule %s (not fast-forward)" +#~ msgstr "無法åˆä½µå模組 %s(éžå¿«è½‰ï¼‰" + +#~ msgid "Found a possible merge resolution for the submodule:\n" +#~ msgstr "æ‰¾åˆ°åæ¨¡çµ„的一個å¯èƒ½çš„åˆä½µæ–¹æ¡ˆï¼š\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" +#~ "\n" +#~ " git update-index --cacheinfo 160000 %s \"%s\"\n" +#~ "\n" +#~ "æŽ¥å—æœ¬å»ºè°ã€‚\n" + +#, c-format +#~ msgid "Failed to merge submodule %s (multiple merges found)" +#~ msgstr "無法åˆä½µå模組 %s (發ç¾å¤šå€‹åˆä½µï¼‰" + +#~ msgid "failed to execute internal merge" +#~ msgstr "無法執行內部åˆä½µ" + +#, c-format +#~ msgid "unable to add %s to database" +#~ msgstr "無法將 %s åŠ é€²è³‡æ–™åº«" + +#, c-format +#~ msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." +#~ msgstr "錯誤:拒絕éºå¤±æœªè¿½è¹¤æª”案 '%s',而是寫入 %s。" + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s " +#~ "left in tree." +#~ msgstr "" +#~ "è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %5$s ä¸è¢« %4$s。%7$s çš„ %6$s " +#~ "版本被ä¿ç•™ã€‚" + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of " +#~ "%s left in tree." +#~ msgstr "" +#~ "è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %6$s ä¸çš„ %5$s 被 %4$s。%8$s " +#~ "çš„ %7$s 版本被ä¿ç•™ã€‚" + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s " +#~ "left in tree at %s." +#~ msgstr "" +#~ "è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %5$s ä¸è¢« %4$s。%7$s çš„ %6$s " +#~ "版本ä¿ç•™åœ¨ %8$s ä¸ã€‚" + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of " +#~ "%s left in tree at %s." +#~ msgstr "" +#~ "è¡çªï¼ˆ%1$s/刪除):%2$s 在 %3$s ä¸è¢«åˆªé™¤ï¼Œåœ¨ %6$s ä¸çš„ %5$s 被 %4$s。%8$s " +#~ "çš„ %7$s 版本ä¿ç•™åœ¨ %9$s ä¸ã€‚" + +#~ msgid "rename" +#~ msgstr "釿–°å‘½å" + +#~ msgid "renamed" +#~ msgstr "已釿–°å‘½å" + +#, c-format +#~ msgid "Refusing to lose dirty file at %s" +#~ msgstr "拒絕éºå¤±é«’檔案 '%s'" + +#, c-format +#~ msgid "Refusing to lose untracked file at %s, even though it's in the way." +#~ msgstr "拒絕在 '%s' 處失去未追蹤檔案,å³ä½¿å®ƒå˜åœ¨æ–¼é‡æ–°å‘½åä¸ã€‚" + +#, c-format +#~ msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" +#~ msgstr "" +#~ "è¡çªï¼ˆé‡æ–°å‘½å/新增):在 %3$s ä¸é‡æ–°å‘½å %1$s->%2$s。在 %5$s 䏿–°å¢ž %4$s" + +#, c-format +#~ msgid "%s is a directory in %s adding as %s instead" +#~ msgstr "%s 是 %s ä¸çš„一個目錄而已 %s 為å被新增" + +#, c-format +#~ msgid "Refusing to lose untracked file at %s; adding as %s instead" +#~ msgstr "拒絕éºå¤±æœªè¿½è¹¤æª”案 '%s',而是新增為 %s" + +#, c-format +#~ msgid "" +#~ "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " +#~ "\"%s\"->\"%s\" in \"%s\"%s" +#~ msgstr "" +#~ "è¡çªï¼ˆé‡æ–°å‘½å/釿–°å‘½å):在分支 \"%3$s\" ä¸é‡æ–°å‘½å \"%1$s\"->\"%2$s\"," +#~ "在分支 \"%6$s\" ä¸é‡æ–°å‘½å \"%4$s\"->\"%5$s\"%7$s" + +#~ msgid " (left unresolved)" +#~ msgstr " (留下未解決)" + +#, c-format +#~ msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" +#~ msgstr "" +#~ "è¡çªï¼ˆé‡æ–°å‘½å/釿–°å‘½å):在 %3$s ä¸é‡æ–°å‘½å %1$s->%2$s,在 %6$s ä¸é‡æ–°å‘½" +#~ "å %4$s->%5$s" + +#, c-format +#~ msgid "" +#~ "CONFLICT (directory rename split): Unclear where to place %s because " +#~ "directory %s was renamed to multiple other directories, with no " +#~ "destination getting a majority of the files." +#~ msgstr "" +#~ "è¡çªï¼ˆåˆ†å‰²çš„ç›®éŒ„é‡æ–°å‘½åï¼‰ï¼šä¸æ¸…楚 %s æ‡‰è©²æ”¾åœ¨å“ªè£¡ï¼Œå› ç‚ºç›®éŒ„ %s è¢«é‡æ–°å‘½å" +#~ "到多個其它目錄,沒有目錄包å«å¤§éƒ¨åˆ†æª”案。" + +#, c-format +#~ msgid "" +#~ "CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory " +#~ "%s->%s in %s" +#~ msgstr "" +#~ "è¡çªï¼ˆé‡æ–°å‘½å/釿–°å‘½å):在 %3$s ä¸é‡æ–°å‘½å目錄 %1$s->%2$s,在 %6$s ä¸é‡" +#~ "新命å目錄 %4$s->%5$s" + +#, c-format +#~ msgid "cannot read object %s" +#~ msgstr "ä¸èƒ½è®€å–物件 %s" + +#, c-format +#~ msgid "object %s is not a blob" +#~ msgstr "物件 %s 䏿˜¯ä¸€å€‹è³‡æ–™ç‰©ä»¶" + +#~ msgid "modify" +#~ msgstr "修改" + +#~ msgid "modified" +#~ msgstr "修改" + +#, c-format +#~ msgid "Skipped %s (merged same as existing)" +#~ msgstr "ç•¥éŽ %s(已經åšéŽç›¸åŒåˆä½µï¼‰" + +#, c-format +#~ msgid "Adding as %s instead" +#~ msgstr "而是以 %s ç‚ºåæ–°å¢ž" + +#, c-format +#~ msgid "Removing %s" +#~ msgstr "刪除 %s" + +#~ msgid "file/directory" +#~ msgstr "檔案/目錄" + +#~ msgid "directory/file" +#~ msgstr "目錄/檔案" + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" +#~ msgstr "" +#~ "è¡çªï¼ˆ%1$s):在 %3$s 䏿œ‰ä¸€å€‹å為 %2$s 的目錄。以 %5$s ç‚ºåæ–°å¢ž %4$s" + +#, c-format +#~ msgid "Adding %s" +#~ msgstr "新增 %s" + +#, c-format +#~ msgid "CONFLICT (add/add): Merge conflict in %s" +#~ msgstr "è¡çªï¼ˆadd/add):åˆä½µè¡çªæ–¼ %s" + +#, c-format +#~ msgid "merging of trees %s and %s failed" +#~ msgstr "無法åˆä½µæ¨¹ %s å’Œ %s" + +#~ msgid "Merging:" +#~ msgstr "åˆä½µï¼š" + +#, c-format +#~ msgid "found %u common ancestor:" +#~ msgid_plural "found %u common ancestors:" +#~ msgstr[0] "ç™¼ç¾ %u 個共åŒç¥–先:" + +#~ msgid "merge returned no commit" +#~ msgstr "åˆä½µæœªè¿”回æäº¤" + +#~ msgid "cannot write incremental MIDX with bitmap" +#~ msgstr "無法寫入有ä½åœ–çš„å¢žé‡ MIDX" + #, c-format #~ msgid "Could not find remote branch %s to clone." #~ msgstr "找ä¸åˆ°è¦è¤‡è£½çš„é 端分支 %s。" @@ -28977,9 +29111,6 @@ msgstr "您真的è¦å‚³é€ %s?[y|N]: " #~ msgid "merging cannot continue; got unclean result of %d" #~ msgstr "無法繼續åˆä½µï¼šå¾ž %d æ”¶åˆ°çš„çµæžœä¸ä¹¾æ·¨" -#~ msgid "git repack [<options>]" -#~ msgstr "git repack [<é¸é …>]" - #~ msgid "--onto and --advance are incompatible" #~ msgstr "--onto å’Œ --advance ä¸ç›¸å®¹" @@ -29029,10 +29160,6 @@ msgstr "您真的è¦å‚³é€ %s?[y|N]: " #~ msgstr "使用 [RFC PATCH] 代替 [PATCH]" #, c-format -#~ msgid "no URLs configured for remote '%s'" -#~ msgstr "沒有給é 端版本庫 '%s' è¨å®š URL" - -#, c-format #~ msgid "remote '%s' has no configured URL" #~ msgstr "“%s†é 端未è¨å®š URL" diff --git a/preload-index.c b/preload-index.c index 40ab2abafb..b222821b44 100644 --- a/preload-index.c +++ b/preload-index.c @@ -2,7 +2,6 @@ * Copyright (C) 2008 Linus Torvalds */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -19,6 +18,7 @@ #include "repository.h" #include "symlinks.h" #include "trace2.h" +#include "config.h" /* * Mostly randomly chosen maximum thread counts: we @@ -111,6 +111,9 @@ void preload_index(struct index_state *index, struct thread_data data[MAX_PARALLEL]; struct progress_data pd; int t2_sum_lstat = 0; + int core_preload_index = 1; + + repo_config_get_bool(index->repo, "core.preloadindex", &core_preload_index); if (!HAVE_THREADS || !core_preload_index) return; @@ -132,7 +135,7 @@ void preload_index(struct index_state *index, memset(&pd, 0, sizeof(pd)); if (refresh_flags & REFRESH_PROGRESS && isatty(2)) { - pd.progress = start_delayed_progress(the_repository, + pd.progress = start_delayed_progress(index->repo, _("Refreshing index"), index->cache_nr); pthread_mutex_init(&pd.mutex, NULL); diff --git a/promisor-remote.c b/promisor-remote.c index 6a0a61382f..9d058586df 100644 --- a/promisor-remote.c +++ b/promisor-remote.c @@ -3,7 +3,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "promisor-remote.h" #include "config.h" #include "trace2.h" @@ -323,13 +323,15 @@ static void promisor_info_vecs(struct repository *repo, promisor_remote_init(repo); for (r = repo->promisor_remote_config->promisors; r; r = r->next) { - char *url; + const char *url; char *url_key = xstrfmt("remote.%s.url", r->name); - strvec_push(names, r->name); - strvec_push(urls, git_config_get_string(url_key, &url) ? NULL : url); + /* Only add remotes with a non empty URL */ + if (!git_config_get_string_tmp(url_key, &url) && *url) { + strvec_push(names, r->name); + strvec_push(urls, url); + } - free(url); free(url_key); } } @@ -356,10 +358,8 @@ char *promisor_remote_info(struct repository *repo) strbuf_addch(&sb, ';'); strbuf_addstr(&sb, "name="); strbuf_addstr_urlencode(&sb, names.v[i], allow_unsanitized); - if (urls.v[i]) { - strbuf_addstr(&sb, ",url="); - strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized); - } + strbuf_addstr(&sb, ",url="); + strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized); } strvec_clear(&names); @@ -370,13 +370,13 @@ char *promisor_remote_info(struct repository *repo) /* * Find first index of 'nicks' where there is 'nick'. 'nick' is - * compared case insensitively to the strings in 'nicks'. If not found + * compared case sensitively to the strings in 'nicks'. If not found * 'nicks->nr' is returned. */ static size_t remote_nick_find(struct strvec *nicks, const char *nick) { for (size_t i = 0; i < nicks->nr; i++) - if (!strcasecmp(nicks->v[i], nick)) + if (!strcmp(nicks->v[i], nick)) return i; return nicks->nr; } @@ -409,10 +409,15 @@ static int should_accept_remote(enum accept_promisor accept, if (accept != ACCEPT_KNOWN_URL) BUG("Unhandled 'enum accept_promisor' value '%d'", accept); + if (!remote_url || !*remote_url) { + warning(_("no or empty URL advertised for remote '%s'"), remote_name); + return 0; + } + if (!strcmp(urls->v[i], remote_url)) return 1; - warning(_("known remote named '%s' but with url '%s' instead of '%s'"), + warning(_("known remote named '%s' but with URL '%s' instead of '%s'"), remote_name, urls->v[i], remote_url); return 0; diff --git a/protocol-caps.c b/protocol-caps.c index 855f279c2f..9b8db37a21 100644 --- a/protocol-caps.c +++ b/protocol-caps.c @@ -6,7 +6,7 @@ #include "hash.h" #include "hex.h" #include "object.h" -#include "object-store-ll.h" +#include "object-store.h" #include "repository.h" #include "string-list.h" #include "strbuf.h" diff --git a/prune-packed.c b/prune-packed.c index 7dad2fc0c1..92fb4fbb0e 100644 --- a/prune-packed.c +++ b/prune-packed.c @@ -2,7 +2,7 @@ #include "git-compat-util.h" #include "gettext.h" -#include "object-store-ll.h" +#include "object-file.h" #include "packfile.h" #include "progress.h" #include "prune-packed.h" diff --git a/pseudo-merge.h b/pseudo-merge.h index c9fbe9d312..cf0e62ecd1 100644 --- a/pseudo-merge.h +++ b/pseudo-merge.h @@ -210,7 +210,7 @@ int cascade_pseudo_merges(const struct pseudo_merge_map *pm, /* * Returns a pseudo-merge which contains the exact set of commits - * listed in the "parents" bitamp, or NULL if none could be found. + * listed in the "parents" bitmap, or NULL if none could be found. */ struct pseudo_merge *pseudo_merge_for_parents(const struct pseudo_merge_map *pm, struct bitmap *parents); diff --git a/range-diff.c b/range-diff.c index 9501c358a8..8a2dcbee32 100644 --- a/range-diff.c +++ b/range-diff.c @@ -467,7 +467,7 @@ static struct diff_filespec *get_filespec(const char *name, const char *p) { struct diff_filespec *spec = alloc_filespec(name); - fill_filespec(spec, null_oid(), 0, 0100644); + fill_filespec(spec, null_oid(the_hash_algo), 0, 0100644); spec->data = (char *)p; spec->size = strlen(p); spec->should_munmap = 0; diff --git a/reachable.c b/reachable.c index 9ee04c89ec..9dc748f0b9 100644 --- a/reachable.c +++ b/reachable.c @@ -14,7 +14,7 @@ #include "list-objects.h" #include "packfile.h" #include "worktree.h" -#include "object-store-ll.h" +#include "object-file.h" #include "pack-bitmap.h" #include "pack-mtimes.h" #include "config.h" @@ -45,7 +45,7 @@ static void add_one_file(const char *path, struct rev_info *revs) } strbuf_trim(&buf); if (!get_oid_hex(buf.buf, &oid)) { - object = parse_object_or_die(&oid, buf.buf); + object = parse_object_or_die(the_repository, &oid, buf.buf); add_pending_object(revs, object, ""); } strbuf_release(&buf); @@ -94,7 +94,7 @@ static int add_one_ref(const char *path, const char *referent UNUSED, const stru return 0; } - object = parse_object_or_die(oid, path); + object = parse_object_or_die(the_repository, oid, path); add_pending_object(revs, object, ""); return 0; @@ -218,7 +218,7 @@ static void add_recent_object(const struct object_id *oid, switch (type) { case OBJ_TAG: case OBJ_COMMIT: - obj = parse_object_or_die(oid, NULL); + obj = parse_object_or_die(the_repository, oid, NULL); break; case OBJ_TREE: obj = (struct object *)lookup_tree(the_repository, oid); @@ -341,7 +341,8 @@ static int mark_object_seen(const struct object_id *oid, int exclude UNUSED, uint32_t name_hash UNUSED, struct packed_git *found_pack UNUSED, - off_t found_offset UNUSED) + off_t found_offset UNUSED, + void *payload UNUSED) { struct object *obj = lookup_object_by_type(the_repository, oid, type); if (!obj) diff --git a/read-cache.c b/read-cache.c index e678c13e8f..c0bb760ad4 100644 --- a/read-cache.c +++ b/read-cache.c @@ -20,7 +20,7 @@ #include "refs.h" #include "dir.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oid-array.h" #include "tree.h" #include "commit.h" @@ -706,11 +706,11 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st, int intent_only = flags & ADD_CACHE_INTENT; int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE| (intent_only ? ADD_CACHE_NEW_ONLY : 0)); - unsigned hash_flags = pretend ? 0 : HASH_WRITE_OBJECT; + unsigned hash_flags = pretend ? 0 : INDEX_WRITE_OBJECT; struct object_id oid; if (flags & ADD_CACHE_RENORMALIZE) - hash_flags |= HASH_RENORMALIZE; + hash_flags |= INDEX_RENORMALIZE; if (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode)) return error(_("%s: can only add regular files, symbolic links or git-directories"), path); @@ -1117,48 +1117,19 @@ static int has_dir_name(struct index_state *istate, * * Compare the entry's full path with the last path in the index. */ - if (istate->cache_nr > 0) { - cmp_last = strcmp_offset(name, - istate->cache[istate->cache_nr - 1]->name, - &len_eq_last); - if (cmp_last > 0) { - if (name[len_eq_last] != '/') { - /* - * The entry sorts AFTER the last one in the - * index. - * - * If there were a conflict with "file", then our - * name would start with "file/" and the last index - * entry would start with "file" but not "file/". - * - * The next character after common prefix is - * not '/', so there can be no conflict. - */ - return retval; - } else { - /* - * The entry sorts AFTER the last one in the - * index, and the next character after common - * prefix is '/'. - * - * Either the last index entry is a file in - * conflict with this entry, or it has a name - * which sorts between this entry and the - * potential conflicting file. - * - * In both cases, we fall through to the loop - * below and let the regular search code handle it. - */ - } - } else if (cmp_last == 0) { - /* - * The entry exactly matches the last one in the - * index, but because of multiple stage and CE_REMOVE - * items, we fall through and let the regular search - * code handle it. - */ - } - } + if (!istate->cache_nr) + return 0; + + cmp_last = strcmp_offset(name, + istate->cache[istate->cache_nr - 1]->name, + &len_eq_last); + if (cmp_last > 0 && name[len_eq_last] != '/') + /* + * The entry sorts AFTER the last one in the + * index and their paths have no common prefix, + * so there cannot be a F/D conflict. + */ + return 0; for (;;) { size_t len; @@ -1735,7 +1706,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size) end = (unsigned char *)hdr + size; start = end - the_hash_algo->rawsz; oidread(&oid, start, the_repository->hash_algo); - if (oideq(&oid, null_oid())) + if (oideq(&oid, null_oid(the_hash_algo))) return 0; the_hash_algo->init_fn(&c); @@ -2686,8 +2657,8 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce, int common, to_remove, prefix_size; unsigned char to_remove_vi[16]; for (common = 0; - (ce->name[common] && - common < previous_name->len && + (common < previous_name->len && + ce->name[common] && ce->name[common] == previous_name->buf[common]); common++) ; /* still matching */ @@ -2848,7 +2819,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile, struct strbuf sb = STRBUF_INIT; int nr, nr_threads, ret; - f = hashfd(tempfile->fd, tempfile->filename.buf); + f = hashfd(the_repository->hash_algo, tempfile->fd, tempfile->filename.buf); prepare_repo_settings(r); f->skip_hash = r->settings.index_skip_hash; diff --git a/ref-filter.c b/ref-filter.c index 6da8d4c03b..7a274633cf 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -12,7 +12,7 @@ #include "refs.h" #include "wildmatch.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oid-array.h" #include "repo-settings.h" #include "repository.h" diff --git a/ref-filter.h b/ref-filter.h index 013d4cfa64..c98c4fbd4c 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -114,11 +114,16 @@ struct ref_format { } /* Macros for checking --merged and --no-merged options */ -#define _OPT_MERGED_NO_MERGED(option, filter, h) \ - { OPTION_CALLBACK, 0, option, (filter), N_("commit"), (h), \ - PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \ - parse_opt_merge_filter, (intptr_t) "HEAD" \ - } +#define _OPT_MERGED_NO_MERGED(option, filter, h) { \ + .type = OPTION_CALLBACK, \ + .long_name = option, \ + .value = (filter), \ + .argh = N_("commit"), \ + .help = (h), \ + .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \ + .callback = parse_opt_merge_filter, \ + .defval = (intptr_t) "HEAD", \ +} #define OPT_MERGED(f, h) _OPT_MERGED_NO_MERGED("merged", f, h) #define OPT_NO_MERGED(f, h) _OPT_MERGED_NO_MERGED("no-merged", f, h) @@ -2,13 +2,120 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" +#include "config.h" #include "gettext.h" -#include "object-store-ll.h" +#include "parse-options.h" +#include "object-store.h" #include "reflog.h" #include "refs.h" #include "revision.h" #include "tree.h" #include "tree-walk.h" +#include "wildmatch.h" + +static struct reflog_expire_entry_option *find_cfg_ent(struct reflog_expire_options *opts, + const char *pattern, size_t len) +{ + struct reflog_expire_entry_option *ent; + + if (!opts->entries_tail) + opts->entries_tail = &opts->entries; + + for (ent = opts->entries; ent; ent = ent->next) + if (!xstrncmpz(ent->pattern, pattern, len)) + return ent; + + FLEX_ALLOC_MEM(ent, pattern, pattern, len); + *opts->entries_tail = ent; + opts->entries_tail = &(ent->next); + return ent; +} + +int reflog_expire_config(const char *var, const char *value, + const struct config_context *ctx, void *cb) +{ + struct reflog_expire_options *opts = cb; + const char *pattern, *key; + size_t pattern_len; + timestamp_t expire; + int slot; + struct reflog_expire_entry_option *ent; + + if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0) + return git_default_config(var, value, ctx, cb); + + if (!strcmp(key, "reflogexpire")) { + slot = REFLOG_EXPIRE_TOTAL; + if (git_config_expiry_date(&expire, var, value)) + return -1; + } else if (!strcmp(key, "reflogexpireunreachable")) { + slot = REFLOG_EXPIRE_UNREACH; + if (git_config_expiry_date(&expire, var, value)) + return -1; + } else + return git_default_config(var, value, ctx, cb); + + if (!pattern) { + switch (slot) { + case REFLOG_EXPIRE_TOTAL: + opts->default_expire_total = expire; + break; + case REFLOG_EXPIRE_UNREACH: + opts->default_expire_unreachable = expire; + break; + } + return 0; + } + + ent = find_cfg_ent(opts, pattern, pattern_len); + if (!ent) + return -1; + switch (slot) { + case REFLOG_EXPIRE_TOTAL: + ent->expire_total = expire; + break; + case REFLOG_EXPIRE_UNREACH: + ent->expire_unreachable = expire; + break; + } + return 0; +} + +void reflog_expire_options_set_refname(struct reflog_expire_options *cb, + const char *ref) +{ + struct reflog_expire_entry_option *ent; + + if (cb->explicit_expiry == (REFLOG_EXPIRE_TOTAL|REFLOG_EXPIRE_UNREACH)) + return; /* both given explicitly -- nothing to tweak */ + + for (ent = cb->entries; ent; ent = ent->next) { + if (!wildmatch(ent->pattern, ref, 0)) { + if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL)) + cb->expire_total = ent->expire_total; + if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH)) + cb->expire_unreachable = ent->expire_unreachable; + return; + } + } + + /* + * If unconfigured, make stash never expire + */ + if (!strcmp(ref, "refs/stash")) { + if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL)) + cb->expire_total = 0; + if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH)) + cb->expire_unreachable = 0; + return; + } + + /* Nothing matched -- use the default value */ + if (!(cb->explicit_expiry & REFLOG_EXPIRE_TOTAL)) + cb->expire_total = cb->default_expire_total; + if (!(cb->explicit_expiry & REFLOG_EXPIRE_UNREACH)) + cb->expire_unreachable = cb->default_expire_unreachable; +} /* Remember to update object flag allocation in object.h */ #define INCOMPLETE (1u<<10) @@ -45,7 +152,8 @@ static int tree_is_complete(const struct object_id *oid) 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) || + if (!has_object(the_repository, &entry.oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR) || (S_ISDIR(entry.mode) && !tree_is_complete(&entry.oid))) { tree->object.flags |= INCOMPLETE; complete = 0; @@ -252,15 +360,15 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, struct expire_reflog_policy_cb *cb = cb_data; struct commit *old_commit, *new_commit; - if (timestamp < cb->cmd.expire_total) + if (timestamp < cb->opts.expire_total) return 1; old_commit = new_commit = NULL; - if (cb->cmd.stalefix && + if (cb->opts.stalefix && (!keep_entry(&old_commit, ooid) || !keep_entry(&new_commit, noid))) return 1; - if (timestamp < cb->cmd.expire_unreachable) { + if (timestamp < cb->opts.expire_unreachable) { switch (cb->unreachable_expire_kind) { case UE_ALWAYS: return 1; @@ -272,7 +380,7 @@ int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, } } - if (cb->cmd.recno && --(cb->cmd.recno) == 0) + if (cb->opts.recno && --(cb->opts.recno) == 0) return 1; return 0; @@ -331,7 +439,7 @@ void reflog_expiry_prepare(const char *refname, struct commit_list *elem; struct commit *commit = NULL; - if (!cb->cmd.expire_unreachable || is_head(refname)) { + if (!cb->opts.expire_unreachable || is_head(refname)) { cb->unreachable_expire_kind = UE_HEAD; } else { commit = lookup_commit_reference_gently(the_repository, @@ -341,7 +449,7 @@ void reflog_expiry_prepare(const char *refname, cb->unreachable_expire_kind = commit ? UE_NORMAL : UE_ALWAYS; } - if (cb->cmd.expire_unreachable <= cb->cmd.expire_total) + if (cb->opts.expire_unreachable <= cb->opts.expire_total) cb->unreachable_expire_kind = UE_ALWAYS; switch (cb->unreachable_expire_kind) { @@ -358,7 +466,7 @@ void reflog_expiry_prepare(const char *refname, /* For reflog_expiry_cleanup() below */ cb->tip_commit = commit; } - cb->mark_limit = cb->cmd.expire_total; + cb->mark_limit = cb->opts.expire_total; mark_reachable(cb); } @@ -390,7 +498,7 @@ int count_reflog_ent(struct object_id *ooid UNUSED, timestamp_t timestamp, int tz UNUSED, const char *message UNUSED, void *cb_data) { - struct cmd_reflog_expire_cb *cb = cb_data; + struct reflog_expire_options *cb = cb_data; if (!cb->expire_total || timestamp < cb->expire_total) cb->recno++; return 0; @@ -398,7 +506,7 @@ int count_reflog_ent(struct object_id *ooid UNUSED, int reflog_delete(const char *rev, enum expire_reflog_flags flags, int verbose) { - struct cmd_reflog_expire_cb cmd = { 0 }; + struct reflog_expire_options opts = { 0 }; int status = 0; reflog_expiry_should_prune_fn *should_prune_fn = should_expire_reflog_ent; const char *spec = strstr(rev, "@{"); @@ -421,17 +529,17 @@ int reflog_delete(const char *rev, enum expire_reflog_flags flags, int verbose) recno = strtoul(spec + 2, &ep, 10); if (*ep == '}') { - cmd.recno = -recno; + opts.recno = -recno; refs_for_each_reflog_ent(get_main_ref_store(the_repository), - ref, count_reflog_ent, &cmd); + ref, count_reflog_ent, &opts); } else { - cmd.expire_total = approxidate(spec + 2); + opts.expire_total = approxidate(spec + 2); refs_for_each_reflog_ent(get_main_ref_store(the_repository), - ref, count_reflog_ent, &cmd); - cmd.expire_total = 0; + ref, count_reflog_ent, &opts); + opts.expire_total = 0; } - cb.cmd = cmd; + cb.opts = opts; status |= refs_reflog_expire(get_main_ref_store(the_repository), ref, flags, reflog_expiry_prepare, @@ -2,13 +2,44 @@ #define REFLOG_H #include "refs.h" -struct cmd_reflog_expire_cb { +#define REFLOG_EXPIRE_TOTAL (1 << 0) +#define REFLOG_EXPIRE_UNREACH (1 << 1) + +struct reflog_expire_entry_option { + struct reflog_expire_entry_option *next; + timestamp_t expire_total; + timestamp_t expire_unreachable; + char pattern[FLEX_ARRAY]; +}; + +struct reflog_expire_options { + struct reflog_expire_entry_option *entries, **entries_tail; int stalefix; int explicit_expiry; + timestamp_t default_expire_total; timestamp_t expire_total; + timestamp_t default_expire_unreachable; timestamp_t expire_unreachable; int recno; }; +#define REFLOG_EXPIRE_OPTIONS_INIT(now) { \ + .default_expire_total = now - 30 * 24 * 3600, \ + .default_expire_unreachable = now - 90 * 24 * 3600, \ +} + +/* + * Parse the reflog expire configuration. This should be used with + * `repo_config()`. + */ +int reflog_expire_config(const char *var, const char *value, + const struct config_context *ctx, void *cb); + +/* + * Adapt the options so that they apply to the given refname. This applies any + * per-reference reflog expiry configuration that may exist to the options. + */ +void reflog_expire_options_set_refname(struct reflog_expire_options *cb, + const char *refname); struct expire_reflog_policy_cb { enum { @@ -18,7 +49,7 @@ struct expire_reflog_policy_cb { } unreachable_expire_kind; struct commit_list *mark_list; unsigned long mark_limit; - struct cmd_reflog_expire_cb cmd; + struct reflog_expire_options opts; struct commit *tip_commit; struct commit_list *tips; unsigned int dry_run:1; @@ -19,7 +19,7 @@ #include "run-command.h" #include "hook.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "object.h" #include "path.h" #include "submodule.h" @@ -376,7 +376,7 @@ int ref_resolves_to_object(const char *refname, { if (flags & REF_ISBROKEN) return 0; - if (!repo_has_object_file(repo, oid)) { + if (!has_object(repo, oid, HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { error(_("%s does not point to a valid object!"), refname); return 0; } @@ -664,7 +664,8 @@ char *repo_default_branch_name(struct repository *r, int quiet) if (!ret) { ret = xstrdup("master"); if (!quiet) - advise(_(default_branch_name_advice), ret); + advise_if_enabled(ADVICE_DEFAULT_BRANCH_NAME, + _(default_branch_name_advice), ret); } full_ref = xstrfmt("refs/heads/%s", ret); @@ -1175,6 +1176,11 @@ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, CALLOC_ARRAY(tr, 1); tr->ref_store = refs; tr->flags = flags; + string_list_init_dup(&tr->refnames); + + if (flags & REF_TRANSACTION_ALLOW_FAILURE) + CALLOC_ARRAY(tr->rejections, 1); + return tr; } @@ -1205,10 +1211,45 @@ void ref_transaction_free(struct ref_transaction *transaction) free((char *)transaction->updates[i]->old_target); free(transaction->updates[i]); } + + if (transaction->rejections) + free(transaction->rejections->update_indices); + free(transaction->rejections); + + string_list_clear(&transaction->refnames, 0); free(transaction->updates); free(transaction); } +int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction, + size_t update_idx, + enum ref_transaction_error err) +{ + if (update_idx >= transaction->nr) + BUG("trying to set rejection on invalid update index"); + + if (!(transaction->flags & REF_TRANSACTION_ALLOW_FAILURE)) + return 0; + + if (!transaction->rejections) + BUG("transaction not inititalized with failure support"); + + /* + * Don't accept generic errors, since these errors are not user + * input related. + */ + if (err == REF_TRANSACTION_ERROR_GENERIC) + return 0; + + transaction->updates[update_idx]->rejection_err = err; + ALLOC_GROW(transaction->rejections->update_indices, + transaction->rejections->nr + 1, + transaction->rejections->alloc); + transaction->rejections->update_indices[transaction->rejections->nr++] = update_idx; + + return 1; +} + struct ref_update *ref_transaction_add_update( struct ref_transaction *transaction, const char *refname, unsigned int flags, @@ -1218,6 +1259,7 @@ struct ref_update *ref_transaction_add_update( const char *committer_info, const char *msg) { + struct string_list_item *item; struct ref_update *update; if (transaction->state != REF_TRANSACTION_OPEN) @@ -1233,6 +1275,7 @@ struct ref_update *ref_transaction_add_update( transaction->updates[transaction->nr++] = update; update->flags = flags; + update->rejection_err = 0; update->new_target = xstrdup_or_null(new_target); update->old_target = xstrdup_or_null(old_target); @@ -1245,6 +1288,16 @@ struct ref_update *ref_transaction_add_update( update->msg = normalize_reflog_message(msg); } + /* + * This list is generally used by the backends to avoid duplicates. + * But we do support multiple log updates for a given refname within + * a single transaction. + */ + if (!(update->flags & REF_LOG_ONLY)) { + item = string_list_append(&transaction->refnames, refname); + item->util = update; + } + return update; } @@ -1377,7 +1430,7 @@ int ref_transaction_create(struct ref_transaction *transaction, return 1; } return ref_transaction_update(transaction, refname, new_oid, - null_oid(), new_target, NULL, flags, + null_oid(the_hash_algo), new_target, NULL, flags, msg, err); } @@ -1396,7 +1449,7 @@ int ref_transaction_delete(struct ref_transaction *transaction, if (old_target && !(flags & REF_NO_DEREF)) BUG("delete cannot operate on symrefs with deref mode"); return ref_transaction_update(transaction, refname, - null_oid(), old_oid, + null_oid(the_hash_algo), old_oid, NULL, old_target, flags, msg, err); } @@ -1699,6 +1752,24 @@ struct ref_iterator *refs_ref_iterator_begin( enum do_for_each_ref_flags flags) { struct ref_iterator *iter; + struct strvec normalized_exclude_patterns = STRVEC_INIT; + + if (exclude_patterns) { + for (size_t i = 0; exclude_patterns[i]; i++) { + const char *pattern = exclude_patterns[i]; + size_t len = strlen(pattern); + if (!len) + continue; + + if (pattern[len - 1] == '/') + strvec_push(&normalized_exclude_patterns, pattern); + else + strvec_pushf(&normalized_exclude_patterns, "%s/", + pattern); + } + + exclude_patterns = normalized_exclude_patterns.v; + } if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) { static int ref_paranoia = -1; @@ -1719,6 +1790,8 @@ struct ref_iterator *refs_ref_iterator_begin( if (trim) iter = prefix_ref_iterator_begin(iter, "", trim); + strvec_clear(&normalized_exclude_patterns); + return iter; } @@ -2160,7 +2233,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo, subrepo = xmalloc(sizeof(*subrepo)); if (repo_submodule_init(subrepo, repo, submodule, - null_oid())) { + null_oid(the_hash_algo))) { free(subrepo); goto done; } @@ -2258,7 +2331,7 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref, REF_NO_DEREF, logmsg, &err)) goto error_return; prepret = ref_transaction_prepare(transaction, &err); - if (prepret && prepret != TRANSACTION_CREATE_EXISTS) + if (prepret && prepret != REF_TRANSACTION_ERROR_CREATE_EXISTS) goto error_return; } else { if (ref_transaction_update(transaction, ref, NULL, NULL, @@ -2276,7 +2349,7 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref, } } - if (prepret == TRANSACTION_CREATE_EXISTS) + if (prepret == REF_TRANSACTION_ERROR_CREATE_EXISTS) goto cleanup; if (ref_transaction_commit(transaction, &err)) @@ -2290,8 +2363,13 @@ cleanup: return ret; } -int ref_update_reject_duplicates(struct string_list *refnames, - struct strbuf *err) +/* + * Write an error to `err` and return a nonzero value iff the same + * refname appears multiple times in `refnames`. `refnames` must be + * sorted on entry to this function. + */ +static int ref_update_reject_duplicates(struct string_list *refnames, + struct strbuf *err) { size_t i, n = refnames->nr; @@ -2345,14 +2423,14 @@ static int run_transaction_hook(struct ref_transaction *transaction, strbuf_reset(&buf); if (!(update->flags & REF_HAVE_OLD)) - strbuf_addf(&buf, "%s ", oid_to_hex(null_oid())); + strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo))); else if (update->old_target) strbuf_addf(&buf, "ref:%s ", update->old_target); else strbuf_addf(&buf, "%s ", oid_to_hex(&update->old_oid)); if (!(update->flags & REF_HAVE_NEW)) - strbuf_addf(&buf, "%s ", oid_to_hex(null_oid())); + strbuf_addf(&buf, "%s ", oid_to_hex(null_oid(the_hash_algo))); else if (update->new_target) strbuf_addf(&buf, "ref:%s ", update->new_target); else @@ -2405,6 +2483,10 @@ int ref_transaction_prepare(struct ref_transaction *transaction, return -1; } + string_list_sort(&transaction->refnames); + if (ref_update_reject_duplicates(&transaction->refnames, err)) + return REF_TRANSACTION_ERROR_GENERIC; + ret = refs->be->transaction_prepare(refs, transaction, err); if (ret) return ret; @@ -2475,20 +2557,21 @@ int ref_transaction_commit(struct ref_transaction *transaction, return ret; } -int refs_verify_refname_available(struct ref_store *refs, - const char *refname, - const struct string_list *extras, - const struct string_list *skip, - unsigned int initial_transaction, - struct strbuf *err) +enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs, + const struct string_list *refnames, + const struct string_list *extras, + const struct string_list *skip, + struct ref_transaction *transaction, + unsigned int initial_transaction, + struct strbuf *err) { - const char *slash; - const char *extra_refname; struct strbuf dirname = STRBUF_INIT; struct strbuf referent = STRBUF_INIT; - struct object_id oid; - unsigned int type; - int ret = -1; + struct string_list_item *item; + struct ref_iterator *iter = NULL; + struct strset conflicting_dirnames; + struct strset dirnames; + int ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; /* * For the sake of comments in this function, suppose that @@ -2497,86 +2580,160 @@ int refs_verify_refname_available(struct ref_store *refs, assert(err); - strbuf_grow(&dirname, strlen(refname) + 1); - for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) { - /* - * Just saying "Is a directory" when we e.g. can't - * lock some multi-level ref isn't very informative, - * the user won't be told *what* is a directory, so - * let's not use strerror() below. - */ - int ignore_errno; - /* Expand dirname to the new prefix, not including the trailing slash: */ - strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len); + strset_init(&conflicting_dirnames); + strset_init(&dirnames); + + for_each_string_list_item(item, refnames) { + const size_t *update_idx = (size_t *)item->util; + const char *refname = item->string; + const char *extra_refname; + struct object_id oid; + unsigned int type; + const char *slash; + + strbuf_reset(&dirname); + + for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) { + /* + * Just saying "Is a directory" when we e.g. can't + * lock some multi-level ref isn't very informative, + * the user won't be told *what* is a directory, so + * let's not use strerror() below. + */ + int ignore_errno; + + /* Expand dirname to the new prefix, not including the trailing slash: */ + strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len); + + /* + * We are still at a leading dir of the refname (e.g., + * "refs/foo"; if there is a reference with that name, + * it is a conflict, *unless* it is in skip. + */ + if (skip && string_list_has_string(skip, dirname.buf)) + continue; + + /* + * If we've already seen the directory we don't need to + * process it again. Skip it to avoid checking common + * prefixes like "refs/heads/" repeatedly. + */ + if (!strset_add(&dirnames, dirname.buf)) + continue; + + if (!initial_transaction && + (strset_contains(&conflicting_dirnames, dirname.buf) || + !refs_read_raw_ref(refs, dirname.buf, &oid, &referent, + &type, &ignore_errno))) { + if (transaction && ref_transaction_maybe_set_rejected( + transaction, *update_idx, + REF_TRANSACTION_ERROR_NAME_CONFLICT)) { + strset_remove(&dirnames, dirname.buf); + strset_add(&conflicting_dirnames, dirname.buf); + continue; + } + + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), + dirname.buf, refname); + goto cleanup; + } + + if (extras && string_list_has_string(extras, dirname.buf)) { + if (transaction && ref_transaction_maybe_set_rejected( + transaction, *update_idx, + REF_TRANSACTION_ERROR_NAME_CONFLICT)) { + strset_remove(&dirnames, dirname.buf); + continue; + } + + strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), + refname, dirname.buf); + goto cleanup; + } + } /* - * We are still at a leading dir of the refname (e.g., - * "refs/foo"; if there is a reference with that name, - * it is a conflict, *unless* it is in skip. + * We are at the leaf of our refname (e.g., "refs/foo/bar"). + * There is no point in searching for a reference with that + * name, because a refname isn't considered to conflict with + * itself. But we still need to check for references whose + * names are in the "refs/foo/bar/" namespace, because they + * *do* conflict. */ - if (skip && string_list_has_string(skip, dirname.buf)) - continue; + strbuf_addstr(&dirname, refname + dirname.len); + strbuf_addch(&dirname, '/'); - if (!initial_transaction && - !refs_read_raw_ref(refs, dirname.buf, &oid, &referent, - &type, &ignore_errno)) { - strbuf_addf(err, _("'%s' exists; cannot create '%s'"), - dirname.buf, refname); - goto cleanup; - } + if (!initial_transaction) { + int ok; - if (extras && string_list_has_string(extras, dirname.buf)) { - strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), - refname, dirname.buf); - goto cleanup; + if (!iter) { + iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, + DO_FOR_EACH_INCLUDE_BROKEN); + } else if (ref_iterator_seek(iter, dirname.buf) < 0) { + goto cleanup; + } + + while ((ok = ref_iterator_advance(iter)) == ITER_OK) { + if (skip && + string_list_has_string(skip, iter->refname)) + continue; + + if (transaction && ref_transaction_maybe_set_rejected( + transaction, *update_idx, + REF_TRANSACTION_ERROR_NAME_CONFLICT)) + continue; + + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), + iter->refname, refname); + goto cleanup; + } + + if (ok != ITER_DONE) + BUG("error while iterating over references"); } - } - /* - * We are at the leaf of our refname (e.g., "refs/foo/bar"). - * There is no point in searching for a reference with that - * name, because a refname isn't considered to conflict with - * itself. But we still need to check for references whose - * names are in the "refs/foo/bar/" namespace, because they - * *do* conflict. - */ - strbuf_addstr(&dirname, refname + dirname.len); - strbuf_addch(&dirname, '/'); - - if (!initial_transaction) { - struct ref_iterator *iter; - int ok; - - iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, - DO_FOR_EACH_INCLUDE_BROKEN); - while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - if (skip && - string_list_has_string(skip, iter->refname)) + extra_refname = find_descendant_ref(dirname.buf, extras, skip); + if (extra_refname) { + if (transaction && ref_transaction_maybe_set_rejected( + transaction, *update_idx, + REF_TRANSACTION_ERROR_NAME_CONFLICT)) continue; - strbuf_addf(err, _("'%s' exists; cannot create '%s'"), - iter->refname, refname); - ref_iterator_abort(iter); + strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), + refname, extra_refname); goto cleanup; } - - if (ok != ITER_DONE) - BUG("error while iterating over references"); } - extra_refname = find_descendant_ref(dirname.buf, extras, skip); - if (extra_refname) - strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"), - refname, extra_refname); - else - ret = 0; + ret = 0; cleanup: strbuf_release(&referent); strbuf_release(&dirname); + strset_clear(&conflicting_dirnames); + strset_clear(&dirnames); + ref_iterator_free(iter); return ret; } +enum ref_transaction_error refs_verify_refname_available( + struct ref_store *refs, + const char *refname, + const struct string_list *extras, + const struct string_list *skip, + unsigned int initial_transaction, + struct strbuf *err) +{ + struct string_list_item item = { .string = (char *) refname }; + struct string_list refnames = { + .items = &item, + .nr = 1, + }; + + return refs_verify_refnames_available(refs, &refnames, extras, skip, + NULL, initial_transaction, err); +} + struct do_for_each_reflog_help { each_reflog_fn *fn; void *cb_data; @@ -2662,6 +2819,28 @@ void ref_transaction_for_each_queued_update(struct ref_transaction *transaction, } } +void ref_transaction_for_each_rejected_update(struct ref_transaction *transaction, + ref_transaction_for_each_rejected_update_fn cb, + void *cb_data) +{ + if (!transaction->rejections) + return; + + for (size_t i = 0; i < transaction->rejections->nr; i++) { + size_t update_index = transaction->rejections->update_indices[i]; + struct ref_update *update = transaction->updates[update_index]; + + if (!update->rejection_err) + continue; + + cb(update->refname, + (update->flags & REF_HAVE_OLD) ? &update->old_oid : NULL, + (update->flags & REF_HAVE_NEW) ? &update->new_oid : NULL, + update->old_target, update->new_target, + update->rejection_err, cb_data); + } +} + int refs_delete_refs(struct ref_store *refs, const char *logmsg, struct string_list *refnames, unsigned int flags) { @@ -2753,8 +2932,9 @@ int ref_update_has_null_new_value(struct ref_update *update) return !update->new_target && is_null_oid(&update->new_oid); } -int ref_update_check_old_target(const char *referent, struct ref_update *update, - struct strbuf *err) +enum ref_transaction_error ref_update_check_old_target(const char *referent, + struct ref_update *update, + struct strbuf *err) { if (!update->old_target) BUG("called without old_target set"); @@ -2762,17 +2942,18 @@ int ref_update_check_old_target(const char *referent, struct ref_update *update, if (!strcmp(referent, update->old_target)) return 0; - if (!strcmp(referent, "")) + if (!strcmp(referent, "")) { strbuf_addf(err, "verifying symref target: '%s': " "reference is missing but expected %s", ref_update_original_update_refname(update), update->old_target); - else - strbuf_addf(err, "verifying symref target: '%s': " - "is at %s but expected %s", + return REF_TRANSACTION_ERROR_NONEXISTENT_REF; + } + + strbuf_addf(err, "verifying symref target: '%s': is at %s but expected %s", ref_update_original_update_refname(update), referent, update->old_target); - return -1; + return REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE; } struct migration_data { @@ -2794,7 +2975,7 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con if (ret < 0) goto done; - ret = ref_transaction_update(data->transaction, refname, NULL, null_oid(), + ret = ref_transaction_update(data->transaction, refname, NULL, null_oid(the_hash_algo), symref_target.buf, NULL, REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf); if (ret < 0) @@ -16,6 +16,23 @@ struct worktree; enum ref_storage_format ref_storage_format_by_name(const char *name); const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format); +enum ref_transaction_error { + /* Default error code */ + REF_TRANSACTION_ERROR_GENERIC = -1, + /* Ref name conflict like A vs A/B */ + REF_TRANSACTION_ERROR_NAME_CONFLICT = -2, + /* Ref to be created already exists */ + REF_TRANSACTION_ERROR_CREATE_EXISTS = -3, + /* ref expected but doesn't exist */ + REF_TRANSACTION_ERROR_NONEXISTENT_REF = -4, + /* Provided old_oid or old_target of reference doesn't match actual */ + REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE = -5, + /* Provided new_oid or new_target is invalid */ + REF_TRANSACTION_ERROR_INVALID_NEW_VALUE = -6, + /* Expected ref to be symref, but is a regular ref */ + REF_TRANSACTION_ERROR_EXPECTED_SYMREF = -7, +}; + /* * Resolve a reference, recursively following symbolic references. * @@ -117,12 +134,12 @@ int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname, * * extras and skip must be sorted. */ -int refs_verify_refname_available(struct ref_store *refs, - const char *refname, - const struct string_list *extras, - const struct string_list *skip, - unsigned int initial_transaction, - struct strbuf *err); +enum ref_transaction_error refs_verify_refname_available(struct ref_store *refs, + const char *refname, + const struct string_list *extras, + const struct string_list *skip, + unsigned int initial_transaction, + struct strbuf *err); int refs_ref_exists(struct ref_store *refs, const char *refname); @@ -638,6 +655,13 @@ enum ref_transaction_flag { * either be absent or null_oid. */ REF_TRANSACTION_FLAG_INITIAL = (1 << 0), + + /* + * The transaction mechanism by default fails all updates if any conflict + * is detected. This flag allows transactions to partially apply updates + * while rejecting updates which do not match the expected state. + */ + REF_TRANSACTION_ALLOW_FAILURE = (1 << 1), }; /* @@ -818,13 +842,6 @@ int ref_transaction_verify(struct ref_transaction *transaction, unsigned int flags, struct strbuf *err); -/* Naming conflict (for example, the ref names A and A/B conflict). */ -#define TRANSACTION_NAME_CONFLICT -1 -/* When only creation was requested, but the ref already exists. */ -#define TRANSACTION_CREATE_EXISTS -2 -/* All other errors. */ -#define TRANSACTION_GENERIC_ERROR -3 - /* * Perform the preparatory stages of committing `transaction`. Acquire * any needed locks, check preconditions, etc.; basically, do as much @@ -876,6 +893,21 @@ void ref_transaction_for_each_queued_update(struct ref_transaction *transaction, void *cb_data); /* + * Execute the given callback function for each of the reference updates which + * have been rejected in the given transaction. + */ +typedef void ref_transaction_for_each_rejected_update_fn(const char *refname, + const struct object_id *old_oid, + const struct object_id *new_oid, + const char *old_target, + const char *new_target, + enum ref_transaction_error err, + void *cb_data); +void ref_transaction_for_each_rejected_update(struct ref_transaction *transaction, + ref_transaction_for_each_rejected_update_fn cb, + void *cb_data); + +/* * Free `*transaction` and all associated data. */ void ref_transaction_free(struct ref_transaction *transaction); diff --git a/refs/debug.c b/refs/debug.c index fbc4df08b4..485e3079d7 100644 --- a/refs/debug.c +++ b/refs/debug.c @@ -169,6 +169,16 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator) return res; } +static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct debug_ref_iterator *diter = + (struct debug_ref_iterator *)ref_iterator; + int res = diter->iter->vtable->seek(diter->iter, prefix); + trace_printf_key(&trace_refs, "iterator_seek: %s: %d\n", prefix ? prefix : "", res); + return res; +} + static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -179,19 +189,19 @@ static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator, return res; } -static int debug_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void debug_ref_iterator_release(struct ref_iterator *ref_iterator) { struct debug_ref_iterator *diter = (struct debug_ref_iterator *)ref_iterator; - int res = diter->iter->vtable->abort(diter->iter); - trace_printf_key(&trace_refs, "iterator_abort: %d\n", res); - return res; + diter->iter->vtable->release(diter->iter); + trace_printf_key(&trace_refs, "iterator_abort\n"); } static struct ref_iterator_vtable debug_ref_iterator_vtable = { .advance = debug_ref_iterator_advance, + .seek = debug_ref_iterator_seek, .peel = debug_ref_iterator_peel, - .abort = debug_ref_iterator_abort, + .release = debug_ref_iterator_release, }; static struct ref_iterator * @@ -217,7 +227,7 @@ static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname, struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store; int res = 0; - oidcpy(oid, null_oid()); + oidcpy(oid, null_oid(ref_store->repo->hash_algo)); res = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent, type, failure_errno); diff --git a/refs/files-backend.c b/refs/files-backend.c index 6c6e67dc1c..bf6f89b1d1 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -663,7 +663,7 @@ static void unlock_ref(struct ref_lock *lock) * broken, lock the reference anyway but clear old_oid. * * Return 0 on success. On failure, write an error message to err and - * return TRANSACTION_NAME_CONFLICT or TRANSACTION_GENERIC_ERROR. + * return REF_TRANSACTION_ERROR_NAME_CONFLICT or REF_TRANSACTION_ERROR_GENERIC. * * Implementation note: This function is basically * @@ -676,18 +676,22 @@ static void unlock_ref(struct ref_lock *lock) * avoided, namely if we were successfully able to read the ref * - Generate informative error messages in the case of failure */ -static int lock_raw_ref(struct files_ref_store *refs, - const char *refname, int mustexist, - const struct string_list *extras, - struct ref_lock **lock_p, - struct strbuf *referent, - unsigned int *type, - struct strbuf *err) -{ +static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs, + struct ref_update *update, + size_t update_idx, + int mustexist, + struct string_list *refnames_to_check, + const struct string_list *extras, + struct ref_lock **lock_p, + struct strbuf *referent, + struct strbuf *err) +{ + enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC; + const char *refname = update->refname; + unsigned int *type = &update->type; struct ref_lock *lock; struct strbuf ref_file = STRBUF_INIT; int attempts_remaining = 3; - int ret = TRANSACTION_GENERIC_ERROR; int failure_errno; assert(err); @@ -704,7 +708,7 @@ static int lock_raw_ref(struct files_ref_store *refs, files_ref_path(refs, &ref_file, refname); retry: - switch (safe_create_leading_directories(ref_file.buf)) { + switch (safe_create_leading_directories(the_repository, ref_file.buf)) { case SCLD_OK: break; /* success */ case SCLD_EXISTS: @@ -727,13 +731,14 @@ retry: strbuf_reset(err); strbuf_addf(err, "unable to resolve reference '%s'", refname); + ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF; } else { /* * The error message set by * refs_verify_refname_available() is * OK. */ - ret = TRANSACTION_NAME_CONFLICT; + ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; } } else { /* @@ -782,11 +787,14 @@ retry: if (files_read_raw_ref(&refs->base, refname, &lock->old_oid, referent, type, &failure_errno)) { + struct string_list_item *item; + if (failure_errno == ENOENT) { if (mustexist) { /* Garden variety missing reference. */ strbuf_addf(err, "unable to resolve reference '%s'", refname); + ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF; goto error_return; } else { /* @@ -819,6 +827,7 @@ retry: /* Garden variety missing reference. */ strbuf_addf(err, "unable to resolve reference '%s'", refname); + ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF; goto error_return; } else if (remove_dir_recursively(&ref_file, REMOVE_DIR_EMPTY_ONLY)) { @@ -829,7 +838,7 @@ retry: * The error message set by * verify_refname_available() is OK. */ - ret = TRANSACTION_NAME_CONFLICT; + ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; goto error_return; } else { /* @@ -855,16 +864,13 @@ retry: } /* - * If the ref did not exist and we are creating it, - * make sure there is no existing packed ref that - * conflicts with refname: + * If the ref did not exist and we are creating it, we have to + * make sure there is no existing packed ref that conflicts + * with refname. This check is deferred so that we can batch it. */ - if (refs_verify_refname_available( - refs->packed_ref_store, refname, - extras, NULL, 0, err)) { - ret = TRANSACTION_NAME_CONFLICT; - goto error_return; - } + item = string_list_append(refnames_to_check, refname); + item->util = xmalloc(sizeof(update_idx)); + memcpy(item->util, &update_idx, sizeof(update_idx)); } ret = 0; @@ -919,13 +925,17 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator) return ITER_OK; } - iter->iter0 = NULL; - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - ok = ITER_ERROR; - return ok; } +static int files_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct files_ref_iterator *iter = + (struct files_ref_iterator *)ref_iterator; + return ref_iterator_seek(iter->iter0, prefix); +} + static int files_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -935,23 +945,18 @@ static int files_ref_iterator_peel(struct ref_iterator *ref_iterator, return ref_iterator_peel(iter->iter0, peeled); } -static int files_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void files_ref_iterator_release(struct ref_iterator *ref_iterator) { struct files_ref_iterator *iter = (struct files_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) - ok = ref_iterator_abort(iter->iter0); - - base_ref_iterator_free(ref_iterator); - return ok; + ref_iterator_free(iter->iter0); } static struct ref_iterator_vtable files_ref_iterator_vtable = { .advance = files_ref_iterator_advance, + .seek = files_ref_iterator_seek, .peel = files_ref_iterator_peel, - .abort = files_ref_iterator_abort, + .release = files_ref_iterator_release, }; static struct ref_iterator *files_ref_iterator_begin( @@ -1114,7 +1119,7 @@ retry_fn: strbuf_addstr(&path_copy, path); do { - scld_result = safe_create_leading_directories(path_copy.buf); + scld_result = safe_create_leading_directories(the_repository, path_copy.buf); if (scld_result == SCLD_OK) goto retry_fn; } while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0); @@ -1270,7 +1275,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r) ref_transaction_add_update( transaction, r->name, REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING, - null_oid(), &r->oid, NULL, NULL, NULL, NULL); + null_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, NULL); if (ref_transaction_commit(transaction, &err)) goto cleanup; @@ -1382,7 +1387,7 @@ static int should_pack_refs(struct files_ref_store *refs, iter->flags, opts)) refcount++; if (refcount >= limit) { - ref_iterator_abort(iter); + ref_iterator_free(iter); return 1; } } @@ -1390,6 +1395,7 @@ static int should_pack_refs(struct files_ref_store *refs, if (ret != ITER_DONE) die("error while iterating over references"); + ref_iterator_free(iter); return 0; } @@ -1456,6 +1462,7 @@ static int files_pack_refs(struct ref_store *ref_store, packed_refs_unlock(refs->packed_ref_store); prune_refs(refs, &refs_to_prune); + ref_iterator_free(iter); strbuf_release(&err); return 0; } @@ -1520,10 +1527,11 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname) return ret; } -static int write_ref_to_lockfile(struct files_ref_store *refs, - struct ref_lock *lock, - const struct object_id *oid, - int skip_oid_verification, struct strbuf *err); +static enum ref_transaction_error write_ref_to_lockfile(struct files_ref_store *refs, + struct ref_lock *lock, + const struct object_id *oid, + int skip_oid_verification, + struct strbuf *err); static int commit_ref_update(struct files_ref_store *refs, struct ref_lock *lock, const struct object_id *oid, const char *logmsg, @@ -1929,10 +1937,11 @@ static int files_log_ref_write(struct files_ref_store *refs, * Write oid into the open lockfile, then close the lockfile. On * errors, rollback the lockfile, fill in *err and return -1. */ -static int write_ref_to_lockfile(struct files_ref_store *refs, - struct ref_lock *lock, - const struct object_id *oid, - int skip_oid_verification, struct strbuf *err) +static enum ref_transaction_error write_ref_to_lockfile(struct files_ref_store *refs, + struct ref_lock *lock, + const struct object_id *oid, + int skip_oid_verification, + struct strbuf *err) { static char term = '\n'; struct object *o; @@ -1946,7 +1955,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs, "trying to write ref '%s' with nonexistent object %s", lock->ref_name, oid_to_hex(oid)); unlock_ref(lock); - return -1; + return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE; } if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) { strbuf_addf( @@ -1954,7 +1963,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs, "trying to write non-commit object %s to branch '%s'", oid_to_hex(oid), lock->ref_name); unlock_ref(lock); - return -1; + return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE; } } fd = get_lock_file_fd(&lock->lk); @@ -1965,7 +1974,7 @@ static int write_ref_to_lockfile(struct files_ref_store *refs, strbuf_addf(err, "couldn't write '%s'", get_lock_file_path(&lock->lk)); unlock_ref(lock); - return -1; + return REF_TRANSACTION_ERROR_GENERIC; } return 0; } @@ -2303,35 +2312,33 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) return ITER_OK; } - iter->dir_iterator = NULL; - if (ref_iterator_abort(ref_iterator) == ITER_ERROR) - ok = ITER_ERROR; return ok; } +static int files_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED, + const char *prefix UNUSED) +{ + BUG("ref_iterator_seek() called for reflog_iterator"); +} + static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED, struct object_id *peeled UNUSED) { BUG("ref_iterator_peel() called for reflog_iterator"); } -static int files_reflog_iterator_abort(struct ref_iterator *ref_iterator) +static void files_reflog_iterator_release(struct ref_iterator *ref_iterator) { struct files_reflog_iterator *iter = (struct files_reflog_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->dir_iterator) - ok = dir_iterator_abort(iter->dir_iterator); - - base_ref_iterator_free(ref_iterator); - return ok; + dir_iterator_free(iter->dir_iterator); } static struct ref_iterator_vtable files_reflog_iterator_vtable = { .advance = files_reflog_iterator_advance, + .seek = files_reflog_iterator_seek, .peel = files_reflog_iterator_peel, - .abort = files_reflog_iterator_abort, + .release = files_reflog_iterator_release, }; static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store, @@ -2381,13 +2388,11 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st * If update is a direct update of head_ref (the reference pointed to * by HEAD), then add an extra REF_LOG_ONLY update for HEAD. */ -static int split_head_update(struct ref_update *update, - struct ref_transaction *transaction, - const char *head_ref, - struct string_list *affected_refnames, - struct strbuf *err) +static enum ref_transaction_error split_head_update(struct ref_update *update, + struct ref_transaction *transaction, + const char *head_ref, + struct strbuf *err) { - struct string_list_item *item; struct ref_update *new_update; if ((update->flags & REF_LOG_ONLY) || @@ -2404,13 +2409,13 @@ static int split_head_update(struct ref_update *update, * 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")) { + if (string_list_has_string(&transaction->refnames, "HEAD")) { /* An entry already existed */ strbuf_addf(err, "multiple updates for 'HEAD' (including one " "via its referent '%s') are not allowed", update->refname); - return TRANSACTION_NAME_CONFLICT; + return REF_TRANSACTION_ERROR_NAME_CONFLICT; } new_update = ref_transaction_add_update( @@ -2426,8 +2431,6 @@ static int split_head_update(struct ref_update *update, */ if (strcmp(new_update->refname, "HEAD")) BUG("%s unexpectedly not 'HEAD'", new_update->refname); - item = string_list_insert(affected_refnames, new_update->refname); - item->util = new_update; return 0; } @@ -2440,13 +2443,11 @@ static int split_head_update(struct ref_update *update, * Note that the new update will itself be subject to splitting when * the iteration gets to it. */ -static int split_symref_update(struct ref_update *update, - const char *referent, - struct ref_transaction *transaction, - struct string_list *affected_refnames, - struct strbuf *err) +static enum ref_transaction_error split_symref_update(struct ref_update *update, + const char *referent, + struct ref_transaction *transaction, + struct strbuf *err) { - struct string_list_item *item; struct ref_update *new_update; unsigned int new_flags; @@ -2456,13 +2457,13 @@ static int split_symref_update(struct ref_update *update, * size, but it happens at most once per symref in a * transaction. */ - if (string_list_has_string(affected_refnames, referent)) { + if (string_list_has_string(&transaction->refnames, referent)) { /* An entry already exists */ strbuf_addf(err, "multiple updates for '%s' (including one " "via symref '%s') are not allowed", referent, update->refname); - return TRANSACTION_NAME_CONFLICT; + return REF_TRANSACTION_ERROR_NAME_CONFLICT; } new_flags = update->flags; @@ -2494,19 +2495,6 @@ static int split_symref_update(struct ref_update *update, update->flags |= REF_LOG_ONLY | REF_NO_DEREF; update->flags &= ~REF_HAVE_OLD; - /* - * Add the referent. This insertion is O(N) in the transaction - * size, but it happens at most once per symref in a - * transaction. Make sure to add new_update->refname, which will - * be valid as long as affected_refnames is in use, and NOT - * referent, which might soon be freed by our caller. - */ - item = string_list_insert(affected_refnames, new_update->refname); - if (item->util) - BUG("%s unexpectedly found in affected_refnames", - new_update->refname); - item->util = new_update; - return 0; } @@ -2516,11 +2504,10 @@ static int split_symref_update(struct ref_update *update, * everything is OK, return 0; otherwise, write an error message to * err and return -1. */ -static int check_old_oid(struct ref_update *update, struct object_id *oid, - struct strbuf *err) +static enum ref_transaction_error check_old_oid(struct ref_update *update, + struct object_id *oid, + struct strbuf *err) { - int ret = TRANSACTION_GENERIC_ERROR; - if (!(update->flags & REF_HAVE_OLD) || oideq(oid, &update->old_oid)) return 0; @@ -2529,21 +2516,20 @@ static int check_old_oid(struct ref_update *update, struct object_id *oid, strbuf_addf(err, "cannot lock ref '%s': " "reference already exists", ref_update_original_update_refname(update)); - ret = TRANSACTION_CREATE_EXISTS; - } - else if (is_null_oid(oid)) + return REF_TRANSACTION_ERROR_CREATE_EXISTS; + } else if (is_null_oid(oid)) { strbuf_addf(err, "cannot lock ref '%s': " "reference is missing but expected %s", ref_update_original_update_refname(update), oid_to_hex(&update->old_oid)); - else - strbuf_addf(err, "cannot lock ref '%s': " - "is at %s but expected %s", - ref_update_original_update_refname(update), - oid_to_hex(oid), - oid_to_hex(&update->old_oid)); + return REF_TRANSACTION_ERROR_NONEXISTENT_REF; + } - return ret; + strbuf_addf(err, "cannot lock ref '%s': is at %s but expected %s", + ref_update_original_update_refname(update), oid_to_hex(oid), + oid_to_hex(&update->old_oid)); + + return REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE; } struct files_transaction_backend_data { @@ -2565,17 +2551,18 @@ struct files_transaction_backend_data { * - If it is an update of head_ref, add a corresponding REF_LOG_ONLY * update of HEAD. */ -static int lock_ref_for_update(struct files_ref_store *refs, - struct ref_update *update, - struct ref_transaction *transaction, - const char *head_ref, - struct string_list *affected_refnames, - struct strbuf *err) +static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *refs, + struct ref_update *update, + size_t update_idx, + struct ref_transaction *transaction, + const char *head_ref, + struct string_list *refnames_to_check, + struct strbuf *err) { struct strbuf referent = STRBUF_INIT; int mustexist = ref_update_expects_existing_old_ref(update); struct files_transaction_backend_data *backend_data; - int ret = 0; + enum ref_transaction_error ret = 0; struct ref_lock *lock; files_assert_main_repository(refs, "lock_ref_for_update"); @@ -2586,8 +2573,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, update->flags |= REF_DELETING; if (head_ref) { - ret = split_head_update(update, transaction, head_ref, - affected_refnames, err); + ret = split_head_update(update, transaction, head_ref, err); if (ret) goto out; } @@ -2596,10 +2582,9 @@ static int lock_ref_for_update(struct files_ref_store *refs, if (lock) { lock->count++; } else { - ret = lock_raw_ref(refs, update->refname, mustexist, - affected_refnames, - &lock, &referent, - &update->type, err); + ret = lock_raw_ref(refs, update, update_idx, mustexist, + refnames_to_check, &transaction->refnames, + &lock, &referent, err); if (ret) { char *reason; @@ -2629,22 +2614,17 @@ static int lock_ref_for_update(struct files_ref_store *refs, strbuf_addf(err, "cannot lock ref '%s': " "error reading reference", ref_update_original_update_refname(update)); - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto out; } } - if (update->old_target) { - if (ref_update_check_old_target(referent.buf, update, err)) { - ret = TRANSACTION_GENERIC_ERROR; - goto out; - } - } else { + if (update->old_target) + ret = ref_update_check_old_target(referent.buf, update, err); + else ret = check_old_oid(update, &lock->old_oid, err); - if (ret) { - goto out; - } - } + if (ret) + goto out; } else { /* * Create a new update for the reference this @@ -2653,9 +2633,8 @@ static int lock_ref_for_update(struct files_ref_store *refs, * of processing the split-off update, so we * don't have to do it here. */ - ret = split_symref_update(update, - referent.buf, transaction, - affected_refnames, err); + ret = split_symref_update(update, referent.buf, + transaction, err); if (ret) goto out; } @@ -2672,7 +2651,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, "but is a regular ref"), ref_update_original_update_refname(update), update->old_target); - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_EXPECTED_SYMREF; goto out; } else { ret = check_old_oid(update, &lock->old_oid, err); @@ -2696,14 +2675,14 @@ static int lock_ref_for_update(struct files_ref_store *refs, if (update->new_target && !(update->flags & REF_LOG_ONLY)) { if (create_symref_lock(lock, update->new_target, err)) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto out; } if (close_ref_gently(lock)) { strbuf_addf(err, "couldn't close '%s.lock'", update->refname); - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto out; } @@ -2721,25 +2700,27 @@ static int lock_ref_for_update(struct files_ref_store *refs, * The reference already has the desired * value, so we don't need to write it. */ - } else if (write_ref_to_lockfile( - refs, lock, &update->new_oid, - update->flags & REF_SKIP_OID_VERIFICATION, - err)) { - char *write_err = strbuf_detach(err, NULL); - - /* - * The lock was freed upon failure of - * write_ref_to_lockfile(): - */ - update->backend_data = NULL; - strbuf_addf(err, - "cannot update ref '%s': %s", - update->refname, write_err); - free(write_err); - ret = TRANSACTION_GENERIC_ERROR; - goto out; } else { - update->flags |= REF_NEEDS_COMMIT; + ret = write_ref_to_lockfile( + refs, lock, &update->new_oid, + update->flags & REF_SKIP_OID_VERIFICATION, + err); + if (ret) { + char *write_err = strbuf_detach(err, NULL); + + /* + * The lock was freed upon failure of + * write_ref_to_lockfile(): + */ + update->backend_data = NULL; + strbuf_addf(err, + "cannot update ref '%s': %s", + update->refname, write_err); + free(write_err); + goto out; + } else { + update->flags |= REF_NEEDS_COMMIT; + } } } if (!(update->flags & REF_NEEDS_COMMIT)) { @@ -2751,7 +2732,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, if (close_ref_gently(lock)) { strbuf_addf(err, "couldn't close '%s.lock'", update->refname); - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto out; } } @@ -2810,7 +2791,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, "ref_transaction_prepare"); size_t i; int ret = 0; - struct string_list affected_refnames = STRING_LIST_INIT_NODUP; + struct string_list refnames_to_check = STRING_LIST_INIT_NODUP; char *head_ref = NULL; int head_type; struct files_transaction_backend_data *backend_data; @@ -2828,36 +2809,14 @@ static int files_transaction_prepare(struct ref_store *ref_store, transaction->backend_data = backend_data; /* - * Fail if a refname appears more than once in the - * transaction. (If we end up splitting up any updates using - * split_symref_update() or split_head_update(), those - * functions will check that the new updates don't have the - * same refname as any existing ones.) Also fail if any of the - * updates use REF_IS_PRUNING without REF_NO_DEREF. + * Fail if any of the updates use REF_IS_PRUNING without REF_NO_DEREF. */ for (i = 0; i < transaction->nr; i++) { struct ref_update *update = transaction->updates[i]; - struct string_list_item *item; if ((update->flags & REF_IS_PRUNING) && !(update->flags & REF_NO_DEREF)) BUG("REF_IS_PRUNING set without REF_NO_DEREF"); - - if (update->flags & REF_LOG_ONLY) - continue; - - item = string_list_append(&affected_refnames, update->refname); - /* - * We store a pointer to update in item->util, but at - * the moment we never use the value of this field - * except to check whether it is non-NULL. - */ - item->util = update; - } - string_list_sort(&affected_refnames); - if (ref_update_reject_duplicates(&affected_refnames, err)) { - ret = TRANSACTION_GENERIC_ERROR; - goto cleanup; } /* @@ -2897,10 +2856,18 @@ static int files_transaction_prepare(struct ref_store *ref_store, for (i = 0; i < transaction->nr; i++) { struct ref_update *update = transaction->updates[i]; - ret = lock_ref_for_update(refs, update, transaction, - head_ref, &affected_refnames, err); - if (ret) + ret = lock_ref_for_update(refs, update, i, transaction, + head_ref, &refnames_to_check, + err); + if (ret) { + if (ref_transaction_maybe_set_rejected(transaction, i, ret)) { + strbuf_reset(err); + ret = 0; + + continue; + } goto cleanup; + } if (update->flags & REF_DELETING && !(update->flags & REF_LOG_ONLY) && @@ -2914,7 +2881,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, refs->packed_ref_store, transaction->flags, err); if (!packed_transaction) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } @@ -2930,9 +2897,30 @@ static int files_transaction_prepare(struct ref_store *ref_store, } } + /* + * Verify that none of the loose reference that we're about to write + * conflict with any existing packed references. Ideally, we'd do this + * check after the packed-refs are locked so that the file cannot + * change underneath our feet. But introducing such a lock now would + * probably do more harm than good as users rely on there not being a + * global lock with the "files" backend. + * + * Another alternative would be to do the check after the (optional) + * lock, but that would extend the time we spend in the globally-locked + * state. + * + * So instead, we accept the race for now. + */ + if (refs_verify_refnames_available(refs->packed_ref_store, &refnames_to_check, + &transaction->refnames, NULL, transaction, + 0, err)) { + ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; + goto cleanup; + } + if (packed_transaction) { if (packed_refs_lock(refs->packed_ref_store, 0, err)) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } backend_data->packed_refs_locked = 1; @@ -2963,7 +2951,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, */ backend_data->packed_transaction = NULL; if (ref_transaction_abort(packed_transaction, err)) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } } @@ -2971,7 +2959,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, cleanup: free(head_ref); - string_list_clear(&affected_refnames, 0); + string_list_clear(&refnames_to_check, 1); if (ret) files_transaction_cleanup(refs, transaction); @@ -3036,6 +3024,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, size_t i; int ret = 0; struct string_list affected_refnames = STRING_LIST_INIT_NODUP; + struct string_list refnames_to_check = STRING_LIST_INIT_NODUP; struct ref_transaction *packed_transaction = NULL; struct ref_transaction *loose_transaction = NULL; @@ -3044,17 +3033,6 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, if (transaction->state != REF_TRANSACTION_PREPARED) BUG("commit called for transaction that is not prepared"); - /* Fail if a refname appears more than once in the transaction: */ - for (i = 0; i < transaction->nr; i++) - if (!(transaction->updates[i]->flags & REF_LOG_ONLY)) - string_list_append(&affected_refnames, - transaction->updates[i]->refname); - string_list_sort(&affected_refnames); - if (ref_update_reject_duplicates(&affected_refnames, err)) { - ret = TRANSACTION_GENERIC_ERROR; - goto cleanup; - } - /* * It's really undefined to call this function in an active * repository or when there are existing references: we are @@ -3068,13 +3046,13 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, * that we are creating already exists. */ if (refs_for_each_rawref(&refs->base, ref_present, - &affected_refnames)) + &transaction->refnames)) BUG("initial ref transaction called with existing refs"); packed_transaction = ref_store_transaction_begin(refs->packed_ref_store, transaction->flags, err); if (!packed_transaction) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } @@ -3085,11 +3063,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, !is_null_oid(&update->old_oid)) BUG("initial ref transaction with old_sha1 set"); - if (refs_verify_refname_available(&refs->base, update->refname, - &affected_refnames, NULL, 1, err)) { - ret = TRANSACTION_NAME_CONFLICT; - goto cleanup; - } + string_list_append(&refnames_to_check, update->refname); /* * packed-refs don't support symbolic refs, root refs and reflogs, @@ -3101,7 +3075,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, if (!loose_transaction) { loose_transaction = ref_store_transaction_begin(&refs->base, 0, err); if (!loose_transaction) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } } @@ -3125,9 +3099,21 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, } } - if (packed_refs_lock(refs->packed_ref_store, 0, err) || - ref_transaction_commit(packed_transaction, err)) { - ret = TRANSACTION_GENERIC_ERROR; + if (packed_refs_lock(refs->packed_ref_store, 0, err)) { + ret = REF_TRANSACTION_ERROR_GENERIC; + goto cleanup; + } + + if (refs_verify_refnames_available(&refs->base, &refnames_to_check, + &affected_refnames, NULL, transaction, + 1, err)) { + packed_refs_unlock(refs->packed_ref_store); + ret = REF_TRANSACTION_ERROR_NAME_CONFLICT; + goto cleanup; + } + + if (ref_transaction_commit(packed_transaction, err)) { + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } packed_refs_unlock(refs->packed_ref_store); @@ -3135,7 +3121,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs, if (loose_transaction) { if (ref_transaction_prepare(loose_transaction, err) || ref_transaction_commit(loose_transaction, err)) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } } @@ -3147,6 +3133,7 @@ cleanup: ref_transaction_free(packed_transaction); transaction->state = REF_TRANSACTION_CLOSED; string_list_clear(&affected_refnames, 0); + string_list_clear(&refnames_to_check, 0); return ret; } @@ -3180,10 +3167,13 @@ static int files_transaction_finish(struct ref_store *ref_store, struct ref_update *update = transaction->updates[i]; struct ref_lock *lock = update->backend_data; + if (update->rejection_err) + continue; + if (update->flags & REF_NEEDS_COMMIT || update->flags & REF_LOG_ONLY) { if (parse_and_write_reflog(refs, update, lock, err)) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } } @@ -3202,7 +3192,7 @@ static int files_transaction_finish(struct ref_store *ref_store, strbuf_addf(err, "couldn't set '%s'", lock->ref_name); unlock_ref(lock); update->backend_data = NULL; - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } } @@ -3258,7 +3248,7 @@ static int files_transaction_finish(struct ref_store *ref_store, strbuf_reset(&sb); files_ref_path(refs, &sb, lock->ref_name); if (unlink_or_msg(sb.buf, err)) { - ret = TRANSACTION_GENERIC_ERROR; + ret = REF_TRANSACTION_ERROR_GENERIC; goto cleanup; } } @@ -3772,6 +3762,9 @@ static int files_fsck_refs_dir(struct ref_store *ref_store, iter = dir_iterator_begin(sb.buf, 0); if (!iter) { + if (errno == ENOENT && !is_main_worktree(wt)) + goto out; + ret = error_errno(_("cannot open directory %s"), sb.buf); goto out; } @@ -3808,6 +3801,7 @@ static int files_fsck_refs_dir(struct ref_store *ref_store, ret = error(_("failed to iterate over '%s'"), sb.buf); out: + dir_iterator_free(iter); strbuf_release(&sb); strbuf_release(&refname); return ret; diff --git a/refs/iterator.c b/refs/iterator.c index d25e568bf0..766d96e795 100644 --- a/refs/iterator.c +++ b/refs/iterator.c @@ -15,15 +15,26 @@ int ref_iterator_advance(struct ref_iterator *ref_iterator) return ref_iterator->vtable->advance(ref_iterator); } +int ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + return ref_iterator->vtable->seek(ref_iterator, prefix); +} + int ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { return ref_iterator->vtable->peel(ref_iterator, peeled); } -int ref_iterator_abort(struct ref_iterator *ref_iterator) +void ref_iterator_free(struct ref_iterator *ref_iterator) { - return ref_iterator->vtable->abort(ref_iterator); + if (ref_iterator) { + ref_iterator->vtable->release(ref_iterator); + /* Help make use-after-free bugs fail quickly: */ + ref_iterator->vtable = NULL; + free(ref_iterator); + } } void base_ref_iterator_init(struct ref_iterator *iter, @@ -36,20 +47,19 @@ void base_ref_iterator_init(struct ref_iterator *iter, iter->flags = 0; } -void base_ref_iterator_free(struct ref_iterator *iter) -{ - /* Help make use-after-free bugs fail quickly: */ - iter->vtable = NULL; - free(iter); -} - struct empty_ref_iterator { struct ref_iterator base; }; -static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator) +static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator UNUSED) +{ + return ITER_DONE; +} + +static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED, + const char *prefix UNUSED) { - return ref_iterator_abort(ref_iterator); + return 0; } static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED, @@ -58,16 +68,15 @@ static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED, BUG("peel called for empty iterator"); } -static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED) { - base_ref_iterator_free(ref_iterator); - return ITER_DONE; } static struct ref_iterator_vtable empty_ref_iterator_vtable = { .advance = empty_ref_iterator_advance, + .seek = empty_ref_iterator_seek, .peel = empty_ref_iterator_peel, - .abort = empty_ref_iterator_abort, + .release = empty_ref_iterator_release, }; struct ref_iterator *empty_ref_iterator_begin(void) @@ -87,7 +96,8 @@ int is_empty_ref_iterator(struct ref_iterator *ref_iterator) struct merge_ref_iterator { struct ref_iterator base; - struct ref_iterator *iter0, *iter1; + struct ref_iterator *iter0, *iter0_owned; + struct ref_iterator *iter1, *iter1_owned; ref_iterator_select_fn *select; void *cb_data; @@ -179,9 +189,8 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) iter->select(iter->iter0, iter->iter1, iter->cb_data); if (selection == ITER_SELECT_DONE) { - return ref_iterator_abort(ref_iterator); + return ITER_DONE; } else if (selection == ITER_SELECT_ERROR) { - ref_iterator_abort(ref_iterator); return ITER_ERROR; } @@ -211,10 +220,31 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) } error: - ref_iterator_abort(ref_iterator); return ITER_ERROR; } +static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct merge_ref_iterator *iter = + (struct merge_ref_iterator *)ref_iterator; + int ret; + + iter->current = NULL; + iter->iter0 = iter->iter0_owned; + iter->iter1 = iter->iter1_owned; + + ret = ref_iterator_seek(iter->iter0, prefix); + if (ret < 0) + return ret; + + ret = ref_iterator_seek(iter->iter1, prefix); + if (ret < 0) + return ret; + + return 0; +} + static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -227,28 +257,19 @@ static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator, return ref_iterator_peel(*iter->current, peeled); } -static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void merge_ref_iterator_release(struct ref_iterator *ref_iterator) { struct merge_ref_iterator *iter = (struct merge_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) { - if (ref_iterator_abort(iter->iter0) != ITER_DONE) - ok = ITER_ERROR; - } - if (iter->iter1) { - if (ref_iterator_abort(iter->iter1) != ITER_DONE) - ok = ITER_ERROR; - } - base_ref_iterator_free(ref_iterator); - return ok; + ref_iterator_free(iter->iter0_owned); + ref_iterator_free(iter->iter1_owned); } static struct ref_iterator_vtable merge_ref_iterator_vtable = { .advance = merge_ref_iterator_advance, + .seek = merge_ref_iterator_seek, .peel = merge_ref_iterator_peel, - .abort = merge_ref_iterator_abort, + .release = merge_ref_iterator_release, }; struct ref_iterator *merge_ref_iterator_begin( @@ -267,8 +288,8 @@ struct ref_iterator *merge_ref_iterator_begin( */ base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable); - iter->iter0 = iter0; - iter->iter1 = iter1; + iter->iter0 = iter->iter0_owned = iter0; + iter->iter1 = iter->iter1_owned = iter1; iter->select = select; iter->cb_data = cb_data; iter->current = NULL; @@ -310,10 +331,10 @@ struct ref_iterator *overlay_ref_iterator_begin( * them. */ if (is_empty_ref_iterator(front)) { - ref_iterator_abort(front); + ref_iterator_free(front); return back; } else if (is_empty_ref_iterator(back)) { - ref_iterator_abort(back); + ref_iterator_free(back); return front; } @@ -350,19 +371,15 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator) while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) { int cmp = compare_prefix(iter->iter0->refname, iter->prefix); - if (cmp < 0) continue; - - if (cmp > 0) { - /* - * As the source iterator is ordered, we - * can stop the iteration as soon as we see a - * refname that comes after the prefix: - */ - ok = ref_iterator_abort(iter->iter0); - break; - } + /* + * As the source iterator is ordered, we + * can stop the iteration as soon as we see a + * refname that comes after the prefix: + */ + if (cmp > 0) + return ITER_DONE; if (iter->trim) { /* @@ -386,12 +403,19 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator) return ITER_OK; } - iter->iter0 = NULL; - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - return ITER_ERROR; return ok; } +static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct prefix_ref_iterator *iter = + (struct prefix_ref_iterator *)ref_iterator; + free(iter->prefix); + iter->prefix = xstrdup_or_null(prefix); + return ref_iterator_seek(iter->iter0, prefix); +} + static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -401,23 +425,19 @@ static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator, return ref_iterator_peel(iter->iter0, peeled); } -static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator) { struct prefix_ref_iterator *iter = (struct prefix_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) - ok = ref_iterator_abort(iter->iter0); + ref_iterator_free(iter->iter0); free(iter->prefix); - base_ref_iterator_free(ref_iterator); - return ok; } static struct ref_iterator_vtable prefix_ref_iterator_vtable = { .advance = prefix_ref_iterator_advance, + .seek = prefix_ref_iterator_seek, .peel = prefix_ref_iterator_peel, - .abort = prefix_ref_iterator_abort, + .release = prefix_ref_iterator_release, }; struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, @@ -453,20 +473,14 @@ int do_for_each_ref_iterator(struct ref_iterator *iter, current_ref_iter = iter; while ((ok = ref_iterator_advance(iter)) == ITER_OK) { retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data); - if (retval) { - /* - * If ref_iterator_abort() returns ITER_ERROR, - * we ignore that error in deference to the - * callback function's return value. - */ - ref_iterator_abort(iter); + if (retval) goto out; - } } out: current_ref_iter = old_ref_iter; if (ok == ITER_ERROR) - return -1; + retval = -1; + ref_iterator_free(iter); return retval; } diff --git a/refs/packed-backend.c b/refs/packed-backend.c index a7b6f74b6e..7fd73a0e6d 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -4,6 +4,7 @@ #include "../git-compat-util.h" #include "../config.h" #include "../dir.h" +#include "../fsck.h" #include "../gettext.h" #include "../hash.h" #include "../hex.h" @@ -299,14 +300,9 @@ struct snapshot_record { size_t len; }; -static int cmp_packed_ref_records(const void *v1, const void *v2, - void *cb_data) -{ - const struct snapshot *snapshot = cb_data; - const struct snapshot_record *e1 = v1, *e2 = v2; - const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1; - const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1; +static int cmp_packed_refname(const char *r1, const char *r2) +{ while (1) { if (*r1 == '\n') return *r2 == '\n' ? 0 : -1; @@ -321,6 +317,17 @@ static int cmp_packed_ref_records(const void *v1, const void *v2, } } +static int cmp_packed_ref_records(const void *v1, const void *v2, + void *cb_data) +{ + const struct snapshot *snapshot = cb_data; + const struct snapshot_record *e1 = v1, *e2 = v2; + const char *r1 = e1->start + snapshot_hexsz(snapshot) + 1; + const char *r2 = e2->start + snapshot_hexsz(snapshot) + 1; + + return cmp_packed_refname(r1, r2); +} + /* * Compare a snapshot record at `rec` to the specified NUL-terminated * refname. @@ -493,8 +500,49 @@ static void verify_buffer_safe(struct snapshot *snapshot) last_line, eof - last_line); } +/* + * When parsing the "packed-refs" file, we will parse it line by line. + * Because we know the start pointer of the refname and the next + * newline pointer, we could calculate the length of the refname by + * subtracting the two pointers. However, there is a corner case where + * the refname contains corrupted embedded NUL characters. And + * `check_refname_format()` will not catch this when the truncated + * refname is still a valid refname. To prevent this, we need to check + * whether the refname contains the NUL characters. + */ +static int refname_contains_nul(struct strbuf *refname) +{ + return !!memchr(refname->buf, '\0', refname->len); +} + #define SMALL_FILE_SIZE (32*1024) +static int allocate_snapshot_buffer(struct snapshot *snapshot, int fd, struct stat *st) +{ + ssize_t bytes_read; + size_t size; + + size = xsize_t(st->st_size); + if (!size) + return 0; + + if (mmap_strategy == MMAP_NONE || size <= SMALL_FILE_SIZE) { + snapshot->buf = xmalloc(size); + bytes_read = read_in_full(fd, snapshot->buf, size); + if (bytes_read < 0 || bytes_read != size) + die_errno("couldn't read %s", snapshot->refs->path); + snapshot->mmapped = 0; + } else { + snapshot->buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + snapshot->mmapped = 1; + } + + snapshot->start = snapshot->buf; + snapshot->eof = snapshot->buf + size; + + return 1; +} + /* * Depending on `mmap_strategy`, either mmap or read the contents of * the `packed-refs` file into the snapshot. Return 1 if the file @@ -503,10 +551,9 @@ static void verify_buffer_safe(struct snapshot *snapshot) */ static int load_contents(struct snapshot *snapshot) { - int fd; struct stat st; - size_t size; - ssize_t bytes_read; + int ret; + int fd; fd = open(snapshot->refs->path, O_RDONLY); if (fd < 0) { @@ -528,27 +575,11 @@ static int load_contents(struct snapshot *snapshot) if (fstat(fd, &st) < 0) die_errno("couldn't stat %s", snapshot->refs->path); - size = xsize_t(st.st_size); - - if (!size) { - close(fd); - return 0; - } else if (mmap_strategy == MMAP_NONE || size <= SMALL_FILE_SIZE) { - snapshot->buf = xmalloc(size); - bytes_read = read_in_full(fd, snapshot->buf, size); - if (bytes_read < 0 || bytes_read != size) - die_errno("couldn't read %s", snapshot->refs->path); - snapshot->mmapped = 0; - } else { - snapshot->buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - snapshot->mmapped = 1; - } - close(fd); - snapshot->start = snapshot->buf; - snapshot->eof = snapshot->buf + size; + ret = allocate_snapshot_buffer(snapshot, fd, &st); - return 1; + close(fd); + return ret; } static const char *find_reference_location_1(struct snapshot *snapshot, @@ -693,7 +724,7 @@ static struct snapshot *create_snapshot(struct packed_ref_store *refs) tmp = xmemdupz(snapshot->buf, eol - snapshot->buf); - if (!skip_prefix(tmp, "# pack-refs with:", (const char **)&p)) + if (!skip_prefix(tmp, "# pack-refs with: ", (const char **)&p)) die_invalid_line(refs->path, snapshot->buf, snapshot->eof - snapshot->buf); @@ -819,6 +850,8 @@ struct packed_ref_iterator { struct snapshot *snapshot; + char *prefix; + /* The current position in the snapshot's buffer: */ const char *pos; @@ -841,11 +874,9 @@ struct packed_ref_iterator { }; /* - * Move the iterator to the next record in the snapshot, without - * respect for whether the record is actually required by the current - * iteration. Adjust the fields in `iter` and return `ITER_OK` or - * `ITER_DONE`. This function does not free the iterator in the case - * of `ITER_DONE`. + * Move the iterator to the next record in the snapshot. Adjust the fields in + * `iter` and return `ITER_OK` or `ITER_DONE`. This function does not free the + * iterator in the case of `ITER_DONE`. */ static int next_record(struct packed_ref_iterator *iter) { @@ -894,6 +925,9 @@ static int next_record(struct packed_ref_iterator *iter) strbuf_add(&iter->refname_buf, p, eol - p); iter->base.refname = iter->refname_buf.buf; + if (refname_contains_nul(&iter->refname_buf)) + die("packed refname contains embedded NULL: %s", iter->base.refname); + if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) { if (!refname_is_safe(iter->base.refname)) die("packed refname is dangerous: %s", @@ -942,6 +976,9 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator) int ok; while ((ok = next_record(iter)) == ITER_OK) { + const char *refname = iter->base.refname; + const char *prefix = iter->prefix; + if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY && !is_per_worktree_ref(iter->base.refname)) continue; @@ -951,15 +988,41 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator) &iter->oid, iter->flags)) continue; + while (prefix && *prefix) { + if ((unsigned char)*refname < (unsigned char)*prefix) + BUG("packed-refs backend yielded reference preceding its prefix"); + else if ((unsigned char)*refname > (unsigned char)*prefix) + return ITER_DONE; + prefix++; + refname++; + } + return ITER_OK; } - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - ok = ITER_ERROR; - return ok; } +static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct packed_ref_iterator *iter = + (struct packed_ref_iterator *)ref_iterator; + const char *start; + + if (prefix && *prefix) + start = find_reference_location(iter->snapshot, prefix, 0); + else + start = iter->snapshot->start; + + free(iter->prefix); + iter->prefix = xstrdup_or_null(prefix); + iter->pos = start; + iter->eof = iter->snapshot->eof; + + return 0; +} + static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -976,23 +1039,21 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator, } } -static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void packed_ref_iterator_release(struct ref_iterator *ref_iterator) { struct packed_ref_iterator *iter = (struct packed_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - strbuf_release(&iter->refname_buf); free(iter->jump); + free(iter->prefix); release_snapshot(iter->snapshot); - base_ref_iterator_free(ref_iterator); - return ok; } static struct ref_iterator_vtable packed_ref_iterator_vtable = { .advance = packed_ref_iterator_advance, + .seek = packed_ref_iterator_seek, .peel = packed_ref_iterator_peel, - .abort = packed_ref_iterator_abort + .release = packed_ref_iterator_release, }; static int jump_list_entry_cmp(const void *va, const void *vb) @@ -1104,7 +1165,6 @@ static struct ref_iterator *packed_ref_iterator_begin( { struct packed_ref_store *refs; struct snapshot *snapshot; - const char *start; struct packed_ref_iterator *iter; struct ref_iterator *ref_iterator; unsigned int required_flags = REF_STORE_READ; @@ -1120,14 +1180,6 @@ static struct ref_iterator *packed_ref_iterator_begin( */ snapshot = get_snapshot(refs); - if (prefix && *prefix) - start = find_reference_location(snapshot, prefix, 0); - else - start = snapshot->start; - - if (start == snapshot->eof) - return empty_ref_iterator_begin(); - CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable); @@ -1137,19 +1189,15 @@ static struct ref_iterator *packed_ref_iterator_begin( iter->snapshot = snapshot; acquire_snapshot(snapshot); - - iter->pos = start; - iter->eof = snapshot->eof; strbuf_init(&iter->refname_buf, 0); - iter->base.oid = &iter->oid; - iter->repo = ref_store->repo; iter->flags = flags; - if (prefix && *prefix) - /* Stop iteration after we've gone *past* prefix: */ - ref_iterator = prefix_ref_iterator_begin(ref_iterator, prefix, 0); + if (packed_ref_iterator_seek(&iter->base, prefix) < 0) { + ref_iterator_free(&iter->base); + return NULL; + } return ref_iterator; } @@ -1312,10 +1360,12 @@ static int packed_ref_store_remove_on_disk(struct ref_store *ref_store, * The packfile must be locked before calling this function and will * remain locked when it is done. */ -static int write_with_updates(struct packed_ref_store *refs, - struct string_list *updates, - struct strbuf *err) +static enum ref_transaction_error write_with_updates(struct packed_ref_store *refs, + struct ref_transaction *transaction, + struct strbuf *err) { + enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC; + struct string_list *updates = &transaction->refnames; struct ref_iterator *iter = NULL; size_t i; int ok; @@ -1339,7 +1389,7 @@ static int write_with_updates(struct packed_ref_store *refs, strbuf_addf(err, "unable to create file %s: %s", sb.buf, strerror(errno)); strbuf_release(&sb); - return -1; + return REF_TRANSACTION_ERROR_GENERIC; } strbuf_release(&sb); @@ -1362,8 +1412,10 @@ static int write_with_updates(struct packed_ref_store *refs, */ iter = packed_ref_iterator_begin(&refs->base, "", NULL, DO_FOR_EACH_INCLUDE_BROKEN); - if ((ok = ref_iterator_advance(iter)) != ITER_OK) + if ((ok = ref_iterator_advance(iter)) != ITER_OK) { + ref_iterator_free(iter); iter = NULL; + } i = 0; @@ -1393,6 +1445,14 @@ static int write_with_updates(struct packed_ref_store *refs, strbuf_addf(err, "cannot update ref '%s': " "reference already exists", update->refname); + ret = REF_TRANSACTION_ERROR_CREATE_EXISTS; + + if (ref_transaction_maybe_set_rejected(transaction, i, ret)) { + strbuf_reset(err); + ret = 0; + continue; + } + goto error; } else if (!oideq(&update->old_oid, iter->oid)) { strbuf_addf(err, "cannot update ref '%s': " @@ -1400,6 +1460,14 @@ static int write_with_updates(struct packed_ref_store *refs, update->refname, oid_to_hex(iter->oid), oid_to_hex(&update->old_oid)); + ret = REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE; + + if (ref_transaction_maybe_set_rejected(transaction, i, ret)) { + strbuf_reset(err); + ret = 0; + continue; + } + goto error; } } @@ -1411,8 +1479,10 @@ static int write_with_updates(struct packed_ref_store *refs, * the iterator over the unneeded * value. */ - if ((ok = ref_iterator_advance(iter)) != ITER_OK) + if ((ok = ref_iterator_advance(iter)) != ITER_OK) { + ref_iterator_free(iter); iter = NULL; + } cmp = +1; } else { /* @@ -1434,6 +1504,14 @@ static int write_with_updates(struct packed_ref_store *refs, "reference is missing but expected %s", update->refname, oid_to_hex(&update->old_oid)); + ret = REF_TRANSACTION_ERROR_NONEXISTENT_REF; + + if (ref_transaction_maybe_set_rejected(transaction, i, ret)) { + strbuf_reset(err); + ret = 0; + continue; + } + goto error; } } @@ -1449,8 +1527,10 @@ static int write_with_updates(struct packed_ref_store *refs, peel_error ? NULL : &peeled)) goto write_error; - if ((ok = ref_iterator_advance(iter)) != ITER_OK) + if ((ok = ref_iterator_advance(iter)) != ITER_OK) { + ref_iterator_free(iter); iter = NULL; + } } else if (is_null_oid(&update->new_oid)) { /* * The update wants to delete the reference, @@ -1489,7 +1569,7 @@ static int write_with_updates(struct packed_ref_store *refs, strerror(errno)); strbuf_release(&sb); delete_tempfile(&refs->tempfile); - return -1; + return REF_TRANSACTION_ERROR_GENERIC; } return 0; @@ -1497,13 +1577,12 @@ static int write_with_updates(struct packed_ref_store *refs, write_error: strbuf_addf(err, "error writing to %s: %s", get_tempfile_path(refs->tempfile), strerror(errno)); + ret = REF_TRANSACTION_ERROR_GENERIC; error: - if (iter) - ref_iterator_abort(iter); - + ref_iterator_free(iter); delete_tempfile(&refs->tempfile); - return -1; + return ret; } int is_packed_transaction_needed(struct ref_store *ref_store, @@ -1604,8 +1683,6 @@ int is_packed_transaction_needed(struct ref_store *ref_store, struct packed_transaction_backend_data { /* True iff the transaction owns the packed-refs lock. */ int own_lock; - - struct string_list updates; }; static void packed_transaction_cleanup(struct packed_ref_store *refs, @@ -1614,8 +1691,6 @@ static void packed_transaction_cleanup(struct packed_ref_store *refs, struct packed_transaction_backend_data *data = transaction->backend_data; if (data) { - string_list_clear(&data->updates, 0); - if (is_tempfile_active(refs->tempfile)) delete_tempfile(&refs->tempfile); @@ -1640,8 +1715,7 @@ static int packed_transaction_prepare(struct ref_store *ref_store, REF_STORE_READ | REF_STORE_WRITE | REF_STORE_ODB, "ref_transaction_prepare"); struct packed_transaction_backend_data *data; - size_t i; - int ret = TRANSACTION_GENERIC_ERROR; + enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC; /* * Note that we *don't* skip transactions with zero updates, @@ -1653,34 +1727,17 @@ static int packed_transaction_prepare(struct ref_store *ref_store, */ CALLOC_ARRAY(data, 1); - string_list_init_nodup(&data->updates); transaction->backend_data = data; - /* - * Stick the updates in a string list by refname so that we - * can sort them: - */ - for (i = 0; i < transaction->nr; i++) { - struct ref_update *update = transaction->updates[i]; - struct string_list_item *item = - string_list_append(&data->updates, update->refname); - - /* Store a pointer to update in item->util: */ - item->util = update; - } - string_list_sort(&data->updates); - - if (ref_update_reject_duplicates(&data->updates, err)) - goto failure; - if (!is_lock_file_locked(&refs->lock)) { if (packed_refs_lock(ref_store, 0, err)) goto failure; data->own_lock = 1; } - if (write_with_updates(refs, &data->updates, err)) + ret = write_with_updates(refs, transaction, err); + if (ret) goto failure; transaction->state = REF_TRANSACTION_PREPARED; @@ -1712,7 +1769,7 @@ static int packed_transaction_finish(struct ref_store *ref_store, ref_store, REF_STORE_READ | REF_STORE_WRITE | REF_STORE_ODB, "ref_transaction_finish"); - int ret = TRANSACTION_GENERIC_ERROR; + int ret = REF_TRANSACTION_ERROR_GENERIC; char *packed_refs_path; clear_snapshot(refs); @@ -1748,15 +1805,333 @@ static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_s return empty_ref_iterator_begin(); } -static int packed_fsck(struct ref_store *ref_store UNUSED, - struct fsck_options *o UNUSED, +static int packed_fsck_ref_next_line(struct fsck_options *o, + unsigned long line_number, const char *start, + const char *eof, const char **eol) +{ + int ret = 0; + + *eol = memchr(start, '\n', eof - start); + if (!*eol) { + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + ret = fsck_report_ref(o, &report, + FSCK_MSG_PACKED_REF_ENTRY_NOT_TERMINATED, + "'%.*s' is not terminated with a newline", + (int)(eof - start), start); + + /* + * There is no newline but we still want to parse it to the end of + * the buffer. + */ + *eol = eof; + strbuf_release(&packed_entry); + } + + return ret; +} + +static int packed_fsck_ref_header(struct fsck_options *o, + const char *start, const char *eol, + unsigned int *sorted) +{ + struct string_list traits = STRING_LIST_INIT_NODUP; + char *tmp_line; + int ret = 0; + char *p; + + tmp_line = xmemdupz(start, eol - start); + if (!skip_prefix(tmp_line, "# pack-refs with: ", (const char **)&p)) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs.header"; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_HEADER, + "'%.*s' does not start with '# pack-refs with: '", + (int)(eol - start), start); + goto cleanup; + } + + string_list_split_in_place(&traits, p, " ", -1); + *sorted = unsorted_string_list_has_string(&traits, "sorted"); + +cleanup: + free(tmp_line); + string_list_clear(&traits, 0); + return ret; +} + +static int packed_fsck_ref_peeled_line(struct fsck_options *o, + struct ref_store *ref_store, + unsigned long line_number, + const char *start, const char *eol) +{ + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct object_id peeled; + const char *p; + int ret = 0; + + /* + * Skip the '^' and parse the peeled oid. + */ + start++; + if (parse_oid_hex_algop(start, &peeled, &p, ref_store->repo->hash_algo)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%.*s' has invalid peeled oid", + (int)(eol - start), start); + goto cleanup; + } + + if (p != eol) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "has trailing garbage after peeled oid '%.*s'", + (int)(eol - p), p); + goto cleanup; + } + +cleanup: + strbuf_release(&packed_entry); + return ret; +} + +static int packed_fsck_ref_main_line(struct fsck_options *o, + struct ref_store *ref_store, + unsigned long line_number, + struct strbuf *refname, + const char *start, const char *eol) +{ + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct object_id oid; + const char *p; + int ret = 0; + + if (parse_oid_hex_algop(start, &oid, &p, ref_store->repo->hash_algo)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%.*s' has invalid oid", + (int)(eol - start), start); + goto cleanup; + } + + if (p == eol || !isspace(*p)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "has no space after oid '%s' but with '%.*s'", + oid_to_hex(&oid), (int)(eol - p), p); + goto cleanup; + } + + p++; + strbuf_reset(refname); + strbuf_add(refname, p, eol - p); + if (refname_contains_nul(refname)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "refname '%s' contains NULL binaries", + refname->buf); + } + + if (check_refname_format(refname->buf, 0)) { + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_NAME, + "has bad refname '%s'", refname->buf); + } + +cleanup: + strbuf_release(&packed_entry); + return ret; +} + +static int packed_fsck_ref_sorted(struct fsck_options *o, + struct ref_store *ref_store, + const char *start, const char *eof) +{ + size_t hexsz = ref_store->repo->hash_algo->hexsz; + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct strbuf refname1 = STRBUF_INIT; + struct strbuf refname2 = STRBUF_INIT; + unsigned long line_number = 1; + const char *former = NULL; + const char *current; + const char *eol; + int ret = 0; + + if (*start == '#') { + eol = memchr(start, '\n', eof - start); + start = eol + 1; + line_number++; + } + + for (; start < eof; line_number++, start = eol + 1) { + eol = memchr(start, '\n', eof - start); + + if (*start == '^') + continue; + + if (!former) { + former = start + hexsz + 1; + continue; + } + + current = start + hexsz + 1; + if (cmp_packed_refname(former, current) >= 0) { + const char *err_fmt = + "refname '%s' is less than previous refname '%s'"; + + eol = memchr(former, '\n', eof - former); + strbuf_add(&refname1, former, eol - former); + eol = memchr(current, '\n', eof - current); + strbuf_add(&refname2, current, eol - current); + + strbuf_addf(&packed_entry, "packed-refs line %lu", line_number); + report.path = packed_entry.buf; + ret = fsck_report_ref(o, &report, + FSCK_MSG_PACKED_REF_UNSORTED, + err_fmt, refname2.buf, refname1.buf); + goto cleanup; + } + former = current; + } + +cleanup: + strbuf_release(&packed_entry); + strbuf_release(&refname1); + strbuf_release(&refname2); + return ret; +} + +static int packed_fsck_ref_content(struct fsck_options *o, + struct ref_store *ref_store, + unsigned int *sorted, + const char *start, const char *eof) +{ + struct strbuf refname = STRBUF_INIT; + unsigned long line_number = 1; + const char *eol; + int ret = 0; + + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + if (*start == '#') { + ret |= packed_fsck_ref_header(o, start, eol, sorted); + + start = eol + 1; + line_number++; + } + + while (start < eof) { + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + ret |= packed_fsck_ref_main_line(o, ref_store, line_number, &refname, start, eol); + start = eol + 1; + line_number++; + if (start < eof && *start == '^') { + ret |= packed_fsck_ref_next_line(o, line_number, start, eof, &eol); + ret |= packed_fsck_ref_peeled_line(o, ref_store, line_number, + start, eol); + start = eol + 1; + line_number++; + } + } + + strbuf_release(&refname); + return ret; +} + +static int packed_fsck(struct ref_store *ref_store, + struct fsck_options *o, struct worktree *wt) { + struct packed_ref_store *refs = packed_downcast(ref_store, + REF_STORE_READ, "fsck"); + struct snapshot snapshot = { 0 }; + unsigned int sorted = 0; + struct stat st; + int ret = 0; + int fd = -1; if (!is_main_worktree(wt)) - return 0; + goto cleanup; - return 0; + if (o->verbose) + fprintf_ln(stderr, "Checking packed-refs file %s", refs->path); + + fd = open_nofollow(refs->path, O_RDONLY); + if (fd < 0) { + /* + * If the packed-refs file doesn't exist, there's nothing + * to check. + */ + if (errno == ENOENT) + goto cleanup; + + if (errno == ELOOP) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs"; + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_FILETYPE, + "not a regular file but a symlink"); + goto cleanup; + } + + ret = error_errno(_("unable to open '%s'"), refs->path); + goto cleanup; + } else if (fstat(fd, &st) < 0) { + ret = error_errno(_("unable to stat '%s'"), refs->path); + goto cleanup; + } else if (!S_ISREG(st.st_mode)) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs"; + ret = fsck_report_ref(o, &report, + FSCK_MSG_BAD_REF_FILETYPE, + "not a regular file"); + goto cleanup; + } + + if (!allocate_snapshot_buffer(&snapshot, fd, &st)) { + struct fsck_ref_report report = { 0 }; + report.path = "packed-refs"; + ret = fsck_report_ref(o, &report, + FSCK_MSG_EMPTY_PACKED_REFS_FILE, + "file is empty"); + goto cleanup; + } + + ret = packed_fsck_ref_content(o, ref_store, &sorted, snapshot.start, + snapshot.eof); + if (!ret && sorted) + ret = packed_fsck_ref_sorted(o, ref_store, snapshot.start, + snapshot.eof); + +cleanup: + if (fd >= 0) + close(fd); + clear_snapshot_buffer(&snapshot); + return ret; } struct ref_storage_be refs_be_packed = { diff --git a/refs/ref-cache.c b/refs/ref-cache.c index 02f09e4df8..c1f1bab1d5 100644 --- a/refs/ref-cache.c +++ b/refs/ref-cache.c @@ -362,9 +362,7 @@ struct cache_ref_iterator { struct ref_iterator base; /* - * The number of levels currently on the stack. This is always - * at least 1, because when it becomes zero the iteration is - * ended and this struct is freed. + * The number of levels currently on the stack. */ size_t levels_nr; @@ -376,7 +374,7 @@ struct cache_ref_iterator { * The prefix is matched textually, without regard for path * component boundaries. */ - const char *prefix; + char *prefix; /* * A stack of levels. levels[0] is the uppermost level that is @@ -389,6 +387,9 @@ struct cache_ref_iterator { struct cache_ref_iterator_level *levels; struct repository *repo; + struct ref_cache *cache; + + int prime_dir; }; static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) @@ -396,6 +397,9 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) struct cache_ref_iterator *iter = (struct cache_ref_iterator *)ref_iterator; + if (!iter->levels_nr) + return ITER_DONE; + while (1) { struct cache_ref_iterator_level *level = &iter->levels[iter->levels_nr - 1]; @@ -409,7 +413,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) if (++level->index == level->dir->nr) { /* This level is exhausted; pop up a level */ if (--iter->levels_nr == 0) - return ref_iterator_abort(ref_iterator); + return ITER_DONE; continue; } @@ -444,6 +448,41 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator) } } +static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct cache_ref_iterator *iter = + (struct cache_ref_iterator *)ref_iterator; + struct cache_ref_iterator_level *level; + struct ref_dir *dir; + + dir = get_ref_dir(iter->cache->root); + if (prefix && *prefix) + dir = find_containing_dir(dir, prefix); + if (!dir) { + iter->levels_nr = 0; + return 0; + } + + if (iter->prime_dir) + prime_ref_dir(dir, prefix); + iter->levels_nr = 1; + level = &iter->levels[0]; + level->index = -1; + level->dir = dir; + + if (prefix && *prefix) { + free(iter->prefix); + iter->prefix = xstrdup(prefix); + level->prefix_state = PREFIX_WITHIN_DIR; + } else { + FREE_AND_NULL(iter->prefix); + level->prefix_state = PREFIX_CONTAINS_DIR; + } + + return 0; +} + static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -452,21 +491,19 @@ static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator, return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0; } -static int cache_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void cache_ref_iterator_release(struct ref_iterator *ref_iterator) { struct cache_ref_iterator *iter = (struct cache_ref_iterator *)ref_iterator; - - free((char *)iter->prefix); + free(iter->prefix); free(iter->levels); - base_ref_iterator_free(ref_iterator); - return ITER_DONE; } static struct ref_iterator_vtable cache_ref_iterator_vtable = { .advance = cache_ref_iterator_advance, + .seek = cache_ref_iterator_seek, .peel = cache_ref_iterator_peel, - .abort = cache_ref_iterator_abort + .release = cache_ref_iterator_release, }; struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, @@ -474,39 +511,22 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache, struct repository *repo, int prime_dir) { - struct ref_dir *dir; struct cache_ref_iterator *iter; struct ref_iterator *ref_iterator; - struct cache_ref_iterator_level *level; - - dir = get_ref_dir(cache->root); - if (prefix && *prefix) - dir = find_containing_dir(dir, prefix); - if (!dir) - /* There's nothing to iterate over. */ - return empty_ref_iterator_begin(); - - if (prime_dir) - prime_ref_dir(dir, prefix); CALLOC_ARRAY(iter, 1); ref_iterator = &iter->base; base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable); ALLOC_GROW(iter->levels, 10, iter->levels_alloc); - iter->levels_nr = 1; - level = &iter->levels[0]; - level->index = -1; - level->dir = dir; + iter->repo = repo; + iter->cache = cache; + iter->prime_dir = prime_dir; - if (prefix && *prefix) { - iter->prefix = xstrdup(prefix); - level->prefix_state = PREFIX_WITHIN_DIR; - } else { - level->prefix_state = PREFIX_CONTAINS_DIR; + if (cache_ref_iterator_seek(&iter->base, prefix) < 0) { + ref_iterator_free(&iter->base); + return NULL; } - iter->repo = repo; - return ref_iterator; } diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 8894b43d1d..f868870851 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -3,6 +3,7 @@ #include "refs.h" #include "iterator.h" +#include "string-list.h" struct fsck_options; struct ref_transaction; @@ -123,6 +124,12 @@ struct ref_update { uint64_t index; /* + * Used in batched reference updates to mark if a given update + * was rejected. + */ + enum ref_transaction_error rejection_err; + + /* * If this ref_update was split off of a symref update via * split_symref_update(), then this member points at that * update. This is used for two purposes: @@ -142,12 +149,11 @@ int refs_read_raw_ref(struct ref_store *ref_store, const char *refname, unsigned int *type, int *failure_errno); /* - * Write an error to `err` and return a nonzero value iff the same - * refname appears multiple times in `refnames`. `refnames` must be - * sorted on entry to this function. + * Mark a given update as rejected with a given reason. */ -int ref_update_reject_duplicates(struct string_list *refnames, - struct strbuf *err); +int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction, + size_t update_idx, + enum ref_transaction_error err); /* * Add a ref_update with the specified properties to transaction, and @@ -191,6 +197,18 @@ enum ref_transaction_state { }; /* + * Data structure to hold indices of updates which were rejected, for batched + * reference updates. While the updates themselves hold the rejection error, + * this structure allows a transaction to iterate only over the rejected + * updates. + */ +struct ref_transaction_rejections { + size_t *update_indices; + size_t alloc; + size_t nr; +}; + +/* * Data structure for holding a reference transaction, which can * consist of checks and updates to multiple references, carried out * as atomically as possible. This structure is opaque to callers. @@ -198,9 +216,11 @@ enum ref_transaction_state { struct ref_transaction { struct ref_store *ref_store; struct ref_update **updates; + struct string_list refnames; size_t alloc; size_t nr; enum ref_transaction_state state; + struct ref_transaction_rejections *rejections; void *backend_data; unsigned int flags; uint64_t max_index; @@ -273,11 +293,11 @@ enum do_for_each_ref_flags { * the next reference and returns ITER_OK. The data pointed at by * refname and oid belong to the iterator; if you want to retain them * after calling ref_iterator_advance() again or calling - * ref_iterator_abort(), you must make a copy. When the iteration has + * ref_iterator_free(), you must make a copy. When the iteration has * been exhausted, ref_iterator_advance() releases any resources * associated with the iteration, frees the ref_iterator object, and * returns ITER_DONE. If you want to abort the iteration early, call - * ref_iterator_abort(), which also frees the ref_iterator object and + * ref_iterator_free(), which also frees the ref_iterator object and * any associated resources. If there was an internal error advancing * to the next entry, ref_iterator_advance() aborts the iteration, * frees the ref_iterator, and returns ITER_ERROR. @@ -293,7 +313,7 @@ enum do_for_each_ref_flags { * * while ((ok = ref_iterator_advance(iter)) == ITER_OK) { * if (want_to_stop_iteration()) { - * ok = ref_iterator_abort(iter); + * ok = ITER_DONE; * break; * } * @@ -307,6 +327,7 @@ enum do_for_each_ref_flags { * * if (ok != ITER_DONE) * handle_error(); + * ref_iterator_free(iter); */ struct ref_iterator { struct ref_iterator_vtable *vtable; @@ -327,18 +348,30 @@ struct ref_iterator { int ref_iterator_advance(struct ref_iterator *ref_iterator); /* + * Seek the iterator to the first reference with the given prefix. + * The prefix is matched as a literal string, without regard for path + * separators. If prefix is NULL or the empty string, seek the iterator to the + * first reference again. + * + * This function is expected to behave as if a new ref iterator with the same + * prefix had been created, but allows reuse of iterators and thus may allow + * the backend to optimize. Parameters other than the prefix that have been + * passed when creating the iterator will remain unchanged. + * + * Returns 0 on success, a negative error code otherwise. + */ +int ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix); + +/* * If possible, peel the reference currently being viewed by the * iterator. Return 0 on success. */ int ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled); -/* - * End the iteration before it has been exhausted, freeing the - * reference iterator and any associated resources and returning - * ITER_DONE. If the abort itself failed, return ITER_ERROR. - */ -int ref_iterator_abort(struct ref_iterator *ref_iterator); +/* Free the reference iterator and any associated resources. */ +void ref_iterator_free(struct ref_iterator *ref_iterator); /* * An iterator over nothing (its first ref_iterator_advance() call @@ -438,13 +471,6 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, void base_ref_iterator_init(struct ref_iterator *iter, struct ref_iterator_vtable *vtable); -/* - * Base class destructor for ref_iterators. Destroy the ref_iterator - * part of iter and shallow-free the object. This is meant to be - * called only by the destructors of derived classes. - */ -void base_ref_iterator_free(struct ref_iterator *iter); - /* Virtual function declarations for ref_iterators: */ /* @@ -456,6 +482,13 @@ void base_ref_iterator_free(struct ref_iterator *iter); typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator); /* + * Seek the iterator to the first reference matching the given prefix. Should + * behave the same as if a new iterator was created with the same prefix. + */ +typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator, + const char *prefix); + +/* * Peels the current ref, returning 0 for success or -1 for failure. */ typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator, @@ -463,15 +496,15 @@ typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator, /* * Implementations of this function should free any resources specific - * to the derived class, then call base_ref_iterator_free() to clean - * up and free the ref_iterator object. + * to the derived class. */ -typedef int ref_iterator_abort_fn(struct ref_iterator *ref_iterator); +typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator); struct ref_iterator_vtable { ref_iterator_advance_fn *advance; + ref_iterator_seek_fn *seek; ref_iterator_peel_fn *peel; - ref_iterator_abort_fn *abort; + ref_iterator_release_fn *release; }; /* @@ -763,8 +796,9 @@ int ref_update_has_null_new_value(struct ref_update *update); * If everything is OK, return 0; otherwise, write an error message to * err and return -1. */ -int ref_update_check_old_target(const char *referent, struct ref_update *update, - struct strbuf *err); +enum ref_transaction_error ref_update_check_old_target(const char *referent, + struct ref_update *update, + struct strbuf *err); /* * Check if the ref must exist, this means that the old_oid or @@ -772,4 +806,20 @@ int ref_update_check_old_target(const char *referent, struct ref_update *update, */ int ref_update_expects_existing_old_ref(struct ref_update *update); +/* + * Same as `refs_verify_refname_available()`, but checking for a list of + * refnames instead of only a single item. This is more efficient in the case + * where one needs to check multiple refnames. + * + * If using batched updates, then individual updates are marked rejected, + * reference backends are then in charge of not committing those updates. + */ +enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs, + const struct string_list *refnames, + const struct string_list *extras, + const struct string_list *skip, + struct ref_transaction *transaction, + unsigned int initial_transaction, + struct strbuf *err); + #endif /* REFS_REFS_INTERNAL_H */ diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 771f50df38..4c3817f4ec 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -547,7 +547,7 @@ struct reftable_ref_iterator { struct reftable_ref_record ref; struct object_id oid; - const char *prefix; + char *prefix; size_t prefix_len; char **exclude_patterns; size_t exclude_patterns_index; @@ -711,20 +711,27 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator) break; } - if (iter->err > 0) { - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - return ITER_ERROR; + if (iter->err > 0) return ITER_DONE; - } - - if (iter->err < 0) { - ref_iterator_abort(ref_iterator); + if (iter->err < 0) return ITER_ERROR; - } - return ITER_OK; } +static int reftable_ref_iterator_seek(struct ref_iterator *ref_iterator, + const char *prefix) +{ + struct reftable_ref_iterator *iter = + (struct reftable_ref_iterator *)ref_iterator; + + free(iter->prefix); + iter->prefix = xstrdup_or_null(prefix); + iter->prefix_len = prefix ? strlen(prefix) : 0; + iter->err = reftable_iterator_seek_ref(&iter->iter, prefix); + + return iter->err; +} + static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator, struct object_id *peeled) { @@ -740,7 +747,7 @@ static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator, return -1; } -static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator) +static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator) { struct reftable_ref_iterator *iter = (struct reftable_ref_iterator *)ref_iterator; @@ -751,14 +758,14 @@ static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator) free(iter->exclude_patterns[i]); free(iter->exclude_patterns); } - free(iter); - return ITER_DONE; + free(iter->prefix); } static struct ref_iterator_vtable reftable_ref_iterator_vtable = { .advance = reftable_ref_iterator_advance, + .seek = reftable_ref_iterator_seek, .peel = reftable_ref_iterator_peel, - .abort = reftable_ref_iterator_abort + .release = reftable_ref_iterator_release, }; static int qsort_strcmp(const void *va, const void *vb) @@ -815,8 +822,6 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_ 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; @@ -830,8 +835,11 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_ if (ret) goto done; - reftable_stack_init_ref_iterator(stack, &iter->iter); - ret = reftable_iterator_seek_ref(&iter->iter, prefix); + ret = reftable_stack_init_ref_iterator(stack, &iter->iter); + if (ret) + goto done; + + ret = reftable_ref_iterator_seek(&iter->base, prefix); if (ret) goto done; @@ -1061,6 +1069,244 @@ static int queue_transaction_update(struct reftable_ref_store *refs, return 0; } +static enum ref_transaction_error prepare_single_update(struct reftable_ref_store *refs, + struct reftable_transaction_data *tx_data, + struct ref_transaction *transaction, + struct reftable_backend *be, + struct ref_update *u, + size_t update_idx, + struct string_list *refnames_to_check, + unsigned int head_type, + struct strbuf *head_referent, + struct strbuf *referent, + struct strbuf *err) +{ + enum ref_transaction_error ret = 0; + struct object_id current_oid = {0}; + const char *rewritten_ref; + + /* + * There is no need to reload the respective backends here as + * we have already reloaded them when preparing the transaction + * update. And given that the stacks have been locked there + * shouldn't have been any concurrent modifications of the + * stack. + */ + ret = backend_for(&be, refs, u->refname, &rewritten_ref, 0); + if (ret) + return REF_TRANSACTION_ERROR_GENERIC; + + /* 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)); + return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE; + } + + 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); + return REF_TRANSACTION_ERROR_INVALID_NEW_VALUE; + } + } + + /* + * 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)) { + /* + * 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(&transaction->refnames, "HEAD")) { + /* An entry already existed */ + strbuf_addf(err, + _("multiple updates for 'HEAD' (including one " + "via its referent '%s') are not allowed"), + u->refname); + return REF_TRANSACTION_ERROR_NAME_CONFLICT; + } + + ref_transaction_add_update( + transaction, "HEAD", + u->flags | REF_LOG_ONLY | REF_NO_DEREF, + &u->new_oid, &u->old_oid, NULL, NULL, NULL, + u->msg); + } + + ret = reftable_backend_read_ref(be, rewritten_ref, + ¤t_oid, referent, &u->type); + if (ret < 0) + return REF_TRANSACTION_ERROR_GENERIC; + if (ret > 0 && !ref_update_expects_existing_old_ref(u)) { + struct string_list_item *item; + /* + * 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. + */ + item = string_list_append(refnames_to_check, u->refname); + item->util = xmalloc(sizeof(update_idx)); + memcpy(item->util, &update_idx, sizeof(update_idx)); + + /* + * There is no need to write the reference deletion + * when the reference in question doesn't exist. + */ + if ((u->flags & REF_HAVE_NEW) && !ref_update_has_null_new_value(u)) { + ret = queue_transaction_update(refs, tx_data, u, + ¤t_oid, err); + if (ret) + return REF_TRANSACTION_ERROR_GENERIC; + } + + return 0; + } + 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'"), + ref_update_original_update_refname(u), u->refname); + return REF_TRANSACTION_ERROR_NONEXISTENT_REF; + } + + 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); + return REF_TRANSACTION_ERROR_GENERIC; + } + } 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 (string_list_has_string(&transaction->refnames, referent->buf)) { + strbuf_addf(err, + _("multiple updates for '%s' (including one " + "via symref '%s') are not allowed"), + referent->buf, u->refname); + return REF_TRANSACTION_ERROR_NAME_CONFLICT; + } + + /* + * 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_target ? NULL : &u->new_oid, + u->old_target ? NULL : &u->old_oid, + u->new_target, u->old_target, + u->committer_info, 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; + } + } + + /* + * 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->old_target) { + if (!(u->type & REF_ISSYMREF)) { + strbuf_addf(err, _("cannot lock ref '%s': " + "expected symref with target '%s': " + "but is a regular ref"), + ref_update_original_update_refname(u), + u->old_target); + return REF_TRANSACTION_ERROR_EXPECTED_SYMREF; + } + + ret = ref_update_check_old_target(referent->buf, u, err); + if (ret) + return ret; + } else 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"), + ref_update_original_update_refname(u)); + return REF_TRANSACTION_ERROR_CREATE_EXISTS; + } else if (is_null_oid(¤t_oid)) { + strbuf_addf(err, _("cannot lock ref '%s': " + "reference is missing but expected %s"), + ref_update_original_update_refname(u), + oid_to_hex(&u->old_oid)); + return REF_TRANSACTION_ERROR_NONEXISTENT_REF; + } else { + strbuf_addf(err, _("cannot lock ref '%s': " + "is at %s but expected %s"), + ref_update_original_update_refname(u), + oid_to_hex(¤t_oid), + oid_to_hex(&u->old_oid)); + return REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE; + } + } + + /* + * 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))) + if (queue_transaction_update(refs, tx_data, u, ¤t_oid, err)) + return REF_TRANSACTION_ERROR_GENERIC; + + return 0; +} + static int reftable_be_transaction_prepare(struct ref_store *ref_store, struct ref_transaction *transaction, struct strbuf *err) @@ -1068,7 +1314,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, 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 string_list refnames_to_check = STRING_LIST_INIT_NODUP; struct reftable_transaction_data *tx_data = NULL; struct reftable_backend *be; struct object_id head_oid; @@ -1092,10 +1338,6 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, transaction->updates[i], err); if (ret) goto done; - - if (!(transaction->updates[i]->flags & REF_LOG_ONLY)) - string_list_append(&affected_refnames, - transaction->updates[i]->refname); } /* @@ -1108,17 +1350,6 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, } /* - * 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; - } - - /* * TODO: it's dubious whether we should reload the stack that "HEAD" * belongs to or not. In theory, it may happen that we only modify * stacks which are _not_ part of the "HEAD" stack. In that case we @@ -1140,250 +1371,33 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, ret = 0; for (i = 0; i < transaction->nr; i++) { - struct ref_update *u = transaction->updates[i]; - struct object_id current_oid = {0}; - const char *rewritten_ref; - - /* - * There is no need to reload the respective backends here as - * we have already reloaded them when preparing the transaction - * update. And given that the stacks have been locked there - * shouldn't have been any concurrent modifications of the - * stack. - */ - ret = backend_for(&be, refs, u->refname, &rewritten_ref, 0); - if (ret) - goto done; - - /* Verify that the new object ID is valid. */ - if ((u->flags & REF_HAVE_NEW) && !is_null_oid(&u->new_oid) && - !(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, NULL, NULL, NULL, - u->msg); - string_list_insert(&affected_refnames, new_update->refname); - } - - ret = reftable_backend_read_ref(be, rewritten_ref, - ¤t_oid, &referent, &u->type); - if (ret < 0) - goto done; - if (ret > 0 && !ref_update_expects_existing_old_ref(u)) { - /* - * 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, - transaction->flags & REF_TRANSACTION_FLAG_INITIAL, - 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) && !ref_update_has_null_new_value(u)) { - 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'"), - ref_update_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_target ? NULL : &u->new_oid, - u->old_target ? NULL : &u->old_oid, - u->new_target, u->old_target, - u->committer_info, 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->old_target) { - if (!(u->type & REF_ISSYMREF)) { - strbuf_addf(err, _("cannot lock ref '%s': " - "expected symref with target '%s': " - "but is a regular ref"), - ref_update_original_update_refname(u), - u->old_target); - ret = -1; - goto done; - } + ret = prepare_single_update(refs, tx_data, transaction, be, + transaction->updates[i], i, + &refnames_to_check, head_type, + &head_referent, &referent, err); + if (ret) { + if (ref_transaction_maybe_set_rejected(transaction, i, ret)) { + strbuf_reset(err); + ret = 0; - if (ref_update_check_old_target(referent.buf, u, err)) { - ret = -1; - goto done; - } - } else if ((u->flags & REF_HAVE_OLD) && !oideq(¤t_oid, &u->old_oid)) { - ret = TRANSACTION_NAME_CONFLICT; - if (is_null_oid(&u->old_oid)) { - strbuf_addf(err, _("cannot lock ref '%s': " - "reference already exists"), - ref_update_original_update_refname(u)); - ret = TRANSACTION_CREATE_EXISTS; + continue; } - else if (is_null_oid(¤t_oid)) - strbuf_addf(err, _("cannot lock ref '%s': " - "reference is missing but expected %s"), - ref_update_original_update_refname(u), - oid_to_hex(&u->old_oid)); - else - strbuf_addf(err, _("cannot lock ref '%s': " - "is at %s but expected %s"), - ref_update_original_update_refname(u), - oid_to_hex(¤t_oid), - oid_to_hex(&u->old_oid)); 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; - } } + ret = refs_verify_refnames_available(ref_store, &refnames_to_check, + &transaction->refnames, NULL, + transaction, + transaction->flags & REF_TRANSACTION_FLAG_INITIAL, + err); + if (ret < 0) + 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; @@ -1391,9 +1405,9 @@ done: strbuf_addf(err, _("reftable: transaction prepare: %s"), reftable_error_str(ret)); } - string_list_clear(&affected_refnames, 0); strbuf_release(&referent); strbuf_release(&head_referent); + string_list_clear(&refnames_to_check, 1); return ret; } @@ -1452,6 +1466,9 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data struct reftable_transaction_update *tx_update = &arg->updates[i]; struct ref_update *u = tx_update->update; + if (u->rejection_err) + continue; + /* * Write a reflog entry when updating a ref to point to * something new in either of the following cases: @@ -2017,20 +2034,20 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator) break; } - if (iter->err > 0) { - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - return ITER_ERROR; + if (iter->err > 0) return ITER_DONE; - } - - if (iter->err < 0) { - ref_iterator_abort(ref_iterator); + if (iter->err < 0) return ITER_ERROR; - } - return ITER_OK; } +static int reftable_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED, + const char *prefix UNUSED) +{ + BUG("reftable reflog iterator cannot be seeked"); + return -1; +} + static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED, struct object_id *peeled UNUSED) { @@ -2038,21 +2055,20 @@ static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSE return -1; } -static int reftable_reflog_iterator_abort(struct ref_iterator *ref_iterator) +static void reftable_reflog_iterator_release(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, + .seek = reftable_reflog_iterator_seek, .peel = reftable_reflog_iterator_peel, - .abort = reftable_reflog_iterator_abort + .release = reftable_reflog_iterator_release, }; static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs, @@ -153,18 +153,22 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet return 1; } -int refspec_item_init(struct refspec_item *item, const char *refspec, int fetch) +static int refspec_item_init(struct refspec_item *item, const char *refspec, + int fetch) { memset(item, 0, sizeof(*item)); item->raw = xstrdup(refspec); return parse_refspec(item, refspec, fetch); } -void refspec_item_init_or_die(struct refspec_item *item, const char *refspec, - int fetch) +int refspec_item_init_fetch(struct refspec_item *item, const char *refspec) { - if (!refspec_item_init(item, refspec, fetch)) - die(_("invalid refspec '%s'"), refspec); + return refspec_item_init(item, refspec, 1); +} + +int refspec_item_init_push(struct refspec_item *item, const char *refspec) +{ + return refspec_item_init(item, refspec, 0); } void refspec_item_clear(struct refspec_item *item) @@ -178,17 +182,29 @@ void refspec_item_clear(struct refspec_item *item) item->exact_sha1 = 0; } -void refspec_init(struct refspec *rs, int fetch) +void refspec_init_fetch(struct refspec *rs) +{ + struct refspec blank = REFSPEC_INIT_FETCH; + memcpy(rs, &blank, sizeof(*rs)); +} + +void refspec_init_push(struct refspec *rs) { - memset(rs, 0, sizeof(*rs)); - rs->fetch = fetch; + struct refspec blank = REFSPEC_INIT_PUSH; + memcpy(rs, &blank, sizeof(*rs)); } void refspec_append(struct refspec *rs, const char *refspec) { struct refspec_item item; + int ret; - refspec_item_init_or_die(&item, refspec, rs->fetch); + if (rs->fetch) + ret = refspec_item_init_fetch(&item, refspec); + else + ret = refspec_item_init_push(&item, refspec); + if (!ret) + die(_("invalid refspec '%s'"), refspec); ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc); rs->items[rs->nr] = item; @@ -233,7 +249,7 @@ void refspec_clear(struct refspec *rs) int valid_fetch_refspec(const char *fetch_refspec_str) { struct refspec_item refspec; - int ret = refspec_item_init(&refspec, fetch_refspec_str, REFSPEC_FETCH); + int ret = refspec_item_init_fetch(&refspec, fetch_refspec_str); refspec_item_clear(&refspec); return ret; } @@ -246,14 +262,24 @@ void refspec_ref_prefixes(const struct refspec *rs, const struct refspec_item *item = &rs->items[i]; const char *prefix = NULL; - if (item->exact_sha1 || item->negative) + if (item->negative) continue; - if (rs->fetch == REFSPEC_FETCH) - prefix = item->src; - else if (item->dst) - prefix = item->dst; - else if (item->src && !item->exact_sha1) + + if (rs->fetch) { + if (item->exact_sha1) + continue; prefix = item->src; + } else { + /* + * Pushes can have an explicit destination like + * "foo:bar", or can implicitly use the src for both + * ("foo" is the same as "foo:foo"). + */ + if (item->dst) + prefix = item->dst; + else if (item->src && !item->exact_sha1) + prefix = item->src; + } if (!prefix) continue; @@ -32,11 +32,8 @@ struct refspec_item { struct string_list; -#define REFSPEC_FETCH 1 -#define REFSPEC_PUSH 0 - -#define REFSPEC_INIT_FETCH { .fetch = REFSPEC_FETCH } -#define REFSPEC_INIT_PUSH { .fetch = REFSPEC_PUSH } +#define REFSPEC_INIT_FETCH { .fetch = 1 } +#define REFSPEC_INIT_PUSH { .fetch = 0 } /** * An array of strings can be parsed into a struct refspec using @@ -47,15 +44,14 @@ struct refspec { int alloc; int nr; - int fetch; + unsigned fetch : 1; }; -int refspec_item_init(struct refspec_item *item, const char *refspec, - int fetch); -void refspec_item_init_or_die(struct refspec_item *item, const char *refspec, - int fetch); +int refspec_item_init_fetch(struct refspec_item *item, const char *refspec); +int refspec_item_init_push(struct refspec_item *item, const char *refspec); void refspec_item_clear(struct refspec_item *item); -void refspec_init(struct refspec *rs, int fetch); +void refspec_init_fetch(struct refspec *rs); +void refspec_init_push(struct refspec *rs); void refspec_append(struct refspec *rs, const char *refspec); __attribute__((format (printf,2,3))) void refspec_appendf(struct refspec *rs, const char *fmt, ...); diff --git a/reftable/basics.c b/reftable/basics.c index 3b5ea27bbd..9988ebd635 100644 --- a/reftable/basics.c +++ b/reftable/basics.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #define REFTABLE_ALLOW_BANNED_ALLOCATORS #include "basics.h" @@ -147,25 +147,6 @@ char *reftable_buf_detach(struct reftable_buf *buf) return result; } -void put_be24(uint8_t *out, uint32_t i) -{ - out[0] = (uint8_t)((i >> 16) & 0xff); - out[1] = (uint8_t)((i >> 8) & 0xff); - out[2] = (uint8_t)(i & 0xff); -} - -uint32_t get_be24(uint8_t *in) -{ - return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 | - (uint32_t)(in[2]); -} - -void put_be16(uint8_t *out, uint16_t i) -{ - out[0] = (uint8_t)((i >> 8) & 0xff); - out[1] = (uint8_t)(i & 0xff); -} - size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args) { size_t lo = 0; diff --git a/reftable/basics.h b/reftable/basics.h index a2a010a0e1..7d22f96261 100644 --- a/reftable/basics.h +++ b/reftable/basics.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef BASICS_H #define BASICS_H @@ -16,12 +16,11 @@ https://developers.google.com/open-source/licenses/bsd #include "system.h" #include "reftable-basics.h" -struct reftable_buf { - size_t alloc; - size_t len; - char *buf; -}; -#define REFTABLE_BUF_INIT { 0 } +#ifdef __GNUC__ +#define REFTABLE_UNUSED __attribute__((__unused__)) +#else +#define REFTABLE_UNUSED +#endif /* * Initialize the buffer such that it is ready for use. This is equivalent to @@ -76,9 +75,79 @@ char *reftable_buf_detach(struct reftable_buf *buf); /* Bigendian en/decoding of integers */ -void put_be24(uint8_t *out, uint32_t i); -uint32_t get_be24(uint8_t *in); -void put_be16(uint8_t *out, uint16_t i); +static inline void reftable_put_be16(void *out, uint16_t i) +{ + unsigned char *p = out; + p[0] = (uint8_t)((i >> 8) & 0xff); + p[1] = (uint8_t)((i >> 0) & 0xff); +} + +static inline void reftable_put_be24(void *out, uint32_t i) +{ + unsigned char *p = out; + p[0] = (uint8_t)((i >> 16) & 0xff); + p[1] = (uint8_t)((i >> 8) & 0xff); + p[2] = (uint8_t)((i >> 0) & 0xff); +} + +static inline void reftable_put_be32(void *out, uint32_t i) +{ + unsigned char *p = out; + p[0] = (uint8_t)((i >> 24) & 0xff); + p[1] = (uint8_t)((i >> 16) & 0xff); + p[2] = (uint8_t)((i >> 8) & 0xff); + p[3] = (uint8_t)((i >> 0) & 0xff); +} + +static inline void reftable_put_be64(void *out, uint64_t i) +{ + unsigned char *p = out; + p[0] = (uint8_t)((i >> 56) & 0xff); + p[1] = (uint8_t)((i >> 48) & 0xff); + p[2] = (uint8_t)((i >> 40) & 0xff); + p[3] = (uint8_t)((i >> 32) & 0xff); + p[4] = (uint8_t)((i >> 24) & 0xff); + p[5] = (uint8_t)((i >> 16) & 0xff); + p[6] = (uint8_t)((i >> 8) & 0xff); + p[7] = (uint8_t)((i >> 0) & 0xff); +} + +static inline uint16_t reftable_get_be16(const void *in) +{ + const unsigned char *p = in; + return (uint16_t)(p[0]) << 8 | + (uint16_t)(p[1]) << 0; +} + +static inline uint32_t reftable_get_be24(const void *in) +{ + const unsigned char *p = in; + return (uint32_t)(p[0]) << 16 | + (uint32_t)(p[1]) << 8 | + (uint32_t)(p[2]) << 0; +} + +static inline uint32_t reftable_get_be32(const void *in) +{ + const unsigned char *p = in; + return (uint32_t)(p[0]) << 24 | + (uint32_t)(p[1]) << 16 | + (uint32_t)(p[2]) << 8| + (uint32_t)(p[3]) << 0; +} + +static inline uint64_t reftable_get_be64(const void *in) +{ + const unsigned char *p = in; + return (uint64_t)(p[0]) << 56 | + (uint64_t)(p[1]) << 48 | + (uint64_t)(p[2]) << 40 | + (uint64_t)(p[3]) << 32 | + (uint64_t)(p[4]) << 24 | + (uint64_t)(p[5]) << 16 | + (uint64_t)(p[6]) << 8 | + (uint64_t)(p[7]) << 0; +} /* * find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is @@ -117,18 +186,46 @@ void reftable_free(void *p); void *reftable_calloc(size_t nelem, size_t elsize); char *reftable_strdup(const char *str); -#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc))) +static inline int reftable_alloc_size(size_t nelem, size_t elsize, size_t *out) +{ + if (nelem && elsize > SIZE_MAX / nelem) + return -1; + *out = nelem * elsize; + return 0; +} + +#define REFTABLE_ALLOC_ARRAY(x, alloc) do { \ + size_t alloc_size; \ + if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \ + errno = ENOMEM; \ + (x) = NULL; \ + } else { \ + (x) = reftable_malloc(alloc_size); \ + } \ + } while (0) #define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x))) -#define REFTABLE_REALLOC_ARRAY(x, alloc) (x) = reftable_realloc((x), st_mult(sizeof(*(x)), (alloc))) +#define REFTABLE_REALLOC_ARRAY(x, alloc) do { \ + size_t alloc_size; \ + if (reftable_alloc_size(sizeof(*(x)), (alloc), &alloc_size) < 0) { \ + errno = ENOMEM; \ + (x) = NULL; \ + } else { \ + (x) = reftable_realloc((x), alloc_size); \ + } \ + } while (0) static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize, size_t *allocp) { void *new_p; - size_t alloc = *allocp * 2 + 1; + size_t alloc = *allocp * 2 + 1, alloc_bytes; if (alloc < nelem) alloc = nelem; - new_p = reftable_realloc(p, st_mult(elsize, alloc)); + if (reftable_alloc_size(elsize, alloc, &alloc_bytes) < 0) { + errno = ENOMEM; + return p; + } + new_p = reftable_realloc(p, alloc_bytes); if (!new_p) return p; *allocp = alloc; @@ -168,6 +265,15 @@ static inline void *reftable_alloc_grow(void *p, size_t nelem, size_t elsize, # define strdup(str) REFTABLE_BANNED(strdup) #endif +#define REFTABLE_SWAP(a, b) do { \ + void *_swap_a_ptr = &(a); \ + void *_swap_b_ptr = &(b); \ + unsigned char _swap_buffer[sizeof(a) - 2 * sizeof(a) * (sizeof(a) != sizeof(b))]; \ + memcpy(_swap_buffer, _swap_a_ptr, sizeof(a)); \ + memcpy(_swap_a_ptr, _swap_b_ptr, sizeof(a)); \ + memcpy(_swap_b_ptr, _swap_buffer, sizeof(a)); \ +} while (0) + /* Find the longest shared prefix size of `a` and `b` */ size_t common_prefix_size(struct reftable_buf *a, struct reftable_buf *b); diff --git a/reftable/block.c b/reftable/block.c index b14a8f1259..920b3f4486 100644 --- a/reftable/block.c +++ b/reftable/block.c @@ -1,15 +1,16 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "block.h" #include "blocksource.h" #include "constants.h" +#include "iter.h" #include "record.h" #include "reftable-error.h" #include "system.h" @@ -49,7 +50,7 @@ static int block_writer_register_restart(struct block_writer *w, int n, if (is_restart) rlen++; if (2 + 3 * rlen + n > w->block_size - w->next) - return -1; + return REFTABLE_ENTRY_TOO_BIG_ERROR; if (is_restart) { REFTABLE_ALLOC_GROW_OR_NULL(w->restarts, w->restart_len + 1, w->restart_cap); @@ -97,9 +98,10 @@ uint8_t block_writer_type(struct block_writer *bw) return bw->block[bw->header_off]; } -/* Adds the reftable_record to the block. Returns -1 if it does not fit, 0 on - success. Returns REFTABLE_API_ERROR if attempting to write a record with - empty key. */ +/* + * Adds the reftable_record to the block. Returns 0 on success and + * appropriate error codes on failure. + */ int block_writer_add(struct block_writer *w, struct reftable_record *rec) { struct reftable_buf empty = REFTABLE_BUF_INIT; @@ -126,14 +128,14 @@ int block_writer_add(struct block_writer *w, struct reftable_record *rec) n = reftable_encode_key(&is_restart, out, last, w->scratch, reftable_record_val_type(rec)); if (n < 0) { - err = -1; + err = n; goto done; } string_view_consume(&out, n); n = reftable_record_encode(rec, out, w->hash_size); if (n < 0) { - err = -1; + err = n; goto done; } string_view_consume(&out, n); @@ -147,19 +149,19 @@ done: int block_writer_finish(struct block_writer *w) { for (uint32_t i = 0; i < w->restart_len; i++) { - put_be24(w->block + w->next, w->restarts[i]); + reftable_put_be24(w->block + w->next, w->restarts[i]); w->next += 3; } - put_be16(w->block + w->next, w->restart_len); + reftable_put_be16(w->block + w->next, w->restart_len); w->next += 2; - put_be24(w->block + 1 + w->header_off, w->next); + reftable_put_be24(w->block + 1 + w->header_off, w->next); /* * Log records are stored zlib-compressed. Note that the compression * also spans over the restart points we have just written. */ - if (block_writer_type(w) == BLOCK_TYPE_LOG) { + if (block_writer_type(w) == REFTABLE_BLOCK_TYPE_LOG) { int block_header_skip = 4 + w->header_off; uLongf src_len = w->next - block_header_skip, compressed_len; int ret; @@ -209,61 +211,91 @@ int block_writer_finish(struct block_writer *w) return w->next; } -int block_reader_init(struct block_reader *br, struct reftable_block *block, - uint32_t header_off, uint32_t table_block_size, - uint32_t hash_size) +static int read_block(struct reftable_block_source *source, + struct reftable_block_data *dest, uint64_t off, + uint32_t sz) { + size_t size = block_source_size(source); + block_source_release_data(dest); + if (off >= size) + return 0; + if (off + sz > size) + sz = size - off; + return block_source_read_data(source, dest, off, sz); +} + +int reftable_block_init(struct reftable_block *block, + struct reftable_block_source *source, + uint32_t offset, uint32_t header_size, + uint32_t table_block_size, uint32_t hash_size, + uint8_t want_type) +{ + uint32_t guess_block_size = table_block_size ? + table_block_size : DEFAULT_BLOCK_SIZE; uint32_t full_block_size = table_block_size; - uint8_t typ = block->data[header_off]; - uint32_t sz = get_be24(block->data + header_off + 1); - int err = 0; - uint16_t restart_count = 0; - uint32_t restart_start = 0; - uint8_t *restart_bytes = NULL; + uint16_t restart_count; + uint32_t restart_off; + uint32_t block_size; + uint8_t block_type; + int err; - reftable_block_done(&br->block); + err = read_block(source, &block->block_data, offset, guess_block_size); + if (err < 0) + goto done; - if (!reftable_is_block_type(typ)) { - err = REFTABLE_FORMAT_ERROR; + block_type = block->block_data.data[header_size]; + if (!reftable_is_block_type(block_type)) { + err = REFTABLE_FORMAT_ERROR; + goto done; + } + if (want_type != REFTABLE_BLOCK_TYPE_ANY && block_type != want_type) { + err = 1; goto done; } - if (typ == BLOCK_TYPE_LOG) { - uint32_t block_header_skip = 4 + header_off; - uLong dst_len = sz - block_header_skip; - uLong src_len = block->len - block_header_skip; + block_size = reftable_get_be24(block->block_data.data + header_size + 1); + if (block_size > guess_block_size) { + err = read_block(source, &block->block_data, offset, block_size); + if (err < 0) + goto done; + } + + if (block_type == REFTABLE_BLOCK_TYPE_LOG) { + uint32_t block_header_skip = 4 + header_size; + uLong dst_len = block_size - block_header_skip; + uLong src_len = block->block_data.len - block_header_skip; /* Log blocks specify the *uncompressed* size in their header. */ - REFTABLE_ALLOC_GROW_OR_NULL(br->uncompressed_data, sz, - br->uncompressed_cap); - if (!br->uncompressed_data) { + REFTABLE_ALLOC_GROW_OR_NULL(block->uncompressed_data, block_size, + block->uncompressed_cap); + if (!block->uncompressed_data) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } /* Copy over the block header verbatim. It's not compressed. */ - memcpy(br->uncompressed_data, block->data, block_header_skip); + memcpy(block->uncompressed_data, block->block_data.data, block_header_skip); - if (!br->zstream) { - REFTABLE_CALLOC_ARRAY(br->zstream, 1); - if (!br->zstream) { + if (!block->zstream) { + REFTABLE_CALLOC_ARRAY(block->zstream, 1); + if (!block->zstream) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - err = inflateInit(br->zstream); + err = inflateInit(block->zstream); } else { - err = inflateReset(br->zstream); + err = inflateReset(block->zstream); } if (err != Z_OK) { err = REFTABLE_ZLIB_ERROR; goto done; } - 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; + block->zstream->next_in = block->block_data.data + block_header_skip; + block->zstream->avail_in = src_len; + block->zstream->next_out = block->uncompressed_data + block_header_skip; + block->zstream->avail_out = dst_len; /* * We know both input as well as output size, and we know that @@ -272,72 +304,71 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block, * 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); + err = inflate(block->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) { + if (block->zstream->total_out + block_header_skip != block_size) { err = REFTABLE_FORMAT_ERROR; goto done; } /* We're done with the input data. */ - reftable_block_done(block); - block->data = br->uncompressed_data; - block->len = sz; - full_block_size = src_len + block_header_skip - br->zstream->avail_in; + block_source_release_data(&block->block_data); + block->block_data.data = block->uncompressed_data; + block->block_data.len = block_size; + full_block_size = src_len + block_header_skip - block->zstream->avail_in; } else if (full_block_size == 0) { - full_block_size = sz; - } else if (sz < full_block_size && sz < block->len && - block->data[sz] != 0) { + full_block_size = block_size; + } else if (block_size < full_block_size && block_size < block->block_data.len && + block->block_data.data[block_size] != 0) { /* If the block is smaller than the full block size, it is padded (data followed by '\0') or the next block is unaligned. */ - full_block_size = sz; + full_block_size = block_size; } - restart_count = get_be16(block->data + sz - 2); - restart_start = sz - 2 - 3 * restart_count; - restart_bytes = block->data + restart_start; + restart_count = reftable_get_be16(block->block_data.data + block_size - 2); + restart_off = block_size - 2 - 3 * restart_count; - /* transfer ownership. */ - br->block = *block; - block->data = NULL; - block->len = 0; + block->block_type = block_type; + block->hash_size = hash_size; + block->restart_off = restart_off; + block->full_block_size = full_block_size; + block->header_off = header_size; + block->restart_count = restart_count; - br->hash_size = hash_size; - br->block_len = restart_start; - br->full_block_size = full_block_size; - br->header_off = header_off; - br->restart_count = restart_count; - br->restart_bytes = restart_bytes; + err = 0; done: + if (err < 0) + reftable_block_release(block); return err; } -void block_reader_release(struct block_reader *br) +void reftable_block_release(struct reftable_block *block) { - inflateEnd(br->zstream); - reftable_free(br->zstream); - reftable_free(br->uncompressed_data); - reftable_block_done(&br->block); + inflateEnd(block->zstream); + reftable_free(block->zstream); + reftable_free(block->uncompressed_data); + block_source_release_data(&block->block_data); + memset(block, 0, sizeof(*block)); } -uint8_t block_reader_type(const struct block_reader *r) +uint8_t reftable_block_type(const struct reftable_block *b) { - return r->block.data[r->header_off]; + return b->block_data.data[b->header_off]; } -int block_reader_first_key(const struct block_reader *br, struct reftable_buf *key) +int reftable_block_first_key(const struct reftable_block *block, struct reftable_buf *key) { - int off = br->header_off + 4, n; + int off = block->header_off + 4, n; struct string_view in = { - .buf = br->block.data + off, - .len = br->block_len - off, + .buf = block->block_data.data + off, + .len = block->restart_off - off, }; uint8_t extra = 0; @@ -352,33 +383,36 @@ int block_reader_first_key(const struct block_reader *br, struct reftable_buf *k return 0; } -static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx) +static uint32_t block_restart_offset(const struct reftable_block *b, size_t idx) +{ + return reftable_get_be24(b->block_data.data + b->restart_off + 3 * idx); +} + +void block_iter_init(struct block_iter *it, const struct reftable_block *block) { - return get_be24(br->restart_bytes + 3 * idx); + it->block = block; + block_iter_seek_start(it); } -void block_iter_seek_start(struct block_iter *it, const struct block_reader *br) +void block_iter_seek_start(struct block_iter *it) { - it->block = br->block.data; - it->block_len = br->block_len; - it->hash_size = br->hash_size; reftable_buf_reset(&it->last_key); - it->next_off = br->header_off + 4; + it->next_off = it->block->header_off + 4; } struct restart_needle_less_args { int error; struct reftable_buf needle; - const struct block_reader *reader; + const struct reftable_block *block; }; static int restart_needle_less(size_t idx, void *_args) { struct restart_needle_less_args *args = _args; - uint32_t off = block_reader_restart_offset(args->reader, idx); + uint32_t off = block_restart_offset(args->block, idx); struct string_view in = { - .buf = args->reader->block.data + off, - .len = args->reader->block_len - off, + .buf = args->block->block_data.data + off, + .len = args->block->restart_off - off, }; uint64_t prefix_len, suffix_len; uint8_t extra; @@ -411,14 +445,14 @@ static int restart_needle_less(size_t idx, void *_args) int block_iter_next(struct block_iter *it, struct reftable_record *rec) { struct string_view in = { - .buf = (unsigned char *) it->block + it->next_off, - .len = it->block_len - it->next_off, + .buf = (unsigned char *) it->block->block_data.data + it->next_off, + .len = it->block->restart_off - it->next_off, }; struct string_view start = in; uint8_t extra = 0; int n = 0; - if (it->next_off >= it->block_len) + if (it->next_off >= it->block->restart_off) return 1; n = reftable_decode_key(&it->last_key, &extra, in); @@ -428,7 +462,7 @@ int block_iter_next(struct block_iter *it, struct reftable_record *rec) return REFTABLE_FORMAT_ERROR; string_view_consume(&in, n); - n = reftable_record_decode(rec, it->last_key, extra, in, it->hash_size, + n = reftable_record_decode(rec, it->last_key, extra, in, it->block->hash_size, &it->scratch); if (n < 0) return -1; @@ -443,8 +477,6 @@ void block_iter_reset(struct block_iter *it) reftable_buf_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) @@ -453,12 +485,11 @@ void block_iter_close(struct block_iter *it) reftable_buf_release(&it->scratch); } -int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, - struct reftable_buf *want) +int block_iter_seek_key(struct block_iter *it, struct reftable_buf *want) { struct restart_needle_less_args args = { .needle = *want, - .reader = br, + .block = it->block, }; struct reftable_record rec; int err = 0; @@ -476,7 +507,7 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, * restart point. While that works alright, we would end up scanning * too many record. */ - i = binsearch(br->restart_count, &restart_needle_less, &args); + i = binsearch(it->block->restart_count, &restart_needle_less, &args); if (args.error) { err = REFTABLE_FORMAT_ERROR; goto done; @@ -501,19 +532,18 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, * starting from the preceding restart point. */ if (i > 0) - it->next_off = block_reader_restart_offset(br, i - 1); + it->next_off = block_restart_offset(it->block, i - 1); else - it->next_off = br->header_off + 4; - it->block = br->block.data; - it->block_len = br->block_len; - it->hash_size = br->hash_size; + it->next_off = it->block->header_off + 4; - reftable_record_init(&rec, block_reader_type(br)); + err = reftable_record_init(&rec, reftable_block_type(it->block)); + if (err < 0) + goto done; /* * 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 + * record. We thus don't want to position our iterator at the sought * after record, but one before. To do so, we have to go one entry too * far and then back up. */ @@ -558,6 +588,61 @@ done: return err; } +static int block_iter_seek_void(void *it, struct reftable_record *want) +{ + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct block_iter *bi = it; + int err; + + if (bi->block->block_type != want->type) + return REFTABLE_API_ERROR; + + err = reftable_record_key(want, &buf); + if (err < 0) + goto out; + + err = block_iter_seek_key(it, &buf); + if (err < 0) + goto out; + + err = 0; + +out: + reftable_buf_release(&buf); + return err; +} + +static int block_iter_next_void(void *it, struct reftable_record *rec) +{ + return block_iter_next(it, rec); +} + +static void block_iter_close_void(void *it) +{ + block_iter_close(it); +} + +static struct reftable_iterator_vtable block_iter_vtable = { + .seek = &block_iter_seek_void, + .next = &block_iter_next_void, + .close = &block_iter_close_void, +}; + +int reftable_block_init_iterator(const struct reftable_block *b, + struct reftable_iterator *it) +{ + struct block_iter *bi; + + REFTABLE_CALLOC_ARRAY(bi, 1); + block_iter_init(bi, b); + + assert(!it->ops); + it->iter_arg = bi; + it->ops = &block_iter_vtable; + + return 0; +} + void block_writer_release(struct block_writer *bw) { deflateEnd(bw->zstream); @@ -568,14 +653,3 @@ void block_writer_release(struct block_writer *bw) reftable_buf_release(&bw->last_key); /* the block is not owned. */ } - -void reftable_block_done(struct reftable_block *blockp) -{ - struct reftable_block_source source = blockp->source; - if (blockp && source.ops) - source.ops->return_block(source.arg, blockp); - blockp->data = NULL; - blockp->len = 0; - blockp->source.ops = NULL; - blockp->source.arg = NULL; -} diff --git a/reftable/block.h b/reftable/block.h index bef2b8a4c5..d6dfaae33e 100644 --- a/reftable/block.h +++ b/reftable/block.h @@ -1,16 +1,17 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef BLOCK_H #define BLOCK_H #include "basics.h" #include "record.h" +#include "reftable-block.h" #include "reftable-blocksource.h" /* @@ -18,7 +19,7 @@ https://developers.google.com/open-source/licenses/bsd * allocation overhead. */ struct block_writer { - z_stream *zstream; + struct z_stream_s *zstream; unsigned char *compressed; size_t compressed_cap; @@ -53,7 +54,7 @@ int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *block, /* returns the block type (eg. 'r' for ref records. */ uint8_t block_writer_type(struct block_writer *bw); -/* appends the record, or -1 if it doesn't fit. */ +/* Attempts to append the record. Returns 0 on success or error code on failure. */ int block_writer_add(struct block_writer *w, struct reftable_record *rec); /* appends the key restarts, and compress the block if necessary. */ @@ -62,53 +63,11 @@ 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 - * reftable. */ - uint32_t header_off; - - /* the memory block */ - struct reftable_block block; - uint32_t 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; - uint16_t restart_count; - - /* size of the data in the file. For log blocks, this is the compressed - * size. */ - 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, - uint32_t 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 reftable_buf *key); - -/* Iterate over entries in a block */ +/* Iterator for records contained in a single block. */ struct block_iter { /* offset within the block of the next entry to read. */ uint32_t next_off; - const unsigned char *block; - size_t block_len; - uint32_t hash_size; + const struct reftable_block *block; /* key for last entry we read. */ struct reftable_buf last_key; @@ -120,12 +79,23 @@ struct block_iter { .scratch = REFTABLE_BUF_INIT, \ } -/* Position `it` at start of the block */ -void block_iter_seek_start(struct block_iter *it, const struct block_reader *br); +/* + * Initialize the block iterator with the given block. The iterator will be + * positioned at the first record contained in the block. The block must remain + * valid until the end of the iterator's lifetime. It is valid to re-initialize + * iterators multiple times. + */ +void block_iter_init(struct block_iter *it, const struct reftable_block *block); -/* Position `it` to the `want` key in the block */ -int block_iter_seek_key(struct block_iter *it, const struct block_reader *br, - struct reftable_buf *want); +/* Position the initialized iterator at the first record of its block. */ +void block_iter_seek_start(struct block_iter *it); + +/* + * Position the initialized iterator at the desired record key. It is not an + * error in case the record cannot be found. If so, a subsequent call to + * `block_iter_next()` will indicate that the iterator is exhausted. + */ +int block_iter_seek_key(struct block_iter *it, struct reftable_buf *want); /* return < 0 for error, 0 for OK, > 0 for EOF. */ int block_iter_next(struct block_iter *it, struct reftable_record *rec); @@ -142,7 +112,4 @@ size_t header_size(int version); /* size of file footer, depending on format version */ size_t footer_size(int version); -/* returns a block to its source. */ -void reftable_block_done(struct reftable_block *ret); - #endif diff --git a/reftable/blocksource.c b/reftable/blocksource.c index bba4a45b98..573c81287f 100644 --- a/reftable/blocksource.c +++ b/reftable/blocksource.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "system.h" @@ -13,19 +13,54 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable-blocksource.h" #include "reftable-error.h" -static void reftable_buf_return_block(void *b UNUSED, struct reftable_block *dest) +void block_source_release_data(struct reftable_block_data *data) +{ + struct reftable_block_source source = data->source; + if (data && source.ops) + source.ops->release_data(source.arg, data); + data->data = NULL; + data->len = 0; + data->source.ops = NULL; + data->source.arg = NULL; +} + +void block_source_close(struct reftable_block_source *source) +{ + if (!source->ops) { + return; + } + + source->ops->close(source->arg); + source->ops = NULL; +} + +ssize_t block_source_read_data(struct reftable_block_source *source, + struct reftable_block_data *dest, uint64_t off, + uint32_t size) +{ + ssize_t result = source->ops->read_data(source->arg, dest, off, size); + dest->source = *source; + return result; +} + +uint64_t block_source_size(struct reftable_block_source *source) +{ + return source->ops->size(source->arg); +} + +static void reftable_buf_release_data(void *b REFTABLE_UNUSED, struct reftable_block_data *dest) { if (dest->len) memset(dest->data, 0xff, dest->len); reftable_free(dest->data); } -static void reftable_buf_close(void *b UNUSED) +static void reftable_buf_close(void *b REFTABLE_UNUSED) { } -static ssize_t reftable_buf_read_block(void *v, struct reftable_block *dest, - uint64_t off, uint32_t size) +static ssize_t reftable_buf_read_data(void *v, struct reftable_block_data *dest, + uint64_t off, uint32_t size) { struct reftable_buf *b = v; assert(off + size <= b->len); @@ -44,8 +79,8 @@ static uint64_t reftable_buf_size(void *b) static struct reftable_block_source_vtable reftable_buf_vtable = { .size = &reftable_buf_size, - .read_block = &reftable_buf_read_block, - .return_block = &reftable_buf_return_block, + .read_data = &reftable_buf_read_data, + .release_data = &reftable_buf_release_data, .close = &reftable_buf_close, }; @@ -67,7 +102,7 @@ static uint64_t file_size(void *b) return ((struct file_block_source *)b)->size; } -static void file_return_block(void *b UNUSED, struct reftable_block *dest UNUSED) +static void file_release_data(void *b REFTABLE_UNUSED, struct reftable_block_data *dest REFTABLE_UNUSED) { } @@ -78,8 +113,8 @@ static void file_close(void *v) reftable_free(b); } -static ssize_t file_read_block(void *v, struct reftable_block *dest, uint64_t off, - uint32_t size) +static ssize_t file_read_data(void *v, struct reftable_block_data *dest, uint64_t off, + uint32_t size) { struct file_block_source *b = v; assert(off + size <= b->size); @@ -90,15 +125,15 @@ static ssize_t file_read_block(void *v, struct reftable_block *dest, uint64_t of static struct reftable_block_source_vtable file_vtable = { .size = &file_size, - .read_block = &file_read_block, - .return_block = &file_return_block, + .read_data = &file_read_data, + .release_data = &file_release_data, .close = &file_close, }; int reftable_block_source_from_file(struct reftable_block_source *bs, const char *name) { - struct file_block_source *p; + struct file_block_source *p = NULL; struct stat st; int fd, err; @@ -122,7 +157,12 @@ int reftable_block_source_from_file(struct reftable_block_source *bs, } p->size = st.st_size; - p->data = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + p->data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (p->data == MAP_FAILED) { + err = REFTABLE_IO_ERROR; + p->data = NULL; + goto out; + } assert(!bs->ops); bs->ops = &file_vtable; @@ -135,5 +175,5 @@ out: close(fd); if (err < 0) reftable_free(p); - return 0; + return err; } diff --git a/reftable/blocksource.h b/reftable/blocksource.h index a84a3ccd89..a110e05958 100644 --- a/reftable/blocksource.h +++ b/reftable/blocksource.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef BLOCKSOURCE_H #define BLOCKSOURCE_H @@ -12,9 +12,34 @@ https://developers.google.com/open-source/licenses/bsd #include "system.h" struct reftable_block_source; +struct reftable_block_data; struct reftable_buf; -/* Create an in-memory block source for reading reftables */ +/* + * Close the block source and the underlying resource. This is a no-op in case + * the block source is zero-initialized. + */ +void block_source_close(struct reftable_block_source *source); + +/* + * Read a block of length `size` from the source at the given `off`. + */ +ssize_t block_source_read_data(struct reftable_block_source *source, + struct reftable_block_data *dest, uint64_t off, + uint32_t size); + +/* + * Return the total length of the underlying resource. + */ +uint64_t block_source_size(struct reftable_block_source *source); + +/* + * Return a block to its original source, releasing any resources associated + * with it. + */ +void block_source_release_data(struct reftable_block_data *data); + +/* Create an in-memory block source for reading reftables. */ void block_source_from_buf(struct reftable_block_source *bs, struct reftable_buf *buf); diff --git a/reftable/constants.h b/reftable/constants.h index f6beb843eb..e3b1aaa516 100644 --- a/reftable/constants.h +++ b/reftable/constants.h @@ -1,19 +1,15 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef CONSTANTS_H #define CONSTANTS_H -#define BLOCK_TYPE_LOG 'g' -#define BLOCK_TYPE_INDEX 'i' -#define BLOCK_TYPE_REF 'r' -#define BLOCK_TYPE_OBJ 'o' -#define BLOCK_TYPE_ANY 0 +#include "reftable-constants.h" #define MAX_RESTARTS ((1 << 16) - 1) #define DEFAULT_BLOCK_SIZE 4096 diff --git a/reftable/error.c b/reftable/error.c index 660d029617..c7cab2dbc4 100644 --- a/reftable/error.c +++ b/reftable/error.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "system.h" #include "reftable-error.h" diff --git a/reftable/iter.c b/reftable/iter.c index 86e801ca9f..2ecc52b336 100644 --- a/reftable/iter.c +++ b/reftable/iter.c @@ -1,19 +1,20 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "iter.h" #include "system.h" #include "block.h" +#include "blocksource.h" #include "constants.h" -#include "reader.h" #include "reftable-error.h" +#include "table.h" int iterator_seek(struct reftable_iterator *it, struct reftable_record *want) { @@ -25,17 +26,17 @@ int iterator_next(struct reftable_iterator *it, struct reftable_record *rec) return it->ops->next(it->iter_arg, rec); } -static int empty_iterator_seek(void *arg UNUSED, struct reftable_record *want UNUSED) +static int empty_iterator_seek(void *arg REFTABLE_UNUSED, struct reftable_record *want REFTABLE_UNUSED) { return 0; } -static int empty_iterator_next(void *arg UNUSED, struct reftable_record *rec UNUSED) +static int empty_iterator_next(void *arg REFTABLE_UNUSED, struct reftable_record *rec REFTABLE_UNUSED) { return 1; } -static void empty_iterator_close(void *arg UNUSED) +static void empty_iterator_close(void *arg REFTABLE_UNUSED) { } @@ -113,7 +114,7 @@ static void indexed_table_ref_iter_close(void *p) { struct indexed_table_ref_iter *it = p; block_iter_close(&it->cur); - reftable_block_done(&it->block_reader.block); + block_source_release_data(&it->block.block_data); reftable_free(it->offsets); reftable_buf_release(&it->oid); } @@ -127,11 +128,10 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) return 1; } - reftable_block_done(&it->block_reader.block); + block_source_release_data(&it->block.block_data); off = it->offsets[it->offset_idx++]; - err = reader_init_block_reader(it->r, &it->block_reader, off, - BLOCK_TYPE_REF); + err = table_init_block(it->table, &it->block, off, REFTABLE_BLOCK_TYPE_REF); if (err < 0) { return err; } @@ -139,15 +139,14 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it) /* indexed block does not exist. */ return REFTABLE_FORMAT_ERROR; } - block_iter_seek_start(&it->cur, &it->block_reader); + block_iter_init(&it->cur, &it->block); return 0; } -static int indexed_table_ref_iter_seek(void *p UNUSED, - struct reftable_record *want UNUSED) +static int indexed_table_ref_iter_seek(void *p REFTABLE_UNUSED, + struct reftable_record *want REFTABLE_UNUSED) { - BUG("seeking indexed table is not supported"); - return -1; + return REFTABLE_API_ERROR; } static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec) @@ -182,7 +181,7 @@ static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec) } int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, - struct reftable_reader *r, uint8_t *oid, + struct reftable_table *t, uint8_t *oid, int oid_len, uint64_t *offsets, int offset_len) { struct indexed_table_ref_iter empty = INDEXED_TABLE_REF_ITER_INIT; @@ -196,7 +195,7 @@ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, } *itr = empty; - itr->r = r; + itr->table = t; err = reftable_buf_add(&itr->oid, oid, oid_len); if (err < 0) @@ -247,7 +246,7 @@ int reftable_iterator_seek_ref(struct reftable_iterator *it, const char *name) { struct reftable_record want = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref = { .refname = (char *)name, }, @@ -259,7 +258,7 @@ int reftable_iterator_next_ref(struct reftable_iterator *it, struct reftable_ref_record *ref) { struct reftable_record rec = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u = { .ref = *ref }, @@ -273,7 +272,7 @@ int reftable_iterator_seek_log_at(struct reftable_iterator *it, const char *name, uint64_t update_index) { struct reftable_record want = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log = { .refname = (char *)name, .update_index = update_index, @@ -292,7 +291,7 @@ int reftable_iterator_next_log(struct reftable_iterator *it, struct reftable_log_record *log) { struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u = { .log = *log, }, diff --git a/reftable/iter.h b/reftable/iter.h index 40f98893b8..cc920970a5 100644 --- a/reftable/iter.h +++ b/reftable/iter.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef ITER_H #define ITER_H @@ -59,7 +59,7 @@ void iterator_from_filtering_ref_iterator(struct reftable_iterator *, * but using the object index. */ struct indexed_table_ref_iter { - struct reftable_reader *r; + struct reftable_table *table; struct reftable_buf oid; /* mutable */ @@ -68,7 +68,7 @@ struct indexed_table_ref_iter { /* Points to the next offset to read. */ int offset_idx; int offset_len; - struct block_reader block_reader; + struct reftable_block block; struct block_iter cur; int is_finished; }; @@ -83,7 +83,7 @@ void iterator_from_indexed_table_ref_iter(struct reftable_iterator *it, /* Takes ownership of `offsets` */ int indexed_table_ref_iter_new(struct indexed_table_ref_iter **dest, - struct reftable_reader *r, uint8_t *oid, + struct reftable_table *t, uint8_t *oid, int oid_len, uint64_t *offsets, int offset_len); #endif diff --git a/reftable/merged.c b/reftable/merged.c index e72b39e178..733de07454 100644 --- a/reftable/merged.c +++ b/reftable/merged.c @@ -1,21 +1,21 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "merged.h" #include "constants.h" #include "iter.h" #include "pq.h" -#include "reader.h" #include "record.h" #include "reftable-merged.h" #include "reftable-error.h" #include "system.h" +#include "table.h" struct merged_subiter { struct reftable_iterator iter; @@ -66,8 +66,11 @@ static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want int err; mi->advance_index = -1; - while (!merged_iter_pqueue_is_empty(mi->pq)) - merged_iter_pqueue_remove(&mi->pq); + while (!merged_iter_pqueue_is_empty(mi->pq)) { + err = merged_iter_pqueue_remove(&mi->pq, NULL); + if (err < 0) + return err; + } for (size_t i = 0; i < mi->subiters_len; i++) { err = iterator_seek(&mi->subiters[i].iter, want); @@ -120,7 +123,9 @@ static int merged_iter_next_entry(struct merged_iter *mi, if (empty) return 1; - entry = merged_iter_pqueue_remove(&mi->pq); + err = merged_iter_pqueue_remove(&mi->pq, &entry); + if (err < 0) + return err; /* One can also use reftable as datacenter-local storage, where the ref @@ -134,18 +139,23 @@ static int merged_iter_next_entry(struct merged_iter *mi, struct pq_entry top = merged_iter_pqueue_top(mi->pq); int cmp; - cmp = reftable_record_cmp(top.rec, entry.rec); + err = reftable_record_cmp(top.rec, entry.rec, &cmp); + if (err < 0) + return err; if (cmp > 0) break; - merged_iter_pqueue_remove(&mi->pq); + err = merged_iter_pqueue_remove(&mi->pq, NULL); + if (err < 0) + return err; + err = merged_iter_advance_subiter(mi, top.index); if (err < 0) return err; } mi->advance_index = entry.index; - SWAP(*rec, *entry.rec); + REFTABLE_SWAP(*rec, *entry.rec); return 0; } @@ -182,7 +192,7 @@ static void iterator_from_merged_iter(struct reftable_iterator *it, } int reftable_merged_table_new(struct reftable_merged_table **dest, - struct reftable_reader **readers, size_t n, + struct reftable_table **tables, size_t n, enum reftable_hash hash_id) { struct reftable_merged_table *m = NULL; @@ -190,10 +200,10 @@ int reftable_merged_table_new(struct reftable_merged_table **dest, uint64_t first_min = 0; for (size_t i = 0; i < n; i++) { - uint64_t min = reftable_reader_min_update_index(readers[i]); - uint64_t max = reftable_reader_max_update_index(readers[i]); + uint64_t min = reftable_table_min_update_index(tables[i]); + uint64_t max = reftable_table_max_update_index(tables[i]); - if (reftable_reader_hash_id(readers[i]) != hash_id) { + if (reftable_table_hash_id(tables[i]) != hash_id) { return REFTABLE_FORMAT_ERROR; } if (i == 0 || min < first_min) { @@ -208,8 +218,8 @@ int reftable_merged_table_new(struct reftable_merged_table **dest, if (!m) return REFTABLE_OUT_OF_MEMORY_ERROR; - m->readers = readers; - m->readers_len = n; + m->tables = tables; + m->tables_len = n; m->min = first_min; m->max = last_max; m->hash_id = hash_id; @@ -244,17 +254,20 @@ int merged_table_init_iter(struct reftable_merged_table *mt, struct merged_iter *mi = NULL; int ret; - if (mt->readers_len) { - REFTABLE_CALLOC_ARRAY(subiters, mt->readers_len); + if (mt->tables_len) { + REFTABLE_CALLOC_ARRAY(subiters, mt->tables_len); if (!subiters) { ret = REFTABLE_OUT_OF_MEMORY_ERROR; goto out; } } - for (size_t i = 0; i < mt->readers_len; i++) { - reftable_record_init(&subiters[i].rec, typ); - ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ); + for (size_t i = 0; i < mt->tables_len; i++) { + ret = reftable_record_init(&subiters[i].rec, typ); + if (ret < 0) + goto out; + + ret = table_init_iter(mt->tables[i], &subiters[i].iter, typ); if (ret < 0) goto out; } @@ -267,14 +280,14 @@ int merged_table_init_iter(struct reftable_merged_table *mt, mi->advance_index = -1; mi->suppress_deletions = mt->suppress_deletions; mi->subiters = subiters; - mi->subiters_len = mt->readers_len; + mi->subiters_len = mt->tables_len; iterator_from_merged_iter(it, mi); ret = 0; out: if (ret < 0) { - for (size_t i = 0; subiters && i < mt->readers_len; i++) { + for (size_t i = 0; subiters && i < mt->tables_len; i++) { reftable_iterator_destroy(&subiters[i].iter); reftable_record_release(&subiters[i].rec); } @@ -288,13 +301,13 @@ out: int reftable_merged_table_init_ref_iterator(struct reftable_merged_table *mt, struct reftable_iterator *it) { - return merged_table_init_iter(mt, it, BLOCK_TYPE_REF); + return merged_table_init_iter(mt, it, REFTABLE_BLOCK_TYPE_REF); } int reftable_merged_table_init_log_iterator(struct reftable_merged_table *mt, struct reftable_iterator *it) { - return merged_table_init_iter(mt, it, BLOCK_TYPE_LOG); + return merged_table_init_iter(mt, it, REFTABLE_BLOCK_TYPE_LOG); } enum reftable_hash reftable_merged_table_hash_id(struct reftable_merged_table *mt) diff --git a/reftable/merged.h b/reftable/merged.h index 0b7d939e92..4317e5f5f6 100644 --- a/reftable/merged.h +++ b/reftable/merged.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef MERGED_H #define MERGED_H @@ -13,8 +13,8 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable-basics.h" struct reftable_merged_table { - struct reftable_reader **readers; - size_t readers_len; + struct reftable_table **tables; + size_t tables_len; enum reftable_hash hash_id; /* If unset, produce deletions. This is useful for compaction. For the diff --git a/reftable/pq.c b/reftable/pq.c index 5591e875e1..9a79f5c5ee 100644 --- a/reftable/pq.c +++ b/reftable/pq.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "pq.h" @@ -15,13 +15,18 @@ https://developers.google.com/open-source/licenses/bsd int pq_less(struct pq_entry *a, struct pq_entry *b) { - int cmp = reftable_record_cmp(a->rec, b->rec); + int cmp, err; + + err = reftable_record_cmp(a->rec, b->rec, &cmp); + if (err < 0) + return err; + if (cmp == 0) return a->index > b->index; return cmp < 0; } -struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq) +int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out) { size_t i = 0; struct pq_entry e = pq->heap[0]; @@ -32,17 +37,34 @@ struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq) size_t min = i; size_t j = 2 * i + 1; size_t k = 2 * i + 2; - if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i])) - min = j; - if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min])) - min = k; + int cmp; + + if (j < pq->len) { + cmp = pq_less(&pq->heap[j], &pq->heap[i]); + if (cmp < 0) + return -1; + else if (cmp) + min = j; + } + + if (k < pq->len) { + cmp = pq_less(&pq->heap[k], &pq->heap[min]); + if (cmp < 0) + return -1; + else if (cmp) + min = k; + } + if (min == i) break; - SWAP(pq->heap[i], pq->heap[min]); + REFTABLE_SWAP(pq->heap[i], pq->heap[min]); i = min; } - return e; + if (out) + *out = e; + + return 0; } int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e) @@ -59,7 +81,7 @@ int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry size_t j = (i - 1) / 2; if (pq_less(&pq->heap[j], &pq->heap[i])) break; - SWAP(pq->heap[j], pq->heap[i]); + REFTABLE_SWAP(pq->heap[j], pq->heap[i]); i = j; } diff --git a/reftable/pq.h b/reftable/pq.h index 83c062eeca..42310670b0 100644 --- a/reftable/pq.h +++ b/reftable/pq.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef PQ_H #define PQ_H @@ -22,7 +22,7 @@ struct merged_iter_pqueue { size_t cap; }; -struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq); +int merged_iter_pqueue_remove(struct merged_iter_pqueue *pq, struct pq_entry *out); int merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e); void merged_iter_pqueue_release(struct merged_iter_pqueue *pq); int pq_less(struct pq_entry *a, struct pq_entry *b); diff --git a/reftable/reader.h b/reftable/reader.h deleted file mode 100644 index bb72108a6f..0000000000 --- a/reftable/reader.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef READER_H -#define READER_H - -#include "block.h" -#include "record.h" -#include "reftable-iterator.h" -#include "reftable-reader.h" - -uint64_t block_source_size(struct reftable_block_source *source); - -ssize_t block_source_read_block(struct reftable_block_source *source, - struct reftable_block *dest, uint64_t off, - uint32_t size); -void block_source_close(struct reftable_block_source *source); - -/* metadata for a block type */ -struct reftable_reader_offsets { - int is_present; - uint64_t offset; - uint64_t index_offset; -}; - -/* The state for reading a reftable file. */ -struct reftable_reader { - /* for convenience, associate a name with the instance. */ - char *name; - struct reftable_block_source source; - - /* Size of the file, excluding the footer. */ - uint64_t size; - - /* The hash function used for ref records. */ - enum reftable_hash hash_id; - - uint32_t block_size; - uint64_t min_update_index; - uint64_t max_update_index; - /* Length of the OID keys in the 'o' section */ - int object_id_len; - int version; - - struct reftable_reader_offsets ref_offsets; - struct reftable_reader_offsets obj_offsets; - struct reftable_reader_offsets log_offsets; - - uint64_t refcount; -}; - -const char *reader_name(struct reftable_reader *r); - -int reader_init_iter(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t typ); - -/* initialize a block reader to read from `r` */ -int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br, - uint64_t next_off, uint8_t want_typ); - -#endif diff --git a/reftable/record.c b/reftable/record.c index 8919df8a4d..fcd387ba5d 100644 --- a/reftable/record.c +++ b/reftable/record.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ /* record.c - methods for different types of records. */ @@ -61,7 +61,7 @@ int put_var_int(struct string_view *dest, uint64_t value) while (value >>= 7) varint[--pos] = 0x80 | (--value & 0x7f); if (dest->len < sizeof(varint) - pos) - return -1; + return REFTABLE_ENTRY_TOO_BIG_ERROR; memcpy(dest->buf, varint + pos, sizeof(varint) - pos); return sizeof(varint) - pos; } @@ -69,10 +69,10 @@ int put_var_int(struct string_view *dest, uint64_t value) int reftable_is_block_type(uint8_t typ) { switch (typ) { - case BLOCK_TYPE_REF: - case BLOCK_TYPE_LOG: - case BLOCK_TYPE_OBJ: - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_OBJ: + case REFTABLE_BLOCK_TYPE_INDEX: return 1; } return 0; @@ -129,10 +129,10 @@ static int encode_string(const char *str, struct string_view s) size_t l = strlen(str); int n = put_var_int(&s, l); if (n < 0) - return -1; + return n; string_view_consume(&s, n); if (s.len < l) - return -1; + return REFTABLE_ENTRY_TOO_BIG_ERROR; memcpy(s.buf, str, l); string_view_consume(&s, l); @@ -148,18 +148,18 @@ int reftable_encode_key(int *restart, struct string_view dest, uint64_t suffix_len = key.len - prefix_len; int n = put_var_int(&dest, prefix_len); if (n < 0) - return -1; + return n; string_view_consume(&dest, n); *restart = (prefix_len == 0); n = put_var_int(&dest, suffix_len << 3 | (uint64_t)extra); if (n < 0) - return -1; + return n; string_view_consume(&dest, n); if (dest.len < suffix_len) - return -1; + return REFTABLE_ENTRY_TOO_BIG_ERROR; memcpy(dest.buf, key.buf + prefix_len, suffix_len); string_view_consume(&dest, suffix_len); @@ -237,11 +237,11 @@ static int reftable_ref_record_copy_from(void *rec, const void *src_rec, size_t refname_cap = 0; int err; - SWAP(refname, ref->refname); - SWAP(refname_cap, ref->refname_cap); + REFTABLE_SWAP(refname, ref->refname); + REFTABLE_SWAP(refname_cap, ref->refname_cap); reftable_ref_record_release(ref); - SWAP(ref->refname, refname); - SWAP(ref->refname_cap, refname_cap); + REFTABLE_SWAP(ref->refname, refname); + REFTABLE_SWAP(ref->refname_cap, refname_cap); if (src->refname) { size_t refname_len = strlen(src->refname); @@ -324,30 +324,27 @@ static int reftable_ref_record_encode(const void *rec, struct string_view s, struct string_view start = s; int n = put_var_int(&s, r->update_index); if (n < 0) - return -1; + return n; string_view_consume(&s, n); switch (r->value_type) { case REFTABLE_REF_SYMREF: n = encode_string(r->value.symref, s); - if (n < 0) { - return -1; - } + if (n < 0) + return n; string_view_consume(&s, n); break; case REFTABLE_REF_VAL2: - if (s.len < 2 * hash_size) { - return -1; - } + if (s.len < 2 * hash_size) + return REFTABLE_ENTRY_TOO_BIG_ERROR; memcpy(s.buf, r->value.val2.value, hash_size); string_view_consume(&s, hash_size); memcpy(s.buf, r->value.val2.target_value, hash_size); string_view_consume(&s, hash_size); break; case REFTABLE_REF_VAL1: - if (s.len < hash_size) { - return -1; - } + if (s.len < hash_size) + return REFTABLE_ENTRY_TOO_BIG_ERROR; memcpy(s.buf, r->value.val1, hash_size); string_view_consume(&s, hash_size); break; @@ -376,11 +373,11 @@ static int reftable_ref_record_decode(void *rec, struct reftable_buf key, return n; string_view_consume(&in, n); - SWAP(refname, r->refname); - SWAP(refname_cap, r->refname_cap); + REFTABLE_SWAP(refname, r->refname); + REFTABLE_SWAP(refname_cap, r->refname_cap); reftable_ref_record_release(r); - SWAP(r->refname, refname); - SWAP(r->refname_cap, refname_cap); + REFTABLE_SWAP(r->refname, refname); + REFTABLE_SWAP(r->refname_cap, refname_cap); REFTABLE_ALLOC_GROW_OR_NULL(r->refname, key.len + 1, r->refname_cap); if (!r->refname) { @@ -462,7 +459,7 @@ static int reftable_ref_record_cmp_void(const void *_a, const void *_b) static struct reftable_record_vtable reftable_ref_record_vtable = { .key = &reftable_ref_record_key, - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .copy_from = &reftable_ref_record_copy_from, .val_type = &reftable_ref_record_val_type, .encode = &reftable_ref_record_encode, @@ -490,7 +487,7 @@ static void reftable_obj_record_release(void *rec) } static int reftable_obj_record_copy_from(void *rec, const void *src_rec, - uint32_t hash_size UNUSED) + uint32_t hash_size REFTABLE_UNUSED) { struct reftable_obj_record *obj = rec; const struct reftable_obj_record *src = src_rec; @@ -504,11 +501,17 @@ static int reftable_obj_record_copy_from(void *rec, const void *src_rec, if (src->hash_prefix_len) memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len); - REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len); - if (!obj->offsets) - return REFTABLE_OUT_OF_MEMORY_ERROR; - obj->offset_len = src->offset_len; - COPY_ARRAY(obj->offsets, src->offsets, src->offset_len); + if (src->offset_len) { + if (sizeof(*src->offsets) > SIZE_MAX / src->offset_len) + return REFTABLE_OUT_OF_MEMORY_ERROR; + + REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len); + if (!obj->offsets) + return REFTABLE_OUT_OF_MEMORY_ERROR; + + memcpy(obj->offsets, src->offsets, sizeof(*src->offsets) * src->offset_len); + obj->offset_len = src->offset_len; + } return 0; } @@ -522,7 +525,7 @@ static uint8_t reftable_obj_record_val_type(const void *rec) } static int reftable_obj_record_encode(const void *rec, struct string_view s, - uint32_t hash_size UNUSED) + uint32_t hash_size REFTABLE_UNUSED) { const struct reftable_obj_record *r = rec; struct string_view start = s; @@ -531,24 +534,22 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s, uint64_t last = 0; if (r->offset_len == 0 || r->offset_len >= 8) { n = put_var_int(&s, r->offset_len); - if (n < 0) { - return -1; - } + if (n < 0) + return n; string_view_consume(&s, n); } if (r->offset_len == 0) return start.len - s.len; n = put_var_int(&s, r->offsets[0]); if (n < 0) - return -1; + return n; string_view_consume(&s, n); last = r->offsets[0]; for (i = 1; i < r->offset_len; i++) { int n = put_var_int(&s, r->offsets[i] - last); - if (n < 0) { - return -1; - } + if (n < 0) + return n; string_view_consume(&s, n); last = r->offsets[i]; } @@ -557,8 +558,8 @@ static int reftable_obj_record_encode(const void *rec, struct string_view s, static int reftable_obj_record_decode(void *rec, struct reftable_buf key, uint8_t val_type, struct string_view in, - uint32_t hash_size UNUSED, - struct reftable_buf *scratch UNUSED) + uint32_t hash_size REFTABLE_UNUSED, + struct reftable_buf *scratch REFTABLE_UNUSED) { struct string_view start = in; struct reftable_obj_record *r = rec; @@ -612,13 +613,13 @@ static int reftable_obj_record_decode(void *rec, struct reftable_buf key, return start.len - in.len; } -static int not_a_deletion(const void *p UNUSED) +static int not_a_deletion(const void *p REFTABLE_UNUSED) { return 0; } static int reftable_obj_record_equal_void(const void *a, const void *b, - uint32_t hash_size UNUSED) + uint32_t hash_size REFTABLE_UNUSED) { struct reftable_obj_record *ra = (struct reftable_obj_record *) a; struct reftable_obj_record *rb = (struct reftable_obj_record *) b; @@ -658,7 +659,7 @@ static int reftable_obj_record_cmp_void(const void *_a, const void *_b) static struct reftable_record_vtable reftable_obj_record_vtable = { .key = &reftable_obj_record_key, - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .copy_from = &reftable_obj_record_copy_from, .val_type = &reftable_obj_record_val_type, .encode = &reftable_obj_record_encode, @@ -683,7 +684,7 @@ static int reftable_log_record_key(const void *r, struct reftable_buf *dest) return err; ts = (~ts) - rec->update_index; - put_be64(&i64[0], ts); + reftable_put_be64(&i64[0], ts); err = reftable_buf_add(dest, i64, sizeof(i64)); if (err < 0) @@ -783,7 +784,7 @@ static int reftable_log_record_encode(const void *rec, struct string_view s, return 0; if (s.len < 2 * hash_size) - return -1; + return REFTABLE_ENTRY_TOO_BIG_ERROR; memcpy(s.buf, r->value.update.old_hash, hash_size); memcpy(s.buf + hash_size, r->value.update.new_hash, hash_size); @@ -791,30 +792,30 @@ static int reftable_log_record_encode(const void *rec, struct string_view s, n = encode_string(r->value.update.name ? r->value.update.name : "", s); if (n < 0) - return -1; + return n; string_view_consume(&s, n); n = encode_string(r->value.update.email ? r->value.update.email : "", s); if (n < 0) - return -1; + return n; string_view_consume(&s, n); n = put_var_int(&s, r->value.update.time); if (n < 0) - return -1; + return n; string_view_consume(&s, n); if (s.len < 2) - return -1; + return REFTABLE_ENTRY_TOO_BIG_ERROR; - put_be16(s.buf, r->value.update.tz_offset); + reftable_put_be16(s.buf, r->value.update.tz_offset); string_view_consume(&s, 2); n = encode_string( r->value.update.message ? r->value.update.message : "", s); if (n < 0) - return -1; + return n; string_view_consume(&s, n); return start.len - s.len; @@ -840,7 +841,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key, } memcpy(r->refname, key.buf, key.len - 8); - ts = get_be64(key.buf + key.len - 8); + ts = reftable_get_be64((unsigned char *)key.buf + key.len - 8); r->update_index = (~max) - ts; @@ -931,7 +932,7 @@ static int reftable_log_record_decode(void *rec, struct reftable_buf key, goto done; } - r->value.update.tz_offset = get_be16(in.buf); + r->value.update.tz_offset = reftable_get_be16(in.buf); string_view_consume(&in, 2); n = decode_string(scratch, in); @@ -1029,7 +1030,7 @@ static int reftable_log_record_is_deletion_void(const void *p) static struct reftable_record_vtable reftable_log_record_vtable = { .key = &reftable_log_record_key, - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .copy_from = &reftable_log_record_copy_from, .val_type = &reftable_log_record_val_type, .encode = &reftable_log_record_encode, @@ -1048,7 +1049,7 @@ static int reftable_index_record_key(const void *r, struct reftable_buf *dest) } static int reftable_index_record_copy_from(void *rec, const void *src_rec, - uint32_t hash_size UNUSED) + uint32_t hash_size REFTABLE_UNUSED) { struct reftable_index_record *dst = rec; const struct reftable_index_record *src = src_rec; @@ -1069,13 +1070,13 @@ static void reftable_index_record_release(void *rec) reftable_buf_release(&idx->last_key); } -static uint8_t reftable_index_record_val_type(const void *rec UNUSED) +static uint8_t reftable_index_record_val_type(const void *rec REFTABLE_UNUSED) { return 0; } static int reftable_index_record_encode(const void *rec, struct string_view out, - uint32_t hash_size UNUSED) + uint32_t hash_size REFTABLE_UNUSED) { const struct reftable_index_record *r = (const struct reftable_index_record *)rec; @@ -1091,10 +1092,10 @@ static int reftable_index_record_encode(const void *rec, struct string_view out, } static int reftable_index_record_decode(void *rec, struct reftable_buf key, - uint8_t val_type UNUSED, + uint8_t val_type REFTABLE_UNUSED, struct string_view in, - uint32_t hash_size UNUSED, - struct reftable_buf *scratch UNUSED) + uint32_t hash_size REFTABLE_UNUSED, + struct reftable_buf *scratch REFTABLE_UNUSED) { struct string_view start = in; struct reftable_index_record *r = rec; @@ -1114,7 +1115,7 @@ static int reftable_index_record_decode(void *rec, struct reftable_buf key, } static int reftable_index_record_equal(const void *a, const void *b, - uint32_t hash_size UNUSED) + uint32_t hash_size REFTABLE_UNUSED) { struct reftable_index_record *ia = (struct reftable_index_record *) a; struct reftable_index_record *ib = (struct reftable_index_record *) b; @@ -1131,7 +1132,7 @@ static int reftable_index_record_cmp(const void *_a, const void *_b) static struct reftable_record_vtable reftable_index_record_vtable = { .key = &reftable_index_record_key, - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .copy_from = &reftable_index_record_copy_from, .val_type = &reftable_index_record_val_type, .encode = &reftable_index_record_encode, @@ -1189,12 +1190,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) +int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b, + int *cmp) { 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)); + return -1; + *cmp = reftable_record_vtable(a)->cmp(reftable_record_data(a), + reftable_record_data(b)); + return 0; } int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size) @@ -1272,13 +1275,13 @@ int reftable_log_record_is_deletion(const struct reftable_log_record *log) static void *reftable_record_data(struct reftable_record *rec) { switch (rec->type) { - case BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_REF: return &rec->u.ref; - case BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_LOG: return &rec->u.log; - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_INDEX: return &rec->u.idx; - case BLOCK_TYPE_OBJ: + case REFTABLE_BLOCK_TYPE_OBJ: return &rec->u.obj; } abort(); @@ -1288,32 +1291,32 @@ static struct reftable_record_vtable * reftable_record_vtable(struct reftable_record *rec) { switch (rec->type) { - case BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_REF: return &reftable_ref_record_vtable; - case BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_LOG: return &reftable_log_record_vtable; - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_INDEX: return &reftable_index_record_vtable; - case BLOCK_TYPE_OBJ: + case REFTABLE_BLOCK_TYPE_OBJ: return &reftable_obj_record_vtable; } abort(); } -void reftable_record_init(struct reftable_record *rec, uint8_t typ) +int reftable_record_init(struct reftable_record *rec, uint8_t typ) { memset(rec, 0, sizeof(*rec)); rec->type = typ; switch (typ) { - case BLOCK_TYPE_REF: - case BLOCK_TYPE_LOG: - case BLOCK_TYPE_OBJ: - return; - case BLOCK_TYPE_INDEX: + case REFTABLE_BLOCK_TYPE_REF: + case REFTABLE_BLOCK_TYPE_LOG: + case REFTABLE_BLOCK_TYPE_OBJ: + return 0; + case REFTABLE_BLOCK_TYPE_INDEX: reftable_buf_init(&rec->u.idx.last_key); - return; + return 0; default: - BUG("unhandled record type"); + return REFTABLE_API_ERROR; } } diff --git a/reftable/record.h b/reftable/record.h index c7755a4d75..7953f352a3 100644 --- a/reftable/record.h +++ b/reftable/record.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef RECORD_H #define RECORD_H @@ -130,11 +130,11 @@ struct reftable_record { } u; }; -/* Initialize the reftable record for the given type */ -void reftable_record_init(struct reftable_record *rec, uint8_t typ); +/* Initialize the reftable record for the given type. */ +int 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_cmp(struct reftable_record *a, struct reftable_record *b, int *cmp); int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, uint32_t hash_size); int reftable_record_key(struct reftable_record *rec, struct reftable_buf *dest); int reftable_record_copy_from(struct reftable_record *rec, diff --git a/reftable/reftable-basics.h b/reftable/reftable-basics.h index e0397ed583..6d73f19c85 100644 --- a/reftable/reftable-basics.h +++ b/reftable/reftable-basics.h @@ -4,13 +4,21 @@ * Use of this source code is governed by a BSD-style * license that can be found in the LICENSE file or at * https://developers.google.com/open-source/licenses/bsd -*/ + */ #ifndef REFTABLE_BASICS_H #define REFTABLE_BASICS_H #include <stddef.h> +/* A buffer that contains arbitrary byte slices. */ +struct reftable_buf { + size_t alloc; + size_t len; + char *buf; +}; +#define REFTABLE_BUF_INIT { 0 } + /* * Hash functions understood by the reftable library. Note that the values are * arbitrary and somewhat random such that we can easily detect cases where the diff --git a/reftable/reftable-block.h b/reftable/reftable-block.h new file mode 100644 index 0000000000..0b05a8f7e3 --- /dev/null +++ b/reftable/reftable-block.h @@ -0,0 +1,75 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef REFTABLE_BLOCK_H +#define REFTABLE_BLOCK_H + +#include <stdint.h> + +#include "reftable-basics.h" +#include "reftable-blocksource.h" +#include "reftable-iterator.h" + +struct z_stream_s; + +/* + * A block part of a reftable. Contains records as well as some metadata + * describing them. + */ +struct reftable_block { + /* + * Offset of the block header; nonzero for the first block in a + * reftable. + */ + uint32_t header_off; + + /* The memory block. */ + struct reftable_block_data block_data; + uint32_t hash_size; + + /* Uncompressed data for log entries. */ + struct z_stream_s *zstream; + unsigned char *uncompressed_data; + size_t uncompressed_cap; + + /* + * Restart point data. Restart points are located after the block's + * record data. + */ + uint16_t restart_count; + uint32_t restart_off; + + /* + * Size of the data in the file. For log blocks, this is the compressed + * size. + */ + uint32_t full_block_size; + uint8_t block_type; +}; + +/* Initialize a reftable block from the given block source. */ +int reftable_block_init(struct reftable_block *b, + struct reftable_block_source *source, + uint32_t offset, uint32_t header_size, + uint32_t table_block_size, uint32_t hash_size, + uint8_t want_type); + +/* Release resources allocated by the block. */ +void reftable_block_release(struct reftable_block *b); + +/* Initialize a generic record iterator from the given block. */ +int reftable_block_init_iterator(const struct reftable_block *b, + struct reftable_iterator *it); + +/* Returns the block type (eg. 'r' for refs). */ +uint8_t reftable_block_type(const struct reftable_block *b); + +/* Decodes the first key in the block. */ +int reftable_block_first_key(const struct reftable_block *b, struct reftable_buf *key); + +#endif /* REFTABLE_BLOCK_H */ diff --git a/reftable/reftable-blocksource.h b/reftable/reftable-blocksource.h index 6b326aa5ea..f5ba867bd6 100644 --- a/reftable/reftable-blocksource.h +++ b/reftable/reftable-blocksource.h @@ -1,17 +1,18 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_BLOCKSOURCE_H #define REFTABLE_BLOCKSOURCE_H #include <stdint.h> -/* block_source is a generic wrapper for a seekable readable file. +/* + * Generic wrapper for a seekable readable file. */ struct reftable_block_source { struct reftable_block_source_vtable *ops; @@ -20,7 +21,7 @@ struct reftable_block_source { /* a contiguous segment of bytes. It keeps track of its generating block_source * so it can return itself into the pool. */ -struct reftable_block { +struct reftable_block_data { uint8_t *data; size_t len; struct reftable_block_source source; @@ -28,20 +29,20 @@ struct reftable_block { /* block_source_vtable are the operations that make up block_source */ struct reftable_block_source_vtable { - /* returns the size of a block source */ + /* Returns the size of a block source. */ uint64_t (*size)(void *source); /* * Reads a segment from the block source. It is an error to read beyond * the end of the block. */ - ssize_t (*read_block)(void *source, struct reftable_block *dest, - uint64_t off, uint32_t size); + ssize_t (*read_data)(void *source, struct reftable_block_data *dest, + uint64_t off, uint32_t size); - /* mark the block as read; may return the data back to malloc */ - void (*return_block)(void *source, struct reftable_block *blockp); + /* Mark the block as read; may release the data. */ + void (*release_data)(void *source, struct reftable_block_data *data); - /* release all resources associated with the block source */ + /* Release all resources associated with the block source. */ void (*close)(void *source); }; diff --git a/reftable/reftable-constants.h b/reftable/reftable-constants.h new file mode 100644 index 0000000000..4ae9ba4bac --- /dev/null +++ b/reftable/reftable-constants.h @@ -0,0 +1,18 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef REFTABLE_CONSTANTS_H +#define REFTABLE_CONSTANTS_H + +#define REFTABLE_BLOCK_TYPE_LOG 'g' +#define REFTABLE_BLOCK_TYPE_INDEX 'i' +#define REFTABLE_BLOCK_TYPE_REF 'r' +#define REFTABLE_BLOCK_TYPE_OBJ 'o' +#define REFTABLE_BLOCK_TYPE_ANY 0 + +#endif /* REFTABLE_CONSTANTS_H */ diff --git a/reftable/reftable-error.h b/reftable/reftable-error.h index a7e33d964d..d100e0df92 100644 --- a/reftable/reftable-error.h +++ b/reftable/reftable-error.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_ERROR_H #define REFTABLE_ERROR_H diff --git a/reftable/reftable-iterator.h b/reftable/reftable-iterator.h index e3bf688d53..af582028c2 100644 --- a/reftable/reftable-iterator.h +++ b/reftable/reftable-iterator.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_ITERATOR_H #define REFTABLE_ITERATOR_H diff --git a/reftable/reftable-merged.h b/reftable/reftable-merged.h index f2d01c3ef8..e5af846b32 100644 --- a/reftable/reftable-merged.h +++ b/reftable/reftable-merged.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_MERGED_H #define REFTABLE_MERGED_H @@ -26,14 +26,14 @@ https://developers.google.com/open-source/licenses/bsd /* A merged table is implements seeking/iterating over a stack of tables. */ struct reftable_merged_table; -struct reftable_reader; +struct reftable_table; /* - * reftable_merged_table_new creates a new merged table. The readers must be + * reftable_merged_table_new creates a new merged table. The tables must be * kept alive as long as the merged table is still in use. */ int reftable_merged_table_new(struct reftable_merged_table **dest, - struct reftable_reader **readers, size_t n, + struct reftable_table **tables, size_t n, enum reftable_hash hash_id); /* Initialize a merged table iterator for reading refs. */ diff --git a/reftable/reftable-reader.h b/reftable/reftable-reader.h deleted file mode 100644 index 0085fbb903..0000000000 --- a/reftable/reftable-reader.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright 2020 Google LLC - - Use of this source code is governed by a BSD-style - license that can be found in the LICENSE file or at - https://developers.google.com/open-source/licenses/bsd -*/ - -#ifndef REFTABLE_READER_H -#define REFTABLE_READER_H - -#include "reftable-iterator.h" -#include "reftable-blocksource.h" - -/* - * Reading single tables - * - * The follow routines are for reading single files. For an - * application-level interface, skip ahead to struct - * reftable_merged_table and struct reftable_stack. - */ - -/* The reader struct is a handle to an open reftable file. */ -struct reftable_reader; - -/* reftable_reader_new opens a reftable for reading. If successful, - * returns 0 code and sets pp. The name is used for creating a - * stack. Typically, it is the basename of the file. The block source - * `src` is owned by the reader, and is closed on calling - * reftable_reader_destroy(). On error, the block source `src` is - * closed as well. - */ -int reftable_reader_new(struct reftable_reader **pp, - struct reftable_block_source *src, const char *name); - -/* - * Manage the reference count of the reftable reader. A newly initialized - * reader starts with a refcount of 1 and will be deleted once the refcount has - * reached 0. - * - * This is required because readers may have longer lifetimes than the stack - * they belong to. The stack may for example be reloaded while the old tables - * are still being accessed by an iterator. - */ -void reftable_reader_incref(struct reftable_reader *reader); -void reftable_reader_decref(struct reftable_reader *reader); - -/* Initialize a reftable iterator for reading refs. */ -int reftable_reader_init_ref_iterator(struct reftable_reader *r, - struct reftable_iterator *it); - -/* Initialize a reftable iterator for reading logs. */ -int reftable_reader_init_log_iterator(struct reftable_reader *r, - struct reftable_iterator *it); - -/* returns the hash ID used in this table. */ -enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r); - -/* return an iterator for the refs pointing to `oid`. */ -int reftable_reader_refs_for(struct reftable_reader *r, - struct reftable_iterator *it, uint8_t *oid); - -/* return the max_update_index for a table */ -uint64_t reftable_reader_max_update_index(struct reftable_reader *r); - -/* return the min_update_index for a table */ -uint64_t reftable_reader_min_update_index(struct reftable_reader *r); - -/* print blocks onto stdout for debugging. */ -int reftable_reader_print_blocks(const char *tablename); - -#endif diff --git a/reftable/reftable-record.h b/reftable/reftable-record.h index 931e594744..385a74cc86 100644 --- a/reftable/reftable-record.h +++ b/reftable/reftable-record.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_RECORD_H #define REFTABLE_RECORD_H diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h index ae14270ea7..910ec6ef3a 100644 --- a/reftable/reftable-stack.h +++ b/reftable/reftable-stack.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_STACK_H #define REFTABLE_STACK_H diff --git a/reftable/reftable-table.h b/reftable/reftable-table.h new file mode 100644 index 0000000000..5f935d02e3 --- /dev/null +++ b/reftable/reftable-table.h @@ -0,0 +1,115 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef REFTABLE_TABLE_H +#define REFTABLE_TABLE_H + +#include "reftable-iterator.h" +#include "reftable-block.h" +#include "reftable-blocksource.h" + +/* + * Reading single tables + * + * The follow routines are for reading single files. For an + * application-level interface, skip ahead to struct + * reftable_merged_table and struct reftable_stack. + */ + +/* Metadata for a block type. */ +struct reftable_table_offsets { + int is_present; + uint64_t offset; + uint64_t index_offset; +}; + +/* The table struct is a handle to an open reftable file. */ +struct reftable_table { + /* for convenience, associate a name with the instance. */ + char *name; + struct reftable_block_source source; + + /* Size of the file, excluding the footer. */ + uint64_t size; + + /* The hash function used for ref records. */ + enum reftable_hash hash_id; + + uint32_t block_size; + uint64_t min_update_index; + uint64_t max_update_index; + /* Length of the OID keys in the 'o' section */ + int object_id_len; + int version; + + struct reftable_table_offsets ref_offsets; + struct reftable_table_offsets obj_offsets; + struct reftable_table_offsets log_offsets; + + uint64_t refcount; +}; + +/* reftable_table_new opens a reftable for reading. If successful, + * returns 0 code and sets pp. The name is used for creating a + * stack. Typically, it is the basename of the file. The block source + * `src` is owned by the table, and is closed on calling + * reftable_table_destroy(). On error, the block source `src` is + * closed as well. + */ +int reftable_table_new(struct reftable_table **out, + struct reftable_block_source *src, const char *name); + +/* + * Manage the reference count of the reftable table. A newly initialized + * table starts with a refcount of 1 and will be deleted once the refcount has + * reached 0. + * + * This is required because tables may have longer lifetimes than the stack + * they belong to. The stack may for example be reloaded while the old tables + * are still being accessed by an iterator. + */ +void reftable_table_incref(struct reftable_table *table); +void reftable_table_decref(struct reftable_table *table); + +/* Initialize a reftable iterator for reading refs. */ +int reftable_table_init_ref_iterator(struct reftable_table *t, + struct reftable_iterator *it); + +/* Initialize a reftable iterator for reading logs. */ +int reftable_table_init_log_iterator(struct reftable_table *t, + struct reftable_iterator *it); + +/* returns the hash ID used in this table. */ +enum reftable_hash reftable_table_hash_id(struct reftable_table *t); + +/* return an iterator for the refs pointing to `oid`. */ +int reftable_table_refs_for(struct reftable_table *t, + struct reftable_iterator *it, uint8_t *oid); + +/* return the max_update_index for a table */ +uint64_t reftable_table_max_update_index(struct reftable_table *t); + +/* return the min_update_index for a table */ +uint64_t reftable_table_min_update_index(struct reftable_table *t); + +/* + * An iterator that iterates through the blocks contained in a given table. + */ +struct reftable_table_iterator { + void *iter_arg; +}; + +int reftable_table_iterator_init(struct reftable_table_iterator *it, + struct reftable_table *t); + +void reftable_table_iterator_release(struct reftable_table_iterator *it); + +int reftable_table_iterator_next(struct reftable_table_iterator *it, + const struct reftable_block **out); + +#endif diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h index 1befe3b07c..0fbeff17f4 100644 --- a/reftable/reftable-writer.h +++ b/reftable/reftable-writer.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef REFTABLE_WRITER_H #define REFTABLE_WRITER_H diff --git a/reftable/stack.c b/reftable/stack.c index 6c4e8be19b..4caf96aa1d 100644 --- a/reftable/stack.c +++ b/reftable/stack.c @@ -1,20 +1,20 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "stack.h" #include "system.h" #include "constants.h" #include "merged.h" -#include "reader.h" #include "reftable-error.h" #include "reftable-record.h" #include "reftable-merged.h" +#include "table.h" #include "writer.h" static int stack_try_add(struct reftable_stack *st, @@ -48,6 +48,25 @@ static int stack_fsync(const struct reftable_write_options *opts, int fd) return fsync(fd); } +static ssize_t reftable_write_data(int fd, const void *data, size_t size) +{ + size_t total_written = 0; + const char *p = data; + + while (total_written < size) { + ssize_t bytes_written = write(fd, p, size - total_written); + if (bytes_written < 0 && (errno == EAGAIN || errno == EINTR)) + continue; + if (bytes_written < 0) + return REFTABLE_IO_ERROR; + + total_written += bytes_written; + p += bytes_written; + } + + return total_written; +} + struct fd_writer { const struct reftable_write_options *opts; int fd; @@ -56,7 +75,7 @@ struct fd_writer { static ssize_t fd_writer_write(void *arg, const void *data, size_t sz) { struct fd_writer *writer = arg; - return write_in_full(writer->fd, data, sz); + return reftable_write_data(writer->fd, data, sz); } static int fd_writer_flush(void *arg) @@ -115,13 +134,16 @@ out: static int fd_read_lines(int fd, char ***namesp) { - off_t size = lseek(fd, 0, SEEK_END); char *buf = NULL; int err = 0; + off_t size; + + size = lseek(fd, 0, SEEK_END); if (size < 0) { err = REFTABLE_IO_ERROR; goto done; } + err = lseek(fd, 0, SEEK_SET); if (err < 0) { err = REFTABLE_IO_ERROR; @@ -134,9 +156,16 @@ static int fd_read_lines(int fd, char ***namesp) goto done; } - if (read_in_full(fd, buf, size) != size) { - err = REFTABLE_IO_ERROR; - goto done; + for (off_t total_read = 0; total_read < size; ) { + ssize_t bytes_read = read(fd, buf + total_read, size - total_read); + if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR)) + continue; + if (bytes_read < 0 || !bytes_read) { + err = REFTABLE_IO_ERROR; + goto done; + } + + total_read += bytes_read; } buf[size] = 0; @@ -174,14 +203,14 @@ int reftable_stack_init_ref_iterator(struct reftable_stack *st, struct reftable_iterator *it) { return merged_table_init_iter(reftable_stack_merged_table(st), - it, BLOCK_TYPE_REF); + it, REFTABLE_BLOCK_TYPE_REF); } int reftable_stack_init_log_iterator(struct reftable_stack *st, struct reftable_iterator *it) { return merged_table_init_iter(reftable_stack_merged_table(st), - it, BLOCK_TYPE_LOG); + it, REFTABLE_BLOCK_TYPE_LOG); } struct reftable_merged_table * @@ -219,11 +248,11 @@ void reftable_stack_destroy(struct reftable_stack *st) REFTABLE_FREE_AND_NULL(names); } - if (st->readers) { + if (st->tables) { struct reftable_buf filename = REFTABLE_BUF_INIT; - for (size_t i = 0; i < st->readers_len; i++) { - const char *name = reader_name(st->readers[i]); + for (size_t i = 0; i < st->tables_len; i++) { + const char *name = reftable_table_name(st->tables[i]); int try_unlinking = 1; reftable_buf_reset(&filename); @@ -231,7 +260,7 @@ void reftable_stack_destroy(struct reftable_stack *st) if (stack_filename(&filename, st, name) < 0) try_unlinking = 0; } - reftable_reader_decref(st->readers[i]); + reftable_table_decref(st->tables[i]); if (try_unlinking && filename.len) { /* On Windows, can only unlink after closing. */ @@ -240,8 +269,8 @@ void reftable_stack_destroy(struct reftable_stack *st) } reftable_buf_release(&filename); - st->readers_len = 0; - REFTABLE_FREE_AND_NULL(st->readers); + st->tables_len = 0; + REFTABLE_FREE_AND_NULL(st->tables); } if (st->list_fd >= 0) { @@ -255,14 +284,14 @@ void reftable_stack_destroy(struct reftable_stack *st) free_names(names); } -static struct reftable_reader **stack_copy_readers(struct reftable_stack *st, - size_t cur_len) +static struct reftable_table **stack_copy_tables(struct reftable_stack *st, + size_t cur_len) { - struct reftable_reader **cur = reftable_calloc(cur_len, sizeof(*cur)); + struct reftable_table **cur = reftable_calloc(cur_len, sizeof(*cur)); if (!cur) return NULL; for (size_t i = 0; i < cur_len; i++) - cur[i] = st->readers[i]; + cur[i] = st->tables[i]; return cur; } @@ -270,19 +299,19 @@ static int reftable_stack_reload_once(struct reftable_stack *st, const char **names, int reuse_open) { - size_t cur_len = !st->merged ? 0 : st->merged->readers_len; - struct reftable_reader **cur = NULL; - struct reftable_reader **reused = NULL; - struct reftable_reader **new_readers = NULL; + size_t cur_len = !st->merged ? 0 : st->merged->tables_len; + struct reftable_table **cur = NULL; + struct reftable_table **reused = NULL; + struct reftable_table **new_tables = NULL; size_t reused_len = 0, reused_alloc = 0, names_len; - size_t new_readers_len = 0; + size_t new_tables_len = 0; struct reftable_merged_table *new_merged = NULL; struct reftable_buf table_path = REFTABLE_BUF_INIT; int err = 0; size_t i; if (cur_len) { - cur = stack_copy_readers(st, cur_len); + cur = stack_copy_tables(st, cur_len); if (!cur) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; @@ -292,28 +321,28 @@ static int reftable_stack_reload_once(struct reftable_stack *st, names_len = names_length(names); if (names_len) { - new_readers = reftable_calloc(names_len, sizeof(*new_readers)); - if (!new_readers) { + new_tables = reftable_calloc(names_len, sizeof(*new_tables)); + if (!new_tables) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } } while (*names) { - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; const char *name = *names++; /* this is linear; we assume compaction keeps the number of tables under control so this is not quadratic. */ for (i = 0; reuse_open && i < cur_len; i++) { if (cur[i] && 0 == strcmp(cur[i]->name, name)) { - rd = cur[i]; + table = cur[i]; cur[i] = NULL; /* * When reloading the stack fails, we end up - * releasing all new readers. This also - * includes the reused readers, even though + * releasing all new tables. This also + * includes the reused tables, even though * they are still in used by the old stack. We * thus need to keep them alive here, which we * do by bumping their refcount. @@ -325,13 +354,13 @@ static int reftable_stack_reload_once(struct reftable_stack *st, err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - reused[reused_len++] = rd; - reftable_reader_incref(rd); + reused[reused_len++] = table; + reftable_table_incref(table); break; } } - if (!rd) { + if (!table) { struct reftable_block_source src = { NULL }; err = stack_filename(&table_path, st, name); @@ -343,36 +372,36 @@ static int reftable_stack_reload_once(struct reftable_stack *st, if (err < 0) goto done; - err = reftable_reader_new(&rd, &src, name); + err = reftable_table_new(&table, &src, name); if (err < 0) goto done; } - new_readers[new_readers_len] = rd; - new_readers_len++; + new_tables[new_tables_len] = table; + new_tables_len++; } /* success! */ - err = reftable_merged_table_new(&new_merged, new_readers, - new_readers_len, st->opts.hash_id); + err = reftable_merged_table_new(&new_merged, new_tables, + new_tables_len, st->opts.hash_id); if (err < 0) goto done; /* - * Close the old, non-reused readers and proactively try to unlink + * Close the old, non-reused tables and proactively try to unlink * them. This is done for systems like Windows, where the underlying - * file of such an open reader wouldn't have been possible to be + * file of such an open table wouldn't have been possible to be * unlinked by the compacting process. */ for (i = 0; i < cur_len; i++) { if (cur[i]) { - const char *name = reader_name(cur[i]); + const char *name = reftable_table_name(cur[i]); err = stack_filename(&table_path, st, name); if (err < 0) goto done; - reftable_reader_decref(cur[i]); + reftable_table_decref(cur[i]); unlink(table_path.buf); } } @@ -383,25 +412,25 @@ static int reftable_stack_reload_once(struct reftable_stack *st, new_merged->suppress_deletions = 1; st->merged = new_merged; - if (st->readers) - reftable_free(st->readers); - st->readers = new_readers; - st->readers_len = new_readers_len; - new_readers = NULL; - new_readers_len = 0; + if (st->tables) + reftable_free(st->tables); + st->tables = new_tables; + st->tables_len = new_tables_len; + new_tables = NULL; + new_tables_len = 0; /* - * Decrement the refcount of reused readers again. This only needs to + * Decrement the refcount of reused tables again. This only needs to * happen on the successful case, because on the unsuccessful one we - * decrement their refcount via `new_readers`. + * decrement their refcount via `new_tables`. */ for (i = 0; i < reused_len; i++) - reftable_reader_decref(reused[i]); + reftable_table_decref(reused[i]); done: - for (i = 0; i < new_readers_len; i++) - reftable_reader_decref(new_readers[i]); - reftable_free(new_readers); + for (i = 0; i < new_tables_len; i++) + reftable_table_decref(new_tables[i]); + reftable_free(new_tables); reftable_free(reused); reftable_free(cur); reftable_buf_release(&table_path); @@ -494,8 +523,8 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, close(fd); fd = -1; - delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1; - sleep_millisec(delay); + delay = delay + (delay * reftable_rand()) / UINT32_MAX + 1; + poll(NULL, 0, delay); } out: @@ -586,10 +615,10 @@ static int stack_uptodate(struct reftable_stack *st) /* * It's fine for "tables.list" to not exist. In that * case, we have to refresh when the loaded stack has - * any readers. + * any tables. */ if (errno == ENOENT) - return !!st->readers_len; + return !!st->tables_len; return REFTABLE_IO_ERROR; } @@ -608,19 +637,19 @@ static int stack_uptodate(struct reftable_stack *st) if (err < 0) return err; - for (size_t i = 0; i < st->readers_len; i++) { + for (size_t i = 0; i < st->tables_len; i++) { if (!names[i]) { err = 1; goto done; } - if (strcmp(st->readers[i]->name, names[i])) { + if (strcmp(st->tables[i]->name, names[i])) { err = 1; goto done; } } - if (names[st->merged->readers_len]) { + if (names[st->merged->tables_len]) { err = 1; goto done; } @@ -659,7 +688,7 @@ int reftable_stack_add(struct reftable_stack *st, static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max) { char buf[100]; - uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE); + uint32_t rnd = reftable_rand(); snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x", min, max, rnd); reftable_buf_reset(dest); @@ -763,8 +792,8 @@ int reftable_addition_commit(struct reftable_addition *add) if (add->new_tables_len == 0) goto done; - for (i = 0; i < add->stack->merged->readers_len; i++) { - if ((err = reftable_buf_addstr(&table_list, add->stack->readers[i]->name)) < 0 || + for (i = 0; i < add->stack->merged->tables_len; i++) { + if ((err = reftable_buf_addstr(&table_list, add->stack->tables[i]->name)) < 0 || (err = reftable_buf_addstr(&table_list, "\n")) < 0) goto done; } @@ -774,7 +803,8 @@ int reftable_addition_commit(struct reftable_addition *add) goto done; } - err = write_in_full(add->tables_list_lock.fd, table_list.buf, table_list.len); + err = reftable_write_data(add->tables_list_lock.fd, + table_list.buf, table_list.len); reftable_buf_release(&table_list); if (err < 0) { err = REFTABLE_IO_ERROR; @@ -970,9 +1000,9 @@ done: uint64_t reftable_stack_next_update_index(struct reftable_stack *st) { - int sz = st->merged->readers_len; + int sz = st->merged->tables_len; if (sz > 0) - return reftable_reader_max_update_index(st->readers[sz - 1]) + + return reftable_table_max_update_index(st->tables[sz - 1]) + 1; return 1; } @@ -991,8 +1021,8 @@ static int stack_compact_locked(struct reftable_stack *st, struct reftable_tmpfile tab_file = REFTABLE_TMPFILE_INIT; int err = 0; - err = format_name(&next_name, reftable_reader_min_update_index(st->readers[first]), - reftable_reader_max_update_index(st->readers[last])); + err = format_name(&next_name, reftable_table_min_update_index(st->tables[first]), + reftable_table_max_update_index(st->tables[last])); if (err < 0) goto done; @@ -1057,18 +1087,18 @@ static int stack_write_compact(struct reftable_stack *st, int err = 0; for (size_t i = first; i <= last; i++) - st->stats.bytes += st->readers[i]->size; - err = reftable_writer_set_limits(wr, st->readers[first]->min_update_index, - st->readers[last]->max_update_index); + st->stats.bytes += st->tables[i]->size; + err = reftable_writer_set_limits(wr, st->tables[first]->min_update_index, + st->tables[last]->max_update_index); if (err < 0) goto done; - err = reftable_merged_table_new(&mt, st->readers + first, subtabs_len, + err = reftable_merged_table_new(&mt, st->tables + first, subtabs_len, st->opts.hash_id); if (err < 0) goto done; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); if (err < 0) goto done; @@ -1096,7 +1126,7 @@ static int stack_write_compact(struct reftable_stack *st, } reftable_iterator_destroy(&it); - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); if (err < 0) goto done; @@ -1220,7 +1250,7 @@ static int stack_compact_range(struct reftable_stack *st, table_locks[i] = REFTABLE_FLOCK_INIT; for (i = last + 1; i > first; i--) { - err = stack_filename(&table_name, st, reader_name(st->readers[i - 1])); + err = stack_filename(&table_name, st, reftable_table_name(st->tables[i - 1])); if (err < 0) goto done; @@ -1346,7 +1376,7 @@ static int stack_compact_range(struct reftable_stack *st, * compacted in the updated "tables.list" file. */ for (size_t i = 0; names[i]; i++) { - if (strcmp(names[i], st->readers[first]->name)) + if (strcmp(names[i], st->tables[first]->name)) continue; /* @@ -1356,8 +1386,8 @@ static int stack_compact_range(struct reftable_stack *st, * have compacted them. */ for (size_t j = 1; j < last - first + 1; j++) { - const char *old = first + j < st->merged->readers_len ? - st->readers[first + j]->name : NULL; + const char *old = first + j < st->merged->tables_len ? + st->tables[first + j]->name : NULL; const char *new = names[i + j]; /* @@ -1397,16 +1427,16 @@ static int stack_compact_range(struct reftable_stack *st, * `fd_read_lines()` uses a `NULL` sentinel to indicate that * the array is at its end. As we use `free_names()` to free * the array, we need to include this sentinel value here and - * thus have to allocate `readers_len + 1` many entries. + * thus have to allocate `tables_len + 1` many entries. */ - REFTABLE_CALLOC_ARRAY(names, st->merged->readers_len + 1); + REFTABLE_CALLOC_ARRAY(names, st->merged->tables_len + 1); if (!names) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - for (size_t i = 0; i < st->merged->readers_len; i++) { - names[i] = reftable_strdup(st->readers[i]->name); + for (size_t i = 0; i < st->merged->tables_len; i++) { + names[i] = reftable_strdup(st->tables[i]->name); if (!names[i]) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; @@ -1421,8 +1451,8 @@ static int stack_compact_range(struct reftable_stack *st, * it into place now. */ if (!is_empty_table) { - err = format_name(&new_table_name, st->readers[first]->min_update_index, - st->readers[last]->max_update_index); + err = format_name(&new_table_name, st->tables[first]->min_update_index, + st->tables[last]->max_update_index); if (err < 0) goto done; @@ -1460,8 +1490,8 @@ static int stack_compact_range(struct reftable_stack *st, goto done; } - err = write_in_full(tables_list_lock.fd, - tables_list_buf.buf, tables_list_buf.len); + err = reftable_write_data(tables_list_lock.fd, + tables_list_buf.buf, tables_list_buf.len); if (err < 0) { err = REFTABLE_IO_ERROR; unlink(new_table_path.buf); @@ -1529,7 +1559,7 @@ done: int reftable_stack_compact_all(struct reftable_stack *st, struct reftable_log_expiry_config *config) { - size_t last = st->merged->readers_len ? st->merged->readers_len - 1 : 0; + size_t last = st->merged->tables_len ? st->merged->tables_len - 1 : 0; return stack_compact_range(st, 0, last, config, 0); } @@ -1620,12 +1650,12 @@ static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st) int overhead = header_size(version) - 1; uint64_t *sizes; - REFTABLE_CALLOC_ARRAY(sizes, st->merged->readers_len); + REFTABLE_CALLOC_ARRAY(sizes, st->merged->tables_len); if (!sizes) return NULL; - for (size_t i = 0; i < st->merged->readers_len; i++) - sizes[i] = st->readers[i]->size - overhead; + for (size_t i = 0; i < st->merged->tables_len; i++) + sizes[i] = st->tables[i]->size - overhead; return sizes; } @@ -1635,14 +1665,14 @@ int reftable_stack_auto_compact(struct reftable_stack *st) struct segment seg; uint64_t *sizes; - if (st->merged->readers_len < 2) + if (st->merged->tables_len < 2) return 0; sizes = stack_table_sizes_for_compaction(st); if (!sizes) return REFTABLE_OUT_OF_MEMORY_ERROR; - seg = suggest_compaction_segment(sizes, st->merged->readers_len, + seg = suggest_compaction_segment(sizes, st->merged->tables_len, st->opts.auto_compaction_factor); reftable_free(sizes); @@ -1733,7 +1763,7 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max, int err = 0; uint64_t update_idx = 0; struct reftable_block_source src = { NULL }; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_buf table_path = REFTABLE_BUF_INIT; err = stack_filename(&table_path, st, name); @@ -1744,12 +1774,12 @@ static void remove_maybe_stale_table(struct reftable_stack *st, uint64_t max, if (err < 0) goto done; - err = reftable_reader_new(&rd, &src, name); + err = reftable_table_new(&table, &src, name); if (err < 0) goto done; - update_idx = reftable_reader_max_update_index(rd); - reftable_reader_decref(rd); + update_idx = reftable_table_max_update_index(table); + reftable_table_decref(table); if (update_idx <= max) { unlink(table_path.buf); @@ -1773,8 +1803,8 @@ static int reftable_stack_clean_locked(struct reftable_stack *st) if (!is_table_name(d->d_name)) continue; - for (size_t i = 0; !found && i < st->readers_len; i++) - found = !strcmp(reader_name(st->readers[i]), d->d_name); + for (size_t i = 0; !found && i < st->tables_len; i++) + found = !strcmp(reftable_table_name(st->tables[i]), d->d_name); if (found) continue; diff --git a/reftable/stack.h b/reftable/stack.h index 5b45cff4f7..bc28f2998a 100644 --- a/reftable/stack.h +++ b/reftable/stack.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef STACK_H #define STACK_H @@ -22,8 +22,8 @@ struct reftable_stack { struct reftable_write_options opts; - struct reftable_reader **readers; - size_t readers_len; + struct reftable_table **tables; + size_t tables_len; struct reftable_merged_table *merged; struct reftable_compaction_stats stats; }; diff --git a/reftable/system.c b/reftable/system.c index adf8e4d30b..1ee268b125 100644 --- a/reftable/system.c +++ b/reftable/system.c @@ -1,9 +1,16 @@ +#include "../git-compat-util.h" + #include "system.h" #include "basics.h" #include "reftable-error.h" #include "../lockfile.h" #include "../tempfile.h" +uint32_t reftable_rand(void) +{ + return git_rand(CSPRNG_BYTES_INSECURE); +} + int tmpfile_from_pattern(struct reftable_tmpfile *out, const char *pattern) { struct tempfile *tempfile; diff --git a/reftable/system.h b/reftable/system.h index d02eacea8f..beb9d2431f 100644 --- a/reftable/system.h +++ b/reftable/system.h @@ -1,20 +1,27 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef SYSTEM_H #define SYSTEM_H /* This header glues the reftable library to the rest of Git */ -#include "git-compat-util.h" +#define MINGW_DONT_HANDLE_IN_USE_ERROR +#include "compat/posix.h" #include "compat/zlib-compat.h" /* + * Return a random 32 bit integer. This function is expected to return + * pre-seeded data. + */ +uint32_t reftable_rand(void); + +/* * An implementation-specific temporary file. By making this specific to the * implementation it becomes possible to tie temporary files into any kind of * signal or atexit handlers for cleanup on abnormal situations. diff --git a/reftable/reader.c b/reftable/table.c index 24bae50ac2..56362df0ed 100644 --- a/reftable/reader.c +++ b/reftable/table.c @@ -1,86 +1,46 @@ /* -Copyright 2020 Google LLC + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ - -#include "reader.h" +#include "table.h" #include "system.h" #include "block.h" +#include "blocksource.h" #include "constants.h" #include "iter.h" #include "record.h" #include "reftable-error.h" -uint64_t block_source_size(struct reftable_block_source *source) -{ - return source->ops->size(source->arg); -} - -ssize_t block_source_read_block(struct reftable_block_source *source, - struct reftable_block *dest, uint64_t off, - uint32_t size) -{ - ssize_t result = source->ops->read_block(source->arg, dest, off, size); - dest->source = *source; - return result; -} - -void block_source_close(struct reftable_block_source *source) -{ - if (!source->ops) { - return; - } - - source->ops->close(source->arg); - source->ops = NULL; -} - -static struct reftable_reader_offsets * -reader_offsets_for(struct reftable_reader *r, uint8_t typ) +static struct reftable_table_offsets * +table_offsets_for(struct reftable_table *t, uint8_t typ) { switch (typ) { - case BLOCK_TYPE_REF: - return &r->ref_offsets; - case BLOCK_TYPE_LOG: - return &r->log_offsets; - case BLOCK_TYPE_OBJ: - return &r->obj_offsets; + case REFTABLE_BLOCK_TYPE_REF: + return &t->ref_offsets; + case REFTABLE_BLOCK_TYPE_LOG: + return &t->log_offsets; + case REFTABLE_BLOCK_TYPE_OBJ: + return &t->obj_offsets; } abort(); } -static int reader_get_block(struct reftable_reader *r, - struct reftable_block *dest, uint64_t off, - uint32_t sz) -{ - ssize_t bytes_read; - if (off >= r->size) - return 0; - if (off + sz > r->size) - sz = r->size - off; - - bytes_read = block_source_read_block(&r->source, dest, off, sz); - if (bytes_read < 0) - return (int)bytes_read; - - return 0; -} - -enum reftable_hash reftable_reader_hash_id(struct reftable_reader *r) +enum reftable_hash reftable_table_hash_id(struct reftable_table *t) { - return r->hash_id; + return t->hash_id; } -const char *reader_name(struct reftable_reader *r) +const char *reftable_table_name(struct reftable_table *t) { - return r->name; + return t->name; } -static int parse_footer(struct reftable_reader *r, uint8_t *footer, +static int parse_footer(struct reftable_table *t, uint8_t *footer, uint8_t *header) { uint8_t *f = footer; @@ -95,29 +55,29 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer, } f += 4; - if (memcmp(footer, header, header_size(r->version))) { + if (memcmp(footer, header, header_size(t->version))) { err = REFTABLE_FORMAT_ERROR; goto done; } f++; - r->block_size = get_be24(f); + t->block_size = reftable_get_be24(f); f += 3; - r->min_update_index = get_be64(f); + t->min_update_index = reftable_get_be64(f); f += 8; - r->max_update_index = get_be64(f); + t->max_update_index = reftable_get_be64(f); f += 8; - if (r->version == 1) { - r->hash_id = REFTABLE_HASH_SHA1; + if (t->version == 1) { + t->hash_id = REFTABLE_HASH_SHA1; } else { - switch (get_be32(f)) { + switch (reftable_get_be32(f)) { case REFTABLE_FORMAT_ID_SHA1: - r->hash_id = REFTABLE_HASH_SHA1; + t->hash_id = REFTABLE_HASH_SHA1; break; case REFTABLE_FORMAT_ID_SHA256: - r->hash_id = REFTABLE_HASH_SHA256; + t->hash_id = REFTABLE_HASH_SHA256; break; default: err = REFTABLE_FORMAT_ERROR; @@ -127,37 +87,37 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer, f += 4; } - r->ref_offsets.index_offset = get_be64(f); + t->ref_offsets.index_offset = reftable_get_be64(f); f += 8; - r->obj_offsets.offset = get_be64(f); + t->obj_offsets.offset = reftable_get_be64(f); f += 8; - r->object_id_len = r->obj_offsets.offset & ((1 << 5) - 1); - r->obj_offsets.offset >>= 5; + t->object_id_len = t->obj_offsets.offset & ((1 << 5) - 1); + t->obj_offsets.offset >>= 5; - r->obj_offsets.index_offset = get_be64(f); + t->obj_offsets.index_offset = reftable_get_be64(f); f += 8; - r->log_offsets.offset = get_be64(f); + t->log_offsets.offset = reftable_get_be64(f); f += 8; - r->log_offsets.index_offset = get_be64(f); + t->log_offsets.index_offset = reftable_get_be64(f); f += 8; computed_crc = crc32(0, footer, f - footer); - file_crc = get_be32(f); + file_crc = reftable_get_be32(f); f += 4; if (computed_crc != file_crc) { err = REFTABLE_FORMAT_ERROR; goto done; } - first_block_typ = header[header_size(r->version)]; - r->ref_offsets.is_present = (first_block_typ == BLOCK_TYPE_REF); - r->ref_offsets.offset = 0; - r->log_offsets.is_present = (first_block_typ == BLOCK_TYPE_LOG || - r->log_offsets.offset > 0); - r->obj_offsets.is_present = r->obj_offsets.offset > 0; - if (r->obj_offsets.is_present && !r->object_id_len) { + first_block_typ = header[header_size(t->version)]; + t->ref_offsets.is_present = (first_block_typ == REFTABLE_BLOCK_TYPE_REF); + t->ref_offsets.offset = 0; + t->log_offsets.is_present = (first_block_typ == REFTABLE_BLOCK_TYPE_LOG || + t->log_offsets.offset > 0); + t->obj_offsets.is_present = t->obj_offsets.offset > 0; + if (t->obj_offsets.is_present && !t->object_id_len) { err = REFTABLE_FORMAT_ERROR; goto done; } @@ -168,20 +128,20 @@ done: } struct table_iter { - struct reftable_reader *r; + struct reftable_table *table; uint8_t typ; uint64_t block_off; - struct block_reader br; + struct reftable_block block; struct block_iter bi; int is_finished; }; -static int table_iter_init(struct table_iter *ti, struct reftable_reader *r) +static int table_iter_init(struct table_iter *ti, struct reftable_table *t) { struct block_iter bi = BLOCK_ITER_INIT; memset(ti, 0, sizeof(*ti)); - reftable_reader_incref(r); - ti->r = r; + reftable_table_incref(t); + ti->table = t; ti->bi = bi; return 0; } @@ -190,8 +150,8 @@ static int table_iter_next_in_block(struct table_iter *ti, struct reftable_record *rec) { int res = block_iter_next(&ti->bi, rec); - if (res == 0 && reftable_record_type(rec) == BLOCK_TYPE_REF) { - rec->u.ref.update_index += ti->r->min_update_index; + if (res == 0 && reftable_record_type(rec) == REFTABLE_BLOCK_TYPE_REF) { + rec->u.ref.update_index += ti->table->min_update_index; } return res; @@ -199,68 +159,23 @@ static int table_iter_next_in_block(struct table_iter *ti, static void table_iter_block_done(struct table_iter *ti) { - block_reader_release(&ti->br); + reftable_block_release(&ti->block); block_iter_reset(&ti->bi); } -static int32_t extract_block_size(uint8_t *data, uint8_t *typ, uint64_t off, - int version) +int table_init_block(struct reftable_table *t, struct reftable_block *block, + uint64_t next_off, uint8_t want_typ) { - int32_t result = 0; - - if (off == 0) { - data += header_size(version); - } - - *typ = data[0]; - if (reftable_is_block_type(*typ)) { - result = get_be24(data + 1); - } - return result; -} - -int reader_init_block_reader(struct reftable_reader *r, struct block_reader *br, - uint64_t next_off, uint8_t want_typ) -{ - int32_t guess_block_size = r->block_size ? r->block_size : - DEFAULT_BLOCK_SIZE; - struct reftable_block block = { NULL }; - uint8_t block_typ = 0; - int err = 0; - uint32_t header_off = next_off ? 0 : header_size(r->version); - int32_t block_size = 0; + uint32_t header_off = next_off ? 0 : header_size(t->version); + int err; - if (next_off >= r->size) + if (next_off >= t->size) return 1; - err = reader_get_block(r, &block, next_off, guess_block_size); - if (err < 0) - goto done; - - block_size = extract_block_size(block.data, &block_typ, next_off, - r->version); - if (block_size < 0) { - err = block_size; - goto done; - } - if (want_typ != BLOCK_TYPE_ANY && block_typ != want_typ) { - err = 1; - goto done; - } - - if (block_size > guess_block_size) { - reftable_block_done(&block); - err = reader_get_block(r, &block, next_off, block_size); - if (err < 0) { - goto done; - } - } - - err = block_reader_init(br, &block, header_off, r->block_size, - hash_size(r->hash_id)); -done: - reftable_block_done(&block); - + err = reftable_block_init(block, &t->source, next_off, header_off, + t->block_size, hash_size(t->hash_id), want_typ); + if (err) + reftable_block_release(block); return err; } @@ -268,15 +183,15 @@ static void table_iter_close(struct table_iter *ti) { table_iter_block_done(ti); block_iter_close(&ti->bi); - reftable_reader_decref(ti->r); + reftable_table_decref(ti->table); } static int table_iter_next_block(struct table_iter *ti) { - uint64_t next_block_off = ti->block_off + ti->br.full_block_size; + uint64_t next_block_off = ti->block_off + ti->block.full_block_size; int err; - err = reader_init_block_reader(ti->r, &ti->br, next_block_off, ti->typ); + err = table_init_block(ti->table, &ti->block, next_block_off, ti->typ); if (err > 0) ti->is_finished = 1; if (err) @@ -284,7 +199,7 @@ static int table_iter_next_block(struct table_iter *ti) ti->block_off = next_block_off; ti->is_finished = 0; - block_iter_seek_start(&ti->bi, &ti->br); + block_iter_init(&ti->bi, &ti->block); return 0; } @@ -326,27 +241,27 @@ static int table_iter_seek_to(struct table_iter *ti, uint64_t off, uint8_t typ) { int err; - err = reader_init_block_reader(ti->r, &ti->br, off, typ); + err = table_init_block(ti->table, &ti->block, off, typ); if (err != 0) return err; - ti->typ = block_reader_type(&ti->br); + ti->typ = reftable_block_type(&ti->block); ti->block_off = off; - block_iter_seek_start(&ti->bi, &ti->br); + block_iter_init(&ti->bi, &ti->block); ti->is_finished = 0; return 0; } static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index) { - struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ); + struct reftable_table_offsets *offs = table_offsets_for(ti->table, typ); uint64_t off = offs->offset; if (index) { off = offs->index_offset; if (off == 0) { return 1; } - typ = BLOCK_TYPE_INDEX; + typ = REFTABLE_BLOCK_TYPE_INDEX; } return table_iter_seek_to(ti, off, typ); @@ -360,7 +275,10 @@ static int table_iter_seek_linear(struct table_iter *ti, struct reftable_record rec; int err; - reftable_record_init(&rec, reftable_record_type(want)); + err = reftable_record_init(&rec, reftable_record_type(want)); + if (err < 0) + goto done; + err = reftable_record_key(want, &want_key); if (err < 0) goto done; @@ -393,10 +311,10 @@ static int table_iter_seek_linear(struct table_iter *ti, * 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; + memset(&next.block.block_data, 0, sizeof(next.block.block_data)); + next.block.zstream = NULL; + next.block.uncompressed_data = NULL; + next.block.uncompressed_cap = 0; err = table_iter_next_block(&next); if (err < 0) @@ -404,7 +322,7 @@ static int table_iter_seek_linear(struct table_iter *ti, if (err > 0) break; - err = block_reader_first_key(&next.br, &got_key); + err = reftable_block_first_key(&next.block, &got_key); if (err < 0) goto done; @@ -422,7 +340,8 @@ static int table_iter_seek_linear(struct table_iter *ti, * 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); + block_iter_init(&ti->bi, &ti->block); + err = block_iter_seek_key(&ti->bi, &want_key); if (err < 0) goto done; err = 0; @@ -438,10 +357,10 @@ static int table_iter_seek_indexed(struct table_iter *ti, struct reftable_record *rec) { struct reftable_record want_index = { - .type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT } + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT } }; struct reftable_record index_result = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }, }; int err; @@ -490,7 +409,9 @@ static int table_iter_seek_indexed(struct table_iter *ti, if (err != 0) goto done; - err = block_iter_seek_key(&ti->bi, &ti->br, &want_index.u.idx.last_key); + block_iter_init(&ti->bi, &ti->block); + + err = block_iter_seek_key(&ti->bi, &want_index.u.idx.last_key); if (err < 0) goto done; @@ -499,7 +420,7 @@ static int table_iter_seek_indexed(struct table_iter *ti, break; } - if (ti->typ != BLOCK_TYPE_INDEX) { + if (ti->typ != REFTABLE_BLOCK_TYPE_INDEX) { err = REFTABLE_FORMAT_ERROR; goto done; } @@ -515,7 +436,7 @@ static int table_iter_seek(struct table_iter *ti, struct reftable_record *want) { uint8_t typ = reftable_record_type(want); - struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ); + struct reftable_table_offsets *offs = table_offsets_for(ti->table, typ); int err; err = table_iter_seek_start(ti, reftable_record_type(want), @@ -563,11 +484,11 @@ static void iterator_from_table_iter(struct reftable_iterator *it, it->ops = &table_iter_vtable; } -int reader_init_iter(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t typ) +int table_init_iter(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t typ) { - struct reftable_reader_offsets *offs = reader_offsets_for(r, typ); + struct reftable_table_offsets *offs = table_offsets_for(t, typ); if (offs->is_present) { struct table_iter *ti; @@ -575,7 +496,7 @@ int reader_init_iter(struct reftable_reader *r, if (!ti) return REFTABLE_OUT_OF_MEMORY_ERROR; - table_iter_init(ti, r); + table_iter_init(ti, t); iterator_from_table_iter(it, ti); } else { iterator_set_empty(it); @@ -584,31 +505,31 @@ int reader_init_iter(struct reftable_reader *r, return 0; } -int reftable_reader_init_ref_iterator(struct reftable_reader *r, - struct reftable_iterator *it) +int reftable_table_init_ref_iterator(struct reftable_table *t, + struct reftable_iterator *it) { - return reader_init_iter(r, it, BLOCK_TYPE_REF); + return table_init_iter(t, it, REFTABLE_BLOCK_TYPE_REF); } -int reftable_reader_init_log_iterator(struct reftable_reader *r, - struct reftable_iterator *it) +int reftable_table_init_log_iterator(struct reftable_table *t, + struct reftable_iterator *it) { - return reader_init_iter(r, it, BLOCK_TYPE_LOG); + return table_init_iter(t, it, REFTABLE_BLOCK_TYPE_LOG); } -int reftable_reader_new(struct reftable_reader **out, - struct reftable_block_source *source, char const *name) +int reftable_table_new(struct reftable_table **out, + struct reftable_block_source *source, char const *name) { - struct reftable_block footer = { 0 }; - struct reftable_block header = { 0 }; - struct reftable_reader *r; + struct reftable_block_data footer = { 0 }; + struct reftable_block_data header = { 0 }; + struct reftable_table *t; uint64_t file_size = block_source_size(source); uint32_t read_size; ssize_t bytes_read; int err; - REFTABLE_CALLOC_ARRAY(r, 1); - if (!r) { + REFTABLE_CALLOC_ARRAY(t, 1); + if (!t) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } @@ -623,7 +544,7 @@ int reftable_reader_new(struct reftable_reader **out, goto done; } - bytes_read = block_source_read_block(source, &header, 0, read_size); + bytes_read = block_source_read_data(source, &header, 0, read_size); if (bytes_read < 0 || (size_t)bytes_read != read_size) { err = REFTABLE_IO_ERROR; goto done; @@ -633,88 +554,84 @@ int reftable_reader_new(struct reftable_reader **out, err = REFTABLE_FORMAT_ERROR; goto done; } - r->version = header.data[4]; - if (r->version != 1 && r->version != 2) { + t->version = header.data[4]; + if (t->version != 1 && t->version != 2) { err = REFTABLE_FORMAT_ERROR; goto done; } - r->size = file_size - footer_size(r->version); - r->source = *source; - r->name = reftable_strdup(name); - if (!r->name) { + t->size = file_size - footer_size(t->version); + t->source = *source; + t->name = reftable_strdup(name); + if (!t->name) { err = REFTABLE_OUT_OF_MEMORY_ERROR; goto done; } - r->hash_id = 0; - r->refcount = 1; + t->hash_id = 0; + t->refcount = 1; - bytes_read = block_source_read_block(source, &footer, r->size, - footer_size(r->version)); - if (bytes_read < 0 || (size_t)bytes_read != footer_size(r->version)) { + bytes_read = block_source_read_data(source, &footer, t->size, + footer_size(t->version)); + if (bytes_read < 0 || (size_t)bytes_read != footer_size(t->version)) { err = REFTABLE_IO_ERROR; goto done; } - err = parse_footer(r, footer.data, header.data); + err = parse_footer(t, footer.data, header.data); if (err) goto done; - *out = r; + *out = t; done: - reftable_block_done(&footer); - reftable_block_done(&header); + block_source_release_data(&footer); + block_source_release_data(&header); if (err) { - if (r) - reftable_free(r->name); - reftable_free(r); + if (t) + reftable_free(t->name); + reftable_free(t); block_source_close(source); } return err; } -void reftable_reader_incref(struct reftable_reader *r) +void reftable_table_incref(struct reftable_table *t) { - if (!r->refcount) - BUG("cannot increment ref counter of dead reader"); - r->refcount++; + t->refcount++; } -void reftable_reader_decref(struct reftable_reader *r) +void reftable_table_decref(struct reftable_table *t) { - if (!r) + if (!t) return; - if (!r->refcount) - BUG("cannot decrement ref counter of dead reader"); - if (--r->refcount) + if (--t->refcount) return; - block_source_close(&r->source); - REFTABLE_FREE_AND_NULL(r->name); - reftable_free(r); + block_source_close(&t->source); + REFTABLE_FREE_AND_NULL(t->name); + reftable_free(t); } -static int reftable_reader_refs_for_indexed(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t *oid) +static int reftable_table_refs_for_indexed(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t *oid) { struct reftable_record want = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj = { .hash_prefix = oid, - .hash_prefix_len = r->object_id_len, + .hash_prefix_len = t->object_id_len, }, }; struct reftable_iterator oit = { NULL }; struct reftable_record got = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj = { 0 }, }; int err = 0; struct indexed_table_ref_iter *itr = NULL; /* Look through the reverse index. */ - err = reader_init_iter(r, &oit, BLOCK_TYPE_OBJ); + err = table_init_iter(t, &oit, REFTABLE_BLOCK_TYPE_OBJ); if (err < 0) goto done; @@ -728,14 +645,14 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r, goto done; if (err > 0 || memcmp(want.u.obj.hash_prefix, got.u.obj.hash_prefix, - r->object_id_len)) { + t->object_id_len)) { /* didn't find it; return empty iterator */ iterator_set_empty(it); err = 0; goto done; } - err = indexed_table_ref_iter_new(&itr, r, oid, hash_size(r->hash_id), + err = indexed_table_ref_iter_new(&itr, t, oid, hash_size(t->hash_id), got.u.obj.offsets, got.u.obj.offset_len); if (err < 0) @@ -749,14 +666,14 @@ done: return err; } -static int reftable_reader_refs_for_unindexed(struct reftable_reader *r, - struct reftable_iterator *it, - uint8_t *oid) +static int reftable_table_refs_for_unindexed(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t *oid) { struct table_iter *ti; struct filtering_ref_iterator *filter = NULL; struct filtering_ref_iterator empty = FILTERING_REF_ITERATOR_INIT; - uint32_t oid_len = hash_size(r->hash_id); + uint32_t oid_len = hash_size(t->hash_id); int err; REFTABLE_ALLOC_ARRAY(ti, 1); @@ -765,8 +682,8 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r, goto out; } - table_iter_init(ti, r); - err = table_iter_seek_start(ti, BLOCK_TYPE_REF, 0); + table_iter_init(ti, t); + err = table_iter_seek_start(ti, REFTABLE_BLOCK_TYPE_REF, 0); if (err < 0) goto out; @@ -796,85 +713,67 @@ out: return err; } -int reftable_reader_refs_for(struct reftable_reader *r, - struct reftable_iterator *it, uint8_t *oid) +int reftable_table_refs_for(struct reftable_table *t, + struct reftable_iterator *it, uint8_t *oid) { - if (r->obj_offsets.is_present) - return reftable_reader_refs_for_indexed(r, it, oid); - return reftable_reader_refs_for_unindexed(r, it, oid); + if (t->obj_offsets.is_present) + return reftable_table_refs_for_indexed(t, it, oid); + return reftable_table_refs_for_unindexed(t, it, oid); } -uint64_t reftable_reader_max_update_index(struct reftable_reader *r) +uint64_t reftable_table_max_update_index(struct reftable_table *t) { - return r->max_update_index; + return t->max_update_index; } -uint64_t reftable_reader_min_update_index(struct reftable_reader *r) +uint64_t reftable_table_min_update_index(struct reftable_table *t) { - return r->min_update_index; + return t->min_update_index; } -int reftable_reader_print_blocks(const char *tablename) +int reftable_table_iterator_init(struct reftable_table_iterator *it, + struct reftable_table *t) { - struct { - const char *name; - int type; - } sections[] = { - { - .name = "ref", - .type = BLOCK_TYPE_REF, - }, - { - .name = "obj", - .type = BLOCK_TYPE_OBJ, - }, - { - .name = "log", - .type = BLOCK_TYPE_LOG, - }, - }; - struct reftable_block_source src = { 0 }; - struct reftable_reader *r = NULL; - struct table_iter ti = { 0 }; - size_t i; + struct table_iter *ti; int err; - err = reftable_block_source_from_file(&src, tablename); - if (err < 0) - goto done; + REFTABLE_ALLOC_ARRAY(ti, 1); + if (!ti) + return REFTABLE_OUT_OF_MEMORY_ERROR; - err = reftable_reader_new(&r, &src, tablename); + err = table_iter_init(ti, t); if (err < 0) - goto done; + goto out; - table_iter_init(&ti, r); + it->iter_arg = ti; + err = 0; - printf("header:\n"); - printf(" block_size: %d\n", r->block_size); +out: + if (err < 0) + reftable_free(ti); + return err; +} - for (i = 0; i < ARRAY_SIZE(sections); i++) { - err = table_iter_seek_start(&ti, sections[i].type, 0); - if (err < 0) - goto done; - if (err > 0) - continue; +void reftable_table_iterator_release(struct reftable_table_iterator *it) +{ + if (!it->iter_arg) + return; + table_iter_close(it->iter_arg); + reftable_free(it->iter_arg); + it->iter_arg = NULL; +} - printf("%s:\n", sections[i].name); +int reftable_table_iterator_next(struct reftable_table_iterator *it, + const struct reftable_block **out) +{ + struct table_iter *ti = it->iter_arg; + int err; - while (1) { - printf(" - length: %u\n", ti.br.block_len); - printf(" restarts: %u\n", ti.br.restart_count); + err = table_iter_next_block(ti); + if (err) + return err; - err = table_iter_next_block(&ti); - if (err < 0) - goto done; - if (err > 0) - break; - } - } + *out = &ti->block; -done: - reftable_reader_decref(r); - table_iter_close(&ti); - return err; + return 0; } diff --git a/reftable/table.h b/reftable/table.h new file mode 100644 index 0000000000..c54703e621 --- /dev/null +++ b/reftable/table.h @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ + +#ifndef TABLE_H +#define TABLE_H + +#include "block.h" +#include "record.h" +#include "reftable-iterator.h" +#include "reftable-table.h" + +const char *reftable_table_name(struct reftable_table *t); + +int table_init_iter(struct reftable_table *t, + struct reftable_iterator *it, + uint8_t typ); + +/* + * Initialize a block by reading from the given table and offset. + */ +int table_init_block(struct reftable_table *t, struct reftable_block *block, + uint64_t next_off, uint8_t want_typ); + +#endif diff --git a/reftable/tree.c b/reftable/tree.c index f4dbe72090..a52f7c0c7d 100644 --- a/reftable/tree.c +++ b/reftable/tree.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "system.h" #include "tree.h" diff --git a/reftable/tree.h b/reftable/tree.h index 9604453b6d..2c9c465299 100644 --- a/reftable/tree.h +++ b/reftable/tree.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef TREE_H #define TREE_H diff --git a/reftable/writer.c b/reftable/writer.c index f3ab1035d6..3b4ebdd6dc 100644 --- a/reftable/writer.c +++ b/reftable/writer.c @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #include "writer.h" @@ -57,8 +57,10 @@ static int padded_write(struct reftable_writer *w, uint8_t *data, size_t len, return -1; n = w->write(w->write_arg, zeroed, w->pending_padding); - if (n < 0) + if (n < 0) { + reftable_free(zeroed); return n; + } w->pending_padding = 0; reftable_free(zeroed); @@ -99,9 +101,9 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest) dest[4] = writer_version(w); - put_be24(dest + 5, w->opts.block_size); - put_be64(dest + 8, w->min_update_index); - put_be64(dest + 16, w->max_update_index); + reftable_put_be24(dest + 5, w->opts.block_size); + reftable_put_be64(dest + 8, w->min_update_index); + reftable_put_be64(dest + 16, w->max_update_index); if (writer_version(w) == 2) { uint32_t hash_id; @@ -116,7 +118,7 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest) return -1; } - put_be32(dest + 24, hash_id); + reftable_put_be32(dest + 24, hash_id); } return header_size(writer_version(w)); @@ -158,7 +160,7 @@ int reftable_writer_new(struct reftable_writer **out, opts = *_opts; options_set_defaults(&opts); if (opts.block_size >= (1 << 24)) - BUG("configured block size exceeds 16MB"); + return REFTABLE_API_ERROR; reftable_buf_init(&wp->block_writer_data.last_key); reftable_buf_init(&wp->last_key); @@ -172,7 +174,7 @@ int reftable_writer_new(struct reftable_writer **out, wp->write_arg = writer_arg; wp->opts = opts; wp->flush = flush_func; - writer_reinit_block_writer(wp, BLOCK_TYPE_REF); + writer_reinit_block_writer(wp, REFTABLE_BLOCK_TYPE_REF); *out = wp; @@ -256,8 +258,10 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has reftable_buf_reset(&key->hash); err = reftable_buf_add(&key->hash, hash->buf, hash->len); - if (err < 0) + if (err < 0) { + reftable_free(key); return err; + } tree_insert(&w->obj_index_tree, key, &obj_index_tree_node_compare); } else { @@ -302,19 +306,19 @@ static int writer_add_record(struct reftable_writer *w, } if (block_writer_type(w->block_writer) != reftable_record_type(rec)) - BUG("record of type %d added to writer of type %d", - reftable_record_type(rec), block_writer_type(w->block_writer)); + return REFTABLE_API_ERROR; /* * Try to add the record to the writer. If this succeeds then we're * done. Otherwise the block writer may have hit the block size limit * and needs to be flushed. */ - if (!block_writer_add(w->block_writer, rec)) { - err = 0; + err = block_writer_add(w->block_writer, rec); + if (err == 0) goto done; - } + if (err != REFTABLE_ENTRY_TOO_BIG_ERROR) + goto done; /* * The current block is full, so we need to flush and reinitialize the * writer to start writing the next block. @@ -329,16 +333,10 @@ static int writer_add_record(struct reftable_writer *w, /* * Try to add the record to the writer again. If this still fails then * the record does not fit into the block size. - * - * TODO: it would be great to have `block_writer_add()` return proper - * error codes so that we don't have to second-guess the failure - * mode here. */ err = block_writer_add(w->block_writer, rec); - if (err) { - err = REFTABLE_ENTRY_TOO_BIG_ERROR; + if (err) goto done; - } done: return err; @@ -348,7 +346,7 @@ int reftable_writer_add_ref(struct reftable_writer *w, struct reftable_ref_record *ref) { struct reftable_record rec = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u = { .ref = *ref }, @@ -412,13 +410,13 @@ static int reftable_writer_add_log_verbatim(struct reftable_writer *w, struct reftable_log_record *log) { struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u = { .log = *log, }, }; if (w->block_writer && - block_writer_type(w->block_writer) == BLOCK_TYPE_REF) { + block_writer_type(w->block_writer) == REFTABLE_BLOCK_TYPE_REF) { int err = writer_finish_public_section(w); if (err < 0) return err; @@ -538,7 +536,7 @@ static int writer_finish_section(struct reftable_writer *w) max_level++; index_start = w->next; - err = writer_reinit_block_writer(w, BLOCK_TYPE_INDEX); + err = writer_reinit_block_writer(w, REFTABLE_BLOCK_TYPE_INDEX); if (err < 0) return err; @@ -550,7 +548,7 @@ static int writer_finish_section(struct reftable_writer *w) w->index_cap = 0; for (i = 0; i < idx_len; i++) { struct reftable_record rec = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u = { .idx = idx[i], }, @@ -615,7 +613,7 @@ static void write_object_record(void *void_arg, void *key) struct write_record_arg *arg = void_arg; struct obj_index_tree_node *entry = key; struct reftable_record - rec = { .type = BLOCK_TYPE_OBJ, + rec = { .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj = { .hash_prefix = (uint8_t *)entry->hash.buf, .hash_prefix_len = arg->w->stats.object_id_len, @@ -625,22 +623,41 @@ static void write_object_record(void *void_arg, void *key) if (arg->err < 0) goto done; + /* + * Try to add the record to the writer. If this succeeds then we're + * done. Otherwise the block writer may have hit the block size limit + * and needs to be flushed. + */ arg->err = block_writer_add(arg->w->block_writer, &rec); if (arg->err == 0) goto done; + if (arg->err != REFTABLE_ENTRY_TOO_BIG_ERROR) + goto done; + + /* + * The current block is full, so we need to flush and reinitialize the + * writer to start writing the next block. + */ arg->err = writer_flush_block(arg->w); if (arg->err < 0) goto done; - arg->err = writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ); + arg->err = writer_reinit_block_writer(arg->w, REFTABLE_BLOCK_TYPE_OBJ); if (arg->err < 0) goto done; + /* + * If this still fails then we may need to reset record's offset + * length to reduce the data size to be written. + */ arg->err = block_writer_add(arg->w->block_writer, &rec); if (arg->err == 0) goto done; + if (arg->err != REFTABLE_ENTRY_TOO_BIG_ERROR) + goto done; + rec.u.obj.offset_len = 0; arg->err = block_writer_add(arg->w->block_writer, &rec); @@ -650,7 +667,7 @@ static void write_object_record(void *void_arg, void *key) done:; } -static void object_record_free(void *void_arg UNUSED, void *key) +static void object_record_free(void *void_arg REFTABLE_UNUSED, void *key) { struct obj_index_tree_node *entry = key; @@ -671,7 +688,7 @@ static int writer_dump_object_index(struct reftable_writer *w) infix_walk(w->obj_index_tree, &update_common, &common); w->stats.object_id_len = common.max + 1; - err = writer_reinit_block_writer(w, BLOCK_TYPE_OBJ); + err = writer_reinit_block_writer(w, REFTABLE_BLOCK_TYPE_OBJ); if (err < 0) return err; @@ -695,7 +712,7 @@ static int writer_finish_public_section(struct reftable_writer *w) err = writer_finish_section(w); if (err < 0) return err; - if (typ == BLOCK_TYPE_REF && !w->opts.skip_index_objects && + if (typ == REFTABLE_BLOCK_TYPE_REF && !w->opts.skip_index_objects && w->stats.ref_stats.index_blocks > 0) { err = writer_dump_object_index(w); if (err < 0) @@ -731,19 +748,19 @@ int reftable_writer_close(struct reftable_writer *w) } p += writer_write_header(w, footer); - put_be64(p, w->stats.ref_stats.index_offset); + reftable_put_be64(p, w->stats.ref_stats.index_offset); p += 8; - put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len); + reftable_put_be64(p, (w->stats.obj_stats.offset) << 5 | w->stats.object_id_len); p += 8; - put_be64(p, w->stats.obj_stats.index_offset); + reftable_put_be64(p, w->stats.obj_stats.index_offset); p += 8; - put_be64(p, w->stats.log_stats.offset); + reftable_put_be64(p, w->stats.log_stats.offset); p += 8; - put_be64(p, w->stats.log_stats.index_offset); + reftable_put_be64(p, w->stats.log_stats.index_offset); p += 8; - put_be32(p, crc32(0, footer, p - footer)); + reftable_put_be32(p, crc32(0, footer, p - footer)); p += 4; err = w->flush(w->write_arg); @@ -800,7 +817,7 @@ static int writer_flush_nonempty_block(struct reftable_writer *w) * By default, all records except for log records are padded to the * block size. */ - if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG) + if (!w->opts.unpadded && typ != REFTABLE_BLOCK_TYPE_LOG) padding = w->opts.block_size - raw_bytes; bstats = writer_reftable_block_stats(w, typ); diff --git a/reftable/writer.h b/reftable/writer.h index 1f4788a430..9f53610b27 100644 --- a/reftable/writer.h +++ b/reftable/writer.h @@ -1,10 +1,10 @@ /* -Copyright 2020 Google LLC - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file or at -https://developers.google.com/open-source/licenses/bsd -*/ + * Copyright 2020 Google LLC + * + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file or at + * https://developers.google.com/open-source/licenses/bsd + */ #ifndef WRITER_H #define WRITER_H diff --git a/remote-curl.c b/remote-curl.c index 1273507a96..b8bc3a80cf 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -877,12 +877,12 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results) headers = curl_slist_append(headers, rpc->hdr_content_type); headers = curl_slist_append(headers, rpc->hdr_accept); - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); - curl_easy_setopt(slot->curl, CURLOPT_POST, 1); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0L); + curl_easy_setopt(slot->curl, CURLOPT_POST, 1L); curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url); curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000"); - curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4); + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4L); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &buf); @@ -970,8 +970,8 @@ retry: slot = get_active_slot(); - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); - curl_easy_setopt(slot->curl, CURLOPT_POST, 1); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0L); + curl_easy_setopt(slot->curl, CURLOPT_POST, 1L); curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url); curl_easy_setopt(slot->curl, CURLOPT_ENCODING, ""); @@ -1058,7 +1058,7 @@ retry: rpc_in_data.check_pktline = stateless_connect; memset(&rpc_in_data.pktline_state, 0, sizeof(rpc_in_data.pktline_state)); curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &rpc_in_data); - curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0L); rpc->any_written = 0; @@ -1239,7 +1239,7 @@ static int fetch_git(struct discovery *heads, packet_buf_flush(&preamble); memset(&rpc, 0, sizeof(rpc)); - rpc.service_name = "git-upload-pack", + rpc.service_name = "git-upload-pack"; rpc.gzip_request = 1; err = rpc_service(&rpc, heads, args.v, &preamble, &rpc_result); @@ -1401,7 +1401,7 @@ static int push_git(struct discovery *heads, int nr_spec, const char **specs) packet_buf_flush(&preamble); memset(&rpc, 0, sizeof(rpc)); - rpc.service_name = "git-receive-pack", + rpc.service_name = "git-receive-pack"; err = rpc_service(&rpc, heads, args.v, &preamble, &rpc_result); if (rpc_result.len) @@ -12,7 +12,7 @@ #include "refs.h" #include "refspec.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "commit.h" #include "diff.h" @@ -143,8 +143,8 @@ static struct remote *make_remote(struct remote_state *remote_state, ret->prune = -1; /* unspecified */ ret->prune_tags = -1; /* unspecified */ ret->name = xstrndup(name, len); - refspec_init(&ret->push, REFSPEC_PUSH); - refspec_init(&ret->fetch, REFSPEC_FETCH); + refspec_init_push(&ret->push); + refspec_init_fetch(&ret->fetch); string_list_init_dup(&ret->server_options); ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1, @@ -1702,7 +1702,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror, if (!reject_reason && !ref->deletion && !is_null_oid(&ref->old_oid)) { if (starts_with(ref->name, "refs/tags/")) reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS; - else if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid, OBJECT_INFO_SKIP_FETCH_OBJECT)) + else if (!has_object(the_repository, &ref->old_oid, HAS_OBJECT_RECHECK_PACKED)) reject_reason = REF_STATUS_REJECT_FETCH_FIRST; else if (!lookup_commit_reference_gently(the_repository, &ref->old_oid, 1) || !lookup_commit_reference_gently(the_repository, &ref->new_oid, 1)) @@ -2297,7 +2297,7 @@ struct ref *get_local_heads(void) struct ref *guess_remote_head(const struct ref *head, const struct ref *refs, - int all) + unsigned flags) { const struct ref *r; struct ref *list = NULL; @@ -2315,8 +2315,10 @@ struct ref *guess_remote_head(const struct ref *head, return copy_ref(find_ref_by_name(refs, head->symref)); /* If a remote branch exists with the default branch name, let's use it. */ - if (!all) { - char *default_branch = repo_default_branch_name(the_repository, 0); + if (!(flags & REMOTE_GUESS_HEAD_ALL)) { + char *default_branch = + repo_default_branch_name(the_repository, + flags & REMOTE_GUESS_HEAD_QUIET); char *ref = xstrfmt("refs/heads/%s", default_branch); r = find_ref_by_name(refs, ref); @@ -2339,7 +2341,7 @@ struct ref *guess_remote_head(const struct ref *head, oideq(&r->old_oid, &head->old_oid)) { *tail = copy_ref(r); tail = &((*tail)->next); - if (!all) + if (!(flags & REMOTE_GUESS_HEAD_ALL)) break; } } @@ -387,15 +387,18 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb, int show_divergence_advice); struct ref *get_local_heads(void); + /* * Find refs from a list which are likely to be pointed to by the given HEAD - * ref. If 'all' is false, returns the most likely ref; otherwise, returns a - * list of all candidate refs. If no match is found (or 'head' is NULL), - * returns NULL. All returns are newly allocated and should be freed. + * ref. If REMOTE_GUESS_HEAD_ALL is set, return a list of all candidate refs; + * otherwise, return the most likely ref. If no match is found (or 'head' is + * NULL), returns NULL. All returns are newly allocated and should be freed. */ +#define REMOTE_GUESS_HEAD_ALL (1 << 0) +#define REMOTE_GUESS_HEAD_QUIET (1 << 1) struct ref *guess_remote_head(const struct ref *head, const struct ref *refs, - int all); + unsigned flags); /* Return refs which no longer exist on remote */ struct ref *get_stale_heads(struct refspec *rs, struct ref *fetch_map); diff --git a/replace-object.c b/replace-object.c index 9a3cdd809a..f8c5f68837 100644 --- a/replace-object.c +++ b/replace-object.c @@ -2,7 +2,7 @@ #include "gettext.h" #include "hex.h" #include "oidmap.h" -#include "object-store-ll.h" +#include "object-store.h" #include "replace-object.h" #include "refs.h" #include "repository.h" @@ -31,7 +31,7 @@ static int register_replace_ref(const char *refname, oidcpy(&repl_obj->replacement, oid); /* Register new object */ - if (oidmap_put(r->objects->replace_map, repl_obj)) + if (oidmap_put(&r->objects->replace_map, repl_obj)) die(_("duplicate replace ref: %s"), refname); return 0; @@ -48,9 +48,7 @@ void prepare_replace_object(struct repository *r) return; } - r->objects->replace_map = - xmalloc(sizeof(*r->objects->replace_map)); - oidmap_init(r->objects->replace_map, 0); + oidmap_init(&r->objects->replace_map, 0); refs_for_each_replace_ref(get_main_ref_store(r), register_replace_ref, r); @@ -80,7 +78,7 @@ const struct object_id *do_lookup_replace_object(struct repository *r, /* Try to recursively replace the object */ while (depth-- > 0) { struct replace_object *repl_obj = - oidmap_get(r->objects->replace_map, cur); + oidmap_get(&r->objects->replace_map, cur); if (!repl_obj) return cur; cur = &repl_obj->replacement; diff --git a/replace-object.h b/replace-object.h index 66c41b938b..3052e96a62 100644 --- a/replace-object.h +++ b/replace-object.h @@ -3,7 +3,7 @@ #include "oidmap.h" #include "repository.h" -#include "object-store-ll.h" +#include "object-store.h" struct replace_object { struct oidmap_entry original; @@ -47,7 +47,7 @@ static inline const struct object_id *lookup_replace_object(struct repository *r { if (!replace_refs_enabled(r) || (r->objects->replace_map_initialized && - r->objects->replace_map->map.tablesize == 0)) + oidmap_get_size(&r->objects->replace_map) == 0)) return oid; return do_lookup_replace_object(r, oid); } diff --git a/repo-settings.c b/repo-settings.c index 67e9cfd2e6..195c24e9c0 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -20,6 +20,13 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest, *dest = def; } +static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest, + unsigned long def) +{ + if (repo_config_get_ulong(r, key, dest)) + *dest = def; +} + void prepare_repo_settings(struct repository *r) { int experimental; @@ -47,11 +54,13 @@ void prepare_repo_settings(struct repository *r) r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING; r->settings.pack_use_bitmap_boundary_traversal = 1; r->settings.pack_use_multi_pack_reuse = 1; + r->settings.pack_use_path_walk = 1; } if (manyfiles) { r->settings.index_version = 4; r->settings.index_skip_hash = 1; r->settings.core_untracked_cache = UNTRACKED_CACHE_WRITE; + r->settings.pack_use_path_walk = 1; } /* Commit graph config or default, does not cascade (simple) */ @@ -66,6 +75,7 @@ void prepare_repo_settings(struct repository *r) /* Boolean config or default, does not cascade (simple) */ repo_cfg_bool(r, "pack.usesparse", &r->settings.pack_use_sparse, 1); + repo_cfg_bool(r, "pack.usepathwalk", &r->settings.pack_use_path_walk, 0); repo_cfg_bool(r, "core.multipackindex", &r->settings.core_multi_pack_index, 1); repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 0); repo_cfg_bool(r, "index.skiphash", &r->settings.index_skip_hash, r->settings.index_skip_hash); @@ -151,6 +161,19 @@ void repo_settings_clear(struct repository *r) r->settings = empty; } +unsigned long repo_settings_get_big_file_threshold(struct repository *repo) +{ + if (!repo->settings.big_file_threshold) + repo_cfg_ulong(repo, "core.bigfilethreshold", + &repo->settings.big_file_threshold, 512 * 1024 * 1024); + return repo->settings.big_file_threshold; +} + +void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value) +{ + repo->settings.big_file_threshold = value; +} + enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo) { const char *value; diff --git a/repo-settings.h b/repo-settings.h index ddc11967e0..d477885561 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -56,6 +56,7 @@ struct repo_settings { enum untracked_cache_setting core_untracked_cache; int pack_use_sparse; + int pack_use_path_walk; enum fetch_negotiation_setting fetch_negotiation_algorithm; int core_multi_pack_index; @@ -64,6 +65,7 @@ struct repo_settings { size_t delta_base_cache_limit; size_t packed_git_window_size; size_t packed_git_limit; + unsigned long big_file_threshold; char *hooks_path; }; @@ -88,6 +90,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo); /* Read the value for "core.hooksPath". */ const char *repo_settings_get_hooks_path(struct repository *repo); +/* Read and set the value for "core.bigFileThreshold". */ +unsigned long repo_settings_get_big_file_threshold(struct repository *repo); +void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value); + /* Read, set or reset the value for "core.sharedRepository". */ int repo_settings_get_shared_repository(struct repository *repo); void repo_settings_set_shared_repository(struct repository *repo, int value); diff --git a/repository.c b/repository.c index 6cbaf2e3da..9b3d6665fc 100644 --- a/repository.c +++ b/repository.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "abspath.h" #include "repository.h" -#include "object-store-ll.h" +#include "object-store.h" #include "config.h" #include "object.h" #include "lockfile.h" @@ -18,7 +18,7 @@ #include "path.h" #include "pathspec.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "strmap.h" #define RESOLVED 0 @@ -860,7 +860,7 @@ static int do_plain_rerere(struct repository *r, string_list_insert(rr, path)->util = id; /* Ensure that the directory exists. */ - mkdir_in_gitdir(rerere_path(&buf, id, NULL)); + safe_create_dir_in_gitdir(the_repository, rerere_path(&buf, id, NULL)); } for (i = 0; i < rr->nr; i++) @@ -895,7 +895,8 @@ static int is_rerere_enabled(void) if (rerere_enabled < 0) return rr_cache_exists; - if (!rr_cache_exists && mkdir_in_gitdir(git_path_rr_cache())) + if (!rr_cache_exists && + safe_create_dir_in_gitdir(the_repository, git_path_rr_cache())) die(_("could not create directory '%s'"), git_path_rr_cache()); return 1; } @@ -80,7 +80,7 @@ static int update_refs(const struct reset_head_opts *opts, } if (!ret && run_hook) run_hooks_l(the_repository, "post-checkout", - oid_to_hex(head ? head : null_oid()), + oid_to_hex(head ? head : null_oid(the_hash_algo)), oid_to_hex(oid), "1", NULL); strbuf_release(&msg); return ret; diff --git a/revision.c b/revision.c index c4390f0938..afee111196 100644 --- a/revision.c +++ b/revision.c @@ -8,7 +8,7 @@ #include "hex.h" #include "object-name.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oidset.h" #include "tag.h" #include "blob.h" @@ -59,14 +59,6 @@ implement_shared_commit_slab(revision_sources, char *); static inline int want_ancestry(const struct rev_info *revs); -void show_object_with_name(FILE *out, struct object *obj, const char *name) -{ - fprintf(out, "%s ", oid_to_hex(&obj->oid)); - for (const char *p = name; *p && *p != '\n'; p++) - fputc(*p, out); - fputc('\n', out); -} - static void mark_blob_uninteresting(struct blob *blob) { if (!blob) @@ -2068,6 +2060,7 @@ static void prepare_show_merge(struct rev_info *revs) parse_pathspec(&revs->prune_data, PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL, PATHSPEC_PREFER_FULL | PATHSPEC_LITERAL_PATH, "", prune); revs->limited = 1; + free(prune); } static int dotdot_missing(const char *arg, char *dotdot, @@ -2488,10 +2481,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg die(_("options '%s' and '%s' cannot be used together"), "--left-only", "--right-only/--cherry"); revs->left_only = 1; + revs->limited = 1; } else if (!strcmp(arg, "--right-only")) { if (revs->left_only) die(_("options '%s' and '%s' cannot be used together"), "--right-only", "--left-only"); revs->right_only = 1; + revs->limited = 1; } else if (!strcmp(arg, "--cherry")) { if (revs->left_only) die(_("options '%s' and '%s' cannot be used together"), "--cherry", "--left-only"); @@ -3612,7 +3607,8 @@ static void set_children(struct rev_info *revs) void reset_revision_walk(void) { - clear_object_flags(SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE); + clear_object_flags(the_repository, + SEEN | ADDED | SHOWN | TOPO_WALK_EXPLORED | TOPO_WALK_INDEGREE); } static int mark_uninteresting(const struct object_id *oid, diff --git a/revision.h b/revision.h index 71e984c452..6d369cdad6 100644 --- a/revision.h +++ b/revision.h @@ -292,7 +292,6 @@ struct rev_info { struct string_list *ref_message_ids; int add_signoff; const char *extra_headers; - const char *log_reencode; const char *subject_prefix; int patch_name_max; int no_inline; @@ -489,8 +488,6 @@ void mark_parents_uninteresting(struct rev_info *revs, struct commit *commit); void mark_tree_uninteresting(struct repository *r, struct tree *tree); void mark_trees_uninteresting_sparse(struct repository *r, struct oidset *trees); -void show_object_with_name(FILE *, struct object *, const char *); - /** * Helpers to check if a reference should be excluded. */ diff --git a/run-command.c b/run-command.c index 402138b8b5..8833b23367 100644 --- a/run-command.c +++ b/run-command.c @@ -515,7 +515,13 @@ static void atfork_prepare(struct atfork_state *as) { sigset_t all; - if (sigfillset(&all)) + /* + * POSIX says sigfillset() can fail, but an overly clever + * compiler can see through the header files and decide + * it cannot fail on a particular platform it is compiling for, + * triggering -Wunreachable-code false positive. + */ + if (NOT_CONSTANT(sigfillset(&all))) die_errno("sigfillset"); #ifdef NO_PTHREADS if (sigprocmask(SIG_SETMASK, &all, &as->old)) @@ -170,6 +170,7 @@ static int set_recommended_config(int reconfigure) { "core.autoCRLF", "false" }, { "core.safeCRLF", "false" }, { "fetch.showForcedUpdates", "false" }, + { "pack.usePathWalk", "true" }, { NULL, NULL }, }; int i; @@ -209,6 +210,12 @@ static int set_recommended_config(int reconfigure) return 0; } +/** + * Enable or disable the maintenance mode for the current repository: + * + * * If 'enable' is nonzero, run 'git maintenance start'. + * * If 'enable' is zero, run 'git maintenance unregister --force'. + */ static int toggle_maintenance(int enable) { return run_git("maintenance", @@ -241,7 +248,7 @@ static int add_or_remove_enlistment(int add) static int start_fsmonitor_daemon(void) { - assert(have_fsmonitor_support()); + ASSERT(have_fsmonitor_support()); if (fsmonitor_ipc__get_state() != IPC_STATE__LISTENING) return run_git("fsmonitor--daemon", "start", NULL); @@ -251,7 +258,7 @@ static int start_fsmonitor_daemon(void) static int stop_fsmonitor_daemon(void) { - assert(have_fsmonitor_support()); + ASSERT(have_fsmonitor_support()); if (fsmonitor_ipc__get_state() == IPC_STATE__LISTENING) return run_git("fsmonitor--daemon", "stop", NULL); @@ -259,7 +266,15 @@ static int stop_fsmonitor_daemon(void) return 0; } -static int register_dir(void) +/** + * Register the current directory as a Scalar enlistment, and set the + * recommended configuration. + * + * * If 'maintenance' is non-zero, then enable background maintenance. + * * If 'maintenance' is zero, then leave background maintenance as it is + * currently configured. + */ +static int register_dir(int maintenance) { if (add_or_remove_enlistment(1)) return error(_("could not add enlistment")); @@ -267,8 +282,9 @@ static int register_dir(void) if (set_recommended_config(0)) return error(_("could not set recommended config")); - if (toggle_maintenance(1)) - warning(_("could not turn on maintenance")); + if (maintenance && + toggle_maintenance(maintenance)) + warning(_("could not toggle maintenance")); if (have_fsmonitor_support() && start_fsmonitor_daemon()) { return error(_("could not start the FSMonitor daemon")); @@ -411,7 +427,7 @@ static int cmd_clone(int argc, const char **argv) const char *branch = NULL; char *branch_to_free = NULL; int full_clone = 0, single_branch = 0, show_progress = isatty(2); - int src = 1, tags = 1; + int src = 1, tags = 1, maintenance = 1; struct option clone_options[] = { OPT_STRING('b', "branch", &branch, N_("<branch>"), N_("branch to checkout after clone")), @@ -424,11 +440,13 @@ static int cmd_clone(int argc, const char **argv) N_("create repository within 'src' directory")), OPT_BOOL(0, "tags", &tags, N_("specify if tags should be fetched during clone")), + OPT_BOOL(0, "maintenance", &maintenance, + N_("specify if background maintenance should be enabled")), OPT_END(), }; const char * const clone_usage[] = { N_("scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n" - "\t[--[no-]src] [--[no-]tags] <url> [<enlistment>]"), + "\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] <url> [<enlistment>]"), NULL }; const char *url; @@ -550,7 +568,8 @@ static int cmd_clone(int argc, const char **argv) if (res) goto cleanup; - res = register_dir(); + /* If --no-maintenance, then skip maintenance command entirely. */ + res = register_dir(maintenance); cleanup: free(branch_to_free); @@ -597,11 +616,14 @@ static int cmd_list(int argc, const char **argv UNUSED) static int cmd_register(int argc, const char **argv) { + int maintenance = 1; struct option options[] = { + OPT_BOOL(0, "maintenance", &maintenance, + N_("specify if background maintenance should be enabled")), OPT_END(), }; const char * const usage[] = { - N_("scalar register [<enlistment>]"), + N_("scalar register [--[no-]maintenance] [<enlistment>]"), NULL }; @@ -610,7 +632,8 @@ static int cmd_register(int argc, const char **argv) setup_enlistment_directory(argc, argv, usage, options, NULL); - return register_dir(); + /* If --no-maintenance, then leave maintenance as-is. */ + return register_dir(maintenance); } static int get_scalar_repos(const char *key, const char *value, @@ -646,13 +669,19 @@ static int remove_deleted_enlistment(struct strbuf *path) static int cmd_reconfigure(int argc, const char **argv) { int all = 0; + const char *maintenance_str = NULL; + int maintenance = 1; /* Enable maintenance by default. */ + struct option options[] = { OPT_BOOL('a', "all", &all, N_("reconfigure all registered enlistments")), + OPT_STRING(0, "maintenance", &maintenance_str, + N_("(enable|disable|keep)"), + N_("signal how to adjust background maintenance")), OPT_END(), }; const char * const usage[] = { - N_("scalar reconfigure [--all | <enlistment>]"), + N_("scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | <enlistment>]"), NULL }; struct string_list scalar_repos = STRING_LIST_INIT_DUP; @@ -672,6 +701,18 @@ static int cmd_reconfigure(int argc, const char **argv) usage_msg_opt(_("--all or <enlistment>, but not both"), usage, options); + if (maintenance_str) { + if (!strcmp(maintenance_str, "enable")) + maintenance = 1; + else if (!strcmp(maintenance_str, "disable")) + maintenance = 0; + else if (!strcmp(maintenance_str, "keep")) + maintenance = -1; + else + die(_("unknown mode for --maintenance option: %s"), + maintenance_str); + } + git_config(get_scalar_repos, &scalar_repos); for (size_t i = 0; i < scalar_repos.nr; i++) { @@ -736,7 +777,8 @@ static int cmd_reconfigure(int argc, const char **argv) the_repository = old_repo; repo_clear(&r); - if (toggle_maintenance(1) >= 0) + if (maintenance >= 0 && + toggle_maintenance(maintenance) >= 0) succeeded = 1; loop_end: @@ -803,13 +845,13 @@ static int cmd_run(int argc, const char **argv) strbuf_release(&buf); if (i == 0) - return register_dir(); + return register_dir(1); if (i > 0) return run_git("maintenance", "run", "--task", tasks[i].task, NULL); - if (register_dir()) + if (register_dir(1)) return -1; for (i = 1; tasks[i].arg; i++) if (run_git("maintenance", "run", diff --git a/send-pack.c b/send-pack.c index 856a65d5f5..86592ce526 100644 --- a/send-pack.c +++ b/send-pack.c @@ -4,7 +4,7 @@ #include "date.h" #include "gettext.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "pkt-line.h" #include "sideband.h" #include "run-command.h" @@ -45,10 +45,7 @@ int option_parse_push_signed(const struct option *opt, static void feed_object(struct repository *r, const struct object_id *oid, FILE *fh, int negative) { - if (negative && - !repo_has_object_file_with_flags(r, oid, - OBJECT_INFO_SKIP_FETCH_OBJECT | - OBJECT_INFO_QUICK)) + if (negative && !has_object(r, oid, 0)) return; if (negative) diff --git a/sequencer.c b/sequencer.c index ad0ab75c8d..9456ca6ee9 100644 --- a/sequencer.c +++ b/sequencer.c @@ -13,7 +13,7 @@ #include "dir.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "object.h" #include "pager.h" #include "commit.h" @@ -225,11 +225,6 @@ struct replay_ctx { */ struct strbuf current_fixups; /* - * Stores the reflog message that will be used when creating a - * commit. Points to a static buffer and should not be free()'d. - */ - const char *reflog_message; - /* * The number of completed fixup and squash commands in the * current chain. */ @@ -265,8 +260,8 @@ static struct update_ref_record *init_update_ref_record(const char *ref) CALLOC_ARRAY(rec, 1); - oidcpy(&rec->before, null_oid()); - oidcpy(&rec->after, null_oid()); + oidcpy(&rec->before, null_oid(the_hash_algo)); + oidcpy(&rec->after, null_oid(the_hash_algo)); /* This may fail, but that's fine, we will keep the null OID. */ refs_read_ref(get_main_ref_store(the_repository), ref, &rec->before); @@ -667,7 +662,7 @@ static int fast_forward_to(struct repository *r, if (!transaction || ref_transaction_update(transaction, "HEAD", to, unborn && !is_rebase_i(opts) ? - null_oid() : from, NULL, NULL, + null_oid(the_hash_algo) : from, NULL, NULL, 0, sb.buf, &err) || ref_transaction_commit(transaction, &err)) { ref_transaction_free(transaction); @@ -781,28 +776,19 @@ static int do_recursive_merge(struct repository *r, for (i = 0; i < opts->xopts.nr; i++) parse_merge_opt(&o, opts->xopts.v[i]); - if (!opts->strategy || !strcmp(opts->strategy, "ort")) { - memset(&result, 0, sizeof(result)); - merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, - &result); - show_output = !is_rebase_i(opts) || !result.clean; - /* - * TODO: merge_switch_to_result will update index/working tree; - * we only really want to do that if !result.clean || this is - * the final patch to be picked. But determining this is the - * final patch would take some work, and "head_tree" would need - * to be replace with the tree the index matched before we - * started doing any picks. - */ - merge_switch_to_result(&o, head_tree, &result, 1, show_output); - clean = result.clean; - } else { - ensure_full_index(r->index); - clean = merge_trees(&o, head_tree, next_tree, base_tree); - if (is_rebase_i(opts) && clean <= 0) - fputs(o.obuf.buf, stdout); - strbuf_release(&o.obuf); - } + memset(&result, 0, sizeof(result)); + merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, &result); + show_output = !is_rebase_i(opts) || !result.clean; + /* + * TODO: merge_switch_to_result will update index/working tree; + * we only really want to do that if !result.clean || this is + * the final patch to be picked. But determining this is the + * final patch would take some work, and "head_tree" would need + * to be replace with the tree the index matched before we + * started doing any picks. + */ + merge_switch_to_result(&o, head_tree, &result, 1, show_output); + clean = result.clean; if (clean < 0) { rollback_lock_file(&index_lock); return clean; @@ -1133,10 +1119,10 @@ static int run_command_silent_on_success(struct child_process *cmd) * author metadata. */ static int run_git_commit(const char *defmsg, + const char *reflog_action, struct replay_opts *opts, unsigned int flags) { - struct replay_ctx *ctx = opts->ctx; struct child_process cmd = CHILD_PROCESS_INIT; if ((flags & CLEANUP_MSG) && (flags & VERBATIM_MSG)) @@ -1154,7 +1140,7 @@ static int run_git_commit(const char *defmsg, gpg_opt, gpg_opt); } - strvec_pushf(&cmd.env, GIT_REFLOG_ACTION "=%s", ctx->reflog_message); + strvec_pushf(&cmd.env, GIT_REFLOG_ACTION "=%s", reflog_action); if (opts->committer_date_is_author_date) strvec_pushf(&cmd.env, "GIT_COMMITTER_DATE=%s", @@ -1301,7 +1287,7 @@ int update_head_with_reflog(const struct commit *old_head, 0, err); if (!transaction || ref_transaction_update(transaction, "HEAD", new_head, - old_head ? &old_head->object.oid : null_oid(), + old_head ? &old_head->object.oid : null_oid(the_hash_algo), NULL, NULL, 0, sb.buf, err) || ref_transaction_commit(transaction, err)) { ret = -1; @@ -1538,10 +1524,10 @@ static int parse_head(struct repository *r, struct commit **head) */ static int try_to_commit(struct repository *r, struct strbuf *msg, const char *author, + const char *reflog_action, struct replay_opts *opts, unsigned int flags, struct object_id *oid) { - struct replay_ctx *ctx = opts->ctx; struct object_id tree; struct commit *current_head = NULL; struct commit_list *parents = NULL; @@ -1703,7 +1689,7 @@ static int try_to_commit(struct repository *r, goto out; } - if (update_head_with_reflog(current_head, oid, ctx->reflog_message, + if (update_head_with_reflog(current_head, oid, reflog_action, msg, &err)) { res = error("%s", err.buf); goto out; @@ -1734,6 +1720,7 @@ static int write_rebase_head(struct object_id *oid) static int do_commit(struct repository *r, const char *msg_file, const char *author, + const char *reflog_action, struct replay_opts *opts, unsigned int flags, struct object_id *oid) { @@ -1749,7 +1736,7 @@ static int do_commit(struct repository *r, msg_file); res = try_to_commit(r, msg_file ? &sb : NULL, - author, opts, flags, &oid); + author, reflog_action, opts, flags, &oid); strbuf_release(&sb); if (!res) { refs_delete_ref(get_main_ref_store(r), "", @@ -1765,7 +1752,7 @@ static int do_commit(struct repository *r, if (is_rebase_i(opts) && oid) if (write_rebase_head(oid)) return -1; - return run_git_commit(msg_file, opts, flags); + return run_git_commit(msg_file, reflog_action, opts, flags); } return res; @@ -2080,6 +2067,9 @@ static int update_squash_messages(struct repository *r, const char *message, *body; const char *encoding = get_commit_output_encoding(); + if (!is_fixup(command)) + BUG("not a FIXUP or SQUASH %d", command); + if (ctx->current_fixup_count > 0) { struct strbuf header = STRBUF_INIT; char *eol; @@ -2147,8 +2137,7 @@ static int update_squash_messages(struct repository *r, strbuf_addstr(&buf, "\n\n"); strbuf_add_commented_lines(&buf, body, strlen(body), comment_line_str); - } else - return error(_("unknown command: %d"), command); + } repo_unuse_commit_buffer(r, commit, message); if (!res) @@ -2235,6 +2224,39 @@ static void refer_to_commit(struct replay_opts *opts, } } +static const char *sequencer_reflog_action(struct replay_opts *opts) +{ + if (!opts->reflog_action) { + opts->reflog_action = getenv(GIT_REFLOG_ACTION); + opts->reflog_action = + xstrdup(opts->reflog_action ? opts->reflog_action + : action_name(opts)); + } + + return opts->reflog_action; +} + +__attribute__((format (printf, 3, 4))) +static const char *reflog_message(struct replay_opts *opts, + const char *sub_action, const char *fmt, ...) +{ + va_list ap; + static struct strbuf buf = STRBUF_INIT; + + va_start(ap, fmt); + strbuf_reset(&buf); + strbuf_addstr(&buf, sequencer_reflog_action(opts)); + if (sub_action) + strbuf_addf(&buf, " (%s)", sub_action); + if (fmt) { + strbuf_addstr(&buf, ": "); + strbuf_vaddf(&buf, fmt, ap); + } + va_end(ap); + + return buf.buf; +} + static int do_pick_commit(struct repository *r, struct todo_item *item, struct replay_opts *opts, @@ -2245,13 +2267,19 @@ static int do_pick_commit(struct repository *r, const char *msg_file = should_edit(opts) ? NULL : git_path_merge_msg(r); struct object_id head; struct commit *base, *next, *parent; - const char *base_label, *next_label; + const char *base_label, *next_label, *reflog_action; char *author = NULL; struct commit_message msg = { NULL, NULL, NULL, NULL }; int res, unborn = 0, reword = 0, allow, drop_commit; enum todo_command command = item->command; struct commit *commit = item->commit; + if (is_rebase_i(opts)) + reflog_action = reflog_message( + opts, command_to_string(item->command), NULL); + else + reflog_action = sequencer_reflog_action(opts); + if (opts->no_commit) { /* * We do not intend to commit immediately. We just want to @@ -2503,7 +2531,8 @@ static int do_pick_commit(struct repository *r, } /* else allow == 0 and there's nothing special to do */ if (!opts->no_commit && !drop_commit) { if (author || command == TODO_REVERT || (flags & AMEND_MSG)) - res = do_commit(r, msg_file, author, opts, flags, + res = do_commit(r, msg_file, author, reflog_action, + opts, flags, commit? &commit->object.oid : NULL); else res = error(_("unable to parse commit author")); @@ -2518,7 +2547,7 @@ fast_forward_edit: * got here. */ flags = EDIT_MSG | VERIFY_MSG | AMEND_MSG | ALLOW_EMPTY; - res = run_git_commit(NULL, opts, flags); + res = run_git_commit(NULL, reflog_action, opts, flags); *check_todo = 1; } } @@ -2609,9 +2638,12 @@ static int is_command(enum todo_command command, const char **bol) const char nick = todo_command_info[command].c; const char *p = *bol; - return (skip_prefix(p, str, &p) || (nick && *p++ == nick)) && - (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || !*p) && - (*bol = p); + if ((skip_prefix(p, str, &p) || (nick && *p++ == nick)) && + (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || !*p)) { + *bol = p; + return 1; + } + return 0; } static int check_label_or_ref_arg(enum todo_command command, const char *arg) @@ -3928,39 +3960,6 @@ static int do_label(struct repository *r, const char *name, int len) return ret; } -static const char *sequencer_reflog_action(struct replay_opts *opts) -{ - if (!opts->reflog_action) { - opts->reflog_action = getenv(GIT_REFLOG_ACTION); - opts->reflog_action = - xstrdup(opts->reflog_action ? opts->reflog_action - : action_name(opts)); - } - - return opts->reflog_action; -} - -__attribute__((format (printf, 3, 4))) -static const char *reflog_message(struct replay_opts *opts, - const char *sub_action, const char *fmt, ...) -{ - va_list ap; - static struct strbuf buf = STRBUF_INIT; - - va_start(ap, fmt); - strbuf_reset(&buf); - strbuf_addstr(&buf, sequencer_reflog_action(opts)); - if (sub_action) - strbuf_addf(&buf, " (%s)", sub_action); - if (fmt) { - strbuf_addstr(&buf, ": "); - strbuf_vaddf(&buf, fmt, ap); - } - va_end(ap); - - return buf.buf; -} - static struct commit *lookup_label(struct repository *r, const char *label, int len, struct strbuf *buf) { @@ -4098,6 +4097,7 @@ static int do_merge(struct repository *r, int merge_arg_len, oneline_offset, can_fast_forward, ret, k; static struct lock_file lock; const char *p; + const char *reflog_action = reflog_message(opts, "merge", NULL); if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) { ret = -1; @@ -4328,20 +4328,13 @@ static int do_merge(struct repository *r, o.branch2 = ref_name.buf; o.buffer_output = 2; - if (!opts->strategy || !strcmp(opts->strategy, "ort")) { - /* - * TODO: Should use merge_incore_recursive() and - * merge_switch_to_result(), skipping the call to - * merge_switch_to_result() when we don't actually need to - * update the index and working copy immediately. - */ - ret = merge_ort_recursive(&o, - head_commit, merge_commit, bases, - &i); - } else { - ret = merge_recursive(&o, head_commit, merge_commit, bases, - &i); - } + /* + * TODO: Should use merge_incore_recursive() and + * merge_switch_to_result(), skipping the call to + * merge_switch_to_result() when we don't actually need to + * update the index and working copy immediately. + */ + ret = merge_ort_recursive(&o, head_commit, merge_commit, bases, &i); if (ret <= 0) fputs(o.obuf.buf, stdout); strbuf_release(&o.obuf); @@ -4352,7 +4345,7 @@ static int do_merge(struct repository *r, goto leave_merge; } /* - * The return value of merge_recursive() is 1 on clean, and 0 on + * The return value of merge_ort_recursive() is 1 on clean, and 0 on * unclean merge. * * Let's reverse that, so that do_merge() returns 0 upon success and @@ -4376,14 +4369,15 @@ static int do_merge(struct repository *r, * value (a negative one would indicate that the `merge` * command needs to be rescheduled). */ - ret = !!run_git_commit(git_path_merge_msg(r), opts, - run_commit_flags); + ret = !!run_git_commit(git_path_merge_msg(r), reflog_action, + opts, run_commit_flags); if (!ret && flags & TODO_EDIT_MERGE_MSG) { fast_forward_edit: *check_todo = 1; run_commit_flags |= AMEND_MSG | EDIT_MSG | VERIFY_MSG; - ret = !!run_git_commit(NULL, opts, run_commit_flags); + ret = !!run_git_commit(NULL, reflog_action, opts, + run_commit_flags); } @@ -4411,7 +4405,7 @@ static int write_update_refs_state(struct string_list *refs_to_oids) goto cleanup; } - if (safe_create_leading_directories(path)) { + if (safe_create_leading_directories(the_repository, path)) { result = error(_("unable to create leading directories of %s"), path); goto cleanup; @@ -4677,13 +4671,13 @@ static void create_autostash_internal(struct repository *r, strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV); if (path) { - if (safe_create_leading_directories_const(path)) + if (safe_create_leading_directories_const(the_repository, path)) die(_("Could not create directory for '%s'"), path); write_file(path, "%s", oid_to_hex(&oid)); } else { refs_update_ref(get_main_ref_store(r), "", refname, - &oid, null_oid(), 0, UPDATE_REFS_DIE_ON_ERR); + &oid, null_oid(the_hash_algo), 0, UPDATE_REFS_DIE_ON_ERR); } printf(_("Created autostash: %s\n"), buf.buf); @@ -4898,13 +4892,9 @@ static int pick_one_commit(struct repository *r, struct replay_opts *opts, int *check_todo, int* reschedule) { - struct replay_ctx *ctx = opts->ctx; int res; struct todo_item *item = todo_list->items + todo_list->current; const char *arg = todo_item_get_arg(todo_list, item); - if (is_rebase_i(opts)) - ctx->reflog_message = reflog_message( - opts, command_to_string(item->command), NULL); res = do_pick_commit(r, item, opts, is_final_fixup(todo_list), check_todo); @@ -4963,9 +4953,8 @@ static int pick_commits(struct repository *r, struct replay_ctx *ctx = opts->ctx; int res = 0, reschedule = 0; - ctx->reflog_message = sequencer_reflog_action(opts); if (opts->allow_ff) - assert(!(opts->signoff || opts->no_commit || + ASSERT(!(opts->signoff || opts->no_commit || opts->record_origin || should_edit(opts) || opts->committer_date_is_author_date || opts->ignore_date)); @@ -5224,6 +5213,7 @@ static int commit_staged_changes(struct repository *r, unsigned int flags = ALLOW_EMPTY | EDIT_MSG; unsigned int final_fixup = 0, is_clean; struct strbuf rev = STRBUF_INIT; + const char *reflog_action = reflog_message(opts, "continue", NULL); int ret; if (has_unstaged_changes(r, 1)) { @@ -5386,7 +5376,7 @@ static int commit_staged_changes(struct repository *r, } if (run_git_commit(final_fixup ? NULL : rebase_path_message(), - opts, flags)) { + reflog_action, opts, flags)) { ret = error(_("could not commit staged changes.")); goto out; } @@ -5418,7 +5408,6 @@ out: int sequencer_continue(struct repository *r, struct replay_opts *opts) { - struct replay_ctx *ctx = opts->ctx; struct todo_list todo_list = TODO_LIST_INIT; int res; @@ -5439,7 +5428,6 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts) unlink(rebase_path_dropped()); } - ctx->reflog_message = reflog_message(opts, "continue", NULL); if (commit_staged_changes(r, opts, &todo_list)) { res = -1; goto release_todo_list; @@ -5491,7 +5479,6 @@ static int single_pick(struct repository *r, TODO_PICK : TODO_REVERT; item.commit = cmit; - opts->ctx->reflog_message = sequencer_reflog_action(opts); return do_pick_commit(r, &item, opts, 0, &check_todo); } @@ -5917,11 +5904,11 @@ static int make_script_with_merges(struct pretty_print_context *pp, /* Create a label from the commit message */ strbuf_reset(&label_from_message); - if (skip_prefix(oneline.buf, "Merge ", &p1) && + if (skip_prefix(oneline.buf, "# Merge ", &p1) && (p1 = strchr(p1, '\'')) && (p2 = strchr(++p1, '\''))) strbuf_add(&label_from_message, p1, p2 - p1); - else if (skip_prefix(oneline.buf, "Merge pull request ", + else if (skip_prefix(oneline.buf, "# Merge pull request ", &p1) && (p1 = strstr(p1, " from "))) strbuf_addstr(&label_from_message, p1 + strlen(" from ")); @@ -5956,7 +5943,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, strbuf_addstr(&buf, label_oid(oid, label, &state)); } - strbuf_addf(&buf, " # %s", oneline.buf); + strbuf_addf(&buf, " %s", oneline.buf); FLEX_ALLOC_STR(entry, string, buf.buf); oidcpy(&entry->entry.oid, &commit->object.oid); @@ -6038,7 +6025,7 @@ static int make_script_with_merges(struct pretty_print_context *pp, else { strbuf_reset(&oneline); pretty_print_commit(pp, commit, &oneline); - strbuf_addf(out, "%s %s # %s\n", + strbuf_addf(out, "%s %s %s\n", cmd_reset, to, oneline.buf); } } @@ -6069,8 +6056,8 @@ static int make_script_with_merges(struct pretty_print_context *pp, oidset_clear(&interesting); oidset_clear(&child_seen); oidset_clear(&shown); - oidmap_free(&commit2todo, 1); - oidmap_free(&state.commit2label, 1); + oidmap_clear(&commit2todo, 1); + oidmap_clear(&state.commit2label, 1); hashmap_clear_and_free(&state.labels, struct labels_entry, entry); strbuf_release(&state.buf); @@ -6106,8 +6093,14 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc, git_config_get_string("rebase.instructionFormat", &format); if (!format || !*format) { free(format); - format = xstrdup("%s"); + format = xstrdup("# %s"); + } + if (*format != '#') { + char *temp = format; + format = xstrfmt("# %s", temp); + free(temp); } + get_commit_format(format, &revs); free(format); pp.fmt = revs.commit_format; @@ -6612,6 +6605,7 @@ int todo_list_rearrange_squash(struct todo_list *todo_list) char **subjects; struct commit_todo_item commit_todo; struct todo_item *items = NULL; + int ret = 0; init_commit_todo_item(&commit_todo); /* @@ -6642,8 +6636,8 @@ int todo_list_rearrange_squash(struct todo_list *todo_list) } if (is_fixup(item->command)) { - clear_commit_todo_item(&commit_todo); - return error(_("the script was already rearranged.")); + ret = error(_("the script was already rearranged.")); + goto cleanup; } repo_parse_commit(the_repository, item->commit); @@ -6745,6 +6739,7 @@ int todo_list_rearrange_squash(struct todo_list *todo_list) todo_list->items = items; } +cleanup: free(next); free(tail); for (i = 0; i < todo_list->nr; i++) @@ -6754,7 +6749,7 @@ int todo_list_rearrange_squash(struct todo_list *todo_list) clear_commit_todo_item(&commit_todo); - return 0; + return ret; } int sequencer_determine_whence(struct repository *r, enum commit_whence *whence) diff --git a/server-info.c b/server-info.c index 1ca0e00d51..d6cd20a39d 100644 --- a/server-info.c +++ b/server-info.c @@ -11,7 +11,7 @@ #include "packfile.h" #include "path.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "server-info.h" #include "strbuf.h" #include "tempfile.h" @@ -88,7 +88,7 @@ static int update_info_file(struct repository *r, char *path, .old_sb = STRBUF_INIT }; - safe_create_leading_directories(path); + safe_create_leading_directories(r, path); f = mks_tempfile_m(tmp, 0666); if (!f) goto out; @@ -5,7 +5,7 @@ #include "repository.h" #include "tempfile.h" #include "lockfile.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "tag.h" #include "pkt-line.h" @@ -226,7 +226,7 @@ struct commit_list *get_shallow_commits_by_rev_list(int ac, const char **av, * SHALLOW (excluded) and NOT_SHALLOW (included) should not be * set at this point. But better be safe than sorry. */ - clear_object_flags(both_flags); + clear_object_flags(the_repository, both_flags); is_repository_shallow(the_repository); /* make sure shallows are read */ @@ -310,7 +310,8 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data) if (graft->nr_parent != -1) return 0; if (data->flags & QUICK) { - if (!repo_has_object_file(the_repository, &graft->oid)) + if (!has_object(the_repository, &graft->oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return 0; } else if (data->flags & SEEN_ONLY) { struct commit *c = lookup_commit(the_repository, &graft->oid); @@ -476,7 +477,8 @@ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa) ALLOC_ARRAY(info->ours, sa->nr); ALLOC_ARRAY(info->theirs, sa->nr); for (size_t i = 0; i < sa->nr; i++) { - if (repo_has_object_file(the_repository, sa->oid + i)) { + if (has_object(the_repository, sa->oid + i, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { struct commit_graft *graft; graft = lookup_commit_graft(the_repository, &sa->oid[i]); @@ -513,7 +515,8 @@ void remove_nonexistent_theirs_shallow(struct shallow_info *info) for (i = dst = 0; i < info->nr_theirs; i++) { if (i != dst) info->theirs[dst] = info->theirs[i]; - if (repo_has_object_file(the_repository, oid + info->theirs[i])) + if (has_object(the_repository, oid + info->theirs[i], + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) dst++; } info->nr_theirs = dst; @@ -613,9 +616,9 @@ static void paint_down(struct paint_info *info, const struct object_id *oid, } } - nr = get_max_object_index(); + nr = get_max_object_index(the_repository); for (i = 0; i < nr; i++) { - struct object *o = get_indexed_object(i); + struct object *o = get_indexed_object(the_repository, i); if (o && o->type == OBJ_COMMIT) o->flags &= ~SEEN; } @@ -675,9 +678,9 @@ void assign_shallow_commits_to_refs(struct shallow_info *info, * Prepare the commit graph to track what refs can reach what * (new) shallow commits. */ - nr = get_max_object_index(); + nr = get_max_object_index(the_repository); for (i = 0; i < nr; i++) { - struct object *o = get_indexed_object(i); + struct object *o = get_indexed_object(the_repository, i); if (!o || o->type != OBJ_COMMIT) continue; diff --git a/streaming.c b/streaming.c index 38839511af..6d6512e2e0 100644 --- a/streaming.c +++ b/streaming.c @@ -10,7 +10,7 @@ #include "streaming.h" #include "repository.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "replace-object.h" #include "packfile.h" @@ -238,7 +238,7 @@ static int open_istream_loose(struct git_istream *st, struct repository *r, return -1; switch (unpack_loose_header(&st->z, st->u.loose.mapped, st->u.loose.mapsize, st->u.loose.hdr, - sizeof(st->u.loose.hdr), NULL)) { + sizeof(st->u.loose.hdr))) { case ULHR_OK: break; case ULHR_BAD: @@ -431,7 +431,8 @@ static int istream_source(struct git_istream *st, st->open = open_istream_loose; return 0; case OI_PACKED: - if (!oi.u.packed.is_delta && big_file_threshold < size) { + if (!oi.u.packed.is_delta && + repo_settings_get_big_file_threshold(the_repository) < size) { st->u.in_pack.pack = oi.u.packed.pack; st->u.in_pack.pos = oi.u.packed.offset; st->open = open_istream_pack_non_delta; diff --git a/sub-process.h b/sub-process.h index 6a61638a8a..bfc3959a1b 100644 --- a/sub-process.h +++ b/sub-process.h @@ -73,7 +73,7 @@ static inline struct child_process *subprocess_get_child_process( /* * Perform the version and capability negotiation as described in the - * "Handshake" section of long-running-process-protocol.txt using the + * "Handshake" section of long-running-process-protocol.adoc using the * given requested versions and capabilities. The "versions" and "capabilities" * parameters are arrays terminated by a 0 or blank struct. * diff --git a/submodule-config.c b/submodule-config.c index a25059ed7f..8630e27947 100644 --- a/submodule-config.c +++ b/submodule-config.c @@ -13,7 +13,7 @@ #include "submodule.h" #include "strbuf.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "parse-options.h" #include "thread-utils.h" #include "tree-walk.h" @@ -831,7 +831,7 @@ static int gitmodules_cb(const char *var, const char *value, parameter.cache = repo->submodule_cache; parameter.treeish_name = NULL; - parameter.gitmodules_oid = null_oid(); + parameter.gitmodules_oid = null_oid(the_hash_algo); parameter.overwrite = 1; return parse_config(var, value, ctx, ¶meter); diff --git a/submodule.c b/submodule.c index 0530e8cf24..ead3fb5dad 100644 --- a/submodule.c +++ b/submodule.c @@ -27,7 +27,7 @@ #include "parse-options.h" #include "object-file.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit-reach.h" #include "read-cache-ll.h" #include "setup.h" @@ -124,7 +124,7 @@ int update_path_in_gitmodules(const char *oldpath, const char *newpath) if (is_gitmodules_unmerged(the_repository->index)) die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first")); - submodule = submodule_from_path(the_repository, null_oid(), oldpath); + submodule = submodule_from_path(the_repository, null_oid(the_hash_algo), oldpath); if (!submodule || !submodule->name) { warning(_("Could not find section in .gitmodules where path=%s"), oldpath); return -1; @@ -153,7 +153,7 @@ int remove_path_from_gitmodules(const char *path) if (is_gitmodules_unmerged(the_repository->index)) die(_("Cannot change unmerged .gitmodules, resolve merge conflicts first")); - submodule = submodule_from_path(the_repository, null_oid(), path); + submodule = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!submodule || !submodule->name) { warning(_("Could not find section in .gitmodules where path=%s"), path); return -1; @@ -204,7 +204,7 @@ void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt, const char *path) { const struct submodule *submodule = submodule_from_path(the_repository, - null_oid(), + null_oid(the_hash_algo), path); if (submodule) { const char *ignore; @@ -312,7 +312,7 @@ int is_tree_submodule_active(struct repository *repo, int is_submodule_active(struct repository *repo, const char *path) { - return is_tree_submodule_active(repo, null_oid(), path); + return is_tree_submodule_active(repo, null_oid(the_hash_algo), path); } int is_submodule_populated_gently(const char *path, int *return_error_code) @@ -778,7 +778,7 @@ const struct submodule *submodule_from_ce(const struct cache_entry *ce) if (!should_update_submodules()) return NULL; - return submodule_from_path(the_repository, null_oid(), ce->name); + return submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name); } @@ -1062,7 +1062,7 @@ static int submodule_needs_pushing(struct repository *r, const char *path, struct oid_array *commits) { - if (!submodule_has_commits(r, path, null_oid(), commits)) + if (!submodule_has_commits(r, path, null_oid(the_hash_algo), commits)) /* * NOTE: We do consider it safe to return "no" here. The * correct answer would be "We do not know" instead of @@ -1126,7 +1126,7 @@ int find_unpushed_submodules(struct repository *r, const struct submodule *submodule; const char *path = NULL; - submodule = submodule_from_name(r, null_oid(), name->string); + submodule = submodule_from_name(r, null_oid(the_hash_algo), name->string); if (submodule) path = submodule->path; else @@ -1351,7 +1351,7 @@ static void calculate_changed_submodule_paths(struct repository *r, const struct submodule *submodule; const char *path = NULL; - submodule = submodule_from_name(r, null_oid(), name->string); + submodule = submodule_from_name(r, null_oid(the_hash_algo), name->string); if (submodule) path = submodule->path; else @@ -1360,7 +1360,7 @@ static void calculate_changed_submodule_paths(struct repository *r, if (!path) continue; - if (submodule_has_commits(r, path, null_oid(), &cs_data->new_commits)) { + if (submodule_has_commits(r, path, null_oid(the_hash_algo), &cs_data->new_commits)) { changed_submodule_data_clear(cs_data); *name->string = '\0'; } @@ -1602,7 +1602,7 @@ get_fetch_task_from_index(struct submodule_parallel_fetch *spf, if (!S_ISGITLINK(ce->ce_mode)) continue; - task = fetch_task_create(spf, ce->name, null_oid()); + task = fetch_task_create(spf, ce->name, null_oid(the_hash_algo)); if (!task) continue; @@ -2166,7 +2166,7 @@ int submodule_move_head(const char *path, const char *super_prefix, if (old_head && !is_submodule_populated_gently(path, error_code_ptr)) return 0; - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) BUG("could not get submodule information for '%s'", path); @@ -2376,7 +2376,7 @@ static void relocate_single_git_dir_into_superproject(const char *path, real_old_git_dir = real_pathdup(old_git_dir, 1); - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) die(_("could not lookup name for submodule '%s'"), path); @@ -2384,7 +2384,7 @@ static void relocate_single_git_dir_into_superproject(const char *path, if (validate_submodule_git_dir(new_gitdir.buf, sub->name) < 0) die(_("refusing to move '%s' into an existing git dir"), real_old_git_dir); - if (safe_create_leading_directories_const(new_gitdir.buf) < 0) + if (safe_create_leading_directories_const(the_repository, new_gitdir.buf) < 0) die(_("could not create directory '%s'"), new_gitdir.buf); real_new_git_dir = real_pathdup(new_gitdir.buf, 1); @@ -2462,7 +2462,7 @@ void absorb_git_dir_into_superproject(const char *path, * superproject did not rewrite the git file links yet, * fix it now. */ - sub = submodule_from_path(the_repository, null_oid(), path); + sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path); if (!sub) die(_("could not lookup name for submodule '%s'"), path); submodule_name_to_gitdir(&sub_gitdir, the_repository, sub->name); @@ -2594,7 +2594,7 @@ int submodule_to_gitdir(struct repository *repo, strbuf_addstr(buf, git_dir); } if (!is_git_directory(buf->buf)) { - sub = submodule_from_path(repo, null_oid(), submodule); + sub = submodule_from_path(repo, null_oid(the_hash_algo), submodule); if (!sub) { ret = -1; goto cleanup; diff --git a/t/Makefile b/t/Makefile index 2994eb5fa9..791e0a0978 100644 --- a/t/Makefile +++ b/t/Makefile @@ -59,16 +59,21 @@ CHAINLINTSUPPRESS = GIT_TEST_EXT_CHAIN_LINT=0 && export GIT_TEST_EXT_CHAIN_LINT all:: $(DEFAULT_TEST_TARGET) -test: pre-clean check-chainlint check-meson $(TEST_LINT) +test: pre-clean check-meson $(TEST_LINT) $(CHAINLINTSUPPRESS) $(MAKE) aggregate-results-and-cleanup +ifneq ($(PERL_PATH),) +test: check-chainlint +prove: check-chainlint +endif + failed: @failed=$$(cd '$(TEST_RESULTS_DIRECTORY_SQ)' && \ grep -l '^failed [1-9]' *.counts | \ sed -n 's/\.counts$$/.sh/p') && \ test -z "$$failed" || $(MAKE) $$failed -prove: pre-clean check-chainlint $(TEST_LINT) +prove: pre-clean $(TEST_LINT) @echo "*** prove (shell & unit tests) ***" @$(CHAINLINTSUPPRESS) TEST_OPTIONS='$(GIT_TEST_OPTS)' TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS) $(MAKE) clean-except-prove-cache @@ -132,8 +137,13 @@ check-meson: fi; \ done -test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \ +test-lint: test-lint-duplicates test-lint-executable \ test-lint-filenames +ifneq ($(PERL_PATH),) +test-lint: test-lint-shell-syntax +else +GIT_TEST_CHAIN_LINT = 0 +endif ifneq ($(GIT_TEST_CHAIN_LINT),0) test-lint: test-chainlint endif @@ -415,6 +415,10 @@ GIT_TEST_PACK_SPARSE=<boolean> if disabled will default the pack-objects builtin to use the non-sparse object walk. This can still be overridden by the --sparse command-line argument. +GIT_TEST_PACK_PATH_WALK=<boolean> if enabled will default the pack-objects +builtin to use the path-walk API for the object walk. This can still be +overridden by the --no-path-walk command-line argument. + GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path by overriding the minimum number of cache entries required per thread. @@ -818,7 +822,7 @@ Skipping tests -------------- If you need to skip tests you should do so by using the three-arg form -of the test_* functions (see the "Test harness library" section +of the test_expect_* functions (see the "Test harness library" section below), e.g.: test_expect_success PERL 'I need Perl' ' @@ -965,6 +969,29 @@ see test-lib-functions.sh for the full list and their options. test_done fi + - test_lazy_prereq <prereq> <script> + + Declare the way to determine if a test prerequisite <prereq> is + satisified or not, but delay the actual determination until the + prerequisite is actually used by "test_have_prereq" or the + three-arg form of the test_expect_* functions. For example, this + is how the SYMLINKS prerequisite is declared to see if the platform + supports symbolic links: + + test_lazy_prereq SYMLINKS ' + ln -s x y && test -h y + ' + + The script is lazily invoked when SYMLINKS prerequisite is first + queried by either "test_have_prereq SYMLINKS" or "test_expect_* + SYMLINKS ...". The script is run in a temporary directory inside + a subshell, so you do not have to worry about removing temporary + files you create there. When the script exits with status 0, the + prerequisite is set. Exiting with non-zero status other than 125 + makes the prerequisite unsatisified. Exiting the script with 125 + signals a programming error and is used to mark a prerequisite that + should not be used by test scripts. + - test_expect_code <exit-code> <command> Run a command and ensure that it exits with the given exit code. diff --git a/t/helper/meson.build b/t/helper/meson.build index d2cabaa2bc..675e64c010 100644 --- a/t/helper/meson.build +++ b/t/helper/meson.build @@ -36,6 +36,7 @@ test_tool_sources = [ 'test-mktemp.c', 'test-name-hash.c', 'test-online-cpus.c', + 'test-pack-deltas.c', 'test-pack-mtimes.c', 'test-parse-options.c', 'test-parse-pathspec-file.c', @@ -76,6 +77,7 @@ test_tool_sources = [ 'test-windows-named-pipe.c', 'test-write-cache.c', 'test-xml-encode.c', + 'test-zlib.c', ] test_tool = executable('test-tool', diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c index 14e075c1a1..9aa2c5a592 100644 --- a/t/helper/test-bloom.c +++ b/t/helper/test-bloom.c @@ -44,7 +44,7 @@ static void get_bloom_filter_for_commit(const struct object_id *commit_oid) print_bloom_filter(filter); } -static const char *bloom_usage = "\n" +static const char *const bloom_usage = "\n" " test-tool bloom get_murmur3 <string>\n" " test-tool bloom get_murmur3_seven_highbit\n" " test-tool bloom generate_filter <string> [<string>...]\n" diff --git a/t/helper/test-date.c b/t/helper/test-date.c index f25512de9a..87d2ad6fca 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -2,7 +2,7 @@ #include "date.h" #include "trace.h" -static const char *usage_msg = "\n" +static const char *const usage_msg = "\n" " test-tool date relative [time_t]...\n" " test-tool date human [time_t]...\n" " test-tool date show:<format> [time_t]...\n" diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c index 6b297bd753..8d46e8ba40 100644 --- a/t/helper/test-dir-iterator.c +++ b/t/helper/test-dir-iterator.c @@ -53,6 +53,7 @@ int cmd__dir_iterator(int argc, const char **argv) printf("(%s) [%s] %s\n", diter->relative_path, diter->basename, diter->path.buf); } + dir_iterator_free(diter); if (iter_status != ITER_DONE) { printf("dir_iterator_advance failure\n"); diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c index 85a69a4e55..76c2f4eba8 100644 --- a/t/helper/test-find-pack.c +++ b/t/helper/test-find-pack.c @@ -15,7 +15,7 @@ * packfiles containing the object is not <n>. */ -static const char *find_pack_usage[] = { +static const char *const find_pack_usage[] = { "test-tool find-pack [--check-count <n>] <object>", NULL }; diff --git a/t/helper/test-getcwd.c b/t/helper/test-getcwd.c index d680038a78..cd4d424079 100644 --- a/t/helper/test-getcwd.c +++ b/t/helper/test-getcwd.c @@ -2,7 +2,7 @@ #include "git-compat-util.h" #include "parse-options.h" -static const char *getcwd_usage[] = { +static const char *const getcwd_usage[] = { "test-tool getcwd", NULL }; diff --git a/t/helper/test-pack-deltas.c b/t/helper/test-pack-deltas.c new file mode 100644 index 0000000000..4caa024b1e --- /dev/null +++ b/t/helper/test-pack-deltas.c @@ -0,0 +1,148 @@ +#define USE_THE_REPOSITORY_VARIABLE + +#include "test-tool.h" +#include "git-compat-util.h" +#include "delta.h" +#include "git-zlib.h" +#include "hash.h" +#include "hex.h" +#include "pack.h" +#include "pack-objects.h" +#include "parse-options.h" +#include "setup.h" +#include "strbuf.h" +#include "string-list.h" + +static const char *usage_str[] = { + "test-tool pack-deltas --num-objects <num-objects>", + NULL +}; + +static unsigned long do_compress(void **pptr, unsigned long size) +{ + git_zstream stream; + void *in, *out; + unsigned long maxsize; + + git_deflate_init(&stream, 1); + maxsize = git_deflate_bound(&stream, size); + + in = *pptr; + out = xmalloc(maxsize); + *pptr = out; + + stream.next_in = in; + stream.avail_in = size; + stream.next_out = out; + stream.avail_out = maxsize; + while (git_deflate(&stream, Z_FINISH) == Z_OK) + ; /* nothing */ + git_deflate_end(&stream); + + free(in); + return stream.total_out; +} + +static void write_ref_delta(struct hashfile *f, + struct object_id *oid, + struct object_id *base) +{ + unsigned char header[MAX_PACK_OBJECT_HEADER]; + unsigned long size, base_size, delta_size, compressed_size, hdrlen; + enum object_type type; + void *base_buf, *delta_buf; + void *buf = repo_read_object_file(the_repository, + oid, &type, + &size); + + if (!buf) + die("unable to read %s", oid_to_hex(oid)); + + base_buf = repo_read_object_file(the_repository, + base, &type, + &base_size); + + if (!base_buf) + die("unable to read %s", oid_to_hex(base)); + + delta_buf = diff_delta(base_buf, base_size, + buf, size, &delta_size, 0); + + compressed_size = do_compress(&delta_buf, delta_size); + + hdrlen = encode_in_pack_object_header(header, sizeof(header), + OBJ_REF_DELTA, delta_size); + hashwrite(f, header, hdrlen); + hashwrite(f, base->hash, the_repository->hash_algo->rawsz); + hashwrite(f, delta_buf, compressed_size); + + free(buf); + free(base_buf); + free(delta_buf); +} + +int cmd__pack_deltas(int argc, const char **argv) +{ + int num_objects = -1; + struct hashfile *f; + struct strbuf line = STRBUF_INIT; + struct option options[] = { + OPT_INTEGER('n', "num-objects", &num_objects, N_("the number of objects to write")), + OPT_END() + }; + + argc = parse_options(argc, argv, NULL, + options, usage_str, 0); + + if (argc || num_objects < 0) + usage_with_options(usage_str, options); + + setup_git_directory(); + + f = hashfd(the_repository->hash_algo, 1, "<stdout>"); + write_pack_header(f, num_objects); + + /* Read each line from stdin into 'line' */ + while (strbuf_getline_lf(&line, stdin) != EOF) { + const char *type_str, *content_oid_str, *base_oid_str = NULL; + struct object_id content_oid, base_oid; + struct string_list items = STRING_LIST_INIT_NODUP; + /* + * Tokenize into two or three parts: + * 1. REF_DELTA, OFS_DELTA, or FULL. + * 2. The object ID for the content object. + * 3. The object ID for the base object (optional). + */ + if (string_list_split_in_place(&items, line.buf, " ", 3) < 0) + die("invalid input format: %s", line.buf); + + if (items.nr < 2) + die("invalid input format: %s", line.buf); + + type_str = items.items[0].string; + content_oid_str = items.items[1].string; + + if (get_oid_hex(content_oid_str, &content_oid)) + die("invalid object: %s", content_oid_str); + if (items.nr >= 3) { + base_oid_str = items.items[2].string; + if (get_oid_hex(base_oid_str, &base_oid)) + die("invalid object: %s", base_oid_str); + } + string_list_clear(&items, 0); + + if (!strcmp(type_str, "REF_DELTA")) + write_ref_delta(f, &content_oid, &base_oid); + else if (!strcmp(type_str, "OFS_DELTA")) + die("OFS_DELTA not implemented"); + else if (!strcmp(type_str, "FULL")) + die("FULL not implemented"); + else + die("unknown pack type: %s", type_str); + } + + finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK, + CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); + strbuf_release(&line); + return 0; +} diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c index f8f9afbb5b..fdf1b13437 100644 --- a/t/helper/test-pack-mtimes.c +++ b/t/helper/test-pack-mtimes.c @@ -3,7 +3,7 @@ #include "test-tool.h" #include "hex.h" #include "strbuf.h" -#include "object-store-ll.h" +#include "object-store.h" #include "packfile.h" #include "pack-mtimes.h" #include "setup.h" @@ -24,7 +24,7 @@ static void dump_mtimes(struct packed_git *p) } } -static const char *pack_mtimes_usage = "\n" +static const char *const pack_mtimes_usage = "\n" " test-tool pack-mtimes <pack-name.mtimes>"; int cmd__pack_mtimes(int argc, const char **argv) diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index bfe45ec68b..f2663dd0c0 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -6,7 +6,7 @@ static int boolean = 0; static int integer = 0; -static unsigned long magnitude = 0; +static unsigned long unsigned_integer = 0; static timestamp_t timestamp; static int abbrev = 7; static int verbose = -1; /* unspecified */ @@ -120,20 +120,31 @@ int cmd__parse_options(int argc, const char **argv) }; struct string_list expect = STRING_LIST_INIT_NODUP; struct string_list list = STRING_LIST_INIT_NODUP; + uint16_t u16 = 0; + int16_t i16 = 0; struct option options[] = { OPT_BOOL(0, "yes", &boolean, "get a boolean"), OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"), - { OPTION_SET_INT, 'B', "no-fear", &boolean, NULL, - "be brave", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 }, + { + .type = OPTION_SET_INT, + .short_name = 'B', + .long_name = "no-fear", + .value = &boolean, + .help = "be brave", + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + .defval = 1, + }, OPT_COUNTUP('b', "boolean", &boolean, "increment by one"), OPT_BIT('4', "or4", &boolean, "bitwise-or boolean with ...0100", 4), OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4), OPT_GROUP(""), OPT_INTEGER('i', "integer", &integer, "get a integer"), + OPT_INTEGER(0, "i16", &i16, "get a 16 bit integer"), OPT_INTEGER('j', NULL, &integer, "get a integer, too"), - OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"), + OPT_UNSIGNED('u', "unsigned", &unsigned_integer, "get an unsigned integer"), + OPT_UNSIGNED(0, "u16", &u16, "get a 16 bit unsigned integer"), OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23), OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1), OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2), @@ -155,12 +166,27 @@ int cmd__parse_options(int argc, const char **argv) OPT_GROUP("Magic arguments"), OPT_NUMBER_CALLBACK(&integer, "set integer to NUM", number_callback), - { OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b", - PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH }, - { OPTION_COUNTUP, 0, "ambiguous", &ambiguous, NULL, - "positive ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, - { OPTION_COUNTUP, 0, "no-ambiguous", &ambiguous, NULL, - "negative ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG }, + { + .type = OPTION_COUNTUP, + .short_name = '+', + .value = &boolean, + .help = "same as -b", + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH, + }, + { + .type = OPTION_COUNTUP, + .long_name = "ambiguous", + .value = &ambiguous, + .help = "positive ambiguity", + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + }, + { + .type = OPTION_COUNTUP, + .long_name = "no-ambiguous", + .value = &ambiguous, + .help = "negative ambiguity", + .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, + }, OPT_GROUP("Standard options"), OPT__ABBREV(&abbrev), OPT__VERBOSE(&verbose, "be verbose"), @@ -188,7 +214,9 @@ int cmd__parse_options(int argc, const char **argv) } show(&expect, &ret, "boolean: %d", boolean); show(&expect, &ret, "integer: %d", integer); - show(&expect, &ret, "magnitude: %lu", magnitude); + show(&expect, &ret, "i16: %"PRIdMAX, (intmax_t) i16); + show(&expect, &ret, "unsigned: %lu", unsigned_integer); + show(&expect, &ret, "u16: %"PRIuMAX, (uintmax_t) u16); show(&expect, &ret, "timestamp: %"PRItime, timestamp); show(&expect, &ret, "string: %s", string ? string : "(not set)"); show(&expect, &ret, "abbrev: %d", abbrev); diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c index a1af9710c3..34f1aee558 100644 --- a/t/helper/test-partial-clone.c +++ b/t/helper/test-partial-clone.c @@ -1,7 +1,7 @@ #include "test-tool.h" #include "hex.h" #include "repository.h" -#include "object-store-ll.h" +#include "object-store.h" #include "setup.h" /* diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index 72ac8d1b1b..086238c826 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -323,6 +323,19 @@ int cmd__path_utils(int argc, const char **argv) return 0; } + if (argc >= 2 && !strcmp(argv[1], "readlink")) { + struct strbuf target = STRBUF_INIT; + while (argc > 2) { + if (strbuf_readlink(&target, argv[2], 0) < 0) + die_errno("cannot read link at '%s'", argv[2]); + puts(target.buf); + argc--; + argv++; + } + strbuf_release(&target); + return 0; + } + if (argc >= 2 && !strcmp(argv[1], "absolute_path")) { while (argc > 2) { puts(absolute_path(argv[2])); @@ -504,6 +517,25 @@ int cmd__path_utils(int argc, const char **argv) return !!res; } + if (argc > 1 && !strcmp(argv[1], "is_path_owned_by_current_user")) { + int res = 0; + + for (int i = 2; i < argc; i++) { + struct strbuf buf = STRBUF_INIT; + + if (is_path_owned_by_current_user(argv[i], &buf)) + printf("'%s' is owned by current SID\n", argv[i]); + else { + printf("'%s' is not owned by current SID: %s\n", argv[i], buf.buf); + res = 1; + } + + strbuf_release(&buf); + } + + return res; + } + fprintf(stderr, "%s: unknown function name: %s\n", argv[0], argv[1] ? argv[1] : "(there was none)"); return 1; diff --git a/t/helper/test-path-walk.c b/t/helper/test-path-walk.c index 61e845e5ec..fe63002c2b 100644 --- a/t/helper/test-path-walk.c +++ b/t/helper/test-path-walk.c @@ -82,6 +82,8 @@ int cmd__path_walk(int argc, const char **argv) N_("toggle inclusion of tree objects")), OPT_BOOL(0, "prune", &info.prune_all_uninteresting, N_("toggle pruning of uninteresting paths")), + OPT_BOOL(0, "edge-aggressive", &info.edge_aggressive, + N_("toggle aggressive edge walk")), OPT_BOOL(0, "stdin-pl", &stdin_pl, N_("read a pattern list over stdin")), OPT_END(), diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c index 3703f734f3..8eccc34216 100644 --- a/t/helper/test-proc-receive.c +++ b/t/helper/test-proc-receive.c @@ -6,7 +6,7 @@ #include "sigchain.h" #include "string-list.h" -static const char *proc_receive_usage[] = { +static const char *const proc_receive_usage[] = { "test-tool proc-receive [<options>]", NULL }; diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index 811dde1cb3..8b413b644b 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -3,7 +3,7 @@ #include "test-tool.h" #include "commit-graph.h" #include "repository.h" -#include "object-store-ll.h" +#include "object-store.h" #include "bloom.h" #include "setup.h" diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c index fc63236961..ac81390899 100644 --- a/t/helper/test-read-midx.c +++ b/t/helper/test-read-midx.c @@ -4,7 +4,7 @@ #include "hex.h" #include "midx.h" #include "repository.h" -#include "object-store-ll.h" +#include "object-store.h" #include "pack-bitmap.h" #include "packfile.h" #include "setup.h" diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index e00fce592b..4cfc7c90b5 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -5,7 +5,7 @@ #include "refs.h" #include "setup.h" #include "worktree.h" -#include "object-store-ll.h" +#include "object-store.h" #include "path.h" #include "repository.h" #include "strbuf.h" @@ -179,7 +179,7 @@ static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv) static int cmd_resolve_ref(struct ref_store *refs, const char **argv) { - struct object_id oid = *null_oid(); + struct object_id oid = *null_oid(the_hash_algo); const char *refname = notnull(*argv++, "refname"); int resolve_flags = arg_flags(*argv++, "resolve-flags", empty_flags); int flags; diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c index 3c72ed985b..b16c0722c8 100644 --- a/t/helper/test-reftable.c +++ b/t/helper/test-reftable.c @@ -2,10 +2,11 @@ #include "hash.h" #include "hex.h" #include "reftable/system.h" +#include "reftable/reftable-constants.h" #include "reftable/reftable-error.h" #include "reftable/reftable-merged.h" -#include "reftable/reftable-reader.h" #include "reftable/reftable-stack.h" +#include "reftable/reftable-table.h" #include "test-tool.h" static void print_help(void) @@ -20,6 +21,72 @@ static void print_help(void) "\n"); } +static int dump_blocks(const char *tablename) +{ + struct reftable_table_iterator ti = { 0 }; + struct reftable_block_source src = { 0 }; + struct reftable_table *table = NULL; + uint8_t section_type = 0; + int err; + + err = reftable_block_source_from_file(&src, tablename); + if (err < 0) + goto done; + + err = reftable_table_new(&table, &src, tablename); + if (err < 0) + goto done; + + err = reftable_table_iterator_init(&ti, table); + if (err < 0) + goto done; + + printf("header:\n"); + printf(" block_size: %d\n", table->block_size); + + while (1) { + const struct reftable_block *block; + + err = reftable_table_iterator_next(&ti, &block); + if (err < 0) + goto done; + if (err > 0) + break; + + if (block->block_type != section_type) { + const char *section; + switch (block->block_type) { + case REFTABLE_BLOCK_TYPE_LOG: + section = "log"; + break; + case REFTABLE_BLOCK_TYPE_REF: + section = "ref"; + break; + case REFTABLE_BLOCK_TYPE_OBJ: + section = "obj"; + break; + case REFTABLE_BLOCK_TYPE_INDEX: + section = "idx"; + break; + default: + err = -1; + goto done; + } + + section_type = block->block_type; + printf("%s:\n", section); + } + + printf(" - length: %u\n", block->restart_off); + printf(" restarts: %u\n", block->restart_count); + } + +done: + reftable_table_iterator_release(&ti); + reftable_table_decref(table); + return err; +} + static int dump_table(struct reftable_merged_table *mt) { struct reftable_iterator it = { NULL }; @@ -126,19 +193,19 @@ static int dump_reftable(const char *tablename) { struct reftable_block_source src = { 0 }; struct reftable_merged_table *mt = NULL; - struct reftable_reader *r = NULL; + struct reftable_table *table = NULL; int err; err = reftable_block_source_from_file(&src, tablename); if (err < 0) goto done; - err = reftable_reader_new(&r, &src, tablename); + err = reftable_table_new(&table, &src, tablename); if (err < 0) goto done; - err = reftable_merged_table_new(&mt, &r, 1, - reftable_reader_hash_id(r)); + err = reftable_merged_table_new(&mt, &table, 1, + reftable_table_hash_id(table)); if (err < 0) goto done; @@ -146,7 +213,7 @@ static int dump_reftable(const char *tablename) done: reftable_merged_table_free(mt); - reftable_reader_decref(r); + reftable_table_decref(table); return err; } @@ -184,7 +251,7 @@ int cmd__dump_reftable(int argc, const char **argv) arg = argv[1]; if (opt_dump_blocks) { - err = reftable_reader_print_blocks(arg); + err = dump_blocks(arg); } else if (opt_dump_table) { err = dump_reftable(arg); } else if (opt_dump_stack) { diff --git a/t/helper/test-rot13-filter.c b/t/helper/test-rot13-filter.c index 722b1cbe77..ad37e10034 100644 --- a/t/helper/test-rot13-filter.c +++ b/t/helper/test-rot13-filter.c @@ -324,7 +324,7 @@ static void packet_initialize(void) packet_flush(1); } -static const char *rot13_usage[] = { +static const char *const rot13_usage[] = { "test-tool rot13-filter [--always-delay] --log=<path> <capabilities>", NULL }; diff --git a/t/helper/test-sha1.sh b/t/helper/test-sha1.sh index bf387d3db1..f03b784ddc 100755 --- a/t/helper/test-sha1.sh +++ b/t/helper/test-sha1.sh @@ -15,7 +15,7 @@ do { test -z "$pfx" || echo "$pfx" dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null | - perl -pe 'y/\000/g/' + tr "\000" "g" } | ./t/helper/test-tool $sha1 $cnt ) if test "$expect" = "$actual" @@ -61,7 +61,7 @@ do { test -z "$pfx" || echo "$pfx" dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null | - perl -pe 'y/\000/g/' + tr "\000" "g" } | sha1sum | sed -e 's/ .*//' ) diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c index 6dce957153..2710341cd5 100644 --- a/t/helper/test-submodule-nested-repo-config.c +++ b/t/helper/test-submodule-nested-repo-config.c @@ -21,7 +21,7 @@ int cmd__submodule_nested_repo_config(int argc, const char **argv) setup_git_directory(); - if (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid())) { + if (repo_submodule_init(&subrepo, the_repository, argv[1], null_oid(the_hash_algo))) { die_usage(argv, "Submodule not found."); } diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c index 22e518d229..0133852e1e 100644 --- a/t/helper/test-submodule.c +++ b/t/helper/test-submodule.c @@ -12,33 +12,33 @@ #define TEST_TOOL_CHECK_NAME_USAGE \ "test-tool submodule check-name" -static const char *submodule_check_name_usage[] = { +static const char *const submodule_check_name_usage[] = { TEST_TOOL_CHECK_NAME_USAGE, NULL }; #define TEST_TOOL_CHECK_URL_USAGE \ "test-tool submodule check-url" -static const char *submodule_check_url_usage[] = { +static const char *const submodule_check_url_usage[] = { TEST_TOOL_CHECK_URL_USAGE, NULL }; #define TEST_TOOL_IS_ACTIVE_USAGE \ "test-tool submodule is-active <name>" -static const char *submodule_is_active_usage[] = { +static const char *const submodule_is_active_usage[] = { TEST_TOOL_IS_ACTIVE_USAGE, NULL }; #define TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE \ "test-tool submodule resolve-relative-url <up_path> <remoteurl> <url>" -static const char *submodule_resolve_relative_url_usage[] = { +static const char *const submodule_resolve_relative_url_usage[] = { TEST_TOOL_RESOLVE_RELATIVE_URL_USAGE, NULL, }; -static const char *submodule_usage[] = { +static const char *const submodule_usage[] = { TEST_TOOL_CHECK_NAME_USAGE, TEST_TOOL_CHECK_URL_USAGE, TEST_TOOL_IS_ACTIVE_USAGE, diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 50dc4dac4e..a7abc618b3 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -46,6 +46,7 @@ static struct test_cmd cmds[] = { { "mktemp", cmd__mktemp }, { "name-hash", cmd__name_hash }, { "online-cpus", cmd__online_cpus }, + { "pack-deltas", cmd__pack_deltas }, { "pack-mtimes", cmd__pack_mtimes }, { "parse-options", cmd__parse_options }, { "parse-options-flags", cmd__parse_options_flags }, @@ -90,6 +91,7 @@ static struct test_cmd cmds[] = { { "windows-named-pipe", cmd__windows_named_pipe }, #endif { "write-cache", cmd__write_cache }, + { "zlib", cmd__zlib }, }; static NORETURN void die_usage(void) diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 6d62a5b53d..7f150fa1eb 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -39,6 +39,7 @@ int cmd__mergesort(int argc, const char **argv); int cmd__mktemp(int argc, const char **argv); int cmd__name_hash(int argc, const char **argv); int cmd__online_cpus(int argc, const char **argv); +int cmd__pack_deltas(int argc, const char **argv); int cmd__pack_mtimes(int argc, const char **argv); int cmd__parse_options(int argc, const char **argv); int cmd__parse_options_flags(int argc, const char **argv); @@ -83,6 +84,7 @@ int cmd__wildmatch(int argc, const char **argv); int cmd__windows_named_pipe(int argc, const char **argv); #endif int cmd__write_cache(int argc, const char **argv); +int cmd__zlib(int argc, const char **argv); int cmd_hash_impl(int ac, const char **av, int algo, int unsafe); diff --git a/t/helper/test-windows-named-pipe.c b/t/helper/test-windows-named-pipe.c index ae52183e63..bd73784ceb 100644 --- a/t/helper/test-windows-named-pipe.c +++ b/t/helper/test-windows-named-pipe.c @@ -3,7 +3,7 @@ #include "strbuf.h" #ifdef GIT_WINDOWS_NATIVE -static const char *usage_string = "<pipe-filename>"; +static const char *const usage_string = "<pipe-filename>"; #define TEST_BUFSIZE (4096) diff --git a/t/helper/test-zlib.c b/t/helper/test-zlib.c new file mode 100644 index 0000000000..de7e9edee1 --- /dev/null +++ b/t/helper/test-zlib.c @@ -0,0 +1,62 @@ +#include "test-tool.h" +#include "git-zlib.h" +#include "strbuf.h" + +static const char *zlib_usage = "test-tool zlib [inflate|deflate]"; + +static void do_zlib(struct git_zstream *stream, + int (*zlib_func)(git_zstream *, int), + int fd_in, int fd_out) +{ + struct strbuf buf_in = STRBUF_INIT; + int status = Z_OK; + + if (strbuf_read(&buf_in, fd_in, 0) < 0) + die_errno("read error"); + + stream->next_in = (unsigned char *)buf_in.buf; + stream->avail_in = buf_in.len; + + while (status == Z_OK || + (status == Z_BUF_ERROR && !stream->avail_out)) { + unsigned char buf_out[4096]; + + stream->next_out = buf_out; + stream->avail_out = sizeof(buf_out); + + status = zlib_func(stream, Z_FINISH); + if (write_in_full(fd_out, buf_out, + sizeof(buf_out) - stream->avail_out) < 0) + die_errno("write error"); + } + + if (status != Z_STREAM_END) + die("zlib error %d", status); + + strbuf_release(&buf_in); +} + +int cmd__zlib(int argc, const char **argv) +{ + git_zstream stream; + + if (argc != 2) + usage(zlib_usage); + + memset(&stream, 0, sizeof(stream)); + + if (!strcmp(argv[1], "inflate")) { + git_inflate_init(&stream); + do_zlib(&stream, git_inflate, 0, 1); + git_inflate_end(&stream); + } else if (!strcmp(argv[1], "deflate")) { + git_deflate_init(&stream, Z_DEFAULT_COMPRESSION); + do_zlib(&stream, git_deflate, 0, 1); + git_deflate_end(&stream); + } else { + error("unknown mode: %s", argv[1]); + usage(zlib_usage); + } + + return 0; +} diff --git a/t/lib-diff.sh b/t/lib-diff.sh index c4606bd4b7..12b3c8fcc6 100644 --- a/t/lib-diff.sh +++ b/t/lib-diff.sh @@ -21,8 +21,8 @@ compare_diff_raw_z () { # Also we do not check SHA1 hash generation in this test, which # is a job for t0000-basic.sh - perl -pe 'y/\000/\012/' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1 - perl -pe 'y/\000/\012/' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2 + tr "\000" "\012" <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1 + tr "\000" "\012" <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2 test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 } diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh index 3845b6ac44..937b876bd0 100644 --- a/t/lib-gpg.sh +++ b/t/lib-gpg.sh @@ -192,9 +192,5 @@ test_lazy_prereq GPGSSH_VERIFYTIME ' ' sanitize_pgp() { - perl -ne ' - /^-----END PGP/ and $in_pgp = 0; - print unless $in_pgp; - /^-----BEGIN PGP/ and $in_pgp = 1; - ' + sed "/^-----BEGIN PGP/,/^-----END PGP/{/^-/p;d;}" } diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index d83bafeab3..5091db949b 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -165,7 +165,7 @@ prepare_httpd() { install_script broken-smart-http.sh install_script error-smart-http.sh install_script error.sh - install_script apply-one-time-perl.sh + install_script apply-one-time-script.sh install_script nph-custom-auth.sh ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules" diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 022276a6b9..e631ab0eb5 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -135,7 +135,7 @@ SetEnv PERL_PATH ${PERL_PATH} SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} SetEnv GIT_HTTP_EXPORT_ALL </LocationMatch> -<LocationMatch /one_time_perl/> +<LocationMatch /one_time_script/> SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} SetEnv GIT_HTTP_EXPORT_ALL </LocationMatch> @@ -159,7 +159,7 @@ ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1 ScriptAlias /broken_smart/ broken-smart-http.sh/ ScriptAlias /error_smart/ error-smart-http.sh/ ScriptAlias /error/ error.sh/ -ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1 +ScriptAliasMatch /one_time_script/(.*) apply-one-time-script.sh/$1 ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1 <Directory ${GIT_EXEC_PATH}> Options FollowSymlinks @@ -182,7 +182,7 @@ ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1 <Files error.sh> Options ExecCGI </Files> -<Files apply-one-time-perl.sh> +<Files apply-one-time-script.sh> Options ExecCGI </Files> <Files ${GIT_EXEC_PATH}/git-http-backend> diff --git a/t/lib-httpd/apply-one-time-perl.sh b/t/lib-httpd/apply-one-time-perl.sh deleted file mode 100644 index d7f9fed6ae..0000000000 --- a/t/lib-httpd/apply-one-time-perl.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# If "one-time-perl" exists in $HTTPD_ROOT_PATH, run perl on the HTTP response, -# using the contents of "one-time-perl" as the perl command to be run. If the -# response was modified as a result, delete "one-time-perl" so that subsequent -# HTTP responses are no longer modified. -# -# This can be used to simulate the effects of the repository changing in -# between HTTP request-response pairs. -if test -f one-time-perl -then - LC_ALL=C - export LC_ALL - - "$GIT_EXEC_PATH/git-http-backend" >out - "$PERL_PATH" -pe "$(cat one-time-perl)" out >out_modified - - if cmp -s out out_modified - then - cat out - else - cat out_modified - rm one-time-perl - fi -else - "$GIT_EXEC_PATH/git-http-backend" -fi diff --git a/t/lib-httpd/apply-one-time-script.sh b/t/lib-httpd/apply-one-time-script.sh new file mode 100644 index 0000000000..b1682944e2 --- /dev/null +++ b/t/lib-httpd/apply-one-time-script.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# If "one-time-script" exists in $HTTPD_ROOT_PATH, run the script on the HTTP +# response. If the response was modified as a result, delete "one-time-script" +# so that subsequent HTTP responses are no longer modified. +# +# This can be used to simulate the effects of the repository changing in +# between HTTP request-response pairs. +if test -f one-time-script +then + LC_ALL=C + export LC_ALL + + "$GIT_EXEC_PATH/git-http-backend" >out + ./one-time-script out >out_modified + + if cmp -s out out_modified + then + cat out + else + cat out_modified + rm one-time-script + fi +else + "$GIT_EXEC_PATH/git-http-backend" +fi diff --git a/t/lib-loose.sh b/t/lib-loose.sh new file mode 100644 index 0000000000..3613631eaf --- /dev/null +++ b/t/lib-loose.sh @@ -0,0 +1,30 @@ +# Support routines for hand-crafting loose objects. + +# Write a loose object into the odb at $1, with object type $2 and contents +# from stdin. Writes the oid to stdout. Example: +# +# oid=$(echo foo | loose_obj .git/objects blob) +# +loose_obj () { + cat >tmp_loose.content && + size=$(wc -c <tmp_loose.content) && + { + # Do not quote $size here; we want the shell + # to strip whitespace that "wc" adds on some platforms. + printf "%s %s\0" "$2" $size && + cat tmp_loose.content + } >tmp_loose.raw && + + oid=$(test-tool $test_hash_algo <tmp_loose.raw) && + suffix=${oid#??} && + prefix=${oid%$suffix} && + dir=$1/$prefix && + file=$dir/$suffix && + + test-tool zlib deflate <tmp_loose.raw >tmp_loose.zlib && + mkdir -p "$dir" && + mv tmp_loose.zlib "$file" && + + rm tmp_loose.raw tmp_loose.content && + echo "$oid" +} diff --git a/t/lib-merge.sh b/t/lib-merge.sh deleted file mode 100644 index 8734ebfc17..0000000000 --- a/t/lib-merge.sh +++ /dev/null @@ -1,13 +0,0 @@ -# Helper functions used by merge tests. - -test_expect_merge_algorithm () { - status_for_recursive=$1 status_for_ort=$2 - shift 2 - - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_expect_${status_for_ort} "$@" - else - test_expect_${status_for_recursive} "$@" - fi -} diff --git a/t/lib-t6000.sh b/t/lib-t6000.sh index fba6778ca3..35c5472465 100644 --- a/t/lib-t6000.sh +++ b/t/lib-t6000.sh @@ -109,13 +109,12 @@ check_output () { # All alphanums translated into -'s which are then compressed and stripped # from front and back. name_from_description () { - perl -pe ' - s/[^A-Za-z0-9.]/-/g; - s/-+/-/g; - s/-$//; - s/^-//; - y/A-Z/a-z/; - ' + sed \ + -e 's/[^A-Za-z0-9.]/-/g' \ + -e 's/--*/-/g' \ + -e 's/-$//' \ + -e 's/^-//' \ + -e 'y/A-Z/a-z/' } diff --git a/t/meson.build b/t/meson.build index a59da26be3..50e89e764a 100644 --- a/t/meson.build +++ b/t/meson.build @@ -12,6 +12,8 @@ clar_test_suites = [ 'unit-tests/u-strbuf.c', 'unit-tests/u-strcmp-offset.c', 'unit-tests/u-strvec.c', + 'unit-tests/u-trailer.c', + 'unit-tests/u-urlmatch-normalization.c', ] clar_sources = [ @@ -49,19 +51,17 @@ clar_unit_tests = executable('unit-tests', sources: clar_sources + clar_test_suites, dependencies: [libgit_commonmain], ) -test('unit-tests', clar_unit_tests) +test('unit-tests', clar_unit_tests, kwargs: test_kwargs) unit_test_programs = [ 'unit-tests/t-reftable-basics.c', 'unit-tests/t-reftable-block.c', 'unit-tests/t-reftable-merged.c', 'unit-tests/t-reftable-pq.c', - 'unit-tests/t-reftable-reader.c', 'unit-tests/t-reftable-readwrite.c', 'unit-tests/t-reftable-record.c', 'unit-tests/t-reftable-stack.c', - 'unit-tests/t-trailer.c', - 'unit-tests/t-urlmatch-normalization.c', + 'unit-tests/t-reftable-table.c', ] foreach unit_test_program : unit_test_programs @@ -76,7 +76,7 @@ foreach unit_test_program : unit_test_programs ) test(unit_test_name, unit_test, workdir: meson.current_source_dir(), - timeout: 0, + kwargs: test_kwargs, ) endforeach @@ -500,6 +500,8 @@ integration_tests = [ 't4067-diff-partial-clone.sh', 't4068-diff-symmetric-merge-base.sh', 't4069-remerge-diff.sh', + 't4070-diff-pairs.sh', + 't4071-diff-minimal.sh', 't4100-apply-stat.sh', 't4101-apply-nonl.sh', 't4102-apply-rename.sh', @@ -627,7 +629,7 @@ integration_tests = [ 't5407-post-rewrite-hook.sh', 't5408-send-pack-stdin.sh', 't5409-colorize-remote-messages.sh', - 't5410-receive-pack-alternates.sh', + 't5410-receive-pack.sh', 't5411-proc-receive-hook.sh', 't5500-fetch-pack.sh', 't5501-fetch-push-alternates.sh', @@ -787,6 +789,7 @@ integration_tests = [ 't6134-pathspec-in-submodule.sh', 't6135-pathspec-with-attrs.sh', 't6136-pathspec-in-bare.sh', + 't6137-pathspec-wildcards-literal.sh', 't6200-fmt-merge-msg.sh', 't6300-for-each-ref.sh', 't6301-for-each-ref-errors.sh', @@ -1096,11 +1099,71 @@ integration_tests = [ 't9903-bash-prompt.sh', ] +benchmarks = [ + 'perf/p0000-perf-lib-sanity.sh', + 'perf/p0001-rev-list.sh', + 'perf/p0002-read-cache.sh', + 'perf/p0003-delta-base-cache.sh', + 'perf/p0004-lazy-init-name-hash.sh', + 'perf/p0005-status.sh', + 'perf/p0006-read-tree-checkout.sh', + 'perf/p0007-write-cache.sh', + 'perf/p0008-odb-fsync.sh', + 'perf/p0071-sort.sh', + 'perf/p0090-cache-tree.sh', + 'perf/p0100-globbing.sh', + 'perf/p1006-cat-file.sh', + 'perf/p1400-update-ref.sh', + 'perf/p1450-fsck.sh', + 'perf/p1451-fsck-skip-list.sh', + 'perf/p1500-graph-walks.sh', + 'perf/p2000-sparse-operations.sh', + 'perf/p3400-rebase.sh', + 'perf/p3404-rebase-interactive.sh', + 'perf/p4000-diff-algorithms.sh', + 'perf/p4001-diff-no-index.sh', + 'perf/p4002-diff-color-moved.sh', + 'perf/p4205-log-pretty-formats.sh', + 'perf/p4209-pickaxe.sh', + 'perf/p4211-line-log.sh', + 'perf/p4220-log-grep-engines.sh', + 'perf/p4221-log-grep-engines-fixed.sh', + 'perf/p5302-pack-index.sh', + 'perf/p5303-many-packs.sh', + 'perf/p5304-prune.sh', + 'perf/p5310-pack-bitmaps.sh', + 'perf/p5311-pack-bitmaps-fetch.sh', + 'perf/p5312-pack-bitmaps-revs.sh', + 'perf/p5313-pack-objects.sh', + 'perf/p5314-name-hash.sh', + 'perf/p5326-multi-pack-bitmaps.sh', + 'perf/p5332-multi-pack-reuse.sh', + 'perf/p5333-pseudo-merge-bitmaps.sh', + 'perf/p5550-fetch-tags.sh', + 'perf/p5551-fetch-rescan.sh', + 'perf/p5600-partial-clone.sh', + 'perf/p5601-clone-reference.sh', + 'perf/p6100-describe.sh', + 'perf/p6300-for-each-ref.sh', + 'perf/p7000-filter-branch.sh', + 'perf/p7102-reset.sh', + 'perf/p7300-clean.sh', + 'perf/p7519-fsmonitor.sh', + 'perf/p7527-builtin-fsmonitor.sh', + 'perf/p7810-grep.sh', + 'perf/p7820-grep-engines.sh', + 'perf/p7821-grep-engines-fixed.sh', + 'perf/p7822-grep-perl-character.sh', + 'perf/p9210-scalar.sh', + 'perf/p9300-fast-import-export.sh', +] + # Sanity check that we are not missing any tests present in 't/'. This check # only runs once at configure time and is thus best-effort, only. It is # sufficient to catch missing test suites in our CI though. foreach glob, tests : { 't[0-9][0-9][0-9][0-9]-*.sh': integration_tests, + 'perf/p[0-9][0-9][0-9][0-9]-*.sh': benchmarks, 'unit-tests/t-*.c': unit_test_programs, 'unit-tests/u-*.c': clar_test_suites, } @@ -1149,6 +1212,23 @@ foreach integration_test : integration_tests workdir: meson.current_source_dir(), env: test_environment, depends: test_dependencies + bin_wrappers, - timeout: 0, + kwargs: test_kwargs, ) endforeach + +if perl.found() and time.found() + benchmark_environment = test_environment + benchmark_environment.set('GTIME', time.full_path()) + + foreach benchmark : benchmarks + benchmark(fs.stem(benchmark), shell, + args: [ + fs.name(benchmark), + ], + workdir: meson.current_source_dir() / 'perf', + env: benchmark_environment, + depends: test_dependencies + bin_wrappers, + timeout: 0, + ) + endforeach +endif diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl index 575d2000cc..1791c7528a 100755 --- a/t/perf/aggregate.perl +++ b/t/perf/aggregate.perl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl use lib '../../perl/build/lib'; use strict; diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh index 39e92b0841..aadf22bc2f 100755 --- a/t/perf/p2000-sparse-operations.sh +++ b/t/perf/p2000-sparse-operations.sh @@ -135,5 +135,8 @@ test_perf_on_all git diff-tree HEAD test_perf_on_all git diff-tree HEAD -- $SPARSE_CONE/a test_perf_on_all "git worktree add ../temp && git worktree remove ../temp" test_perf_on_all git check-attr -a -- $SPARSE_CONE/a +test_perf_on_all 'echo >>a && test_write_lines y | git add -p' +test_perf_on_all 'test_write_lines y y y | git checkout --patch -' +test_perf_on_all 'echo >>a && git add a && test_write_lines y | git reset --patch' test_done diff --git a/t/perf/p5313-pack-objects.sh b/t/perf/p5313-pack-objects.sh index be5229a0ec..46a6cd32d2 100755 --- a/t/perf/p5313-pack-objects.sh +++ b/t/perf/p5313-pack-objects.sh @@ -3,9 +3,6 @@ test_description='Tests pack performance using bitmaps' . ./perf-lib.sh -GIT_TEST_PASSING_SANITIZE_LEAK=0 -export GIT_TEST_PASSING_SANITIZE_LEAK - test_perf_large_repo test_expect_success 'create rev input' ' @@ -25,46 +22,53 @@ test_expect_success 'create rev input' ' EOF ' -for version in 1 2 -do - export version +test_all_with_args () { + parameter=$1 + export parameter - test_perf "thin pack with version $version" ' + test_perf "thin pack with $parameter" ' git pack-objects --thin --stdout --revs --sparse \ - --name-hash-version=$version <in-thin >out + $parameter <in-thin >out ' - test_size "thin pack size with version $version" ' + test_size "thin pack size with $parameter" ' test_file_size out ' - test_perf "big pack with version $version" ' + test_perf "big pack with $parameter" ' git pack-objects --stdout --revs --sparse \ - --name-hash-version=$version <in-big >out + $parameter <in-big >out ' - test_size "big pack size with version $version" ' + test_size "big pack size with $parameter" ' test_file_size out ' - test_perf "shallow fetch pack with version $version" ' + test_perf "shallow fetch pack with $parameter" ' git pack-objects --stdout --revs --sparse --shallow \ - --name-hash-version=$version <in-shallow >out + $parameter <in-shallow >out ' - test_size "shallow pack size with version $version" ' + test_size "shallow pack size with $parameter" ' test_file_size out ' - test_perf "repack with version $version" ' - git repack -adf --name-hash-version=$version + test_perf "repack with $parameter" ' + git repack -adf $parameter ' - test_size "repack size with version $version" ' + test_size "repack size with $parameter" ' gitdir=$(git rev-parse --git-dir) && pack=$(ls $gitdir/objects/pack/pack-*.pack) && test_file_size "$pack" ' +} + +for version in 1 2 +do + test_all_with_args --name-hash-version=$version done +test_all_with_args --path-walk + test_done diff --git a/t/perf/p5314-name-hash.sh b/t/perf/p5314-name-hash.sh index 4ef0ba7711..235cdfc824 100755 --- a/t/perf/p5314-name-hash.sh +++ b/t/perf/p5314-name-hash.sh @@ -3,9 +3,6 @@ test_description='Tests pack performance using bitmaps' . ./perf-lib.sh -GIT_TEST_PASSING_SANITIZE_LEAK=0 -export GIT_TEST_PASSING_SANITIZE_LEAK - test_perf_large_repo test_size 'paths at head' ' diff --git a/t/perf/p5332-multi-pack-reuse.sh b/t/perf/p5332-multi-pack-reuse.sh index d1c89a8b7d..0a2525db44 100755 --- a/t/perf/p5332-multi-pack-reuse.sh +++ b/t/perf/p5332-multi-pack-reuse.sh @@ -58,7 +58,7 @@ do ' test_expect_success "setup bitmaps for $nr_packs-pack scenario" ' - find $packdir -type f -name "*.idx" | sed -e "s/.*\/\(.*\)$/+\1/g" | + find $packdir -type f -name "*.idx" | sed -e "s/.*\///" | git multi-pack-index write --stdin-packs --bitmap \ --preferred-pack="$(find_pack $(git rev-parse HEAD))" ' diff --git a/t/perf/p7821-grep-engines-fixed.sh b/t/perf/p7821-grep-engines-fixed.sh index 61e41b82cf..66bec284e3 100755 --- a/t/perf/p7821-grep-engines-fixed.sh +++ b/t/perf/p7821-grep-engines-fixed.sh @@ -7,7 +7,7 @@ git-grep. Make sure to include a leading space, e.g. GIT_PERF_7821_GREP_OPTS=' -w'. See p7820-grep-engines.sh for more options to try. -If GIT_PERF_7821_THREADS is set to a list of threads (e.g. '1 4 8' +If GIT_PERF_GREP_THREADS is set to a list of threads (e.g. '1 4 8' etc.) we will test the patterns under those numbers of threads. " @@ -33,13 +33,13 @@ do fi if ! test_have_prereq PERF_GREP_ENGINES_THREADS then - test_perf $prereq "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern" " + test_perf "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern" --prereq "$prereq" " git -c grep.patternType=$engine grep$GIT_PERF_7821_GREP_OPTS $pattern >'out.$engine' || : " else for threads in $GIT_PERF_GREP_THREADS do - test_perf PTHREADS,$prereq "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern with $threads threads" " + test_perf "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern with $threads threads" --prereq "PTHREADS,$prereq" " git -c grep.patternType=$engine -c grep.threads=$threads grep$GIT_PERF_7821_GREP_OPTS $pattern >'out.$engine.$threads' || : " done diff --git a/t/perf/p9210-scalar.sh b/t/perf/p9210-scalar.sh index 265f7cd1fe..56b075e906 100755 --- a/t/perf/p9210-scalar.sh +++ b/t/perf/p9210-scalar.sh @@ -7,7 +7,8 @@ test_perf_large_repo "$TRASH_DIRECTORY/to-clone" test_expect_success 'enable server-side partial clone' ' git -C to-clone config uploadpack.allowFilter true && - git -C to-clone config uploadpack.allowAnySHA1InWant true + git -C to-clone config uploadpack.allowAnySHA1InWant true && + git -C to-clone checkout -B test-branch ' test_perf 'scalar clone' ' diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index 8ab6d9c469..b15c74d6f1 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -25,7 +25,43 @@ TEST_OUTPUT_DIRECTORY=$(pwd) TEST_NO_CREATE_REPO=t TEST_NO_MALLOC_CHECK=t -. ../test-lib.sh +# GIT-BUILD-OPTIONS, sourced by test-lib.sh, overwrites the `GIT_PERF_*` +# values that are set by the user (if any). Let's stash them away as +# `eval`-able assignments. +git_perf_settings="$(env | + sed -n "/^GIT_PERF_/{ + # escape all single-quotes in the value + s/'/'\\\\''/g + # turn this into an eval-able assignment + s/^\\([^=]*=\\)\\(.*\\)/\\1'\\2'/p + }")" + +# While test-lib.sh computes the build directory for us, we also have to do the +# same thing in order to locate the script via GIT-BUILD-OPTIONS in the first +# place. +GIT_BUILD_DIR="${GIT_BUILD_DIR:-$TEST_DIRECTORY/..}" +if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR" +then + GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1 + # On Windows, we must convert Windows paths lest they contain a colon + case "$(uname -s)" in + *MINGW*) + GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")" + ;; + esac +fi + +if test ! -f "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +then + echo >&2 'error: GIT-BUILD-OPTIONS missing (has Git been built?).' + exit 1 +fi + +. "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +. "$GIT_SOURCE_DIR"/t/test-lib.sh + +# Then restore GIT_PERF_* settings. +eval "$git_perf_settings" unset GIT_CONFIG_NOSYSTEM GIT_CONFIG_SYSTEM="$TEST_DIRECTORY/perf/config" @@ -98,6 +134,8 @@ test_perf_create_repo_from () { source_git="$("$MODERN_GIT" -C "$source" rev-parse --git-dir)" objects_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-path objects)" common_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-common-dir)" + refformat="$("$MODERN_GIT" -C "$source" rev-parse --show-ref-format)" + objectformat="$("$MODERN_GIT" -C "$source" rev-parse --show-object-format)" mkdir -p "$repo/.git" ( cd "$source" && @@ -114,7 +152,7 @@ test_perf_create_repo_from () { ) && ( cd "$repo" && - "$MODERN_GIT" init -q && + "$MODERN_GIT" init -q --ref-format="$refformat" --object-format="$objectformat" && test_perf_do_repo_symlink_config_ && mv .git/hooks .git/hooks-disabled 2>/dev/null && if test -f .git/index.lock @@ -274,7 +312,7 @@ test_perf_ () { else test_ok_ "$1" fi - "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".result + "$PERL_PATH" "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".result rm test_time.* } @@ -322,7 +360,7 @@ test_at_end_hook_ () { if test -z "$GIT_PERF_AGGREGATING_LATER"; then ( cd "$TEST_DIRECTORY"/perf && - ./aggregate.perl --results-dir="$TEST_RESULTS_DIR" $(basename "$0") + "$PERL_PATH" "$GIT_SOURCE_DIR"/t/perf/aggregate.perl --results-dir="$TEST_RESULTS_DIR" $(basename "$0") ) fi } diff --git a/t/perf/run b/t/perf/run index 486ead2198..073bcb2aff 100755 --- a/t/perf/run +++ b/t/perf/run @@ -192,10 +192,10 @@ run_subsection () { if test -z "$GIT_PERF_SEND_TO_CODESPEED" then - ./aggregate.perl --results-dir="$TEST_RESULTS_DIR" $codespeed_opt "$@" + "$PERL_PATH" ./aggregate.perl --results-dir="$TEST_RESULTS_DIR" $codespeed_opt "$@" else json_res_file=""$TEST_RESULTS_DIR"/$GIT_PERF_SUBSECTION/aggregate.json" - ./aggregate.perl --results-dir="$TEST_RESULTS_DIR" --codespeed "$@" | tee "$json_res_file" + "$PERL_PATH" ./aggregate.perl --results-dir="$TEST_RESULTS_DIR" --codespeed "$@" | tee "$json_res_file" send_data_url="$GIT_PERF_SEND_TO_CODESPEED/result/add/json/" curl -v --request POST --data-urlencode "json=$(cat "$json_res_file")" "$send_data_url" fi diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 35c5c2b4f9..2b63e1c86c 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -130,7 +130,7 @@ test_expect_success 'subtest: a failing TODO test' ' ' test_expect_success 'subtest: a passing TODO test' ' - write_and_run_sub_test_lib_test passing-todo <<-\EOF && + write_and_run_sub_test_lib_test_err passing-todo <<-\EOF && test_expect_failure "pretend we have fixed a known breakage" "true" test_done EOF @@ -142,7 +142,7 @@ test_expect_success 'subtest: a passing TODO test' ' ' test_expect_success 'subtest: 2 TODO tests, one passin' ' - write_and_run_sub_test_lib_test partially-passing-todos <<-\EOF && + write_and_run_sub_test_lib_test_err partially-passing-todos <<-\EOF && test_expect_failure "pretend we have a known breakage" "false" test_expect_success "pretend we have a passing test" "true" test_expect_failure "pretend we have fixed another known breakage" "true" @@ -219,41 +219,44 @@ test_expect_success 'subtest: --verbose option' ' test_expect_success "failing test" false test_done EOF - mv t1234-verbose/out t1234-verbose/out+ && - grep -v "^Initialized empty" t1234-verbose/out+ >t1234-verbose/out && - check_sub_test_lib_test t1234-verbose <<-\EOF - > expecting success of 1234.1 '\''passing test'\'': true + mv t1234-verbose/err t1234-verbose/err+ && + grep -v "^Initialized empty" t1234-verbose/err+ >t1234-verbose/err && + check_sub_test_lib_test_err t1234-verbose \ + <<-\EOF_OUT 3<<-\EOF_ERR > ok 1 - passing test + > ok 2 - test with output + > not ok 3 - failing test + > # false + > # failed 1 among 3 test(s) + > 1..3 + EOF_OUT + > expecting success of 1234.1 '\''passing test'\'': true > Z > expecting success of 1234.2 '\''test with output'\'': echo foo > foo - > ok 2 - test with output > Z > expecting success of 1234.3 '\''failing test'\'': false - > not ok 3 - failing test - > # false > Z - > # failed 1 among 3 test(s) - > 1..3 - EOF + EOF_ERR ' test_expect_success 'subtest: --verbose-only option' ' run_sub_test_lib_test_err \ t1234-verbose \ --verbose-only=2 && - check_sub_test_lib_test t1234-verbose <<-\EOF + check_sub_test_lib_test_err t1234-verbose <<-\EOF_OUT 3<<-\EOF_ERR > ok 1 - passing test - > Z - > expecting success of 1234.2 '\''test with output'\'': echo foo - > foo > ok 2 - test with output - > Z > not ok 3 - failing test > # false > # failed 1 among 3 test(s) > 1..3 - EOF + EOF_OUT + > Z + > expecting success of 1234.2 '\''test with output'\'': echo foo + > foo + > Z + EOF_ERR ' test_expect_success 'subtest: skip one with GIT_SKIP_TESTS' ' diff --git a/t/t0001-init.sh b/t/t0001-init.sh index c49d9e0d38..f11a40811f 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -830,6 +830,14 @@ test_expect_success 'advice on unconfigured init.defaultBranch' ' test_grep "<YELLOW>hint: " decoded ' +test_expect_success 'advice on unconfigured init.defaultBranch disabled' ' + test_when_finished "rm -rf no-advice" && + + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \ + git -c advice.defaultBranchName=false init no-advice 2>err && + test_grep ! "hint: " err +' + test_expect_success 'overridden default main branch name (env)' ' test_config_global init.defaultBranch nmb && GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=env git init main-branch-env && diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh index c9376dffb5..273d71411f 100755 --- a/t/t0008-ignores.sh +++ b/t/t0008-ignores.sh @@ -39,11 +39,11 @@ test_stderr () { } broken_c_unquote () { - "$PERL_PATH" -pe 's/^"//; s/\\//; s/"$//; tr/\n/\0/' "$@" + sed -e 's/^"//' -e 's/\\//' -e 's/"$//' "$1" | tr '\n' '\0' } broken_c_unquote_verbose () { - "$PERL_PATH" -pe 's/ "/ /; s/\\//; s/"$//; tr/:\t\n/\0/' "$@" + sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' "$1" | tr ':\t\n' '\000' } stderr_contains () { diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 3f6433d304..bf10d253ec 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -20,8 +20,7 @@ EOF generate_random_characters () { LEN=$1 NAME=$2 - test-tool genrandom some-seed $LEN | - perl -pe "s/./chr((ord($&) % 26) + ord('a'))/sge" >"$TEST_ROOT/$NAME" + test-tool genrandom some-seed | tr -dc 'a-z' | test_copy_bytes "$LEN" >"$TEST_ROOT/$NAME" } filter_git () { @@ -841,7 +840,7 @@ test_expect_success 'process filter abort stops processing of all further files' ) ' -test_expect_success PERL 'invalid process filter must fail (and not hang!)' ' +test_expect_success 'invalid process filter must fail (and not hang!)' ' test_config_global filter.protocol.process cat && test_config_global filter.protocol.required true && rm -rf repo && @@ -1111,19 +1110,19 @@ do branch) opt='-f HEAD' ;; esac - test_expect_success PERL,TTY "delayed checkout shows progress by default on tty ($mode checkout)" ' + test_expect_success TTY "delayed checkout shows progress by default on tty ($mode checkout)" ' test_delayed_checkout_progress test_terminal git checkout $opt ' - test_expect_success PERL "delayed checkout omits progress on non-tty ($mode checkout)" ' + test_expect_success "delayed checkout omits progress on non-tty ($mode checkout)" ' test_delayed_checkout_progress ! git checkout $opt ' - test_expect_success PERL,TTY "delayed checkout omits progress with --quiet ($mode checkout)" ' + test_expect_success TTY "delayed checkout omits progress with --quiet ($mode checkout)" ' test_delayed_checkout_progress ! test_terminal git checkout --quiet $opt ' - test_expect_success PERL,TTY "delayed checkout honors --[no]-progress ($mode checkout)" ' + test_expect_success TTY "delayed checkout honors --[no]-progress ($mode checkout)" ' test_delayed_checkout_progress ! test_terminal git checkout --no-progress $opt && test_delayed_checkout_progress test_terminal git checkout --quiet --progress $opt ' diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 2fe3522305..ca55ea8228 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -22,8 +22,10 @@ usage: test-tool parse-options <options> -i, --[no-]integer <n> get a integer + --[no-]i16 <n> get a 16 bit integer -j <n> get a integer, too - -m, --magnitude <n> get a magnitude + -u, --unsigned <n> get an unsigned integer + --u16 <n> get a 16 bit unsigned integer --[no-]set23 set integer to 23 --mode1 set integer to 1 (cmdmode option) --mode2 set integer to 2 (cmdmode option) @@ -111,32 +113,36 @@ test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown_i18n --no-no-fear test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt' -test_expect_success 'OPT_INT() negative' 'check integer: -2345 -i -2345' +test_expect_success 'OPT_INTEGER() negative' 'check integer: -2345 -i -2345' +test_expect_success 'OPT_INTEGER() kilo' 'check integer: 239616 -i 234k' +test_expect_success 'OPT_INTEGER() negative kilo' 'check integer: -239616 -i -234k' -test_expect_success 'OPT_MAGNITUDE() simple' ' - check magnitude: 2345678 -m 2345678 +test_expect_success 'OPT_UNSIGNED() simple' ' + check unsigned: 2345678 -u 2345678 ' -test_expect_success 'OPT_MAGNITUDE() kilo' ' - check magnitude: 239616 -m 234k +test_expect_success 'OPT_UNSIGNED() kilo' ' + check unsigned: 239616 -u 234k ' -test_expect_success 'OPT_MAGNITUDE() mega' ' - check magnitude: 104857600 -m 100m +test_expect_success 'OPT_UNSIGNED() mega' ' + check unsigned: 104857600 -u 100m ' -test_expect_success 'OPT_MAGNITUDE() giga' ' - check magnitude: 1073741824 -m 1g +test_expect_success 'OPT_UNSIGNED() giga' ' + check unsigned: 1073741824 -u 1g ' -test_expect_success 'OPT_MAGNITUDE() 3giga' ' - check magnitude: 3221225472 -m 3g +test_expect_success 'OPT_UNSIGNED() 3giga' ' + check unsigned: 3221225472 -u 3g ' cat >expect <<\EOF boolean: 2 integer: 1729 -magnitude: 16384 +i16: 0 +unsigned: 16384 +u16: 0 timestamp: 0 string: 123 abbrev: 7 @@ -147,7 +153,7 @@ file: prefix/my.file EOF test_expect_success 'short options' ' - test-tool parse-options -s123 -b -i 1729 -m 16k -b -vv -n -F my.file \ + test-tool parse-options -s123 -b -i 1729 -u 16k -b -vv -n -F my.file \ >output 2>output.err && test_cmp expect output && test_must_be_empty output.err @@ -156,7 +162,9 @@ test_expect_success 'short options' ' cat >expect <<\EOF boolean: 2 integer: 1729 -magnitude: 16384 +i16: 9000 +unsigned: 16384 +u16: 32768 timestamp: 0 string: 321 abbrev: 10 @@ -167,8 +175,8 @@ file: prefix/fi.le EOF test_expect_success 'long options' ' - test-tool parse-options --boolean --integer 1729 --magnitude 16k \ - --boolean --string2=321 --verbose --verbose --no-dry-run \ + test-tool parse-options --boolean --integer 1729 --i16 9000 --unsigned 16k \ + --u16 32k --boolean --string2=321 --verbose --verbose --no-dry-run \ --abbrev=10 --file fi.le --obsolete \ >output 2>output.err && test_must_be_empty output.err && @@ -179,7 +187,9 @@ test_expect_success 'abbreviate to something longer than SHA1 length' ' cat >expect <<-EOF && boolean: 0 integer: 0 - magnitude: 0 + i16: 0 + unsigned: 0 + u16: 0 timestamp: 0 string: (not set) abbrev: 100 @@ -253,7 +263,9 @@ test_expect_success 'superfluous value provided: cmdmode' ' cat >expect <<\EOF boolean: 1 integer: 13 -magnitude: 0 +i16: 0 +unsigned: 0 +u16: 0 timestamp: 0 string: 123 abbrev: 7 @@ -276,7 +288,9 @@ test_expect_success 'intermingled arguments' ' cat >expect <<\EOF boolean: 0 integer: 2 -magnitude: 0 +i16: 0 +unsigned: 0 +u16: 0 timestamp: 0 string: (not set) abbrev: 7 @@ -343,7 +357,9 @@ cat >expect <<\EOF Callback: "four", 0 boolean: 5 integer: 4 -magnitude: 0 +i16: 0 +unsigned: 0 +u16: 0 timestamp: 0 string: (not set) abbrev: 7 @@ -368,7 +384,9 @@ test_expect_success 'OPT_CALLBACK() and callback errors work' ' cat >expect <<\EOF boolean: 1 integer: 23 -magnitude: 0 +i16: 0 +unsigned: 0 +u16: 0 timestamp: 0 string: (not set) abbrev: 7 @@ -447,7 +465,9 @@ test_expect_success 'OPT_NUMBER_CALLBACK() works' ' cat >expect <<\EOF boolean: 0 integer: 0 -magnitude: 0 +i16: 0 +unsigned: 0 +u16: 0 timestamp: 0 string: (not set) abbrev: 7 @@ -771,16 +791,35 @@ test_expect_success 'subcommands are incompatible with KEEP_DASHDASH unless in c grep ^BUG err ' -test_expect_success 'negative magnitude' ' - test_must_fail test-tool parse-options --magnitude -1 >out 2>err && +test_expect_success 'negative unsigned' ' + test_must_fail test-tool parse-options --unsigned -1 >out 2>err && grep "non-negative integer" err && test_must_be_empty out ' -test_expect_success 'magnitude with units but no numbers' ' - test_must_fail test-tool parse-options --magnitude m >out 2>err && +test_expect_success 'unsigned with units but no numbers' ' + test_must_fail test-tool parse-options --unsigned m >out 2>err && grep "non-negative integer" err && test_must_be_empty out ' +test_expect_success 'i16 limits range' ' + test-tool parse-options --i16 32767 >out && + test_grep "i16: 32767" out && + test_must_fail test-tool parse-options --i16 32768 2>err && + test_grep "value 32768 for option .i16. not in range \[-32768,32767\]" err && + + test-tool parse-options --i16 -32768 >out && + test_grep "i16: -32768" out && + test_must_fail test-tool parse-options --i16 -32769 2>err && + test_grep "value -32769 for option .i16. not in range \[-32768,32767\]" err +' + +test_expect_success 'u16 limits range' ' + test-tool parse-options --u16 65535 >out && + test_grep "u16: 65535" out && + test_must_fail test-tool parse-options --u16 65536 2>err && + test_grep "value 65536 for option .u16. not in range \[0,65535\]" err +' + test_done diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh index 5c9dc90d0b..ca8568067d 100755 --- a/t/t0050-filesystem.sh +++ b/t/t0050-filesystem.sh @@ -10,53 +10,35 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME auml=$(printf '\303\244') aumlcdiar=$(printf '\141\314\210') -if test_have_prereq CASE_INSENSITIVE_FS -then - say "will test on a case insensitive filesystem" - test_case=test_expect_failure -else - test_case=test_expect_success -fi - if test_have_prereq UTF8_NFD_TO_NFC then - say "will test on a unicode corrupting filesystem" test_unicode=test_expect_failure else test_unicode=test_expect_success fi -test_have_prereq SYMLINKS || - say "will test on a filesystem lacking symbolic links" - -if test_have_prereq CASE_INSENSITIVE_FS -then -test_expect_success "detection of case insensitive filesystem during repo init" ' +test_expect_success CASE_INSENSITIVE_FS "detection of case insensitive filesystem during repo init" ' test $(git config --bool core.ignorecase) = true ' -else -test_expect_success "detection of case insensitive filesystem during repo init" ' + +test_expect_success !CASE_INSENSITIVE_FS "detection of case insensitive filesystem during repo init" ' { test_must_fail git config --bool core.ignorecase >/dev/null || test $(git config --bool core.ignorecase) = false } ' -fi -if test_have_prereq SYMLINKS -then -test_expect_success "detection of filesystem w/o symlink support during repo init" ' +test_expect_success SYMLINKS "detection of filesystem w/o symlink support during repo init" ' { test_must_fail git config --bool core.symlinks || test "$(git config --bool core.symlinks)" = true } ' -else -test_expect_success "detection of filesystem w/o symlink support during repo init" ' + +test_expect_success !SYMLINKS "detection of filesystem w/o symlink support during repo init" ' v=$(git config --bool core.symlinks) && test "$v" = false ' -fi test_expect_success "setup case tests" ' git config core.ignorecase true && diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh index ab80c9ef13..d901588294 100755 --- a/t/t0090-cache-tree.sh +++ b/t/t0090-cache-tree.sh @@ -128,7 +128,7 @@ test_expect_success 'second commit has cache-tree' ' test_cache_tree ' -test_expect_success PERL 'commit --interactive gives cache-tree on partial commit' ' +test_expect_success 'commit --interactive gives cache-tree on partial commit' ' test_when_finished "git reset --hard" && cat <<-\EOT >foo.c && int foo() @@ -162,7 +162,7 @@ test_expect_success PERL 'commit --interactive gives cache-tree on partial commi test_cache_tree expected.status ' -test_expect_success PERL 'commit -p with shrinking cache-tree' ' +test_expect_success 'commit -p with shrinking cache-tree' ' mkdir -p deep/very-long-subdir && echo content >deep/very-long-subdir/file && git add deep && diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh index 4287ed3fbb..96c68f65df 100755 --- a/t/t0210-trace2-normal.sh +++ b/t/t0210-trace2-normal.sh @@ -53,10 +53,41 @@ GIT_TRACE2_BRIEF=1 && export GIT_TRACE2_BRIEF # # Implicit return from cmd_<verb> function propagates <code>. +scrub_normal () { + # Scrub the variable fields from the normal trace2 output to make + # testing easier: + # + # 1. Various messages include an elapsed time in the middle of the + # message. Replace the time with a placeholder to simplify our + # HEREDOC in the test script. + # + # 2. We expect: + # + # start <argv0> [<argv1> [<argv2> [...]]] + # + # where argv0 might be a relative or absolute path, with or + # without quotes, and platform dependent. Replace argv0 with a + # token for HEREDOC matching in the test script. + # + # 3. Likewise, the 'cmd_path' message breaks out argv[0]. + # + # This line is only emitted when RUNTIME_PREFIX is defined, + # so just omit it for testing purposes. + # + # 4. 'cmd_ancestry' is not implemented everywhere, so for portability's + # sake, skip it when parsing normal. + sed \ + -e 's/elapsed:[0-9]*\.[0-9][0-9]*\([eE][-+]\{0,1\}[0-9][0-9]*\)\{0,1\}/elapsed:_TIME_/g' \ + -e "s/^start '[^']*' \(.*\)/start _EXE_ \1/" \ + -e 's/^start [^ ][^ ]* \(.*\)/start _EXE_ \1/' \ + -e '/^cmd_path/d' \ + -e '/^cmd_ancestry/d' +} + test_expect_success 'normal stream, return code 0' ' test_when_finished "rm trace.normal actual expect" && GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 001return 0 && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 001return 0 @@ -70,7 +101,7 @@ test_expect_success 'normal stream, return code 0' ' test_expect_success 'normal stream, return code 1' ' test_when_finished "rm trace.normal actual expect" && test_must_fail env GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 001return 1 && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 001return 1 @@ -85,7 +116,7 @@ test_expect_success 'automatic filename' ' test_when_finished "rm -r traces actual expect" && mkdir traces && GIT_TRACE2="$(pwd)/traces" test-tool trace2 001return 0 && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <"$(ls traces/*)" >actual && + scrub_normal <"$(ls traces/*)" >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 001return 0 @@ -103,7 +134,7 @@ test_expect_success 'automatic filename' ' test_expect_success 'normal stream, exit code 0' ' test_when_finished "rm trace.normal actual expect" && GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 002exit 0 && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 002exit 0 @@ -117,7 +148,7 @@ test_expect_success 'normal stream, exit code 0' ' test_expect_success 'normal stream, exit code 1' ' test_when_finished "rm trace.normal actual expect" && test_must_fail env GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 002exit 1 && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 002exit 1 @@ -135,7 +166,7 @@ test_expect_success 'normal stream, exit code 1' ' test_expect_success 'normal stream, error event' ' test_when_finished "rm trace.normal actual expect" && GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 003error "hello world" "this is a test" && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 003error '\''hello world'\'' '\''this is a test'\'' @@ -155,7 +186,7 @@ test_expect_success 'normal stream, error event' ' test_expect_success 'BUG messages are written to trace2' ' test_when_finished "rm trace.normal actual expect" && test_must_fail env GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 007bug && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 007bug @@ -179,7 +210,7 @@ test_expect_success 'bug messages with BUG_if_bug() are written to trace2' ' sed "s/^.*: //" <err >actual && test_cmp expect actual && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 008bug @@ -205,7 +236,7 @@ test_expect_success 'bug messages without explicit BUG_if_bug() are written to t sed "s/^.*: //" <err >actual && test_cmp expect actual && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 009bug_BUG @@ -230,7 +261,7 @@ test_expect_success 'bug messages followed by BUG() are written to trace2' ' sed "s/^.*: //" <err >actual && test_cmp expect actual && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 010bug_BUG @@ -262,7 +293,7 @@ test_expect_success 'using global config, normal stream, return code 0' ' test_config_global trace2.normalBrief 1 && test_config_global trace2.normalTarget "$(pwd)/trace.normal" && test-tool trace2 001return 0 && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 001return 0 @@ -280,7 +311,7 @@ test_expect_success 'using global config with include' ' mv "$(pwd)/.gitconfig" "$(pwd)/real.gitconfig" && test_config_global include.path "$(pwd)/real.gitconfig" && test-tool trace2 001return 0 && - perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + scrub_normal <trace.normal >actual && cat >expect <<-EOF && version $V start _EXE_ trace2 001return 0 diff --git a/t/t0210/scrub_normal.perl b/t/t0210/scrub_normal.perl deleted file mode 100644 index 7cc4de392a..0000000000 --- a/t/t0210/scrub_normal.perl +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/perl -# -# Scrub the variable fields from the normal trace2 output to -# make testing easier. - -use strict; -use warnings; - -my $float = '[0-9]*\.[0-9]+([eE][-+]?[0-9]+)?'; - -# This code assumes that the trace2 data was written with bare -# turned on (which omits the "<clock> <file>:<line>" prefix. - -while (<>) { - # Various messages include an elapsed time in the middle - # of the message. Replace the time with a placeholder to - # simplify our HEREDOC in the test script. - s/elapsed:$float/elapsed:_TIME_/g; - - my $line = $_; - - # we expect: - # start <argv0> [<argv1> [<argv2> [...]]] - # - # where argv0 might be a relative or absolute path, with - # or without quotes, and platform dependent. Replace argv0 - # with a token for HEREDOC matching in the test script. - - if ($line =~ m/^start/) { - $line =~ /^start\s+(.*)/; - my $argv = $1; - $argv =~ m/(\'[^\']*\'|[^ ]+)\s+(.*)/; - my $argv_0 = $1; - my $argv_rest = $2; - - print "start _EXE_ $argv_rest\n"; - } - elsif ($line =~ m/^cmd_path/) { - # Likewise, the 'cmd_path' message breaks out argv[0]. - # - # This line is only emitted when RUNTIME_PREFIX is defined, - # so just omit it for testing purposes. - # print "cmd_path _EXE_\n"; - } - elsif ($line =~ m/^cmd_ancestry/) { - # 'cmd_ancestry' is not implemented everywhere, so for portability's - # sake, skip it when parsing normal. - # - # print "$line"; - } - else { - print "$line"; - } -} diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh index bac9046540..760cf69087 100755 --- a/t/t0211-trace2-perf.sh +++ b/t/t0211-trace2-perf.sh @@ -4,6 +4,12 @@ test_description='test trace2 facility (perf target)' . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping trace2 tests; Perl not available' + test_done +fi + # Turn off any inherited trace2 settings for this test. sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT sane_unset GIT_TRACE2_PERF_BRIEF diff --git a/t/t0411-clone-from-partial.sh b/t/t0411-clone-from-partial.sh index 196fc61784..9e6bca5625 100755 --- a/t/t0411-clone-from-partial.sh +++ b/t/t0411-clone-from-partial.sh @@ -59,6 +59,12 @@ test_expect_success 'pack-objects should fetch from promisor remote and execute test_expect_success 'clone from promisor remote does not lazy-fetch by default' ' rm -f script-executed && + + # The --path-walk feature of "git pack-objects" is not + # compatible with this kind of fetch from an incomplete repo. + GIT_TEST_PACK_PATH_WALK=0 && + export GIT_TEST_PACK_PATH_WALK && + test_must_fail git clone evil no-lazy 2>err && test_grep "lazy fetching disabled" err && test_path_is_missing script-executed diff --git a/t/t0450/adoc-help-mismatches b/t/t0450/adoc-help-mismatches index c4a15fd0cb..06b469bdee 100644 --- a/t/t0450/adoc-help-mismatches +++ b/t/t0450/adoc-help-mismatches @@ -38,7 +38,6 @@ merge-one-file multi-pack-index name-rev notes -pack-objects push range-diff rebase diff --git a/t/t0602-reffiles-fsck.sh b/t/t0602-reffiles-fsck.sh index d4a08b823b..0ef483659d 100755 --- a/t/t0602-reffiles-fsck.sh +++ b/t/t0602-reffiles-fsck.sh @@ -14,222 +14,248 @@ test_expect_success 'ref name should be checked' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - - git commit --allow-empty -m initial && - git checkout -b default-branch && - git tag default-tag && - git tag multi_hierarchy/default-tag && - - cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ && - git refs verify 2>err && - test_must_be_empty err && - rm $branch_dir_prefix/@ && - - cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock && - git refs verify 2>err && - rm $tag_dir_prefix/tag-1.lock && - test_must_be_empty err && - - cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/.lock: badRefName: invalid refname format - EOF - rm $tag_dir_prefix/.lock && - test_cmp expect err && - - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/$refname: badRefName: invalid refname format - EOF - rm "$branch_dir_prefix/$refname" && - test_cmp expect err || return 1 - done && + ( + cd repo && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/$refname: badRefName: invalid refname format - EOF - rm "$tag_dir_prefix/$refname" && - test_cmp expect err || return 1 - done && + git commit --allow-empty -m initial && + git checkout -b default-branch && + git tag default-tag && + git tag multi_hierarchy/default-tag && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format - EOF - rm "$tag_dir_prefix/multi_hierarchy/$refname" && - test_cmp expect err || return 1 - done && + cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ && + git refs verify 2>err && + test_must_be_empty err && + rm $branch_dir_prefix/@ && - for refname in ".refname-starts-with-dot" "~refname-has-stride" - do - mkdir "$branch_dir_prefix/$refname" && - cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" && + cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock && + git refs verify 2>err && + rm $tag_dir_prefix/tag-1.lock && + test_must_be_empty err && + + cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: refs/heads/$refname/default-branch: badRefName: invalid refname format + error: refs/tags/.lock: badRefName: invalid refname format EOF - rm -r "$branch_dir_prefix/$refname" && - test_cmp expect err || return 1 - done + rm $tag_dir_prefix/.lock && + test_cmp expect err && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/$refname: badRefName: invalid refname format + EOF + rm "$branch_dir_prefix/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/tags/$refname: badRefName: invalid refname format + EOF + rm "$tag_dir_prefix/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format + EOF + rm "$tag_dir_prefix/multi_hierarchy/$refname" && + test_cmp expect err || return 1 + done && + + for refname in ".refname-starts-with-dot" "~refname-has-stride" + do + mkdir "$branch_dir_prefix/$refname" && + cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/$refname/default-branch: badRefName: invalid refname format + EOF + rm -r "$branch_dir_prefix/$refname" && + test_cmp expect err || return 1 + done + ) ' test_expect_success 'ref name check should be adapted into fsck messages' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - git commit --allow-empty -m initial && - git checkout -b branch-1 && - - cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && - git -c fsck.badRefName=warn refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/.branch-1: badRefName: invalid refname format - EOF - rm $branch_dir_prefix/.branch-1 && - test_cmp expect err && - - cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && - git -c fsck.badRefName=ignore refs verify 2>err && - test_must_be_empty err + ( + cd repo && + git commit --allow-empty -m initial && + git checkout -b branch-1 && + + cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && + git -c fsck.badRefName=warn refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/.branch-1: badRefName: invalid refname format + EOF + rm $branch_dir_prefix/.branch-1 && + test_cmp expect err && + + cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 && + git -c fsck.badRefName=ignore refs verify 2>err && + test_must_be_empty err + ) ' -test_expect_success 'ref name check should work for multiple worktrees' ' +test_expect_success 'no refs directory of worktree should not cause problems' ' test_when_finished "rm -rf repo" && git init repo && - - cd repo && - test_commit initial && - git checkout -b branch-1 && - test_commit second && - git checkout -b branch-2 && - test_commit third && - git checkout -b branch-3 && - git worktree add ./worktree-1 branch-1 && - git worktree add ./worktree-2 branch-2 && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && - ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-3 - ) && - ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-3 - ) && - - cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' && - cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format - error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format - EOF - sort err >sorted_err && - test_cmp expect sorted_err && - - for worktree in "worktree-1" "worktree-2" - do + cd repo && + test_commit initial && + git worktree add --detach ./worktree && + ( - cd $worktree && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format - error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format - EOF - sort err >sorted_err && - test_cmp expect sorted_err || return 1 + cd worktree && + worktree_refdir="$(git rev-parse --git-dir)/refs" && + # Simulate old directory layout + rmdir "$worktree_refdir" && + git refs verify 2>err && + test_must_be_empty err ) - done + ) ' -test_expect_success 'regular ref content should be checked (individual)' ' +test_expect_success 'ref name check should work for multiple worktrees' ' test_when_finished "rm -rf repo" && git init repo && - branch_dir_prefix=.git/refs/heads && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit initial && + git checkout -b branch-1 && + test_commit second && + git checkout -b branch-2 && + test_commit third && + git checkout -b branch-3 && + git worktree add ./worktree-1 branch-1 && + git worktree add ./worktree-2 branch-2 && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + + ( + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-3 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-3 + ) && - git refs verify 2>err && - test_must_be_empty err && + cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' && + cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' && - for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$branch_dir_prefix/branch-bad && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: refs/heads/branch-bad: badRefContent: $bad_content + error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format + error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format EOF - rm $branch_dir_prefix/branch-bad && - test_cmp expect err || return 1 - done && + sort err >sorted_err && + test_cmp expect sorted_err && + + for worktree in "worktree-1" "worktree-2" + do + ( + cd $worktree && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format + error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format + EOF + sort err >sorted_err && + test_cmp expect sorted_err || return 1 + ) + done + ) +' - for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/a/b/branch-bad: badRefContent: $bad_content - EOF - rm $branch_dir_prefix/a/b/branch-bad && - test_cmp expect err || return 1 - done && - - printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $branch_dir_prefix/branch-no-newline && - test_cmp expect err && - - for trailing_content in " garbage" " more garbage" - do - printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage && +test_expect_success 'regular ref content should be checked (individual)' ' + test_when_finished "rm -rf repo" && + git init repo && + branch_dir_prefix=.git/refs/heads && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + git refs verify 2>err && + test_must_be_empty err && + + for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$branch_dir_prefix/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad: badRefContent: $bad_content + EOF + rm $branch_dir_prefix/branch-bad && + test_cmp expect err || return 1 + done && + + for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/a/b/branch-bad: badRefContent: $bad_content + EOF + rm $branch_dir_prefix/a/b/branch-bad && + test_cmp expect err || return 1 + done && + + printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && git refs verify 2>err && cat >expect <<-EOF && - warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end EOF - rm $branch_dir_prefix/branch-garbage && - test_cmp expect err || return 1 - done && + rm $branch_dir_prefix/branch-no-newline && + test_cmp expect err && - printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' - '\'' - EOF - rm $branch_dir_prefix/branch-garbage-special && - test_cmp expect err && - printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' + '\'' + EOF + rm $branch_dir_prefix/branch-garbage-special && + test_cmp expect err && + printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\'' - garbage'\'' - EOF - rm $branch_dir_prefix/branch-garbage-special && - test_cmp expect err + + garbage'\'' + EOF + rm $branch_dir_prefix/branch-garbage-special && + test_cmp expect err + ) ' test_expect_success 'regular ref content should be checked (aggregate)' ' @@ -237,99 +263,103 @@ test_expect_success 'regular ref content should be checked (aggregate)' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - bad_content_1=$(git rev-parse main)x && - bad_content_2=xfsazqfxcadas && - bad_content_3=Xfsazqfxcadas && - printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 && - printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 && - printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad && - printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && - printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3 - error: refs/tags/tag-bad-1: badRefContent: $bad_content_1 - error: refs/tags/tag-bad-2: badRefContent: $bad_content_2 - warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - sort err >sorted_err && - test_cmp expect sorted_err + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + bad_content_1=$(git rev-parse main)x && + bad_content_2=xfsazqfxcadas && + bad_content_3=Xfsazqfxcadas && + printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 && + printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 && + printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad && + printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline && + printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3 + error: refs/tags/tag-bad-1: badRefContent: $bad_content_1 + error: refs/tags/tag-bad-2: badRefContent: $bad_content_2 + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end + EOF + sort err >sorted_err && + test_cmp expect sorted_err + ) ' test_expect_success 'textual symref content should be checked (individual)' ' test_when_finished "rm -rf repo" && git init repo && branch_dir_prefix=.git/refs/heads && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + for good_referent in "refs/heads/branch" "HEAD" + do + printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + git refs verify 2>err && + rm $branch_dir_prefix/branch-good && + test_must_be_empty err || return 1 + done && + + for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch" + do + printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\'' + EOF + rm $branch_dir_prefix/branch-bad && + test_cmp expect err || return 1 + done && - for good_referent in "refs/heads/branch" "HEAD" - do - printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline && git refs verify 2>err && - rm $branch_dir_prefix/branch-good && - test_must_be_empty err || return 1 - done && + cat >expect <<-EOF && + warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end + EOF + rm $branch_dir_prefix/branch-no-newline && + test_cmp expect err && - for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch" - do - printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad && - test_must_fail git refs verify 2>err && + printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-1 && + test_cmp expect err && + + printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-2 && + test_cmp expect err && + + printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && + git refs verify 2>err && cat >expect <<-EOF && - error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\'' - EOF - rm $branch_dir_prefix/branch-bad && - test_cmp expect err || return 1 - done && - - printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $branch_dir_prefix/branch-no-newline && - test_cmp expect err && - - printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-1 && - test_cmp expect err && - - printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-2 && - test_cmp expect err && - - printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-trailing-3 && - test_cmp expect err && - - printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines - EOF - rm $branch_dir_prefix/a/b/branch-complicated && - test_cmp expect err + warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-trailing-3 && + test_cmp expect err && + + printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines + EOF + rm $branch_dir_prefix/a/b/branch-complicated && + test_cmp expect err + ) ' test_expect_success 'textual symref content should be checked (aggregate)' ' @@ -337,32 +367,34 @@ test_expect_success 'textual symref content should be checked (aggregate)' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good && - printf "ref: HEAD\n" >$branch_dir_prefix/branch-head && - printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 && - printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && - printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && - printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && - printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && - printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 && - - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\'' - warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end - warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines - warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end - EOF - sort err >sorted_err && - test_cmp expect sorted_err + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good && + printf "ref: HEAD\n" >$branch_dir_prefix/branch-head && + printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 && + printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 && + printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 && + printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 && + printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated && + printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 && + + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\'' + warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end + warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines + warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end + EOF + sort err >sorted_err && + test_cmp expect sorted_err + ) ' test_expect_success 'the target of the textual symref should be checked' ' @@ -370,230 +402,507 @@ test_expect_success 'the target of the textual symref should be checked' ' git init repo && branch_dir_prefix=.git/refs/heads && tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && + + for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag" + do + printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + git refs verify 2>err && + rm $branch_dir_prefix/branch-good && + test_must_be_empty err || return 1 + done && + + for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch" + do + printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\'' + EOF + rm $branch_dir_prefix/branch-bad-1 && + test_cmp expect err || return 1 + done + ) +' + +test_expect_success SYMLINKS 'symlink symref content should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + branch_dir_prefix=.git/refs/heads && + tag_dir_prefix=.git/refs/tags && + ( + cd repo && + test_commit default && + mkdir -p "$branch_dir_prefix/a/b" && - for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag" - do - printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good && + ln -sf ./main $branch_dir_prefix/branch-symbolic-good && git refs verify 2>err && - rm $branch_dir_prefix/branch-good && - test_must_be_empty err || return 1 - done && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $branch_dir_prefix/branch-symbolic-good && + test_cmp expect err && - for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch" - do - printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 && + ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic && git refs verify 2>err && cat >expect <<-EOF && - warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\'' + warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref + warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' + EOF + rm $branch_dir_prefix/branch-symbolic && + test_cmp expect err && + + ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref + error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\'' + EOF + rm $branch_dir_prefix/branch-symbolic-bad && + test_cmp expect err && + + ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref + error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\'' EOF - rm $branch_dir_prefix/branch-bad-1 && - test_cmp expect err || return 1 - done + rm $tag_dir_prefix/tag-symbolic-1 && + test_cmp expect err + ) ' -test_expect_success SYMLINKS 'symlink symref content should be checked' ' +test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' ' test_when_finished "rm -rf repo" && git init repo && - branch_dir_prefix=.git/refs/heads && - tag_dir_prefix=.git/refs/tags && - cd repo && - test_commit default && - mkdir -p "$branch_dir_prefix/a/b" && - - ln -sf ./main $branch_dir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $branch_dir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref - warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' - EOF - rm $branch_dir_prefix/branch-symbolic && - test_cmp expect err && - - ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref - error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\'' - EOF - rm $branch_dir_prefix/branch-symbolic-bad && - test_cmp expect err && - - ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 && - test_must_fail git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref - error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\'' - EOF - rm $tag_dir_prefix/tag-symbolic-1 && - test_cmp expect err + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git worktree add ./worktree-1 branch-2 && + git worktree add ./worktree-2 branch-3 && + main_worktree_refdir_prefix=.git/refs/heads && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + + ( + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + + ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $worktree1_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $worktree2_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good && + git refs verify 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref + EOF + rm $main_worktree_refdir_prefix/branch-symbolic-good && + test_cmp expect err && + + ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic && + git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref + warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' + EOF + rm $worktree1_refdir_prefix/branch-symbolic && + test_cmp expect err && + + for bad_referent_name in ".tag" "branch " + do + ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\'' + EOF + rm $worktree1_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + EOF + rm $worktree1_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\'' + EOF + rm $worktree2_refdir_prefix/bad-symbolic && + test_cmp expect err && + + ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref + error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + EOF + rm $worktree2_refdir_prefix/bad-symbolic && + test_cmp expect err || return 1 + done + ) ' -test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' ' +test_expect_success 'ref content checks should work with worktrees' ' test_when_finished "rm -rf repo" && git init repo && - cd repo && - test_commit default && - git branch branch-1 && - git branch branch-2 && - git branch branch-3 && - git worktree add ./worktree-1 branch-2 && - git worktree add ./worktree-2 branch-3 && - main_worktree_refdir_prefix=.git/refs/heads && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && - - ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && - - ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $worktree1_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $worktree2_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good && - git refs verify 2>err && - cat >expect <<-EOF && - warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref - EOF - rm $main_worktree_refdir_prefix/branch-symbolic-good && - test_cmp expect err && - - ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref - warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\'' - EOF - rm $worktree1_refdir_prefix/branch-symbolic && - test_cmp expect err && - - for bad_referent_name in ".tag" "branch " - do - ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && - test_must_fail git refs verify 2>err && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git worktree add ./worktree-1 branch-2 && + git worktree add ./worktree-2 branch-3 && + worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && + worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + + ( + cd worktree-1 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + ( + cd worktree-2 && + git update-ref refs/worktree/branch-4 refs/heads/branch-1 + ) && + + for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content + EOF + rm $worktree1_refdir_prefix/bad-branch-1 && + test_cmp expect err || return 1 + done && + + for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" + do + printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content + EOF + rm $worktree2_refdir_prefix/bad-branch-2 && + test_cmp expect err || return 1 + done && + + printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline && + git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\'' + warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end EOF - rm $worktree1_refdir_prefix/bad-symbolic && + rm $worktree1_refdir_prefix/branch-no-newline && test_cmp expect err && - ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic && - test_must_fail git refs verify 2>err && + printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage && + git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' EOF - rm $worktree1_refdir_prefix/bad-symbolic && - test_cmp expect err && + rm $worktree1_refdir_prefix/branch-garbage && + test_cmp expect err + ) +' - ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && +test_expect_success SYMLINKS 'the filetype of packed-refs should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git branch branch-3 && + git pack-refs --all && + + mv .git/packed-refs .git/packed-refs-back && + ln -sf packed-refs-back .git/packed-refs && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\'' + error: packed-refs: badRefFiletype: not a regular file but a symlink EOF - rm $worktree2_refdir_prefix/bad-symbolic && + rm .git/packed-refs && test_cmp expect err && - ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic && + mkdir .git/packed-refs && test_must_fail git refs verify 2>err && cat >expect <<-EOF && - warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref - error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\'' + error: packed-refs: badRefFiletype: not a regular file EOF - rm $worktree2_refdir_prefix/bad-symbolic && - test_cmp expect err || return 1 - done + rm -r .git/packed-refs && + test_cmp expect err + ) ' -test_expect_success 'ref content checks should work with worktrees' ' +test_expect_success 'empty packed-refs should be reported' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + >.git/packed-refs && + git refs verify 2>err && + cat >expect <<-EOF && + warning: packed-refs: emptyPackedRefsFile: file is empty + EOF + rm .git/packed-refs && + test_cmp expect err + ) +' + +test_expect_success 'packed-refs header should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + git refs verify 2>err && + test_must_be_empty err && + + for bad_header in "# pack-refs wit: peeled fully-peeled sorted " \ + "# pack-refs with traits: peeled fully-peeled sorted " \ + "# pack-refs with a: peeled fully-peeled" \ + "# pack-refs with:peeled fully-peeled sorted" + do + printf "%s\n" "$bad_header" >.git/packed-refs && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs.header: badPackedRefHeader: '\''$bad_header'\'' does not start with '\''# pack-refs with: '\'' + EOF + rm .git/packed-refs && + test_cmp expect err || return 1 + done + ) +' + +test_expect_success 'packed-refs missing header should not be reported' ' test_when_finished "rm -rf repo" && git init repo && - cd repo && - test_commit default && - git branch branch-1 && - git branch branch-2 && - git branch branch-3 && - git worktree add ./worktree-1 branch-2 && - git worktree add ./worktree-2 branch-3 && - worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree && - worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree && + ( + cd repo && + test_commit default && + + printf "$(git rev-parse HEAD) refs/heads/main\n" >.git/packed-refs && + git refs verify 2>err && + test_must_be_empty err + ) +' +test_expect_success 'packed-refs unknown traits should not be reported' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + + printf "# pack-refs with: peeled fully-peeled sorted foo\n" >.git/packed-refs && + git refs verify 2>err && + test_must_be_empty err + ) +' + +test_expect_success 'packed-refs content should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && ( - cd worktree-1 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + git tag -a annotated-tag-2 -m tag-2 && + + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_2_oid=$(git rev-parse annotated-tag-2) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + tag_2_peeled_oid=$(git rev-parse annotated-tag-2^{}) && + short_oid=$(printf "%s" $tag_1_peeled_oid | cut -c 1-4) && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $short_oid refs/heads/branch-1 + ${branch_1_oid}x + $branch_2_oid refs/heads/bad-branch + $branch_2_oid refs/heads/branch. + $tag_1_oid refs/tags/annotated-tag-3 + ^$short_oid + $tag_2_oid refs/tags/annotated-tag-4. + ^$tag_2_peeled_oid garbage + EOF + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs line 2: badPackedRefEntry: '\''$short_oid refs/heads/branch-1'\'' has invalid oid + error: packed-refs line 3: badPackedRefEntry: has no space after oid '\''$branch_1_oid'\'' but with '\''x'\'' + error: packed-refs line 4: badRefName: has bad refname '\'' refs/heads/bad-branch'\'' + error: packed-refs line 5: badRefName: has bad refname '\''refs/heads/branch.'\'' + error: packed-refs line 7: badPackedRefEntry: '\''$short_oid'\'' has invalid peeled oid + error: packed-refs line 8: badRefName: has bad refname '\''refs/tags/annotated-tag-4.'\'' + error: packed-refs line 9: badPackedRefEntry: has trailing garbage after peeled oid '\'' garbage'\'' + EOF + test_cmp expect err + ) +' + +test_expect_success 'packed-ref with sorted trait should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && ( - cd worktree-2 && - git update-ref refs/worktree/branch-4 refs/heads/branch-1 - ) && + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + refname1="refs/heads/main" && + refname2="refs/heads/foo" && + refname3="refs/tags/foo" && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + EOF + git refs verify 2>err && + rm .git/packed-refs && + test_must_be_empty err && - for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 && + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $branch_2_oid $refname1 + EOF + git refs verify 2>err && + rm .git/packed-refs && + test_must_be_empty err && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $branch_2_oid $refname1 + $branch_1_oid $refname2 + $tag_1_oid $refname3 + EOF test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content + error: packed-refs line 3: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname1'\'' EOF - rm $worktree1_refdir_prefix/bad-branch-1 && - test_cmp expect err || return 1 - done && + rm .git/packed-refs && + test_cmp expect err && - for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas" - do - printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 && + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled sorted + $tag_1_oid $refname3 + ^$tag_1_peeled_oid + $branch_2_oid $refname2 + EOF test_must_fail git refs verify 2>err && cat >expect <<-EOF && - error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content - EOF - rm $worktree2_refdir_prefix/bad-branch-2 && - test_cmp expect err || return 1 - done && - - printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end - EOF - rm $worktree1_refdir_prefix/branch-no-newline && - test_cmp expect err && - - printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage && - git refs verify 2>err && - cat >expect <<-EOF && - warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\'' - EOF - rm $worktree1_refdir_prefix/branch-garbage && - test_cmp expect err + error: packed-refs line 4: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname3'\'' + EOF + rm .git/packed-refs && + test_cmp expect err + ) +' + +test_expect_success 'packed-ref without sorted trait should not be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit default && + git branch branch-1 && + git branch branch-2 && + git tag -a annotated-tag-1 -m tag-1 && + branch_1_oid=$(git rev-parse branch-1) && + branch_2_oid=$(git rev-parse branch-2) && + tag_1_oid=$(git rev-parse annotated-tag-1) && + tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) && + refname1="refs/heads/main" && + refname2="refs/heads/foo" && + refname3="refs/tags/foo" && + + cat >.git/packed-refs <<-EOF && + # pack-refs with: peeled fully-peeled + $branch_2_oid $refname1 + $branch_1_oid $refname2 + EOF + git refs verify 2>err && + test_must_be_empty err + ) +' + +test_expect_success '--[no-]references option should apply to fsck' ' + test_when_finished "rm -rf repo" && + git init repo && + branch_dir_prefix=.git/refs/heads && + ( + cd repo && + test_commit default && + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck --references 2>err && + cat >expect <<-EOF && + warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\'' + EOF + rm $branch_dir_prefix/branch-garbage && + test_cmp expect err || return 1 + done && + + for trailing_content in " garbage" " more garbage" + do + printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage && + git fsck --no-references 2>err && + rm $branch_dir_prefix/branch-garbage && + test_must_be_empty err || return 1 + done + ) ' test_done diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh index 4618ffc108..1be534a895 100755 --- a/t/t0610-reftable-basics.sh +++ b/t/t0610-reftable-basics.sh @@ -14,6 +14,13 @@ export GIT_TEST_DEFAULT_REF_FORMAT INVALID_OID=$(test_oid 001) +test_expect_success 'pack-refs does not crash with -h' ' + test_expect_code 129 git pack-refs -h >usage && + test_grep "[Uu]sage: git pack-refs " usage && + test_expect_code 129 nongit git pack-refs -h >usage && + test_grep "[Uu]sage: git pack-refs " usage +' + test_expect_success 'init: creates basic reftable structures' ' test_when_finished "rm -rf repo" && git init repo && @@ -646,9 +653,8 @@ test_expect_success 'basic: commit and list refs' ' 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 && + + awk "BEGIN { for (i = 0; i < 50000; i++) printf \"%s\", \"this is a long commit message\" }" >commit-msg && git -C repo commit --allow-empty --file=../commit-msg ' diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh index e2708e11d5..6447920c9b 100755 --- a/t/t0613-reftable-write-options.sh +++ b/t/t0613-reftable-write-options.sh @@ -93,6 +93,9 @@ test_expect_success 'many refs results in multiple blocks' ' restarts: 3 - length: 3289 restarts: 3 + idx: + - length: 103 + restarts: 1 EOF test-tool dump-reftable -b .git/reftable/*.ref >actual && test_cmp expect actual @@ -145,7 +148,7 @@ test_expect_success 'small block size fails with large reflog message' ' ( cd repo && test_commit A && - perl -e "print \"a\" x 500" >logmsg && + test-tool genzeros 500 | tr "\000" "a" >logmsg && cat >expect <<-EOF && fatal: update_ref failed for ref ${SQ}refs/heads/logme${SQ}: reftable: transaction failure: entry too large EOF @@ -241,6 +244,9 @@ test_expect_success 'object index gets written by default with ref index' ' restarts: 1 - length: 80 restarts: 1 + idx: + - length: 55 + restarts: 2 obj: - length: 11 restarts: 1 @@ -277,6 +283,9 @@ test_expect_success 'object index can be disabled' ' restarts: 1 - length: 80 restarts: 1 + idx: + - length: 55 + restarts: 2 EOF test-tool dump-reftable -b .git/reftable/*.ref >actual && test_cmp expect actual diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 4a88bb9ef0..2e8d9384e1 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -362,7 +362,7 @@ test_expect_success 'a/b (untracked) vs a case setup.' ' test_expect_success 'a/b (untracked) vs a, plus c/d case test.' ' read_tree_u_must_fail -u -m "$treeH" "$treeM" && git ls-files --stage && - test -f a/b + test_path_is_file a/b ' test_expect_success 'read-tree supports the super-prefix' ' diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 398865d6eb..f123ef1e36 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -3,6 +3,7 @@ test_description='git cat-file' . ./test-lib.sh +. "$TEST_DIRECTORY/lib-loose.sh" test_cmdmode_usage () { test_expect_code 129 "$@" 2>err && @@ -112,65 +113,55 @@ strlen () { run_tests () { type=$1 - oid=$2 - size=$3 - content=$4 - pretty_content=$5 + object_name="$2" + mode=$3 + size=$4 + content=$5 + pretty_content=$6 + oid=${7:-"$object_name"} batch_output="$oid $type $size $content" test_expect_success "$type exists" ' - git cat-file -e $oid + git cat-file -e "$object_name" ' test_expect_success "Type of $type is correct" ' echo $type >expect && - git cat-file -t $oid >actual && + git cat-file -t "$object_name" >actual && test_cmp expect actual ' test_expect_success "Size of $type is correct" ' echo $size >expect && - 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 $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 $oid >actual && + git cat-file -s "$object_name" >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 $oid >actual && + git cat-file $type "$object_name" >actual && test_cmp expect actual ' test_expect_success "Pretty content of $type is correct" ' echo_without_newline "$pretty_content" >expect && - git cat-file -p $oid >actual && + git cat-file -p "$object_name" >actual && test_cmp expect actual ' test -z "$content" || test_expect_success "--batch output of $type is correct" ' echo "$batch_output" >expect && - echo $oid | git cat-file --batch >actual && + echo "$object_name" | git cat-file --batch >actual && test_cmp expect actual ' test_expect_success "--batch-check output of $type is correct" ' echo "$oid $type $size" >expect && - echo_without_newline $oid | git cat-file --batch-check >actual && + echo_without_newline "$object_name" | git cat-file --batch-check >actual && test_cmp expect actual ' @@ -179,13 +170,13 @@ $content" test -z "$content" || test_expect_success "--batch-command $opt output of $type content is correct" ' echo "$batch_output" >expect && - test_write_lines "contents $oid" | git cat-file --batch-command $opt >actual && + test_write_lines "contents $object_name" | git cat-file --batch-command $opt >actual && test_cmp expect actual ' test_expect_success "--batch-command $opt output of $type info is correct" ' echo "$oid $type $size" >expect && - test_write_lines "info $oid" | + test_write_lines "info $object_name" | git cat-file --batch-command $opt >actual && test_cmp expect actual ' @@ -193,30 +184,45 @@ $content" test_expect_success "custom --batch-check format" ' echo "$type $oid" >expect && - echo $oid | git cat-file --batch-check="%(objecttype) %(objectname)" >actual && + echo "$object_name" | git cat-file --batch-check="%(objecttype) %(objectname)" >actual && test_cmp expect actual ' test_expect_success "custom --batch-command format" ' echo "$type $oid" >expect && - echo "info $oid" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual && + echo "info $object_name" | git cat-file --batch-command="%(objecttype) %(objectname)" >actual && test_cmp expect actual ' - test_expect_success '--batch-check with %(rest)' ' + # FIXME: %(rest) is incompatible with object names that include whitespace, + # e.g. HEAD:path/to/a/file with spaces. Use the resolved OID as input to + # test this instead of the raw object name. + if echo "$object_name" | grep " "; then + test_rest=test_expect_failure + else + test_rest=test_expect_success + fi + + $test_rest '--batch-check with %(rest)' ' echo "$type this is some extra content" >expect && - echo "$oid this is some extra content" | + echo "$object_name this is some extra content" | git cat-file --batch-check="%(objecttype) %(rest)" >actual && test_cmp expect actual ' + test_expect_success '--batch-check with %(objectmode)' ' + echo "$mode $oid" >expect && + echo $object_name | git cat-file --batch-check="%(objectmode) %(objectname)" >actual && + test_cmp expect actual + ' + test -z "$content" || test_expect_success "--batch without type ($type)" ' { echo "$size" && echo "$content" } >expect && - echo $oid | git cat-file --batch="%(objectsize)" >actual && + echo "$object_name" | git cat-file --batch="%(objectsize)" >actual && test_cmp expect actual ' @@ -226,7 +232,7 @@ $content" echo "$type" && echo "$content" } >expect && - echo $oid | git cat-file --batch="%(objecttype)" >actual && + echo "$object_name" | git cat-file --batch="%(objecttype)" >actual && test_cmp expect actual ' } @@ -241,13 +247,14 @@ test_expect_success "setup" ' git config extensions.compatobjectformat $test_compat_hash_algo && echo_without_newline "$hello_content" > hello && git update-index --add hello && + echo_without_newline "$hello_content" > "path with spaces" && + git update-index --add --chmod=+x "path with spaces" && git commit -m "add hello file" ' run_blob_tests () { oid=$1 - - run_tests 'blob' $oid $hello_size "$hello_content" "$hello_content" + 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 && @@ -280,13 +287,17 @@ test_expect_success '--batch-check without %(rest) considers whole line' ' 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_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_oid $tree_size "" "$tree_pretty_content" -run_tests 'tree' $tree_compat_oid $tree_compat_size "" "$tree_compat_pretty_content" +tree_size=$((2 * $(test_oid rawsz) + 13 + 24)) +tree_compat_size=$((2 * $(test_oid --hash=compat rawsz) + 13 + 24)) +tree_pretty_content="100644 blob $hello_oid hello${LF}100755 blob $hello_oid path with spaces${LF}" +tree_compat_pretty_content="100644 blob $hello_compat_oid hello${LF}100755 blob $hello_compat_oid path with spaces${LF}" + +run_tests 'tree' $tree_oid "" $tree_size "" "$tree_pretty_content" +run_tests 'tree' $tree_compat_oid "" $tree_compat_size "" "$tree_compat_pretty_content" +run_tests 'blob' "$tree_oid:hello" "100644" $hello_size "" "$hello_content" $hello_oid +run_tests 'blob' "$tree_compat_oid:hello" "100644" $hello_size "" "$hello_content" $hello_compat_oid +run_tests 'blob' "$tree_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_oid +run_tests 'blob' "$tree_compat_oid:path with spaces" "100755" $hello_size "" "$hello_content" $hello_compat_oid commit_message="Initial commit" commit_oid=$(echo_without_newline "$commit_message" | git commit-tree $tree_oid) @@ -305,8 +316,8 @@ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE $commit_message" -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" +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_oid="type blob tag hellotag @@ -329,8 +340,8 @@ tag_size=$(strlen "$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" +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 && @@ -669,103 +680,75 @@ test_expect_success 'setup bogus data' ' bogus_short_type="bogus" && bogus_short_content="bogus" && bogus_short_size=$(strlen "$bogus_short_content") && - bogus_short_oid=$(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" | loose_obj .git/objects $bogus_short_type) && bogus_long_type="abcdefghijklmnopqrstuvwxyz1234679" && bogus_long_content="bogus" && bogus_long_size=$(strlen "$bogus_long_content") && - bogus_long_oid=$(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" | loose_obj .git/objects $bogus_long_type) ' -for arg1 in '' --allow-unknown-type +for arg1 in -s -t -p do - for arg2 in -s -t -p - do - if test "$arg1" = "--allow-unknown-type" && test "$arg2" = "-p" - then - continue - fi + test_expect_success "cat-file $arg1 error on bogus short OID" ' + cat >expect <<-\EOF && + fatal: invalid object type + EOF + test_must_fail git cat-file $arg1 $bogus_short_oid >out 2>actual && + test_must_be_empty out && + test_cmp expect actual + ' - test_expect_success "cat-file $arg1 $arg2 error on bogus short OID" ' - cat >expect <<-\EOF && - fatal: invalid object type + test_expect_success "cat-file $arg1 error on bogus full OID" ' + if test "$arg1" = "-p" + then + cat >expect <<-EOF + 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_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_oid - else - test_must_fail git cat-file $arg1 $arg2 $bogus_short_oid >out 2>actual && - test_must_be_empty out && - test_cmp expect actual - fi - ' + test_must_fail git cat-file $arg1 $bogus_long_oid >out 2>actual && + test_must_be_empty out && + test_cmp expect actual + ' - test_expect_success "cat-file $arg1 $arg2 error on bogus full OID" ' - if test "$arg2" = "-p" - then - cat >expect <<-EOF - 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_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_oid - else - test_must_fail git cat-file $arg1 $arg2 $bogus_long_oid >out 2>actual && - test_must_be_empty out && - test_cmp expect actual - fi - ' + test_expect_success "cat-file $arg1 error on missing short OID" ' + cat >expect.err <<-EOF && + fatal: Not a valid object name $(test_oid deadbeef_short) + EOF + test_must_fail git cat-file $arg1 $(test_oid deadbeef_short) >out 2>err.actual && + test_must_be_empty out && + test_cmp expect.err err.actual + ' - test_expect_success "cat-file $arg1 $arg2 error on missing short OID" ' - cat >expect.err <<-EOF && - fatal: Not a valid object name $(test_oid deadbeef_short) + test_expect_success "cat-file $arg1 error on missing full OID" ' + if test "$arg1" = "-p" + then + cat >expect.err <<-EOF + fatal: Not a valid object name $(test_oid deadbeef) EOF - test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual && - test_must_be_empty out && - test_cmp expect.err err.actual - ' - - test_expect_success "cat-file $arg1 $arg2 error on missing full OID" ' - if test "$arg2" = "-p" - then - cat >expect.err <<-EOF - fatal: Not a valid object name $(test_oid deadbeef) - EOF - else - cat >expect.err <<-\EOF - fatal: git cat-file: could not get object info - EOF - fi && - test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef) >out 2>err.actual && - test_must_be_empty out && - test_cmp expect.err err.actual - ' - done + else + cat >expect.err <<-\EOF + fatal: git cat-file: could not get object info + EOF + fi && + test_must_fail git cat-file $arg1 $(test_oid deadbeef) >out 2>err.actual && + test_must_be_empty out && + test_cmp expect.err err.actual + ' done -test_expect_success '-e is OK with a broken object without --allow-unknown-type' ' +test_expect_success '-e is OK with a broken object' ' 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_oid -' - -test_expect_success '-p cannot print a broken object even with --allow-unknown-type' ' - 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" @@ -788,60 +771,8 @@ test_expect_success 'broken types combined with --batch and --batch-check' ' test_cmp err.expect err.actual ' -test_expect_success 'the --batch and --batch-check options do not combine with --allow-unknown-type' ' - test_expect_code 128 git cat-file --batch --allow-unknown-type <bogus-oid && - test_expect_code 128 git cat-file --batch-check --allow-unknown-type <bogus-oid -' - -test_expect_success 'the --allow-unknown-type option does not consider replacement refs' ' - cat >expect <<-EOF && - $bogus_short_type - EOF - 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_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_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_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_oid >actual && - test_cmp expect actual -' - -test_expect_success 'clean up broken object' ' - 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_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_oid >actual && - test_cmp expect actual -' - -test_expect_success 'clean up broken object' ' +test_expect_success 'clean up broken objects' ' + rm .git/objects/$(test_oid_to_path $bogus_short_oid) && rm .git/objects/$(test_oid_to_path $bogus_long_oid) ' @@ -903,6 +834,40 @@ test_expect_success 'cat-file -t and -s on corrupt loose object' ' ) ' +test_expect_success 'object reading handles zlib dictionary' - <<\EOT + echo 'content that will be recompressed' >file && + blob=$(git hash-object -w file) && + objpath=.git/objects/$(test_oid_to_path "$blob") && + + # Recompress a loose object using a precomputed zlib dictionary. + # This was originally done with: + # + # perl -MCompress::Raw::Zlib -e ' + # binmode STDIN; + # binmode STDOUT; + # my $data = do { local $/; <STDIN> }; + # my $in = new Compress::Raw::Zlib::Inflate; + # my $de = new Compress::Raw::Zlib::Deflate( + # -Dictionary => "anything" + # ); + # $in->inflate($data, $raw); + # $de->deflate($raw, $out); + # print $out; + # ' <obj.bak >$objpath + # + # but we do not want to require the perl module for all test runs (nor + # carry a custom t/helper program that uses zlib features we don't + # otherwise care about). + mv "$objpath" obj.bak && + test_when_finished 'mv obj.bak "$objpath"' && + printf '\170\273\017\112\003\143' >$objpath && + + test_must_fail git cat-file blob $blob 2>err && + test_grep ! 'too long' err && + test_grep 'error: unable to unpack' err && + test_grep 'error: inflate: needs dictionary' err +EOT + # Tests for git cat-file --follow-symlinks test_expect_success 'prep for symlink tests' ' echo_without_newline "$hello_content" >morx && @@ -1255,6 +1220,31 @@ test_expect_success 'cat-file --batch-check respects replace objects' ' test_cmp expect actual ' +test_expect_success 'batch-check with a submodule' ' + # FIXME: this call to mktree is incompatible with compatObjectFormat + # because the submodule OID cannot be mapped to the compat hash algo. + test_unconfig extensions.compatobjectformat && + printf "160000 commit $(test_oid deadbeef)\tsub\n" >tree-with-sub && + tree=$(git mktree <tree-with-sub) && + test_config extensions.compatobjectformat $test_compat_hash_algo && + + git cat-file --batch-check >actual <<-EOF && + $tree:sub + EOF + printf "$(test_oid deadbeef) submodule\n" >expect && + test_cmp expect actual +' + +test_expect_success 'batch-check with a submodule, object exists' ' + printf "160000 commit $commit_oid\tsub\n" >tree-with-sub && + tree=$(git mktree <tree-with-sub) && + git cat-file --batch-check >actual <<-EOF && + $tree:sub + EOF + printf "$commit_oid commit $commit_size\n" >expect && + test_cmp expect actual +' + # Pull the entry for object with oid "$1" out of the output of # "cat-file --batch", including its object content (which requires # parsing and reading a set amount of bytes, hence perl). @@ -1270,7 +1260,7 @@ extract_batch_output () { ' "$@" } -test_expect_success 'cat-file --batch-all-objects --batch ignores replace' ' +test_expect_success PERL_TEST_HELPERS 'cat-file --batch-all-objects --batch ignores replace' ' git cat-file --batch-all-objects --batch >actual.raw && extract_batch_output $orig <actual.raw >actual && { @@ -1323,7 +1313,7 @@ test_expect_success 'batch-command flush without --buffer' ' grep "^fatal:.*flush is only for --buffer mode.*" err ' -script=' +perl_script=' use warnings; use strict; use IPC::Open2; @@ -1345,12 +1335,115 @@ $? == 0 or die "\$?=$?"; expect="$hello_oid blob $hello_size" -test_expect_success PERL '--batch-check is unbuffered by default' ' - perl -e "$script" -- --batch-check $hello_oid "$expect" +test_lazy_prereq PERL_IPC_OPEN2 ' + perl -MIPC::Open2 -e "exit 0" ' -test_expect_success PERL '--batch-command info is unbuffered by default' ' - perl -e "$script" -- --batch-command $hello_oid "$expect" "info " +test_expect_success PERL_IPC_OPEN2 '--batch-check is unbuffered by default' ' + perl -e "$perl_script" -- --batch-check $hello_oid "$expect" ' +test_expect_success PERL_IPC_OPEN2 '--batch-command info is unbuffered by default' ' + perl -e "$perl_script" -- --batch-command $hello_oid "$expect" "info " +' + +test_expect_success 'setup for objects filter' ' + git init repo && + ( + # Seed the repository with four different sets of objects: + # + # - The first set is fully packed and has a bitmap. + # - The second set is packed, but has no bitmap. + # - The third set is loose. + # - The fourth set is loose and contains big objects. + # + # This ensures that we cover all these types as expected. + cd repo && + test_commit first && + git repack -Adb && + test_commit second && + git repack -d && + test_commit third && + + for n in 1000 10000 + do + printf "%"$n"s" X >large.$n || return 1 + done && + git add large.* && + git commit -m fourth + ) +' + +test_expect_success 'objects filter with unknown option' ' + cat >expect <<-EOF && + fatal: invalid filter-spec ${SQ}unknown${SQ} + EOF + test_must_fail git -C repo cat-file --filter=unknown 2>err && + test_cmp expect err +' + +for option in sparse:oid=1234 tree:1 sparse:path=x +do + test_expect_success "objects filter with unsupported option $option" ' + case "$option" in + tree:1) + echo "usage: objects filter not supported: ${SQ}tree${SQ}" >expect + ;; + sparse:path=x) + echo "fatal: sparse:path filters support has been dropped" >expect + ;; + *) + option_name=$(echo "$option" | cut -d= -f1) && + printf "usage: objects filter not supported: ${SQ}%s${SQ}\n" "$option_name" >expect + ;; + esac && + test_must_fail git -C repo cat-file --filter=$option 2>err && + test_cmp expect err + ' +done + +test_expect_success 'objects filter: disabled' ' + git -C repo cat-file --batch-check="%(objectname)" --batch-all-objects --no-filter >actual && + sort actual >actual.sorted && + git -C repo rev-list --objects --no-object-names --all >expect && + sort expect >expect.sorted && + test_cmp expect.sorted actual.sorted +' + +test_objects_filter () { + filter="$1" + + test_expect_success "objects filter: $filter" ' + git -C repo cat-file --batch-check="%(objectname)" --batch-all-objects --filter="$filter" >actual && + sort actual >actual.sorted && + git -C repo rev-list --objects --no-object-names --all --filter="$filter" --filter-provided-objects >expect && + sort expect >expect.sorted && + test_cmp expect.sorted actual.sorted + ' + + test_expect_success "objects filter prints excluded objects: $filter" ' + # Find all objects that would be excluded by the current filter. + git -C repo rev-list --objects --no-object-names --all >all && + git -C repo rev-list --objects --no-object-names --all --filter="$filter" --filter-provided-objects >filtered && + sort all >all.sorted && + sort filtered >filtered.sorted && + comm -23 all.sorted filtered.sorted >expected.excluded && + test_line_count -gt 0 expected.excluded && + + git -C repo cat-file --batch-check="%(objectname)" --filter="$filter" <expected.excluded >actual && + awk "/excluded/{ print \$1 }" actual | sort >actual.excluded && + test_cmp expected.excluded actual.excluded + ' +} + +test_objects_filter "blob:none" +test_objects_filter "blob:limit=1" +test_objects_filter "blob:limit=500" +test_objects_filter "blob:limit=1000" +test_objects_filter "blob:limit=1k" +test_objects_filter "object:type=blob" +test_objects_filter "object:type=commit" +test_objects_filter "object:type=tag" +test_objects_filter "object:type=tree" + test_done diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index a0481139de..64658b3ba5 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -30,7 +30,7 @@ setup_repo() { test_repo=test push_repo() { - test_create_repo $test_repo + git init --quiet $test_repo cd $test_repo setup_repo @@ -205,7 +205,7 @@ test_expect_success 'too-short tree' ' grep "too-short tree object" err ' -test_expect_success 'malformed mode in tree' ' +test_expect_success PERL_TEST_HELPERS 'malformed mode in tree' ' hex_oid=$(echo foo | git hash-object --stdin -w) && bin_oid=$(echo $hex_oid | hex2oct) && printf "9100644 \0$bin_oid" >tree-with-malformed-mode && @@ -213,7 +213,7 @@ test_expect_success 'malformed mode in tree' ' grep "malformed mode in tree entry" err ' -test_expect_success 'empty filename in tree' ' +test_expect_success PERL_TEST_HELPERS 'empty filename in tree' ' hex_oid=$(echo foo | git hash-object --stdin -w) && bin_oid=$(echo $hex_oid | hex2oct) && printf "100644 \0$bin_oid" >tree-with-empty-filename && @@ -221,7 +221,7 @@ test_expect_success 'empty filename in tree' ' grep "empty filename in tree entry" err ' -test_expect_success 'duplicate filename in tree' ' +test_expect_success PERL_TEST_HELPERS 'duplicate filename in tree' ' hex_oid=$(echo foo | git hash-object --stdin -w) && bin_oid=$(echo $hex_oid | hex2oct) && { @@ -248,15 +248,8 @@ test_expect_success 'hash-object complains about truncated type name' ' test_must_fail git hash-object -t bl --stdin </dev/null ' -test_expect_success '--literally' ' - t=1234567890 && - echo example | git hash-object -t $t --literally --stdin -' - -test_expect_success '--literally with extra-long type' ' - t=12345678901234567890123456789012345678901234567890 && - t="$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t" && - echo example | git hash-object -t $t --literally --stdin +test_expect_success '--literally complains about non-standard types' ' + test_must_fail git hash-object -t bogus --literally --stdin ' test_expect_success '--stdin outside of repository (uses SHA-1)' ' diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh index c291a2b33d..e9973f7494 100755 --- a/t/t1010-mktree.sh +++ b/t/t1010-mktree.sh @@ -42,13 +42,13 @@ test_expect_success 'ls-tree piped to mktree (2)' ' ' test_expect_success 'ls-tree output in wrong order given to mktree (1)' ' - perl -e "print reverse <>" <top | + sort -r <top | git mktree >actual && test_cmp tree actual ' test_expect_success 'ls-tree output in wrong order given to mktree (2)' ' - perl -e "print reverse <>" <top.withsub | + sort -r <top.withsub | git mktree >actual && test_cmp tree.withsub actual ' diff --git a/t/t1050-large.sh b/t/t1050-large.sh index c71932b024..5be273611a 100755 --- a/t/t1050-large.sh +++ b/t/t1050-large.sh @@ -6,7 +6,8 @@ test_description='adding and checking out large blobs' . ./test-lib.sh test_expect_success 'core.bigFileThreshold must be non-negative' ' - test_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err && + : >input && + test_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err && grep "bad numeric config value" err && test_must_be_empty out ' diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index a4c7c41fc0..d8101139b4 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -384,6 +384,44 @@ test_expect_success 'add, commit, checkout' ' test_all_match git checkout - ' +test_expect_success 'git add, checkout, and reset with -p' ' + init_repos && + + write_script edit-contents <<-\EOF && + echo text >>$1 + EOF + + # Does not expand when edits are within sparse checkout. + run_on_all ../edit-contents deep/a && + run_on_all ../edit-contents deep/deeper1/a && + + test_write_lines y n >in && + run_on_all git add -p <in && + test_all_match git status --porcelain=v2 && + test_all_match git reset -p <in && + + test_write_lines u 1 "" q >in && + run_on_all git add -i <in && + test_all_match git status --porcelain=v2 && + test_all_match git reset --hard && + + run_on_sparse mkdir -p folder1 && + run_on_all ../edit-contents folder1/a && + test_write_lines y n y >in && + run_on_all git add -p <in && + test_sparse_match git status --porcelain=v2 && + test_sparse_match git reset && + test_write_lines u 2 3 "" q >in && + run_on_all git add -i <in && + test_sparse_match git status --porcelain=v2 && + + run_on_all git add --sparse folder1 && + run_on_all git commit -m "take changes" && + test_write_lines y n y >in && + test_sparse_match git checkout HEAD~1 --patch <in && + test_sparse_match git status --porcelain=v2 +' + test_expect_success 'deep changes during checkout' ' init_repos && @@ -1340,6 +1378,30 @@ test_expect_success 'submodule handling' ' grep "160000 $(git -C initial-repo rev-parse HEAD) 0 modules/sub" cache ' +test_expect_success 'git apply functionality' ' + init_repos && + + test_all_match git checkout base && + + git -C full-checkout diff base..merge-right -- deep >patch-in-sparse && + git -C full-checkout diff base..merge-right -- folder2 >patch-outside && + + # Apply a patch to a file inside the sparse definition + test_all_match git apply --index --stat ../patch-in-sparse && + test_all_match git status --porcelain=v2 && + + # Apply a patch to a file outside the sparse definition + test_sparse_match test_must_fail git apply ../patch-outside && + grep "No such file or directory" sparse-checkout-err && + + # But it works with --index and --cached + test_all_match git apply --index --stat ../patch-outside && + test_all_match git status --porcelain=v2 && + test_all_match git reset --hard && + test_all_match git apply --cached --stat ../patch-outside && + test_all_match git status --porcelain=v2 +' + # When working with a sparse index, some commands will need to expand the # index to operate properly. If those commands also write the index back # to disk, they need to convert the index to sparse before writing. @@ -1486,7 +1548,6 @@ test_expect_success 'sparse-index is not expanded' ' ensure_not_expanded checkout -f update-deep && test_config -C sparse-index pull.twohead ort && ( - sane_unset GIT_TEST_MERGE_ALGORITHM && for OPERATION in "merge -m merge" cherry-pick rebase do ensure_not_expanded merge -m merge update-folder1 && @@ -1506,7 +1567,6 @@ test_expect_success 'sparse-index is not expanded: merge conflict in cone' ' done && ( - sane_unset GIT_TEST_MERGE_ALGORITHM && git -C sparse-index config pull.twohead ort && ensure_not_expanded ! merge -m merged expand-right ) @@ -2347,6 +2407,95 @@ test_expect_success 'sparse-index is not expanded: check-attr' ' ensure_not_expanded check-attr -a --cached -- folder1/a ' +test_expect_success 'sparse-index is not expanded: git apply' ' + init_repos && + + git -C sparse-index checkout base && + git -C full-checkout diff base..merge-right -- deep >patch-in-sparse && + git -C full-checkout diff base..merge-right -- folder2 >patch-outside && + + # Apply a patch to a file inside the sparse definition + ensure_not_expanded apply --index --stat ../patch-in-sparse && + + # Apply a patch to a file outside the sparse definition + # Fails when caring about the worktree. + ensure_not_expanded ! apply ../patch-outside && + + # Expands when using --index. + ensure_expanded apply --index ../patch-outside && + + # Does not when index is partially expanded. + git -C sparse-index reset --hard && + ensure_not_expanded apply --cached ../patch-outside && + + # Try again with a reset and collapsed index. + git -C sparse-index reset --hard && + git -C sparse-index sparse-checkout reapply && + + # Expands when index is collapsed. + ensure_expanded apply --cached ../patch-outside +' + +test_expect_success 'sparse-index is not expanded: git add -p' ' + init_repos && + + # Does not expand when edits are within sparse checkout. + echo "new content" >sparse-index/deep/a && + echo "new content" >sparse-index/deep/deeper1/a && + test_write_lines y n >in && + ensure_not_expanded add -p <in && + git -C sparse-index reset && + ensure_not_expanded add -i <in && + + # -p does expand when edits are outside sparse checkout. + mkdir -p sparse-index/folder1 && + echo "new content" >sparse-index/folder1/a && + test_write_lines y n y >in && + ensure_expanded add -p <in && + + # Fully reset the index. + git -C sparse-index reset --hard && + git -C sparse-index sparse-checkout reapply && + + # -i does expand when edits are outside sparse checkout. + mkdir -p sparse-index/folder1 && + echo "new content" >sparse-index/folder1/a && + test_write_lines u 2 3 "" q >in && + ensure_expanded add -i <in +' + +test_expect_success 'sparse-index is not expanded: checkout -p, reset -p' ' + init_repos && + + # Does not expand when edits are within sparse checkout. + echo "new content" >sparse-index/deep/a && + echo "new content" >sparse-index/deep/deeper1/a && + git -C sparse-index commit -a -m "inside-changes" && + + test_write_lines y y >in && + ensure_not_expanded checkout HEAD~1 --patch <in && + + echo "new content" >sparse-index/deep/a && + echo "new content" >sparse-index/deep/deeper1/a && + git -C sparse-index add . && + ensure_not_expanded reset --patch <in && + + # -p does expand when edits are outside sparse checkout. + mkdir -p sparse-index/folder1 && + echo "new content" >sparse-index/folder1/a && + git -C sparse-index add --sparse folder1 && + git -C sparse-index sparse-checkout reapply && + ensure_expanded reset --patch <in && + + # Fully reset the index. + mkdir -p sparse-index/folder1 && + echo "new content" >sparse-index/folder1/a && + git -C sparse-index add --sparse folder1 && + git -C sparse-index commit -m "folder1 change" && + git -C sparse-index sparse-checkout reapply && + ensure_expanded checkout HEAD~1 --patch <in +' + test_expect_success 'advice.sparseIndexExpanded' ' init_repos && diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index 29045aad43..d29d23cb89 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -2066,6 +2066,239 @@ do grep "$(git rev-parse $a) $(git rev-parse $a)" actual ' + test_expect_success "stdin $type batch-updates" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit commit && + head=$(git rev-parse HEAD) && + + format_command $type "update refs/heads/ref1" "$head" "$Z" >stdin && + format_command $type "update refs/heads/ref2" "$head" "$Z" >>stdin && + git update-ref $type --stdin --batch-updates <stdin && + echo $head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + git rev-parse refs/heads/ref2 >actual && + test_cmp expect actual + ) + ' + + test_expect_success "stdin $type batch-updates with invalid new_oid" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref1 $head && + git update-ref refs/heads/ref2 $head && + + format_command $type "update refs/heads/ref1" "$old_head" "$head" >stdin && + format_command $type "update refs/heads/ref2" "$(test_oid 001)" "$head" >>stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + echo $head >expect && + git rev-parse refs/heads/ref2 >actual && + test_cmp expect actual && + test_grep -q "invalid new value provided" stdout + ) + ' + + test_expect_success "stdin $type batch-updates with non-commit new_oid" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + head_tree=$(git rev-parse HEAD^{tree}) && + git update-ref refs/heads/ref1 $head && + git update-ref refs/heads/ref2 $head && + + format_command $type "update refs/heads/ref1" "$old_head" "$head" >stdin && + format_command $type "update refs/heads/ref2" "$head_tree" "$head" >>stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + echo $head >expect && + git rev-parse refs/heads/ref2 >actual && + test_cmp expect actual && + test_grep -q "invalid new value provided" stdout + ) + ' + + test_expect_success "stdin $type batch-updates with non-existent ref" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref1 $head && + + format_command $type "update refs/heads/ref1" "$old_head" "$head" >stdin && + format_command $type "update refs/heads/ref2" "$old_head" "$head" >>stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + test_must_fail git rev-parse refs/heads/ref2 && + test_grep -q "reference does not exist" stdout + ) + ' + + test_expect_success "stdin $type batch-updates with dangling symref" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref1 $head && + git symbolic-ref refs/heads/ref2 refs/heads/nonexistent && + + format_command $type "update refs/heads/ref1" "$old_head" "$head" >stdin && + format_command $type "update refs/heads/ref2" "$old_head" "$head" >>stdin && + git update-ref $type --no-deref --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + echo $head >expect && + test_must_fail git rev-parse refs/heads/ref2 && + test_grep -q "reference does not exist" stdout + ) + ' + + test_expect_success "stdin $type batch-updates with regular ref as symref" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref1 $head && + git update-ref refs/heads/ref2 $head && + + format_command $type "update refs/heads/ref1" "$old_head" "$head" >stdin && + format_command $type "symref-update refs/heads/ref2" "$old_head" "ref" "refs/heads/nonexistent" >>stdin && + git update-ref $type --no-deref --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + echo $head >expect && + echo $head >expect && + git rev-parse refs/heads/ref2 >actual && + test_cmp expect actual && + test_grep -q "expected symref but found regular ref" stdout + ) + ' + + test_expect_success "stdin $type batch-updates with invalid old_oid" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref1 $head && + git update-ref refs/heads/ref2 $head && + + format_command $type "update refs/heads/ref1" "$old_head" "$head" >stdin && + format_command $type "update refs/heads/ref2" "$old_head" "$Z" >>stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + echo $head >expect && + git rev-parse refs/heads/ref2 >actual && + test_cmp expect actual && + test_grep -q "reference already exists" stdout + ) + ' + + test_expect_success "stdin $type batch-updates with incorrect old oid" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref1 $head && + git update-ref refs/heads/ref2 $head && + + format_command $type "update refs/heads/ref1" "$old_head" "$head" >stdin && + format_command $type "update refs/heads/ref2" "$head" "$old_head" >>stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref1 >actual && + test_cmp expect actual && + echo $head >expect && + git rev-parse refs/heads/ref2 >actual && + test_cmp expect actual && + test_grep -q "incorrect old value provided" stdout + ) + ' + + test_expect_success "stdin $type batch-updates refname conflict" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref/foo $head && + + format_command $type "update refs/heads/ref/foo" "$old_head" "$head" >stdin && + format_command $type "update refs/heads/ref" "$old_head" "" >>stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/ref/foo >actual && + test_cmp expect actual && + test_grep -q "refname conflict" stdout + ) + ' + + test_expect_success "stdin $type batch-updates refname conflict new ref" ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + test_commit one && + old_head=$(git rev-parse HEAD) && + test_commit two && + head=$(git rev-parse HEAD) && + git update-ref refs/heads/ref/foo $head && + + format_command $type "update refs/heads/foo" "$old_head" "" >stdin && + format_command $type "update refs/heads/ref" "$old_head" "" >>stdin && + git update-ref $type --stdin --batch-updates <stdin >stdout && + echo $old_head >expect && + git rev-parse refs/heads/foo >actual && + test_cmp expect actual && + test_grep -q "refname conflict" stdout + ) + ' done test_expect_success 'update-ref should also create reflog for HEAD' ' diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh index 9d698b3cc3..9da3650e91 100755 --- a/t/t1403-show-ref.sh +++ b/t/t1403-show-ref.sh @@ -196,7 +196,7 @@ test_expect_success 'show-ref --verify with dangling ref' ' remove_object() { file=$(sha1_file "$*") && - test -e "$file" && + test_path_is_file "$file" && rm -f "$file" } && diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh index 41ba1f1d7f..833477f0fa 100755 --- a/t/t1408-packed-refs.sh +++ b/t/t1408-packed-refs.sh @@ -42,4 +42,19 @@ test_expect_success 'no error from stale entry in packed-refs' ' test_cmp expect actual ' +test_expect_success 'list packed refs with unicode characters' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit --no-tag A && + git update-ref refs/heads/î¿ HEAD && + git update-ref refs/heads/z HEAD && + git pack-refs --all && + printf "%s commit\trefs/heads/z\n" $(git rev-parse HEAD) >expect && + git for-each-ref refs/heads/z >actual && + test_cmp expect actual + ) +' + test_done diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index 388fdf9ae5..42b501f163 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -315,9 +315,9 @@ test_expect_success 'git reflog expire unknown reference' ' test_config gc.reflogexpireunreachable never && test_must_fail git reflog expire main@{123} 2>stderr && - test_grep "points nowhere" stderr && + test_grep "error: reflog could not be found: ${SQ}main@{123}${SQ}" stderr && test_must_fail git reflog expire does-not-exist 2>stderr && - test_grep "points nowhere" stderr + test_grep "error: reflog could not be found: ${SQ}does-not-exist${SQ}" stderr ' test_expect_success 'checkout should not delete log for packed ref' ' @@ -551,4 +551,126 @@ test_expect_success 'reflog with invalid object ID can be listed' ' ) ' +test_expect_success 'reflog drop non-existent ref' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_must_fail git reflog exists refs/heads/non-existent && + test_must_fail git reflog drop refs/heads/non-existent 2>stderr && + test_grep "error: reflog could not be found: ${SQ}refs/heads/non-existent${SQ}" stderr + ) +' + +test_expect_success 'reflog drop' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test_commit_bulk --ref=refs/heads/branch 1 && + git reflog exists refs/heads/main && + git reflog exists refs/heads/branch && + git reflog drop refs/heads/main && + test_must_fail git reflog exists refs/heads/main && + git reflog exists refs/heads/branch + ) +' + +test_expect_success 'reflog drop multiple references' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test_commit_bulk --ref=refs/heads/branch 1 && + git reflog exists refs/heads/main && + git reflog exists refs/heads/branch && + git reflog drop refs/heads/main refs/heads/branch && + test_must_fail git reflog exists refs/heads/main && + test_must_fail git reflog exists refs/heads/branch + ) +' + +test_expect_success 'reflog drop multiple references some non-existent' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test_commit_bulk --ref=refs/heads/branch 1 && + git reflog exists refs/heads/main && + git reflog exists refs/heads/branch && + test_must_fail git reflog exists refs/heads/non-existent && + test_must_fail git reflog drop refs/heads/main refs/heads/non-existent refs/heads/branch 2>stderr && + test_must_fail git reflog exists refs/heads/main && + test_must_fail git reflog exists refs/heads/branch && + test_must_fail git reflog exists refs/heads/non-existent && + test_grep "error: reflog could not be found: ${SQ}refs/heads/non-existent${SQ}" stderr + ) +' + +test_expect_success 'reflog drop --all' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test_commit_bulk --ref=refs/heads/branch 1 && + git reflog exists refs/heads/main && + git reflog exists refs/heads/branch && + git reflog drop --all && + test_must_fail git reflog exists refs/heads/main && + test_must_fail git reflog exists refs/heads/branch + ) +' + +test_expect_success 'reflog drop --all multiple worktrees' ' + test_when_finished "rm -rf repo" && + test_when_finished "rm -rf wt" && + git init repo && + ( + cd repo && + test_commit A && + git worktree add ../wt && + test_commit_bulk -C ../wt --ref=refs/heads/branch 1 && + git reflog exists refs/heads/main && + git reflog exists refs/heads/branch && + git reflog drop --all && + test_must_fail git reflog exists refs/heads/main && + test_must_fail git reflog exists refs/heads/branch + ) +' + +test_expect_success 'reflog drop --all --single-worktree' ' + test_when_finished "rm -rf repo" && + test_when_finished "rm -rf wt" && + git init repo && + ( + cd repo && + test_commit A && + git worktree add ../wt && + test_commit -C ../wt foobar && + git reflog exists refs/heads/main && + git reflog exists refs/heads/wt && + test-tool ref-store worktree:wt reflog-exists HEAD && + git reflog drop --all --single-worktree && + test_must_fail git reflog exists refs/heads/main && + test_must_fail git reflog exists refs/heads/wt && + test_must_fail test-tool ref-store worktree:main reflog-exists HEAD && + test-tool ref-store worktree:wt reflog-exists HEAD + ) +' + +test_expect_success 'reflog drop --all with reference' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test_must_fail git reflog drop --all refs/heads/main 2>stderr && + test_grep "usage: references specified along with --all" stderr + ) +' + test_done diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh index c04eeb7211..04797aee59 100755 --- a/t/t1419-exclude-refs.sh +++ b/t/t1419-exclude-refs.sh @@ -46,6 +46,10 @@ test_expect_success 'setup' ' echo "create refs/heads/$name/$i $base" || return 1 done || return 1 done >in && + for i in 5 6 7 + do + echo "create refs/heads/bar/4/$i $base" || return 1 + done >>in && echo "delete refs/heads/main" >>in && git update-ref --stdin <in && @@ -99,9 +103,17 @@ test_expect_success 'adjacent, non-overlapping excluded regions' ' esac ' -test_expect_success 'overlapping excluded regions' ' +test_expect_success 'non-directory excluded regions' ' for_each_ref__exclude refs/heads refs/heads/ba refs/heads/baz >actual 2>perf && - for_each_ref refs/heads/foo refs/heads/quux >expect && + for_each_ref refs/heads/bar refs/heads/foo refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'overlapping excluded regions' ' + for_each_ref__exclude refs/heads refs/heads/bar refs/heads/bar/4 >actual 2>perf && + for_each_ref refs/heads/baz refs/heads/foo refs/heads/quux >expect && test_cmp expect actual && assert_jumps 1 perf @@ -155,4 +167,14 @@ test_expect_success 'meta-characters are discarded' ' assert_no_jumps perf ' +test_expect_success 'empty string exclude pattern is ignored' ' + git update-ref refs/heads/loose $(git rev-parse refs/heads/foo/1) && + + for_each_ref__exclude refs/heads "" >actual 2>perf && + for_each_ref >expect && + + test_cmp expect actual && + assert_no_jumps perf +' + test_done diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 8a456b1142..5ae86c42be 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -7,6 +7,7 @@ test_description='git fsck random collection of tests ' . ./test-lib.sh +. "$TEST_DIRECTORY/lib-loose.sh" test_expect_success setup ' git config gc.auto 0 && @@ -71,30 +72,6 @@ test_expect_success 'object with hash mismatch' ' ) ' -test_expect_success 'object with hash and type mismatch' ' - git init --bare hash-type-mismatch && - ( - cd hash-type-mismatch && - - oid=$(echo blob | git hash-object -w --stdin -t garbage --literally) && - oldoid=$oid && - old=$(test_oid_to_path "$oid") && - new=$(dirname $old)/$(test_oid ff_2) && - oid="$(dirname $new)$(basename $new)" && - - mv objects/$old objects/$new && - git update-index --add --cacheinfo 100644 $oid foo && - tree=$(git write-tree) && - cmt=$(echo bogus | git commit-tree $tree) && - git update-ref refs/heads/bogus $cmt && - - - test_must_fail git fsck 2>out && - grep "^error: $oldoid: hash-path mismatch, found at: .*$new" out && - grep "^error: $oldoid: object is of unknown type '"'"'garbage'"'"'" out - ) -' - test_expect_success 'zlib corrupt loose object output ' ' git init --bare corrupt-loose-output && ( @@ -346,7 +323,7 @@ test_expect_success 'unparseable tree object' ' test_grep ! "fatal: empty filename in tree entry" out ' -test_expect_success 'tree entry with type mismatch' ' +test_expect_success PERL_TEST_HELPERS 'tree entry with type mismatch' ' test_when_finished "remove_object \$blob" && test_when_finished "remove_object \$tree" && test_when_finished "remove_object \$commit" && @@ -364,7 +341,7 @@ test_expect_success 'tree entry with type mismatch' ' test_grep ! "dangling blob" out ' -test_expect_success 'tree entry with bogus mode' ' +test_expect_success PERL_TEST_HELPERS 'tree entry with bogus mode' ' test_when_finished "remove_object \$blob" && test_when_finished "remove_object \$tree" && blob=$(echo blob | git hash-object -w --stdin) && @@ -984,7 +961,7 @@ corrupt_index_checksum () { # Corrupt the checksum on the index and then # verify that only fsck notices. -test_expect_success 'detect corrupt index file in fsck' ' +test_expect_success PERL_TEST_HELPERS 'detect corrupt index file in fsck' ' cp .git/index .git/index.backup && test_when_finished "mv .git/index.backup .git/index" && corrupt_index_checksum && @@ -997,12 +974,13 @@ test_expect_success 'fsck error and recovery on invalid object type' ' ( cd garbage-type && - garbage_blob=$(git hash-object --stdin -w -t garbage --literally </dev/null) && + garbage_blob=$(loose_obj objects garbage </dev/null) && test_must_fail git fsck 2>err && grep -e "^error" -e "^fatal" err >errors && - test_line_count = 1 errors && - grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err + test_line_count = 2 errors && + test_grep "unable to parse type from header .garbage" err && + test_grep "$garbage_blob: object corrupt or missing:" err ) ' diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 70f1e0a998..1a380a4184 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -24,6 +24,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +. "$TEST_DIRECTORY/lib-loose.sh" test_cmp_failed_rev_parse () { dir=$1 @@ -67,8 +68,8 @@ test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' ' cd blob.bad && # Both have the prefix "bad0" - echo xyzfaowcoh | git hash-object -t bad -w --stdin --literally && - echo xyzhjpyvwl | git hash-object -t bad -w --stdin --literally + echo xyzfaowcoh | loose_obj objects bad && + echo xyzhjpyvwl | loose_obj objects bad ) && test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh index dbd8cd6906..6824581317 100755 --- a/t/t1517-outside-repo.sh +++ b/t/t1517-outside-repo.sh @@ -107,4 +107,11 @@ test_expect_success LIBCURL 'remote-http outside repository' ' test_grep "^error: remote-curl" actual ' +test_expect_success 'update-server-info does not crash with -h' ' + test_expect_code 129 git update-server-info -h >usage && + test_grep "[Uu]sage: git update-server-info " usage && + test_expect_code 129 nongit git update-server-info -h >usage && + test_grep "[Uu]sage: git update-server-info " usage +' + test_done diff --git a/t/t2006-checkout-index-basic.sh b/t/t2006-checkout-index-basic.sh index bac231b167..fedd2cc097 100755 --- a/t/t2006-checkout-index-basic.sh +++ b/t/t2006-checkout-index-basic.sh @@ -21,6 +21,13 @@ test_expect_success 'checkout-index -h in broken repository' ' test_grep "[Uu]sage" broken/usage ' +test_expect_success 'checkout-index does not crash with -h' ' + test_expect_code 129 git checkout-index -h >usage && + test_grep "[Uu]sage: git checkout-index " usage && + test_expect_code 129 nongit git checkout-index -h >usage && + test_grep "[Uu]sage: git checkout-index " usage +' + test_expect_success 'checkout-index reports errors (cmdline)' ' test_must_fail git checkout-index -- does-not-exist 2>stderr && test_grep not.in.the.cache stderr diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index 90638fa886..023e1301c8 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -42,8 +42,8 @@ test_expect_success '"add" using - shorthand' ' test_expect_success '"add" refuses to checkout locked branch' ' test_must_fail git worktree add zere main && - ! test -d zere && - ! test -d .git/worktrees/zere + test_path_is_missing zere && + test_path_is_missing .git/worktrees/zere ' test_expect_success 'checking out paths not complaining about linked checkouts' ' @@ -70,14 +70,14 @@ test_expect_success '"add" worktree' ' test_expect_success '"add" worktree with lock' ' git worktree add --detach --lock here-with-lock main && test_when_finished "git worktree unlock here-with-lock || :" && - test -f .git/worktrees/here-with-lock/locked + test_path_is_file .git/worktrees/here-with-lock/locked ' test_expect_success '"add" worktree with lock and reason' ' lock_reason="why not" && git worktree add --detach --lock --reason "$lock_reason" here-with-lock-reason main && test_when_finished "git worktree unlock here-with-lock-reason || :" && - test -f .git/worktrees/here-with-lock-reason/locked && + test_path_is_file .git/worktrees/here-with-lock-reason/locked && echo "$lock_reason" >expect && test_cmp expect .git/worktrees/here-with-lock-reason/locked ' @@ -412,14 +412,14 @@ test_expect_success '"add --orphan" with empty repository' ' test_expect_success '"add" worktree with orphan branch and lock' ' git worktree add --lock --orphan -b orphanbr orphan-with-lock && test_when_finished "git worktree unlock orphan-with-lock || :" && - test -f .git/worktrees/orphan-with-lock/locked + test_path_is_file .git/worktrees/orphan-with-lock/locked ' test_expect_success '"add" worktree with orphan branch, lock, and reason' ' lock_reason="why not" && git worktree add --detach --lock --reason "$lock_reason" orphan-with-lock-reason main && test_when_finished "git worktree unlock orphan-with-lock-reason || :" && - test -f .git/worktrees/orphan-with-lock-reason/locked && + test_path_is_file .git/worktrees/orphan-with-lock-reason/locked && echo "$lock_reason" >expect && test_cmp expect .git/worktrees/orphan-with-lock-reason/locked ' @@ -474,7 +474,7 @@ test_expect_success 'local clone --shared from linked checkout' ' test_expect_success '"add" worktree with --no-checkout' ' git worktree add --no-checkout -b swamp swamp && - ! test -e swamp/init.t && + test_path_is_missing swamp/init.t && git -C swamp reset --hard && test_cmp init.t swamp/init.t ' @@ -497,7 +497,7 @@ test_expect_success 'put a worktree under rebase' ' test_expect_success 'add a worktree, checking out a rebased branch' ' test_must_fail git worktree add new-rebase under-rebase && - ! test -d new-rebase + test_path_is_missing new-rebase ' test_expect_success 'checking out a rebased branch from another worktree' ' @@ -535,7 +535,7 @@ test_expect_success 'checkout a branch under bisect' ' git worktree list >actual && grep "under-bisect.*detached HEAD" actual && test_must_fail git worktree add new-bisect under-bisect && - ! test -d new-bisect + test_path_is_missing new-bisect ) ' @@ -1165,7 +1165,7 @@ test_expect_success '"add" not tripped up by magic worktree matching"' ' test_expect_success FUNNYNAMES 'sanitize generated worktree name' ' git worktree add --detach ". weird*..?.lock.lock" && - test -d .git/worktrees/---weird-.- + test_path_is_dir .git/worktrees/---weird-.- ' test_expect_success '"add" should not fail because of another bad worktree' ' diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index f6d8d7d03d..be9140bbaa 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -117,8 +117,6 @@ test_expect_success 'merge fails if cwd needs to be removed; recursive friendly' grep "Refusing to remove the current working directory" error ' -GIT_TEST_MERGE_ALGORITHM=ort - test_expect_success 'merge fails if cwd needs to be removed' ' test_required_dir_removal git merge fd_conflict ' diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh index a1078f8701..4034a5a59f 100755 --- a/t/t3004-ls-files-basic.sh +++ b/t/t3004-ls-files-basic.sh @@ -34,6 +34,13 @@ test_expect_success 'ls-files -h in corrupt repository' ' test_grep "[Uu]sage: git ls-files " broken/usage ' +test_expect_success 'ls-files does not crash with -h' ' + test_expect_code 129 git ls-files -h >usage && + test_grep "[Uu]sage: git ls-files " usage && + test_expect_code 129 nongit git ls-files -h >usage && + test_grep "[Uu]sage: git ls-files " usage +' + test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' ' mkdir subs && ln -s nosuch link && diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index f5bf16abcd..dd0586b007 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -70,7 +70,7 @@ test_expect_success 'ls-files -z does not quote funny filename' ' tabs ," (dq) and spaces EOF git ls-files -z >ls-files.z && - perl -pe "y/\000/\012/" <ls-files.z >current && + tr "\000" "\012" <ls-files.z >current && test_cmp expected current ' @@ -107,7 +107,7 @@ test_expect_success 'diff-index -z does not quote funny filename' ' tabs ," (dq) and spaces EOF git diff-index -z --name-status $t0 >diff-index.z && - perl -pe "y/\000/\012/" <diff-index.z >current && + tr "\000" "\012" <diff-index.z >current && test_cmp expected current ' @@ -117,7 +117,7 @@ test_expect_success 'diff-tree -z does not quote funny filename' ' tabs ," (dq) and spaces EOF git diff-tree -z --name-status $t0 $t1 >diff-tree.z && - perl -pe y/\\000/\\012/ <diff-tree.z >current && + tr "\000" "\012" <diff-tree.z >current && test_cmp expected current ' diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 2aee9789a2..6bac217ed3 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1468,7 +1468,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' ' cat >expect <<-EOF && Warning: some commits may have been dropped accidentally. Dropped commits (newer to older): - - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) + - $(git log --format="%h # %s" -1 primary) To avoid this message, use "drop" to explicitly remove a commit. EOF test_config rebase.missingCommitsCheck warn && @@ -1486,8 +1486,8 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' ' cat >expect <<-EOF && Warning: some commits may have been dropped accidentally. Dropped commits (newer to older): - - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) - - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~2) + - $(git log --format="%h # %s" -1 primary) + - $(git log --format="%h # %s" -1 primary~2) To avoid this message, use "drop" to explicitly remove a commit. Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings. @@ -1530,11 +1530,11 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ig test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' ' cat >expect <<-EOF && error: invalid command '\''pickled'\'' - error: invalid line 1: pickled $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) + error: invalid line 1: pickled $(git log --format="%h # %s" -1 primary~4) Warning: some commits may have been dropped accidentally. Dropped commits (newer to older): - - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) - - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) + - $(git log --format="%h # %s" -1 primary) + - $(git log --format="%h # %s" -1 primary~4) To avoid this message, use "drop" to explicitly remove a commit. EOF head -n5 expect >expect.2 && @@ -1565,11 +1565,11 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = wa test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' ' cat >expect <<-EOF && error: invalid command '\''pickled'\'' - error: invalid line 1: pickled $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) + error: invalid line 1: pickled $(git log --format="%h # %s" -1 primary~4) Warning: some commits may have been dropped accidentally. Dropped commits (newer to older): - - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) - - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) + - $(git log --format="%h # %s" -1 primary) + - $(git log --format="%h # %s" -1 primary~4) To avoid this message, use "drop" to explicitly remove a commit. Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings. @@ -1642,11 +1642,11 @@ test_expect_success 'respects rebase.abbreviateCommands with fixup, squash and e test_commit "fixup! first" file2.txt "first line again" first_fixup && test_commit "squash! second" file1.txt "another line here" second_squash && cat >expected <<-EOF && - p $(git rev-list --abbrev-commit -1 first) first - f $(git rev-list --abbrev-commit -1 first_fixup) fixup! first + p $(git rev-list --abbrev-commit -1 first) # first + f $(git rev-list --abbrev-commit -1 first_fixup) # fixup! first x git show HEAD - p $(git rev-list --abbrev-commit -1 second) second - s $(git rev-list --abbrev-commit -1 second_squash) squash! second + p $(git rev-list --abbrev-commit -1 second) # second + s $(git rev-list --abbrev-commit -1 second_squash) # squash! second x git show HEAD EOF git checkout abbrevcmd && @@ -1665,7 +1665,7 @@ test_expect_success 'static check of bad command' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ git rebase -i --root 2>actual && - test_grep "pickled $(git rev-list --oneline -1 primary~1)" \ + test_grep "pickled $(git log --format="%h # %s" -1 primary~1)" \ actual && test_grep "You can fix this with .git rebase --edit-todo.." \ actual && @@ -1865,15 +1865,15 @@ test_expect_success '--update-refs adds label and update-ref commands' ' set_cat_todo_editor && cat >expect <<-EOF && - pick $(git log -1 --format=%h J) J - fixup $(git log -1 --format=%h update-refs) fixup! J # empty + pick $(git log -1 --format=%h J) # J + fixup $(git log -1 --format=%h update-refs) # fixup! J # empty update-ref refs/heads/second update-ref refs/heads/first - pick $(git log -1 --format=%h K) K - pick $(git log -1 --format=%h L) L - fixup $(git log -1 --format=%h is-not-reordered) fixup! L # empty + pick $(git log -1 --format=%h K) # K + pick $(git log -1 --format=%h L) # L + fixup $(git log -1 --format=%h is-not-reordered) # fixup! L # empty update-ref refs/heads/third - pick $(git log -1 --format=%h M) M + pick $(git log -1 --format=%h M) # M update-ref refs/heads/no-conflict-branch update-ref refs/heads/is-not-reordered update-ref refs/heads/shared-tip @@ -1905,19 +1905,19 @@ test_expect_success '--update-refs adds commands with --rebase-merges' ' cat >expect <<-EOF && label onto reset onto - pick $(git log -1 --format=%h branch2~1) F - pick $(git log -1 --format=%h branch2) I + pick $(git log -1 --format=%h branch2~1) # F + pick $(git log -1 --format=%h branch2) # I update-ref refs/heads/branch2 label branch2 reset onto - pick $(git log -1 --format=%h refs/heads/second) J + pick $(git log -1 --format=%h refs/heads/second) # J update-ref refs/heads/second update-ref refs/heads/first - pick $(git log -1 --format=%h refs/heads/third~1) K - pick $(git log -1 --format=%h refs/heads/third) L - fixup $(git log -1 --format=%h update-refs-with-merge) fixup! L # empty + pick $(git log -1 --format=%h refs/heads/third~1) # K + pick $(git log -1 --format=%h refs/heads/third) # L + fixup $(git log -1 --format=%h update-refs-with-merge) # fixup! L # empty update-ref refs/heads/third - pick $(git log -1 --format=%h HEAD~2) M + pick $(git log -1 --format=%h HEAD~2) # M update-ref refs/heads/no-conflict-branch merge -C $(git log -1 --format=%h HEAD~1) branch2 # merge update-ref refs/heads/merge-branch diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index fcc40d6fe1..26b42a526a 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -257,8 +257,8 @@ test_expect_success 'auto squash of fixup commit that matches branch name which GIT_SEQUENCE_EDITOR="cat >tmp" git rebase --autosquash -i HEAD^^ && sed -ne "/^[^#]/{s/[0-9a-f]\{7,\}/HASH/g;p;}" tmp >actual && cat <<-EOF >expect && - pick HASH second commit - pick HASH fixup! self-cycle # empty + pick HASH # second commit + pick HASH # fixup! self-cycle # empty EOF test_cmp expect actual ' @@ -311,10 +311,10 @@ test_auto_fixup_fixup () { parent2=$(git rev-parse --short HEAD^^) && parent3=$(git rev-parse --short HEAD^^^) && cat >expected <<-EOF && - pick $parent3 first commit - $1 $parent1 $1! first - $1 $head $1! $2! first - pick $parent2 second commit + pick $parent3 # first commit + $1 $parent1 # $1! first + $1 $head # $1! $2! first + pick $parent2 # second commit EOF test_cmp expected actual ) && @@ -389,7 +389,7 @@ test_expect_success 'autosquash with empty custom instructionFormat' ' set_cat_todo_editor && test_must_fail git -c rebase.instructionFormat= \ rebase --autosquash --force-rebase -i HEAD^ >actual && - git log -1 --format="pick %h %s" >expect && + git log -1 --format="pick %h # %s" >expect && test_cmp expect actual ) ' diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index b84d68c4b9..cc627e34a7 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -86,7 +86,7 @@ test_expect_success 'create completely different structure' ' test_config sequence.editor \""$PWD"/replace-editor.sh\" && test_tick && git rebase -i -r A main && - test_cmp_graph <<-\EOF + test_cmp_graph <<-\EOF && * Merge the topic branch '\''onebranch'\'' |\ | * D @@ -99,6 +99,15 @@ test_expect_success 'create completely different structure' ' |/ * A EOF + + head="$(git show-ref --verify -s --abbrev HEAD)" && + cat >expect <<-EOF && + $head HEAD@{0}: rebase (finish): returning to refs/heads/main + $head HEAD@{1}: rebase (merge): Merge the topic branch ${SQ}onebranch${SQ} + EOF + + git reflog -n2 HEAD >actual && + test_cmp expect actual ' test_expect_success 'generate correct todo list' ' @@ -106,18 +115,18 @@ test_expect_success 'generate correct todo list' ' label onto reset onto - pick $b B + pick $b # B label first reset onto - pick $c C + pick $c # C label branch-point - pick $f F - pick $g G + pick $f # F + pick $g # G label second reset branch-point # C - pick $d D + pick $d # D merge -C $e first # E merge -C $h second # H diff --git a/t/t3512-cherry-pick-submodule.sh b/t/t3512-cherry-pick-submodule.sh index f22d1ddead..85a7932697 100755 --- a/t/t3512-cherry-pick-submodule.sh +++ b/t/t3512-cherry-pick-submodule.sh @@ -8,11 +8,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh -if test "$GIT_TEST_MERGE_ALGORITHM" != ort -then - KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 - KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 -fi test_submodule_switch "cherry-pick" test_expect_success 'unrelated submodule/file conflict is ignored' ' diff --git a/t/t3513-revert-submodule.sh b/t/t3513-revert-submodule.sh index 8bfe3ed246..32e15c72ee 100755 --- a/t/t3513-revert-submodule.sh +++ b/t/t3513-revert-submodule.sh @@ -30,10 +30,6 @@ git_revert () { git revert HEAD } -if test "$GIT_TEST_MERGE_ALGORITHM" != ort -then - KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 -fi test_submodule_switch_func "git_revert" test_done diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 98259e2ada..1f16e6b522 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -17,11 +17,6 @@ test_expect_success 'Initialize test directory' ' git commit -m "add normal files" ' -if test_have_prereq !FUNNYNAMES -then - say 'Your filesystem does not allow tabs in filenames.' -fi - test_expect_success FUNNYNAMES 'add files with funny names' ' touch -- "tab embedded" "newline${LF}embedded" && git add -- "tab embedded" "newline${LF}embedded" && diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh index 389670262e..58b3759935 100755 --- a/t/t3650-replay-basics.sh +++ b/t/t3650-replay-basics.sh @@ -195,4 +195,26 @@ test_expect_success 'using replay on bare repo to rebase multiple divergent bran done ' +test_expect_success 'merge.directoryRenames=false' ' + # create a test case that stress-tests the rename caching + git switch -c rename-onto && + + mkdir -p to-rename && + test_commit to-rename/move && + + mkdir -p renamed-directory && + git mv to-rename/move* renamed-directory/ && + test_tick && + git commit -m renamed-directory && + + git switch -c rename-from HEAD^ && + test_commit to-rename/add-a-file && + echo modified >to-rename/add-a-file.t && + test_tick && + git commit -m modified to-rename/add-a-file.t && + + git -c merge.directoryRenames=false replay \ + --onto rename-onto rename-onto..rename-from +' + test_done diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 74666ff3e4..35b85c7909 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -1177,6 +1177,28 @@ test_expect_success 'stash -- <pathspec> stashes and restores the file' ' test_path_is_file bar ' +test_expect_success 'stash --patch <pathspec> stash and restores the file' ' + test_write_lines b c >file && + git commit -m "add a few lines" file && + test_write_lines a b c d >file && + test_write_lines b c d >expect-file && + echo changed-other-file >other-file && + test_write_lines s y n | git stash -m "stash bar" --patch file && + test_cmp expect-file file && + echo changed-other-file >expect && + test_cmp expect other-file && + git checkout HEAD -- file && + git stash pop && + test_cmp expect other-file && + test_write_lines a b c >expect && + test_cmp expect file +' + +test_expect_success 'stash <pathspec> -p is rejected' ' + test_must_fail git stash file -p 2>err && + test_grep "subcommand wasn${SQ}t specified; ${SQ}push${SQ} can${SQ}t be assumed due to unexpected token ${SQ}file${SQ}" err +' + test_expect_success 'stash -- <pathspec> stashes in subdirectory' ' mkdir sub && >foo && @@ -1592,4 +1614,36 @@ test_expect_success 'stash apply reports a locked index' ' ) ' +test_expect_success 'submodules does not affect the branch recorded in stash message' ' + git init sub_project && + ( + cd sub_project && + echo "Initial content in sub_project" >sub_file.txt && + git add sub_file.txt && + git commit -m "Initial commit in sub_project" + ) && + + git init main_project && + ( + cd main_project && + echo "Initial content in main_project" >main_file.txt && + git add main_file.txt && + git commit -m "Initial commit in main_project" && + + git -c protocol.file.allow=always submodule add ../sub_project sub && + git commit -m "Added submodule sub_project" && + + git checkout -b feature_main && + git -C sub checkout -b feature_sub && + + git checkout -b work_branch && + echo "Important work to be stashed" >work_item.txt && + git add work_item.txt && + git stash push -m "custom stash for work_branch" && + + git stash list >../actual_stash_list.txt && + grep "On work_branch: custom stash for work_branch" ../actual_stash_list.txt + ) +' + test_done diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index a51f881b1c..32b14e3a71 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -36,7 +36,7 @@ test_expect_success 'git diff-files -p after editing work tree.' ' # that's as far as it comes if [ "$(git config --get core.filemode)" = false ] then - say 'filemode disabled on the filesystem' + skip_all='filemode disabled on the filesystem' test_done fi diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 8e38df1685..8ebd170451 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -11,6 +11,12 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping diff various tests; Perl not available' + test_done +fi + test_expect_success setup ' GIT_AUTHOR_DATE="2006-06-26 00:00:00 +0000" && @@ -202,7 +208,7 @@ do case "$cmd" in whatchanged | whatchanged" "*) - prereq=WITHOUT_BREAKING_CHANGES + prereq=!WITH_BREAKING_CHANGES ;; *) prereq=;; @@ -470,7 +476,7 @@ diff-tree --stat --compact-summary initial mode diff-tree -R --stat --compact-summary initial mode EOF -test_expect_success WITHOUT_BREAKING_CHANGES 'whatchanged needs --i-still-use-this' ' +test_expect_success !WITH_BREAKING_CHANGES 'whatchanged needs --i-still-use-this' ' test_must_fail git whatchanged >message 2>&1 && test_grep "nominated for removal" message ' diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 884f83fb8a..2782b1fc18 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -448,7 +448,7 @@ cat >>expect.no-threading <<EOF --- EOF -test_expect_success 'no threading' ' +test_expect_success PERL_TEST_HELPERS 'no threading' ' git checkout side && check_threading expect.no-threading main ' @@ -466,11 +466,11 @@ In-Reply-To: <0> References: <0> EOF -test_expect_success 'thread' ' +test_expect_success PERL_TEST_HELPERS 'thread' ' check_threading expect.thread --thread main ' -test_expect_success '--thread overrides format.thread=deep' ' +test_expect_success PERL_TEST_HELPERS '--thread overrides format.thread=deep' ' test_config format.thread deep && check_threading expect.thread --thread main ' @@ -490,7 +490,7 @@ In-Reply-To: <1> References: <1> EOF -test_expect_success 'thread in-reply-to' ' +test_expect_success PERL_TEST_HELPERS 'thread in-reply-to' ' check_threading expect.in-reply-to --in-reply-to="<test.message>" \ --thread main ' @@ -512,7 +512,7 @@ In-Reply-To: <0> References: <0> EOF -test_expect_success 'thread cover-letter' ' +test_expect_success PERL_TEST_HELPERS 'thread cover-letter' ' check_threading expect.cover-letter --cover-letter --thread main ' @@ -538,12 +538,12 @@ References: <1> <0> EOF -test_expect_success 'thread cover-letter in-reply-to' ' +test_expect_success PERL_TEST_HELPERS 'thread cover-letter in-reply-to' ' check_threading expect.cl-irt --cover-letter \ --in-reply-to="<test.message>" --thread main ' -test_expect_success 'thread explicit shallow' ' +test_expect_success PERL_TEST_HELPERS 'thread explicit shallow' ' check_threading expect.cl-irt --cover-letter \ --in-reply-to="<test.message>" --thread=shallow main ' @@ -562,7 +562,7 @@ References: <0> <1> EOF -test_expect_success 'thread deep' ' +test_expect_success PERL_TEST_HELPERS 'thread deep' ' check_threading expect.deep --thread=deep main ' @@ -584,7 +584,7 @@ References: <1> <2> EOF -test_expect_success 'thread deep in-reply-to' ' +test_expect_success PERL_TEST_HELPERS 'thread deep in-reply-to' ' check_threading expect.deep-irt --thread=deep \ --in-reply-to="<test.message>" main ' @@ -609,7 +609,7 @@ References: <0> <2> EOF -test_expect_success 'thread deep cover-letter' ' +test_expect_success PERL_TEST_HELPERS 'thread deep cover-letter' ' check_threading expect.deep-cl --cover-letter --thread=deep main ' @@ -638,27 +638,27 @@ References: <1> <3> EOF -test_expect_success 'thread deep cover-letter in-reply-to' ' +test_expect_success PERL_TEST_HELPERS 'thread deep cover-letter in-reply-to' ' check_threading expect.deep-cl-irt --cover-letter \ --in-reply-to="<test.message>" --thread=deep main ' -test_expect_success 'thread via config' ' +test_expect_success PERL_TEST_HELPERS 'thread via config' ' test_config format.thread true && check_threading expect.thread main ' -test_expect_success 'thread deep via config' ' +test_expect_success PERL_TEST_HELPERS 'thread deep via config' ' test_config format.thread deep && check_threading expect.deep main ' -test_expect_success 'thread config + override' ' +test_expect_success PERL_TEST_HELPERS 'thread config + override' ' test_config format.thread deep && check_threading expect.thread --thread main ' -test_expect_success 'thread config + --no-thread' ' +test_expect_success PERL_TEST_HELPERS 'thread config + --no-thread' ' test_config format.thread deep && check_threading expect.no-threading --no-thread main ' diff --git a/t/t4018/bash-bashism-style-complete-line-capture b/t/t4018/bash-bashism-style-complete-line-capture new file mode 100644 index 0000000000..070b979fa6 --- /dev/null +++ b/t/t4018/bash-bashism-style-complete-line-capture @@ -0,0 +1,4 @@ +function myfunc # RIGHT +{ + echo 'ChangeMe' +} diff --git a/t/t4018/bash-posix-style-complete-line-capture b/t/t4018/bash-posix-style-complete-line-capture new file mode 100644 index 0000000000..b56942f322 --- /dev/null +++ b/t/t4018/bash-posix-style-complete-line-capture @@ -0,0 +1,4 @@ +func() { # RIGHT + + ChangeMe +} diff --git a/t/t4018/bash-posix-style-single-command-function b/t/t4018/bash-posix-style-single-command-function new file mode 100644 index 0000000000..398ae1c5d2 --- /dev/null +++ b/t/t4018/bash-posix-style-single-command-function @@ -0,0 +1,3 @@ +RIGHT() echo "hello" + + ChangeMe diff --git a/t/t4018/ini-section b/t/t4018/ini-section new file mode 100644 index 0000000000..c895ad9b4f --- /dev/null +++ b/t/t4018/ini-section @@ -0,0 +1,5 @@ +[RIGHT] + # comment + ; comment + name = value + ChangeMe diff --git a/t/t4018/ini-section-noindent b/t/t4018/ini-section-noindent new file mode 100644 index 0000000000..733d23c801 --- /dev/null +++ b/t/t4018/ini-section-noindent @@ -0,0 +1,5 @@ +[RIGHT] +# comment +; comment +name = value +ChangeMe diff --git a/t/t4018/ini-section-same-line b/t/t4018/ini-section-same-line new file mode 100644 index 0000000000..522a1fa4a1 --- /dev/null +++ b/t/t4018/ini-section-same-line @@ -0,0 +1,4 @@ +[RIGHT] name = value + # comment + ; comment + ChangeMe diff --git a/t/t4018/ini-subsection b/t/t4018/ini-subsection new file mode 100644 index 0000000000..3d47349e60 --- /dev/null +++ b/t/t4018/ini-subsection @@ -0,0 +1,12 @@ +[LEFT] + + [LEFT "CENTER"] + # comment + ; comment + name = value + + [LEFT "RIGHT"] + # comment + ; comment + name = value + ChangeMe diff --git a/t/t4018/ini-subsection-noindent b/t/t4018/ini-subsection-noindent new file mode 100644 index 0000000000..698ea00ea3 --- /dev/null +++ b/t/t4018/ini-subsection-noindent @@ -0,0 +1,12 @@ +[LEFT] + +[LEFT "CENTER"] +# comment +; comment +name = value + +[LEFT "RIGHT"] +# comment +; comment +name = value +ChangeMe diff --git a/t/t4018/r-indent b/t/t4018/r-indent new file mode 100644 index 0000000000..9df440f2a4 --- /dev/null +++ b/t/t4018/r-indent @@ -0,0 +1,6 @@ +RIGHT <- function(a, b) { + c = mean(a, b) + d = c + 2 + ChangeMe() + return (d) +} diff --git a/t/t4018/r-indent-nested b/t/t4018/r-indent-nested new file mode 100644 index 0000000000..30412e6c79 --- /dev/null +++ b/t/t4018/r-indent-nested @@ -0,0 +1,10 @@ +LEFT = function(a, b) { + c = mean(a, b) + RIGHT = function(d, e) { + f = var(d, e) + g = f + 1 + ChangeMe() + return (g) + } + return (RIGHT(2, 3)) +} diff --git a/t/t4018/r-noindent b/t/t4018/r-noindent new file mode 100644 index 0000000000..6d9b01ffe3 --- /dev/null +++ b/t/t4018/r-noindent @@ -0,0 +1,6 @@ +RIGHT <- function(a, b) { +c = mean(a, b) +d = c + 2 +ChangeMe() +return (c) +} diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index f1efe482a5..c8a23d5148 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -237,7 +237,7 @@ check_external_diff 0 empty empty 0 on --quiet check_external_diff 1 empty empty 1 on --quiet check_external_diff 128 empty error 2 on --quiet -echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file +echo NULZbetweenZwords | tr "Z" "\000" > file test_expect_success 'force diff with "diff"' ' after=$(git hash-object file) && diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh index 32b6e9a4e7..90cdde88d8 100755 --- a/t/t4029-diff-trailing-space.sh +++ b/t/t4029-diff-trailing-space.sh @@ -31,7 +31,8 @@ test_expect_success "$test_description" ' git config --bool diff.suppressBlankEmpty true && git diff f > actual && test_cmp exp actual && - perl -i.bak -p -e "s/^\$/ /" exp && + sed "s/^\$/ /" exp >exp.munged && + mv exp.munged exp && git config --bool diff.suppressBlankEmpty false && git diff f > actual && test_cmp exp actual && diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index daebf9796f..f904fc19f6 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -20,13 +20,10 @@ cat >expect.text <<'EOF' +1 EOF -cat >hexdump <<'EOF' -#!/bin/sh -"$PERL_PATH" -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" -EOF -chmod +x hexdump - test_expect_success 'setup binary file with history' ' + write_script hexdump <<-\EOF && + tr "\000\001" "01" <"$1" + EOF test_commit --printf one file "\\0\\n" && test_commit --printf --append two file "\\01\\n" ' diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh index c4394a27b5..15e012ccc7 100755 --- a/t/t4031-diff-rewrite-binary.sh +++ b/t/t4031-diff-rewrite-binary.sh @@ -57,24 +57,19 @@ test_expect_success 'diff --stat counts binary rewrite as 0 lines' ' grep " rewrite file" diff ' -{ - echo "#!$SHELL_PATH" - cat <<'EOF' -"$PERL_PATH" -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" -EOF -} >dump -chmod +x dump - test_expect_success 'setup textconv' ' + write_script dump <<-\EOF && + test-tool hexdump <"$1" + EOF echo file diff=foo >.gitattributes && git config diff.foo.textconv "\"$(pwd)\""/dump ' test_expect_success 'rewrite diff respects textconv' ' git diff -B >diff && - grep "dissimilarity index" diff && - grep "^-61" diff && - grep "^-0" diff + test_grep "dissimilarity index" diff && + test_grep "^-3d 0a 00" diff && + test_grep "^+3d 0a 01" diff ' test_done diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index f51d3557f1..0be647c2fb 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -320,6 +320,7 @@ test_expect_success 'unset default driver' ' test_language_driver ada test_language_driver bibtex +test_language_driver bash test_language_driver cpp test_language_driver csharp test_language_driver css diff --git a/t/t4034/bash/expect b/t/t4034/bash/expect new file mode 100644 index 0000000000..1864ab25dc --- /dev/null +++ b/t/t4034/bash/expect @@ -0,0 +1,36 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index 09ac008..60ba6a2 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,31 +1,31 @@<RESET> +<RED>my_var<RESET><GREEN>new_var<RESET>=10 +x=<RED>123<RESET><GREEN>456<RESET> +echo <RED>$1<RESET><GREEN>$2<RESET> +echo <RED>$USER<RESET><GREEN>$USERNAME<RESET> +${<RED>HOME<RESET><GREEN>HOMEDIR<RESET>} +((a<RED>+<RESET><GREEN>+=<RESET>b)) +((a<RED>*<RESET><GREEN>*=<RESET>b)) +((a<RED>/<RESET><GREEN>/=<RESET>b)) +((a<RED>%<RESET><GREEN>%=<RESET>b)) +((a<RED>|<RESET><GREEN>|=<RESET>b)) +((a<RED>^<RESET><GREEN>^=<RESET>b)) +((a<RED>=<RESET><GREEN>==<RESET>b)) +((a<RED>!<RESET><GREEN>!=<RESET>b)) +((a<RED><<RESET><GREEN><=<RESET>b)) +((a<RED>><RESET><GREEN>>=<RESET>b)) +$((a<RED><<RESET><GREEN><<<RESET>b)) +$((a<RED>><RESET><GREEN>>><RESET>b)) +$((a<RED>&<RESET><GREEN>&&<RESET>b)) +$((a<RED>|<RESET><GREEN>||<RESET>b)) +${a<RED>:<RESET><GREEN>:-<RESET>b} +${a<RED>:<RESET><GREEN>:=<RESET>b} +${a<RED>:<RESET><GREEN>:+<RESET>b} +${a<RED>:<RESET><GREEN>:?<RESET>b} +${a<RED>#<RESET><GREEN>##<RESET>*/} +${a<RED>%<RESET><GREEN>%%<RESET>.*} +${a<RED>^<RESET><GREEN>^^<RESET>} +${a<RED>,<RESET><GREEN>,,<RESET>} +${<GREEN>!<RESET>a} +${a[<RED>*<RESET><GREEN>@<RESET>]} +ls <RED>-a<RESET><GREEN>-x<RESET> +ls <RED>--all<RESET><GREEN>--color<RESET> diff --git a/t/t4034/bash/post b/t/t4034/bash/post new file mode 100644 index 0000000000..2bbee8936d --- /dev/null +++ b/t/t4034/bash/post @@ -0,0 +1,31 @@ +new_var=10 +x=456 +echo $2 +echo $USERNAME +${HOMEDIR} +((a+=b)) +((a*=b)) +((a/=b)) +((a%=b)) +((a|=b)) +((a^=b)) +((a==b)) +((a!=b)) +((a<=b)) +((a>=b)) +$((a<<b)) +$((a>>b)) +$((a&&b)) +$((a||b)) +${a:-b} +${a:=b} +${a:+b} +${a:?b} +${a##*/} +${a%%.*} +${a^^} +${a,,} +${!a} +${a[@]} +ls -x +ls --color diff --git a/t/t4034/bash/pre b/t/t4034/bash/pre new file mode 100644 index 0000000000..8d22039c40 --- /dev/null +++ b/t/t4034/bash/pre @@ -0,0 +1,31 @@ +my_var=10 +x=123 +echo $1 +echo $USER +${HOME} +((a+b)) +((a*b)) +((a/b)) +((a%b)) +((a|b)) +((a^b)) +((a=b)) +((a!b)) +((a<b)) +((a>b)) +$((a<b)) +$((a>b)) +$((a&b)) +$((a|b)) +${a:b} +${a:b} +${a:b} +${a:b} +${a#*/} +${a%.*} +${a^} +${a,} +${a} +${a[*]} +ls -a +ls --all diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh index 28f9d83d4c..4d4aa1650f 100755 --- a/t/t4041-diff-submodule-option.sh +++ b/t/t4041-diff-submodule-option.sh @@ -48,11 +48,12 @@ commit_file () { git commit "$@" -m "Commit $*" >/dev/null } -test_create_repo sm1 && -add_file . foo >/dev/null - -head1=$(add_file sm1 foo1 foo2) -fullhead1=$(cd sm1; git rev-parse --verify HEAD) +test_expect_success 'setup submodule' ' + git init sm1 && + add_file . foo && + head1=$(add_file sm1 foo1 foo2) && + fullhead1=$(cd sm1 && git rev-parse --verify HEAD) +' test_expect_success 'added submodule' ' git add sm1 && @@ -235,10 +236,13 @@ test_expect_success 'typechanged submodule(submodule->blob)' ' test_cmp expected actual ' -rm -f sm1 && -test_create_repo sm1 && -head6=$(add_file sm1 foo6 foo7) -fullhead6=$(cd sm1; git rev-parse --verify HEAD) +test_expect_success 'setup submodule anew' ' + rm -f sm1 && + git init sm1 && + head6=$(add_file sm1 foo6 foo7) && + fullhead6=$(cd sm1 && git rev-parse --verify HEAD) +' + test_expect_success 'nonexistent commit' ' git diff-index -p --submodule=log HEAD >actual && cat >expected <<-EOF && diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 5e5bad61ca..01db9243ab 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -295,4 +295,79 @@ test_expect_success PIPE,SYMLINKS 'diff --no-index reads from pipes' ' test_cmp expect actual ' +test_expect_success 'diff --no-index F F rejects pathspecs' ' + test_must_fail git diff --no-index -- a/1 a/2 a 2>actual.err && + test_grep "usage: git diff --no-index" actual.err +' + +test_expect_success 'diff --no-index D F rejects pathspecs' ' + test_must_fail git diff --no-index -- a a/2 a 2>actual.err && + test_grep "usage: git diff --no-index" actual.err +' + +test_expect_success 'diff --no-index F D rejects pathspecs' ' + test_must_fail git diff --no-index -- a/1 b b 2>actual.err && + test_grep "usage: git diff --no-index" actual.err +' + +test_expect_success 'diff --no-index rejects absolute pathspec' ' + test_must_fail git diff --no-index -- a b $(pwd)/a/1 +' + +test_expect_success 'diff --no-index with pathspec' ' + test_expect_code 1 git diff --name-status --no-index a b 1 >actual && + cat >expect <<-EOF && + D a/1 + EOF + test_cmp expect actual +' + +test_expect_success 'diff --no-index with pathspec no matches' ' + test_expect_code 0 git diff --name-status --no-index a b missing +' + +test_expect_success 'diff --no-index with negative pathspec' ' + test_expect_code 1 git diff --name-status --no-index a b ":!2" >actual && + cat >expect <<-EOF && + D a/1 + EOF + test_cmp expect actual +' + +test_expect_success 'setup nested' ' + mkdir -p c/1/2 && + mkdir -p d/1/2 && + echo 1 >c/1/2/a && + echo 2 >c/1/2/b +' + +test_expect_success 'diff --no-index with pathspec nested negative pathspec' ' + test_expect_code 0 git diff --no-index c d ":!1" +' + +test_expect_success 'diff --no-index with pathspec nested pathspec' ' + test_expect_code 1 git diff --name-status --no-index c d 1/2 >actual && + cat >expect <<-EOF && + D c/1/2/a + D c/1/2/b + EOF + test_cmp expect actual +' + +test_expect_success 'diff --no-index with pathspec glob' ' + test_expect_code 1 git diff --name-status --no-index c d ":(glob)**/a" >actual && + cat >expect <<-EOF && + D c/1/2/a + EOF + test_cmp expect actual +' + +test_expect_success 'diff --no-index with pathspec glob and exclude' ' + test_expect_code 1 git diff --name-status --no-index c d ":(glob,exclude)**/a" >actual && + cat >expect <<-EOF && + D c/1/2/b + EOF + test_cmp expect actual +' + test_done diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh index f7ff234cf9..ec2804eea6 100755 --- a/t/t4055-diff-context.sh +++ b/t/t4055-diff-context.sh @@ -89,4 +89,14 @@ test_expect_success '-U0 is valid, so is diff.context=0' ' grep "^+MODIFIED" output ' +test_expect_success '-U2147483647 works' ' + echo APPENDED >>x && + test_line_count = 16 x && + git diff -U2147483647 >output && + test_line_count = 22 output && + grep "^-ADDED" output && + grep "^+MODIFIED" output && + grep "^+APPENDED" output +' + test_done diff --git a/t/t4058-diff-duplicates.sh b/t/t4058-diff-duplicates.sh index 2fce4a9897..16266dff2a 100755 --- a/t/t4058-diff-duplicates.sh +++ b/t/t4058-diff-duplicates.sh @@ -13,6 +13,12 @@ test_description='test tree diff when trees have duplicate entries' . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping diff duplicates tests; Perl not available' + test_done +fi + # make_tree_entry <mode> <mode> <sha1> # # We have to rely on perl here because not all printfs understand diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh index 76b83101d3..dbfeb7470b 100755 --- a/t/t4060-diff-submodule-option-diff-format.sh +++ b/t/t4060-diff-submodule-option-diff-format.sh @@ -363,9 +363,12 @@ test_expect_success 'typechanged submodule(submodule->blob)' ' diff_cmp expected actual ' -rm -f sm1 && -test_create_repo sm1 && -head6=$(add_file sm1 foo6 foo7) +test_expect_success 'setup' ' + rm -f sm1 && + git init sm1 && + head6=$(add_file sm1 foo6 foo7) +' + test_expect_success 'nonexistent commit' ' git diff-index -p --submodule=diff HEAD >actual && cat >expected <<-EOF && diff --git a/t/t4069-remerge-diff.sh b/t/t4069-remerge-diff.sh index c6c94aef14..966882ce91 100755 --- a/t/t4069-remerge-diff.sh +++ b/t/t4069-remerge-diff.sh @@ -4,13 +4,6 @@ test_description='remerge-diff handling' . ./test-lib.sh -# This test is ort-specific -if test "${GIT_TEST_MERGE_ALGORITHM}" != ort -then - skip_all="GIT_TEST_MERGE_ALGORITHM != ort" - test_done -fi - test_expect_success 'setup basic merges' ' test_write_lines 1 2 3 4 5 6 7 8 9 >numbers && git add numbers && diff --git a/t/t4070-diff-pairs.sh b/t/t4070-diff-pairs.sh new file mode 100755 index 0000000000..70deafb860 --- /dev/null +++ b/t/t4070-diff-pairs.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='basic diff-pairs tests' +. ./test-lib.sh + +# This creates a diff with added, modified, deleted, renamed, copied, and +# typechange entries. This includes a submodule to test submodule diff support. +test_expect_success 'setup' ' + test_config_global protocol.file.allow always && + git init sub && + test_commit -C sub initial && + + git init main && + cd main && + echo to-be-gone >deleted && + echo original >modified && + echo now-a-file >symlink && + test_seq 200 >two-hundred && + test_seq 201 500 >five-hundred && + git add . && + test_tick && + git commit -m base && + git tag base && + + git submodule add ../sub && + echo now-here >added && + echo new >modified && + rm deleted && + mkdir subdir && + echo content >subdir/file && + mv two-hundred renamed && + test_seq 201 500 | sed s/300/modified/ >copied && + rm symlink && + git add -A . && + test_ln_s_add dest symlink && + test_tick && + git commit -m new && + git tag new +' + +test_expect_success 'diff-pairs recreates --raw' ' + git diff-tree -r -M -C -C -z base new >expect && + git diff-pairs --raw -z >actual <expect && + test_cmp expect actual +' + +test_expect_success 'diff-pairs can create -p output' ' + git diff-tree -p -M -C -C base new >expect && + git diff-tree -r -M -C -C -z base new | + git diff-pairs -p -z >actual && + test_cmp expect actual +' + +test_expect_success 'diff-pairs does not support normal raw diff input' ' + git diff-tree -r base new | + test_must_fail git diff-pairs >out 2>err && + + echo "usage: working without -z is not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs does not support tree objects as input' ' + git diff-tree -z base new | + test_must_fail git diff-pairs -z >out 2>err && + + echo "fatal: tree objects not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs does not support pathspec arguments' ' + git diff-tree -r -z base new | + test_must_fail git diff-pairs -z -- new >out 2>err && + + echo "usage: pathspec arguments not supported" >expect && + test_must_be_empty out && + test_cmp expect err +' + +test_expect_success 'diff-pairs explicit queue flush' ' + git diff-tree -r -M -C -C -z base new >expect && + printf "\0" >>expect && + git diff-tree -r -M -C -C -z base new >>expect && + + git diff-pairs --raw -z <expect >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t4071-diff-minimal.sh b/t/t4071-diff-minimal.sh new file mode 100755 index 0000000000..4c484dadfb --- /dev/null +++ b/t/t4071-diff-minimal.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +test_description='minimal diff algorithm' + +. ./test-lib.sh + +test_expect_success 'minimal diff should not mark changes between changed lines' ' + test_write_lines x x x x >pre && + test_write_lines x x x A B C D x E F G >post && + test_expect_code 1 git diff --no-index --minimal pre post >diff && + test_grep ! ^[+-]x diff +' + +test_done diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh index d370ecfe0d..8e302a5a57 100755 --- a/t/t4103-apply-binary.sh +++ b/t/t4103-apply-binary.sh @@ -26,10 +26,10 @@ test_expect_success 'setup' ' git commit -m "Initial Version" 2>/dev/null && git checkout -b binary && - perl -pe "y/x/\000/" <file1 >file3 && + tr "x" "\000" <file1 >file3 && cat file3 >file4 && git add file2 && - perl -pe "y/\000/v/" <file3 >file1 && + tr "y" "\000" <file3 >file1 && rm -f file2 && git update-index --add --remove file1 file2 file3 file4 && git commit -m "Second Version" && @@ -158,7 +158,7 @@ test_expect_success 'apply binary -p0 diff' ' test -z "$(git diff --name-status binary -- file3)" ' -test_expect_success 'reject truncated binary diff' ' +test_expect_success PERL_TEST_HELPERS 'reject truncated binary diff' ' do_reset && # this length is calculated to get us very close to diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh index 0784ba033a..1e7beab001 100755 --- a/t/t4116-apply-reverse.sh +++ b/t/t4116-apply-reverse.sh @@ -13,14 +13,14 @@ test_description='git apply in reverse test_expect_success setup ' test_write_lines a b c d e f g h i j k l m n >file1 && - perl -pe "y/ijk/\\000\\001\\002/" <file1 >file2 && + tr "ijk" "\000\001\002" <file1 >file2 && git add file1 file2 && git commit -m initial && git tag initial && test_write_lines a b c g h i J K L m o n p q >file1 && - perl -pe "y/mon/\\000\\001\\002/" <file1 >file2 && + tr "mon" "\000\001\002" <file1 >file2 && git commit -a -m second && git tag second && diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh index 2149ad5da4..1d6317bd71 100755 --- a/t/t4129-apply-samemode.sh +++ b/t/t4129-apply-samemode.sh @@ -102,15 +102,32 @@ test_expect_success POSIXPERM 'do not use core.sharedRepository for working tree ) ' +test_file_mode_common () { + if test "$1" = "000000" + then + test_must_be_empty "$2" + else + test_grep "^$1 " "$2" + fi +} + +test_file_mode_staged () { + git ls-files --stage -- "$2" >ls-files-output && + test_file_mode_common "$1" ls-files-output +} + +test_file_mode_HEAD () { + git ls-tree HEAD -- "$2" >ls-tree-output && + test_file_mode_common "$1" ls-tree-output +} + 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_file_mode_staged 100755 script.sh && test_tick && git commit -m "Add script" && - git ls-tree -r HEAD script.sh >ls-tree-output && - test_grep "^100755" ls-tree-output && + test_file_mode_HEAD 100755 script.sh && echo true >>script.sh && test_tick && git commit -m "Modify script" script.sh && @@ -126,7 +143,211 @@ test_expect_success 'git apply respects core.fileMode' ' test_grep ! "has type 100644, expected 100755" err && git apply --cached patch 2>err && - test_grep ! "has type 100644, expected 100755" err + test_grep ! "has type 100644, expected 100755" err && + git reset --hard +' + +test_expect_success 'setup: git apply [--reverse] warns about incorrect file modes' ' + test_config core.fileMode false && + + >mode_test && + git add --chmod=-x mode_test && + test_file_mode_staged 100644 mode_test && + test_tick && git commit -m "add mode_test" && + test_file_mode_HEAD 100644 mode_test && + git tag mode_test_forward_initial && + + echo content >>mode_test && + test_tick && git commit -m "append to mode_test" mode_test && + test_file_mode_HEAD 100644 mode_test && + git tag mode_test_reverse_initial && + + git format-patch -1 --stdout >patch && + test_grep "^index .* 100644$" patch +' + +test_expect_success 'git apply warns about incorrect file modes' ' + test_config core.fileMode false && + git reset --hard mode_test_forward_initial && + + git add --chmod=+x mode_test && + test_file_mode_staged 100755 mode_test && + test_tick && git commit -m "make mode_test executable" && + test_file_mode_HEAD 100755 mode_test && + + git apply --index patch 2>err && + test_grep "has type 100755, expected 100644" err && + test_file_mode_staged 100755 mode_test && + test_tick && git commit -m "redo: append to mode_test" && + test_file_mode_HEAD 100755 mode_test +' + +test_expect_success 'git apply --reverse warns about incorrect file modes' ' + test_config core.fileMode false && + git reset --hard mode_test_reverse_initial && + + git add --chmod=+x mode_test && + test_file_mode_staged 100755 mode_test && + test_tick && git commit -m "make mode_test executable" && + test_file_mode_HEAD 100755 mode_test && + + git apply --index --reverse patch 2>err && + test_grep "has type 100755, expected 100644" err && + test_file_mode_staged 100755 mode_test && + test_tick && git commit -m "undo: append to mode_test" && + test_file_mode_HEAD 100755 mode_test +' + +test_expect_success 'setup: git apply [--reverse] restores file modes (change_x_to_notx)' ' + test_config core.fileMode false && + + touch change_x_to_notx && + git add --chmod=+x change_x_to_notx && + test_file_mode_staged 100755 change_x_to_notx && + test_tick && git commit -m "add change_x_to_notx as executable" && + test_file_mode_HEAD 100755 change_x_to_notx && + + git add --chmod=-x change_x_to_notx && + test_file_mode_staged 100644 change_x_to_notx && + test_tick && git commit -m "make change_x_to_notx not executable" && + test_file_mode_HEAD 100644 change_x_to_notx && + + git rm change_x_to_notx && + test_file_mode_staged 000000 change_x_to_notx && + test_tick && git commit -m "remove change_x_to_notx" && + test_file_mode_HEAD 000000 change_x_to_notx && + + git format-patch -o patches -3 && + mv patches/0001-* change_x_to_notx-0001-create-0755.patch && + mv patches/0002-* change_x_to_notx-0002-chmod-0644.patch && + mv patches/0003-* change_x_to_notx-0003-delete.patch && + + test_grep "^new file mode 100755$" change_x_to_notx-0001-create-0755.patch && + test_grep "^old mode 100755$" change_x_to_notx-0002-chmod-0644.patch && + test_grep "^new mode 100644$" change_x_to_notx-0002-chmod-0644.patch && + test_grep "^deleted file mode 100644$" change_x_to_notx-0003-delete.patch && + + git tag change_x_to_notx_initial +' + +test_expect_success 'git apply restores file modes (change_x_to_notx)' ' + test_config core.fileMode false && + git reset --hard change_x_to_notx_initial && + + git apply --index change_x_to_notx-0001-create-0755.patch && + test_file_mode_staged 100755 change_x_to_notx && + test_tick && git commit -m "redo: add change_x_to_notx as executable" && + test_file_mode_HEAD 100755 change_x_to_notx && + + git apply --index change_x_to_notx-0002-chmod-0644.patch 2>err && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 100644 change_x_to_notx && + test_tick && git commit -m "redo: make change_x_to_notx not executable" && + test_file_mode_HEAD 100644 change_x_to_notx && + + git apply --index change_x_to_notx-0003-delete.patch 2>err && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 000000 change_x_to_notx && + test_tick && git commit -m "redo: remove change_notx_to_x" && + test_file_mode_HEAD 000000 change_x_to_notx +' + +test_expect_success 'git apply --reverse restores file modes (change_x_to_notx)' ' + test_config core.fileMode false && + git reset --hard change_x_to_notx_initial && + + git apply --index --reverse change_x_to_notx-0003-delete.patch && + test_file_mode_staged 100644 change_x_to_notx && + test_tick && git commit -m "undo: remove change_x_to_notx" && + test_file_mode_HEAD 100644 change_x_to_notx && + + git apply --index --reverse change_x_to_notx-0002-chmod-0644.patch 2>err && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 100755 change_x_to_notx && + test_tick && git commit -m "undo: make change_x_to_notx not executable" && + test_file_mode_HEAD 100755 change_x_to_notx && + + git apply --index --reverse change_x_to_notx-0001-create-0755.patch 2>err && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 000000 change_x_to_notx && + test_tick && git commit -m "undo: add change_x_to_notx as executable" && + test_file_mode_HEAD 000000 change_x_to_notx +' + +test_expect_success 'setup: git apply [--reverse] restores file modes (change_notx_to_x)' ' + test_config core.fileMode false && + + touch change_notx_to_x && + git add --chmod=-x change_notx_to_x && + test_file_mode_staged 100644 change_notx_to_x && + test_tick && git commit -m "add change_notx_to_x as not executable" && + test_file_mode_HEAD 100644 change_notx_to_x && + + git add --chmod=+x change_notx_to_x && + test_file_mode_staged 100755 change_notx_to_x && + test_tick && git commit -m "make change_notx_to_x executable" && + test_file_mode_HEAD 100755 change_notx_to_x && + + git rm change_notx_to_x && + test_file_mode_staged 000000 change_notx_to_x && + test_tick && git commit -m "remove change_notx_to_x" && + test_file_mode_HEAD 000000 change_notx_to_x && + + git format-patch -o patches -3 && + mv patches/0001-* change_notx_to_x-0001-create-0644.patch && + mv patches/0002-* change_notx_to_x-0002-chmod-0755.patch && + mv patches/0003-* change_notx_to_x-0003-delete.patch && + + test_grep "^new file mode 100644$" change_notx_to_x-0001-create-0644.patch && + test_grep "^old mode 100644$" change_notx_to_x-0002-chmod-0755.patch && + test_grep "^new mode 100755$" change_notx_to_x-0002-chmod-0755.patch && + test_grep "^deleted file mode 100755$" change_notx_to_x-0003-delete.patch && + + git tag change_notx_to_x_initial +' + +test_expect_success 'git apply restores file modes (change_notx_to_x)' ' + test_config core.fileMode false && + git reset --hard change_notx_to_x_initial && + + git apply --index change_notx_to_x-0001-create-0644.patch && + test_file_mode_staged 100644 change_notx_to_x && + test_tick && git commit -m "redo: add change_notx_to_x as not executable" && + test_file_mode_HEAD 100644 change_notx_to_x && + + git apply --index change_notx_to_x-0002-chmod-0755.patch 2>err && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 100755 change_notx_to_x && + test_tick && git commit -m "redo: make change_notx_to_x executable" && + test_file_mode_HEAD 100755 change_notx_to_x && + + git apply --index change_notx_to_x-0003-delete.patch && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 000000 change_notx_to_x && + test_tick && git commit -m "undo: remove change_notx_to_x" && + test_file_mode_HEAD 000000 change_notx_to_x +' + +test_expect_success 'git apply --reverse restores file modes (change_notx_to_x)' ' + test_config core.fileMode false && + git reset --hard change_notx_to_x_initial && + + git apply --index --reverse change_notx_to_x-0003-delete.patch && + test_file_mode_staged 100755 change_notx_to_x && + test_tick && git commit -m "undo: remove change_notx_to_x" && + test_file_mode_HEAD 100755 change_notx_to_x && + + git apply --index --reverse change_notx_to_x-0002-chmod-0755.patch 2>err && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 100644 change_notx_to_x && + test_tick && git commit -m "undo: make change_notx_to_x executable" && + test_file_mode_HEAD 100644 change_notx_to_x && + + git apply --index --reverse change_notx_to_x-0001-create-0644.patch 2>err && + test_grep ! "has type 100.*, expected 100.*" err && + test_file_mode_staged 000000 change_notx_to_x && + test_tick && git commit -m "undo: add change_notx_to_x as not executable" && + test_file_mode_HEAD 000000 change_notx_to_x ' test_expect_success POSIXPERM 'patch mode for new file is canonicalized' ' diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 5e2b6c80ea..2ae93d3c96 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -1084,13 +1084,13 @@ test_expect_success 'am works with multi-line in-body headers' ' Body test" --author="$LONG <long@example.com>" && git format-patch --stdout -1 >patch && # bump from, date, and subject down to in-body header - perl -lpe " - if (/^From:/) { + awk " + /^From:/{ print \"From: x <x\@example.com>\"; print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\"; print \"Subject: x\n\"; - } - " patch >msg && + }; 1 + " <patch >msg && git checkout HEAD^ && git am msg && # Ensure that the author and full message are present diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh index edb38da701..8e1ecf8a68 100755 --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@ -112,7 +112,7 @@ test_expect_success 'am --abort will keep dirty index intact' ' test_expect_success 'am -3 stops on conflict on unborn branch' ' git checkout -f --orphan orphan && git reset && - rm -f otherfile-4 && + rm -f file-1 otherfile-4 && test_must_fail git am -3 0003-*.patch && test 2 -eq $(git ls-files -u | wc -l) && test 4 = "$(cat otherfile-4)" diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index b0a3e84984..204325f4d5 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -81,7 +81,7 @@ test_expect_success 'activate rerere, old style (conflicting merge)' ' test_might_fail git config --unset rerere.enabled && test_must_fail git merge first && - sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + sha1=$(sed "s/ .*//" .git/MERGE_RR) && rr=.git/rr-cache/$sha1 && grep "^=======\$" $rr/preimage && ! test -f $rr/postimage && @@ -94,7 +94,7 @@ test_expect_success 'rerere.enabled works, too' ' git reset --hard && test_must_fail git merge first && - sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + sha1=$(sed "s/ .*//" .git/MERGE_RR) && rr=.git/rr-cache/$sha1 && grep ^=======$ $rr/preimage ' @@ -104,7 +104,7 @@ test_expect_success 'set up rr-cache' ' git config rerere.enabled true && git reset --hard && test_must_fail git merge first && - sha1=$(perl -pe "s/ .*//" .git/MERGE_RR) && + sha1=$(sed "s/ .*//" .git/MERGE_RR) && rr=.git/rr-cache/$sha1 ' @@ -188,7 +188,7 @@ test_expect_success 'rerere updates postimage timestamp' ' test_expect_success 'rerere clear' ' mv $rr/postimage .git/post-saved && - echo "$sha1 a1" | perl -pe "y/\012/\000/" >.git/MERGE_RR && + echo "$sha1 a1" | tr "\012" "\000" >.git/MERGE_RR && git rerere clear && ! test -d $rr ' diff --git a/t/t4202-log.sh b/t/t4202-log.sh index ad05f6772f..4a6c4dfbf4 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -487,7 +487,7 @@ test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurati ' cmds="show reflog format-patch" -if test_have_prereq WITHOUT_BREAKING_CHANGES +if test_have_prereq !WITH_BREAKING_CHANGES then cmds="$cmds whatchanged" fi @@ -1207,7 +1207,7 @@ test_expect_success 'reflog is expected format' ' test_cmp expect actual ' -test_expect_success WITHOUT_BREAKING_CHANGES 'whatchanged is expected format' ' +test_expect_success !WITH_BREAKING_CHANGES 'whatchanged is expected format' ' whatchanged="whatchanged --i-still-use-this" && git log --no-merges --raw >expect && git $whatchanged >actual && @@ -1223,7 +1223,7 @@ test_expect_success 'log.abbrevCommit configuration' ' git reflog --abbrev-commit >expect.reflog.abbrev && git reflog --no-abbrev-commit >expect.reflog.full && - if test_have_prereq WITHOUT_BREAKING_CHANGES + if test_have_prereq !WITH_BREAKING_CHANGES then git $whatchanged --abbrev-commit >expect.whatchanged.abbrev && git $whatchanged --no-abbrev-commit >expect.whatchanged.full @@ -1244,7 +1244,7 @@ test_expect_success 'log.abbrevCommit configuration' ' git reflog --no-abbrev-commit >actual && test_cmp expect.reflog.full actual && - if test_have_prereq WITHOUT_BREAKING_CHANGES + if test_have_prereq !WITH_BREAKING_CHANGES then git $whatchanged >actual && test_cmp expect.whatchanged.abbrev actual && diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 4a6242ff99..74b7ddccb2 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -1133,4 +1133,37 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us test_cmp expect actual ' +test_expect_success 'git cat-file --mailmap works with different author and committer' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + Mailmapped User <mailmapped-user@gitlab.com> C O Mitter <committer@example.com> + EOF + git commit --allow-empty -m "different author/committer" \ + --author="Different Author <different@example.com>" && + cat >expect <<-\EOF && + author Different Author <different@example.com> + committer Mailmapped User <mailmapped-user@gitlab.com> + EOF + git cat-file --mailmap commit HEAD >log && + sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual && + test_cmp expect actual +' + +test_expect_success 'git cat-file --mailmap maps both author and committer when both need mapping' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + Mapped Author <mapped-author@example.com> <different@example.com> + Mapped Committer <mapped-committer@example.com> C O Mitter <committer@example.com> + EOF + git commit --allow-empty -m "both author and committer mapped" \ + --author="Different Author <different@example.com>" && + cat >expect <<-\EOF && + author Mapped Author <mapped-author@example.com> + committer Mapped Committer <mapped-committer@example.com> + EOF + git cat-file --mailmap commit HEAD >log && + sed -n -e "/^author /s/>.*/>/p" -e "/^committer /s/>.*/>/p" log >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index f81e42a84d..8f2ba98963 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -698,7 +698,7 @@ test_expect_success '%(trailers:only=no,only=true) shows only "key: value" trail test_cmp expect actual ' -test_expect_success '%(trailers:unfold) unfolds trailers' ' +test_expect_success PERL_TEST_HELPERS '%(trailers:unfold) unfolds trailers' ' git log --no-walk --pretty="%(trailers:unfold)" >actual && { unfold <trailers && @@ -707,7 +707,7 @@ test_expect_success '%(trailers:unfold) unfolds trailers' ' test_cmp expect actual ' -test_expect_success ':only and :unfold work together' ' +test_expect_success PERL_TEST_HELPERS ':only and :unfold work together' ' git log --no-walk --pretty="%(trailers:only,unfold)" >actual && git log --no-walk --pretty="%(trailers:unfold,only)" >reverse && test_cmp actual reverse && @@ -754,7 +754,7 @@ test_expect_success '%(trailers:key=foo) handles multiple lines even if folded' test_cmp expect actual ' -test_expect_success '%(trailers:key=foo,unfold) properly unfolds' ' +test_expect_success PERL_TEST_HELPERS '%(trailers:key=foo,unfold) properly unfolds' ' git log --no-walk --pretty="format:%(trailers:key=Signed-Off-by,unfold)" >actual && unfold <trailers | grep Signed-off-by >expect && test_cmp expect actual diff --git a/t/t4206-log-follow-harder-copies.sh b/t/t4206-log-follow-harder-copies.sh index bcab71c8e8..190c484321 100755 --- a/t/t4206-log-follow-harder-copies.sh +++ b/t/t4206-log-follow-harder-copies.sh @@ -54,4 +54,36 @@ test_expect_success 'validate the output.' ' compare_diff_patch current expected ' +test_expect_success 'log --follow -B does not BUG' ' + git switch --orphan break_and_follow_are_icky_so_use_both && + + test_seq 1 127 >numbers && + git add numbers && + git commit -m "numbers" && + + printf "%s\n" A B C D E F G H I J K L M N O Q R S T U V W X Y Z >pool && + echo changed >numbers && + git add pool numbers && + git commit -m "pool" && + + git log -1 -B --raw --follow -- "p*" +' + +test_expect_success 'log --follow -B does not die or use uninitialized memory' ' + printf "%s\n" A B C D E F G H I J K L M N O P Q R S T U V W X Y Z >z && + git add z && + git commit -m "Initial" && + + test_seq 1 130 >z && + echo lame >somefile && + git add z somefile && + git commit -m "Rewrite z, introduce lame somefile" && + + echo Content >somefile && + git add somefile && + git commit -m "Rewrite somefile" && + + git log -B --follow somefile +' + test_done diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh index 3f163dc396..8910d53cac 100755 --- a/t/t4216-log-bloom.sh +++ b/t/t4216-log-bloom.sh @@ -738,20 +738,20 @@ check_corrupt_graph () { test_cmp expect.out out } -test_expect_success 'Bloom reader notices too-small data chunk' ' +test_expect_success PERL_TEST_HELPERS 'Bloom reader notices too-small data chunk' ' check_corrupt_graph BDAT clear 00000000 && echo "warning: ignoring too-small changed-path chunk" \ "(4 < 12) in commit-graph file" >expect.err && test_cmp expect.err err ' -test_expect_success 'Bloom reader notices out-of-bounds filter offsets' ' +test_expect_success PERL_TEST_HELPERS 'Bloom reader notices out-of-bounds filter offsets' ' check_corrupt_graph BIDX 12 FFFFFFFF && # use grep to avoid depending on exact chunk size grep "warning: ignoring out-of-range offset (4294967295) for changed-path filter at pos 3 of .git/objects/info/commit-graph" err ' -test_expect_success 'Bloom reader notices too-small index chunk' ' +test_expect_success PERL_TEST_HELPERS 'Bloom reader notices too-small index chunk' ' # replace the index with a single entry, making most # lookups out-of-bounds check_corrupt_graph BIDX clear 00000000 && @@ -760,7 +760,7 @@ test_expect_success 'Bloom reader notices too-small index chunk' ' test_cmp expect.err err ' -test_expect_success 'Bloom reader notices out-of-order index offsets' ' +test_expect_success PERL_TEST_HELPERS 'Bloom reader notices out-of-order index offsets' ' # we do not know any real offsets, but we can pick # something plausible; we should not get to the point of # actually reading from the bogus offsets anyway. diff --git a/t/t4255-am-submodule.sh b/t/t4255-am-submodule.sh index a7ba08f728..e6679a01b4 100755 --- a/t/t4255-am-submodule.sh +++ b/t/t4255-am-submodule.sh @@ -19,7 +19,6 @@ am_3way () { $2 git am --3way patch } -KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 test_submodule_switch_func "am_3way" test_expect_success 'setup diff.submodule' ' diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index eea19907b5..6e117ee93c 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -4,13 +4,6 @@ test_description='git merge-tree --write-tree' . ./test-lib.sh -# This test is ort-specific -if test "$GIT_TEST_MERGE_ALGORITHM" != "ort" -then - skip_all="GIT_TEST_MERGE_ALGORITHM != ort" - test_done -fi - test_expect_success setup ' test_write_lines 1 2 3 4 5 >numbers && echo hello >greeting && @@ -61,6 +54,25 @@ test_expect_success setup ' git commit -m first-commit ' +test_expect_success '--quiet on clean merge' ' + # Get rid of loose objects to start with + git gc && + echo "0 objects, 0 kilobytes" >expect && + git count-objects >actual && + test_cmp expect actual && + + # Ensure merge is successful (exit code of 0) + git merge-tree --write-tree --quiet side1 side3 >output && + + # Ensure there is no output + test_must_be_empty output && + + # Ensure no loose objects written (all new objects written would have + # been in "outer layer" of the merge) + git count-objects >actual && + test_cmp expect actual +' + test_expect_success 'Clean merge' ' TREE_OID=$(git merge-tree --write-tree side1 side3) && q_to_tab <<-EOF >expect && @@ -73,6 +85,31 @@ test_expect_success 'Clean merge' ' test_cmp expect actual ' +# Repeat the previous test, but turn off rename detection +test_expect_success 'Failed merge without rename detection' ' + test_must_fail git -c diff.renames=false merge-tree --write-tree side1 side3 >out && + grep "CONFLICT (modify/delete): numbers deleted" out +' + +test_expect_success '--quiet on conflicted merge' ' + # Get rid of loose objects to start with + git gc && + echo "0 objects, 0 kilobytes" >expect && + git count-objects >actual && + test_cmp expect actual && + + # Ensure merge has conflict + test_expect_code 1 git merge-tree --write-tree --quiet side1 side2 >output && + + # Ensure there is no output + test_must_be_empty output && + + # Ensure no loose objects written (all new objects written would have + # been in "outer layer" of the merge) + git count-objects >actual && + test_cmp expect actual +' + test_expect_success 'Content merge and a few conflicts' ' git checkout side1^0 && test_must_fail git merge side2 && diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index 50344e17ca..5174995191 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -4,6 +4,12 @@ test_description='test corner cases of git-archive' . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping archive corner cases tests; Perl not available' + test_done +fi + # the 10knuls.tar file is used to test for an empty git generated tar # without having to invoke tar because an otherwise valid empty GNU tar # will be considered broken by {Open,Net}BSD tar diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh index cb67bac1c4..270ce6ea48 100755 --- a/t/t5150-request-pull.sh +++ b/t/t5150-request-pull.sh @@ -7,12 +7,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh -if ! test_have_prereq PERL -then - skip_all='skipping request-pull tests, perl not available' - test_done -fi - test_expect_success 'setup' ' git init --bare upstream.git && diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 5ac8d39094..ae72158b94 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -9,9 +9,9 @@ test_description='git pack-object' test_expect_success 'setup' ' rm -f .git/index* && - perl -e "print \"a\" x 4096;" >a && - perl -e "print \"b\" x 4096;" >b && - perl -e "print \"c\" x 4096;" >c && + test-tool genzeros 4096 | tr "\000" "a" >a && + test-tool genzeros 4096 | tr "\000" "b" >b && + test-tool genzeros 4096 | tr "\000" "c" >c && test-tool genrandom "seed a" 2097152 >a_big && test-tool genrandom "seed b" 2097152 >b_big && git update-index --add a a_big b b_big c && @@ -140,7 +140,7 @@ test_expect_success 'pack-object <stdin parsing: --stdin-packs handles garbage' # usage: check_deltas <stderr_from_pack_objects> <cmp_op> <nr_deltas> # e.g.: check_deltas stderr -gt 0 check_deltas() { - deltas=$(perl -lne '/delta (\d+)/ and print $1' "$1") && + deltas=$(sed -n 's/Total [0-9][0-9]* (delta \([0-9][0-9]*\)).*/\1/p' "$1") && shift && if ! test "$deltas" "$@" then @@ -215,7 +215,7 @@ test_expect_success 'unpack with OFS_DELTA (core.fsyncmethod=batch)' ' check_unpack test-3-${packname_3} obj-list "$BATCH_CONFIGURATION" ' -test_expect_success 'compare delta flavors' ' +test_expect_success PERL_TEST_HELPERS 'compare delta flavors' ' perl -e '\'' defined($_ = -s $_) or die for @ARGV; exit 1 if $ARGV[0] <= $ARGV[1]; @@ -723,4 +723,23 @@ test_expect_success '--name-hash-version=2 and --write-bitmap-index are incompat ! test_grep "currently, --write-bitmap-index requires --name-hash-version=1" err ' +test_expect_success '--path-walk pack everything' ' + git -C server rev-parse HEAD >in && + GIT_PROGRESS_DELAY=0 git -C server pack-objects \ + --stdout --revs --path-walk --progress <in >out.pack 2>err && + grep "Compressing objects by path" err && + git -C server index-pack --stdin <out.pack +' + +test_expect_success '--path-walk thin pack' ' + cat >in <<-EOF && + $(git -C server rev-parse HEAD) + ^$(git -C server rev-parse HEAD~2) + EOF + GIT_PROGRESS_DELAY=0 git -C server pack-objects \ + --thin --stdout --revs --path-walk --progress <in >out.pack 2>err && + grep "Compressing objects by path" err && + git -C server index-pack --fix-thin --stdin <out.pack +' + test_done diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh index de58ca654a..ab99c8b685 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -103,7 +103,8 @@ test_expect_success 'create corruption in data of first object' ' create_new_pack && git prune-packed && chmod +w ${pack}.pack && - perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack && + sed "s/ base /abcdef/" ${pack}.pack >${pack}.pack.munged && + mv ${pack}.pack.munged ${pack}.pack && test_must_fail git cat-file blob $blob_1 > /dev/null && test_must_fail git cat-file blob $blob_2 > /dev/null && test_must_fail git cat-file blob $blob_3 > /dev/null @@ -160,7 +161,8 @@ test_expect_success 'create corruption in data of first delta' ' create_new_pack && git prune-packed && chmod +w ${pack}.pack && - perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack && + sed "s/ delta1 /abcdefgh/" ${pack}.pack >${pack}.pack.munged && + mv ${pack}.pack.munged ${pack}.pack && git cat-file blob $blob_1 > /dev/null && test_must_fail git cat-file blob $blob_2 > /dev/null && test_must_fail git cat-file blob $blob_3 > /dev/null diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh index 805d60ff31..609399d54f 100755 --- a/t/t5306-pack-nobase.sh +++ b/t/t5306-pack-nobase.sh @@ -59,6 +59,11 @@ test_expect_success 'indirectly clone patch_clone' ' git pull ../.git && test $(git rev-parse HEAD) = $B && + # The --path-walk feature of "git pack-objects" is not + # compatible with this kind of fetch from an incomplete repo. + GIT_TEST_PACK_PATH_WALK=0 && + export GIT_TEST_PACK_PATH_WALK && + git pull ../patch_clone/.git && test $(git rev-parse HEAD) = $C ) diff --git a/t/t5309-pack-delta-cycles.sh b/t/t5309-pack-delta-cycles.sh index 60fc710bac..6b03675d91 100755 --- a/t/t5309-pack-delta-cycles.sh +++ b/t/t5309-pack-delta-cycles.sh @@ -60,7 +60,10 @@ test_expect_success 'index-pack detects REF_DELTA cycles' ' test_expect_success 'failover to an object in another pack' ' clear_packs && git index-pack --stdin <ab.pack && - test_must_fail git index-pack --stdin --fix-thin <cycle.pack + + # This cycle does not fail since the existence of A & B in + # the repo allows us to resolve the cycle. + git index-pack --stdin --fix-thin <cycle.pack ' test_expect_success 'failover to a duplicate object in the same pack' ' @@ -72,7 +75,34 @@ test_expect_success 'failover to a duplicate object in the same pack' ' pack_obj $A } >recoverable.pack && pack_trailer recoverable.pack && - test_must_fail git index-pack --fix-thin --stdin <recoverable.pack + + # This cycle does not fail since the existence of a full copy + # of A in the pack allows us to resolve the cycle. + git index-pack --fix-thin --stdin <recoverable.pack +' + +test_expect_success 'index-pack works with thin pack A->B->C with B on disk' ' + git init server && + ( + cd server && + test_commit_bulk 4 + ) && + + A=$(git -C server rev-parse HEAD^{tree}) && + B=$(git -C server rev-parse HEAD~1^{tree}) && + C=$(git -C server rev-parse HEAD~2^{tree}) && + git -C server reset --hard HEAD~1 && + + test-tool -C server pack-deltas --num-objects=2 >thin.pack <<-EOF && + REF_DELTA $A $B + REF_DELTA $B $C + EOF + + git clone "file://$(pwd)/server" client && + ( + cd client && + git index-pack --fix-thin --stdin <../thin.pack + ) ' test_done diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index 621bbbdd26..b6926f1027 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -158,8 +158,9 @@ test_bitmap_cases () { ls .git/objects/pack/ | grep bitmap >output && test_line_count = 1 output && # verify equivalent packs are generated with/without using bitmap index - packasha1=$(git pack-objects --no-use-bitmap-index --all packa </dev/null) && - packbsha1=$(git pack-objects --use-bitmap-index --all packb </dev/null) && + # Be careful to not use the path-walk option in either case. + packasha1=$(git pack-objects --no-use-bitmap-index --no-path-walk --all packa </dev/null) && + packbsha1=$(git pack-objects --use-bitmap-index --no-path-walk --all packb </dev/null) && list_packed_objects packa-$packasha1.idx >packa.objects && list_packed_objects packb-$packbsha1.idx >packb.objects && test_cmp packa.objects packb.objects @@ -388,6 +389,14 @@ test_bitmap_cases () { git init --bare client.git && ( cd client.git && + + # This test relies on reusing a delta, but if the + # path-walk machinery is engaged, the base object + # is considered too small to use during the + # dynamic computation, so is not used. + GIT_TEST_PACK_PATH_WALK=0 && + export GIT_TEST_PACK_PATH_WALK && + git config transfer.unpackLimit 1 && git fetch .. delta-reuse-old:delta-reuse-old && git fetch .. delta-reuse-new:delta-reuse-new && @@ -421,7 +430,7 @@ test_bitmap_cases () { # mark the commits which did not receive bitmaps as preferred, # and generate the bitmap again - perl -pe "s{^}{create refs/tags/include/$. }" <before | + sed "s|\(.*\)|create refs/tags/include/\1 \1|" before | git update-ref --stdin && git -c pack.preferBitmapTips=refs/tags/include repack -adb && diff --git a/t/t5316-pack-delta-depth.sh b/t/t5316-pack-delta-depth.sh index 32cf422745..03dfb7a61e 100755 --- a/t/t5316-pack-delta-depth.sh +++ b/t/t5316-pack-delta-depth.sh @@ -76,11 +76,11 @@ test_expect_success 'create series of packs' ' max_chain() { git index-pack --verify-stat-only "$1" >output && - perl -lne ' - BEGIN { $len = 0 } - /chain length = (\d+)/ and $len = $1; - END { print $len } - ' output + awk ' + BEGIN { len=0 } + /chain length = [0-9]+:/{ len=$4 } + END { print len } + ' <output | tr -d ':' } # Note that this whole setup is pretty reliant on the current @@ -89,15 +89,18 @@ max_chain() { # adjusted (or scrapped if the heuristics have become too unreliable) test_expect_success 'packing produces a long delta' ' # Use --window=0 to make sure we are seeing reused deltas, - # not computing a new long chain. - pack=$(git pack-objects --all --window=0 </dev/null pack) && + # not computing a new long chain. (Also avoid the --path-walk + # option as it may break delta chains.) + pack=$(git pack-objects --all --window=0 --no-path-walk </dev/null pack) && echo 9 >expect && max_chain pack-$pack.pack >actual && test_cmp expect actual ' test_expect_success '--depth limits depth' ' - pack=$(git pack-objects --all --depth=5 </dev/null pack) && + # Avoid --path-walk to avoid breaking delta chains across path + # boundaries. + pack=$(git pack-objects --all --depth=5 --no-path-walk </dev/null pack) && echo 5 >expect && max_chain pack-$pack.pack >actual && test_cmp expect actual diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index f68f64cd85..0b3404f58f 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -837,7 +837,7 @@ check_corrupt_chunk () { test_cmp expect.out out } -test_expect_success 'reader notices too-small oid fanout chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small oid fanout chunk' ' # make it big enough that the graph file is plausible, # otherwise we hit an earlier check check_corrupt_chunk OIDF clear $(printf "000000%02x" $(test_seq 250)) && @@ -848,7 +848,7 @@ test_expect_success 'reader notices too-small oid fanout chunk' ' test_cmp expect.err err ' -test_expect_success 'reader notices fanout/lookup table mismatch' ' +test_expect_success PERL_TEST_HELPERS 'reader notices fanout/lookup table mismatch' ' check_corrupt_chunk OIDF 1020 "FFFFFFFF" && cat >expect.err <<-\EOF && error: commit-graph OID lookup chunk is the wrong size @@ -857,7 +857,7 @@ test_expect_success 'reader notices fanout/lookup table mismatch' ' test_cmp expect.err err ' -test_expect_success 'reader notices out-of-bounds fanout' ' +test_expect_success PERL_TEST_HELPERS 'reader notices out-of-bounds fanout' ' # Rather than try to corrupt a specific hash, we will just # wreck them all. But we cannot just set them all to 0xFFFFFFFF or # similar, as they are used for hi/lo starts in a binary search (so if @@ -873,7 +873,7 @@ test_expect_success 'reader notices out-of-bounds fanout' ' test_cmp expect.err err ' -test_expect_success 'reader notices too-small commit data chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small commit data chunk' ' check_corrupt_chunk CDAT clear 00000000 && cat >expect.err <<-\EOF && error: commit-graph commit data chunk is wrong size @@ -882,7 +882,7 @@ test_expect_success 'reader notices too-small commit data chunk' ' test_cmp expect.err err ' -test_expect_success 'reader notices out-of-bounds extra edge' ' +test_expect_success PERL_TEST_HELPERS 'reader notices out-of-bounds extra edge' ' check_corrupt_chunk EDGE clear && cat >expect.err <<-\EOF && error: commit-graph extra-edges pointer out of bounds @@ -890,7 +890,7 @@ test_expect_success 'reader notices out-of-bounds extra edge' ' test_cmp expect.err err ' -test_expect_success 'reader notices too-small generations chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small generations chunk' ' check_corrupt_chunk GDA2 clear 00000000 && cat >expect.err <<-\EOF && error: commit-graph generations chunk is wrong size diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index 0f215ad2e8..bd75dea950 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -1120,7 +1120,7 @@ corrupt_chunk () { corrupt_chunk_file $midx "$@" } -test_expect_success 'reader notices too-small oid fanout chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small oid fanout chunk' ' corrupt_chunk OIDF clear 00000000 && test_must_fail git log 2>err && cat >expect <<-\EOF && @@ -1130,7 +1130,7 @@ test_expect_success 'reader notices too-small oid fanout chunk' ' test_cmp expect err ' -test_expect_success 'reader notices too-small oid lookup chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small oid lookup chunk' ' corrupt_chunk OIDL clear 00000000 && test_must_fail git log 2>err && cat >expect <<-\EOF && @@ -1140,7 +1140,7 @@ test_expect_success 'reader notices too-small oid lookup chunk' ' test_cmp expect err ' -test_expect_success 'reader notices too-small pack names chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small pack names chunk' ' # There is no NUL to terminate the name here, so the # chunk is too short. corrupt_chunk PNAM clear 70656666 && @@ -1151,7 +1151,7 @@ test_expect_success 'reader notices too-small pack names chunk' ' test_cmp expect err ' -test_expect_success 'reader handles unaligned chunks' ' +test_expect_success PERL_TEST_HELPERS 'reader handles unaligned chunks' ' # A 9-byte PNAM means all of the subsequent chunks # will no longer be 4-byte aligned, but it is still # a valid one-pack chunk on its own (it is "foo.pack\0"). @@ -1165,7 +1165,7 @@ test_expect_success 'reader handles unaligned chunks' ' test_cmp expect.err err ' -test_expect_success 'reader notices too-small object offset chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small object offset chunk' ' corrupt_chunk OOFF clear 00000000 && test_must_fail git log 2>err && cat >expect <<-\EOF && @@ -1175,7 +1175,7 @@ test_expect_success 'reader notices too-small object offset chunk' ' test_cmp expect err ' -test_expect_success 'reader bounds-checks large offset table' ' +test_expect_success PERL_TEST_HELPERS 'reader bounds-checks large offset table' ' # re-use the objects64 dir here to cheaply get access to a midx # with large offsets. git init repo && @@ -1197,7 +1197,7 @@ test_expect_success 'reader bounds-checks large offset table' ' ) ' -test_expect_success 'reader notices too-small revindex chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader notices too-small revindex chunk' ' # We only get a revindex with bitmaps (and likewise only # load it when they are asked for). test_config repack.writeBitmaps true && @@ -1214,7 +1214,7 @@ test_expect_success 'reader notices too-small revindex chunk' ' test_cmp expect.err err ' -test_expect_success 'reader notices out-of-bounds fanout' ' +test_expect_success PERL_TEST_HELPERS 'reader notices out-of-bounds fanout' ' # This is similar to the out-of-bounds fanout test in t5318. The values # in adjacent entries should be large but not identical (they # are used as hi/lo starts for a binary search, which would then abort diff --git a/t/t5323-pack-redundant.sh b/t/t5323-pack-redundant.sh index f2f20cfa40..2d96afd6f7 100755 --- a/t/t5323-pack-redundant.sh +++ b/t/t5323-pack-redundant.sh @@ -36,7 +36,7 @@ relationship between packs and objects is as follows: . ./test-lib.sh -if ! test_have_prereq WITHOUT_BREAKING_CHANGES +if test_have_prereq WITH_BREAKING_CHANGES then skip_all='skipping git-pack-redundant tests; built with breaking changes' test_done diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index a32be3867d..49a057cc2e 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -401,7 +401,7 @@ test_expect_success 'verify across alternates' ' ) ' -test_expect_success 'reader bounds-checks base-graph chunk' ' +test_expect_success PERL_TEST_HELPERS 'reader bounds-checks base-graph chunk' ' git clone --no-hardlinks . corrupt-base-chunk && ( cd corrupt-base-chunk && diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh index d27557b9b0..892aeb09e4 100755 --- a/t/t5326-multi-pack-bitmaps.sh +++ b/t/t5326-multi-pack-bitmaps.sh @@ -176,8 +176,8 @@ test_midx_bitmap_cases () { comm -13 bitmaps commits >before && test_line_count = 1 before && - perl -ne "printf(\"create refs/tags/include/%d \", $.); print" \ - <before | git update-ref --stdin && + sed "s|\(.*\)|create refs/tags/include/\1 \1|" before | + git update-ref --stdin && rm -fr $midx-$(midx_checksum $objdir).bitmap && rm -fr $midx && diff --git a/t/t5328-commit-graph-64bit-time.sh b/t/t5328-commit-graph-64bit-time.sh index a766a3e3f8..d8891e6a92 100755 --- a/t/t5328-commit-graph-64bit-time.sh +++ b/t/t5328-commit-graph-64bit-time.sh @@ -74,7 +74,7 @@ test_expect_success 'single commit with generation data exceeding UINT32_MAX' ' git -C repo-uint32-max commit-graph verify ' -test_expect_success 'reader notices out-of-bounds generation overflow' ' +test_expect_success PERL_TEST_HELPERS 'reader notices out-of-bounds generation overflow' ' graph=.git/objects/info/commit-graph && test_when_finished "rm -rf $graph" && git commit-graph write --reachable && diff --git a/t/t5329-pack-objects-cruft.sh b/t/t5329-pack-objects-cruft.sh index b71a0aef40..25ddda5cf3 100755 --- a/t/t5329-pack-objects-cruft.sh +++ b/t/t5329-pack-objects-cruft.sh @@ -360,43 +360,6 @@ test_expect_success 'expired objects are pruned' ' ) ' -test_expect_success 'repack --cruft generates a cruft pack' ' - git init repo && - test_when_finished "rm -fr repo" && - ( - cd repo && - - test_commit reachable && - git branch -M main && - git checkout --orphan other && - test_commit unreachable && - - git checkout main && - git branch -D other && - git tag -d unreachable && - # objects are not cruft if they are contained in the reflogs - git reflog expire --all --expire=all && - - git rev-list --objects --all --no-object-names >reachable.raw && - git cat-file --batch-all-objects --batch-check="%(objectname)" >objects && - sort <reachable.raw >reachable && - comm -13 reachable objects >unreachable && - - git repack --cruft -d && - - cruft=$(basename $(ls $packdir/pack-*.mtimes) .mtimes) && - pack=$(basename $(ls $packdir/pack-*.pack | grep -v $cruft) .pack) && - - git show-index <$packdir/$pack.idx >actual.raw && - cut -f2 -d" " actual.raw | sort >actual && - test_cmp reachable actual && - - git show-index <$packdir/$cruft.idx >actual.raw && - cut -f2 -d" " actual.raw | sort >actual && - test_cmp unreachable actual - ) -' - test_expect_success 'loose objects mtimes upsert others' ' git init repo && test_when_finished "rm -fr repo" && @@ -470,219 +433,6 @@ test_expect_success 'expiring cruft objects with git gc' ' ) ' -test_expect_success 'cruft packs are not included in geometric repack' ' - git init repo && - test_when_finished "rm -fr repo" && - ( - cd repo && - - test_commit reachable && - git repack -Ad && - git branch -M main && - - git checkout --orphan other && - test_commit cruft && - git repack -d && - - git checkout main && - git branch -D other && - git tag -d cruft && - git reflog expire --all --expire=all && - - git repack --cruft && - - find $packdir -type f | sort >before && - git repack --geometric=2 -d && - find $packdir -type f | sort >after && - - test_cmp before after - ) -' - -test_expect_success 'repack --geometric collects once-cruft objects' ' - git init repo && - test_when_finished "rm -fr repo" && - ( - cd repo && - - test_commit reachable && - git repack -Ad && - git branch -M main && - - git checkout --orphan other && - git rm -rf . && - test_commit --no-tag cruft && - cruft="$(git rev-parse HEAD)" && - - git checkout main && - git branch -D other && - git reflog expire --all --expire=all && - - # Pack the objects created in the previous step into a cruft - # pack. Intentionally leave loose copies of those objects - # around so we can pick them up in a subsequent --geometric - # reapack. - git repack --cruft && - - # Now make those objects reachable, and ensure that they are - # packed into the new pack created via a --geometric repack. - git update-ref refs/heads/other $cruft && - - # Without this object, the set of unpacked objects is exactly - # the set of objects already in the cruft pack. Tweak that set - # to ensure we do not overwrite the cruft pack entirely. - test_commit reachable2 && - - find $packdir -name "pack-*.idx" | sort >before && - git repack --geometric=2 -d && - find $packdir -name "pack-*.idx" | sort >after && - - { - git rev-list --objects --no-object-names $cruft && - git rev-list --objects --no-object-names reachable..reachable2 - } >want.raw && - sort want.raw >want && - - pack=$(comm -13 before after) && - git show-index <$pack >objects.raw && - - cut -d" " -f2 objects.raw | sort >got && - - test_cmp want got - ) -' - -test_expect_success 'cruft repack with no reachable objects' ' - git init repo && - test_when_finished "rm -fr repo" && - ( - cd repo && - - test_commit base && - git repack -ad && - - base="$(git rev-parse base)" && - - git for-each-ref --format="delete %(refname)" >in && - git update-ref --stdin <in && - git reflog expire --all --expire=all && - rm -fr .git/index && - - git repack --cruft -d && - - git cat-file -t $base - ) -' - -write_blob () { - test-tool genrandom "$@" >in && - git hash-object -w -t blob in -} - -find_pack () { - for idx in $(ls $packdir/pack-*.idx) - do - git show-index <$idx >out && - if grep -q "$1" out - then - echo $idx - fi || return 1 - done -} - -test_expect_success 'cruft repack with --max-pack-size' ' - git init max-pack-size && - ( - cd max-pack-size && - test_commit base && - - # two cruft objects which exceed the maximum pack size - foo=$(write_blob foo 1048576) && - bar=$(write_blob bar 1048576) && - test-tool chmtime --get -1000 \ - "$objdir/$(test_oid_to_path $foo)" >foo.mtime && - test-tool chmtime --get -2000 \ - "$objdir/$(test_oid_to_path $bar)" >bar.mtime && - git repack --cruft --max-pack-size=1M && - find $packdir -name "*.mtimes" >cruft && - test_line_count = 2 cruft && - - foo_mtimes="$(basename $(find_pack $foo) .idx).mtimes" && - bar_mtimes="$(basename $(find_pack $bar) .idx).mtimes" && - test-tool pack-mtimes $foo_mtimes >foo.actual && - test-tool pack-mtimes $bar_mtimes >bar.actual && - - echo "$foo $(cat foo.mtime)" >foo.expect && - echo "$bar $(cat bar.mtime)" >bar.expect && - - test_cmp foo.expect foo.actual && - test_cmp bar.expect bar.actual && - test "$foo_mtimes" != "$bar_mtimes" - ) -' - -test_expect_success 'cruft repack with pack.packSizeLimit' ' - ( - cd max-pack-size && - # repack everything back together to remove the existing cruft - # pack (but to keep its objects) - git repack -adk && - git -c pack.packSizeLimit=1M repack --cruft && - # ensure the same post condition is met when --max-pack-size - # would otherwise be inferred from the configuration - find $packdir -name "*.mtimes" >cruft && - test_line_count = 2 cruft && - for pack in $(cat cruft) - do - test-tool pack-mtimes "$(basename $pack)" >objects && - test_line_count = 1 objects || return 1 - done - ) -' - -test_expect_success 'cruft repack respects repack.cruftWindow' ' - git init repo && - test_when_finished "rm -fr repo" && - ( - cd repo && - - test_commit base && - - GIT_TRACE2_EVENT=$(pwd)/event.trace \ - git -c pack.window=1 -c repack.cruftWindow=2 repack \ - --cruft --window=3 && - - grep "pack-objects.*--window=2.*--cruft" event.trace - ) -' - -test_expect_success 'cruft repack respects --window by default' ' - git init repo && - test_when_finished "rm -fr repo" && - ( - cd repo && - - test_commit base && - - GIT_TRACE2_EVENT=$(pwd)/event.trace \ - git -c pack.window=2 repack --cruft --window=3 && - - grep "pack-objects.*--window=3.*--cruft" event.trace - ) -' - -test_expect_success 'cruft repack respects --quiet' ' - git init repo && - test_when_finished "rm -fr repo" && - ( - cd repo && - - test_commit base && - GIT_PROGRESS_DELAY=0 git repack --cruft --quiet 2>err && - test_must_be_empty err - ) -' - test_expect_success 'cruft --local drops unreachable objects' ' git init alternate && git init repo && @@ -945,4 +695,56 @@ test_expect_success 'additional cruft blobs via gc.recentObjectsHook' ' ) ' +test_expect_success 'split cruft packs with --max-cruft-size' ' + repo=cruft-with--max-cruft-size && + test_when_finished "rm -fr $repo" && + + git init "$repo" && + + ( + cd "$repo" && + + git config core.compression 0 && + + sz=$((1024 * 1024)) && # 1MiB + test-tool genrandom foo $sz >foo && + test-tool genrandom bar $sz >bar && + foo="$(git hash-object -w -t blob foo)" && + bar="$(git hash-object -w -t blob bar)" && + + to=$packdir/pack && + # Pack together foo and bar into a single 2MiB pack. + pack="$(git pack-objects $to <<-EOF + $foo + $bar + EOF + )" && + + # Then generate a cruft pack containing foo and bar. + # + # Generate the pack with --max-pack-size equal to the + # size of one object, forcing us to write two cruft + # packs. + git pack-objects --cruft --max-pack-size=$sz $to <<-EOF && + -pack-$pack.pack + EOF + + ls $packdir/pack-*.mtimes >crufts && + test_line_count = 2 crufts && + + for cruft in $(cat crufts) + do + test-tool pack-mtimes "$(basename "$cruft")" || return 1 + done >actual.raw && + + cut -d" " -f1 <actual.raw | sort >actual && + sort >expect <<-EOF && + $foo + $bar + EOF + + test_cmp expect actual + ) +' + test_done diff --git a/t/t5332-multi-pack-reuse.sh b/t/t5332-multi-pack-reuse.sh index 57cad7708f..395d09444c 100755 --- a/t/t5332-multi-pack-reuse.sh +++ b/t/t5332-multi-pack-reuse.sh @@ -7,6 +7,13 @@ test_description='pack-objects multi-pack reuse' GIT_TEST_MULTI_PACK_INDEX=0 GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 + +# The --path-walk option does not consider the preferred pack +# at all for reusing deltas, so this variable changes the +# behavior of this test, if enabled. +GIT_TEST_PACK_PATH_WALK=0 +export GIT_TEST_PACK_PATH_WALK + objdir=.git/objects packdir=$objdir/pack diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh index 3905cb6e4f..ba5ae6a00c 100755 --- a/t/t5333-pseudo-merge-bitmaps.sh +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -28,9 +28,8 @@ test_pseudo_merges_reused () { tag_everything () { git rev-list --all --no-object-names >in && - perl -lne ' - print "create refs/tags/" . $. . " " . $1 if /([0-9a-f]+)/ - ' <in | git update-ref --stdin + sed 's|\(.*\)|create refs/tags/\1 \1|' in | + git update-ref --stdin } test_expect_success 'setup' ' @@ -102,7 +101,7 @@ test_expect_success 'stale bitmap traversal with pseudo-merges' ' test_cmp expect actual ' -test_expect_success 'bitmapPseudoMerge.sampleRate adjusts commit selection rate' ' +test_expect_success PERL_TEST_HELPERS 'bitmapPseudoMerge.sampleRate adjusts commit selection rate' ' test_config bitmapPseudoMerge.test.pattern "refs/tags/" && test_config bitmapPseudoMerge.test.maxMerges 1 && test_config bitmapPseudoMerge.test.stableThreshold never && @@ -235,8 +234,7 @@ test_expect_success 'pseudo-merge pattern with capture groups' ' test_commit_bulk 16 && git rev-list HEAD~16.. >in && - - perl -lne "print \"create refs/remotes/$r/tags/\$. \$_\"" <in | + sed "s|\(.*\)|create refs/remotes/$r/tags/\1 \1" in | git update-ref --stdin || return 1 done && @@ -252,7 +250,7 @@ test_expect_success 'pseudo-merge pattern with capture groups' ' do test_pseudo_merge_commits $m >oids && grep -f oids refs | - perl -lne "print \$1 if /refs\/remotes\/([0-9]+)/" | + sed -n "s|refs/remotes/\([0-9][0-9]*\)/|\1|p" && sort -u || return 1 done >remotes && @@ -447,4 +445,21 @@ test_expect_success 'pseudo-merge closure' ' ) ' +test_expect_success 'use pseudo-merge in boundary traversal' ' + git init pseudo-merge-boundary-traversal && + ( + cd pseudo-merge-boundary-traversal && + + git config bitmapPseudoMerge.test.pattern refs/ && + git config pack.useBitmapBoundaryTraversal true && + + test_commit A && + git repack -adb && + test_commit B && + + nr=$(git rev-list --count --use-bitmap-index HEAD~1..HEAD) && + test 1 -eq "$nr" + ) +' + test_done diff --git a/t/t5334-incremental-multi-pack-index.sh b/t/t5334-incremental-multi-pack-index.sh index 26257e5660..d30d7253d6 100755 --- a/t/t5334-incremental-multi-pack-index.sh +++ b/t/t5334-incremental-multi-pack-index.sh @@ -44,4 +44,91 @@ test_expect_success 'convert incremental to non-incremental' ' compare_results_with_midx 'non-incremental MIDX conversion' +write_midx_layer () { + n=1 + if test -f $midx_chain + then + n="$(($(wc -l <$midx_chain) + 1))" + fi + + for i in 1 2 + do + test_commit $n.$i && + git repack -d || return 1 + done && + git multi-pack-index write --bitmap --incremental +} + +test_expect_success 'write initial MIDX layer' ' + git repack -ad && + write_midx_layer +' + +test_expect_success 'read bitmap from first MIDX layer' ' + git rev-list --test-bitmap 1.2 +' + +test_expect_success 'write another MIDX layer' ' + write_midx_layer +' + +test_expect_success 'midx verify with multiple layers' ' + test_path_is_file "$midx_chain" && + test_line_count = 2 "$midx_chain" && + + git multi-pack-index verify +' + +test_expect_success 'read bitmap from second MIDX layer' ' + git rev-list --test-bitmap 2.2 +' + +test_expect_success 'read earlier bitmap from second MIDX layer' ' + git rev-list --test-bitmap 1.2 +' + +test_expect_success 'show object from first pack' ' + git cat-file -p 1.1 +' + +test_expect_success 'show object from second pack' ' + git cat-file -p 2.2 +' + +for reuse in false single multi +do + test_expect_success "full clone (pack.allowPackReuse=$reuse)" ' + rm -fr clone.git && + + git config pack.allowPackReuse $reuse && + git clone --no-local --bare . clone.git + ' +done + +test_expect_success 'relink existing MIDX layer' ' + rm -fr "$midxdir" && + + GIT_TEST_MIDX_WRITE_REV=1 git multi-pack-index write --bitmap && + + midx_hash="$(test-tool read-midx --checksum $objdir)" && + + test_path_is_file "$packdir/multi-pack-index" && + test_path_is_file "$packdir/multi-pack-index-$midx_hash.bitmap" && + test_path_is_file "$packdir/multi-pack-index-$midx_hash.rev" && + + test_commit another && + git repack -d && + git multi-pack-index write --bitmap --incremental && + + test_path_is_missing "$packdir/multi-pack-index" && + test_path_is_missing "$packdir/multi-pack-index-$midx_hash.bitmap" && + test_path_is_missing "$packdir/multi-pack-index-$midx_hash.rev" && + + test_path_is_file "$midxdir/multi-pack-index-$midx_hash.midx" && + test_path_is_file "$midxdir/multi-pack-index-$midx_hash.bitmap" && + test_path_is_file "$midxdir/multi-pack-index-$midx_hash.rev" && + test_line_count = 2 "$midx_chain" + +' + test_done diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 3f81f16e13..83b42ff073 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -55,6 +55,13 @@ test_expect_success setup ' echo Rebase && git log' +test_expect_success 'send-pack does not crash with -h' ' + test_expect_code 129 git send-pack -h >usage && + test_grep "[Uu]sage: git send-pack " usage && + test_expect_code 129 nongit git send-pack -h >usage && + test_grep "[Uu]sage: git send-pack " usage +' + test_expect_success 'pack the source repository' ' git repack -a -d && git prune @@ -268,7 +275,7 @@ extract_ref_advertisement () { ' } -test_expect_success 'receive-pack de-dupes .have lines' ' +test_expect_success PERL_TEST_HELPERS 'receive-pack de-dupes .have lines' ' git init shared && git -C shared commit --allow-empty -m both && git clone -s shared fork && diff --git a/t/t5410-receive-pack-alternates.sh b/t/t5410-receive-pack-alternates.sh deleted file mode 100755 index 0b28e4e452..0000000000 --- a/t/t5410-receive-pack-alternates.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -test_description='git receive-pack with alternate ref filtering' - -GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main -export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME - -. ./test-lib.sh - -test_expect_success 'setup' ' - test_commit base && - git clone -s --bare . fork && - git checkout -b public/branch main && - test_commit public && - git checkout -b private/branch main && - test_commit private -' - -extract_haves () { - depacketize | perl -lne '/^(\S+) \.have/ and print $1' -} - -test_expect_success 'with core.alternateRefsCommand' ' - write_script fork/alternate-refs <<-\EOF && - git --git-dir="$1" for-each-ref \ - --format="%(objectname)" \ - refs/heads/public/ - EOF - test_config -C fork core.alternateRefsCommand ./alternate-refs && - git rev-parse public/branch >expect && - printf "0000" | git receive-pack fork >actual && - extract_haves <actual >actual.haves && - test_cmp expect actual.haves -' - -test_expect_success 'with core.alternateRefsPrefixes' ' - test_config -C fork core.alternateRefsPrefixes "refs/heads/private" && - git rev-parse private/branch >expect && - printf "0000" | git receive-pack fork >actual && - extract_haves <actual >actual.haves && - test_cmp expect actual.haves -' - -test_done diff --git a/t/t5410-receive-pack.sh b/t/t5410-receive-pack.sh new file mode 100755 index 0000000000..09d6bfd2a1 --- /dev/null +++ b/t/t5410-receive-pack.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +test_description='git receive-pack' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit base && + git clone -s --bare . fork && + git checkout -b public/branch main && + test_commit public && + git checkout -b private/branch main && + test_commit private +' + +extract_haves () { + depacketize | sed -n 's/^\([^ ][^ ]*\) \.have/\1/p' +} + +test_expect_success 'with core.alternateRefsCommand' ' + write_script fork/alternate-refs <<-\EOF && + git --git-dir="$1" for-each-ref \ + --format="%(objectname)" \ + refs/heads/public/ + EOF + test_config -C fork core.alternateRefsCommand ./alternate-refs && + git rev-parse public/branch >expect && + printf "0000" | git receive-pack fork >actual && + extract_haves <actual >actual.haves && + test_cmp expect actual.haves +' + +test_expect_success 'with core.alternateRefsPrefixes' ' + test_config -C fork core.alternateRefsPrefixes "refs/heads/private" && + git rev-parse private/branch >expect && + printf "0000" | git receive-pack fork >actual && + extract_haves <actual >actual.haves && + test_cmp expect actual.haves +' + +# The `tee.exe` shipped in Git for Windows v2.49.0 is known to hang frequently +# when spawned from `git.exe` and piping its output to `git.exe`. This seems +# related to MSYS2 runtime bug fixes regarding the signal handling; Let's just +# skip the tests that need to exercise this when the faulty MSYS2 runtime is +# detected; The test cases are exercised enough in other matrix jobs of the CI +# runs. +test_lazy_prereq TEE_DOES_NOT_HANG ' + test_have_prereq !MINGW && + case "$(uname -a)" in *3.5.7-463ebcdc.x86_64*) false;; esac +' + +test_expect_success TEE_DOES_NOT_HANG \ + 'receive-pack missing objects fails connectivity check' ' + test_when_finished rm -rf repo remote.git setup.git && + + git init repo && + git -C repo commit --allow-empty -m 1 && + git clone --bare repo setup.git && + git -C repo commit --allow-empty -m 2 && + + # Capture git-send-pack(1) output sent to git-receive-pack(1). + git -C repo send-pack ../setup.git --all \ + --receive-pack="tee ${SQ}$(pwd)/out${SQ} | git-receive-pack" && + + # Replay captured git-send-pack(1) output on new empty repository. + git init --bare remote.git && + git receive-pack remote.git <out >actual 2>err && + + test_grep "missing necessary objects" actual && + test_grep "fatal: Failed to traverse parents" err && + test_must_fail git -C remote.git cat-file -e $(git -C repo rev-parse HEAD) +' + +test_expect_success TEE_DOES_NOT_HANG \ + 'receive-pack missing objects bypasses connectivity check' ' + test_when_finished rm -rf repo remote.git setup.git && + + git init repo && + git -C repo commit --allow-empty -m 1 && + git clone --bare repo setup.git && + git -C repo commit --allow-empty -m 2 && + + # Capture git-send-pack(1) output sent to git-receive-pack(1). + git -C repo send-pack ../setup.git --all \ + --receive-pack="tee ${SQ}$(pwd)/out${SQ} | git-receive-pack" && + + # Replay captured git-send-pack(1) output on new empty repository. + git init --bare remote.git && + git receive-pack --skip-connectivity-check remote.git <out >actual 2>err && + + test_grep ! "missing necessary objects" actual && + test_must_be_empty err && + git -C remote.git cat-file -e $(git -C repo rev-parse HEAD) && + test_must_fail git -C remote.git rev-list $(git -C repo rev-parse HEAD) +' + +test_done diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh index 845ca43ea0..febe441041 100755 --- a/t/t5503-tagfollow.sh +++ b/t/t5503-tagfollow.sh @@ -7,6 +7,12 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping tagfollow tests; Perl not available' + test_done +fi + # End state of the repository: # # T - tag1 S - tag2 diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 58074506c5..438250c75e 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -359,7 +359,7 @@ test_expect_success \ grep "Cannot demote unterminatedheader" act ' -test_expect_success 'badFilemode is not a strict error' ' +test_expect_success PERL_TEST_HELPERS 'badFilemode is not a strict error' ' git init --bare badmode.git && tree=$( cd badmode.git && diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index bb7e0c6879..bef0250e89 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -499,7 +499,7 @@ test_expect_success 'set-head --auto has no problem w/multiple HEADs' ' cd test && git fetch two "refs/heads/*:refs/remotes/two/*" && git remote set-head --auto two >output 2>&1 && - echo "${SQ}two/HEAD${SQ} is unchanged and points to ${SQ}main${SQ}" >expect && + echo "${SQ}two/HEAD${SQ} is now created and points to ${SQ}main${SQ}" >expect && test_cmp expect output ) ' @@ -1123,7 +1123,7 @@ Pull: refs/heads/main:refs/heads/origin Pull: refs/heads/next:refs/heads/origin2 EOF -test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/remotes' ' +test_expect_success !WITH_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/remotes' ' git clone one five && origin_url=$(pwd)/one && ( @@ -1149,7 +1149,7 @@ test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file i ) ' -test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches' ' +test_expect_success !WITH_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches' ' git clone --template= one six && origin_url=$(pwd)/one && ( @@ -1165,7 +1165,7 @@ test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file i ) ' -test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches (2)' ' +test_expect_success !WITH_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches (2)' ' git clone --template= one seven && ( cd seven && diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 5f350facf5..ebc696546b 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -8,6 +8,12 @@ test_description='Per branch config variables affects "git fetch". . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bundle.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping fetch tests; Perl not available' + test_done +fi + D=$(pwd) test_expect_success setup ' @@ -119,7 +125,10 @@ test_expect_success "fetch test followRemoteHEAD never" ' cd two && git update-ref --no-deref -d refs/remotes/origin/HEAD && git config set remote.origin.followRemoteHEAD "never" && - git fetch && + GIT_TRACE_PACKET=$PWD/trace.out git fetch && + # Confirm that we do not even ask for HEAD when we are + # not going to act on it. + test_grep ! "ref-prefix HEAD" trace.out && test_must_fail git rev-parse --verify refs/remotes/origin/HEAD ) ' @@ -250,6 +259,20 @@ test_expect_success "fetch test followRemoteHEAD always" ' ) ' +test_expect_success 'followRemoteHEAD does not kick in with refspecs' ' + test_when_finished "git config unset remote.origin.followRemoteHEAD" && + ( + cd "$D" && + cd two && + git remote set-head origin other && + git config set remote.origin.followRemoteHEAD always && + git fetch origin refs/heads/main:refs/remotes/origin/main && + echo refs/remotes/origin/other >expect && + git symbolic-ref refs/remotes/origin/HEAD >actual && + test_cmp expect actual + ) +' + test_expect_success 'fetch --prune on its own works as expected' ' cd "$D" && git clone . prune && @@ -537,6 +560,19 @@ test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' ' test_cmp expected atomic/.git/FETCH_HEAD ' +test_expect_success REFFILES 'fetch --atomic fails transaction if reference locked' ' + test_when_finished "rm -rf upstream repo" && + + git init upstream && + git -C upstream commit --allow-empty -m 1 && + git -C upstream switch -c foobar && + git clone --mirror upstream repo && + git -C upstream commit --allow-empty -m 2 && + touch repo/refs/heads/foobar.lock && + + test_must_fail git -C repo fetch --atomic origin +' + test_expect_success '--refmap="" ignores configured refspec' ' cd "$TRASH_DIRECTORY" && git clone "$D" remote-refs && diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 4e6026c611..8ac04d742c 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -104,7 +104,7 @@ test_expect_success setup ' git config remote.config-glob.fetch refs/heads/*:refs/remotes/rem/* && remotes="$remotes config-glob" && - if test_have_prereq WITHOUT_BREAKING_CHANGES + if ! test_have_prereq WITH_BREAKING_CHANGES then mkdir -p .git/remotes && cat >.git/remotes/remote-explicit <<-\EOF && diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 85ed049627..782f5f93ea 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -495,7 +495,7 @@ test_expect_success 'push tag with non-existent, incomplete dest' ' ' -test_expect_success 'push sha1 with non-existent, incomplete dest' ' +test_expect_success 'push oid with non-existent, incomplete dest' ' mk_test testrepo && test_must_fail git push testrepo $(git rev-parse main):foo @@ -975,7 +975,7 @@ test_expect_success 'allow push to HEAD of non-bare repository (config)' ' ! grep "warning: updating the current branch" stderr ' -test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches' ' +test_expect_success !WITH_BREAKING_CHANGES 'fetch with branches' ' mk_empty testrepo && git branch second $the_first_commit && git checkout second && @@ -991,7 +991,7 @@ test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches' ' git checkout main ' -test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches containing #' ' +test_expect_success !WITH_BREAKING_CHANGES 'fetch with branches containing #' ' mk_empty testrepo && mkdir testrepo/.git/branches && echo "..#second" > testrepo/.git/branches/branch2 && @@ -1005,7 +1005,7 @@ test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches containing #' git checkout main ' -test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches' ' +test_expect_success !WITH_BREAKING_CHANGES 'push with branches' ' mk_empty testrepo && git checkout second && @@ -1022,7 +1022,7 @@ test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches' ' ) ' -test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches containing #' ' +test_expect_success !WITH_BREAKING_CHANGES 'push with branches containing #' ' mk_empty testrepo && test_when_finished "rm -rf .git/branches" && @@ -1251,7 +1251,7 @@ do ' done -test_expect_success 'fetch exact SHA1' ' +test_expect_success 'fetch exact oid' ' mk_test testrepo heads/main hidden/one && git push testrepo main:refs/hidden/one && ( @@ -1297,7 +1297,7 @@ test_expect_success 'fetch exact SHA1' ' ) ' -test_expect_success 'fetch exact SHA1 in protocol v2' ' +test_expect_success 'fetch exact oid in protocol v2' ' mk_test testrepo heads/main hidden/one && git push testrepo main:refs/hidden/one && git -C testrepo config transfer.hiderefs refs/hidden && @@ -1312,8 +1312,10 @@ test_expect_success 'fetch exact SHA1 in protocol v2' ' test_must_fail git -C child cat-file -t $the_commit && # fetching the hidden object succeeds by default - # NEEDSWORK: should this match the v0 behavior instead? - git -C child fetch -v ../testrepo $the_commit:refs/heads/copy + GIT_TRACE_PACKET=$PWD/trace.out \ + git -C child fetch -v ../testrepo $the_commit:refs/heads/copy && + + test_grep ! "ref-prefix.*$the_commit" trace.out ' for configallowtipsha1inwant in true false @@ -1907,4 +1909,14 @@ test_expect_success 'push with config push.useBitmaps' ' --thin --delta-base-offset -q --no-use-bitmap-index <false ' +test_expect_success 'push with config pack.usePathWalk=true' ' + mk_test testrepo heads/main && + git checkout main && + test_config pack.usePathWalk true && + GIT_TRACE2_EVENT="$(pwd)/path-walk.txt" \ + git push --quiet testrepo main:test && + + test_region pack-objects path-walk path-walk.txt +' + test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 47534f1062..63c9a8f04b 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -813,7 +813,7 @@ test_expect_success 'git pull --rebase does not reapply old patches' ' cd dst && test_must_fail git pull --rebase && cat .git/rebase-merge/done .git/rebase-merge/git-rebase-todo >work && - grep -v -e \# -e ^$ work >patches && + grep -v -e ^\# -e ^$ work >patches && test_line_count = 1 patches && rm -f work ) diff --git a/t/t5532-fetch-proxy.sh b/t/t5532-fetch-proxy.sh index 3755822629..95d0f33b29 100755 --- a/t/t5532-fetch-proxy.sh +++ b/t/t5532-fetch-proxy.sh @@ -4,6 +4,12 @@ test_description='fetching via git:// using core.gitproxy' . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping fetch proxy tests; Perl not available' + test_done +fi + test_expect_success 'setup remote repo' ' git init remote && (cd remote && diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh index c91a62b77a..2a782214ee 100755 --- a/t/t5534-push-signed.sh +++ b/t/t5534-push-signed.sh @@ -205,7 +205,7 @@ test_expect_success GPG 'inconsistent push options in signed push not allowed' ' # Tweak the push output to make the push option outside the cert # different, then replay it on a fresh dst, checking that ff is not # deleted. - perl -pe "s/([^ ])bar/\$1baz/" push >push.tweak && + sed "s/\([^ ]\)bar/\1baz/" push >push.tweak && prepare_dst && git -C dst config receive.certnonceseed sekrit && git -C dst config receive.advertisepushoptions 1 && diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index 37f7547a4c..6588ce6226 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -271,22 +271,21 @@ test_expect_success 'shallow fetches check connectivity before writing shallow f git -C "$REPO" config protocol.version 2 && git -C client config protocol.version 2 && - git -C client fetch --depth=2 "$HTTPD_URL/one_time_perl/repo" main:a_branch && + git -C client fetch --depth=2 "$HTTPD_URL/one_time_script/repo" main:a_branch && # Craft a situation in which the server sends back an unshallow request # with an empty packfile. This is done by refetching with a shorter # depth (to ensure that the packfile is empty), and overwriting the # shallow line in the response with the unshallow line we want. - printf "$(test_oid perl)" \ - "$(git -C "$REPO" rev-parse HEAD)" \ - "$(git -C "$REPO" rev-parse HEAD^)" \ - >"$HTTPD_ROOT_PATH/one-time-perl" && + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF && + sed "$(printf "$(test_oid perl)" "$(git -C "$REPO" rev-parse HEAD)" "$(git -C "$REPO" rev-parse HEAD^)")" "\$1" + EOF test_must_fail env GIT_TEST_SIDEBAND_ALL=0 git -C client \ - fetch --depth=1 "$HTTPD_URL/one_time_perl/repo" \ + fetch --depth=1 "$HTTPD_URL/one_time_script/repo" \ main:a_branch && - # Ensure that the one-time-perl script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-perl" && + # Ensure that the one-time-script script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-script" && # Ensure that the resulting repo is consistent, despite our failure to # fetch. diff --git a/t/t5538-push-shallow.sh b/t/t5538-push-shallow.sh index e91fcc173e..dc0e972943 100755 --- a/t/t5538-push-shallow.sh +++ b/t/t5538-push-shallow.sh @@ -123,4 +123,45 @@ EOF git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null ) ' + +test_expect_success 'push new commit from shallow clone has correct object count' ' + git init origin && + test_commit -C origin a && + test_commit -C origin b && + + git clone --depth=1 "file://$(pwd)/origin" client && + git -C client checkout -b topic && + git -C client commit --allow-empty -m "empty" && + GIT_PROGRESS_DELAY=0 git -C client push --progress origin topic 2>err && + test_grep "Enumerating objects: 1, done." err +' + +test_expect_success 'push new commit from shallow clone has good deltas' ' + git init base && + test_seq 1 999 >base/a && + test_commit -C base initial && + git -C base add a && + git -C base commit -m "big a" && + + git clone --depth=1 "file://$(pwd)/base" deltas && + git -C deltas checkout -b deltas && + test_seq 1 1000 >deltas/a && + git -C deltas commit -a -m "bigger a" && + GIT_PROGRESS_DELAY=0 git -C deltas push --progress origin deltas 2>err && + + test_grep "Enumerating objects: 5, done" err && + + # If the delta base is found, then this message uses "bytes". + # If the delta base is not found, then this message uses "KiB". + test_grep "Writing objects: .* bytes" err && + + git -C deltas commit --amend -m "changed message" && + GIT_TRACE2_EVENT="$(pwd)/config-push.txt" \ + GIT_PROGRESS_DELAY=0 git -C deltas -c pack.usePathWalk=true \ + push --progress -f origin deltas 2>err && + + test_grep "Enumerating objects: 1, done" err && + test_region pack-objects path-walk config-push.txt +' + test_done diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 761fdfcfe6..b0d4ea7801 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -7,6 +7,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-httpd.sh + +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping http fetch smart tests; Perl not available' + test_done +fi + test "$HTTP_PROTO" = "HTTP/2" && enable_http2 start_httpd diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh index 3816ed5058..9b211a626b 100755 --- a/t/t5558-clone-bundle-uri.sh +++ b/t/t5558-clone-bundle-uri.sh @@ -58,7 +58,7 @@ test_expect_success 'create bundle' ' test_expect_success 'clone with path bundle' ' git clone --bundle-uri="clone-from/B.bundle" \ clone-from clone-path && - git -C clone-path rev-parse refs/bundles/topic >actual && + git -C clone-path rev-parse refs/bundles/heads/topic >actual && git -C clone-from rev-parse topic >expect && test_cmp expect actual ' @@ -68,9 +68,9 @@ test_expect_success 'clone with bundle that has bad header' ' git clone --bundle-uri="clone-from/bad-header.bundle" \ clone-from clone-bad-header 2>err && commit_b=$(git -C clone-from rev-parse B) && - test_grep "trying to write ref '\''refs/bundles/topic'\'' with nonexistent object $commit_b" err && + test_grep "trying to write ref '\''refs/bundles/heads/topic'\'' with nonexistent object $commit_b" err && git -C clone-bad-header for-each-ref --format="%(refname)" >refs && - test_grep ! "refs/bundles/" refs + test_grep ! "refs/bundles/heads/" refs ' test_expect_success 'clone with bundle that has bad object' ' @@ -78,8 +78,8 @@ test_expect_success 'clone with bundle that has bad object' ' git clone --bundle-uri="clone-from/bad-object.bundle" \ clone-from clone-bad-object-no-fsck && git -C clone-bad-object-no-fsck for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && - test_write_lines refs/bundles/bad >expect && + grep "refs/bundles/heads/" refs >actual && + test_write_lines refs/bundles/heads/bad >expect && test_cmp expect actual && # Unbundle fails with fsckObjects set true, but clone can still proceed. @@ -87,14 +87,14 @@ test_expect_success 'clone with bundle that has bad object' ' clone-from clone-bad-object-fsck 2>err && test_grep "missingEmail" err && git -C clone-bad-object-fsck for-each-ref --format="%(refname)" >refs && - test_grep ! "refs/bundles/" refs + test_grep ! "refs/bundles/heads/" refs ' test_expect_success 'clone with path bundle and non-default hash' ' test_when_finished "rm -rf clone-path-non-default-hash" && GIT_DEFAULT_HASH=sha256 git clone --bundle-uri="clone-from/B.bundle" \ clone-from clone-path-non-default-hash && - git -C clone-path-non-default-hash rev-parse refs/bundles/topic >actual && + git -C clone-path-non-default-hash rev-parse refs/bundles/heads/topic >actual && git -C clone-from rev-parse topic >expect && test_cmp expect actual ' @@ -102,11 +102,41 @@ test_expect_success 'clone with path bundle and non-default hash' ' test_expect_success 'clone with file:// bundle' ' git clone --bundle-uri="file://$(pwd)/clone-from/B.bundle" \ clone-from clone-file && - git -C clone-file rev-parse refs/bundles/topic >actual && + git -C clone-file rev-parse refs/bundles/heads/topic >actual && git -C clone-from rev-parse topic >expect && test_cmp expect actual ' +test_expect_success 'create bundle with tags' ' + git init clone-from-tags && + ( + cd clone-from-tags && + git checkout -b base && + git checkout -b topic && + + test_commit A && + git tag tag-A && + git checkout -b base && + git branch -d topic && + test_commit B && + + git bundle create ALL.bundle --all && + git bundle verify ALL.bundle + ) +' + +test_expect_success 'clone with tags bundle' ' + git clone --bundle-uri="clone-from-tags/ALL.bundle" \ + clone-from-tags clone-tags-path && + + git -C clone-from-tags for-each-ref --format="%(refname:lstrip=1)" \ + >expect && + git -C clone-tags-path for-each-ref --format="%(refname:lstrip=2)" \ + refs/bundles >actual && + + test_cmp expect actual +' + # To get interesting tests for bundle lists, we need to construct a # somewhat-interesting commit history. # @@ -173,12 +203,12 @@ test_expect_success 'clone bundle list (file, no heuristic)' ' git -C clone-list-file cat-file --batch-check <oids && git -C clone-list-file for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && + grep "refs/bundles/heads/" refs >actual && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/merge - refs/bundles/right + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/merge + refs/bundles/heads/right EOF test_cmp expect actual ' @@ -220,10 +250,10 @@ test_expect_success 'clone bundle list (file, all mode, some failures)' ' git -C clone-all-some cat-file --batch-check <oids && git -C clone-all-some for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && + grep "refs/bundles/heads/" refs >actual && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left + refs/bundles/heads/base + refs/bundles/heads/left EOF test_cmp expect actual ' @@ -253,7 +283,7 @@ test_expect_success 'clone bundle list (file, all mode, all failures)' ' git -C clone-all-fail cat-file --batch-check <oids && git -C clone-all-fail for-each-ref --format="%(refname)" >refs && - ! grep "refs/bundles/" refs + ! grep "refs/bundles/heads/" refs ' test_expect_success 'clone bundle list (file, any mode)' ' @@ -282,9 +312,9 @@ test_expect_success 'clone bundle list (file, any mode)' ' git -C clone-any-file cat-file --batch-check <oids && git -C clone-any-file for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && + grep "refs/bundles/heads/" refs >actual && cat >expect <<-\EOF && - refs/bundles/base + refs/bundles/heads/base EOF test_cmp expect actual ' @@ -313,7 +343,7 @@ test_expect_success 'clone bundle list (file, any mode, all failures)' ' git -C clone-any-fail cat-file --batch-check <oids && git -C clone-any-fail for-each-ref --format="%(refname)" >refs && - ! grep "refs/bundles/" refs + ! grep "refs/bundles/heads/" refs ' test_expect_success 'negotiation: bundle with part of wanted commits' ' @@ -322,10 +352,10 @@ test_expect_success 'negotiation: bundle with part of wanted commits' ' git clone --no-local --bundle-uri="clone-from/A.bundle" \ clone-from nego-bundle-part && git -C nego-bundle-part for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && - test_write_lines refs/bundles/topic >expect && + grep "refs/bundles/heads/" refs >actual && + test_write_lines refs/bundles/heads/topic >expect && test_cmp expect actual && - # Ensure that refs/bundles/topic are sent as "have". + # Ensure that refs/bundles/heads/topic are sent as "have". tip=$(git -C clone-from rev-parse A) && test_grep "clone> have $tip" trace-packet.txt ' @@ -337,8 +367,8 @@ test_expect_success 'negotiation: bundle with all wanted commits' ' --bundle-uri="clone-from/B.bundle" \ clone-from nego-bundle-all && git -C nego-bundle-all for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && - test_write_lines refs/bundles/topic >expect && + grep "refs/bundles/heads/" refs >actual && + test_write_lines refs/bundles/heads/topic >expect && test_cmp expect actual && # We already have all needed commits so no "want" needed. test_grep ! "clone> want " trace-packet.txt @@ -363,13 +393,13 @@ test_expect_success 'negotiation: bundle list (no heuristic)' ' clone-from nego-bundle-list-no-heuristic && git -C nego-bundle-list-no-heuristic for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && + grep "refs/bundles/heads/" refs >actual && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left + refs/bundles/heads/base + refs/bundles/heads/left EOF test_cmp expect actual && - tip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/left) && + tip=$(git -C nego-bundle-list-no-heuristic rev-parse refs/bundles/heads/left) && test_grep "clone> have $tip" trace-packet.txt ' @@ -395,13 +425,13 @@ test_expect_success 'negotiation: bundle list (creationToken)' ' clone-from nego-bundle-list-heuristic && git -C nego-bundle-list-heuristic for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && + grep "refs/bundles/heads/" refs >actual && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left + refs/bundles/heads/base + refs/bundles/heads/left EOF test_cmp expect actual && - tip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/left) && + tip=$(git -C nego-bundle-list-heuristic rev-parse refs/bundles/heads/left) && test_grep "clone> have $tip" trace-packet.txt ' @@ -428,10 +458,10 @@ test_expect_success 'negotiation: bundle list with all wanted commits' ' clone-from nego-bundle-list-all && git -C nego-bundle-list-all for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && + grep "refs/bundles/heads/" refs >actual && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left + refs/bundles/heads/base + refs/bundles/heads/left EOF test_cmp expect actual && # We already have all needed commits so no "want" needed. @@ -465,7 +495,7 @@ test_expect_success 'clone HTTP bundle' ' git clone --bundle-uri="$HTTPD_URL/B.bundle" \ "$HTTPD_URL/smart/fetch.git" clone-http && - git -C clone-http rev-parse refs/bundles/topic >actual && + git -C clone-http rev-parse refs/bundles/heads/topic >actual && git -C clone-from rev-parse topic >expect && test_cmp expect actual && @@ -476,7 +506,7 @@ test_expect_success 'clone HTTP bundle with non-default hash' ' test_when_finished "rm -rf clone-http-non-default-hash" && GIT_DEFAULT_HASH=sha256 git clone --bundle-uri="$HTTPD_URL/B.bundle" \ "$HTTPD_URL/smart/fetch.git" clone-http-non-default-hash && - git -C clone-http-non-default-hash rev-parse refs/bundles/topic >actual && + git -C clone-http-non-default-hash rev-parse refs/bundles/heads/topic >actual && git -C clone-from rev-parse topic >expect && test_cmp expect actual ' @@ -553,12 +583,12 @@ test_expect_success 'clone bundle list (HTTP, any mode)' ' git -C clone-any-http cat-file --batch-check <oids && git -C clone-list-file for-each-ref --format="%(refname)" >refs && - grep "refs/bundles/" refs >actual && + grep "refs/bundles/heads/" refs >actual && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/merge - refs/bundles/right + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/merge + refs/bundles/heads/right EOF test_cmp expect actual ' @@ -641,9 +671,9 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' ' test_cmp expect actual && # We now have only one bundle ref. - git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-\EOF && - refs/bundles/base + refs/bundles/heads/base EOF test_cmp expect refs && @@ -679,13 +709,13 @@ test_expect_success 'clone incomplete bundle list (http, creationToken)' ' test_cmp expect actual && # We now have all bundle refs. - git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/merge - refs/bundles/right + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/merge + refs/bundles/heads/right EOF test_cmp expect refs ' @@ -721,9 +751,9 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' ' test_cmp expect actual && # only received base ref from bundle-1 - git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-\EOF && - refs/bundles/base + refs/bundles/heads/base EOF test_cmp expect refs && @@ -749,10 +779,10 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' ' test_cmp expect actual && # received left from bundle-2 - git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left + refs/bundles/heads/base + refs/bundles/heads/left EOF test_cmp expect refs && @@ -795,12 +825,12 @@ test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' ' # received merge ref from bundle-4, but right is missing # because we did not download bundle-3. - git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-\EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/merge + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/merge EOF test_cmp expect refs && @@ -862,7 +892,7 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' ' test_cmp expect actual && # All bundles failed to unbundle - git -C download-1 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C download-1 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && test_must_be_empty refs && # Case 2: middle bundle does not exist, only two bundles can unbundle @@ -909,10 +939,10 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' ' test_cmp expect actual && # bundle-1 and bundle-3 could unbundle, but bundle-4 could not - git -C download-2 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C download-2 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-EOF && - refs/bundles/base - refs/bundles/right + refs/bundles/heads/base + refs/bundles/heads/right EOF test_cmp expect refs && @@ -961,11 +991,11 @@ test_expect_success 'creationToken heuristic with failed downloads (clone)' ' test_cmp expect actual && # fake.bundle did not unbundle, but the others did. - git -C download-3 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C download-3 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/right + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/right EOF test_cmp expect refs ' @@ -1083,15 +1113,15 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' ' test_cmp expect actual && # Check which bundles have unbundled by refs - git -C fetch-1 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C fetch-1 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/lefter - refs/bundles/merge - refs/bundles/right - refs/bundles/righter - refs/bundles/top + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/lefter + refs/bundles/heads/merge + refs/bundles/heads/right + refs/bundles/heads/righter + refs/bundles/heads/top EOF test_cmp expect refs && @@ -1144,12 +1174,12 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' ' test_cmp expect actual && # Check which bundles have unbundled by refs - git -C fetch-2 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C fetch-2 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/merge - refs/bundles/right + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/merge + refs/bundles/heads/right EOF test_cmp expect refs && @@ -1204,13 +1234,13 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' ' test_cmp expect actual && # Check which bundles have unbundled by refs - git -C fetch-3 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && + git -C fetch-3 for-each-ref --format="%(refname)" "refs/bundles/heads/*" >refs && cat >expect <<-EOF && - refs/bundles/base - refs/bundles/left - refs/bundles/lefter - refs/bundles/right - refs/bundles/righter + refs/bundles/heads/base + refs/bundles/heads/left + refs/bundles/heads/lefter + refs/bundles/heads/right + refs/bundles/heads/righter EOF test_cmp expect refs ' diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh index f3b158274c..b6ee06f5c8 100755 --- a/t/t5562-http-backend-content-length.sh +++ b/t/t5562-http-backend-content-length.sh @@ -4,6 +4,12 @@ test_description='test git-http-backend respects CONTENT_LENGTH' . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping http backend content tests; Perl not available' + test_done +fi + test_lazy_prereq GZIP 'gzip --version' verify_http_result() { diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh index f7650e8475..45f384dd32 100755 --- a/t/t5572-pull-submodule.sh +++ b/t/t5572-pull-submodule.sh @@ -45,11 +45,6 @@ git_pull_noff () { $2 git pull --no-ff } -if test "$GIT_TEST_MERGE_ALGORITHM" != ort -then - KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 - KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 -fi test_submodule_switch_func "git_pull_noff" test_expect_success 'setup' ' diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index d0c18660e3..d743d986c4 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -649,7 +649,7 @@ test_expect_success 'GIT_TRACE_PACKFILE produces a usable pack' ' git -C replay.git index-pack -v --stdin <tmp.pack ' -test_expect_success 'clone on case-insensitive fs' ' +test_expect_success PERL_TEST_HELPERS 'clone on case-insensitive fs' ' git init icasefs && ( cd icasefs && @@ -662,7 +662,7 @@ test_expect_success 'clone on case-insensitive fs' ' ) ' -test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' ' +test_expect_success PERL_TEST_HELPERS,CASE_INSENSITIVE_FS 'colliding file detection' ' grep X icasefs/warning && grep x icasefs/warning && test_grep "the following paths have collided" icasefs/warning diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh index 4605703496..2397f8fa61 100755 --- a/t/t5605-clone-local.sh +++ b/t/t5605-clone-local.sh @@ -156,11 +156,10 @@ test_expect_success 'cloning a local path with --no-local does not hardlink' ' test_expect_success 'cloning a local path with --no-local from a different user succeeds' ' git clone --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \ --no-local a nonlocal-otheruser 2>err && - ! repo_is_hardlinked nonlocal-otheruser && + ! repo_is_hardlinked nonlocal-otheruser/.git && # Verify that this is a git repository. git -C nonlocal-otheruser rev-parse --show-toplevel && - ! test_grep "detected dubious ownership" err - + test_grep ! "detected dubious ownership" err ' test_expect_success 'cloning locally respects "-u" for fetching refs' ' diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh index 82e3621ec5..d709bea753 100755 --- a/t/t5607-clone-bundle.sh +++ b/t/t5607-clone-bundle.sh @@ -211,4 +211,16 @@ test_expect_success 'git bundle v3 rejects unknown capabilities' ' test_grep "unknown capability .unknown=silly." output ' +test_expect_success 'cloning bundle suppresses default branch name advice' ' + test_when_finished "rm -rf bundle-repo clone-repo" && + + git init bundle-repo && + git -C bundle-repo commit --allow-empty -m init && + git -C bundle-repo bundle create repo.bundle --all && + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \ + git clone --single-branch bundle-repo/repo.bundle clone-repo 2>err && + + test_grep ! "hint: " err +' + test_done diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index 4650451964..1e354e057f 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -737,18 +737,22 @@ intersperse () { sed 's/\(..\)/'$1'\1/g' } -# Create a one-time-perl command to replace the existing packfile with $1. +# Create a one-time-script command to replace the existing packfile with $1. replace_packfile () { - # The protocol requires that the packfile be sent in sideband 1, hence - # the extra \x01 byte at the beginning. - cp $1 "$HTTPD_ROOT_PATH/one-time-pack" && - echo 'if (/packfile/) { - print; - my $length = -s "one-time-pack"; - printf "%04x\x01", $length + 5; - print `cat one-time-pack` . "0000"; - last - }' >"$HTTPD_ROOT_PATH/one-time-perl" + cp "$1" one-time-pack && + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF + if grep packfile "\$1" >/dev/null + then + sed '/packfile/q' "\$1" && + # The protocol requires that the packfile be sent in sideband + # 1, hence the extra \001 byte at the beginning. + printf "%04x\001" \$((\$(wc -c <"$PWD/one-time-pack") + 5)) && + cat "$PWD/one-time-pack" && + printf "0000" + else + cat "\$1" + fi + EOF } test_expect_success 'upon cloning, check that all refs point to objects' ' @@ -776,12 +780,12 @@ test_expect_success 'upon cloning, check that all refs point to objects' ' # section header. test_config -C "$SERVER" protocol.version 2 && test_must_fail git -c protocol.version=2 clone \ - --filter=blob:none $HTTPD_URL/one_time_perl/server repo 2>err && + --filter=blob:none $HTTPD_URL/one_time_script/server repo 2>err && test_grep "did not send all necessary objects" err && - # Ensure that the one-time-perl script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-perl" + # Ensure that the one-time-script script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-script" ' test_expect_success 'when partial cloning, tolerate server not sending target of tag' ' @@ -818,14 +822,14 @@ test_expect_success 'when partial cloning, tolerate server not sending target of # Exercise to make sure it works. git -c protocol.version=2 clone \ - --filter=blob:none $HTTPD_URL/one_time_perl/server repo 2> err && + --filter=blob:none $HTTPD_URL/one_time_script/server repo 2> err && ! grep "missing object referenced by" err && - # Ensure that the one-time-perl script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-perl" + # Ensure that the one-time-script script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-script" ' -test_expect_success 'tolerate server sending REF_DELTA against missing promisor objects' ' +test_expect_success PERL_TEST_HELPERS 'tolerate server sending REF_DELTA against missing promisor objects' ' SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" && rm -rf "$SERVER" repo && test_create_repo "$SERVER" && @@ -845,7 +849,7 @@ test_expect_success 'tolerate server sending REF_DELTA against missing promisor # Clone. The client has deltabase_have but not deltabase_missing. git -c protocol.version=2 clone --no-checkout \ - --filter=blob:none $HTTPD_URL/one_time_perl/server repo && + --filter=blob:none $HTTPD_URL/one_time_script/server repo && git -C repo hash-object -w -- "$SERVER/have.txt" && # Sanity check to ensure that the client does not have @@ -899,8 +903,8 @@ test_expect_success 'tolerate server sending REF_DELTA against missing promisor grep "want $(cat deltabase_missing)" trace && ! grep "want $(cat deltabase_have)" trace && - # Ensure that the one-time-perl script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-perl" + # Ensure that the one-time-script script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-script" ' # DO NOT add non-httpd-specific tests here, because the last part of this diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index 678a346ed0..d4c28bae39 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -228,7 +228,10 @@ test_expect_success 'ignore very large set of prefixes' ' echo command=ls-refs && echo object-format=$(test_oid algo) && echo 0001 && - perl -le "print \"ref-prefix refs/heads/\$_\" for (1..65536)" && + awk "{ + for (i = 1; i <= 65536; i++) + print \"ref-prefix refs/heads/\", \$i + }" && echo 0000 } | test-tool pkt-line pack >in && diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index d3df81e785..f826ac46a5 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -665,7 +665,7 @@ test_expect_success 'even with handcrafted request, filter does not work if not test-tool -C server serve-v2 --stateless-rpc <in >/dev/null ' -test_expect_success 'default refspec is used to filter ref when fetchcing' ' +test_expect_success 'default refspec is used to filter ref when fetching' ' test_when_finished "rm -f log" && GIT_TRACE_PACKET="$(pwd)/log" git -C file_child -c protocol.version=2 \ @@ -679,6 +679,48 @@ test_expect_success 'default refspec is used to filter ref when fetchcing' ' grep "ref-prefix refs/tags/" log ' +test_expect_success 'set up parent for prefix tests' ' + git init prefix-parent && + git -C prefix-parent commit --allow-empty -m foo && + git -C prefix-parent tag my-tag && + git -C prefix-parent branch unrelated-branch +' + +test_expect_success 'empty refspec filters refs when fetching' ' + git init configless-child && + + test_when_finished "rm -f log" && + GIT_TRACE_PACKET="$(pwd)/log" \ + git -C configless-child fetch ../prefix-parent && + test_grep ! unrelated-branch log +' + +test_expect_success 'exact oid fetch with tag following' ' + git init exact-oid-tags && + + commit=$(git -C prefix-parent rev-parse --verify HEAD) && + + test_when_finished "rm -f log" && + GIT_TRACE_PACKET="$(pwd)/log" \ + git -C exact-oid-tags fetch ../prefix-parent \ + $commit:refs/heads/exact && + test_grep ! unrelated-branch log && + git -C exact-oid-tags rev-parse --verify my-tag +' + +test_expect_success 'exact oid fetch avoids pointless HEAD request' ' + git init exact-oid-head && + git -C exact-oid-head remote add origin ../prefix-parent && + + commit=$(git -C prefix-parent rev-parse --verify HEAD) && + + test_when_finished "rm -f log" && + GIT_TRACE_PACKET="$(pwd)/log" \ + git -C exact-oid-head fetch --no-tags origin \ + $commit:refs/heads/exact && + test_grep ! command=ls-refs log +' + test_expect_success 'fetch supports various ways of have lines' ' rm -rf server client trace && git init server && @@ -1132,11 +1174,12 @@ test_expect_success 'when server sends "ready", expect DELIM' ' # After "ready" in the acknowledgments section, pretend that a FLUSH # (0000) was sent instead of a DELIM (0001). - printf "\$ready = 1 if /ready/; \$ready && s/0001/0000/" \ - >"$HTTPD_ROOT_PATH/one-time-perl" && + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF && + sed "/ready/{n;s/0001/0000/;}" "$1" + EOF test_must_fail git -C http_child -c protocol.version=2 \ - fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err && + fetch "$HTTPD_URL/one_time_script/http_parent" 2> err && test_grep "expected packfile to be sent after .ready." err ' @@ -1157,12 +1200,13 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' # After the acknowledgments section, pretend that a DELIM # (0001) was sent instead of a FLUSH (0000). - printf "\$ack = 1 if /acknowledgments/; \$ack && s/0000/0001/" \ - >"$HTTPD_ROOT_PATH/one-time-perl" && + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF && + sed "/acknowledgments/,//{s/0000/0001/;}" "$1" + EOF test_must_fail env GIT_TRACE_PACKET="$(pwd)/log" git -C http_child \ -c protocol.version=2 \ - fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err && + fetch "$HTTPD_URL/one_time_script/http_parent" 2> err && grep "fetch< .*acknowledgments" log && ! grep "fetch< .*ready" log && test_grep "expected no other sections to be sent after no .ready." err @@ -1448,12 +1492,13 @@ test_expect_success 'http:// --negotiate-only' ' test_expect_success 'http:// --negotiate-only without wait-for-done support' ' SERVER="server" && - URI="$HTTPD_URL/one_time_perl/server" && + URI="$HTTPD_URL/one_time_script/server" && setup_negotiate_only "$SERVER" "$URI" && - echo "s/ wait-for-done/ xxxx-xxx-xxxx/" \ - >"$HTTPD_ROOT_PATH/one-time-perl" && + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF && + sed "s/ wait-for-done/ xxxx-xxx-xxxx/" "$1" + EOF test_must_fail git -c protocol.version=2 -C client fetch \ --no-tags \ diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index 191097171b..249137b467 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -83,18 +83,15 @@ test_expect_success 'setup repository' ' test_expect_success 'config controls ref-in-want advertisement' ' test-tool serve-v2 --advertise-capabilities >out && - perl -ne "/ref-in-want/ and print" out >out.filter && - test_must_be_empty out.filter && + test_grep ! "ref-in-want" out && git config uploadpack.allowRefInWant false && test-tool serve-v2 --advertise-capabilities >out && - perl -ne "/ref-in-want/ and print" out >out.filter && - test_must_be_empty out.filter && + test_grep ! "ref-in-want" out && git config uploadpack.allowRefInWant true && test-tool serve-v2 --advertise-capabilities >out && - perl -ne "/ref-in-want/ and print" out >out.filter && - test_file_not_empty out.filter + test_grep "ref-in-want" out ' test_expect_success 'invalid want-ref line' ' @@ -462,7 +459,7 @@ test_expect_success 'setup repos for change-while-negotiating test' ' test_commit m3 && git tag -d m2 m3 ) && - git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_perl/repo" && + git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_script/repo" && git -C "$LOCAL_PRISTINE" config protocol.version 2 ' @@ -475,10 +472,12 @@ inconsistency () { # RPCs during a single negotiation. oid1=$(git -C "$REPO" rev-parse $1) && oid2=$(git -C "$REPO" rev-parse $2) && - echo "s/$oid1/$oid2/" >"$HTTPD_ROOT_PATH/one-time-perl" + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF + sed "s/$oid1/$oid2/" "\$1" + EOF } -test_expect_success 'server is initially ahead - no ref in want' ' +test_expect_success PERL_TEST_HELPERS 'server is initially ahead - no ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant false && rm -rf local && cp -r "$LOCAL_PRISTINE" local && @@ -487,7 +486,7 @@ test_expect_success 'server is initially ahead - no ref in want' ' test_grep "fatal: remote error: upload-pack: not our ref" err ' -test_expect_success 'server is initially ahead - ref in want' ' +test_expect_success PERL_TEST_HELPERS 'server is initially ahead - ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant true && rm -rf local && cp -r "$LOCAL_PRISTINE" local && @@ -499,7 +498,7 @@ test_expect_success 'server is initially ahead - ref in want' ' test_cmp expected actual ' -test_expect_success 'server is initially behind - no ref in want' ' +test_expect_success PERL_TEST_HELPERS 'server is initially behind - no ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant false && rm -rf local && cp -r "$LOCAL_PRISTINE" local && @@ -511,7 +510,7 @@ test_expect_success 'server is initially behind - no ref in want' ' test_cmp expected actual ' -test_expect_success 'server is initially behind - ref in want' ' +test_expect_success PERL_TEST_HELPERS 'server is initially behind - ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant true && rm -rf local && cp -r "$LOCAL_PRISTINE" local && @@ -523,11 +522,13 @@ test_expect_success 'server is initially behind - ref in want' ' test_cmp expected actual ' -test_expect_success 'server loses a ref - ref in want' ' +test_expect_success PERL_TEST_HELPERS 'server loses a ref - ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant true && rm -rf local && cp -r "$LOCAL_PRISTINE" local && - echo "s/main/rain/" >"$HTTPD_ROOT_PATH/one-time-perl" && + write_script "$HTTPD_ROOT_PATH/one-time-script" <<-\EOF && + sed "s/main/rain/" "$1" + EOF test_must_fail git -C local fetch 2>err && test_grep "fatal: remote error: unknown ref refs/heads/rain" err diff --git a/t/t5710-promisor-remote-capability.sh b/t/t5710-promisor-remote-capability.sh index d2cc69a17e..cb061b1f35 100755 --- a/t/t5710-promisor-remote-capability.sh +++ b/t/t5710-promisor-remote-capability.sh @@ -4,6 +4,12 @@ test_description='handling of promisor remote advertisement' . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping promisor remote capabilities tests; Perl not available' + test_done +fi + GIT_TEST_MULTI_PACK_INDEX=0 GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0 @@ -93,6 +99,7 @@ test_expect_success "setup for testing promisor remote advertisement" ' test_expect_success "clone with promisor.advertise set to 'true'" ' git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && # Clone from server to create a client GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ @@ -100,7 +107,6 @@ test_expect_success "clone with promisor.advertise set to 'true'" ' -c remote.lop.url="file://$(pwd)/lop" \ -c promisor.acceptfromserver=All \ --no-local --filter="blob:limit=5k" server client && - test_when_finished "rm -rf client" && # Check that the largest object is still missing on the server check_missing_objects server 1 "$oid" @@ -108,6 +114,7 @@ test_expect_success "clone with promisor.advertise set to 'true'" ' test_expect_success "clone with promisor.advertise set to 'false'" ' git -C server config promisor.advertise false && + test_when_finished "rm -rf client" && # Clone from server to create a client GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ @@ -115,7 +122,6 @@ test_expect_success "clone with promisor.advertise set to 'false'" ' -c remote.lop.url="file://$(pwd)/lop" \ -c promisor.acceptfromserver=All \ --no-local --filter="blob:limit=5k" server client && - test_when_finished "rm -rf client" && # Check that the largest object is not missing on the server check_missing_objects server 0 "" && @@ -126,6 +132,7 @@ test_expect_success "clone with promisor.advertise set to 'false'" ' test_expect_success "clone with promisor.acceptfromserver set to 'None'" ' git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && # Clone from server to create a client GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ @@ -133,7 +140,6 @@ test_expect_success "clone with promisor.acceptfromserver set to 'None'" ' -c remote.lop.url="file://$(pwd)/lop" \ -c promisor.acceptfromserver=None \ --no-local --filter="blob:limit=5k" server client && - test_when_finished "rm -rf client" && # Check that the largest object is not missing on the server check_missing_objects server 0 "" && @@ -144,8 +150,8 @@ test_expect_success "clone with promisor.acceptfromserver set to 'None'" ' test_expect_success "init + fetch with promisor.advertise set to 'true'" ' git -C server config promisor.advertise true && - test_when_finished "rm -rf client" && + mkdir client && git -C client init && git -C client config remote.lop.promisor true && @@ -162,6 +168,7 @@ test_expect_success "init + fetch with promisor.advertise set to 'true'" ' test_expect_success "clone with promisor.acceptfromserver set to 'KnownName'" ' git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && # Clone from server to create a client GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ @@ -169,7 +176,6 @@ test_expect_success "clone with promisor.acceptfromserver set to 'KnownName'" ' -c remote.lop.url="file://$(pwd)/lop" \ -c promisor.acceptfromserver=KnownName \ --no-local --filter="blob:limit=5k" server client && - test_when_finished "rm -rf client" && # Check that the largest object is still missing on the server check_missing_objects server 1 "$oid" @@ -177,6 +183,7 @@ test_expect_success "clone with promisor.acceptfromserver set to 'KnownName'" ' test_expect_success "clone with 'KnownName' and different remote names" ' git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && # Clone from server to create a client GIT_NO_LAZY_FETCH=0 git clone -c remote.serverTwo.promisor=true \ @@ -184,8 +191,26 @@ test_expect_success "clone with 'KnownName' and different remote names" ' -c remote.serverTwo.url="file://$(pwd)/lop" \ -c promisor.acceptfromserver=KnownName \ --no-local --filter="blob:limit=5k" server client && + + # Check that the largest object is not missing on the server + check_missing_objects server 0 "" && + + # Reinitialize server so that the largest object is missing again + initialize_server 1 "$oid" +' + +test_expect_success "clone with 'KnownName' and missing URL in the config" ' + git -C server config promisor.advertise true && test_when_finished "rm -rf client" && + # Clone from server to create a client + # Lazy fetching by the client from the LOP will fail because of the + # missing URL in the client config, so the server will have to lazy + # fetch from the LOP. + GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c promisor.acceptfromserver=KnownName \ + --no-local --filter="blob:limit=5k" server client && + # Check that the largest object is not missing on the server check_missing_objects server 0 "" && @@ -195,6 +220,7 @@ test_expect_success "clone with 'KnownName' and different remote names" ' test_expect_success "clone with promisor.acceptfromserver set to 'KnownUrl'" ' git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && # Clone from server to create a client GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ @@ -202,7 +228,6 @@ test_expect_success "clone with promisor.acceptfromserver set to 'KnownUrl'" ' -c remote.lop.url="file://$(pwd)/lop" \ -c promisor.acceptfromserver=KnownUrl \ --no-local --filter="blob:limit=5k" server client && - test_when_finished "rm -rf client" && # Check that the largest object is still missing on the server check_missing_objects server 1 "$oid" @@ -212,6 +237,7 @@ test_expect_success "clone with 'KnownUrl' and different remote urls" ' ln -s lop serverTwo && git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && # Clone from server to create a client GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ @@ -219,7 +245,6 @@ test_expect_success "clone with 'KnownUrl' and different remote urls" ' -c remote.lop.url="file://$(pwd)/serverTwo" \ -c promisor.acceptfromserver=KnownUrl \ --no-local --filter="blob:limit=5k" server client && - test_when_finished "rm -rf client" && # Check that the largest object is not missing on the server check_missing_objects server 0 "" && @@ -228,6 +253,48 @@ test_expect_success "clone with 'KnownUrl' and different remote urls" ' initialize_server 1 "$oid" ' +test_expect_success "clone with 'KnownUrl' and url not configured on the server" ' + git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && + + test_when_finished "git -C server config set remote.lop.url \"file://$(pwd)/lop\"" && + git -C server config unset remote.lop.url && + + # Clone from server to create a client + # It should fail because the client will reject the LOP as URLs are + # different, and the server cannot lazy fetch as the LOP URL is + # missing, so the remote name will be used instead which will fail. + test_must_fail env GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownUrl \ + --no-local --filter="blob:limit=5k" server client && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + +test_expect_success "clone with 'KnownUrl' and empty url, so not advertised" ' + git -C server config promisor.advertise true && + test_when_finished "rm -rf client" && + + test_when_finished "git -C server config set remote.lop.url \"file://$(pwd)/lop\"" && + git -C server config set remote.lop.url "" && + + # Clone from server to create a client + # It should fail because the client will reject the LOP as an empty URL is + # not advertised, and the server cannot lazy fetch as the LOP URL is empty, + # so the remote name will be used instead which will fail. + test_must_fail env GIT_NO_LAZY_FETCH=0 git clone -c remote.lop.promisor=true \ + -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \ + -c remote.lop.url="file://$(pwd)/lop" \ + -c promisor.acceptfromserver=KnownUrl \ + --no-local --filter="blob:limit=5k" server client && + + # Check that the largest object is still missing on the server + check_missing_objects server 1 "$oid" +' + test_expect_success "clone with promisor.advertise set to 'true' but don't delete the client" ' git -C server config promisor.advertise true && diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index 6289a2e8b0..fec16448cf 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -182,4 +182,70 @@ test_expect_success 'rev-list --unpacked' ' test_cmp expect actual ' +test_expect_success 'rev-list one-sided unrelated symmetric diff' ' + test_tick && + git commit --allow-empty -m xyz && + git branch cmp && + git rebase --force-rebase --root && + + git rev-list --left-only HEAD...cmp >head && + git rev-list --right-only HEAD...cmp >cmp && + + sort head >head.sorted && + sort cmp >cmp.sorted && + comm -12 head.sorted cmp.sorted >actual && + test_line_count = 0 actual +' + +test_expect_success 'rev-list -z' ' + test_when_finished rm -rf repo && + + git init repo && + test_commit -C repo 1 && + test_commit -C repo 2 && + + oid1=$(git -C repo rev-parse HEAD~) && + oid2=$(git -C repo rev-parse HEAD) && + + printf "%s\0%s\0" "$oid2" "$oid1" >expect && + git -C repo rev-list -z HEAD >actual && + + test_cmp expect actual +' + +test_expect_success 'rev-list -z --objects' ' + test_when_finished rm -rf repo && + + git init repo && + test_commit -C repo 1 && + test_commit -C repo 2 && + + oid1=$(git -C repo rev-parse HEAD:1.t) && + oid2=$(git -C repo rev-parse HEAD:2.t) && + path1=1.t && + path2=2.t && + + printf "%s\0path=%s\0%s\0path=%s\0" "$oid1" "$path1" "$oid2" "$path2" \ + >expect && + git -C repo rev-list -z --objects HEAD:1.t HEAD:2.t >actual && + + test_cmp expect actual +' + +test_expect_success 'rev-list -z --boundary' ' + test_when_finished rm -rf repo && + + git init repo && + test_commit -C repo 1 && + test_commit -C repo 2 && + + oid1=$(git -C repo rev-parse HEAD~) && + oid2=$(git -C repo rev-parse HEAD) && + + printf "%s\0%s\0boundary=yes\0" "$oid2" "$oid1" >expect && + git -C repo rev-list -z --boundary HEAD~.. >actual && + + test_cmp expect actual +' + test_done diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh index bad02cf5b8..1dd1e50d21 100755 --- a/t/t6011-rev-list-with-bad-commit.sh +++ b/t/t6011-rev-list-with-bad-commit.sh @@ -35,11 +35,16 @@ test_expect_success 'verify number of revisions' \ first_commit=$(git rev-parse HEAD~3) ' -test_expect_success 'corrupt second commit object' \ - ' - perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack && - test_must_fail git fsck --full - ' +test_expect_success 'corrupt second commit object' ' + for p in .git/objects/pack/*.pack + do + chmod +w "$p" && + sed "s/second commit/socond commit/" "$p" >"$p.munged" && + mv "$p.munged" "$p" || + return 1 + done && + test_must_fail git fsck --full +' test_expect_success 'rev-list should fail' ' test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git -c core.commitGraph=false rev-list --all > /dev/null diff --git a/t/t6013-rev-list-reverse-parents.sh b/t/t6013-rev-list-reverse-parents.sh index 39793cbbd6..273196f52b 100755 --- a/t/t6013-rev-list-reverse-parents.sh +++ b/t/t6013-rev-list-reverse-parents.sh @@ -26,17 +26,19 @@ test_expect_success 'set up --reverse example' ' commit five ' +reverse () { + awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' +} + test_expect_success '--reverse --parents --full-history combines correctly' ' - git rev-list --parents --full-history main -- foo | - perl -e "print reverse <>" > expected && + git rev-list --parents --full-history main -- foo | reverse >expected && git rev-list --reverse --parents --full-history main -- foo \ > actual && test_cmp expected actual ' test_expect_success '--boundary does too' ' - git rev-list --boundary --parents --full-history main ^root -- foo | - perl -e "print reverse <>" > expected && + git rev-list --boundary --parents --full-history main ^root -- foo | reverse >expected && git rev-list --boundary --reverse --parents --full-history \ main ^root -- foo > actual && test_cmp expected actual diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh index b3807e8f35..500c81b8a1 100755 --- a/t/t6020-bundle-misc.sh +++ b/t/t6020-bundle-misc.sh @@ -673,6 +673,59 @@ test_expect_success 'bundle progress with --no-quiet' ' grep "%" err ' +test_expect_success 'create bundle with duplicate refnames' ' + git bundle create out.bdl "main" "main" && + + git bundle list-heads out.bdl | + make_user_friendly_and_stable_output >actual && + cat >expect <<-\EOF && + <COMMIT-P> refs/heads/main + EOF + test_cmp expect actual +' + +test_expect_success 'create bundle with duplicate refnames and --all' ' + git bundle create out.bdl --all "main" "main" && + + git bundle list-heads out.bdl | + make_user_friendly_and_stable_output >actual && + cat >expect <<-\EOF && + <COMMIT-P> refs/heads/main + <COMMIT-N> refs/heads/release + <COMMIT-D> refs/heads/topic/1 + <COMMIT-H> refs/heads/topic/2 + <COMMIT-D> refs/pull/1/head + <COMMIT-G> refs/pull/2/head + <TAG-1> refs/tags/v1 + <TAG-2> refs/tags/v2 + <TAG-3> refs/tags/v3 + <COMMIT-P> HEAD + EOF + test_cmp expect actual +' + +test_expect_success 'create bundle with duplicate exlusion refnames' ' + git bundle create out.bdl "main" "main^!" && + + git bundle list-heads out.bdl | + make_user_friendly_and_stable_output >actual && + cat >expect <<-\EOF && + <COMMIT-P> refs/heads/main + EOF + test_cmp expect actual +' + +test_expect_success 'create bundle with duplicate refname short-form' ' + git bundle create out.bdl "main" "main" "refs/heads/main" "refs/heads/main" && + + git bundle list-heads out.bdl | + make_user_friendly_and_stable_output >actual && + cat >expect <<-\EOF && + <COMMIT-P> refs/heads/main + EOF + test_cmp expect actual +' + test_expect_success 'read bundle over stdin' ' git bundle create some.bundle HEAD && diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh index 3e2790d4c8..08e92dd002 100755 --- a/t/t6022-rev-list-missing.sh +++ b/t/t6022-rev-list-missing.sh @@ -198,4 +198,35 @@ do ' done +test_expect_success "-z nul-delimited --missing" ' + test_when_finished rm -rf repo && + + git init repo && + ( + cd repo && + git commit --allow-empty -m first && + + path="foo bar" && + echo foobar >"$path" && + git add -A && + git commit -m second && + + oid=$(git rev-parse "HEAD:$path") && + type="$(git cat-file -t $oid)" && + + obj_path=".git/objects/$(test_oid_to_path $oid)" && + + git rev-list -z --objects --no-object-names \ + HEAD ^"$oid" >expect && + printf "%s\0missing=yes\0path=%s\0type=%s\0" "$oid" "$path" \ + "$type" >>expect && + + mv "$obj_path" "$obj_path.hidden" && + git rev-list -z --objects --no-object-names \ + --missing=print-info HEAD >actual && + + test_cmp expect actual + ) +' + test_done diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh index 22dfd6d978..eb98b3919c 100755 --- a/t/t6102-rev-list-unexpected-objects.sh +++ b/t/t6102-rev-list-unexpected-objects.sh @@ -4,6 +4,12 @@ test_description='git rev-list should handle unexpected object types' . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping rev-list unexpected objects tests; Perl not available' + test_done +fi + test_expect_success 'setup well-formed objects' ' blob="$(printf "foo" | git hash-object -w --stdin)" && tree="$(printf "100644 blob $blob\tfoo" | git mktree)" && diff --git a/t/t6115-rev-list-du.sh b/t/t6115-rev-list-du.sh index 3385fe9f13..04c577dad6 100755 --- a/t/t6115-rev-list-du.sh +++ b/t/t6115-rev-list-du.sh @@ -22,7 +22,7 @@ test_expect_success 'set up repository' ' disk_usage_slow () { git rev-list --no-object-names "$@" | git cat-file --batch-check="%(objectsize:disk)" | - perl -lne '$total += $_; END { print $total}' + awk '{ i += $1 } END { print i }' } # check behavior with given rev-list options; note that diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 76843a6169..256ccaefb7 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -292,15 +292,23 @@ test_expect_success 'name-rev --annotate-stdin' ' echo "$rev ($name)" >>expect.unsorted || return 1 done && sort <expect.unsorted >expect && - git rev-list --all | git name-rev --annotate-stdin >actual.unsorted && + git rev-list --all >list && + git name-rev --annotate-stdin <list >actual.unsorted && sort <actual.unsorted >actual && test_cmp expect actual ' -test_expect_success 'name-rev --stdin deprecated' " - git rev-list --all | git name-rev --stdin 2>actual && - grep -E 'warning: --stdin is deprecated' actual -" +test_expect_success 'name-rev --stdin deprecated' ' + git rev-list --all >list && + if ! test_have_prereq WITH_BREAKING_CHANGES + then + git name-rev --stdin <list 2>actual && + test_grep "warning: --stdin is deprecated" actual + else + test_must_fail git name-rev --stdin <list 2>actual && + test_grep "unknown option .stdin." actual + fi +' test_expect_success 'describe --contains with the exact tags' ' echo "A^0" >expect && diff --git a/t/t6137-pathspec-wildcards-literal.sh b/t/t6137-pathspec-wildcards-literal.sh new file mode 100755 index 0000000000..20abad5667 --- /dev/null +++ b/t/t6137-pathspec-wildcards-literal.sh @@ -0,0 +1,429 @@ +#!/bin/sh +test_description='test wildcards and literals with git add/commit (subshell style)' + +. ./test-lib.sh + +test_have_prereq FUNNYNAMES || { + skip_all='skipping: needs FUNNYNAMES (non-Windows only)' + test_done +} + +prepare_test_files () { + for f in "*" "**" "?" "[abc]" "a" "f*" "f**" "f?z" "foo*bar" "hello?world" "hello_world" + do + >"$f" || return + done +} + +test_expect_success 'add wildcard *' ' + git init test-asterisk && + ( + cd test-asterisk && + prepare_test_files && + git add "*" && + cat >expect <<-EOF && + * + ** + ? + [abc] + a + f* + f** + f?z + foo*bar + hello?world + hello_world + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add literal \*' ' + git init test-asterisk-literal && + ( + cd test-asterisk-literal && + prepare_test_files && + git add "\*" && + cat >expect <<-EOF && + * + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard **' ' + git init test-dstar && + ( + cd test-dstar && + prepare_test_files && + git add "**" && + cat >expect <<-EOF && + * + ** + ? + [abc] + a + f* + f** + f?z + foo*bar + hello?world + hello_world + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard ?' ' + git init test-qmark && + ( + cd test-qmark && + prepare_test_files && + git add "?" && + cat >expect <<-\EOF | sort && + * + ? + a + EOF + git ls-files | sort >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard [abc]' ' + git init test-brackets && + ( + cd test-brackets && + prepare_test_files && + git add "[abc]" && + cat >expect <<-\EOF | sort && + [abc] + a + EOF + git ls-files | sort >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard f*' ' + git init test-f-wild && + ( + cd test-f-wild && + prepare_test_files && + git add "f*" && + cat >expect <<-\EOF | sort && + f* + f** + f?z + foo*bar + EOF + git ls-files | sort >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add literal f\*' ' + git init test-f-lit && + ( + cd test-f-lit && + prepare_test_files && + git add "f\*" && + cat >expect <<-\EOF && + f* + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard f**' ' + git init test-fdstar && + ( + cd test-fdstar && + prepare_test_files && + git add "f**" && + cat >expect <<-\EOF | sort && + f* + f** + f?z + foo*bar + EOF + git ls-files | sort >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add literal f\*\*' ' + git init test-fdstar-lit && + ( + cd test-fdstar-lit && + prepare_test_files && + git add "f\*\*" && + cat >expect <<-\EOF && + f** + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard f?z' ' + git init test-fqz && + ( + cd test-fqz && + prepare_test_files && + git add "f?z" && + cat >expect <<-\EOF && + f?z + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add literal \? literal' ' + git init test-q-lit && + ( + cd test-q-lit && + prepare_test_files && + git add "\?" && + cat >expect <<-\EOF && + ? + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard foo*bar' ' + git init test-foobar && + ( + cd test-foobar && + prepare_test_files && + git add "foo*bar" && + cat >expect <<-\EOF && + foo*bar + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add wildcard hello?world' ' + git init test-hellowild && + ( + cd test-hellowild && + prepare_test_files && + git add "hello?world" && + cat >expect <<-\EOF && + hello?world + hello_world + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add literal hello\?world' ' + git init test-hellolit && + ( + cd test-hellolit && + prepare_test_files && + git add "hello\?world" && + cat >expect <<-\EOF && + hello?world + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'add literal [abc]' ' + git init test-brackets-lit && + ( + cd test-brackets-lit && + prepare_test_files && + git add "\[abc\]" && + cat >expect <<-\EOF && + [abc] + EOF + git ls-files >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: wildcard *' ' + git init test-c-asterisk && + ( + cd test-c-asterisk && + prepare_test_files && + git add . && + git commit -m "c1" -- "*" && + cat >expect <<-EOF && + * + ** + ? + [abc] + a + f* + f** + f?z + foo*bar + hello?world + hello_world + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: literal *' ' + git init test-c-asterisk-lit && + ( + cd test-c-asterisk-lit && + prepare_test_files && + git add . && + git commit -m "c2" -- "\*" && + cat >expect <<-EOF && + * + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: wildcard f*' ' + git init test-c-fwild && + ( + cd test-c-fwild && + prepare_test_files && + git add . && + git commit -m "c3" -- "f*" && + cat >expect <<-EOF && + f* + f** + f?z + foo*bar + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: literal f\*' ' + git init test-c-flit && + ( + cd test-c-flit && + prepare_test_files && + git add . && + git commit -m "c4" -- "f\*" && + cat >expect <<-EOF && + f* + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: wildcard pathspec limits commit' ' + git init test-c-pathlimit && + ( + cd test-c-pathlimit && + prepare_test_files && + git add . && + git commit -m "c5" -- "f**" && + cat >expect <<-EOF && + f* + f** + f?z + foo*bar + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: literal f\*\*' ' + git init test-c-fdstar-lit && + ( + cd test-c-fdstar-lit && + prepare_test_files && + git add . && + git commit -m "c6" -- "f\*\*" && + cat >expect <<-EOF && + f** + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: wildcard ?' ' + git init test-c-qwild && + ( + cd test-c-qwild && + prepare_test_files && + git add . && + git commit -m "c7" -- "?" && + cat >expect <<-EOF && + * + ? + a + EOF + git ls-tree -r --name-only HEAD | sort >actual && + sort expect >expect.sorted && + test_cmp expect.sorted actual + ) +' + +test_expect_success 'commit: literal \?' ' + git init test-c-qlit && + ( + cd test-c-qlit && + prepare_test_files && + git add . && + git commit -m "c8" -- "\?" && + cat >expect <<-EOF && + ? + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit: wildcard hello?world' ' + git init test-c-hellowild && + ( + cd test-c-hellowild && + prepare_test_files && + git add . && + git commit -m "c9" -- "hello?world" && + cat >expect <<-EOF && + hello?world + hello_world + EOF + git ls-tree -r --name-only HEAD | sort >actual && + sort expect >expect.sorted && + test_cmp expect.sorted actual + ) +' + +test_expect_success 'commit: literal hello\?world' ' + git init test-c-hellolit && + ( + cd test-c-hellolit && + prepare_test_files && + git add . && + git commit -m "c10" -- "hello\?world" && + cat >expect <<-EOF && + hello?world + EOF + git ls-tree -r --name-only HEAD >actual && + test_cmp expect actual + ) +' + +test_done diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index a5c7794385..ce9af79ab1 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -292,6 +292,13 @@ test_expect_success 'Check invalid atoms names are errors' ' test_must_fail git for-each-ref --format="%(INVALID)" refs/heads ' +test_expect_success 'for-each-ref does not crash with -h' ' + test_expect_code 129 git for-each-ref -h >usage && + test_grep "[Uu]sage: git for-each-ref " usage && + test_expect_code 129 nongit git for-each-ref -h >usage && + test_grep "[Uu]sage: git for-each-ref " usage +' + test_expect_success 'Check format specifiers are ignored in naming date atoms' ' git for-each-ref --format="%(authordate)" refs/heads && git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads && @@ -1209,7 +1216,7 @@ test_expect_success '%(raw) with --tcl must fail' ' test_must_fail git for-each-ref --format="%(raw)" --tcl ' -test_expect_success '%(raw) with --perl' ' +test_expect_success PERL_TEST_HELPERS '%(raw) with --perl' ' git for-each-ref --format="\$name= %(raw); print \"\$name\"" refs/myblobs/blob1 --perl | perl >actual && cmp blob1 actual && @@ -1436,9 +1443,14 @@ test_expect_success 'set up trailers for next test' ' ' test_trailer_option () { + if test "$#" -eq 3 + then + prereq="$1" + shift + fi && title=$1 option=$2 cat >expect - test_expect_success "$title" ' + test_expect_success $prereq "$title" ' git for-each-ref --format="%($option)" refs/heads/main >actual && test_cmp expect actual && git for-each-ref --format="%(contents:$option)" refs/heads/main >actual && @@ -1446,7 +1458,7 @@ test_trailer_option () { ' } -test_trailer_option '%(trailers:unfold) unfolds trailers' \ +test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) unfolds trailers' \ 'trailers:unfold' <<-EOF $(unfold <trailers) @@ -1476,13 +1488,13 @@ test_trailer_option '%(trailers:only=no) shows all trailers' \ EOF -test_trailer_option '%(trailers:only) and %(trailers:unfold) work together' \ +test_trailer_option PERL_TEST_HELPERS '%(trailers:only) and %(trailers:unfold) work together' \ 'trailers:only,unfold' <<-EOF $(grep -v patch.description <trailers | unfold) EOF -test_trailer_option '%(trailers:unfold) and %(trailers:only) work together' \ +test_trailer_option PERL_TEST_HELPERS '%(trailers:unfold) and %(trailers:only) work together' \ 'trailers:unfold,only' <<-EOF $(grep -v patch.description <trailers | unfold) diff --git a/t/t6400-merge-df.sh b/t/t6400-merge-df.sh index 3de4ef6bd9..b46fe49440 100755 --- a/t/t6400-merge-df.sh +++ b/t/t6400-merge-df.sh @@ -84,12 +84,7 @@ test_expect_success 'modify/delete + directory/file conflict' ' test_stdout_line_count = 5 git ls-files -s && test_stdout_line_count = 4 git ls-files -u && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_stdout_line_count = 0 git ls-files -o - else - test_stdout_line_count = 1 git ls-files -o - fi && + test_stdout_line_count = 0 git ls-files -o && test_path_is_file letters/file && test_path_is_file letters.txt && @@ -105,12 +100,7 @@ test_expect_success 'modify/delete + directory/file conflict; other way' ' test_stdout_line_count = 5 git ls-files -s && test_stdout_line_count = 4 git ls-files -u && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_stdout_line_count = 0 git ls-files -o - else - test_stdout_line_count = 1 git ls-files -o - fi && + test_stdout_line_count = 0 git ls-files -o && test_path_is_file letters/file && test_path_is_file letters.txt && diff --git a/t/t6402-merge-rename.sh b/t/t6402-merge-rename.sh index 2738b50c2a..ff00b74e9c 100755 --- a/t/t6402-merge-rename.sh +++ b/t/t6402-merge-rename.sh @@ -313,12 +313,7 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' ' test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && test_grep "Auto-merging dir" output && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_grep "moving it to dir~HEAD instead" output - else - test_grep "Adding as dir~HEAD instead" output - fi && + test_grep "moving it to dir~HEAD instead" output && test_stdout_line_count = 3 git ls-files -u && test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && @@ -340,12 +335,7 @@ test_expect_success 'Same as previous, but merged other way' ' ! grep "error: refusing to lose untracked file at" errors && test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && test_grep "Auto-merging dir" output && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_grep "moving it to dir~renamed-file-has-no-conflicts instead" output - else - test_grep "Adding as dir~renamed-file-has-no-conflicts instead" output - fi && + test_grep "moving it to dir~renamed-file-has-no-conflicts instead" output && test_stdout_line_count = 3 git ls-files -u && test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && @@ -400,14 +390,7 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in t test_must_fail git merge --strategy=recursive dir-in-way && test_stdout_line_count = 5 git ls-files -u && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_stdout_line_count = 3 git ls-files -u dir~HEAD - else - git ls-files -u dir >out && - test 3 -eq $(grep -v file-in-the-way out | wc -l) && - rm -f out - fi && + test_stdout_line_count = 3 git ls-files -u dir~HEAD && test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && test_must_fail git diff --quiet && @@ -425,14 +408,7 @@ test_expect_success 'Same as previous, but merged other way' ' test_must_fail git merge --strategy=recursive renamed-file-has-conflicts && test_stdout_line_count = 5 git ls-files -u && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_stdout_line_count = 3 git ls-files -u dir~renamed-file-has-conflicts - else - git ls-files -u dir >out && - test 3 -eq $(grep -v file-in-the-way out | wc -l) && - rm -f out - fi && + test_stdout_line_count = 3 git ls-files -u dir~renamed-file-has-conflicts && test_stdout_line_count = 2 git ls-files -u dir/file-in-the-way && test_must_fail git diff --quiet && @@ -488,12 +464,7 @@ test_expect_success 'both rename source and destination involved in D/F conflict git checkout -q rename-dest^0 && test_must_fail git merge --strategy=recursive source-conflict && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_stdout_line_count = 2 git ls-files -u - else - test_stdout_line_count = 1 git ls-files -u - fi && + test_stdout_line_count = 2 git ls-files -u && test_must_fail git diff --quiet && @@ -527,63 +498,33 @@ test_expect_success 'setup pair rename to parent of other (D/F conflicts)' ' git commit -m "Rename one/file -> two" ' -if test "$GIT_TEST_MERGE_ALGORITHM" = ort -then - test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' ' - git checkout -q rename-one^0 && - mkdir one && - test_must_fail git merge --strategy=recursive rename-two && - - test_stdout_line_count = 4 git ls-files -u && - test_stdout_line_count = 2 git ls-files -u one && - test_stdout_line_count = 2 git ls-files -u two && - - test_must_fail git diff --quiet && - - test 3 -eq $(find . | grep -v .git | wc -l) && - - test_path_is_file one && - test_path_is_file two && - test "other" = $(cat one) && - test "stuff" = $(cat two) - ' -else - test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' ' - git checkout -q rename-one^0 && - mkdir one && - test_must_fail git merge --strategy=recursive rename-two && +test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' ' + git checkout -q rename-one^0 && + mkdir one && + test_must_fail git merge --strategy=recursive rename-two && - test_stdout_line_count = 2 git ls-files -u && - test_stdout_line_count = 1 git ls-files -u one && - test_stdout_line_count = 1 git ls-files -u two && + test_stdout_line_count = 4 git ls-files -u && + test_stdout_line_count = 2 git ls-files -u one && + test_stdout_line_count = 2 git ls-files -u two && - test_must_fail git diff --quiet && + test_must_fail git diff --quiet && - test 4 -eq $(find . | grep -v .git | wc -l) && + test 3 -eq $(find . | grep -v .git | wc -l) && - test_path_is_dir one && - test_path_is_file one~rename-two && - test_path_is_file two && - test "other" = $(cat one~rename-two) && - test "stuff" = $(cat two) - ' -fi + test_path_is_file one && + test_path_is_file two && + test "other" = $(cat one) && + test "stuff" = $(cat two) +' test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean start' ' git reset --hard && git clean -fdqx && test_must_fail git merge --strategy=recursive rename-two && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_stdout_line_count = 4 git ls-files -u && - test_stdout_line_count = 2 git ls-files -u one && - test_stdout_line_count = 2 git ls-files -u two - else - test_stdout_line_count = 2 git ls-files -u && - test_stdout_line_count = 1 git ls-files -u one && - test_stdout_line_count = 1 git ls-files -u two - fi && + test_stdout_line_count = 4 git ls-files -u && + test_stdout_line_count = 2 git ls-files -u one && + test_stdout_line_count = 2 git ls-files -u two && test_must_fail git diff --quiet && @@ -623,22 +564,12 @@ test_expect_success 'check handling of differently renamed file with D/F conflic git checkout -q first-rename^0 && test_must_fail git merge --strategy=recursive second-rename && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_stdout_line_count = 5 git ls-files -s && - test_stdout_line_count = 3 git ls-files -u && - test_stdout_line_count = 1 git ls-files -u one~HEAD && - test_stdout_line_count = 1 git ls-files -u two~second-rename && - test_stdout_line_count = 1 git ls-files -u original && - test_stdout_line_count = 0 git ls-files -o - else - test_stdout_line_count = 5 git ls-files -s && - test_stdout_line_count = 3 git ls-files -u && - test_stdout_line_count = 1 git ls-files -u one && - test_stdout_line_count = 1 git ls-files -u two && - test_stdout_line_count = 1 git ls-files -u original && - test_stdout_line_count = 2 git ls-files -o - fi && + test_stdout_line_count = 5 git ls-files -s && + test_stdout_line_count = 3 git ls-files -u && + test_stdout_line_count = 1 git ls-files -u one~HEAD && + test_stdout_line_count = 1 git ls-files -u two~second-rename && + test_stdout_line_count = 1 git ls-files -u original && + test_stdout_line_count = 0 git ls-files -o && test_path_is_file one/file && test_path_is_file two/file && diff --git a/t/t6404-recursive-merge.sh b/t/t6404-recursive-merge.sh index ae687f2ce5..346f3608b9 100755 --- a/t/t6404-recursive-merge.sh +++ b/t/t6404-recursive-merge.sh @@ -108,12 +108,7 @@ test_expect_success 'refuse to merge binary files' ' printf "\0\0" >binary-file && git add binary-file && git commit -m binary2 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_must_fail git merge F >merge_output - else - test_must_fail git merge F 2>merge_output - fi && + test_must_fail git merge F >merge_output && grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge_output ' @@ -129,22 +124,12 @@ test_expect_success 'mark rename/delete as unmerged' ' test_tick && git commit -m rename && test_must_fail git merge delete && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test 2 = $(git ls-files --unmerged | wc -l) - else - test 1 = $(git ls-files --unmerged | wc -l) - fi && + test 2 = $(git ls-files --unmerged | wc -l) && git rev-parse --verify :2:a2 && test_must_fail git rev-parse --verify :3:a2 && git checkout -f delete && test_must_fail git merge rename && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test 2 = $(git ls-files --unmerged | wc -l) - else - test 1 = $(git ls-files --unmerged | wc -l) - fi && + test 2 = $(git ls-files --unmerged | wc -l) && test_must_fail git rev-parse --verify :2:a2 && git rev-parse --verify :3:a2 ' diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh index 66e01464b5..8f6fbef002 100755 --- a/t/t6406-merge-attr.sh +++ b/t/t6406-merge-attr.sh @@ -259,12 +259,7 @@ test_expect_success 'binary files with union attribute' ' printf "two\0" >bin.txt && git commit -am two && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_must_fail git merge bin-main >output - else - test_must_fail git merge bin-main 2>output - fi && + test_must_fail git merge bin-main >output && grep -i "warning.*cannot merge.*HEAD vs. bin-main" output ' diff --git a/t/t6416-recursive-corner-cases.sh b/t/t6416-recursive-corner-cases.sh index 17b54d625d..ed20de8ea2 100755 --- a/t/t6416-recursive-corner-cases.sh +++ b/t/t6416-recursive-corner-cases.sh @@ -6,7 +6,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh # # L1 L2 @@ -529,15 +528,8 @@ test_expect_success 'setup differently handled merges of directory/file conflict git checkout B^0 && test_must_fail git merge C^0 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git rm -rf a/ && - git rm a~HEAD - else - git clean -fd && - git rm -rf a/ && - git rm a - fi && + git rm -rf a/ && + git rm a~HEAD && git cat-file -p B:a >a2 && git add a2 && git commit -m D2 && @@ -556,12 +548,7 @@ test_expect_success 'setup differently handled merges of directory/file conflict git checkout C^0 && test_must_fail git merge B^0 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git rm a~B^0 - else - git clean -fd - fi && + git rm a~B^0 && git rm -rf a/ && test_write_lines 1 2 3 4 5 6 7 8 >a && git add a && @@ -570,15 +557,8 @@ test_expect_success 'setup differently handled merges of directory/file conflict git checkout C^0 && test_must_fail git merge B^0 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git rm -rf a/ && - git rm a~B^0 - else - git clean -fd && - git rm -rf a/ && - git rm a - fi && + git rm -rf a/ && + git rm a~B^0 && test_write_lines 1 2 3 4 5 6 7 8 >a2 && git add a2 && git commit -m E4 && @@ -596,34 +576,16 @@ test_expect_success 'merge of D1 & E1 fails but has appropriate contents' ' test_must_fail git merge -s recursive E1^0 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git ls-files -s >out && - test_line_count = 3 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >expect \ - A:ignore-me B:a D1:a && - git rev-parse >actual \ - :0:ignore-me :1:a :2:a && - test_cmp expect actual - else - git ls-files -s >out && - test_line_count = 2 out && - git ls-files -u >out && - test_line_count = 1 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >expect \ - A:ignore-me B:a && - git rev-parse >actual \ - :0:ignore-me :2:a && - test_cmp expect actual - fi + git ls-files -s >out && + test_line_count = 3 out && + git ls-files -u >out && + test_line_count = 2 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >expect A:ignore-me B:a D1:a && + git rev-parse >actual :0:ignore-me :1:a :2:a && + test_cmp expect actual ) ' @@ -637,34 +599,18 @@ test_expect_success 'merge of E1 & D1 fails but has appropriate contents' ' test_must_fail git merge -s recursive D1^0 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git ls-files -s >out && - test_line_count = 3 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >expect \ - A:ignore-me B:a D1:a && - git rev-parse >actual \ - :0:ignore-me :1:a :3:a && - test_cmp expect actual - else - git ls-files -s >out && - test_line_count = 2 out && - git ls-files -u >out && - test_line_count = 1 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >expect \ - A:ignore-me B:a && - git rev-parse >actual \ - :0:ignore-me :3:a && - test_cmp expect actual - fi + git ls-files -s >out && + test_line_count = 3 out && + git ls-files -u >out && + test_line_count = 2 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >expect \ + A:ignore-me B:a D1:a && + git rev-parse >actual \ + :0:ignore-me :1:a :3:a && + test_cmp expect actual ) ' @@ -678,32 +624,17 @@ test_expect_success 'merge of D1 & E2 fails but has appropriate contents' ' test_must_fail git merge -s recursive E2^0 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git ls-files -s >out && - test_line_count = 5 out && - git ls-files -u >out && - test_line_count = 4 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >expect \ - B:a D1:a E2:a/file C:a/file A:ignore-me && - git rev-parse >actual \ - :1:a~HEAD :2:a~HEAD :3:a/file :1:a/file :0:ignore-me - else - git ls-files -s >out && - test_line_count = 4 out && - git ls-files -u >out && - test_line_count = 3 out && - git ls-files -o >out && - test_line_count = 2 out && - - git rev-parse >expect \ - B:a E2:a/file C:a/file A:ignore-me && - git rev-parse >actual \ - :2:a :3:a/file :1:a/file :0:ignore-me - fi && + git ls-files -s >out && + test_line_count = 5 out && + git ls-files -u >out && + test_line_count = 4 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >expect \ + B:a D1:a E2:a/file C:a/file A:ignore-me && + git rev-parse >actual \ + :1:a~HEAD :2:a~HEAD :3:a/file :1:a/file :0:ignore-me && test_cmp expect actual && test_path_is_file a~HEAD @@ -720,32 +651,17 @@ test_expect_success 'merge of E2 & D1 fails but has appropriate contents' ' test_must_fail git merge -s recursive D1^0 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git ls-files -s >out && - test_line_count = 5 out && - git ls-files -u >out && - test_line_count = 4 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >expect \ - B:a D1:a E2:a/file C:a/file A:ignore-me && - git rev-parse >actual \ - :1:a~D1^0 :3:a~D1^0 :2:a/file :1:a/file :0:ignore-me - else - git ls-files -s >out && - test_line_count = 4 out && - git ls-files -u >out && - test_line_count = 3 out && - git ls-files -o >out && - test_line_count = 2 out && - - git rev-parse >expect \ - B:a E2:a/file C:a/file A:ignore-me && - git rev-parse >actual \ - :3:a :2:a/file :1:a/file :0:ignore-me - fi && + git ls-files -s >out && + test_line_count = 5 out && + git ls-files -u >out && + test_line_count = 4 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >expect \ + B:a D1:a E2:a/file C:a/file A:ignore-me && + git rev-parse >actual \ + :1:a~D1^0 :3:a~D1^0 :2:a/file :1:a/file :0:ignore-me && test_cmp expect actual && test_path_is_file a~D1^0 @@ -777,7 +693,7 @@ test_expect_success 'merge of D1 & E3 succeeds' ' ) ' -test_expect_merge_algorithm failure success 'merge of D1 & E4 puts merge of a and a2 in both a and a2' ' +test_expect_success 'merge of D1 & E4 puts merge of a and a2 in both a and a2' ' test_when_finished "git -C directory-file reset --hard" && test_when_finished "git -C directory-file clean -fdqx" && ( @@ -1140,7 +1056,7 @@ test_expect_success 'setup symlink modify/modify' ' ) ' -test_expect_merge_algorithm failure success 'check symlink modify/modify' ' +test_expect_success 'check symlink modify/modify' ' ( cd symlink-modify-modify && @@ -1206,7 +1122,7 @@ test_expect_success 'setup symlink add/add' ' ) ' -test_expect_merge_algorithm failure success 'check symlink add/add' ' +test_expect_success 'check symlink add/add' ' ( cd symlink-add-add && @@ -1294,7 +1210,7 @@ test_expect_success 'setup submodule modify/modify' ' ) ' -test_expect_merge_algorithm failure success 'check submodule modify/modify' ' +test_expect_success 'check submodule modify/modify' ' ( cd submodule-modify-modify && @@ -1382,7 +1298,7 @@ test_expect_success 'setup submodule add/add' ' ) ' -test_expect_merge_algorithm failure success 'check submodule add/add' ' +test_expect_success 'check submodule add/add' ' ( cd submodule-add-add && @@ -1457,7 +1373,7 @@ test_expect_success 'setup conflicting entry types (submodule vs symlink)' ' ) ' -test_expect_merge_algorithm failure success 'check conflicting entry types (submodule vs symlink)' ' +test_expect_success 'check conflicting entry types (submodule vs symlink)' ' ( cd submodule-symlink-add-add && diff --git a/t/t6421-merge-partial-clone.sh b/t/t6421-merge-partial-clone.sh index b99f29ef9b..6eb51285a0 100755 --- a/t/t6421-merge-partial-clone.sh +++ b/t/t6421-merge-partial-clone.sh @@ -27,7 +27,6 @@ test_description="limiting blob downloads when merging with partial clones" # files that might be renamed into each other's paths.) . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh test_setup_repo () { test -d server && return @@ -207,7 +206,7 @@ test_setup_repo () { # # Summary: 2 fetches (1 for 2 objects, 1 for 1 object) # -test_expect_merge_algorithm failure success 'Objects downloaded for single relevant rename' ' +test_expect_success 'Objects downloaded for single relevant rename' ' test_setup_repo && git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-single && ( @@ -297,7 +296,7 @@ test_expect_merge_algorithm failure success 'Objects downloaded for single relev # this are not all that common.) # Summary: 1 fetches for 6 objects # -test_expect_merge_algorithm failure success 'Objects downloaded when a directory rename triggered' ' +test_expect_success 'Objects downloaded when a directory rename triggered' ' test_setup_repo && git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-dir && ( @@ -399,7 +398,7 @@ test_expect_merge_algorithm failure success 'Objects downloaded when a directory # # Summary: 4 fetches (1 for 6 objects, 1 for 8, 1 for 3, 1 for 2) # -test_expect_merge_algorithm failure success 'Objects downloaded with lots of renames and modifications' ' +test_expect_success 'Objects downloaded with lots of renames and modifications' ' test_setup_repo && git clone --sparse --filter=blob:none "file://$(pwd)/server" objects-many && ( diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh index 62b49c67e2..9cbe7ca782 100755 --- a/t/t6422-merge-rename-corner-cases.sh +++ b/t/t6422-merge-rename-corner-cases.sh @@ -7,7 +7,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh test_setup_rename_delete_untracked () { git init rename-delete-untracked && @@ -316,12 +315,7 @@ test_expect_success 'rename/directory conflict + clean content merge' ' git ls-files -u >out && test_line_count = 1 out && git ls-files -o >out && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_line_count = 1 out - else - test_line_count = 2 out - fi && + test_line_count = 1 out && echo 0 >expect && git cat-file -p base:file >>expect && @@ -350,12 +344,7 @@ test_expect_success 'rename/directory conflict + content merge conflict' ' git ls-files -u >out && test_line_count = 3 out && git ls-files -o >out && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_line_count = 1 out - else - test_line_count = 2 out - fi && + test_line_count = 1 out && git cat-file -p left-conflict:newfile >left && git cat-file -p base:file >base && @@ -369,14 +358,8 @@ test_expect_success 'rename/directory conflict + content merge conflict' ' git rev-parse >expect \ base:file left-conflict:newfile right:file && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git rev-parse >actual \ - :1:newfile~HEAD :2:newfile~HEAD :3:newfile~HEAD - else - git rev-parse >actual \ - :1:newfile :2:newfile :3:newfile - fi && + git rev-parse >actual \ + :1:newfile~HEAD :2:newfile~HEAD :3:newfile~HEAD && test_cmp expect actual && test_path_is_file newfile/realfile && @@ -896,7 +879,7 @@ test_setup_rad () { ) } -test_expect_merge_algorithm failure success 'rad-check: rename/add/delete conflict' ' +test_expect_success 'rad-check: rename/add/delete conflict' ' test_setup_rad && ( cd rad && @@ -969,7 +952,7 @@ test_setup_rrdd () { ) } -test_expect_merge_algorithm failure success 'rrdd-check: rename/rename(2to1)/delete/delete conflict' ' +test_expect_success 'rrdd-check: rename/rename(2to1)/delete/delete conflict' ' test_setup_rrdd && ( cd rrdd && @@ -1058,7 +1041,7 @@ test_setup_mod6 () { ) } -test_expect_merge_algorithm failure success 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' ' +test_expect_success 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' ' test_setup_mod6 && ( cd mod6 && diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh index 94080c65d1..f48ed6d035 100755 --- a/t/t6423-merge-rename-directories.sh +++ b/t/t6423-merge-rename-directories.sh @@ -26,8 +26,6 @@ test_description="recursive merge with directory renames" # files that might be renamed into each other's paths.) . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh - ########################################################################### # SECTION 1: Basic cases we should be able to handle @@ -302,20 +300,11 @@ test_expect_success '1d: Directory renames cause a rename/rename(2to1) conflict' git cat-file -p :2:x/wham >expect && git cat-file -p :3:x/wham >other && >empty && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_must_fail git merge-file \ - -L "HEAD:y/wham" \ - -L "" \ - -L "B^0:z/wham" \ - expect empty other - else - test_must_fail git merge-file \ - -L "HEAD" \ - -L "" \ - -L "B^0" \ - expect empty other - fi && + test_must_fail git merge-file \ + -L "HEAD:y/wham" \ + -L "" \ + -L "B^0:z/wham" \ + expect empty other && test_cmp expect x/wham ) ' @@ -1186,18 +1175,10 @@ test_expect_success '5d: Directory/file/file conflict due to directory rename' ' git ls-files -u >out && test_line_count = 1 out && git ls-files -o >out && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_line_count = 1 out && - - git rev-parse >actual \ - :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d~HEAD :0:y/d/e - else - test_line_count = 2 out && - - git rev-parse >actual \ - :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d :0:y/d/e - fi && + test_line_count = 1 out && + + git rev-parse >actual \ + :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d~HEAD :0:y/d/e && git rev-parse >expect \ O:z/b O:z/c B:z/d B:z/f A:y/d B:y/d/e && test_cmp expect actual && @@ -1280,32 +1261,17 @@ test_expect_success '6a: Tricky rename/delete' ' test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_grep "CONFLICT (rename/delete).*z/c.*y/c" out && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git ls-files -s >out && - test_line_count = 3 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >actual \ - :0:y/b :1:y/c :3:y/c && - git rev-parse >expect \ - O:z/b O:z/c O:z/c - else - git ls-files -s >out && - test_line_count = 2 out && - git ls-files -u >out && - test_line_count = 1 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >actual \ - :0:y/b :3:y/c && - git rev-parse >expect \ - O:z/b O:z/c - fi && + git ls-files -s >out && + test_line_count = 3 out && + git ls-files -u >out && + test_line_count = 2 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >actual \ + :0:y/b :1:y/c :3:y/c && + git rev-parse >expect \ + O:z/b O:z/c O:z/c && test_cmp expect actual ) ' @@ -1372,7 +1338,7 @@ test_setup_6b1 () { ) } -test_expect_merge_algorithm failure success '6b1: Same renames done on both sides, plus another rename' ' +test_expect_success '6b1: Same renames done on both sides, plus another rename' ' test_setup_6b1 && ( cd 6b1 && @@ -1445,7 +1411,7 @@ test_setup_6b2 () { ) } -test_expect_merge_algorithm failure success '6b2: Same rename done on both sides' ' +test_expect_success '6b2: Same rename done on both sides' ' test_setup_6b2 && ( cd 6b2 && @@ -1832,20 +1798,11 @@ test_expect_success '7b: rename/rename(2to1), but only due to transitive rename' git cat-file -p :2:y/d >expect && git cat-file -p :3:y/d >other && >empty && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_must_fail git merge-file \ - -L "HEAD:y/d" \ - -L "" \ - -L "B^0:z/d" \ - expect empty other - else - test_must_fail git merge-file \ - -L "HEAD" \ - -L "" \ - -L "B^0" \ - expect empty other - fi && + test_must_fail git merge-file \ + -L "HEAD:y/d" \ + -L "" \ + -L "B^0:z/d" \ + expect empty other && test_cmp expect y/d ) ' @@ -1967,32 +1924,17 @@ test_expect_success '7d: transitive rename involved in rename/delete; how is it test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git ls-files -s >out && - test_line_count = 4 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >actual \ - :0:y/b :0:y/c :1:y/d :3:y/d && - git rev-parse >expect \ - O:z/b O:z/c O:x/d O:x/d - else - git ls-files -s >out && - test_line_count = 3 out && - git ls-files -u >out && - test_line_count = 1 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >actual \ - :0:y/b :0:y/c :3:y/d && - git rev-parse >expect \ - O:z/b O:z/c O:x/d - fi && + git ls-files -s >out && + test_line_count = 4 out && + git ls-files -u >out && + test_line_count = 2 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >actual \ + :0:y/b :0:y/c :1:y/d :3:y/d && + git rev-parse >expect \ + O:z/b O:z/c O:x/d O:x/d && test_cmp expect actual ) ' @@ -2073,32 +2015,17 @@ test_expect_success '7e: transitive rename in rename/delete AND dirs in the way' test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git ls-files -s >out && - test_line_count = 6 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 1 out && - - git rev-parse >actual \ - :0:x/d/f :0:y/d/g :0:y/b :0:y/c :1:y/d~B^0 :3:y/d~B^0 && - git rev-parse >expect \ - A:x/d/f A:y/d/g O:z/b O:z/c O:x/d O:x/d - else - git ls-files -s >out && - test_line_count = 5 out && - git ls-files -u >out && - test_line_count = 1 out && - git ls-files -o >out && - test_line_count = 2 out && - - git rev-parse >actual \ - :0:x/d/f :0:y/d/g :0:y/b :0:y/c :3:y/d && - git rev-parse >expect \ - A:x/d/f A:y/d/g O:z/b O:z/c O:x/d - fi && + git ls-files -s >out && + test_line_count = 6 out && + git ls-files -u >out && + test_line_count = 2 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >actual \ + :0:x/d/f :0:y/d/g :0:y/b :0:y/c :1:y/d~B^0 :3:y/d~B^0 && + git rev-parse >expect \ + A:x/d/f A:y/d/g O:z/b O:z/c O:x/d O:x/d && test_cmp expect actual && git hash-object y/d~B^0 >actual && @@ -3284,34 +3211,15 @@ test_expect_success '10b: Overwrite untracked with dir rename + delete' ' echo contents >y/e && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: The following untracked working tree files would be overwritten by merge" err && - - git ls-files -s >out && - test_line_count = 1 out && - git ls-files -u >out && - test_line_count = 0 out && - git ls-files -o >out && - test_line_count = 5 out - else - test_grep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out && - test_grep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out && - - git ls-files -s >out && - test_line_count = 3 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 5 out && - - git rev-parse >actual \ - :0:y/b :3:y/d :3:y/e && - git rev-parse >expect \ - O:z/b O:z/c B:z/e && - test_cmp expect actual - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && + + git ls-files -s >out && + test_line_count = 1 out && + git ls-files -u >out && + test_line_count = 0 out && + git ls-files -o >out && + test_line_count = 5 out && echo very >expect && test_cmp expect y/c && @@ -3374,38 +3282,15 @@ test_expect_success '10c1: Overwrite untracked with dir rename/rename(1to2)' ' echo important >y/c && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: The following untracked working tree files would be overwritten by merge" err && - - git ls-files -s >out && - test_line_count = 4 out && - git ls-files -u >out && - test_line_count = 0 out && - git ls-files -o >out && - test_line_count = 3 out - else - test_grep "CONFLICT (rename/rename)" out && - test_grep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out && - - git ls-files -s >out && - test_line_count = 6 out && - git ls-files -u >out && - test_line_count = 3 out && - git ls-files -o >out && - test_line_count = 3 out && - - git rev-parse >actual \ - :0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :3:y/c && - git rev-parse >expect \ - O:z/a O:z/b O:x/d O:x/c O:x/c O:x/c && - test_cmp expect actual && - - git hash-object y/c~B^0 >actual && - git rev-parse O:x/c >expect && - test_cmp expect actual - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && + + git ls-files -s >out && + test_line_count = 4 out && + git ls-files -u >out && + test_line_count = 0 out && + git ls-files -o >out && + test_line_count = 3 out && echo important >expect && test_cmp expect y/c @@ -3425,38 +3310,15 @@ test_expect_success '10c2: Overwrite untracked with dir rename/rename(1to2), oth echo important >y/c && test_must_fail git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: The following untracked working tree files would be overwritten by merge" err && - - git ls-files -s >out && - test_line_count = 4 out && - git ls-files -u >out && - test_line_count = 0 out && - git ls-files -o >out && - test_line_count = 3 out - else - test_grep "CONFLICT (rename/rename)" out && - test_grep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out && - - git ls-files -s >out && - test_line_count = 6 out && - git ls-files -u >out && - test_line_count = 3 out && - git ls-files -o >out && - test_line_count = 3 out && - - git rev-parse >actual \ - :0:y/a :0:y/b :0:x/d :1:x/c :3:w/c :2:y/c && - git rev-parse >expect \ - O:z/a O:z/b O:x/d O:x/c O:x/c O:x/c && - test_cmp expect actual && - - git hash-object y/c~HEAD >actual && - git rev-parse O:x/c >expect && - test_cmp expect actual - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && + + git ls-files -s >out && + test_line_count = 4 out && + git ls-files -u >out && + test_line_count = 0 out && + git ls-files -o >out && + test_line_count = 3 out && echo important >expect && test_cmp expect y/c @@ -3514,47 +3376,15 @@ test_expect_success '10d: Delete untracked with dir rename/rename(2to1)' ' echo important >y/wham && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: The following untracked working tree files would be overwritten by merge" err && - - git ls-files -s >out && - test_line_count = 6 out && - git ls-files -u >out && - test_line_count = 0 out && - git ls-files -o >out && - test_line_count = 3 out - else - test_grep "CONFLICT (rename/rename)" out && - test_grep "Refusing to lose untracked file at y/wham" out && - - git ls-files -s >out && - test_line_count = 6 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 3 out && - - git rev-parse >actual \ - :0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham && - git rev-parse >expect \ - O:z/a O:z/b O:x/d O:x/e O:z/c O:x/f && - test_cmp expect actual && - - test_must_fail git rev-parse :1:y/wham && - - # Test that two-way merge in y/wham~merged is as expected - git cat-file -p :2:y/wham >expect && - git cat-file -p :3:y/wham >other && - >empty && - test_must_fail git merge-file \ - -L "HEAD" \ - -L "" \ - -L "B^0" \ - expect empty other && - test_cmp expect y/wham~merged - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && + + git ls-files -s >out && + test_line_count = 6 out && + git ls-files -u >out && + test_line_count = 0 out && + git ls-files -o >out && + test_line_count = 3 out && echo important >expect && test_cmp expect y/wham @@ -3596,7 +3426,7 @@ test_setup_10e () { ) } -test_expect_merge_algorithm failure success '10e: Does git complain about untracked file that is not really in the way?' ' +test_expect_success '10e: Does git complain about untracked file that is not really in the way?' ' test_setup_10e && ( cd 10e && @@ -3687,30 +3517,8 @@ test_expect_success '11a: Avoid losing dirty contents with simple rename' ' echo stuff >>z/c && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: Your local changes to the following files would be overwritten by merge" err - else - test_grep "Refusing to lose dirty file at z/c" out && - - git ls-files -s >out && - test_line_count = 2 out && - git ls-files -u >out && - test_line_count = 1 out && - git ls-files -o >out && - test_line_count = 3 out && - - git rev-parse >actual \ - :0:z/a :2:z/c && - git rev-parse >expect \ - O:z/a B:z/b && - test_cmp expect actual && - - git hash-object z/c~HEAD >actual && - git rev-parse B:z/b >expect && - test_cmp expect actual - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: Your local changes to the following files would be overwritten by merge" err && test_seq 1 10 >expected && echo stuff >>expected && @@ -3766,34 +3574,9 @@ test_expect_success '11b: Avoid losing dirty file involved in directory rename' git checkout A^0 && echo stuff >>z/c && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: Your local changes to the following files would be overwritten by merge" err - else - git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_grep "Refusing to lose dirty file at z/c" out && - - git ls-files -s >out && - test_line_count = 3 out && - git ls-files -u >out && - test_line_count = 0 out && - git ls-files -m >out && - test_line_count = 0 out && - git ls-files -o >out && - test_line_count = 3 out && - - git rev-parse >actual \ - :0:x/b :0:y/a :0:y/c && - git rev-parse >expect \ - O:x/b O:z/a B:x/c && - test_cmp expect actual && - - git hash-object y/c >actual && - git rev-parse B:x/c >expect && - test_cmp expect actual - fi && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: Your local changes to the following files would be overwritten by merge" err && grep -q stuff z/c && test_seq 1 10 >expected && @@ -3850,13 +3633,8 @@ test_expect_success '11c: Avoid losing not-uptodate with rename + D/F conflict' echo stuff >>y/c && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: Your local changes to the following files would be overwritten by merge" err - else - test_grep "following files would be overwritten by merge" err - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: Your local changes to the following files would be overwritten by merge" err && grep -q stuff y/c && test_seq 1 10 >expected && @@ -3924,30 +3702,8 @@ test_expect_success '11d: Avoid losing not-uptodate with rename + D/F conflict' echo stuff >>z/c && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: Your local changes to the following files would be overwritten by merge" err - else - test_grep "Refusing to lose dirty file at z/c" out && - - git ls-files -s >out && - test_line_count = 4 out && - git ls-files -u >out && - test_line_count = 1 out && - git ls-files -o >out && - test_line_count = 4 out && - - git rev-parse >actual \ - :0:x/b :0:y/a :0:y/c/d :3:y/c && - git rev-parse >expect \ - O:x/b O:z/a B:y/c/d B:x/c && - test_cmp expect actual && - - git hash-object y/c~HEAD >actual && - git rev-parse B:x/c >expect && - test_cmp expect actual - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: Your local changes to the following files would be overwritten by merge" err && grep -q stuff z/c && test_seq 1 10 >expected && @@ -4010,39 +3766,8 @@ test_expect_success '11e: Avoid deleting not-uptodate with dir rename/rename(1to echo mods >>y/c && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: Your local changes to the following files would be overwritten by merge" err - else - test_grep "CONFLICT (rename/rename)" out && - test_grep "Refusing to lose dirty file at y/c" out && - - git ls-files -s >out && - test_line_count = 7 out && - git ls-files -u >out && - test_line_count = 4 out && - git ls-files -o >out && - test_line_count = 3 out && - - git rev-parse >actual \ - :0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :2:y/c :3:y/c && - git rev-parse >expect \ - O:z/a O:z/b O:x/d O:x/c O:x/c A:y/c O:x/c && - test_cmp expect actual && - - # See if y/c~merged has expected contents; requires manually - # doing the expected file merge - git cat-file -p A:y/c >c1 && - git cat-file -p B:z/c >c2 && - >empty && - test_must_fail git merge-file \ - -L "HEAD" \ - -L "" \ - -L "B^0" \ - c1 empty c2 && - test_cmp c1 y/c~merged - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: Your local changes to the following files would be overwritten by merge" err && echo different >expected && echo mods >>expected && @@ -4099,40 +3824,8 @@ test_expect_success '11f: Avoid deleting not-uptodate with dir rename/rename(2to echo important >>y/wham && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_path_is_missing .git/MERGE_HEAD && - test_grep "error: Your local changes to the following files would be overwritten by merge" err - else - test_grep "CONFLICT (rename/rename)" out && - test_grep "Refusing to lose dirty file at y/wham" out && - - git ls-files -s >out && - test_line_count = 4 out && - git ls-files -u >out && - test_line_count = 2 out && - git ls-files -o >out && - test_line_count = 3 out && - - test_must_fail git rev-parse :1:y/wham && - - git rev-parse >actual \ - :0:y/a :0:y/b :2:y/wham :3:y/wham && - git rev-parse >expect \ - O:z/a O:z/b O:x/c O:x/d && - test_cmp expect actual && - - # Test that two-way merge in y/wham~merged is as expected - git cat-file -p :2:y/wham >expect && - git cat-file -p :3:y/wham >other && - >empty && - test_must_fail git merge-file \ - -L "HEAD" \ - -L "" \ - -L "B^0" \ - expect empty other && - test_cmp expect y/wham~merged - fi && + test_path_is_missing .git/MERGE_HEAD && + test_grep "error: Your local changes to the following files would be overwritten by merge" err && test_seq 1 10 >expected && echo important >>expected && @@ -4267,7 +3960,7 @@ test_setup_12b1 () { ) } -test_expect_merge_algorithm failure success '12b1: Moving two directory hierarchies into each other' ' +test_expect_success '12b1: Moving two directory hierarchies into each other' ' test_setup_12b1 && ( cd 12b1 && @@ -4435,7 +4128,7 @@ test_setup_12c1 () { ) } -test_expect_merge_algorithm failure success '12c1: Moving one directory hierarchy into another w/ content merge' ' +test_expect_success '12c1: Moving one directory hierarchy into another w/ content merge' ' test_setup_12c1 && ( cd 12c1 && @@ -4797,7 +4490,7 @@ test_setup_12f () { ) } -test_expect_merge_algorithm failure success '12f: Trivial directory resolve, caching, all kinds of fun' ' +test_expect_success '12f: Trivial directory resolve, caching, all kinds of fun' ' test_setup_12f && ( cd 12f && @@ -5253,7 +4946,7 @@ test_setup_12l () { ) } -test_expect_merge_algorithm failure success '12l (B into A): Rename into each other + add/add conflict' ' +test_expect_success '12l (B into A): Rename into each other + add/add conflict' ' test_setup_12l BintoA && ( cd 12l_BintoA && @@ -5280,7 +4973,7 @@ test_expect_merge_algorithm failure success '12l (B into A): Rename into each ot ) ' -test_expect_merge_algorithm failure success '12l (A into B): Rename into each other + add/add conflict' ' +test_expect_success '12l (A into B): Rename into each other + add/add conflict' ' test_setup_12l AintoB && ( cd 12l_AintoB && @@ -5348,7 +5041,7 @@ test_setup_12m () { ) } -test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir to symlink on other side' ' +test_expect_success '12m: Change parent of renamed-dir to symlink on other side' ' test_setup_12m && ( cd 12m && @@ -5363,6 +5056,47 @@ test_expect_merge_algorithm failure success '12m: Change parent of renamed-dir t ) ' +test_setup_12n () { + git init 12n && + ( + cd 12n && + + mkdir tools && + echo hello >tools/hello && + git add tools/hello && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git switch A && + echo world >world && + git add world && + git commit -q world -m 'Add world' && + + git mv world tools/world && + git commit -m "Move world into tools/" && + + git switch B && + git mv tools/hello hello && + git commit -m "Move hello from tools/ to toplevel" + ) +} + +test_expect_success '12n: Directory rename transitively makes rename back to self' ' + test_setup_12n && + ( + cd 12n && + + git checkout -q B^0 && + + test_must_fail git cherry-pick A^0 >out && + grep "CONFLICT (file location).*should perhaps be moved" out + ) +' + + ########################################################################### # SECTION 13: Checking informational and conflict messages # @@ -5549,9 +5283,9 @@ test_expect_success '13b(info): messages for transitive rename with conflicted c # Commit A: y/{b,c,d}, x/e # Commit B: z/{b,c,d}, x/e # Expected: y/{b,c,d}, x/e, with info or conflict messages for d -# A: renamed x/d -> z/d; B: renamed z/ -> y/ AND renamed x/d to y/d -# One could argue A had partial knowledge of what was done with -# d and B had full knowledge, but that's a slippery slope as +# B: renamed x/d -> z/d; A: renamed z/ -> y/ AND renamed x/d to y/d +# One could argue B had partial knowledge of what was done with +# d and A had full knowledge, but that's a slippery slope as # shown in testcase 13d. test_setup_13c () { diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh index 7677c5f08d..ddc7524f6c 100755 --- a/t/t6424-merge-unrelated-index-changes.sh +++ b/t/t6424-merge-unrelated-index-changes.sh @@ -176,9 +176,11 @@ test_expect_success 'merge-recursive, when index==head but head!=HEAD' ' # Make index match B git diff C B -- | git apply --cached && test_when_finished "git clean -fd" && # Do not leave untracked around + git write-tree >index-before && # Merge B & F, with B as "head" git merge-recursive A -- B F > out && - test_grep "Already up to date" out + git write-tree >index-after && + test_cmp index-before index-after ' test_expect_success 'recursive, when file has staged changes not matching HEAD nor what a merge would give' ' @@ -294,10 +296,8 @@ test_expect_success 'with multiple strategies, recursive or ort failure do not e git add a && git rev-parse :a >expect && - sane_unset GIT_TEST_MERGE_ALGORITHM && - test_must_fail git merge -s recursive -s ort -s octopus C^0 >output 2>&1 && + test_must_fail git merge -s ort -s octopus C^0 >output 2>&1 && - grep "Trying merge strategy recursive..." output && grep "Trying merge strategy ort..." output && grep "Trying merge strategy octopus..." output && grep "No merge strategy handled the merge." output && diff --git a/t/t6426-merge-skip-unneeded-updates.sh b/t/t6426-merge-skip-unneeded-updates.sh index b059475ed0..404cd3f2ca 100755 --- a/t/t6426-merge-skip-unneeded-updates.sh +++ b/t/t6426-merge-skip-unneeded-updates.sh @@ -23,8 +23,6 @@ test_description="merge cases" # files that might be renamed into each other's paths.) . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh - ########################################################################### # SECTION 1: Cases involving no renames (one side has subset of changes of @@ -663,7 +661,7 @@ test_setup_4a () { # correct requires doing the merge in-memory first, then realizing that no # updates to the file are necessary, and thus that we can just leave the path # alone. -test_expect_merge_algorithm failure success '4a: Change on A, change on B subset of A, dirty mods present' ' +test_expect_success '4a: Change on A, change on B subset of A, dirty mods present' ' test_setup_4a && ( cd 4a && diff --git a/t/t6427-diff3-conflict-markers.sh b/t/t6427-diff3-conflict-markers.sh index dd5fe6a402..57569c4f4b 100755 --- a/t/t6427-diff3-conflict-markers.sh +++ b/t/t6427-diff3-conflict-markers.sh @@ -207,7 +207,7 @@ test_expect_success 'rebase --apply describes fake ancestor base' ' cd rebase && git rebase --abort && test_must_fail git -c merge.conflictstyle=diff3 rebase --apply main && - grep "||||||| constructed merge base" file + grep "||||||| constructed fake ancestor" file ) ' diff --git a/t/t6428-merge-conflicts-sparse.sh b/t/t6428-merge-conflicts-sparse.sh index 9919c3fa7c..c86e02c6e2 100755 --- a/t/t6428-merge-conflicts-sparse.sh +++ b/t/t6428-merge-conflicts-sparse.sh @@ -23,8 +23,6 @@ test_description="merge cases" # files that might be renamed into each other's paths.) . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh - # Testcase basic, conflicting changes in 'numerals' diff --git a/t/t6430-merge-recursive.sh b/t/t6430-merge-recursive.sh index ca15e6dd6d..e59560a5dd 100755 --- a/t/t6430-merge-recursive.sh +++ b/t/t6430-merge-recursive.sh @@ -6,7 +6,6 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh test_expect_success 'setup 1' ' @@ -373,9 +372,9 @@ test_expect_success 'merge-recursive d/f conflict result' ' git ls-files -s >actual && ( - echo "100644 $o0 1 a" && - echo "100644 $o1 2 a" && echo "100644 $o4 0 a/c" && + echo "100644 $o0 1 a~$c1" && + echo "100644 $o1 2 a~$c1" && echo "100644 $o0 0 b" && echo "100644 $o0 0 c" && echo "100644 $o1 0 d/e" @@ -397,9 +396,9 @@ test_expect_success 'merge-recursive d/f conflict result the other way' ' git ls-files -s >actual && ( - echo "100644 $o0 1 a" && - echo "100644 $o1 3 a" && echo "100644 $o4 0 a/c" && + echo "100644 $o0 1 a~$c1" && + echo "100644 $o1 3 a~$c1" && echo "100644 $o0 0 b" && echo "100644 $o0 0 c" && echo "100644 $o1 0 d/e" @@ -424,9 +423,9 @@ test_expect_success 'merge-recursive d/f conflict result' ' echo "100644 $o1 0 a" && echo "100644 $o0 0 b" && echo "100644 $o0 0 c" && - echo "100644 $o6 3 d" && echo "100644 $o0 1 d/e" && - echo "100644 $o1 2 d/e" + echo "100644 $o1 2 d/e" && + echo "100644 $o6 3 d~$c6" ) >expected && test_cmp expected actual @@ -448,9 +447,9 @@ test_expect_success 'merge-recursive d/f conflict result' ' echo "100644 $o1 0 a" && echo "100644 $o0 0 b" && echo "100644 $o0 0 c" && - echo "100644 $o6 2 d" && echo "100644 $o0 1 d/e" && - echo "100644 $o1 3 d/e" + echo "100644 $o1 3 d/e" && + echo "100644 $o6 2 d~$c6" ) >expected && test_cmp expected actual @@ -645,7 +644,7 @@ test_expect_success 'merge-recursive copy vs. rename' ' test_cmp expected actual ' -test_expect_merge_algorithm failure success 'merge-recursive rename vs. rename/symlink' ' +test_expect_success 'merge-recursive rename vs. rename/symlink' ' git checkout -f rename && git merge rename-ln && @@ -696,33 +695,6 @@ test_expect_success 'merging with triple rename across D/F conflict' ' git merge other ' -test_expect_success 'merge-recursive remembers the names of all base trees' ' - git reset --hard HEAD && - - # make the index match $c1 so that merge-recursive below does not - # fail early - git diff --binary HEAD $c1 -- | git apply --cached && - - # more trees than static slots used by oid_to_hex() - for commit in $c0 $c2 $c4 $c5 $c6 $c7 - do - git rev-parse "$commit^{tree}" || return 1 - done >trees && - - # ignore the return code; it only fails because the input is weird... - test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out && - - # ...but make sure it fails in the expected way - test_grep CONFLICT.*rename/rename out && - - # merge-recursive prints in reverse order, but we do not care - sort <trees >expect && - sed -n "s/^virtual //p" out | sort >actual && - test_cmp expect actual && - - git clean -fd -' - test_expect_success 'merge-recursive internal merge resolves to the sameness' ' git reset --hard HEAD && diff --git a/t/t6434-merge-recursive-rename-options.sh b/t/t6434-merge-recursive-rename-options.sh index 6e913c30a1..5a6f74839c 100755 --- a/t/t6434-merge-recursive-rename-options.sh +++ b/t/t6434-merge-recursive-rename-options.sh @@ -34,7 +34,9 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME get_expected_stages () { git checkout rename -- $1-new && git ls-files --stage $1-new >expected-stages-undetected-$1 && - sed "s/ 0 / 2 /" <expected-stages-undetected-$1 \ + git ls-tree HEAD^ $1-old >tmp && + git ls-tree HEAD $1-new >>tmp && + cat tmp | awk '{print $1 " " $3 " " NR "\t" '$1'"-new"}' \ >expected-stages-detected-$1 && git read-tree -u --reset HEAD } @@ -51,11 +53,11 @@ rename_undetected () { check_common () { git ls-files --stage >stages-actual && - test_line_count = 4 stages-actual + test_line_count = $1 stages-actual } check_threshold_0 () { - check_common && + check_common 8 && rename_detected 0 && rename_detected 1 && rename_detected 2 && @@ -63,7 +65,7 @@ check_threshold_0 () { } check_threshold_1 () { - check_common && + check_common 7 && rename_undetected 0 && rename_detected 1 && rename_detected 2 && @@ -71,7 +73,7 @@ check_threshold_1 () { } check_threshold_2 () { - check_common && + check_common 6 && rename_undetected 0 && rename_undetected 1 && rename_detected 2 && @@ -79,7 +81,7 @@ check_threshold_2 () { } check_exact_renames () { - check_common && + check_common 5 && rename_undetected 0 && rename_undetected 1 && rename_undetected 2 && @@ -87,7 +89,7 @@ check_exact_renames () { } check_no_renames () { - check_common && + check_common 4 && rename_undetected 0 && rename_undetected 1 && rename_undetected 2 && diff --git a/t/t6436-merge-overwrite.sh b/t/t6436-merge-overwrite.sh index 4f4376421e..70b5d2d694 100755 --- a/t/t6436-merge-overwrite.sh +++ b/t/t6436-merge-overwrite.sh @@ -101,19 +101,10 @@ test_expect_success 'will not overwrite unstaged changes in renamed file' ' git mv c1.c other.c && git commit -m rename && cp important other.c && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - test_must_fail git merge c1a >out 2>err && - test_grep "would be overwritten by merge" err && - test_cmp important other.c && - test_path_is_missing .git/MERGE_HEAD - else - test_must_fail git merge c1a >out && - test_grep "Refusing to lose dirty file at other.c" out && - test_path_is_file other.c~HEAD && - test $(git hash-object other.c~HEAD) = $(git rev-parse c1a:c1.c) && - test_cmp important other.c - fi + test_must_fail git merge c1a >out 2>err && + test_grep "would be overwritten by merge" err && + test_cmp important other.c && + test_path_is_missing .git/MERGE_HEAD ' test_expect_success 'will not overwrite untracked subtree' ' diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh index 4815559157..a564758f52 100755 --- a/t/t6437-submodule-merge.sh +++ b/t/t6437-submodule-merge.sh @@ -9,7 +9,6 @@ GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-merge.sh # # history @@ -110,14 +109,10 @@ test_expect_success 'merging should conflict for non fast-forward' ' test_when_finished "git -C merge-search reset --hard" && (cd merge-search && git checkout -b test-nonforward-a b && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - 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 - test_must_fail git merge c 2> actual - fi) + 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 + ) ' test_expect_success 'finish setup for merge-search' ' @@ -151,14 +146,9 @@ test_expect_success 'merging should conflict for non fast-forward (resolution ex git checkout -b test-nonforward-b b && (cd sub && git rev-parse --short sub-d > ../expect) && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - 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" sub-actual - else - test_must_fail git merge c 2> actual - fi && + 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" sub-actual && grep $(cat expect) actual > /dev/null && git reset --hard) ' @@ -169,23 +159,12 @@ test_expect_success 'merging should fail for ambiguous common parent' ' (cd sub && git checkout -b ambiguous sub-b && git merge sub-c && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - git rev-parse --short sub-d >../expect1 && - git rev-parse --short ambiguous >../expect2 - else - git rev-parse sub-d > ../expect1 && - git rev-parse ambiguous > ../expect2 - fi + git rev-parse --short sub-d >../expect1 && + git rev-parse --short ambiguous >../expect2 ) && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - 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" sub-actual - else - test_must_fail git merge c 2> actual - fi && + 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" sub-actual && grep $(cat expect1) actual > /dev/null && grep $(cat expect2) actual > /dev/null && git reset --hard) @@ -227,11 +206,9 @@ test_expect_success 'merging should fail for changes that are backwards' ' git checkout -b test-backward e && 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)" && - grep "$sub_expect" actual - fi) + sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" && + grep "$sub_expect" actual + ) ' @@ -358,7 +335,7 @@ test_expect_success 'setup file/submodule conflict' ' ) ' -test_expect_merge_algorithm failure success 'file/submodule conflict' ' +test_expect_success 'file/submodule conflict' ' test_when_finished "git -C file-submodule reset --hard" && ( cd file-submodule && @@ -467,7 +444,7 @@ test_expect_failure 'directory/submodule conflict; keep submodule clean' ' ) ' -test_expect_merge_algorithm failure success !FAIL_PREREQS 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' +test_expect_success !FAIL_PREREQS 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' test_when_finished "git -C directory-submodule/path reset --hard" && test_when_finished "git -C directory-submodule reset --hard" && ( @@ -535,11 +512,9 @@ test_expect_success 'merging should fail with no merge base' ' git add sub && git commit -m "b" && 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)" && - grep "$sub_expect" actual - fi) + sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" && + grep "$sub_expect" actual + ) ' test_done diff --git a/t/t6438-submodule-directory-file-conflicts.sh b/t/t6438-submodule-directory-file-conflicts.sh index 8df67a0ef9..53d83c828a 100755 --- a/t/t6438-submodule-directory-file-conflicts.sh +++ b/t/t6438-submodule-directory-file-conflicts.sh @@ -12,11 +12,6 @@ test_submodule_switch "merge --ff" test_submodule_switch "merge --ff-only" -if test "$GIT_TEST_MERGE_ALGORITHM" != ort -then - KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 - KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 -fi test_submodule_switch "merge --no-ff" test_done diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh index 55bd744a3f..643c9368e0 100755 --- a/t/t6439-merge-co-error-msgs.sh +++ b/t/t6439-merge-co-error-msgs.sh @@ -47,7 +47,7 @@ test_expect_success 'untracked files overwritten by merge (fast and non-fast for export GIT_MERGE_VERBOSITY && test_must_fail git merge branch 2>out2 ) && - echo "Merge with strategy ${GIT_TEST_MERGE_ALGORITHM:-ort} failed." >>expect && + echo "Merge with strategy ort failed." >>expect && test_cmp out2 expect && git reset --hard HEAD^ ' diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh index c89b0f1e19..56bd1e3c5b 100755 --- a/t/t6601-path-walk.sh +++ b/t/t6601-path-walk.sh @@ -1,7 +1,5 @@ #!/bin/sh -TEST_PASSES_SANITIZE_LEAK=true - test_description='direct path-walk API tests' . ./test-lib.sh @@ -378,6 +376,26 @@ test_expect_success 'topic, not base, boundary with pruning' ' test_cmp_sorted expect out ' +test_expect_success 'topic, not base, --edge-aggressive with pruning' ' + test-tool path-walk --prune --edge-aggressive -- topic --not base >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 1:tree::$(git rev-parse topic^{tree}) + 1:tree::$(git rev-parse base^{tree}):UNINTERESTING + 2:tree:right/:$(git rev-parse topic:right) + 2:tree:right/:$(git rev-parse base:right):UNINTERESTING + 3:blob:right/c:$(git rev-parse base:right/c):UNINTERESTING + 3:blob:right/c:$(git rev-parse topic:right/c) + blobs:2 + commits:1 + tags:0 + trees:4 + EOF + + test_cmp_sorted expect out +' + test_expect_success 'trees are reported exactly once' ' test_when_finished "rm -rf unique-trees" && test_create_repo unique-trees && diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index 25334b5062..920479e925 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -550,16 +550,32 @@ test_expect_success 'moving nested submodules' ' git status ' -test_expect_failure 'nonsense mv triggers assertion failure and partially updated index' ' +test_expect_success 'moving file and its parent directory at the same time fails' ' test_when_finished git reset --hard HEAD && git reset --hard HEAD && mkdir -p a && mkdir -p b && >a/a.txt && git add a/a.txt && - test_must_fail git mv a/a.txt a b && - git status --porcelain >actual && - grep "^A[ ]*a/a.txt$" actual + cat >expect <<-EOF && + fatal: cannot move both ${SQ}a/a.txt${SQ} and its parent directory ${SQ}a${SQ} + EOF + test_must_fail git mv a/a.txt a b 2>err && + test_cmp expect err +' + +test_expect_success 'moving nested directory and its parent directory at the same time fails' ' + test_when_finished git reset --hard HEAD && + git reset --hard HEAD && + mkdir -p a/b/c && + >a/b/c/file.txt && + git add a && + mkdir target && + cat >expect <<-EOF && + fatal: cannot move both ${SQ}a/b/c${SQ} and its parent directory ${SQ}a${SQ} + EOF + test_must_fail git mv a/b/c a target 2>err && + test_cmp expect err ' test_done diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index 932c26cb45..9717e825f0 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -662,9 +662,9 @@ test_expect_success 'setup trace2' ' ' test_expect_success 'setup large log output' ' - perl -e " - print \"this is a long commit message\" x 50000 - " >commit-msg && + test-tool genzeros 50000 | + tr "\000" "a" | + sed "s/a/this is a long commit message/g" >commit-msg && git commit --allow-empty -F commit-msg ' diff --git a/t/t7007-show.sh b/t/t7007-show.sh index d6cc69e0f2..2d322b53d1 100755 --- a/t/t7007-show.sh +++ b/t/t7007-show.sh @@ -167,4 +167,28 @@ test_expect_success 'show --graph is forbidden' ' test_must_fail git show --graph HEAD ' +test_expect_success 'show unmerged index' ' + git reset --hard && + + git switch -C base && + echo "base" >conflicting && + git add conflicting && + git commit -m "base" && + + git branch hello && + git branch goodbye && + + git switch hello && + echo "hello" >conflicting && + git commit -am "hello" && + + git switch goodbye && + echo "goodbye" >conflicting && + git commit -am "goodbye" && + + git switch hello && + test_must_fail git merge goodbye && + git show --merge HEAD +' + test_done diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh index 6f526c37c2..2c147072c1 100755 --- a/t/t7030-verify-tag.sh +++ b/t/t7030-verify-tag.sh @@ -7,6 +7,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY/lib-gpg.sh" +test_expect_success GPG 'verify-tag does not crash with -h' ' + test_expect_code 129 git verify-tag -h >usage && + test_grep "[Uu]sage: git verify-tag " usage && + test_expect_code 129 nongit git verify-tag -h >usage && + test_grep "[Uu]sage: git verify-tag " usage +' + test_expect_success GPG 'create signed tags' ' echo 1 >file && git add file && test_tick && git commit -m initial && diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh index 9c3cc4cf40..66c3ec2da2 100755 --- a/t/t7401-submodule-summary.sh +++ b/t/t7401-submodule-summary.sh @@ -38,10 +38,11 @@ commit_file () { git commit "$@" -m "Commit $*" >/dev/null } -test_create_repo sm1 && -add_file . foo >/dev/null - -head1=$(add_file sm1 foo1 foo2) +test_expect_success 'setup submodule' ' + git init sm1 && + add_file . foo && + head1=$(add_file sm1 foo1 foo2) +' test_expect_success 'added submodule' " git add sm1 && @@ -214,9 +215,12 @@ test_expect_success 'typechanged submodule(submodule->blob)' " test_cmp expected actual " -rm -f sm1 && -test_create_repo sm1 && -head6=$(add_file sm1 foo6 foo7) +test_expect_success 'setup submodule' ' + rm -f sm1 && + git init sm1 && + head6=$(add_file sm1 foo6 foo7) +' + test_expect_success 'nonexistent commit' " git submodule summary >actual && cat >expected <<-EOF && diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh index 25b33a1e87..06cee3432f 100755 --- a/t/t7402-submodule-rebase.sh +++ b/t/t7402-submodule-rebase.sh @@ -124,11 +124,8 @@ test_expect_success 'rebasing submodule that should conflict' ' echo "160000 $(git rev-parse HEAD) 3 submodule" ) >expect && test_cmp expect actual && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - sub_expect="go to submodule (submodule), and either merge commit $(git -C submodule rev-parse --short HEAD^0)" && - grep "$sub_expect" actual_output - fi + sub_expect="go to submodule (submodule), and either merge commit $(git -C submodule rev-parse --short HEAD^0)" && + grep "$sub_expect" actual_output ' test_done diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index c562bad042..ab76d4b6dc 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -1095,12 +1095,15 @@ test_expect_success 'submodule update --quiet passes quietness to fetch with a s (cd super5 && # This test var can mess with the stderr output checked in this test. GIT_TEST_NAME_HASH_VERSION=1 \ + GIT_TEST_PACK_PATH_WALK=0 \ git submodule update --quiet --init --depth=1 submodule3 >out 2>err && test_must_be_empty out && test_must_be_empty err ) && git clone super4 super6 && (cd super6 && + # This test variable will create a "warning" message to stderr + GIT_TEST_PACK_PATH_WALK=0 \ git submodule update --init --depth=1 submodule3 >out 2>err && test_file_not_empty out && test_file_not_empty err diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh index 0c605fd271..3d944a00e0 100755 --- a/t/t7416-submodule-dash-url.sh +++ b/t/t7416-submodule-dash-url.sh @@ -33,7 +33,8 @@ test_expect_success 'fsck accepts protected dash' ' ' test_expect_success 'remove ./ protection from .gitmodules url' ' - perl -i -pe "s{\./}{}" .gitmodules && + sed "s|\./||" .gitmodules >.gitmodules.munged && + mv .gitmodules.munged .gitmodules && git commit -am "drop protection" ' diff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh index cc12f99f11..a37509f004 100755 --- a/t/t7501-commit-basic-functionality.sh +++ b/t/t7501-commit-basic-functionality.sh @@ -46,7 +46,7 @@ test_expect_success 'paths and -a do not mix' ' test_must_fail git commit -m foo -a file ' -test_expect_success PERL 'can use paths with --interactive' ' +test_expect_success 'can use paths with --interactive' ' echo bong-o-bong >file && # 2: update, 1:st path, that is all, 7: quit test_write_lines 2 1 "" 7 | @@ -345,12 +345,12 @@ test_expect_success 'overriding author from command line' ' grep Rubber.Duck output ' -test_expect_success PERL 'interactive add' ' +test_expect_success 'interactive add' ' echo 7 | test_must_fail git commit --interactive >out && grep "What now" out ' -test_expect_success PERL "commit --interactive doesn't change index if editor aborts" ' +test_expect_success "commit --interactive doesn't change index if editor aborts" ' echo zoo >file && test_must_fail git diff --exit-code >diff1 && test_write_lines u "*" q | diff --git a/t/t7508-status.sh b/t/t7508-status.sh index b2070d4e39..cdc1d6fcc7 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -1066,7 +1066,7 @@ test_expect_success 'status -s submodule summary (clean submodule)' ' test_expect_success 'status -z implies porcelain' ' git status --porcelain | - perl -pe "s/\012/\000/g" >expect && + tr "\012" "\000" >expect && git status -z >output && test_cmp expect output ' diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 0d2dd29fe6..39677e859a 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -8,6 +8,13 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GNUPGHOME_NOT_USED=$GNUPGHOME . "$TEST_DIRECTORY/lib-gpg.sh" +test_expect_success GPG 'verify-commit does not crash with -h' ' + test_expect_code 129 git verify-commit -h >usage && + test_grep "[Uu]sage: git verify-commit " usage && + test_expect_code 129 nongit git verify-commit -h >usage && + test_grep "[Uu]sage: git verify-commit " usage +' + test_expect_success GPG 'create signed commits' ' test_oid_cache <<-\EOF && header sha1:gpgsig diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index 802f8f704c..25e8e9711f 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -139,7 +139,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last command done (1 command done): - pick $LAST_COMMIT one_second + pick $LAST_COMMIT # one_second No commands remaining. You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''. (fix conflicts and then run "git rebase --continue") @@ -168,7 +168,7 @@ test_expect_success 'status during rebase -i after resolving conflicts' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last command done (1 command done): - pick $LAST_COMMIT one_second + pick $LAST_COMMIT # one_second No commands remaining. You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''. (all conflicts fixed: run "git rebase --continue") @@ -200,8 +200,8 @@ test_expect_success 'status when rebasing -i in edit mode' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - pick $COMMIT2 two_rebase_i - edit $COMMIT3 three_rebase_i + pick $COMMIT2 # two_rebase_i + edit $COMMIT3 # three_rebase_i No commands remaining. You are currently editing a commit while rebasing branch '\''rebase_i_edit'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -233,10 +233,10 @@ test_expect_success 'status when splitting a commit' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - pick $COMMIT2 two_split - edit $COMMIT3 three_split + pick $COMMIT2 # two_split + edit $COMMIT3 # three_split Next command to do (1 remaining command): - pick $COMMIT4 four_split + pick $COMMIT4 # four_split (use "git rebase --edit-todo" to view and edit) You are currently splitting a commit while rebasing branch '\''split_commit'\'' on '\''$ONTO'\''. (Once your working directory is clean, run "git rebase --continue") @@ -271,8 +271,8 @@ test_expect_success 'status after editing the last commit with --amend during a cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (3 commands done): - pick $COMMIT3 three_amend - edit $COMMIT4 four_amend + pick $COMMIT3 # three_amend + edit $COMMIT4 # four_amend (see more in file .git/rebase-merge/done) No commands remaining. You are currently editing a commit while rebasing branch '\''amend_last'\'' on '\''$ONTO'\''. @@ -309,10 +309,10 @@ test_expect_success 'status: (continue first edit) second edit' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -340,10 +340,10 @@ test_expect_success 'status: (continue first edit) second edit and split' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (Once your working directory is clean, run "git rebase --continue") @@ -375,10 +375,10 @@ test_expect_success 'status: (continue first edit) second edit and amend' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -406,10 +406,10 @@ test_expect_success 'status: (amend first edit) second edit' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -438,10 +438,10 @@ test_expect_success 'status: (amend first edit) second edit and split' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (Once your working directory is clean, run "git rebase --continue") @@ -474,10 +474,10 @@ test_expect_success 'status: (amend first edit) second edit and amend' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -507,10 +507,10 @@ test_expect_success 'status: (split first edit) second edit' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -541,10 +541,10 @@ test_expect_success 'status: (split first edit) second edit and split' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (Once your working directory is clean, run "git rebase --continue") @@ -579,10 +579,10 @@ test_expect_success 'status: (split first edit) second edit and amend' ' cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - edit $COMMIT2 two_edits - edit $COMMIT3 three_edits + edit $COMMIT2 # two_edits + edit $COMMIT3 # three_edits Next command to do (1 remaining command): - pick $COMMIT4 four_edits + pick $COMMIT4 # four_edits (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -997,11 +997,11 @@ test_expect_success 'status: two commands done with some white lines in done fil cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (2 commands done): - pick $COMMIT2 two_commit + pick $COMMIT2 # two_commit exec exit 15 Next commands to do (2 remaining commands): - pick $COMMIT3 three_commit - pick $COMMIT4 four_commit + pick $COMMIT3 # three_commit + pick $COMMIT4 # four_commit (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_commits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -1025,12 +1025,12 @@ test_expect_success 'status: two remaining commands with some white lines in tod cat >expected <<EOF && interactive rebase in progress; onto $ONTO Last commands done (3 commands done): - pick $COMMIT2 two_commit + pick $COMMIT2 # two_commit exec exit 15 (see more in file .git/rebase-merge/done) Next commands to do (2 remaining commands): - pick $COMMIT3 three_commit - pick $COMMIT4 four_commit + pick $COMMIT3 # three_commit + pick $COMMIT4 # four_commit (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_commits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) @@ -1050,7 +1050,7 @@ test_expect_success 'status: handle not-yet-started rebase -i gracefully' ' On branch several_commits No commands done. Next command to do (1 remaining command): - pick $COMMIT four_commit + pick $COMMIT # four_commit (use "git rebase --edit-todo" to view and edit) You are currently editing a commit while rebasing branch '\''several_commits'\'' on '\''$ONTO'\''. (use "git commit --amend" to amend the current commit) diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh index ff085b086c..42f675b739 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -77,12 +77,9 @@ Merge made by the 'recursive' strategy. EOF test_expect_success 'merge reduces irrelevant remote heads' ' - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - mv expected expected.tmp && - sed s/recursive/ort/ expected.tmp >expected && - rm expected.tmp - fi && + mv expected expected.tmp && + sed s/recursive/ort/ expected.tmp >expected && + rm expected.tmp && GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual && test_cmp expected actual ' diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index c077aba7ce..957f8e20ba 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -535,14 +535,9 @@ test_expect_success 'file vs modified submodule' ' yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && yes "" | git mergetool both && yes "d" | git mergetool file11 file12 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - yes "c" | git mergetool submod~HEAD && - git rm submod && - git mv submod~HEAD submod - else - yes "l" | git mergetool submod - fi && + yes "c" | git mergetool submod~HEAD && + git rm submod && + git mv submod~HEAD submod && git submodule update -N && echo "not a submodule" >expect && test_cmp expect submod && @@ -559,15 +554,10 @@ test_expect_success 'file vs modified submodule' ' yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && yes "" | git mergetool both && yes "d" | git mergetool file11 file12 && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - mv submod submod.orig && - git rm --cached submod && - yes "c" | git mergetool submod~test19 && - git mv submod~test19 submod - else - yes "r" | git mergetool submod - fi && + mv submod submod.orig && + git rm --cached submod && + yes "c" | git mergetool submod~test19 && + git mv submod~test19 submod && test -d submod.orig && git submodule update -N && echo "not a submodule" >expect && @@ -585,10 +575,7 @@ test_expect_success 'file vs modified submodule' ' yes "" | git mergetool both && yes "d" | git mergetool file11 file12 && yes "l" | git mergetool submod && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - yes "d" | git mergetool submod~test19 - fi && + yes "d" | git mergetool submod~test19 && echo "main submodule" >expect && test_cmp expect submod/bar && git submodule update -N && @@ -686,14 +673,9 @@ test_expect_success 'directory vs modified submodule' ' test_must_fail git merge main && test -n "$(git ls-files -u)" && test ! -e submod.orig && - if test "$GIT_TEST_MERGE_ALGORITHM" = ort - then - yes "r" | git mergetool submod~main && - git mv submod submod.orig && - git mv submod~main submod - else - yes "r" | git mergetool submod - fi && + yes "r" | git mergetool submod~main && + git mv submod submod.orig && + git mv submod~main submod && test -d submod.orig && echo "not a submodule" >expect && test_cmp expect submod.orig/file16 && diff --git a/t/t7615-diff-algo-with-mergy-operations.sh b/t/t7615-diff-algo-with-mergy-operations.sh index 3b1aad0167..5822d02d51 100755 --- a/t/t7615-diff-algo-with-mergy-operations.sh +++ b/t/t7615-diff-algo-with-mergy-operations.sh @@ -22,11 +22,9 @@ test_expect_success 'setup' ' git tag c2 ' -GIT_TEST_MERGE_ALGORITHM=recursive - test_expect_success 'merge c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' ' git reset --hard c1 && - test_must_fail git merge -s recursive c2 + test_must_fail git merge -s recursive -Xdiff-algorithm=myers c2 ' test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' ' @@ -42,7 +40,7 @@ test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' ' git reset --hard c1 && - test_must_fail git cherry-pick -s recursive c2 + test_must_fail git cherry-pick -s recursive -Xdiff-algorithm=myers c2 ' test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' ' diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh index 959e6e2648..8aebfb45f5 100755 --- a/t/t7704-repack-cruft.sh +++ b/t/t7704-repack-cruft.sh @@ -149,7 +149,7 @@ generate_cruft_pack () { echo "$packdir/pack-$pack.mtimes" } -test_expect_success '--max-cruft-size creates new packs when above threshold' ' +test_expect_success '--max-cruft-size creates new packs when too large' ' git init max-cruft-size-large && ( cd max-cruft-size-large && @@ -173,7 +173,7 @@ test_expect_success '--max-cruft-size creates new packs when above threshold' ' ) ' -test_expect_success '--max-cruft-size combines existing packs when below threshold' ' +test_expect_success '--max-cruft-size combines existing packs when not too large' ' git init max-cruft-size-small && ( cd max-cruft-size-small && @@ -194,10 +194,13 @@ test_expect_success '--max-cruft-size combines existing packs when below thresho ) ' -test_expect_success '--max-cruft-size combines smaller packs first' ' - git init max-cruft-size-consume-small && +test_expect_success '--combine-cruft-below-size combines packs' ' + repo=combine-cruft-below-size && + test_when_finished "rm -fr $repo" && + + git init "$repo" && ( - cd max-cruft-size-consume-small && + cd "$repo" && test_commit base && git repack -ad && @@ -211,11 +214,11 @@ test_expect_success '--max-cruft-size combines smaller packs first' ' test-tool pack-mtimes "$(basename $cruft_bar)" >>expect.raw && sort expect.raw >expect.objects && - # repacking with `--max-cruft-size=2M` should combine - # both 0.5 MiB packs together, instead of, say, one of - # the 0.5 MiB packs with the 1.0 MiB pack + # Repacking with `--combine-cruft-below-size=1M` + # should combine both 0.5 MiB packs together, but + # ignore the two packs which are >= 1.0 MiB. ls $packdir/pack-*.mtimes | sort >cruft.before && - git repack -d --cruft --max-cruft-size=2M && + git repack -d --cruft --combine-cruft-below-size=1M && ls $packdir/pack-*.mtimes | sort >cruft.after && comm -13 cruft.before cruft.after >cruft.new && @@ -224,11 +227,12 @@ test_expect_success '--max-cruft-size combines smaller packs first' ' test_line_count = 1 cruft.new && test_line_count = 2 cruft.removed && - # the two smaller packs should be rolled up first + # The two packs smaller than 1.0MiB should be repacked + # together. printf "%s\n" $cruft_foo $cruft_bar | sort >expect.removed && test_cmp expect.removed cruft.removed && - # ...and contain the set of objects rolled up + # ...and contain the set of objects rolled up. test-tool pack-mtimes "$(basename $(cat cruft.new))" >actual.raw && sort actual.raw >actual.objects && @@ -236,10 +240,10 @@ test_expect_success '--max-cruft-size combines smaller packs first' ' ) ' -test_expect_success 'setup --max-cruft-size with freshened objects' ' - git init max-cruft-size-freshen && +test_expect_success 'setup cruft with freshened objects' ' + git init cruft-freshen && ( - cd max-cruft-size-freshen && + cd cruft-freshen && test_commit base && git repack -ad && @@ -257,9 +261,9 @@ test_expect_success 'setup --max-cruft-size with freshened objects' ' ) ' -test_expect_success '--max-cruft-size with freshened objects (loose)' ' +test_expect_success 'cruft with freshened objects (loose)' ' ( - cd max-cruft-size-freshen && + cd cruft-freshen && # regenerate the object, setting its mtime to be more recent foo="$(generate_random_blob foo 64)" && @@ -275,9 +279,9 @@ test_expect_success '--max-cruft-size with freshened objects (loose)' ' ) ' -test_expect_success '--max-cruft-size with freshened objects (packed)' ' +test_expect_success 'cruft with freshened objects (packed)' ' ( - cd max-cruft-size-freshen && + cd cruft-freshen && # regenerate the object and store it in a packfile, # setting its mtime to be more recent @@ -304,6 +308,70 @@ test_expect_success '--max-cruft-size with freshened objects (packed)' ' ) ' +test_expect_success 'multi-cruft with freshened objects (previously cruft)' ' + repo="max-cruft-size-threshold" && + + test_when_finished "rm -fr $repo" && + git init "$repo" && + ( + cd "$repo" && + + test_commit base && + foo="$(generate_random_blob foo $((2*1024*1024)))" && + bar="$(generate_random_blob bar $((2*1024*1024)))" && + baz="$(generate_random_blob baz $((2*1024*1024)))" && + + test-tool chmtime --get -100000 \ + "$objdir/$(test_oid_to_path "$foo")" >foo.old && + test-tool chmtime --get -100000 \ + "$objdir/$(test_oid_to_path "$bar")" >bar.old && + test-tool chmtime --get -100000 \ + "$objdir/$(test_oid_to_path "$baz")" >baz.old && + + git repack --cruft -d && + + # Make an identical copy of foo stored in a pack with a more + # recent mtime. + foo="$(generate_random_blob foo $((2*1024*1024)))" && + foo_pack="$(echo "$foo" | git pack-objects $packdir/pack)" && + test-tool chmtime --get -100 \ + "$packdir/pack-$foo_pack.pack" >foo.new && + git prune-packed && + + # Make a loose copy of bar, also with a more recent mtime. + bar="$(generate_random_blob bar $((2*1024*1024)))" && + test-tool chmtime --get -100 \ + "$objdir/$(test_oid_to_path "$bar")" >bar.new && + + # Make a new cruft object $quux to ensure we do not + # generate an identical pack to the existing cruft + # pack. + quux="$(generate_random_blob quux $((1024)))" && + test-tool chmtime --get -100 \ + "$objdir/$(test_oid_to_path "$quux")" >quux.new && + + git repack --cruft --max-cruft-size=3M -d && + + for p in $packdir/pack-*.mtimes + do + test-tool pack-mtimes "$(basename "$p")" || return 1 + done >actual.raw && + sort actual.raw >actual && + + # Among the set of all cruft packs, we should see the + # new mtimes for object $foo and $bar, as well as the + # single new copy of $baz. + sort >expect <<-EOF && + $foo $(cat foo.new) + $bar $(cat bar.new) + $baz $(cat baz.old) + $quux $(cat quux.new) + EOF + + test_cmp expect actual + ) +' + test_expect_success '--max-cruft-size with pruning' ' git init max-cruft-size-prune && ( @@ -411,4 +479,249 @@ test_expect_success 'reachable packs are preferred over cruft ones' ' ) ' +test_expect_success 'repack --cruft generates a cruft pack' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit reachable && + git branch -M main && + git checkout --orphan other && + test_commit unreachable && + + git checkout main && + git branch -D other && + git tag -d unreachable && + # objects are not cruft if they are contained in the reflogs + git reflog expire --all --expire=all && + + git rev-list --objects --all --no-object-names >reachable.raw && + git cat-file --batch-all-objects --batch-check="%(objectname)" >objects && + sort <reachable.raw >reachable && + comm -13 reachable objects >unreachable && + + git repack --cruft -d && + + cruft=$(basename $(ls $packdir/pack-*.mtimes) .mtimes) && + pack=$(basename $(ls $packdir/pack-*.pack | grep -v $cruft) .pack) && + + git show-index <$packdir/$pack.idx >actual.raw && + cut -f2 -d" " actual.raw | sort >actual && + test_cmp reachable actual && + + git show-index <$packdir/$cruft.idx >actual.raw && + cut -f2 -d" " actual.raw | sort >actual && + test_cmp unreachable actual + ) +' + +test_expect_success 'cruft packs are not included in geometric repack' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit reachable && + git repack -Ad && + git branch -M main && + + git checkout --orphan other && + test_commit cruft && + git repack -d && + + git checkout main && + git branch -D other && + git tag -d cruft && + git reflog expire --all --expire=all && + + git repack --cruft && + + find $packdir -type f | sort >before && + git repack --geometric=2 -d && + find $packdir -type f | sort >after && + + test_cmp before after + ) +' + +test_expect_success 'repack --geometric collects once-cruft objects' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit reachable && + git repack -Ad && + git branch -M main && + + git checkout --orphan other && + git rm -rf . && + test_commit --no-tag cruft && + cruft="$(git rev-parse HEAD)" && + + git checkout main && + git branch -D other && + git reflog expire --all --expire=all && + + # Pack the objects created in the previous step into a cruft + # pack. Intentionally leave loose copies of those objects + # around so we can pick them up in a subsequent --geometric + # reapack. + git repack --cruft && + + # Now make those objects reachable, and ensure that they are + # packed into the new pack created via a --geometric repack. + git update-ref refs/heads/other $cruft && + + # Without this object, the set of unpacked objects is exactly + # the set of objects already in the cruft pack. Tweak that set + # to ensure we do not overwrite the cruft pack entirely. + test_commit reachable2 && + + find $packdir -name "pack-*.idx" | sort >before && + git repack --geometric=2 -d && + find $packdir -name "pack-*.idx" | sort >after && + + { + git rev-list --objects --no-object-names $cruft && + git rev-list --objects --no-object-names reachable..reachable2 + } >want.raw && + sort want.raw >want && + + pack=$(comm -13 before after) && + git show-index <$pack >objects.raw && + + cut -d" " -f2 objects.raw | sort >got && + + test_cmp want got + ) +' + +test_expect_success 'cruft repack with no reachable objects' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit base && + git repack -ad && + + base="$(git rev-parse base)" && + + git for-each-ref --format="delete %(refname)" >in && + git update-ref --stdin <in && + git reflog expire --all --expire=all && + rm -fr .git/index && + + git repack --cruft -d && + + git cat-file -t $base + ) +' + +find_pack () { + for idx in $(ls $packdir/pack-*.idx) + do + git show-index <$idx >out && + if grep -q "$1" out + then + echo $idx + fi || return 1 + done +} + +test_expect_success 'cruft repack with --max-pack-size' ' + git init max-pack-size && + ( + cd max-pack-size && + test_commit base && + + # two cruft objects which exceed the maximum pack size + foo=$(generate_random_blob foo 1048576) && + bar=$(generate_random_blob bar 1048576) && + test-tool chmtime --get -1000 \ + "$objdir/$(test_oid_to_path $foo)" >foo.mtime && + test-tool chmtime --get -2000 \ + "$objdir/$(test_oid_to_path $bar)" >bar.mtime && + git repack --cruft --max-pack-size=1M && + find $packdir -name "*.mtimes" >cruft && + test_line_count = 2 cruft && + + foo_mtimes="$(basename $(find_pack $foo) .idx).mtimes" && + bar_mtimes="$(basename $(find_pack $bar) .idx).mtimes" && + test-tool pack-mtimes $foo_mtimes >foo.actual && + test-tool pack-mtimes $bar_mtimes >bar.actual && + + echo "$foo $(cat foo.mtime)" >foo.expect && + echo "$bar $(cat bar.mtime)" >bar.expect && + + test_cmp foo.expect foo.actual && + test_cmp bar.expect bar.actual && + test "$foo_mtimes" != "$bar_mtimes" + ) +' + +test_expect_success 'cruft repack with pack.packSizeLimit' ' + ( + cd max-pack-size && + # repack everything back together to remove the existing cruft + # pack (but to keep its objects) + git repack -adk && + git -c pack.packSizeLimit=1M repack --cruft && + # ensure the same post condition is met when --max-pack-size + # would otherwise be inferred from the configuration + find $packdir -name "*.mtimes" >cruft && + test_line_count = 2 cruft && + for pack in $(cat cruft) + do + test-tool pack-mtimes "$(basename $pack)" >objects && + test_line_count = 1 objects || return 1 + done + ) +' + +test_expect_success 'cruft repack respects repack.cruftWindow' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit base && + + GIT_TRACE2_EVENT=$(pwd)/event.trace \ + git -c pack.window=1 -c repack.cruftWindow=2 repack \ + --cruft --window=3 && + + grep "pack-objects.*--window=2.*--cruft" event.trace + ) +' + +test_expect_success 'cruft repack respects --window by default' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit base && + + GIT_TRACE2_EVENT=$(pwd)/event.trace \ + git -c pack.window=2 repack --cruft --window=3 && + + grep "pack-objects.*--window=3.*--cruft" event.trace + ) +' + +test_expect_success 'cruft repack respects --quiet' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit base && + GIT_PROGRESS_DELAY=0 git repack --cruft --quiet 2>err && + test_must_be_empty err + ) +' + test_done diff --git a/t/t7815-grep-binary.sh b/t/t7815-grep-binary.sh index 90ebb64f46..55d5e6de17 100755 --- a/t/t7815-grep-binary.sh +++ b/t/t7815-grep-binary.sh @@ -63,7 +63,7 @@ test_expect_success 'git grep ile a' ' git grep ile a ' -test_expect_failure 'git grep .fi a' ' +test_expect_failure !CYGWIN,!MACOS 'git grep .fi a' ' git grep .fi a ' @@ -114,13 +114,10 @@ test_expect_success 'grep respects not-binary diff attribute' ' test_cmp expect actual ' -cat >nul_to_q_textconv <<'EOF' -#!/bin/sh -"$PERL_PATH" -pe 'y/\000/Q/' < "$1" -EOF -chmod +x nul_to_q_textconv - test_expect_success 'setup textconv filters' ' + write_script nul_to_q_textconv <<-\EOF && + tr "\000" "Q" <"$1" + EOF echo a diff=foo >.gitattributes && git config diff.foo.textconv "\"$(pwd)\""/nul_to_q_textconv ' diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index 1909aed95e..8cf89e285f 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -306,6 +306,34 @@ test_expect_success 'maintenance.loose-objects.auto' ' test_subcommand git prune-packed --quiet <trace-loC ' +test_expect_success 'maintenance.loose-objects.batchSize' ' + git init loose-batch && + + # This creates three objects per commit. + test_commit_bulk -C loose-batch 34 && + pack=$(ls loose-batch/.git/objects/pack/pack-*.pack) && + index="${pack%pack}idx" && + rm "$index" && + git -C loose-batch unpack-objects <"$pack" && + git -C loose-batch config maintenance.loose-objects.batchSize 50 && + + GIT_PROGRESS_DELAY=0 \ + git -C loose-batch maintenance run --no-quiet --task=loose-objects 2>err && + grep "Enumerating objects: 50, done." err && + + GIT_PROGRESS_DELAY=0 \ + git -C loose-batch maintenance run --no-quiet --task=loose-objects 2>err && + grep "Enumerating objects: 50, done." err && + + GIT_PROGRESS_DELAY=0 \ + git -C loose-batch maintenance run --no-quiet --task=loose-objects 2>err && + grep "Enumerating objects: 2, done." err && + + GIT_PROGRESS_DELAY=0 \ + git -C loose-batch maintenance run --no-quiet --task=loose-objects 2>err && + test_must_be_empty err +' + test_expect_success 'incremental-repack task' ' packDir=.git/objects/pack && for i in $(test_seq 1 5) @@ -447,6 +475,139 @@ test_expect_success 'pack-refs task' ' test_subcommand git pack-refs --all --prune <pack-refs.txt ' +test_expect_success 'reflog-expire task' ' + GIT_TRACE2_EVENT="$(pwd)/reflog-expire.txt" \ + git maintenance run --task=reflog-expire && + test_subcommand git reflog expire --all <reflog-expire.txt +' + +test_expect_success 'reflog-expire task --auto only packs when exceeding limits' ' + git reflog expire --all --expire=now && + test_commit reflog-one && + test_commit reflog-two && + GIT_TRACE2_EVENT="$(pwd)/reflog-expire-auto.txt" \ + git -c maintenance.reflog-expire.auto=3 maintenance run --auto --task=reflog-expire && + test_subcommand ! git reflog expire --all <reflog-expire-auto.txt && + GIT_TRACE2_EVENT="$(pwd)/reflog-expire-auto.txt" \ + git -c maintenance.reflog-expire.auto=2 maintenance run --auto --task=reflog-expire && + test_subcommand git reflog expire --all <reflog-expire-auto.txt +' + +test_expect_worktree_prune () { + negate= + if test "$1" = "!" + then + negate="!" + shift + fi + + rm -f "worktree-prune.txt" && + GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" "$@" && + test_subcommand $negate git worktree prune --expire 3.months.ago <worktree-prune.txt +} + +test_expect_success 'worktree-prune task without --auto always prunes' ' + test_expect_worktree_prune git maintenance run --task=worktree-prune +' + +test_expect_success 'worktree-prune task --auto only prunes with prunable worktree' ' + test_expect_worktree_prune ! git maintenance run --auto --task=worktree-prune && + mkdir .git/worktrees && + : >.git/worktrees/abc && + test_expect_worktree_prune git maintenance run --auto --task=worktree-prune +' + +test_expect_success 'worktree-prune task with --auto honors maintenance.worktree-prune.auto' ' + # A negative value should always prune. + test_expect_worktree_prune git -c maintenance.worktree-prune.auto=-1 maintenance run --auto --task=worktree-prune && + + mkdir .git/worktrees && + : >.git/worktrees/first && + : >.git/worktrees/second && + : >.git/worktrees/third && + + # Zero should never prune. + test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=0 maintenance run --auto --task=worktree-prune && + # A positive value should require at least this many prunable worktrees. + test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=4 maintenance run --auto --task=worktree-prune && + test_expect_worktree_prune git -c maintenance.worktree-prune.auto=3 maintenance run --auto --task=worktree-prune +' + +test_expect_success 'worktree-prune task with --auto honors maintenance.worktree-prune.auto' ' + # A negative value should always prune. + test_expect_worktree_prune git -c maintenance.worktree-prune.auto=-1 maintenance run --auto --task=worktree-prune && + + mkdir .git/worktrees && + : >.git/worktrees/first && + : >.git/worktrees/second && + : >.git/worktrees/third && + + # Zero should never prune. + test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=0 maintenance run --auto --task=worktree-prune && + # A positive value should require at least this many prunable worktrees. + test_expect_worktree_prune ! git -c maintenance.worktree-prune.auto=4 maintenance run --auto --task=worktree-prune && + test_expect_worktree_prune git -c maintenance.worktree-prune.auto=3 maintenance run --auto --task=worktree-prune +' + +test_expect_success 'worktree-prune task honors gc.worktreePruneExpire' ' + git worktree add worktree && + rm -rf worktree && + + rm -f worktree-prune.txt && + GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" git -c gc.worktreePruneExpire=1.week.ago maintenance run --auto --task=worktree-prune && + test_subcommand ! git worktree prune --expire 1.week.ago <worktree-prune.txt && + test_path_is_dir .git/worktrees/worktree && + + rm -f worktree-prune.txt && + GIT_TRACE2_EVENT="$(pwd)/worktree-prune.txt" git -c gc.worktreePruneExpire=now maintenance run --auto --task=worktree-prune && + test_subcommand git worktree prune --expire now <worktree-prune.txt && + test_path_is_missing .git/worktrees/worktree +' + +test_expect_rerere_gc () { + negate= + if test "$1" = "!" + then + negate="!" + shift + fi + + rm -f "rerere-gc.txt" && + GIT_TRACE2_EVENT="$(pwd)/rerere-gc.txt" "$@" && + test_subcommand $negate git rerere gc <rerere-gc.txt +} + +test_expect_success 'rerere-gc task without --auto always collects garbage' ' + test_expect_rerere_gc git maintenance run --task=rerere-gc +' + +test_expect_success 'rerere-gc task with --auto only prunes with prunable entries' ' + test_when_finished "rm -rf .git/rr-cache" && + test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc && + mkdir .git/rr-cache && + test_expect_rerere_gc ! git maintenance run --auto --task=rerere-gc && + : >.git/rr-cache/entry && + test_expect_rerere_gc git maintenance run --auto --task=rerere-gc +' + +test_expect_success 'rerere-gc task with --auto honors maintenance.rerere-gc.auto' ' + test_when_finished "rm -rf .git/rr-cache" && + + # A negative value should always prune. + test_expect_rerere_gc git -c maintenance.rerere-gc.auto=-1 maintenance run --auto --task=rerere-gc && + + # A positive value prunes when there is at least one entry. + test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc && + mkdir .git/rr-cache && + test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc && + : >.git/rr-cache/entry-1 && + test_expect_rerere_gc git -c maintenance.rerere-gc.auto=9000 maintenance run --auto --task=rerere-gc && + + # Zero should never prune. + : >.git/rr-cache/entry-1 && + test_expect_rerere_gc ! git -c maintenance.rerere-gc.auto=0 maintenance run --auto --task=rerere-gc +' + test_expect_success '--auto and --schedule incompatible' ' test_must_fail git maintenance run --auto --schedule=daily 2>err && test_grep "at most one" err diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh index d7167f5539..609845aeb1 100755 --- a/t/t8001-annotate.sh +++ b/t/t8001-annotate.sh @@ -7,6 +7,12 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping annotate tests; Perl not available' + test_done +fi + PROG='git annotate' . "$TEST_DIRECTORY"/annotate-tests.sh diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index e98993276a..7822947f02 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -7,6 +7,12 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping blame colors tests; Perl not available' + test_done +fi + PROG='git blame -c' . "$TEST_DIRECTORY"/annotate-tests.sh @@ -101,7 +107,7 @@ test_expect_success 'set up abbrev tests' ' expect=$1 && shift && echo $sha1 | cut -c 1-$expect >expect && git blame "$@" abbrev.t >actual && - perl -lne "/[0-9a-f]+/ and print \$&" <actual >actual.sha && + sed -n "s/^[\^]\{0,1\}\([0-9a-f][0-9a-f]*\).*/\1/p" actual >actual.sha && test_cmp expect actual.sha } ' diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh index 07a287ffd3..db1e2afb2c 100755 --- a/t/t8006-blame-textconv.sh +++ b/t/t8006-blame-textconv.sh @@ -11,7 +11,7 @@ find_blame() { cat >helper <<'EOF' #!/bin/sh grep -q '^bin: ' "$1" || { echo "E: $1 is not \"binary\" file" 1>&2; exit 1; } -"$PERL_PATH" -p -e 's/^bin: /converted: /' "$1" +sed 's/^bin: /converted: /' "$1" EOF chmod +x helper diff --git a/t/t8011-blame-split-file.sh b/t/t8011-blame-split-file.sh index c66494f5ba..388057245c 100755 --- a/t/t8011-blame-split-file.sh +++ b/t/t8011-blame-split-file.sh @@ -81,7 +81,7 @@ do git blame --root -C --$output combined >output ' - test_expect_success "$output output finds correct commits" ' + test_expect_success PERL_TEST_HELPERS "$output output finds correct commits" ' generate_expect >expect <<-\EOF && 5 base 1 modified @@ -93,7 +93,7 @@ do test_cmp expect actual ' - test_expect_success "$output output shows correct filenames" ' + test_expect_success PERL_TEST_HELPERS "$output output shows correct filenames" ' generate_expect >expect <<-\EOF && 11 one 11 two @@ -102,7 +102,7 @@ do test_cmp expect actual ' - test_expect_success "$output output shows correct previous pointer" ' + test_expect_success PERL_TEST_HELPERS "$output output shows correct previous pointer" ' generate_expect >expect <<-EOF && 5 NONE 1 $(git rev-parse modified^) one diff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh index c3a5f6d01f..3d77352650 100755 --- a/t/t8012-blame-colors.sh +++ b/t/t8012-blame-colors.sh @@ -7,6 +7,12 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh +if ! test_have_prereq PERL_TEST_HELPERS +then + skip_all='skipping blame colors tests; Perl not available' + test_done +fi + PROG='git blame -c' . "$TEST_DIRECTORY"/annotate-tests.sh diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh index 370b768149..cace00ae8d 100755 --- a/t/t8013-blame-ignore-revs.sh +++ b/t/t8013-blame-ignore-revs.sh @@ -158,6 +158,25 @@ test_expect_success mark_unblamable_lines ' test_cmp expect actual ' +for opt in --porcelain --line-porcelain +do + test_expect_success "mark_unblamable_lines with $opt" " + sha=$(git rev-parse Y) && + + git -c blame.markUnblamableLines=false blame $opt --ignore-rev Y file >raw && + cat > sedscript <<- 'EOF' && + /^ y3/i\\ + unblamable + /^ y4/i\\ + unblamable + EOF + sed -f sedscript raw >expect && + + git -c blame.markUnblamableLines=true blame $opt --ignore-rev Y file >actual && + test_cmp expect actual + " +done + # Commit Z will touch the first two lines. Y touched all four. # A--B--X--Y--Z # The blame output when ignoring Z should be: @@ -191,6 +210,25 @@ test_expect_success mark_ignored_lines ' ! test_cmp expect actual ' +for opt in --porcelain --line-porcelain +do + test_expect_success "mark_ignored_lines with $opt" " + sha=$(git rev-parse Y) && + + git -c blame.markIgnoredLines=false blame $opt --ignore-rev Z file >raw && + cat > sedscript <<- 'EOF' && + /^ line-one-Z/i\\ + ignored + /^ line-two-Z/i\\ + ignored + EOF + sed -f sedscript raw >expect && + + git -c blame.markIgnoredLines=true blame $opt --ignore-rev Z file >actual && + test_cmp expect actual + " +done + # For ignored revs that added 'unblamable' lines and more recent commits changed # the blamable lines, mark the unblamable lines with a # '*' diff --git a/t/t9137-git-svn-dcommit-clobber-series.sh b/t/t9137-git-svn-dcommit-clobber-series.sh index 067b15bad2..b57a362bb9 100755 --- a/t/t9137-git-svn-dcommit-clobber-series.sh +++ b/t/t9137-git-svn-dcommit-clobber-series.sh @@ -20,8 +20,8 @@ test_expect_success '(supposedly) non-conflicting change from SVN' ' test x"$(sed -n -e 61p < file)" = x61 && svn_cmd co "$svnrepo" tmp && (cd tmp && - perl -i.bak -p -e "s/^58$/5588/" file && - perl -i.bak -p -e "s/^61$/6611/" file && + sed -e "s/^58$/5588/" -e "s/^61$/6611/" file >file.munged && + mv file.munged file && poke file && test x"$(sed -n -e 58p < file)" = x5588 && test x"$(sed -n -e 61p < file)" = x6611 && @@ -40,8 +40,10 @@ test_expect_success 'some unrelated changes to git' " test_expect_success 'change file but in unrelated area' " test x\"\$(sed -n -e 4p < file)\" = x4 && test x\"\$(sed -n -e 7p < file)\" = x7 && - perl -i.bak -p -e 's/^4\$/4444/' file && - perl -i.bak -p -e 's/^7\$/7777/' file && + sed -e 's/^4\$/4444/' \ + -e 's/^7\$/7777/' \ + file >file.munged && + mv file.munged file && test x\"\$(sed -n -e 4p < file)\" = x4444 && test x\"\$(sed -n -e 7p < file)\" = x7777 && git commit -m '4 => 4444, 7 => 7777' file && diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index a81662713e..bd6f0c40d2 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -108,7 +108,7 @@ test_expect_success 'scalar register warns when background maintenance fails' ' git init register-repo && GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ scalar register register-repo 2>err && - grep "could not turn on maintenance" err + grep "could not toggle maintenance" err ' test_expect_success 'scalar unregister' ' @@ -129,6 +129,17 @@ test_expect_success 'scalar unregister' ' scalar unregister vanish ' +test_expect_success 'scalar register --no-maintenance' ' + git init register-no-maint && + event_log="$(pwd)/no-maint.event" && + GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ + GIT_TRACE2_EVENT="$event_log" \ + GIT_TRACE2_EVENT_DEPTH=100 \ + scalar register --no-maintenance register-no-maint 2>err && + test_must_be_empty err && + test_subcommand ! git maintenance unregister --force <no-maint.event +' + test_expect_success 'set up repository to clone' ' test_commit first && test_commit second && @@ -199,7 +210,18 @@ test_expect_success 'scalar reconfigure' ' GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a && test_path_is_file one/src/cron.txt && test true = "$(git -C one/src config core.preloadIndex)" && - test_subcommand git maintenance start <reconfigure + test_subcommand git maintenance start <reconfigure && + test_subcommand ! git maintenance unregister --force <reconfigure && + + GIT_TRACE2_EVENT="$(pwd)/reconfigure-maint-disable" \ + scalar reconfigure -a --maintenance=disable && + test_subcommand ! git maintenance start <reconfigure-maint-disable && + test_subcommand git maintenance unregister --force <reconfigure-maint-disable && + + GIT_TRACE2_EVENT="$(pwd)/reconfigure-maint-keep" \ + scalar reconfigure --maintenance=keep -a && + test_subcommand ! git maintenance start <reconfigure-maint-keep && + test_subcommand ! git maintenance unregister --force <reconfigure-maint-keep ' test_expect_success 'scalar reconfigure --all with includeIf.onbranch' ' diff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh index 01f71910f5..bfbf22a462 100755 --- a/t/t9211-scalar-clone.sh +++ b/t/t9211-scalar-clone.sh @@ -177,7 +177,16 @@ test_expect_success 'progress without tty' ' test_expect_success 'scalar clone warns when background maintenance fails' ' GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ scalar clone "file://$(pwd)/to-clone" maint-fail 2>err && - grep "could not turn on maintenance" err + grep "could not toggle maintenance" err +' + +test_expect_success 'scalar clone --no-maintenance' ' + GIT_TEST_MAINT_SCHEDULER="crontab:false,launchctl:false,schtasks:false" \ + GIT_TRACE2_EVENT="$(pwd)/no-maint.event" \ + GIT_TRACE2_EVENT_DEPTH=100 \ + scalar clone --no-maintenance "file://$(pwd)/to-clone" no-maint 2>err && + ! grep "could not toggle maintenance" err && + test_subcommand ! git maintenance unregister --force <no-maint.event ' test_expect_success '`scalar clone --no-src`' ' diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 40427883ec..76619765fc 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -8,6 +8,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +. "$TEST_DIRECTORY/lib-gpg.sh" test_expect_success 'setup' ' @@ -253,6 +254,24 @@ test_expect_success 'signed-tags=verbatim' ' ' +test_expect_success 'signed-tags=warn-verbatim' ' + + git fast-export --signed-tags=warn-verbatim sign-your-name >output 2>err && + grep PGP output && + test -s err + +' + +# 'warn' is a backward-compatibility alias for 'warn-verbatim'; test +# that it keeps working. +test_expect_success 'signed-tags=warn' ' + + git fast-export --signed-tags=warn sign-your-name >output 2>err && + grep PGP output && + test -s err + +' + test_expect_success 'signed-tags=strip' ' git fast-export --signed-tags=strip sign-your-name > output && @@ -266,10 +285,95 @@ test_expect_success 'signed-tags=warn-strip' ' test -s err ' +test_expect_success GPG 'set up signed commit' ' + + # Generate a commit with both "gpgsig" and "encoding" set, so + # that we can test that fast-import gets the ordering correct + # between the two. + test_config i18n.commitEncoding ISO-8859-1 && + git checkout -f -b commit-signing main && + echo Sign your name >file-sign && + git add file-sign && + git commit -S -m "signed commit" && + COMMIT_SIGNING=$(git rev-parse --verify commit-signing) + +' + +test_expect_success GPG 'signed-commits default is same as strip' ' + git fast-export --reencode=no commit-signing >out1 2>err && + git fast-export --reencode=no --signed-commits=strip commit-signing >out2 && + test_cmp out1 out2 +' + +test_expect_success GPG 'signed-commits=abort' ' + + test_must_fail git fast-export --signed-commits=abort commit-signing + +' + +test_expect_success GPG 'signed-commits=verbatim' ' + + git fast-export --signed-commits=verbatim --reencode=no commit-signing >output && + grep "^gpgsig sha" output && + grep "encoding ISO-8859-1" output && + ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-signing) && + test $COMMIT_SIGNING = $STRIPPED + ) <output + +' + +test_expect_success GPG 'signed-commits=warn-verbatim' ' + + git fast-export --signed-commits=warn-verbatim --reencode=no commit-signing >output 2>err && + grep "^gpgsig sha" output && + grep "encoding ISO-8859-1" output && + test -s err && + ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-signing) && + test $COMMIT_SIGNING = $STRIPPED + ) <output + +' + +test_expect_success GPG 'signed-commits=strip' ' + + git fast-export --signed-commits=strip --reencode=no commit-signing >output && + ! grep ^gpgsig output && + grep "^encoding ISO-8859-1" output && + sed "s/commit-signing/commit-strip-signing/" output | ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) && + test $COMMIT_SIGNING != $STRIPPED + ) + +' + +test_expect_success GPG 'signed-commits=warn-strip' ' + + git fast-export --signed-commits=warn-strip --reencode=no commit-signing >output 2>err && + ! grep ^gpgsig output && + grep "^encoding ISO-8859-1" output && + test -s err && + sed "s/commit-signing/commit-strip-signing/" output | ( + cd new && + git fast-import && + STRIPPED=$(git rev-parse --verify refs/heads/commit-strip-signing) && + test $COMMIT_SIGNING != $STRIPPED + ) + +' + test_expect_success 'setup submodule' ' test_config_global protocol.file.allow always && git checkout -f main && + test_might_fail git update-ref -d refs/heads/commit-signing && mkdir sub && ( cd sub && @@ -610,7 +714,7 @@ test_expect_success 'directory becomes symlink' ' (cd result && git show main:foo) ' -test_expect_success 'fast-export quotes pathnames' ' +test_expect_success PERL_TEST_HELPERS 'fast-export quotes pathnames' ' git init crazy-paths && test_config -C crazy-paths core.protectNTFS false && (cd crazy-paths && diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 7679780fb8..578d6c8b32 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -700,19 +700,17 @@ test_expect_success \ # ---------------------------------------------------------------------- # syntax highlighting +test_lazy_prereq HIGHLIGHT ' + highlight_version=$(highlight --version </dev/null 2>/dev/null) && + test -n "$highlight_version" +' -highlight_version=$(highlight --version </dev/null 2>/dev/null) -if [ $? -eq 127 ]; then - say "Skipping syntax highlighting tests: 'highlight' not found" -elif test -z "$highlight_version"; then - say "Skipping syntax highlighting tests: incorrect 'highlight' found" -else - test_set_prereq HIGHLIGHT +test_expect_success HIGHLIGHT ' cat >>gitweb_config.perl <<-\EOF our $highlight_bin = "highlight"; - $feature{'highlight'}{'override'} = 1; + $feature{"highlight"}{"override"} = 1; EOF -fi +' test_expect_success HIGHLIGHT \ 'syntax highlighting (no highlight, unknown syntax)' \ diff --git a/t/t9811-git-p4-label-import.sh b/t/t9811-git-p4-label-import.sh index 5ac5383fb7..7614dfbd95 100755 --- a/t/t9811-git-p4-label-import.sh +++ b/t/t9811-git-p4-label-import.sh @@ -95,9 +95,8 @@ test_expect_success 'two labels on the same changelist' ' cd "$git" && git p4 sync --import-labels && - git tag | grep TAG_F1 && - git tag | grep -q TAG_F1_1 && - git tag | grep -q TAG_F1_2 && + git show-ref --verify refs/tags/TAG_F1_1 && + git show-ref --verify refs/tags/TAG_F1_2 && cd main && @@ -207,8 +206,7 @@ test_expect_success 'use git config to enable import/export of tags' ' git tag CFG_A_GIT_TAG && git p4 rebase --verbose && git p4 submit --verbose && - git tag && - git tag | grep TAG_F1_1 + git show-ref --verify refs/tags/TAG_F1_1 ) && ( cd "$cli" && diff --git a/t/t9822-git-p4-path-encoding.sh b/t/t9822-git-p4-path-encoding.sh index 572d395498..e6e07facd4 100755 --- a/t/t9822-git-p4-path-encoding.sh +++ b/t/t9822-git-p4-path-encoding.sh @@ -7,12 +7,17 @@ test_description='Clone repositories with non ASCII paths' UTF8_ESCAPED="a-\303\244_o-\303\266_u-\303\274.txt" ISO8859_ESCAPED="a-\344_o-\366_u-\374.txt" -ISO8859="$(printf "$ISO8859_ESCAPED")" && -echo content123 >"$ISO8859" && -rm "$ISO8859" || { +test_lazy_prereq FS_ACCEPTS_ISO_8859_1 ' + ISO8859="$(printf "$ISO8859_ESCAPED")" && + echo content123 >"$ISO8859" && + rm "$ISO8859" +' + +if ! test_have_prereq FS_ACCEPTS_ISO_8859_1 +then skip_all="fs does not accept ISO-8859-1 filenames" test_done -} +fi test_expect_success 'start p4d' ' start_p4d diff --git a/t/t9835-git-p4-metadata-encoding-python2.sh b/t/t9835-git-p4-metadata-encoding-python2.sh index 6116f806f6..b969c7e0d5 100755 --- a/t/t9835-git-p4-metadata-encoding-python2.sh +++ b/t/t9835-git-p4-metadata-encoding-python2.sh @@ -12,23 +12,25 @@ failing, and produces maximally sane output in git.' ## SECTION REPEATED IN t9836 ## ############################### +EXTRA_PATH="$(pwd)/temp_python" +mkdir "$EXTRA_PATH" +PATH="$EXTRA_PATH:$PATH" +export PATH + # These tests are specific to Python 2. Write a custom script that executes # git-p4 directly with the Python 2 interpreter to ensure that we use that # version even if Git was compiled with Python 3. -python_target_binary=$(which python2) -if test -n "$python_target_binary" -then - mkdir temp_python - PATH="$(pwd)/temp_python:$PATH" - export PATH - - write_script temp_python/git-p4-python2 <<-EOF +test_lazy_prereq P4_PYTHON2 ' + python_target_binary=$(which python2) && + test -n "$python_target_binary" && + write_script "$EXTRA_PATH"/git-p4-python2 <<-EOF && exec "$python_target_binary" "$(git --exec-path)/git-p4" "\$@" EOF -fi + ( git p4-python2 || true ) >err && + test_grep "valid commands" err +' -git p4-python2 >err -if ! grep 'valid commands' err +if ! test_have_prereq P4_PYTHON2 then skip_all="skipping python2 git p4 tests; python2 not available" test_done diff --git a/t/t9836-git-p4-metadata-encoding-python3.sh b/t/t9836-git-p4-metadata-encoding-python3.sh index 5e5217a66b..da6669bf71 100755 --- a/t/t9836-git-p4-metadata-encoding-python3.sh +++ b/t/t9836-git-p4-metadata-encoding-python3.sh @@ -12,23 +12,25 @@ failing, and produces maximally sane output in git.' ## SECTION REPEATED IN t9835 ## ############################### +EXTRA_PATH="$(pwd)/temp_python" +mkdir "$EXTRA_PATH" +PATH="$EXTRA_PATH:$PATH" +export PATH + # These tests are specific to Python 3. Write a custom script that executes # git-p4 directly with the Python 3 interpreter to ensure that we use that # version even if Git was compiled with Python 2. -python_target_binary=$(which python3) -if test -n "$python_target_binary" -then - mkdir temp_python - PATH="$(pwd)/temp_python:$PATH" - export PATH - - write_script temp_python/git-p4-python3 <<-EOF +test_lazy_prereq P4_PYTHON3 ' + python_target_binary=$(which python3) && + test -n "$python_target_binary" && + write_script "$EXTRA_PATH"/git-p4-python3 <<-EOF && exec "$python_target_binary" "$(git --exec-path)/git-p4" "\$@" EOF -fi + ( git p4-python3 || true ) >err && + test_grep "valid commands" err +' -git p4-python3 >err -if ! grep 'valid commands' err +if ! test_have_prereq P4_PYTHON3 then skip_all="skipping python3 git p4 tests; python3 not available" test_done diff --git a/t/t9850-shell.sh b/t/t9850-shell.sh index 36566ace21..21c3af48bd 100755 --- a/t/t9850-shell.sh +++ b/t/t9850-shell.sh @@ -30,7 +30,7 @@ test_expect_success 'shell allows interactive command' ' ' test_expect_success 'shell complains of overlong commands' ' - perl -e "print \"a\" x 2**12 for (0..2**19)" | + test-tool genzeros | tr "\000" "a" | test_must_fail git shell 2>err && grep "too long" err ' diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 51bd750837..343b8cd191 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -149,7 +149,8 @@ fi test_expect_success 'setup for __git_find_repo_path/__gitdir tests' ' mkdir -p subdir/subsubdir && mkdir -p non-repo && - git init -b main otherrepo + git init -b main otherrepo && + git init -b main slashrepo ' test_expect_success '__git_find_repo_path - from command line (through $__git_dir)' ' @@ -455,6 +456,32 @@ test_expect_success '__git_dequote - open double quote' ' ' +test_expect_success '__git_count_path_components - no slashes' ' + echo 1 >expected && + __git_count_path_components a >"$actual" && + test_cmp expected "$actual" +' + +test_expect_success '__git_count_path_components - relative' ' + echo 3 >expected && + __git_count_path_components a/b/c >"$actual" && + test_cmp expected "$actual" + +' + +test_expect_success '__git_count_path_components - absolute' ' + echo 3 >expected && + __git_count_path_components /a/b/c >"$actual" && + test_cmp expected "$actual" +' + +test_expect_success '__git_count_path_components - trailing slash' ' + echo 3 >expected && + __git_count_path_components a/b/c/ >"$actual" && + test_cmp expected "$actual" +' + + test_expect_success '__gitcomp_direct - puts everything into COMPREPLY as-is' ' sed -e "s/Z$//g" >expected <<-EOF && with-trailing-space Z @@ -648,6 +675,13 @@ test_expect_success 'setup for ref completion' ' ) && git remote add other "$ROOT/otherrepo/.git" && git fetch --no-tags other && + ( + cd slashrepo && + git commit --allow-empty -m initial && + git branch -m main branch/with/slash + ) && + git remote add remote/with/slash "$ROOT/slashrepo/.git" && + git fetch --no-tags remote/with/slash && rm -f .git/FETCH_HEAD && git init thirdrepo ' @@ -660,6 +694,8 @@ test_expect_success '__git_refs - simple' ' other/HEAD other/branch-in-other other/main-in-other + remote/with/slash/HEAD + remote/with/slash/branch/with/slash matching-tag EOF ( @@ -676,6 +712,8 @@ test_expect_success '__git_refs - full refs' ' refs/remotes/other/HEAD refs/remotes/other/branch-in-other refs/remotes/other/main-in-other + refs/remotes/remote/with/slash/HEAD + refs/remotes/remote/with/slash/branch/with/slash refs/tags/matching-tag EOF ( @@ -741,6 +779,19 @@ test_expect_success '__git_refs - configured remote' ' test_cmp expected "$actual" ' +test_expect_success '__git_refs - configured remote - with slash' ' + cat >expected <<-EOF && + HEAD + HEAD + branch/with/slash + EOF + ( + cur= && + __git_refs remote/with/slash >"$actual" + ) && + test_cmp expected "$actual" +' + test_expect_success '__git_refs - configured remote - full refs' ' cat >expected <<-EOF && HEAD @@ -883,17 +934,19 @@ test_expect_success '__git_refs - unique remote branches for git checkout DWIMer other/ambiguous other/branch-in-other other/main-in-other - remote/ambiguous - remote/branch-in-remote + remote/with/slash/HEAD + remote/with/slash/ambiguous + remote/with/slash/branch-in-remote + remote/with/slash/branch/with/slash matching-tag - HEAD branch-in-other branch-in-remote + branch/with/slash main-in-other EOF for remote_ref in refs/remotes/other/ambiguous \ - refs/remotes/remote/ambiguous \ - refs/remotes/remote/branch-in-remote + refs/remotes/remote/with/slash/ambiguous \ + refs/remotes/remote/with/slash/branch-in-remote do git update-ref $remote_ref main && test_when_finished "git update-ref -d $remote_ref" || return 1 @@ -913,6 +966,8 @@ test_expect_success '__git_refs - after --opt=' ' other/HEAD other/branch-in-other other/main-in-other + remote/with/slash/HEAD + remote/with/slash/branch/with/slash matching-tag EOF ( @@ -929,6 +984,8 @@ test_expect_success '__git_refs - after --opt= - full refs' ' refs/remotes/other/HEAD refs/remotes/other/branch-in-other refs/remotes/other/main-in-other + refs/remotes/remote/with/slash/HEAD + refs/remotes/remote/with/slash/branch/with/slash refs/tags/matching-tag EOF ( @@ -946,6 +1003,8 @@ test_expect_success '__git refs - excluding refs' ' ^other/HEAD ^other/branch-in-other ^other/main-in-other + ^remote/with/slash/HEAD + ^remote/with/slash/branch/with/slash ^matching-tag EOF ( @@ -962,6 +1021,8 @@ test_expect_success '__git refs - excluding full refs' ' ^refs/remotes/other/HEAD ^refs/remotes/other/branch-in-other ^refs/remotes/other/main-in-other + ^refs/remotes/remote/with/slash/HEAD + ^refs/remotes/remote/with/slash/branch/with/slash ^refs/tags/matching-tag EOF ( @@ -989,6 +1050,8 @@ test_expect_success '__git_refs - do not filter refs unless told so' ' other/branch-in-other other/main-in-other other/matching/branch-in-other + remote/with/slash/HEAD + remote/with/slash/branch/with/slash matching-tag matching/tag EOF @@ -1109,6 +1172,8 @@ test_expect_success '__git_complete_refs - simple' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z matching-tag Z EOF ( @@ -1147,6 +1212,20 @@ test_expect_success '__git_complete_refs - remote' ' test_cmp expected out ' +test_expect_success '__git_complete_refs - remote - with slash' ' + sed -e "s/Z$//" >expected <<-EOF && + HEAD Z + HEAD Z + branch/with/slash Z + EOF + ( + cur= && + __git_complete_refs --remote=remote/with/slash && + print_comp + ) && + test_cmp expected out +' + test_expect_success '__git_complete_refs - track' ' sed -e "s/Z$//" >expected <<-EOF && HEAD Z @@ -1155,9 +1234,11 @@ test_expect_success '__git_complete_refs - track' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z matching-tag Z - HEAD Z branch-in-other Z + branch/with/slash Z main-in-other Z EOF ( @@ -1202,6 +1283,8 @@ test_expect_success '__git_complete_refs - suffix' ' other/HEAD. other/branch-in-other. other/main-in-other. + remote/with/slash/HEAD. + remote/with/slash/branch/with/slash. matching-tag. EOF ( @@ -1227,6 +1310,20 @@ test_expect_success '__git_complete_fetch_refspecs - simple' ' test_cmp expected out ' +test_expect_success '__git_complete_fetch_refspecs - with slash' ' + sed -e "s/Z$//" >expected <<-EOF && + HEAD:HEAD Z + HEAD:HEAD Z + branch/with/slash:branch/with/slash Z + EOF + ( + cur= && + __git_complete_fetch_refspecs remote/with/slash && + print_comp + ) && + test_cmp expected out +' + test_expect_success '__git_complete_fetch_refspecs - matching' ' sed -e "s/Z$//" >expected <<-EOF && branch-in-other:branch-in-other Z @@ -1307,8 +1404,8 @@ test_expect_success '__git_complete_worktree_paths with -C' ' test_expect_success 'git switch - with no options, complete local branches and unique remote branch names for DWIM logic' ' test_completion "git switch " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1454,8 +1551,8 @@ test_expect_success 'git-bisect - existing view subcommand is recognized and ena test_expect_success 'git checkout - completes refs and unique remote branches for DWIM' ' test_completion "git checkout " <<-\EOF HEAD Z - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1463,6 +1560,8 @@ test_expect_success 'git checkout - completes refs and unique remote branches fo other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1482,8 +1581,8 @@ test_expect_success 'git switch - with GIT_COMPLETION_CHECKOUT_NO_GUESS=1, compl test_expect_success 'git switch - --guess overrides GIT_COMPLETION_CHECKOUT_NO_GUESS=1, complete local branches and unique remote names for DWIM logic' ' GIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion "git switch --guess " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1492,8 +1591,8 @@ test_expect_success 'git switch - --guess overrides GIT_COMPLETION_CHECKOUT_NO_G test_expect_success 'git switch - a later --guess overrides previous --no-guess, complete local and remote unique branches for DWIM' ' test_completion "git switch --no-guess --guess " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1516,14 +1615,16 @@ test_expect_success 'git checkout - with GIT_COMPLETION_NO_GUESS=1 only complete other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' test_expect_success 'git checkout - --guess overrides GIT_COMPLETION_NO_GUESS=1, complete refs and unique remote branches for DWIM' ' GIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion "git checkout --guess " <<-\EOF HEAD Z - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1531,6 +1632,8 @@ test_expect_success 'git checkout - --guess overrides GIT_COMPLETION_NO_GUESS=1, other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1543,14 +1646,16 @@ test_expect_success 'git checkout - with --no-guess, only completes refs' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' test_expect_success 'git checkout - a later --guess overrides previous --no-guess, complete refs and unique remote branches for DWIM' ' test_completion "git checkout --no-guess --guess " <<-\EOF HEAD Z - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1558,6 +1663,8 @@ test_expect_success 'git checkout - a later --guess overrides previous --no-gues other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1570,6 +1677,8 @@ test_expect_success 'git checkout - a later --no-guess overrides previous --gues other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1583,6 +1692,8 @@ test_expect_success 'git checkout - with checkout.guess = false, only completes other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1590,8 +1701,8 @@ test_expect_success 'git checkout - with checkout.guess = true, completes refs a test_config checkout.guess true && test_completion "git checkout " <<-\EOF HEAD Z - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1599,6 +1710,8 @@ test_expect_success 'git checkout - with checkout.guess = true, completes refs a other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1606,8 +1719,8 @@ test_expect_success 'git checkout - a later --guess overrides previous checkout. test_config checkout.guess false && test_completion "git checkout --guess " <<-\EOF HEAD Z - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -1615,6 +1728,8 @@ test_expect_success 'git checkout - a later --guess overrides previous checkout. other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1628,6 +1743,8 @@ test_expect_success 'git checkout - a later --no-guess overrides previous checko other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1640,6 +1757,8 @@ test_expect_success 'git switch - with --detach, complete all references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1652,6 +1771,8 @@ test_expect_success 'git checkout - with --detach, complete only references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1824,6 +1945,8 @@ test_expect_success 'git switch - with -d, complete all references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1836,6 +1959,8 @@ test_expect_success 'git checkout - with -d, complete only references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1844,11 +1969,15 @@ test_expect_success 'git switch - with --track, complete only remote branches' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF test_completion "git switch -t " <<-\EOF other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1857,11 +1986,15 @@ test_expect_success 'git checkout - with --track, complete only remote branches' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF test_completion "git checkout -t " <<-\EOF other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1881,6 +2014,8 @@ test_expect_success 'git checkout - with --no-track, complete only local referen other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1893,6 +2028,8 @@ test_expect_success 'git switch - with -c, complete all references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1905,6 +2042,8 @@ test_expect_success 'git switch - with -C, complete all references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1917,6 +2056,8 @@ test_expect_success 'git switch - with -c and --track, complete all references' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1929,6 +2070,8 @@ test_expect_success 'git switch - with -C and --track, complete all references' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1941,6 +2084,8 @@ test_expect_success 'git switch - with -c and --no-track, complete all reference other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1953,6 +2098,8 @@ test_expect_success 'git switch - with -C and --no-track, complete all reference other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1965,6 +2112,8 @@ test_expect_success 'git checkout - with -b, complete all references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1977,6 +2126,8 @@ test_expect_success 'git checkout - with -B, complete all references' ' other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -1989,6 +2140,8 @@ test_expect_success 'git checkout - with -b and --track, complete all references other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -2001,6 +2154,8 @@ test_expect_success 'git checkout - with -B and --track, complete all references other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -2013,6 +2168,8 @@ test_expect_success 'git checkout - with -b and --no-track, complete all referen other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -2025,13 +2182,15 @@ test_expect_success 'git checkout - with -B and --no-track, complete all referen other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' test_expect_success 'git switch - for -c, complete local branches and unique remote branches' ' test_completion "git switch -c " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -2040,8 +2199,8 @@ test_expect_success 'git switch - for -c, complete local branches and unique rem test_expect_success 'git switch - for -C, complete local branches and unique remote branches' ' test_completion "git switch -C " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -2078,8 +2237,8 @@ test_expect_success 'git switch - for -C with --no-track, complete local branche test_expect_success 'git checkout - for -b, complete local branches and unique remote branches' ' test_completion "git checkout -b " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -2088,8 +2247,8 @@ test_expect_success 'git checkout - for -b, complete local branches and unique r test_expect_success 'git checkout - for -B, complete local branches and unique remote branches' ' test_completion "git checkout -B " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -2126,8 +2285,8 @@ test_expect_success 'git checkout - for -B with --no-track, complete local branc test_expect_success 'git switch - with --orphan completes local branch names and unique remote branch names' ' test_completion "git switch --orphan " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -2142,8 +2301,8 @@ test_expect_success 'git switch - --orphan with branch already provided complete test_expect_success 'git checkout - with --orphan completes local branch names and unique remote branch names' ' test_completion "git checkout --orphan " <<-\EOF - HEAD Z branch-in-other Z + branch/with/slash Z main Z main-in-other Z matching-branch Z @@ -2159,6 +2318,8 @@ test_expect_success 'git checkout - --orphan with branch already provided comple other/HEAD Z other/branch-in-other Z other/main-in-other Z + remote/with/slash/HEAD Z + remote/with/slash/branch/with/slash Z EOF ' @@ -2173,7 +2334,8 @@ test_expect_success 'git restore completes modified files' ' test_expect_success 'teardown after ref completion' ' git branch -d matching-branch && git tag -d matching-tag && - git remote remove other + git remote remove other && + git remote remove remote/with/slash ' diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index d667dda654..637a6f13a6 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -66,10 +66,6 @@ test_expect_success 'prompt - unborn branch' ' test_cmp expected "$actual" ' -if test_have_prereq !FUNNYNAMES; then - say 'Your filesystem does not allow newlines in filenames.' -fi - test_expect_success FUNNYNAMES 'prompt - with newline in path' ' repo_with_newline="repo with diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 79377bc0fc..bee4a2ca34 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -88,15 +88,15 @@ test_decode_color () { } lf_to_nul () { - perl -pe 'y/\012/\000/' + tr '\012' '\000' } nul_to_q () { - perl -pe 'y/\000/Q/' + tr '\000' 'Q' } q_to_nul () { - perl -pe 'y/Q/\000/' + tr 'Q' '\000' } q_to_cr () { @@ -773,6 +773,8 @@ mkdir -p "$TRASH_DIRECTORY/prereq-test-dir-'"$1"'" && rm -rf "$TRASH_DIRECTORY/prereq-test-dir-$1" if test "$eval_ret" = 0; then say >&3 "prerequisite $1 ok" + elif test "$eval_ret" = 125; then + :; else say >&3 "prerequisite $1 not satisfied" fi @@ -811,6 +813,9 @@ test_have_prereq () { if test_run_lazy_prereq_ "$prerequisite" "$script" then test_set_prereq $prerequisite + elif test $? = 125 + then + BUG "Do not use $prerequisite" fi lazily_tested_prereq="$lazily_tested_prereq$prerequisite " esac @@ -1640,17 +1645,7 @@ test_match_signal () { # Read up to "$1" bytes (or to EOF) from stdin and write them to stdout. test_copy_bytes () { - perl -e ' - my $len = $ARGV[1]; - while ($len > 0) { - my $s; - my $nread = sysread(STDIN, $s, $len); - die "cannot read: $!" unless defined($nread); - last unless $nread; - print $s; - $len -= $nread; - } - ' - "$1" + dd ibs=1 count="$1" 2>/dev/null } # run "$@" inside a non-git directory @@ -1989,7 +1984,7 @@ test_remote_https_urls() { # Print the destination of symlink(s) provided as arguments. Basically # the same as the readlink command, but it's not available everywhere. test_readlink () { - perl -le 'print readlink($_) for @ARGV' "$@" + test-tool path-utils readlink "$@" } # Set mtime to a fixed "magic" timestamp in mid February 2009, before we diff --git a/t/test-lib.sh b/t/test-lib.sh index 9001ed3a64..51370a201c 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -470,7 +470,7 @@ then then : Executed by a Bash version supporting BASH_XTRACEFD. Good. else - echo >&2 "warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD" + echo >&2 "# warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD" trace= fi fi @@ -499,24 +499,20 @@ EDITOR=: # /usr/xpg4/bin/sh and /bin/ksh to bail out. So keep the unsets # deriving from the command substitution clustered with the other # ones. -unset VISUAL EMAIL LANGUAGE $("$PERL_PATH" -e ' - my @env = keys %ENV; - my $ok = join("|", qw( - TRACE - DEBUG - TEST - .*_TEST - PROVE - VALGRIND - UNZIP - PERF_ - CURL_VERBOSE - TRACE_CURL - BUILD_DIR - )); - my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env); - print join("\n", @vars); -') +unset VISUAL EMAIL LANGUAGE $(env | sed -n \ + -e '/^GIT_TRACE/d' \ + -e '/^GIT_DEBUG/d' \ + -e '/^GIT_TEST/d' \ + -e '/^GIT_.*_TEST/d' \ + -e '/^GIT_PROVE/d' \ + -e '/^GIT_VALGRIND/d' \ + -e '/^GIT_UNZIP/d' \ + -e '/^GIT_PERF_/d' \ + -e '/^GIT_CURL_VERBOSE/d' \ + -e '/^GIT_TRACE_CURL/d' \ + -e '/^GIT_BUILD_DIR/d' \ + -e 's/^\(GIT_[^=]*\)=.*/\1/p' +) unset XDG_CACHE_HOME unset XDG_CONFIG_HOME unset GITPERLLIB @@ -544,8 +540,6 @@ GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}" export GIT_DEFAULT_HASH GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}" export GIT_DEFAULT_REF_FORMAT -GIT_TEST_MERGE_ALGORITHM="${GIT_TEST_MERGE_ALGORITHM:-ort}" -export GIT_TEST_MERGE_ALGORITHM # Tests using GIT_TRACE typically don't want <timestamp> <file>:<line> output GIT_TRACE_BARE=1 @@ -713,7 +707,7 @@ then exec 3>>"$GIT_TEST_TEE_OUTPUT_FILE" 4>&3 elif test "$verbose" = "t" then - exec 4>&2 3>&1 + exec 4>&2 3>&2 else exec 4>/dev/null 3>/dev/null fi @@ -955,7 +949,7 @@ maybe_setup_verbose () { test -z "$verbose_only" && return if match_pattern_list $test_count "$verbose_only" then - exec 4>&2 3>&1 + exec 4>&2 3>&2 # Emit a delimiting blank line when going from # non-verbose to verbose. Within verbose mode the # delimiter is printed by test_expect_*. The choice @@ -1278,7 +1272,14 @@ test_done () { check_test_results_san_file_ "$test_failure" - if test -z "$skip_all" && test -n "$invert_exit_code" + if test "$test_fixed" != 0 + then + if test -z "$invert_exit_code" + then + GIT_EXIT_OK=t + exit 1 + fi + elif test -z "$skip_all" && test -n "$invert_exit_code" then say_color warn "# faking up non-zero exit with --invert-exit-code" GIT_EXIT_OK=t @@ -1523,6 +1524,22 @@ then export LSAN_OPTIONS fi +if test -z "$PERL_PATH" +then + case "${GIT_TEST_CHAIN_LINT:-unset}" in + unset) + GIT_TEST_CHAIN_LINT=0 + ;; + 0) + # The user has explicitly disabled the chain linter, so we + # don't have anything to worry about. + ;; + *) + BAIL_OUT 'You need Perl for the chain linter' + ;; + esac +fi + if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 && test "${GIT_TEST_EXT_CHAIN_LINT:-1}" != 0 then @@ -1567,6 +1584,8 @@ fi # Use -P to resolve symlinks in our working directory so that the cwd # in subprocesses like git equals our $PWD (for pathname comparisons). cd -P "$TRASH_DIRECTORY" || BAIL_OUT "cannot cd -P to \"$TRASH_DIRECTORY\"" +TRASH_DIRECTORY=$(pwd) +HOME="$TRASH_DIRECTORY" start_test_output "$0" @@ -1626,6 +1645,12 @@ fi # Fix some commands on Windows, and other OS-specific things uname_s=$(uname -s) case $uname_s in +Darwin) + test_set_prereq MACOS + test_set_prereq POSIXPERM + test_set_prereq BSLASHPSPEC + test_set_prereq EXECKEEPSPID + ;; *MINGW*) # Windows has its own (incompatible) sort and find sort () { @@ -1694,6 +1719,7 @@ test -n "$USE_LIBPCRE2" && test_set_prereq LIBPCRE2 test -z "$NO_GETTEXT" && test_set_prereq GETTEXT test -n "$SANITIZE_LEAK" && test_set_prereq SANITIZE_LEAK test -n "$GIT_VALGRIND_ENABLED" && test_set_prereq VALGRIND +test -n "$PERL_PATH" && test_set_prereq PERL_TEST_HELPERS if test -z "$GIT_TEST_CHECK_CACHE_TREE" then @@ -1862,8 +1888,13 @@ test_lazy_prereq CURL ' curl --version ' +test_lazy_prereq WITH_BREAKING_CHANGES ' + test -n "$WITH_BREAKING_CHANGES" +' + test_lazy_prereq WITHOUT_BREAKING_CHANGES ' - test -z "$WITH_BREAKING_CHANGES" + # Signal that this prereq should not be used. + exit 125 ' # SHA1 is a test if the hash algorithm in use is SHA-1. This is both for tests diff --git a/t/unit-tests/clar/clar/fs.h b/t/unit-tests/clar/clar/fs.h index 8b206179fc..2203743fb4 100644 --- a/t/unit-tests/clar/clar/fs.h +++ b/t/unit-tests/clar/clar/fs.h @@ -376,9 +376,12 @@ fs_copydir_helper(const char *source, const char *dest, int dest_mode) mkdir(dest, dest_mode); cl_assert_(source_dir = opendir(source), "Could not open source dir"); - while ((d = (errno = 0, readdir(source_dir))) != NULL) { + for (;;) { char *child; + errno = 0; + if ((d = readdir(source_dir)) == NULL) + break; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; @@ -479,9 +482,12 @@ fs_rmdir_helper(const char *path) struct dirent *d; cl_assert_(dir = opendir(path), "Could not open dir"); - while ((d = (errno = 0, readdir(dir))) != NULL) { + for (;;) { char *child; + errno = 0; + if ((d = readdir(dir)) == NULL) + break; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c index 9ba7eb05ad..c9e751e49e 100644 --- a/t/unit-tests/t-reftable-basics.c +++ b/t/unit-tests/t-reftable-basics.c @@ -128,12 +128,30 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED) reftable_buf_release(&b); } - if_test ("put_be24 and get_be24 work") { + if_test ("reftable_put_be64 and reftable_get_be64 work") { + uint64_t in = 0x1122334455667788; + uint8_t dest[8]; + uint64_t out; + reftable_put_be64(dest, in); + out = reftable_get_be64(dest); + check_int(in, ==, out); + } + + if_test ("reftable_put_be32 and reftable_get_be32 work") { + uint32_t in = 0x11223344; + uint8_t dest[4]; + uint32_t out; + reftable_put_be32(dest, in); + out = reftable_get_be32(dest); + check_int(in, ==, out); + } + + if_test ("reftable_put_be24 and reftable_get_be24 work") { uint32_t in = 0x112233; uint8_t dest[3]; uint32_t out; - put_be24(dest, in); - out = get_be24(dest); + reftable_put_be24(dest, in); + out = reftable_get_be24(dest); check_int(in, ==, out); } @@ -141,8 +159,8 @@ int cmd_main(int argc UNUSED, const char *argv[] UNUSED) uint32_t in = 0xfef1; uint8_t dest[3]; uint32_t out; - put_be16(dest, in); - out = get_be16(dest); + reftable_put_be16(dest, in); + out = reftable_get_be16(dest); check_int(in, ==, out); } diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index 22040aeefa..52f1dae1c9 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -19,24 +19,25 @@ static void t_ref_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 1024; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source ,&buf); - ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -62,9 +63,11 @@ static void t_ref_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source ,&block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -77,10 +80,9 @@ static void t_ref_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_record_key(&recs[i], &want); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -89,7 +91,7 @@ static void t_ref_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); want.len--; - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -97,12 +99,11 @@ static void t_ref_block_read_write(void) check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } @@ -113,24 +114,25 @@ static void t_log_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 2048; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source ,&buf); - ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size, + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -151,9 +153,11 @@ static void t_log_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_LOG); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -166,11 +170,10 @@ static void t_log_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_buf_reset(&want); check(!reftable_buf_addstr(&want, recs[i].u.log.refname)); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -179,7 +182,7 @@ static void t_log_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); want.len--; - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -187,12 +190,11 @@ static void t_log_block_read_write(void) check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } @@ -203,24 +205,25 @@ static void t_obj_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 1024; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; + + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source, &buf); - ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size, + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -243,9 +246,11 @@ static void t_obj_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_OBJ); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -258,10 +263,9 @@ static void t_obj_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_record_key(&recs[i], &want); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -270,12 +274,11 @@ static void t_obj_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } @@ -286,25 +289,26 @@ static void t_index_block_read_write(void) struct reftable_record recs[30]; const size_t N = ARRAY_SIZE(recs); const size_t block_size = 1024; - struct reftable_block block = { 0 }; + struct reftable_block_source source = { 0 }; struct block_writer bw = { .last_key = REFTABLE_BUF_INIT, }; struct reftable_record rec = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.last_key = REFTABLE_BUF_INIT, }; size_t i = 0; int ret; - struct block_reader br = { 0 }; + struct reftable_block block = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - struct reftable_buf want = REFTABLE_BUF_INIT, buf = REFTABLE_BUF_INIT; + struct reftable_buf want = REFTABLE_BUF_INIT; + struct reftable_buf block_data = REFTABLE_BUF_INIT; - REFTABLE_CALLOC_ARRAY(block.data, block_size); - check(block.data != NULL); - block.len = block_size; - block_source_from_buf(&block.source, &buf); - ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size, + REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); + check(block_data.buf != NULL); + block_data.len = block_size; + + ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size, header_off, hash_size(REFTABLE_HASH_SHA1)); check(!ret); @@ -314,7 +318,7 @@ static void t_index_block_read_write(void) snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); reftable_buf_init(&recs[i].u.idx.last_key); - recs[i].type = BLOCK_TYPE_INDEX; + recs[i].type = REFTABLE_BLOCK_TYPE_INDEX; check(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); recs[i].u.idx.offset = i; @@ -327,9 +331,11 @@ static void t_index_block_read_write(void) block_writer_release(&bw); - block_reader_init(&br, &block, header_off, block_size, REFTABLE_HASH_SIZE_SHA1); + block_source_from_buf(&source, &block_data); + reftable_block_init(&block, &source, 0, header_off, block_size, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_INDEX); - block_iter_seek_start(&it, &br); + block_iter_init(&it, &block); for (i = 0; ; i++) { ret = block_iter_next(&it, &rec); @@ -342,10 +348,9 @@ static void t_index_block_read_write(void) } for (i = 0; i < N; i++) { - block_iter_reset(&it); reftable_record_key(&recs[i], &want); - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -354,7 +359,7 @@ static void t_index_block_read_write(void) check(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1)); want.len--; - ret = block_iter_seek_key(&it, &br, &want); + ret = block_iter_seek_key(&it, &want); check_int(ret, ==, 0); ret = block_iter_next(&it, &rec); @@ -362,22 +367,100 @@ static void t_index_block_read_write(void) check(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1)); } - block_reader_release(&br); + reftable_block_release(&block); block_iter_close(&it); reftable_record_release(&rec); - reftable_block_done(&br.block); reftable_buf_release(&want); - reftable_buf_release(&buf); + reftable_buf_release(&block_data); for (i = 0; i < N; i++) reftable_record_release(&recs[i]); } +static void t_block_iterator(void) +{ + struct reftable_block_source source = { 0 }; + struct block_writer writer = { + .last_key = REFTABLE_BUF_INIT, + }; + struct reftable_record expected_refs[20]; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_block block = { 0 }; + struct reftable_buf data; + int err; + + data.len = 1024; + REFTABLE_CALLOC_ARRAY(data.buf, data.len); + check(data.buf != NULL); + + err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF, (uint8_t *) data.buf, data.len, + 0, hash_size(REFTABLE_HASH_SHA1)); + check(!err); + + for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) { + expected_refs[i] = (struct reftable_record) { + .type = REFTABLE_BLOCK_TYPE_REF, + .u.ref = { + .value_type = REFTABLE_REF_VAL1, + .refname = xstrfmt("refs/heads/branch-%02"PRIuMAX, (uintmax_t)i), + }, + }; + memset(expected_refs[i].u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); + + err = block_writer_add(&writer, &expected_refs[i]); + check_int(err, ==, 0); + } + + err = block_writer_finish(&writer); + check_int(err, >, 0); + + block_source_from_buf(&source, &data); + reftable_block_init(&block, &source, 0, 0, data.len, + REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF); + + err = reftable_block_init_iterator(&block, &it); + check_int(err, ==, 0); + + for (size_t i = 0; ; i++) { + err = reftable_iterator_next_ref(&it, &ref); + if (err > 0) { + check_int(i, ==, ARRAY_SIZE(expected_refs)); + break; + } + check_int(err, ==, 0); + + check(reftable_ref_record_equal(&ref, &expected_refs[i].u.ref, + REFTABLE_HASH_SIZE_SHA1)); + } + + err = reftable_iterator_seek_ref(&it, "refs/heads/does-not-exist"); + check_int(err, ==, 0); + err = reftable_iterator_next_ref(&it, &ref); + check_int(err, ==, 1); + + err = reftable_iterator_seek_ref(&it, "refs/heads/branch-13"); + check_int(err, ==, 0); + err = reftable_iterator_next_ref(&it, &ref); + check_int(err, ==, 0); + check(reftable_ref_record_equal(&ref, &expected_refs[13].u.ref, + REFTABLE_HASH_SIZE_SHA1)); + + for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) + reftable_free(expected_refs[i].u.ref.refname); + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_block_release(&block); + block_writer_release(&writer); + reftable_buf_release(&data); +} + int cmd_main(int argc UNUSED, const char *argv[] UNUSED) { TEST(t_index_block_read_write(), "read-write operations on index blocks work"); TEST(t_log_block_read_write(), "read-write operations on log blocks work"); TEST(t_obj_block_read_write(), "read-write operations on obj blocks work"); TEST(t_ref_block_read_write(), "read-write operations on ref blocks work"); + TEST(t_block_iterator(), "block iterator works"); return test_done(); } diff --git a/t/unit-tests/t-reftable-merged.c b/t/unit-tests/t-reftable-merged.c index 60836f80d6..18c3251a56 100644 --- a/t/unit-tests/t-reftable-merged.c +++ b/t/unit-tests/t-reftable-merged.c @@ -11,7 +11,7 @@ https://developers.google.com/open-source/licenses/bsd #include "reftable/blocksource.h" #include "reftable/constants.h" #include "reftable/merged.h" -#include "reftable/reader.h" +#include "reftable/table.h" #include "reftable/reftable-error.h" #include "reftable/reftable-merged.h" #include "reftable/reftable-writer.h" @@ -19,7 +19,7 @@ https://developers.google.com/open-source/licenses/bsd static struct reftable_merged_table * merged_table_from_records(struct reftable_ref_record **refs, struct reftable_block_source **source, - struct reftable_reader ***readers, const size_t *sizes, + struct reftable_table ***tables, const size_t *sizes, struct reftable_buf *buf, const size_t n) { struct reftable_merged_table *mt = NULL; @@ -28,8 +28,8 @@ merged_table_from_records(struct reftable_ref_record **refs, }; int err; - REFTABLE_CALLOC_ARRAY(*readers, n); - check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*tables, n); + check(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); check(*source != NULL); @@ -37,21 +37,21 @@ merged_table_from_records(struct reftable_ref_record **refs, t_reftable_write_to_buf(&buf[i], refs[i], sizes[i], NULL, 0, &opts); block_source_from_buf(&(*source)[i], &buf[i]); - err = reftable_reader_new(&(*readers)[i], &(*source)[i], - "name"); + err = reftable_table_new(&(*tables)[i], &(*source)[i], + "name"); check(!err); } - err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); + err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); check(!err); return mt; } -static void readers_destroy(struct reftable_reader **readers, const size_t n) +static void tables_destroy(struct reftable_table **tables, const size_t n) { for (size_t i = 0; i < n; i++) - reftable_reader_decref(readers[i]); - reftable_free(readers); + reftable_table_decref(tables[i]); + reftable_free(tables); } static void t_merged_single_record(void) @@ -77,14 +77,14 @@ static void t_merged_single_record(void) size_t sizes[] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + merged_table_from_records(refs, &bs, &tables, sizes, bufs, 3); struct reftable_ref_record ref = { 0 }; struct reftable_iterator it = { 0 }; int err; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); check(!err); err = reftable_iterator_seek_ref(&it, "a"); check(!err); @@ -94,7 +94,7 @@ static void t_merged_single_record(void) check(reftable_ref_record_equal(&r2[0], &ref, REFTABLE_HASH_SIZE_SHA1)); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); @@ -154,9 +154,9 @@ static void t_merged_refs(void) size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = - merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3); + merged_table_from_records(refs, &bs, &tables, sizes, bufs, 3); struct reftable_iterator it = { 0 }; int err; struct reftable_ref_record *out = NULL; @@ -164,7 +164,7 @@ static void t_merged_refs(void) size_t cap = 0; size_t i; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); check(!err); err = reftable_iterator_seek_ref(&it, "a"); check(!err); @@ -193,7 +193,7 @@ static void t_merged_refs(void) for (i = 0; i < 3; i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); reftable_free(bs); } @@ -238,13 +238,13 @@ static void t_merged_seek_multiple_times(void) REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, }; struct reftable_block_source *sources = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; struct reftable_merged_table *mt; - mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2); + merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); for (size_t i = 0; i < 5; i++) { int err = reftable_iterator_seek_ref(&it, "c"); @@ -266,7 +266,7 @@ static void t_merged_seek_multiple_times(void) for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, ARRAY_SIZE(refs)); + tables_destroy(tables, ARRAY_SIZE(refs)); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); reftable_merged_table_free(mt); @@ -313,14 +313,14 @@ static void t_merged_seek_multiple_times_without_draining(void) REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, }; struct reftable_block_source *sources = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; struct reftable_merged_table *mt; int err; - mt = merged_table_from_records(refs, &sources, &readers, sizes, bufs, 2); - merged_table_init_iter(mt, &it, BLOCK_TYPE_REF); + mt = merged_table_from_records(refs, &sources, &tables, sizes, bufs, 2); + merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_REF); err = reftable_iterator_seek_ref(&it, "b"); check(!err); @@ -338,7 +338,7 @@ static void t_merged_seek_multiple_times_without_draining(void) for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, ARRAY_SIZE(refs)); + tables_destroy(tables, ARRAY_SIZE(refs)); reftable_ref_record_release(&rec); reftable_iterator_destroy(&it); reftable_merged_table_free(mt); @@ -348,7 +348,7 @@ static void t_merged_seek_multiple_times_without_draining(void) static struct reftable_merged_table * merged_table_from_log_records(struct reftable_log_record **logs, struct reftable_block_source **source, - struct reftable_reader ***readers, const size_t *sizes, + struct reftable_table ***tables, const size_t *sizes, struct reftable_buf *buf, const size_t n) { struct reftable_merged_table *mt = NULL; @@ -358,8 +358,8 @@ merged_table_from_log_records(struct reftable_log_record **logs, }; int err; - REFTABLE_CALLOC_ARRAY(*readers, n); - check(*readers != NULL); + REFTABLE_CALLOC_ARRAY(*tables, n); + check(*tables != NULL); REFTABLE_CALLOC_ARRAY(*source, n); check(*source != NULL); @@ -367,12 +367,12 @@ merged_table_from_log_records(struct reftable_log_record **logs, t_reftable_write_to_buf(&buf[i], NULL, 0, logs[i], sizes[i], &opts); block_source_from_buf(&(*source)[i], &buf[i]); - err = reftable_reader_new(&(*readers)[i], &(*source)[i], - "name"); + err = reftable_table_new(&(*tables)[i], &(*source)[i], + "name"); check(!err); } - err = reftable_merged_table_new(&mt, *readers, n, REFTABLE_HASH_SHA1); + err = reftable_merged_table_new(&mt, *tables, n, REFTABLE_HASH_SHA1); check(!err); return mt; } @@ -435,9 +435,9 @@ static void t_merged_logs(void) size_t sizes[3] = { ARRAY_SIZE(r1), ARRAY_SIZE(r2), ARRAY_SIZE(r3) }; struct reftable_buf bufs[3] = { REFTABLE_BUF_INIT, REFTABLE_BUF_INIT, REFTABLE_BUF_INIT }; struct reftable_block_source *bs = NULL; - struct reftable_reader **readers = NULL; + struct reftable_table **tables = NULL; struct reftable_merged_table *mt = merged_table_from_log_records( - logs, &bs, &readers, sizes, bufs, 3); + logs, &bs, &tables, sizes, bufs, 3); struct reftable_iterator it = { 0 }; int err; struct reftable_log_record *out = NULL; @@ -445,7 +445,7 @@ static void t_merged_logs(void) size_t cap = 0; size_t i; - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); check(!err); err = reftable_iterator_seek_log(&it, "a"); check(!err); @@ -469,7 +469,7 @@ static void t_merged_logs(void) check(reftable_log_record_equal(want[i], &out[i], REFTABLE_HASH_SIZE_SHA1)); - err = merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG); + err = merged_table_init_iter(mt, &it, REFTABLE_BLOCK_TYPE_LOG); check(!err); err = reftable_iterator_seek_log_at(&it, "a", 2); check(!err); @@ -485,7 +485,7 @@ static void t_merged_logs(void) for (i = 0; i < 3; i++) reftable_buf_release(&bufs[i]); - readers_destroy(readers, 3); + tables_destroy(tables, 3); reftable_merged_table_free(mt); reftable_free(bs); } @@ -502,7 +502,7 @@ static void t_default_write_opts(void) int err; struct reftable_block_source source = { 0 }; uint32_t hash_id; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_merged_table *merged = NULL; reftable_writer_set_limits(w, 1, 1); @@ -516,18 +516,18 @@ static void t_default_write_opts(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&rd, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); - hash_id = reftable_reader_hash_id(rd); + hash_id = reftable_table_hash_id(table); check_int(hash_id, ==, REFTABLE_HASH_SHA1); - err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA256); + err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA256); check_int(err, ==, REFTABLE_FORMAT_ERROR); - err = reftable_merged_table_new(&merged, &rd, 1, REFTABLE_HASH_SHA1); + err = reftable_merged_table_new(&merged, &table, 1, REFTABLE_HASH_SHA1); check(!err); - reftable_reader_decref(rd); + reftable_table_decref(table); reftable_merged_table_free(merged); reftable_buf_release(&buf); } diff --git a/t/unit-tests/t-reftable-pq.c b/t/unit-tests/t-reftable-pq.c index f3f8a0cdf3..fb5a4eb187 100644 --- a/t/unit-tests/t-reftable-pq.c +++ b/t/unit-tests/t-reftable-pq.c @@ -21,7 +21,9 @@ static void merged_iter_pqueue_check(const struct merged_iter_pqueue *pq) static int pq_entry_equal(struct pq_entry *a, struct pq_entry *b) { - return !reftable_record_cmp(a->rec, b->rec) && (a->index == b->index); + int cmp; + check(!reftable_record_cmp(a->rec, b->rec, &cmp)); + return !cmp && (a->index == b->index); } static void t_pq_record(void) @@ -32,7 +34,7 @@ static void t_pq_record(void) char *last = NULL; for (i = 0; i < N; i++) { - reftable_record_init(&recs[i], BLOCK_TYPE_REF); + check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i); } @@ -49,11 +51,13 @@ static void t_pq_record(void) while (!merged_iter_pqueue_is_empty(pq)) { struct pq_entry top = merged_iter_pqueue_top(pq); - struct pq_entry e = merged_iter_pqueue_remove(&pq); + struct pq_entry e; + + check(!merged_iter_pqueue_remove(&pq, &e)); merged_iter_pqueue_check(&pq); check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); + check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); if (last) check_int(strcmp(last, e.rec->u.ref.refname), <, 0); last = e.rec->u.ref.refname; @@ -72,7 +76,7 @@ static void t_pq_index(void) size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - reftable_record_init(&recs[i], BLOCK_TYPE_REF); + check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } @@ -90,11 +94,13 @@ static void t_pq_index(void) for (i = N - 1; i > 0; i--) { struct pq_entry top = merged_iter_pqueue_top(pq); - struct pq_entry e = merged_iter_pqueue_remove(&pq); + struct pq_entry e; + + check(!merged_iter_pqueue_remove(&pq, &e)); merged_iter_pqueue_check(&pq); check(pq_entry_equal(&top, &e)); - check(reftable_record_type(e.rec) == BLOCK_TYPE_REF); + check(reftable_record_type(e.rec) == REFTABLE_BLOCK_TYPE_REF); check_int(e.index, ==, i); if (last) check_str(last, e.rec->u.ref.refname); @@ -111,7 +117,7 @@ static void t_merged_iter_pqueue_top(void) size_t N = ARRAY_SIZE(recs), i; for (i = 0; i < N; i++) { - reftable_record_init(&recs[i], BLOCK_TYPE_REF); + check(!reftable_record_init(&recs[i], REFTABLE_BLOCK_TYPE_REF)); recs[i].u.ref.refname = (char *) "refs/heads/master"; } @@ -129,7 +135,9 @@ static void t_merged_iter_pqueue_top(void) for (i = N - 1; i > 0; i--) { struct pq_entry top = merged_iter_pqueue_top(pq); - struct pq_entry e = merged_iter_pqueue_remove(&pq); + struct pq_entry e; + + check(!merged_iter_pqueue_remove(&pq, &e)); merged_iter_pqueue_check(&pq); check(pq_entry_equal(&top, &e)); diff --git a/t/unit-tests/t-reftable-reader.c b/t/unit-tests/t-reftable-reader.c deleted file mode 100644 index 546df6005e..0000000000 --- a/t/unit-tests/t-reftable-reader.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "test-lib.h" -#include "lib-reftable.h" -#include "reftable/blocksource.h" -#include "reftable/reader.h" - -static int t_reader_seek_once(void) -{ - struct reftable_ref_record records[] = { - { - .refname = (char *) "refs/heads/main", - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 42 }, - }, - }; - struct reftable_block_source source = { 0 }; - struct reftable_ref_record ref = { 0 }; - struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; - struct reftable_buf buf = REFTABLE_BUF_INIT; - int ret; - - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); - block_source_from_buf(&source, &buf); - - ret = reftable_reader_new(&reader, &source, "name"); - check(!ret); - - reftable_reader_init_ref_iterator(reader, &it); - ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); - ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); - - ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); - - ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); - - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - reftable_reader_decref(reader); - reftable_buf_release(&buf); - return 0; -} - -static int t_reader_reseek(void) -{ - struct reftable_ref_record records[] = { - { - .refname = (char *) "refs/heads/main", - .value_type = REFTABLE_REF_VAL1, - .value.val1 = { 42 }, - }, - }; - struct reftable_block_source source = { 0 }; - struct reftable_ref_record ref = { 0 }; - struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; - struct reftable_buf buf = REFTABLE_BUF_INIT; - int ret; - - t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); - block_source_from_buf(&source, &buf); - - ret = reftable_reader_new(&reader, &source, "name"); - check(!ret); - - reftable_reader_init_ref_iterator(reader, &it); - - for (size_t i = 0; i < 5; i++) { - ret = reftable_iterator_seek_ref(&it, ""); - check(!ret); - ret = reftable_iterator_next_ref(&it, &ref); - check(!ret); - - ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); - check_int(ret, ==, 1); - - ret = reftable_iterator_next_ref(&it, &ref); - check_int(ret, ==, 1); - } - - reftable_ref_record_release(&ref); - reftable_iterator_destroy(&it); - reftable_reader_decref(reader); - reftable_buf_release(&buf); - return 0; -} - -int cmd_main(int argc UNUSED, const char *argv[] UNUSED) -{ - TEST(t_reader_seek_once(), "reader can seek once"); - TEST(t_reader_reseek(), "reader can reseek multiple times"); - return test_done(); -} diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c index c9626831da..4c49129439 100644 --- a/t/unit-tests/t-reftable-readwrite.c +++ b/t/unit-tests/t-reftable-readwrite.c @@ -12,9 +12,9 @@ https://developers.google.com/open-source/licenses/bsd #include "lib-reftable.h" #include "reftable/basics.h" #include "reftable/blocksource.h" -#include "reftable/reader.h" #include "reftable/reftable-error.h" #include "reftable/reftable-writer.h" +#include "reftable/table.h" #include "strbuf.h" static const int update_index = 5; @@ -23,22 +23,22 @@ static void t_buffer(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_block out = { 0 }; + struct reftable_block_data out = { 0 }; int n; uint8_t in[] = "hello"; check(!reftable_buf_add(&buf, in, sizeof(in))); block_source_from_buf(&source, &buf); check_int(block_source_size(&source), ==, 6); - n = block_source_read_block(&source, &out, 0, sizeof(in)); + n = block_source_read_data(&source, &out, 0, sizeof(in)); check_int(n, ==, sizeof(in)); check(!memcmp(in, out.data, n)); - reftable_block_done(&out); + block_source_release_data(&out); - n = block_source_read_block(&source, &out, 1, 2); + n = block_source_read_data(&source, &out, 1, 2); check_int(n, ==, 2); check(!memcmp(out.data, "el", 2)); - reftable_block_done(&out); + block_source_release_data(&out); block_source_close(&source); reftable_buf_release(&buf); } @@ -204,7 +204,7 @@ static void t_log_write_read(void) struct reftable_ref_record ref = { 0 }; struct reftable_log_record log = { 0 }; struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); @@ -254,10 +254,10 @@ static void t_log_write_read(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check(!err); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, names[N - 1]); @@ -273,7 +273,7 @@ static void t_log_write_read(void) reftable_iterator_destroy(&it); reftable_ref_record_release(&ref); - err = reftable_reader_init_log_iterator(reader, &it); + err = reftable_table_init_log_iterator(table, &it); check(!err); err = reftable_iterator_seek_log(&it, ""); check(!err); @@ -294,7 +294,7 @@ static void t_log_write_read(void) /* cleanup. */ reftable_buf_release(&buf); free_names(names); - reftable_reader_decref(reader); + reftable_table_decref(table); } static void t_log_zlib_corruption(void) @@ -303,7 +303,7 @@ static void t_log_zlib_corruption(void) .block_size = 256, }; struct reftable_iterator it = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); @@ -345,10 +345,10 @@ static void t_log_zlib_corruption(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check(!err); - err = reftable_reader_init_log_iterator(reader, &it); + err = reftable_table_init_log_iterator(table, &it); check(!err); err = reftable_iterator_seek_log(&it, "refname"); check_int(err, ==, REFTABLE_ZLIB_ERROR); @@ -356,7 +356,7 @@ static void t_log_zlib_corruption(void) reftable_iterator_destroy(&it); /* cleanup. */ - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); } @@ -367,7 +367,7 @@ static void t_table_read_write_sequential(void) int N = 50; struct reftable_iterator it = { 0 }; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err = 0; int j = 0; @@ -375,10 +375,10 @@ static void t_table_read_write_sequential(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, ""); check(!err); @@ -396,7 +396,7 @@ static void t_table_read_write_sequential(void) check_int(j, ==, N); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); free_names(names); } @@ -417,7 +417,7 @@ static void t_table_read_api(void) char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; int err; struct reftable_log_record log = { 0 }; @@ -427,10 +427,10 @@ static void t_table_read_api(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, names[0]); check(!err); @@ -441,7 +441,7 @@ static void t_table_read_api(void) reftable_buf_release(&buf); free_names(names); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&buf); } @@ -450,7 +450,7 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) char **names; struct reftable_buf buf = REFTABLE_BUF_INIT; int N = 50; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; int err; int i = 0; @@ -463,18 +463,18 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); - check_int(hash_id, ==, reftable_reader_hash_id(reader)); + check_int(hash_id, ==, reftable_table_hash_id(table)); if (!index) { - reader->ref_offsets.index_offset = 0; + table->ref_offsets.index_offset = 0; } else { - check_int(reader->ref_offsets.index_offset, >, 0); + check_int(table->ref_offsets.index_offset, >, 0); } for (i = 1; i < N; i++) { - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, names[i]); check(!err); @@ -491,7 +491,7 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) check(!reftable_buf_addstr(&pastLast, names[N - 1])); check(!reftable_buf_addstr(&pastLast, "/")); - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, pastLast.buf); if (err == 0) { @@ -507,7 +507,7 @@ static void t_table_read_write_seek(int index, enum reftable_hash hash_id) reftable_buf_release(&buf); free_names(names); - reftable_reader_decref(reader); + reftable_table_decref(table); } static void t_table_read_write_seek_linear(void) @@ -535,7 +535,7 @@ static void t_table_refs_for(int indexed) .block_size = 256, }; struct reftable_ref_record ref = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; struct reftable_block_source source = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); @@ -585,18 +585,18 @@ static void t_table_refs_for(int indexed) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.ref"); + err = reftable_table_new(&table, &source, "file.ref"); check(!err); if (!indexed) - reader->obj_offsets.is_present = 0; + table->obj_offsets.is_present = 0; - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, ""); check(!err); reftable_iterator_destroy(&it); - err = reftable_reader_refs_for(reader, &it, want_hash); + err = reftable_table_refs_for(table, &it, want_hash); check(!err); for (j = 0; ; j++) { @@ -613,7 +613,7 @@ static void t_table_refs_for(int indexed) reftable_buf_release(&buf); free_names(want_names); reftable_iterator_destroy(&it); - reftable_reader_decref(reader); + reftable_table_decref(table); } static void t_table_refs_for_no_index(void) @@ -632,7 +632,7 @@ static void t_write_empty_table(void) struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_writer *w = t_reftable_strbuf_writer(&buf, &opts); struct reftable_block_source source = { 0 }; - struct reftable_reader *rd = NULL; + struct reftable_table *table = NULL; struct reftable_ref_record rec = { 0 }; struct reftable_iterator it = { 0 }; int err; @@ -647,10 +647,10 @@ static void t_write_empty_table(void) block_source_from_buf(&source, &buf); - err = reftable_reader_new(&rd, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); - err = reftable_reader_init_ref_iterator(rd, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, ""); check(!err); @@ -659,7 +659,7 @@ static void t_write_empty_table(void) check_int(err, >, 0); reftable_iterator_destroy(&it); - reftable_reader_decref(rd); + reftable_table_decref(table); reftable_buf_release(&buf); } @@ -803,7 +803,7 @@ static void t_write_multiple_indices(void) struct reftable_iterator it = { 0 }; const struct reftable_stats *stats; struct reftable_writer *writer; - struct reftable_reader *reader; + struct reftable_table *table; char buf[128]; int err, i; @@ -852,21 +852,21 @@ static void t_write_multiple_indices(void) check_int(stats->log_stats.index_offset, >, 0); block_source_from_buf(&source, &writer_buf); - err = reftable_reader_new(&reader, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); /* * Seeking the log uses the log index now. In case there is any * confusion regarding indices we would notice here. */ - err = reftable_reader_init_log_iterator(reader, &it); + err = reftable_table_init_log_iterator(table, &it); check(!err); err = reftable_iterator_seek_log(&it, ""); check(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&writer_buf); } @@ -880,7 +880,7 @@ static void t_write_multi_level_index(void) struct reftable_iterator it = { 0 }; const struct reftable_stats *stats; struct reftable_writer *writer; - struct reftable_reader *reader; + struct reftable_table *table; int err; writer = t_reftable_strbuf_writer(&writer_buf, &opts); @@ -909,20 +909,20 @@ static void t_write_multi_level_index(void) check_int(stats->ref_stats.max_index_level, ==, 2); block_source_from_buf(&source, &writer_buf); - err = reftable_reader_new(&reader, &source, "filename"); + err = reftable_table_new(&table, &source, "filename"); check(!err); /* * Seeking the last ref should work as expected. */ - err = reftable_reader_init_ref_iterator(reader, &it); + err = reftable_table_init_ref_iterator(table, &it); check(!err); err = reftable_iterator_seek_ref(&it, "refs/heads/199"); check(!err); reftable_iterator_destroy(&it); reftable_writer_free(writer); - reftable_reader_decref(reader); + reftable_table_decref(table); reftable_buf_release(&writer_buf); reftable_buf_release(&buf); } @@ -931,11 +931,11 @@ static void t_corrupt_table_empty(void) { struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err; block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check_int(err, ==, REFTABLE_FORMAT_ERROR); } @@ -944,12 +944,12 @@ static void t_corrupt_table(void) uint8_t zeros[1024] = { 0 }; struct reftable_buf buf = REFTABLE_BUF_INIT; struct reftable_block_source source = { 0 }; - struct reftable_reader *reader; + struct reftable_table *table; int err; check(!reftable_buf_add(&buf, zeros, sizeof(zeros))); block_source_from_buf(&source, &buf); - err = reftable_reader_new(&reader, &source, "file.log"); + err = reftable_table_new(&table, &source, "file.log"); check_int(err, ==, REFTABLE_FORMAT_ERROR); reftable_buf_release(&buf); diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c index d49d2a2729..553a007664 100644 --- a/t/unit-tests/t-reftable-record.c +++ b/t/unit-tests/t-reftable-record.c @@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec) uint8_t typ; typ = reftable_record_type(rec); - reftable_record_init(©, typ); + check(!reftable_record_init(©, typ)); reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); /* do it twice to catch memory leaks */ reftable_record_copy_from(©, rec, REFTABLE_HASH_SIZE_SHA1); @@ -84,32 +84,36 @@ static void t_reftable_ref_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "refs/heads/master", .u.ref.value_type = REFTABLE_REF_VAL1, }, { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "refs/heads/master", .u.ref.value_type = REFTABLE_REF_DELETION, }, { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.refname = (char *) "HEAD", .u.ref.value_type = REFTABLE_REF_SYMREF, .u.ref.value.symref = (char *) "refs/heads/master", }, }; + int cmp; check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + check(!cmp); check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + check(!reftable_record_cmp(&in[1], &in[2], &cmp)); + check_int(cmp, >, 0); in[1].u.ref.value_type = in[0].u.ref.value_type; check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + check(!cmp); } static void t_reftable_ref_record_compare_name(void) @@ -137,10 +141,10 @@ static void t_reftable_ref_record_roundtrip(void) for (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) { struct reftable_record in = { - .type = BLOCK_TYPE_REF, + .type = REFTABLE_BLOCK_TYPE_REF, .u.ref.value_type = i, }; - struct reftable_record out = { .type = BLOCK_TYPE_REF }; + struct reftable_record out = { .type = REFTABLE_BLOCK_TYPE_REF }; struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -194,32 +198,35 @@ static void t_reftable_log_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/master", .u.log.update_index = 42, }, { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/master", .u.log.update_index = 22, }, { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log.refname = (char *) "refs/heads/main", .u.log.update_index = 22, }, }; + int cmp; check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + check(!reftable_record_cmp(&in[1], &in[2], &cmp)); + check_int(cmp, >, 0); /* comparison should be reversed for equal keys, because * comparison is now performed on the basis of update indices */ - check_int(reftable_record_cmp(&in[0], &in[1]), <, 0); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + check_int(cmp, <, 0); in[1].u.log.update_index = in[0].u.log.update_index; check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); } static void t_reftable_log_record_compare_key(void) @@ -290,7 +297,7 @@ static void t_reftable_log_record_roundtrip(void) check(!reftable_log_record_is_deletion(&in[2])); for (size_t i = 0; i < ARRAY_SIZE(in); i++) { - struct reftable_record rec = { .type = BLOCK_TYPE_LOG }; + struct reftable_record rec = { .type = REFTABLE_BLOCK_TYPE_LOG }; struct reftable_buf key = REFTABLE_BUF_INIT; uint8_t buffer[1024] = { 0 }; struct string_view dest = { @@ -299,7 +306,7 @@ static void t_reftable_log_record_roundtrip(void) }; /* populate out, to check for leaks. */ struct reftable_record out = { - .type = BLOCK_TYPE_LOG, + .type = REFTABLE_BLOCK_TYPE_LOG, .u.log = { .refname = xstrdup("old name"), .value_type = REFTABLE_LOG_UPDATE, @@ -377,35 +384,39 @@ static void t_reftable_obj_record_comparison(void) uint64_t offsets[] = { 0, 16, 32, 48, 64, 80, 96, 112}; struct reftable_record in[3] = { { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 7, .u.obj.offsets = offsets, .u.obj.offset_len = 8, }, { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 7, .u.obj.offsets = offsets, .u.obj.offset_len = 5, }, { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u.obj.hash_prefix = id_bytes, .u.obj.hash_prefix_len = 5, }, }; + int cmp; check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + check(!cmp); check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + check(!reftable_record_cmp(&in[1], &in[2], &cmp)); + check_int(cmp, >, 0); in[1].u.obj.offset_len = in[0].u.obj.offset_len; check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + check(!cmp); } static void t_reftable_obj_record_roundtrip(void) @@ -439,13 +450,13 @@ static void t_reftable_obj_record_roundtrip(void) .len = sizeof(buffer), }; struct reftable_record in = { - .type = BLOCK_TYPE_OBJ, + .type = REFTABLE_BLOCK_TYPE_OBJ, .u = { .obj = recs[i], }, }; struct reftable_buf key = REFTABLE_BUF_INIT; - struct reftable_record out = { .type = BLOCK_TYPE_OBJ }; + struct reftable_record out = { .type = REFTABLE_BLOCK_TYPE_OBJ }; int n, m; uint8_t extra; @@ -471,34 +482,39 @@ static void t_reftable_index_record_comparison(void) { struct reftable_record in[3] = { { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 22, .u.idx.last_key = REFTABLE_BUF_INIT, }, { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 32, .u.idx.last_key = REFTABLE_BUF_INIT, }, { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx.offset = 32, .u.idx.last_key = REFTABLE_BUF_INIT, }, }; + int cmp; + check(!reftable_buf_addstr(&in[0].u.idx.last_key, "refs/heads/master")); check(!reftable_buf_addstr(&in[1].u.idx.last_key, "refs/heads/master")); check(!reftable_buf_addstr(&in[2].u.idx.last_key, "refs/heads/branch")); check(!reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + check(!cmp); check(!reftable_record_equal(&in[1], &in[2], REFTABLE_HASH_SIZE_SHA1)); - check_int(reftable_record_cmp(&in[1], &in[2]), >, 0); + check(!reftable_record_cmp(&in[1], &in[2], &cmp)); + check_int(cmp, >, 0); in[1].u.idx.offset = in[0].u.idx.offset; check(reftable_record_equal(&in[0], &in[1], REFTABLE_HASH_SIZE_SHA1)); - check(!reftable_record_cmp(&in[0], &in[1])); + check(!reftable_record_cmp(&in[0], &in[1], &cmp)); + check(!cmp); for (size_t i = 0; i < ARRAY_SIZE(in); i++) reftable_record_release(&in[i]); @@ -507,7 +523,7 @@ static void t_reftable_index_record_comparison(void) static void t_reftable_index_record_roundtrip(void) { struct reftable_record in = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .offset = 42, .last_key = REFTABLE_BUF_INIT, @@ -521,7 +537,7 @@ static void t_reftable_index_record_roundtrip(void) struct reftable_buf scratch = REFTABLE_BUF_INIT; struct reftable_buf key = REFTABLE_BUF_INIT; struct reftable_record out = { - .type = BLOCK_TYPE_INDEX, + .type = REFTABLE_BLOCK_TYPE_INDEX, .u.idx = { .last_key = REFTABLE_BUF_INIT }, }; int n, m; diff --git a/t/unit-tests/t-reftable-stack.c b/t/unit-tests/t-reftable-stack.c index c3f0059c34..2f49c97519 100644 --- a/t/unit-tests/t-reftable-stack.c +++ b/t/unit-tests/t-reftable-stack.c @@ -12,9 +12,9 @@ https://developers.google.com/open-source/licenses/bsd #include "lib-reftable.h" #include "dir.h" #include "reftable/merged.h" -#include "reftable/reader.h" #include "reftable/reftable-error.h" #include "reftable/stack.h" +#include "reftable/table.h" #include "strbuf.h" #include "tempfile.h" #include <dirent.h> @@ -176,7 +176,7 @@ static void t_reftable_stack_add_one(void) err = reftable_stack_read_ref(st, ref.refname, &dest); check(!err); check(reftable_ref_record_equal(&ref, &dest, REFTABLE_HASH_SIZE_SHA1)); - check_int(st->readers_len, >, 0); + check_int(st->tables_len, >, 0); #ifndef GIT_WINDOWS_NATIVE check(!reftable_buf_addstr(&scratch, dir)); @@ -189,7 +189,7 @@ static void t_reftable_stack_add_one(void) check(!reftable_buf_addstr(&scratch, dir)); check(!reftable_buf_addstr(&scratch, "/")); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&scratch, st->readers[0]->name)); + check(!reftable_buf_addstr(&scratch, st->tables[0]->name)); err = stat(scratch.buf, &stat_result); check(!err); check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); @@ -402,9 +402,9 @@ static void t_reftable_stack_transaction_api_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->readers_len, ==, i + 1); + check_int(st->merged->tables_len, ==, i + 1); else - check_int(st->merged->readers_len, ==, 1); + check_int(st->merged->tables_len, ==, 1); } reftable_stack_destroy(st); @@ -430,7 +430,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void) err = reftable_stack_add(st, write_test_ref, &ref); check(!err); - check_int(st->merged->readers_len, ==, 1); + check_int(st->merged->tables_len, ==, 1); check_int(st->stats.attempts, ==, 0); check_int(st->stats.failures, ==, 0); @@ -441,14 +441,14 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void) */ check(!reftable_buf_addstr(&table_path, dir)); check(!reftable_buf_addstr(&table_path, "/")); - check(!reftable_buf_addstr(&table_path, st->readers[0]->name)); + check(!reftable_buf_addstr(&table_path, st->tables[0]->name)); check(!reftable_buf_addstr(&table_path, ".lock")); write_file_buf(table_path.buf, "", 0); ref.update_index = 2; err = reftable_stack_add(st, write_test_ref, &ref); check(!err); - check_int(st->merged->readers_len, ==, 2); + check_int(st->merged->tables_len, ==, 2); check_int(st->stats.attempts, ==, 1); check_int(st->stats.failures, ==, 1); @@ -592,7 +592,7 @@ static void t_reftable_stack_add(void) check(!reftable_buf_addstr(&path, dir)); check(!reftable_buf_addstr(&path, "/")); /* do not try at home; not an external API for reftable. */ - check(!reftable_buf_addstr(&path, st->readers[0]->name)); + check(!reftable_buf_addstr(&path, st->tables[0]->name)); err = stat(path.buf, &stat_result); check(!err); check_int((stat_result.st_mode & 0777), ==, opts.default_permissions); @@ -1026,7 +1026,7 @@ static void t_reftable_stack_auto_compaction(void) err = reftable_stack_auto_compact(st); check(!err); - check(i < 2 || st->merged->readers_len < 2 * fastlogN(i, 2)); + check(i < 2 || st->merged->tables_len < 2 * fastlogN(i, 2)); } check_int(reftable_stack_compaction_stats(st)->entries_written, <, @@ -1061,7 +1061,7 @@ static void t_reftable_stack_auto_compaction_factor(void) err = reftable_stack_add(st, &write_test_ref, &ref); check(!err); - check(i < 5 || st->merged->readers_len < 5 * fastlogN(i, 5)); + check(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5)); } reftable_stack_destroy(st); @@ -1082,7 +1082,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) check(!err); write_n_ref_tables(st, 5); - check_int(st->merged->readers_len, ==, 5); + check_int(st->merged->tables_len, ==, 5); /* * Given that all tables we have written should be roughly the same @@ -1091,7 +1091,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) */ check(!reftable_buf_addstr(&buf, dir)); check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->readers[2]->name)); + check(!reftable_buf_addstr(&buf, st->tables[2]->name)); check(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); @@ -1104,7 +1104,7 @@ static void t_reftable_stack_auto_compaction_with_locked_tables(void) err = reftable_stack_auto_compact(st); check(!err); check_int(st->stats.failures, ==, 0); - check_int(st->merged->readers_len, ==, 4); + check_int(st->merged->tables_len, ==, 4); reftable_stack_destroy(st); reftable_buf_release(&buf); @@ -1149,9 +1149,9 @@ static void t_reftable_stack_add_performs_auto_compaction(void) * all tables in the stack. */ if (i != n) - check_int(st->merged->readers_len, ==, i + 1); + check_int(st->merged->tables_len, ==, i + 1); else - check_int(st->merged->readers_len, ==, 1); + check_int(st->merged->tables_len, ==, 1); } reftable_stack_destroy(st); @@ -1172,12 +1172,12 @@ static void t_reftable_stack_compaction_with_locked_tables(void) check(!err); write_n_ref_tables(st, 3); - check_int(st->merged->readers_len, ==, 3); + check_int(st->merged->tables_len, ==, 3); /* Lock one of the tables that we're about to compact. */ check(!reftable_buf_addstr(&buf, dir)); check(!reftable_buf_addstr(&buf, "/")); - check(!reftable_buf_addstr(&buf, st->readers[1]->name)); + check(!reftable_buf_addstr(&buf, st->tables[1]->name)); check(!reftable_buf_addstr(&buf, ".lock")); write_file_buf(buf.buf, "", 0); @@ -1188,7 +1188,7 @@ static void t_reftable_stack_compaction_with_locked_tables(void) err = reftable_stack_compact_all(st, NULL); check_int(err, ==, REFTABLE_LOCK_ERROR); check_int(st->stats.failures, ==, 1); - check_int(st->merged->readers_len, ==, 3); + check_int(st->merged->tables_len, ==, 3); reftable_stack_destroy(st); reftable_buf_release(&buf); @@ -1222,10 +1222,10 @@ static void t_reftable_stack_compaction_concurrent(void) static void unclean_stack_close(struct reftable_stack *st) { /* break abstraction boundary to simulate unclean shutdown. */ - for (size_t i = 0; i < st->readers_len; i++) - reftable_reader_decref(st->readers[i]); - st->readers_len = 0; - REFTABLE_FREE_AND_NULL(st->readers); + for (size_t i = 0; i < st->tables_len; i++) + reftable_table_decref(st->tables[i]); + st->tables_len = 0; + REFTABLE_FREE_AND_NULL(st->tables); } static void t_reftable_stack_compaction_concurrent_clean(void) @@ -1275,7 +1275,7 @@ static void t_reftable_stack_read_across_reload(void) err = reftable_new_stack(&st1, dir, &opts); check(!err); write_n_ref_tables(st1, 2); - check_int(st1->merged->readers_len, ==, 2); + check_int(st1->merged->tables_len, ==, 2); reftable_stack_init_ref_iterator(st1, &it); err = reftable_iterator_seek_ref(&it, ""); check(!err); @@ -1283,10 +1283,10 @@ static void t_reftable_stack_read_across_reload(void) /* Set up a second stack for the same directory and compact it. */ err = reftable_new_stack(&st2, dir, &opts); check(!err); - check_int(st2->merged->readers_len, ==, 2); + check_int(st2->merged->tables_len, ==, 2); err = reftable_stack_compact_all(st2, NULL); check(!err); - check_int(st2->merged->readers_len, ==, 1); + check_int(st2->merged->tables_len, ==, 1); /* * Verify that we can continue to use the old iterator even after we @@ -1294,7 +1294,7 @@ static void t_reftable_stack_read_across_reload(void) */ err = reftable_stack_reload(st1); check(!err); - check_int(st1->merged->readers_len, ==, 1); + check_int(st1->merged->tables_len, ==, 1); err = reftable_iterator_next_ref(&it, &rec); check(!err); check_str(rec.refname, "refs/heads/branch-0000"); @@ -1325,19 +1325,19 @@ static void t_reftable_stack_reload_with_missing_table(void) err = reftable_new_stack(&st, dir, &opts); check(!err); write_n_ref_tables(st, 2); - check_int(st->merged->readers_len, ==, 2); + check_int(st->merged->tables_len, ==, 2); reftable_stack_init_ref_iterator(st, &it); err = reftable_iterator_seek_ref(&it, ""); check(!err); /* * Update the tables.list file with some garbage data, while reusing - * our old readers. This should trigger a partial reload of the stack, - * where we try to reuse our old readers. + * our old tables. This should trigger a partial reload of the stack, + * where we try to reuse our old tables. */ - check(!reftable_buf_addstr(&content, st->readers[0]->name)); + check(!reftable_buf_addstr(&content, st->tables[0]->name)); check(!reftable_buf_addstr(&content, "\n")); - check(!reftable_buf_addstr(&content, st->readers[1]->name)); + check(!reftable_buf_addstr(&content, st->tables[1]->name)); check(!reftable_buf_addstr(&content, "\n")); check(!reftable_buf_addstr(&content, "garbage\n")); check(!reftable_buf_addstr(&table_path, st->list_file)); @@ -1348,7 +1348,7 @@ static void t_reftable_stack_reload_with_missing_table(void) err = reftable_stack_reload(st); check_int(err, ==, -4); - check_int(st->merged->readers_len, ==, 2); + check_int(st->merged->tables_len, ==, 2); /* * Even though the reload has failed, we should be able to continue diff --git a/t/unit-tests/t-reftable-table.c b/t/unit-tests/t-reftable-table.c new file mode 100644 index 0000000000..7e1eb533d0 --- /dev/null +++ b/t/unit-tests/t-reftable-table.c @@ -0,0 +1,206 @@ +#include "test-lib.h" +#include "lib-reftable.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/iter.h" +#include "reftable/table.h" +#include "strbuf.h" + +static int t_table_seek_once(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + check(!ret); + + reftable_table_init_ref_iterator(table, &it); + ret = reftable_iterator_seek_ref(&it, ""); + check(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + check(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); + check_int(ret, ==, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + check_int(ret, ==, 1); + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); + return 0; +} + +static int t_table_reseek(void) +{ + struct reftable_ref_record records[] = { + { + .refname = (char *) "refs/heads/main", + .value_type = REFTABLE_REF_VAL1, + .value.val1 = { 42 }, + }, + }; + struct reftable_block_source source = { 0 }; + struct reftable_ref_record ref = { 0 }; + struct reftable_iterator it = { 0 }; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + int ret; + + t_reftable_write_to_buf(&buf, records, ARRAY_SIZE(records), NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + check(!ret); + + reftable_table_init_ref_iterator(table, &it); + + for (size_t i = 0; i < 5; i++) { + ret = reftable_iterator_seek_ref(&it, ""); + check(!ret); + ret = reftable_iterator_next_ref(&it, &ref); + check(!ret); + + ret = reftable_ref_record_equal(&ref, &records[0], REFTABLE_HASH_SIZE_SHA1); + check_int(ret, ==, 1); + + ret = reftable_iterator_next_ref(&it, &ref); + check_int(ret, ==, 1); + } + + reftable_ref_record_release(&ref); + reftable_iterator_destroy(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); + return 0; +} + +static int t_table_block_iterator(void) +{ + struct reftable_block_source source = { 0 }; + struct reftable_table_iterator it = { 0 }; + struct reftable_ref_record *records; + const struct reftable_block *block; + struct reftable_table *table; + struct reftable_buf buf = REFTABLE_BUF_INIT; + struct { + uint8_t block_type; + uint16_t header_off; + uint16_t restart_count; + uint16_t record_count; + } expected_blocks[] = { + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .header_off = 24, + .restart_count = 10, + .record_count = 158, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 10, + .record_count = 159, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 10, + .record_count = 159, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_REF, + .restart_count = 2, + .record_count = 24, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_INDEX, + .restart_count = 1, + .record_count = 4, + }, + { + .block_type = REFTABLE_BLOCK_TYPE_OBJ, + .restart_count = 1, + .record_count = 1, + }, + }; + const size_t nrecords = 500; + int ret; + + REFTABLE_CALLOC_ARRAY(records, nrecords); + for (size_t i = 0; i < nrecords; i++) { + records[i].value_type = REFTABLE_REF_VAL1; + records[i].refname = xstrfmt("refs/heads/branch-%03"PRIuMAX, + (uintmax_t) i); + } + + t_reftable_write_to_buf(&buf, records, nrecords, NULL, 0, NULL); + block_source_from_buf(&source, &buf); + + ret = reftable_table_new(&table, &source, "name"); + check(!ret); + + ret = reftable_table_iterator_init(&it, table); + check(!ret); + + for (size_t i = 0; i < ARRAY_SIZE(expected_blocks); i++) { + struct reftable_iterator record_it = { 0 }; + struct reftable_record record = { + .type = expected_blocks[i].block_type, + }; + + ret = reftable_table_iterator_next(&it, &block); + check(!ret); + + check_int(block->block_type, ==, expected_blocks[i].block_type); + check_int(block->header_off, ==, expected_blocks[i].header_off); + check_int(block->restart_count, ==, expected_blocks[i].restart_count); + + ret = reftable_block_init_iterator(block, &record_it); + check(!ret); + + for (size_t j = 0; ; j++) { + ret = iterator_next(&record_it, &record); + if (ret > 0) { + check_int(j, ==, expected_blocks[i].record_count); + break; + } + check(!ret); + } + + reftable_iterator_destroy(&record_it); + reftable_record_release(&record); + } + + ret = reftable_table_iterator_next(&it, &block); + check_int(ret, ==, 1); + + for (size_t i = 0; i < nrecords; i++) + reftable_free(records[i].refname); + reftable_table_iterator_release(&it); + reftable_table_decref(table); + reftable_buf_release(&buf); + reftable_free(records); + return 0; +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_table_seek_once(), "table can seek once"); + TEST(t_table_reseek(), "table can reseek multiple times"); + TEST(t_table_block_iterator(), "table can iterate through blocks"); + return test_done(); +} diff --git a/t/unit-tests/t-trailer.c b/t/unit-tests/t-trailer.c deleted file mode 100644 index 184593e73d..0000000000 --- a/t/unit-tests/t-trailer.c +++ /dev/null @@ -1,317 +0,0 @@ -#define DISABLE_SIGN_COMPARE_WARNINGS - -#include "test-lib.h" -#include "trailer.h" - -struct contents { - const char *raw; - const char *key; - const char *val; -}; - -static void t_trailer_iterator(const char *msg, size_t num_expected, - struct contents *contents) -{ - struct trailer_iterator iter; - size_t i = 0; - - trailer_iterator_init(&iter, msg); - while (trailer_iterator_advance(&iter)) { - if (num_expected) { - check_str(iter.raw, contents[i].raw); - check_str(iter.key.buf, contents[i].key); - check_str(iter.val.buf, contents[i].val); - } - i++; - } - trailer_iterator_release(&iter); - - check_uint(i, ==, num_expected); -} - -static void run_t_trailer_iterator(void) -{ - - static struct test_cases { - const char *name; - const char *msg; - size_t num_expected; - struct contents contents[10]; - } tc[] = { - { - "empty input", - "", - 0, - {{0}}, - }, - { - "no newline at beginning", - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n", - 0, - {{0}}, - }, - { - "newline at beginning", - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n", - 3, - { - { - .raw = "Fixes: x\n", - .key = "Fixes", - .val = "x", - }, - { - .raw = "Acked-by: x\n", - .key = "Acked-by", - .val = "x", - }, - { - .raw = "Reviewed-by: x\n", - .key = "Reviewed-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "without body text", - "subject: foo bar\n" - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n", - 3, - { - { - .raw = "Fixes: x\n", - .key = "Fixes", - .val = "x", - }, - { - .raw = "Acked-by: x\n", - .key = "Acked-by", - .val = "x", - }, - { - .raw = "Reviewed-by: x\n", - .key = "Reviewed-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with body text, without divider", - "my subject\n" - "\n" - "my body which is long\n" - "and contains some special\n" - "chars like : = ? !\n" - "hello\n" - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n" - "Signed-off-by: x\n", - 4, - { - { - .raw = "Fixes: x\n", - .key = "Fixes", - .val = "x", - }, - { - .raw = "Acked-by: x\n", - .key = "Acked-by", - .val = "x", - }, - { - .raw = "Reviewed-by: x\n", - .key = "Reviewed-by", - .val = "x", - }, - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with body text, without divider (second trailer block)", - "my subject\n" - "\n" - "my body which is long\n" - "and contains some special\n" - "chars like : = ? !\n" - "hello\n" - "\n" - "Fixes: x\n" - "Acked-by: x\n" - "Reviewed-by: x\n" - "Signed-off-by: x\n" - "\n" - /* - * Because this is the last trailer block, it takes - * precedence over the first one encountered above. - */ - "Helped-by: x\n" - "Signed-off-by: x\n", - 2, - { - { - .raw = "Helped-by: x\n", - .key = "Helped-by", - .val = "x", - }, - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with body text, with divider", - "my subject\n" - "\n" - "my body which is long\n" - "and contains some special\n" - "chars like : = ? !\n" - "hello\n" - "\n" - "---\n" - "\n" - /* - * This trailer still counts because the iterator - * always ignores the divider. - */ - "Signed-off-by: x\n", - 1, - { - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with non-trailer lines in trailer block", - "subject: foo bar\n" - "\n" - /* - * Even though this trailer block has a non-trailer line - * in it, it's still a valid trailer block because it's - * at least 25% trailers and is Git-generated (see - * git_generated_prefixes[] in trailer.c). - */ - "not a trailer line\n" - "not a trailer line\n" - "not a trailer line\n" - "Signed-off-by: x\n", - /* - * Even though there is only really 1 real "trailer" - * (Signed-off-by), we still have 4 trailer objects - * because we still want to iterate through the entire - * block. - */ - 4, - { - { - .raw = "not a trailer line\n", - .key = "not a trailer line", - .val = "", - }, - { - .raw = "not a trailer line\n", - .key = "not a trailer line", - .val = "", - }, - { - .raw = "not a trailer line\n", - .key = "not a trailer line", - .val = "", - }, - { - .raw = "Signed-off-by: x\n", - .key = "Signed-off-by", - .val = "x", - }, - { - 0 - }, - }, - }, - { - "with non-trailer lines (one too many) in trailer block", - "subject: foo bar\n" - "\n" - /* - * This block has only 20% trailers, so it's below the - * 25% threshold. - */ - "not a trailer line\n" - "not a trailer line\n" - "not a trailer line\n" - "not a trailer line\n" - "Signed-off-by: x\n", - 0, - {{0}}, - }, - { - "with non-trailer lines (only 1) in trailer block, but no Git-generated trailers", - "subject: foo bar\n" - "\n" - /* - * This block has only 1 non-trailer out of 10 (IOW, 90% - * trailers) but is not considered a trailer block - * because the 25% threshold only applies to cases where - * there was a Git-generated trailer. - */ - "Reviewed-by: x\n" - "Reviewed-by: x\n" - "Reviewed-by: x\n" - "Helped-by: x\n" - "Helped-by: x\n" - "Helped-by: x\n" - "Acked-by: x\n" - "Acked-by: x\n" - "Acked-by: x\n" - "not a trailer line\n", - 0, - {{0}}, - }, - }; - - for (int i = 0; i < sizeof(tc) / sizeof(tc[0]); i++) { - TEST(t_trailer_iterator(tc[i].msg, - tc[i].num_expected, - tc[i].contents), - "%s", tc[i].name); - } -} - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - run_t_trailer_iterator(); - return test_done(); -} diff --git a/t/unit-tests/u-oidmap.c b/t/unit-tests/u-oidmap.c index dc805b7e3c..b23af449f6 100644 --- a/t/unit-tests/u-oidmap.c +++ b/t/unit-tests/u-oidmap.c @@ -35,7 +35,7 @@ void test_oidmap__initialize(void) void test_oidmap__cleanup(void) { - oidmap_free(&map, 1); + oidmap_clear(&map, 1); } void test_oidmap__replace(void) diff --git a/t/unit-tests/u-trailer.c b/t/unit-tests/u-trailer.c new file mode 100644 index 0000000000..3d60ea1603 --- /dev/null +++ b/t/unit-tests/u-trailer.c @@ -0,0 +1,320 @@ +#define DISABLE_SIGN_COMPARE_WARNINGS + +#include "unit-test.h" +#include "trailer.h" + +struct contents { + const char *raw; + const char *key; + const char *val; +}; + +static void t_trailer_iterator(const char *msg, size_t num_expected, + struct contents *contents) +{ + struct trailer_iterator iter; + size_t i = 0; + + trailer_iterator_init(&iter, msg); + while (trailer_iterator_advance(&iter)) { + if (num_expected) { + cl_assert_equal_s(iter.raw, contents[i].raw); + cl_assert_equal_s(iter.key.buf, contents[i].key); + cl_assert_equal_s(iter.val.buf, contents[i].val); + } + i++; + } + trailer_iterator_release(&iter); + + cl_assert_equal_i(i, num_expected); +} + +void test_trailer__empty_input(void) +{ + struct contents expected_contents[] = { 0 }; + t_trailer_iterator("", 0, expected_contents); +} + +void test_trailer__no_newline_start(void) +{ + struct contents expected_contents[] = { 0 }; + + t_trailer_iterator("Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n", + 0, + expected_contents); +} + +void test_trailer__newline_start(void) +{ + struct contents expected_contents[] = { + { + .raw = "Fixes: x\n", + .key = "Fixes", + .val = "x", + }, + { + .raw = "Acked-by: x\n", + .key = "Acked-by", + .val = "x", + }, + { + .raw = "Reviewed-by: x\n", + .key = "Reviewed-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n", + 3, + expected_contents); +} + +void test_trailer__no_body_text(void) +{ + struct contents expected_contents[] = { + + { + .raw = "Fixes: x\n", + .key = "Fixes", + .val = "x", + }, + { + .raw = "Acked-by: x\n", + .key = "Acked-by", + .val = "x", + }, + { + .raw = "Reviewed-by: x\n", + .key = "Reviewed-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n", + 3, + expected_contents); +} + +void test_trailer__body_text_no_divider(void) +{ + struct contents expected_contents[] = { + { + .raw = "Fixes: x\n", + .key = "Fixes", + .val = "x", + }, + { + .raw = "Acked-by: x\n", + .key = "Acked-by", + .val = "x", + }, + { + .raw = "Reviewed-by: x\n", + .key = "Reviewed-by", + .val = "x", + }, + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("my subject\n" + "\n" + "my body which is long\n" + "and contains some special\n" + "chars like : = ? !\n" + "hello\n" + "\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n" + "Signed-off-by: x\n", + 4, + expected_contents); +} + +void test_trailer__body_no_divider_2nd_block(void) +{ + struct contents expected_contents[] = { + { + .raw = "Helped-by: x\n", + .key = "Helped-by", + .val = "x", + }, + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("my subject\n" + "\n" + "my body which is long\n" + "and contains some special\n" + "chars like : = ? !\n" + "hello\n" + "\n" + "Fixes: x\n" + "Acked-by: x\n" + "Reviewed-by: x\n" + "Signed-off-by: x\n" + "\n" + /* + * Because this is the last trailer block, it takes + * precedence over the first one encountered above. + */ + "Helped-by: x\n" + "Signed-off-by: x\n", + 2, + expected_contents); +} + +void test_trailer__body_and_divider(void) +{ + struct contents expected_contents[] = { + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("my subject\n" + "\n" + "my body which is long\n" + "and contains some special\n" + "chars like : = ? !\n" + "hello\n" + "\n" + "---\n" + "\n" + /* + * This trailer still counts because the iterator + * always ignores the divider. + */ + "Signed-off-by: x\n", + 1, + expected_contents); +} + +void test_trailer__non_trailer_in_block(void) +{ + struct contents expected_contents[] = { + { + .raw = "not a trailer line\n", + .key = "not a trailer line", + .val = "", + }, + { + .raw = "not a trailer line\n", + .key = "not a trailer line", + .val = "", + }, + { + .raw = "not a trailer line\n", + .key = "not a trailer line", + .val = "", + }, + { + .raw = "Signed-off-by: x\n", + .key = "Signed-off-by", + .val = "x", + }, + { + 0 + }, + }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + /* + * Even though this trailer block has a non-trailer line + * in it, it's still a valid trailer block because it's + * at least 25% trailers and is Git-generated (see + * git_generated_prefixes[] in trailer.c). + */ + "not a trailer line\n" + "not a trailer line\n" + "not a trailer line\n" + "Signed-off-by: x\n", + /* + * Even though there is only really 1 real "trailer" + * (Signed-off-by), we still have 4 trailer objects + * because we still want to iterate through the entire + * block. + */ + 4, + expected_contents); +} + +void test_trailer__too_many_non_trailers(void) +{ + struct contents expected_contents[] = { 0 }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + /* + * This block has only 20% trailers, so it's below the + * 25% threshold. + */ + "not a trailer line\n" + "not a trailer line\n" + "not a trailer line\n" + "not a trailer line\n" + "Signed-off-by: x\n", + 0, + expected_contents); +} + +void test_trailer__one_non_trailer_no_git_trailers(void) +{ + struct contents expected_contents[] = { 0 }; + + t_trailer_iterator("subject: foo bar\n" + "\n" + /* + * This block has only 1 non-trailer out of 10 (IOW, 90% + * trailers) but is not considered a trailer block + * because the 25% threshold only applies to cases where + * there was a Git-generated trailer. + */ + "Reviewed-by: x\n" + "Reviewed-by: x\n" + "Reviewed-by: x\n" + "Helped-by: x\n" + "Helped-by: x\n" + "Helped-by: x\n" + "Acked-by: x\n" + "Acked-by: x\n" + "Acked-by: x\n" + "not a trailer line\n", + 0, + expected_contents); +} diff --git a/t/unit-tests/t-urlmatch-normalization.c b/t/unit-tests/u-urlmatch-normalization.c index 1769c357b9..39f6e1ba26 100644 --- a/t/unit-tests/t-urlmatch-normalization.c +++ b/t/unit-tests/u-urlmatch-normalization.c @@ -1,12 +1,11 @@ -#include "test-lib.h" +#include "unit-test.h" #include "urlmatch.h" static void check_url_normalizable(const char *url, unsigned int normalizable) { char *url_norm = url_normalize(url, NULL); - if (!check_int(normalizable, ==, url_norm ? 1 : 0)) - test_msg("input url: %s", url); + cl_assert_equal_i(normalizable, url_norm ? 1 : 0); free(url_norm); } @@ -14,8 +13,7 @@ static void check_normalized_url(const char *url, const char *expect) { char *url_norm = url_normalize(url, NULL); - if (!check_str(url_norm, expect)) - test_msg("input url: %s", url); + cl_assert_equal_s(url_norm, expect); free(url_norm); } @@ -26,13 +24,9 @@ static void compare_normalized_urls(const char *url1, const char *url2, char *url2_norm = url_normalize(url2, NULL); if (equal) { - if (!check_str(url1_norm, url2_norm)) - test_msg("input url1: %s\n input url2: %s", url1, - url2); - } else if (!check_int(strcmp(url1_norm, url2_norm), !=, 0)) { - test_msg(" normalized url1: %s\n normalized url2: %s\n" - " input url1: %s\n input url2: %s", - url1_norm, url2_norm, url1, url2); + cl_assert_equal_s(url1_norm, url2_norm); + } else { + cl_assert(strcmp(url1_norm, url2_norm) != 0); } free(url1_norm); free(url2_norm); @@ -43,14 +37,12 @@ static void check_normalized_url_length(const char *url, size_t len) struct url_info info; char *url_norm = url_normalize(url, &info); - if (!check_int(info.url_len, ==, len)) - test_msg(" input url: %s\n normalized url: %s", url, - url_norm); + cl_assert_equal_i(info.url_len, len); free(url_norm); } /* Note that only "file:" URLs should be allowed without a host */ -static void t_url_scheme(void) +void test_urlmatch_normalization__scheme(void) { check_url_normalizable("", 0); check_url_normalizable("_", 0); @@ -73,7 +65,7 @@ static void t_url_scheme(void) check_normalized_url("AbCdeF://x.Y", "abcdef://x.y/"); } -static void t_url_authority(void) +void test_urlmatch_normalization__authority(void) { check_url_normalizable("scheme://user:pass@", 0); check_url_normalizable("scheme://?", 0); @@ -109,7 +101,7 @@ static void t_url_authority(void) check_url_normalizable("scheme://invalid....:[", 0); } -static void t_url_port(void) +void test_urlmatch_normalization__port(void) { check_url_normalizable("xyz://q@some.host:", 1); check_url_normalizable("xyz://q@some.host:456/", 1); @@ -139,7 +131,7 @@ static void t_url_port(void) check_url_normalizable("xyz://[::1]:030f/", 0); } -static void t_url_port_normalization(void) +void test_urlmatch_normalization__port_normalization(void) { check_normalized_url("http://x:800", "http://x:800/"); check_normalized_url("http://x:0800", "http://x:800/"); @@ -154,7 +146,7 @@ static void t_url_port_normalization(void) check_normalized_url("https://x:000000443", "https://x/"); } -static void t_url_general_escape(void) +void test_urlmatch_normalization__general_escape(void) { check_url_normalizable("http://x.y?%fg", 0); check_normalized_url("X://W/%7e%41^%3a", "x://w/~A%5E%3A"); @@ -164,7 +156,7 @@ static void t_url_general_escape(void) check_normalized_url("X://W?!", "x://w/?!"); } -static void t_url_high_bit(void) +void test_urlmatch_normalization__high_bit(void) { check_normalized_url( "x://q/\x01\x02\x03\x04\x05\x06\x07\x08\x0e\x0f\x10\x11\x12", @@ -198,26 +190,26 @@ static void t_url_high_bit(void) "x://q/%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"); } -static void t_url_utf8_escape(void) +void test_urlmatch_normalization__utf8_escape(void) { check_normalized_url( "x://q/\xc2\x80\xdf\xbf\xe0\xa0\x80\xef\xbf\xbd\xf0\x90\x80\x80\xf0\xaf\xbf\xbd", "x://q/%C2%80%DF%BF%E0%A0%80%EF%BF%BD%F0%90%80%80%F0%AF%BF%BD"); } -static void t_url_username_pass(void) +void test_urlmatch_normalization__username_pass(void) { check_normalized_url("x://%41%62(^):%70+d@foo", "x://Ab(%5E):p+d@foo/"); } -static void t_url_length(void) +void test_urlmatch_normalization__length(void) { check_normalized_url_length("Http://%4d%65:%4d^%70@The.Host", 25); check_normalized_url_length("http://%41:%42@x.y/%61/", 17); check_normalized_url_length("http://@x.y/^", 15); } -static void t_url_dots(void) +void test_urlmatch_normalization__dots(void) { check_normalized_url("x://y/.", "x://y/"); check_normalized_url("x://y/./", "x://y/"); @@ -244,7 +236,7 @@ static void t_url_dots(void) * "http://foo" specifies neither a user name nor a password. * So they should not be equivalent. */ -static void t_url_equivalents(void) +void test_urlmatch_normalization__equivalents(void) { compare_normalized_urls("httP://x", "Http://X/", 1); compare_normalized_urls("Http://%4d%65:%4d^%70@The.Host", "hTTP://Me:%4D^p@the.HOST:80/", 1); @@ -253,19 +245,3 @@ static void t_url_equivalents(void) compare_normalized_urls("https://@x.y/^/../abc", "httpS://@x.y:0443/abc", 1); compare_normalized_urls("https://@x.y/^/..", "httpS://@x.y:0443/", 1); } - -int cmd_main(int argc UNUSED, const char **argv UNUSED) -{ - TEST(t_url_scheme(), "url scheme"); - TEST(t_url_authority(), "url authority"); - TEST(t_url_port(), "url port checks"); - TEST(t_url_port_normalization(), "url port normalization"); - TEST(t_url_general_escape(), "url general escapes"); - TEST(t_url_high_bit(), "url high-bit escapes"); - TEST(t_url_utf8_escape(), "url utf8 escapes"); - TEST(t_url_username_pass(), "url username/password escapes"); - TEST(t_url_length(), "url normalized lengths"); - TEST(t_url_dots(), "url . and .. segments"); - TEST(t_url_equivalents(), "url equivalents"); - return test_done(); -} @@ -5,7 +5,7 @@ #include "environment.h" #include "tag.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "tree.h" #include "blob.h" diff --git a/templates/meson.build b/templates/meson.build index 1faf9a44ce..02e6eebe80 100644 --- a/templates/meson.build +++ b/templates/meson.build @@ -1,6 +1,6 @@ template_config = configuration_data() -template_config.set('PERL_PATH', perl.found() ? fs.as_posix(perl.full_path()) : '') -template_config.set('SHELL_PATH', fs.as_posix(shell.full_path())) +template_config.set('PERL_PATH', target_perl.found() ? fs.as_posix(target_perl.full_path()) : '') +template_config.set('SHELL_PATH', fs.as_posix(target_shell.full_path())) template_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) configure_file( diff --git a/thread-utils.c b/thread-utils.c index 1f89ffab4c..374890e6b0 100644 --- a/thread-utils.c +++ b/thread-utils.c @@ -46,11 +46,11 @@ int online_cpus(void) mib[0] = CTL_HW; # ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; - len = sizeof(cpucount); - if (!sysctl(mib, 2, &cpucount, &len, NULL, 0)) - return cpucount; -# endif /* HW_AVAILCPU */ +# elif defined(HW_NCPUONLINE) + mib[1] = HW_NCPUONLINE; +# else mib[1] = HW_NCPU; +# endif /* HW_AVAILCPU */ len = sizeof(cpucount); if (!sysctl(mib, 2, &cpucount, &len, NULL, 0)) return cpucount; diff --git a/tmp-objdir.c b/tmp-objdir.c index 31d16a4c2c..c38fbeb5e8 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -10,7 +10,7 @@ #include "strbuf.h" #include "strvec.h" #include "quote.h" -#include "object-store-ll.h" +#include "object-store.h" #include "repository.h" struct tmp_objdir { diff --git a/trace2/tr2_tmr.c b/trace2/tr2_tmr.c index 51f564b07a..038181ad9b 100644 --- a/trace2/tr2_tmr.c +++ b/trace2/tr2_tmr.c @@ -102,25 +102,11 @@ void tr2_update_final_timers(void) struct tr2_timer *t_final = &final_timer_block.timer[tid]; struct tr2_timer *t = &ctx->timer_block.timer[tid]; - if (t->recursion_count) { - /* - * The current thread is exiting with - * timer[tid] still running. - * - * Technically, this is a bug, but I'm going - * to ignore it. - * - * I don't think it is worth calling die() - * for. I don't think it is worth killing the - * process for this bookkeeping error. We - * might want to call warning(), but I'm going - * to wait on that. - * - * The downside here is that total_ns won't - * include the current open interval (now - - * start_ns). I can live with that. - */ - } + /* + * `t->recursion_count` could technically be non-zero, which + * would constitute a bug. Reporting the bug would potentially + * cause an infinite recursion, though, so let's ignore it. + */ if (!t->interval_count) continue; /* this timer was not used by this thread */ diff --git a/transport-helper.c b/transport-helper.c index d457b42550..0789e5bca5 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -162,7 +162,7 @@ static struct child_process *get_helper(struct transport *transport) data->helper = helper; data->no_disconnect_req = 0; - refspec_init(&data->rs, REFSPEC_FETCH); + refspec_init_fetch(&data->rs); /* * Open the output as FILE* so strbuf_getline_*() family of @@ -1437,7 +1437,7 @@ static int udt_do_read(struct unidirectional_transfer *t) transfer_debug("%s EOF (with %i bytes in buffer)", t->src_name, (int)t->bufuse); t->state = SSTATE_FLUSHING; - } else if (bytes > 0) { + } else { t->bufuse += bytes; transfer_debug("Read %i bytes from %s (buffer now at %i)", (int)bytes, t->src_name, (int)t->bufuse); diff --git a/tree-diff.c b/tree-diff.c index 60c558c2b5..e00fc2f450 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -181,7 +181,7 @@ static void emit_path(struct combine_diff_path ***tail, strbuf_add(base, path, pathlen); p = combine_diff_path_new(base->buf, base->len, mode, - oid ? oid : null_oid(), + oid ? oid : null_oid(the_hash_algo), nparent); strbuf_setlen(base, old_baselen); @@ -206,7 +206,7 @@ static void emit_path(struct combine_diff_path ***tail, mode_i = tp[i].entry.mode; } else { - oid_i = null_oid(); + oid_i = null_oid(the_hash_algo); mode_i = 0; } diff --git a/tree-walk.c b/tree-walk.c index a033397965..90655d5237 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -6,7 +6,7 @@ #include "gettext.h" #include "hex.h" #include "object-file.h" -#include "object-store-ll.h" +#include "object-store.h" #include "trace2.h" #include "tree.h" #include "pathspec.h" diff --git a/tree-walk.h b/tree-walk.h index aaea689f9a..29a55328bd 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -176,11 +176,14 @@ struct traverse_info { }; /** - * Find an entry in a tree given a pathname and the sha1 of a tree to - * search. Returns 0 if the entry is found and -1 otherwise. The third - * and fourth parameters are set to the entry's sha1 and mode respectively. - */ -int get_tree_entry(struct repository *, const struct object_id *, const char *, struct object_id *, unsigned short *); + * Walk trees starting with "tree_oid" to find the entry for "name", and + * return the the object name and the mode of the found entry via the + * "oid" and "mode" parameters. Return 0 if the entry is found, and -1 + * otherwise. + */ +int get_tree_entry(struct repository *repo, const struct object_id *tree_oid, + const char *name, struct object_id *oid, + unsigned short *mode); /** * Generate the full pathname of a tree entry based from the root of the @@ -4,7 +4,7 @@ #include "hex.h" #include "tree.h" #include "object-name.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "alloc.h" #include "tree-walk.h" diff --git a/unpack-trees.c b/unpack-trees.c index cf5b73c84b..471837f032 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -26,7 +26,7 @@ #include "symlinks.h" #include "trace2.h" #include "fsmonitor.h" -#include "object-store-ll.h" +#include "object-store.h" #include "promisor-remote.h" #include "entry.h" #include "parallel-checkout.h" diff --git a/upload-pack.c b/upload-pack.c index 7498b45e2e..26f29b85b5 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -10,7 +10,7 @@ #include "pkt-line.h" #include "sideband.h" #include "repository.h" -#include "object-store-ll.h" +#include "object-store.h" #include "oid-array.h" #include "object.h" #include "commit.h" @@ -509,8 +509,7 @@ static int got_oid(struct upload_pack_data *data, { if (get_oid_hex(hex, oid)) die("git upload-pack: expected SHA1 object, got '%s'", hex); - if (!repo_has_object_file_with_flags(the_repository, oid, - OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT)) + if (!has_object(the_repository, oid, 0)) return -1; return do_got_oid(data, oid); } @@ -665,8 +664,8 @@ static int do_reachable_revlist(struct child_process *cmd, cmd_in = xfdopen(cmd->in, "w"); - for (i = get_max_object_index(); 0 < i; ) { - o = get_indexed_object(--i); + for (i = get_max_object_index(the_repository); 0 < i; ) { + o = get_indexed_object(the_repository, --i); if (!o) continue; if (reachable && o->type == OBJ_COMMIT) @@ -734,8 +733,8 @@ static int get_reachable_list(struct upload_pack_data *data, o->flags &= ~TMP_MARK; } } - for (i = get_max_object_index(); 0 < i; i--) { - o = get_indexed_object(i - 1); + for (i = get_max_object_index(the_repository); 0 < i; i--) { + o = get_indexed_object(the_repository, i - 1); if (o && o->type == OBJ_COMMIT && (o->flags & TMP_MARK)) { add_object_array(o, NULL, reachable); @@ -1449,7 +1448,7 @@ void upload_pack(const int advertise_refs, const int stateless_rpc, for_each_namespaced_ref_1(send_ref, &data); if (!data.sent_capabilities) { const char *refname = "capabilities^{}"; - write_v0_ref(&data, refname, refname, null_oid()); + write_v0_ref(&data, refname, refname, null_oid(the_hash_algo)); } /* * fflush stdout before calling advertise_shallow_grafts because send_ref @@ -1557,7 +1556,7 @@ static int parse_want_ref(struct packet_writer *writer, const char *line, } if (!o) - o = parse_object_or_die(&oid, refname_nons); + o = parse_object_or_die(the_repository, &oid, refname_nons); if (!(o->flags & WANTED)) { o->flags |= WANTED; @@ -1781,27 +1780,27 @@ static void send_shallow_info(struct upload_pack_data *data) packet_delim(1); } -enum fetch_state { - FETCH_PROCESS_ARGS = 0, - FETCH_SEND_ACKS, - FETCH_SEND_PACK, - FETCH_DONE, +enum upload_state { + UPLOAD_PROCESS_ARGS = 0, + UPLOAD_SEND_ACKS, + UPLOAD_SEND_PACK, + UPLOAD_DONE, }; int upload_pack_v2(struct repository *r, struct packet_reader *request) { - enum fetch_state state = FETCH_PROCESS_ARGS; + enum upload_state state = UPLOAD_PROCESS_ARGS; struct upload_pack_data data; - clear_object_flags(ALL_FLAGS); + clear_object_flags(the_repository, ALL_FLAGS); upload_pack_data_init(&data); data.use_sideband = LARGE_PACKET_MAX; get_upload_pack_config(r, &data); - while (state != FETCH_DONE) { + while (state != UPLOAD_DONE) { switch (state) { - case FETCH_PROCESS_ARGS: + case UPLOAD_PROCESS_ARGS: process_args(request, &data); if (!data.want_obj.nr && !data.wait_for_done) { @@ -1812,27 +1811,27 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request) * to just send 'have's without 'want's); guess * they didn't want anything. */ - state = FETCH_DONE; + state = UPLOAD_DONE; } else if (data.seen_haves) { /* * Request had 'have' lines, so lets ACK them. */ - state = FETCH_SEND_ACKS; + state = UPLOAD_SEND_ACKS; } else { /* * Request had 'want's but no 'have's so we can * immediately go to construct and send a pack. */ - state = FETCH_SEND_PACK; + state = UPLOAD_SEND_PACK; } break; - case FETCH_SEND_ACKS: + case UPLOAD_SEND_ACKS: if (process_haves_and_send_acks(&data)) - state = FETCH_SEND_PACK; + state = UPLOAD_SEND_PACK; else - state = FETCH_DONE; + state = UPLOAD_DONE; break; - case FETCH_SEND_PACK: + case UPLOAD_SEND_PACK: send_wanted_ref_info(&data); send_shallow_info(&data); @@ -1842,9 +1841,9 @@ int upload_pack_v2(struct repository *r, struct packet_reader *request) packet_writer_write(&data.writer, "packfile\n"); create_pack_file(&data, NULL); } - state = FETCH_DONE; + state = UPLOAD_DONE; break; - case FETCH_DONE: + case UPLOAD_DONE: continue; } } diff --git a/userdiff.c b/userdiff.c index 340c4eb4f7..fe710a68bf 100644 --- a/userdiff.c +++ b/userdiff.c @@ -59,20 +59,30 @@ PATTERNS("bash", "(" "(" /* POSIX identifier with mandatory parentheses */ - "[a-zA-Z_][a-zA-Z0-9_]*[ \t]*\\([ \t]*\\))" + "([a-zA-Z_][a-zA-Z0-9_]*[ \t]*\\([ \t]*\\))" "|" /* Bashism identifier with optional parentheses */ - "(function[ \t]+[a-zA-Z_][a-zA-Z0-9_]*(([ \t]*\\([ \t]*\\))|([ \t]+))" + "(function[ \t]+[a-zA-Z_][a-zA-Z0-9_]*(([ \t]*\\([ \t]*\\))|([ \t]+)))" ")" - /* Optional whitespace */ - "[ \t]*" - /* Compound command starting with `{`, `(`, `((` or `[[` */ - "(\\{|\\(\\(?|\\[\\[)" + /* Everything after the function header is captured */ + ".*$" /* End of captured text */ ")", /* -- */ - /* Characters not in the default $IFS value */ - "[^ \t]+"), + /* Identifiers: variable and function names */ + "[a-zA-Z_][a-zA-Z0-9_]*" + /* Shell variables: $VAR, ${VAR} */ + "|\\$[a-zA-Z0-9_]+|\\$\\{" + /*Command list separators and redirection operators */ + "|\\|\\||&&|<<|>>" + /* Operators ending in '=' (comparison + compound assignment) */ + "|==|!=|<=|>=|[-+*/%&|^]=" + /* Additional parameter expansion operators */ + "|:=|:-|:\\+|:\\?|##|%%|\\^\\^|,," + /* Command-line options (to avoid splitting -option) */ + "|[-a-zA-Z0-9_]+" + /* Brackets and grouping symbols */ + "|\\(|\\)|\\{|\\}|\\[|\\]"), PATTERNS("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", /* -- */ @@ -211,6 +221,10 @@ PATTERNS("html", "^[ \t]*(<[Hh][1-6]([ \t].*)?>.*)$", /* -- */ "[^<>= \t]+"), +PATTERNS("ini", + "^[ \t]*\\[[^]]+\\]", + /* -- */ + "[^ \t]+"), PATTERNS("java", "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" /* Class, enum, interface, and record declarations */ @@ -313,6 +327,10 @@ PATTERNS("python", "|[-+0-9.e]+[jJlL]?|0[xX]?[0-9a-fA-F]+[lL]?" "|[-+*/<>%&^|=!]=|//=?|<<=?|>>=?|\\*\\*=?"), /* -- */ +PATTERNS("r", + "^[ \t]*([a-zA-z][a-zA-Z0-9_.]*[ \t]*(<-|=)[ \t]*function.*)$", + /* -- */ + "[^ \t]+"), PATTERNS("ruby", "^[ \t]*((class|module|def)[ \t].*)$", /* -- */ @@ -5,7 +5,7 @@ #include "hex.h" #include "walker.h" #include "repository.h" -#include "object-store-ll.h" +#include "object-store.h" #include "commit.h" #include "strbuf.h" #include "tree.h" @@ -150,7 +150,8 @@ static int process(struct walker *walker, struct object *obj) return 0; obj->flags |= SEEN; - if (repo_has_object_file(the_repository, &obj->oid)) { + if (has_object(the_repository, &obj->oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { /* We already have it, so we should scan it now. */ obj->flags |= TO_SCAN; } diff --git a/wildmatch.c b/wildmatch.c index 8ea29141bd..69a2ae7000 100644 --- a/wildmatch.c +++ b/wildmatch.c @@ -223,7 +223,7 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) p_ch = '['; if (t_ch == p_ch) matched = 1; - continue; + goto next; } if (CC_EQ(s,i, "alnum")) { if (ISALNUM(t_ch)) @@ -268,7 +268,10 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) p_ch = 0; /* This makes "prev_ch" get set to 0. */ } else if (t_ch == p_ch) matched = 1; - } while (prev_ch = p_ch, (p_ch = *++p) != ']'); +next: + prev_ch = p_ch; + p_ch = *++p; + } while (p_ch != ']'); if (matched == negated || ((flags & WM_PATHNAME) && t_ch == '/')) return WM_NOMATCH; diff --git a/worktree.c b/worktree.c index 6449b6798d..c34b9eb74e 100644 --- a/worktree.c +++ b/worktree.c @@ -199,6 +199,11 @@ struct worktree **get_worktrees(void) return get_worktrees_internal(0); } +struct worktree **get_worktrees_without_reading_head(void) +{ + return get_worktrees_internal(1); +} + char *get_worktree_git_dir(const struct worktree *wt) { if (!wt) diff --git a/worktree.h b/worktree.h index 16368588a0..e4bcccdc0a 100644 --- a/worktree.h +++ b/worktree.h @@ -31,6 +31,14 @@ struct worktree { struct worktree **get_worktrees(void); /* + * Like `get_worktrees`, but does not read HEAD. Skip reading HEAD allows to + * get the worktree without worrying about failures pertaining to parsing + * the HEAD ref. This is useful in contexts where it is assumed that the + * refdb may not be in a consistent state. + */ +struct worktree **get_worktrees_without_reading_head(void); + +/* * Returns 1 if linked worktrees exist, 0 otherwise. */ int submodule_uses_worktrees(const char *path); @@ -737,7 +737,26 @@ int is_empty_or_missing_file(const char *filename) int open_nofollow(const char *path, int flags) { #ifdef O_NOFOLLOW - return open(path, flags | O_NOFOLLOW); + int ret = open(path, flags | O_NOFOLLOW); + /* + * NetBSD sets errno to EFTYPE when path is a symlink. The only other + * time this errno occurs when O_REGULAR is used. Since we don't use + * it anywhere we can avoid an lstat here. FreeBSD does the same with + * EMLINK. + */ +# ifdef __NetBSD__ +# define SYMLINK_ERRNO EFTYPE +# elif defined(__FreeBSD__) +# define SYMLINK_ERRNO EMLINK +# endif +# if SYMLINK_ERRNO + if (ret < 0 && errno == SYMLINK_ERRNO) { + errno = ELOOP; + return -1; + } +# undef SYMLINK_ERRNO +# endif + return ret; #else struct stat st; if (lstat(path, &st) < 0) @@ -829,3 +848,51 @@ uint32_t git_rand(unsigned flags) return result; } + +static void mmap_limit_check(size_t length) +{ + static size_t limit = 0; + if (!limit) { + limit = git_env_ulong("GIT_MMAP_LIMIT", 0); + if (!limit) + limit = SIZE_MAX; + } + if (length > limit) + die(_("attempting to mmap %"PRIuMAX" over limit %"PRIuMAX), + (uintmax_t)length, (uintmax_t)limit); +} + +void *xmmap_gently(void *start, size_t length, + int prot, int flags, int fd, off_t offset) +{ + void *ret; + + mmap_limit_check(length); + ret = mmap(start, length, prot, flags, fd, offset); + if (ret == MAP_FAILED && !length) + ret = NULL; + return ret; +} + +const char *mmap_os_err(void) +{ + static const char blank[] = ""; +#if defined(__linux__) + if (errno == ENOMEM) { + /* this continues an existing error message: */ + static const char enomem[] = +", check sys.vm.max_map_count and/or RLIMIT_DATA"; + return enomem; + } +#endif /* OS-specific bits */ + return blank; +} + +void *xmmap(void *start, size_t length, + int prot, int flags, int fd, off_t offset) +{ + void *ret = xmmap_gently(start, length, prot, flags, fd, offset); + if (ret == MAP_FAILED) + die_errno(_("mmap failed%s"), mmap_os_err()); + return ret; +} diff --git a/wt-status.c b/wt-status.c index 1da5732f57..454601afa1 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1824,10 +1824,10 @@ void wt_status_get_state(struct repository *r, if (!sequencer_get_last_command(r, &action)) { if (action == REPLAY_PICK && !state->cherry_pick_in_progress) { state->cherry_pick_in_progress = 1; - oidcpy(&state->cherry_pick_head_oid, null_oid()); + oidcpy(&state->cherry_pick_head_oid, null_oid(the_hash_algo)); } else if (action == REPLAY_REVERT && !state->revert_in_progress) { state->revert_in_progress = 1; - oidcpy(&state->revert_head_oid, null_oid()); + oidcpy(&state->revert_head_oid, null_oid(the_hash_algo)); } } if (get_detached_from) diff --git a/xdiff-interface.c b/xdiff-interface.c index 3bd61f26e9..1edcd319e6 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -5,7 +5,7 @@ #include "gettext.h" #include "config.h" #include "hex.h" -#include "object-store-ll.h" +#include "object-store.h" #include "strbuf.h" #include "xdiff-interface.h" #include "xdiff/xtypes.h" @@ -181,7 +181,7 @@ void read_mmblob(mmfile_t *ptr, const struct object_id *oid) unsigned long size; enum object_type type; - if (oideq(oid, null_oid())) { + if (oideq(oid, null_oid(the_hash_algo))) { ptr->ptr = xstrdup(""); ptr->size = 0; return; diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index 8889b8b62a..5a96e36dfb 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -211,8 +211,10 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1, for (d = fmax; d >= fmin; d -= 2) { i1 = XDL_MIN(kvdf[d], lim1); i2 = i1 - d; - if (lim2 < i2) - i1 = lim2 + d, i2 = lim2; + if (lim2 < i2) { + i1 = lim2 + d; + i2 = lim2; + } if (fbest < i1 + i2) { fbest = i1 + i2; fbest1 = i1; @@ -223,8 +225,10 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1, for (d = bmax; d >= bmin; d -= 2) { i1 = XDL_MAX(off1, kvdb[d]); i2 = i1 - d; - if (i2 < off2) - i1 = off2 + d, i2 = off2; + if (i2 < off2) { + i1 = off2 + d; + i2 = off2; + } if (i1 + i2 < bbest) { bbest = i1 + i2; bbest1 = i1; diff --git a/xdiff/xemit.c b/xdiff/xemit.c index f8e3f25b03..1d40c9cb40 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -43,6 +43,10 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t * return 0; } +static long saturating_add(long a, long b) +{ + return signed_add_overflows(a, b) ? LONG_MAX : a + b; +} /* * Starting at the passed change atom, find the latest change atom to be included @@ -52,7 +56,9 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t * xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) { xdchange_t *xch, *xchp, *lxch; - long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen; + long max_common = saturating_add(saturating_add(xecfg->ctxlen, + xecfg->ctxlen), + xecfg->interhunkctxlen); long max_ignorable = xecfg->ctxlen; long ignored = 0; /* number of ignored blank lines */ diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c index c84549f6c5..e1d4017b2d 100644 --- a/xdiff/xprepare.c +++ b/xdiff/xprepare.c @@ -368,6 +368,7 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd xrecord_t **recs; xdlclass_t *rcrec; char *dis, *dis1, *dis2; + int need_min = !!(cf->flags & XDF_NEED_MINIMAL); if (!XDL_CALLOC_ARRAY(dis, xdf1->nrec + xdf2->nrec + 2)) return -1; @@ -379,7 +380,7 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) { rcrec = cf->rcrecs[(*recs)->ha]; nm = rcrec ? rcrec->len2 : 0; - dis1[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1; + dis1[i] = (nm == 0) ? 0: (nm >= mlim && !need_min) ? 2: 1; } if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT) @@ -387,7 +388,7 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) { rcrec = cf->rcrecs[(*recs)->ha]; nm = rcrec ? rcrec->len1 : 0; - dis2[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1; + dis2[i] = (nm == 0) ? 0: (nm >= mlim && !need_min) ? 2: 1; } for (nreff = 0, i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; |
