origin \
${{ github.ref }} \
$args
- - uses: actions/setup-go@v2
+ - uses: actions/setup-go@v5
with:
go-version: '>=1.16'
+ cache: false
- name: Install git-po-helper
run: go install github.com/git-l10n/git-po-helper@main
- name: Install other dependencies
cat git-po-helper.out
exit $exit_code
- name: Create comment in pull request for report
- uses: mshick/add-pr-comment@v1
+ uses: mshick/add-pr-comment@v2
if: >-
always() &&
github.event_name == 'pull_request_target' &&
env.COMMENT_BODY != ''
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- repo-token-user-login: 'github-actions[bot]'
message: >
${{ steps.check-commits.outcome == 'failure' && 'Errors and warnings' || 'Warnings' }}
found by [git-po-helper](https://github.com/git-l10n/git-po-helper#readme) in workflow
- jobname: linux-sha256
cc: clang
pool: ubuntu-latest
+ - jobname: linux-reftable
+ cc: clang
+ pool: ubuntu-latest
- jobname: linux-gcc
cc: gcc
cc_package: gcc-8
- jobname: osx-clang
cc: clang
pool: macos-13
+ - jobname: osx-reftable
+ cc: clang
+ pool: macos-13
- jobname: osx-gcc
cc: gcc
cc_package: gcc-13
- jobname: linux-leaks
cc: gcc
pool: ubuntu-latest
+ - jobname: linux-reftable-leaks
+ cc: gcc
+ pool: ubuntu-latest
- jobname: linux-asan-ubsan
cc: clang
pool: ubuntu-latest
- jobname: linux-sha256
image: ubuntu:latest
CC: clang
+ - jobname: linux-reftable
+ image: ubuntu:latest
+ CC: clang
- jobname: linux-gcc
image: ubuntu:20.04
CC: gcc
- jobname: linux-leaks
image: ubuntu:latest
CC: gcc
+ - jobname: linux-reftable-leaks
+ image: ubuntu:latest
+ CC: gcc
- jobname: linux-asan-ubsan
image: ubuntu:latest
CC: clang
- jobname: osx-clang
image: macos-13-xcode-14
CC: clang
+ - jobname: osx-reftable
+ image: macos-13-xcode-14
+ CC: clang
artifacts:
paths:
- t/failed-test-artifacts
detail.
- The first #include in C files, except in platform specific compat/
- implementations and sha1dc/, must be either "git-compat-util.h" or
- one of the approved headers that includes it first for you. (The
- approved headers currently include "builtin.h",
- "t/helper/test-tool.h", "xdiff/xinclude.h", or
- "reftable/system.h".) You do not have to include more than one of
- these.
+ implementations and sha1dc/, must be <git-compat-util.h>. This
+ header file insulates other header files and source files from
+ platform differences, like which system header files must be
+ included in what order, and what C preprocessor feature macros must
+ be defined to trigger certain features we expect out of the system.
+ A collorary to this is that C files should not directly include
+ system header files themselves.
+
+ There are some exceptions, because certain group of files that
+ implement an API all have to include the same header file that
+ defines the API and it is convenient to include <git-compat-util.h>
+ there. Namely:
+
+ - the implementation of the built-in commands in the "builtin/"
+ directory that include "builtin.h" for the cmd_foo() prototype
+ definition,
+
+ - the test helper programs in the "t/helper/" directory that include
+ "t/helper/test-tool.h" for the cmd__foo() prototype definition,
+
+ - the xdiff implementation in the "xdiff/" directory that includes
+ "xdiff/xinclude.h" for the xdiff machinery internals,
+
+ - the unit test programs in "t/unit-tests/" directory that include
+ "t/unit-tests/test-lib.h" that gives them the unit-tests
+ framework, and
+
+ - the source files that implement reftable in the "reftable/"
+ directory that include "reftable/system.h" for the reftable
+ internals,
+
+ are allowed to assume that they do not have to include
+ <git-compat-util.h> themselves, as it is included as the first
+ '#include' in these header files. These headers must be the first
+ header file to be "#include"d in them, though.
- A C file must directly include the header files that declare the
functions and the types it uses, except for the functions and types
<new-branch-name>
--template=<template-directory>
+ When a placeholder is cited in text paragraph, it is enclosed in angle
+ brackets to remind the reader the reference in the synopsis section.
+ For better visibility, the placeholder is typeset in italics:
+ The _<file>_ to be added.
+
Possibility of multiple occurrences is indicated by three dots:
<file>...
(One or more of <file>.)
Incorrect:
`\--pretty=oneline`
+A placeholder is not enclosed in backticks, as it is not a literal.
+
If some place in the documentation needs to typeset a command usage
example with inline substitutions, it is fine to use +monospaced and
inline substituted text+ instead of `monospaced literal text`, and with
--- /dev/null
+Git 2.43.3 Release Notes
+========================
+
+Relative to Git 2.43.2, this release fixes one regression that
+manifests while running "git commit -v --trailer".
+
+Fixes since Git 2.43.2
+----------------------
+
+ * "git commit -v --trailer=..." was broken with recent update and
+ placed the trailer _after_ the divider line, which has been
+ corrected.
Backward Compatibility Notes
- * "git chekcout -B <branch>" used to allow switching to a branch that
+ * "git checkout -B <branch>" used to allow switching to a branch that
is in use on another worktree, but this was by mistake. The users
need to use "--ignore-other-worktrees" option.
gitweb behaved as if the file did not exist at all, but now it
errors out. This is a change that may break backward compatibility.
- * When $HOME/.gitignore is missing but XDG config file available, we
+ * When $HOME/.gitconfig is missing but XDG config file is available, we
should write into the latter, not former. "git gc" and "git
maintenance" wrote into a wrong "global config" file, which have
been corrected.
option is used with author or committer timestamp with a format
specifier (e.g., "--sort=creatordate:format:%H:%M:%S").
+ * The command line completion script (in contrib/) learned to
+ complete configuration variable names better.
+
Performance, Internal Implementation, Development Support etc.
mechanism by flipping what yes/no means by mistake, which has been
corrected.
+ * The sequencer machinery does not use the ref API and instead
+ records names of certain objects it needs for its correct operation
+ in temporary files, which makes these objects susceptible to loss
+ by garbage collection. These temporary files have been added as
+ starting points for reachability analysis to fix this.
+ (merge bc7f5db896 pw/gc-during-rebase later to maint).
+
+ * "git cherry-pick" invoked during "git rebase -i" session lost
+ the authorship information, which has been corrected.
+ (merge e4301f73ff vn/rebase-with-cherry-pick-authorship later to maint).
+
+ * The code paths that call repo_read_object_file() have been
+ tightened to react to errors.
+ (merge 568459bf5e js/check-null-from-read-object-file later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge 5aea3955bc rj/clarify-branch-doc-m later to maint).
(merge 9cce3be2df bk/bisect-doc-fix later to maint).
(merge 8430b438f6 vd/fsck-submodule-url-test later to maint).
(merge 3cb4384683 jc/t0091-with-unknown-git later to maint).
+ (merge 020456cb74 rs/receive-pack-remove-find-header later to maint).
+ (merge bc47139f4f la/trailer-cleanups later to maint).
--- /dev/null
+Git v2.45 Release Notes
+=======================
+
+Backward Compatibility Notes
+
+UI, Workflows & Features
+
+ * Integrate the reftable code into the refs framework as a backend.
+ With "git init --ref-format=reftable", hopefully it would be a lot
+ more efficient to manage a repository with many references.
+
+ * "git checkout -p" and friends learned that that "@" is a synonym
+ for "HEAD".
+
+ * Variants of vimdiff learned to honor mergetool.<variant>.layout
+ settings.
+
+ * "git reflog" learned a "list" subcommand that enumerates known reflogs.
+
+ * When a merge conflicted at a submodule, merge-ort backend used to
+ unconditionally give a lengthy message to suggest how to resolve
+ it. Now the message can be squelched as an advice message.
+
+ * "git for-each-ref" learned "--include-root-refs" option to show
+ even the stuff outside the 'refs/' hierarchy.
+
+ * "git rev-list --missing=print" has learned to optionally take
+ "--allow-missing-tips", which allows the objects at the starting
+ points to be missing.
+
+ * "git merge-tree" has learned that the three trees involved in the
+ 3-way merge only need to be trees, not necessarily commits.
+
+ * "git log --merge" learned to pay attention to CHERRY_PICK_HEAD and
+ other kinds of *_HEAD pseudorefs.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The code to iterate over refs with the reftable backend has seen
+ some optimization.
+
+ * More tests that are marked as "ref-files only" have been updated to
+ improve test coverage of reftable backend.
+
+ * Some parts of command line completion script (in contrib/) have
+ been micro-optimized.
+
+ * The way placeholders are to be marked-up in documentation have been
+ specified; use "_<placeholder>_" to typeset the word inside a pair
+ of <angle-brakets> emphasized.
+
+ * "git --no-lazy-fetch cmd" allows to run "cmd" while disabling lazy
+ fetching of objects from the promisor remote, which may be handy
+ for debugging.
+
+
+Fixes since v2.44
+-----------------
+
+ * "git apply" on a filesystem without filemode support have learned
+ to take a hint from what is in the index for the path, even when
+ not working with the "--index" or "--cached" option, when checking
+ the executable bit match what is required by the preimage in the
+ patch.
+ (merge 45b625142d cp/apply-core-filemode later to maint).
+
+ * "git column" has been taught to reject negative padding value, as
+ it would lead to nonsense behaviour including division by zero.
+ (merge 76fb807faa kh/column-reject-negative-padding later to maint).
+
+ * "git am --help" now tells readers what actions are available in
+ "git am --whitespace=<action>", in addition to saying that the
+ option is passed through to the underlying "git apply".
+ (merge a171dac734 jc/am-whitespace-doc later to maint).
+
+ * "git tag --column" failed to check the exit status of its "git
+ column" invocation, which has been corrected.
+ (merge 92e66478fc rj/tag-column-fix later to maint).
+
+ * Credential helper based on libsecret (in contrib/) has been updated
+ to handle an empty password correctly.
+ (merge 8f1f2023b7 mh/libsecret-empty-password-fix later to maint).
+
+ * "git difftool --dir-diff" learned to honor the "--trust-exit-code"
+ option; it used to always exit with 0 and signalled success.
+ (merge eb84c8b6ce ps/difftool-dir-diff-exit-code later to maint).
+
+ * The code incorrectly attempted to use textconv cache when asked,
+ even when we are not running in a repository, which has been
+ corrected.
+ (merge affe355fe7 jk/textconv-cache-outside-repo-fix later to maint).
+
+ * Remove an empty file that shouldn't have been added in the first
+ place.
+ (merge 4f66942215 js/remove-cruft-files later to maint).
+
+ * The logic to access reflog entries by date and number had ugly
+ corner cases at the boundaries, which have been cleaned up.
+ (merge 5edd126720 jk/reflog-special-cases-fix later to maint).
+
+ * An error message from "git upload-pack", which responds to "git
+ fetch" requests, had a trialing NUL in it, which has been
+ corrected.
+ (merge 3f4c7a0805 sg/upload-pack-error-message-fix later to maint).
+
+ * Clarify wording in the CodingGuidelines that requires <git-compat-util.h>
+ to be the first header file.
+ (merge 4e89f0e07c jc/doc-compat-util later to maint).
+
+ * "git commit -v --cleanup=scissors" used to add the scissors line
+ twice in the log message buffer, which has been corrected.
+ (merge e90cc075cc jt/commit-redundant-scissors-fix later to maint).
+
+ * A custom remote helper no longer cannot access the newly created
+ repository during "git clone", which is a regression in Git 2.44.
+ This has been corrected.
+ (merge 199f44cb2e ps/remote-helper-repo-initialization-fix later to maint).
+
+ * Various parts of upload-pack has been updated to bound the resource
+ consumption relative to the size of the repository to protect from
+ abusive clients.
+ (merge 6cd05e768b jk/upload-pack-bounded-resources later to maint).
+
+ * The upload-pack program, when talking over v2, accepted the
+ packfile-uris protocol extension from the client, even if it did
+ not advertise the capability, which has been corrected.
+ (merge a922bfa3b5 jk/upload-pack-v2-capability-cleanup later to maint).
+
+ * Make sure failure return from merge_bases_many() is properly caught.
+ (merge 25fd20eb44 js/merge-base-with-missing-commit later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+ (merge f0e578c69c rs/use-xstrncmpz later to maint).
+ (merge 83e6eb7d7a ba/credential-test-clean-fix later to maint).
+ (merge 64562d784d jb/doc-interactive-singlekey-do-not-need-perl later to maint).
+ (merge c431a235e2 cp/t9146-use-test-path-helpers later to maint).
+ (merge 82d75402d5 ds/doc-send-email-capitalization later to maint).
+ (merge 41bff66e35 jc/doc-add-placeholder-fix later to maint).
+ (merge 6835f0efe9 jw/remote-doc-typofix later to maint).
+ (merge 244001aa20 hs/rebase-not-in-progress later to maint).
+ (merge 2ca6c07db2 jc/no-include-of-compat-util-from-headers later to maint).
+ (merge 87bd7fbb9c rs/fetch-simplify-with-starts-with later to maint).
+ (merge f39addd0d9 rs/name-rev-with-mempool later to maint).
+ (merge 9a97b43e03 rs/submodule-prefix-simplify later to maint).
+ (merge 40b8076462 ak/rebase-autosquash later to maint).
+ (merge 3223204456 eg/add-uflags later to maint).
+ (merge 5f78d52dce es/config-doc-sort-sections later to maint).
names do not conflict with those that are used by Git itself and
other popular tools, and describe them in your documentation.
-include::config/advice.txt[]
-
-include::config/attr.txt[]
-
-include::config/core.txt[]
-
include::config/add.txt[]
+include::config/advice.txt[]
+
include::config/alias.txt[]
include::config/am.txt[]
include::config/apply.txt[]
+include::config/attr.txt[]
+
include::config/blame.txt[]
include::config/branch.txt[]
include::config/commitgraph.txt[]
-include::config/credential.txt[]
-
include::config/completion.txt[]
+include::config/core.txt[]
+
+include::config/credential.txt[]
+
include::config/diff.txt[]
include::config/difftool.txt[]
include::config/fetch.txt[]
-include::config/format.txt[]
-
include::config/filter.txt[]
+include::config/format.txt[]
+
include::config/fsck.txt[]
include::config/fsmonitor--daemon.txt[]
include::config/gitweb.txt[]
-include::config/grep.txt[]
-
include::config/gpg.txt[]
+include::config/grep.txt[]
+
include::config/gui.txt[]
include::config/guitool.txt[]
include::config/ssh.txt[]
-include::config/status.txt[]
-
include::config/stash.txt[]
+include::config/status.txt[]
+
include::config/submodule.txt[]
include::config/tag.txt[]
submoduleAlternateErrorStrategyDie::
Advice shown when a submodule.alternateErrorStrategy option
configured to "die" causes a fatal error.
+ submoduleMergeConflict::
+ Advice shown when a non-trivial submodule merge conflict is
+ encountered.
submodulesNotUpdated::
Advice shown when a user runs a submodule command that fails
because `git submodule update --init` was not run.
clean.requireForce::
- A boolean to make git-clean do nothing unless given -f,
- -i, or -n. Defaults to true.
+ A boolean to make git-clean refuse to delete files unless -f
+ is given. Defaults to true.
diff.colorMovedWS::
When moved lines are colored using e.g. the `diff.colorMoved` setting,
- this option controls the `<mode>` how spaces are treated
- for details of valid modes see '--color-moved-ws' in linkgit:git-diff[1].
+ this option controls the `<mode>` how spaces are treated.
+ For details of valid modes see '--color-moved-ws' in linkgit:git-diff[1].
Currently this is used by the `--patch` mode of
linkgit:git-add[1], linkgit:git-checkout[1],
linkgit:git-restore[1], linkgit:git-commit[1],
- linkgit:git-reset[1], and linkgit:git-stash[1]. Note that this
- setting is silently ignored if portable keystroke input
- is not available; requires the Perl module Term::ReadKey.
+ linkgit:git-reset[1], and linkgit:git-stash[1].
interactive.diffFilter::
When an interactive command (such as `git add --patch`) shows
value of `false` avoids using `--auto-merge` altogether, and is the
default value.
-mergetool.vimdiff.layout::
- The vimdiff backend uses this variable to control how its split
- windows appear. Applies even if you are using Neovim (`nvim`) or
- gVim (`gvim`) as the merge tool. See BACKEND SPECIFIC HINTS section
+mergetool.<vimdiff variant>.layout::
+ Configure the split window layout for vimdiff's `<variant>`, which is any of `vimdiff`,
+ `nvimdiff`, `gvimdiff`.
+ Upon launching `git mergetool` with `--tool=<variant>` (or without `--tool`
+ if `merge.tool` is configured as `<variant>`), Git will consult
+ `mergetool.<variant>.layout` to determine the tool's layout. If the
+ variant-specific configuration is not available, `vimdiff`'s is used as
+ fallback. If that too is not available, a default layout with 4 windows
+ will be used. To configure the layout, see the `BACKEND SPECIFIC HINTS`
+ifdef::git-mergetool[]
+ section.
+endif::[]
ifndef::git-mergetool[]
- in linkgit:git-mergetool[1].
+ section in linkgit:git-mergetool[1].
endif::[]
- for details.
mergetool.hideResolved::
During a merge, Git will automatically resolve as many conflicts as
reachability bitmap is available, pack-objects will try to send
parts of all packs in the MIDX.
+
- If only a single pack bitmap is available, and
- `pack.allowPackReuse` is set to "multi", reuse parts of just the
- bitmapped packfile. This can reduce memory and CPU usage to
- serve fetches, but might result in sending a slightly larger
- pack. Defaults to true.
+If only a single pack bitmap is available, and `pack.allowPackReuse`
+is set to "multi", reuse parts of just the bitmapped packfile. This
+can reduce memory and CPU usage to serve fetches, but might result in
+sending a slightly larger pack. Defaults to true.
pack.island::
An extended regular expression configuring a set of delta
See linkgit:git-send-email[1] for description. Note that this
setting is not subject to the 'identity' mechanism.
-sendemail.smtpsslcertpath::
+sendemail.smtpSSLCertPath::
Path to ca-certificates (either a directory or a single file).
Set it to an empty string to disable certificate verification.
sendemail.envelopeSender::
sendemail.from::
sendemail.headerCmd::
-sendemail.signedoffbycc::
+sendemail.signedOffByCc::
sendemail.smtpPass::
-sendemail.suppresscc::
+sendemail.suppressCc::
sendemail.suppressFrom::
sendemail.to::
-sendemail.tocmd::
+sendemail.toCmd::
sendemail.smtpDomain::
sendemail.smtpServer::
sendemail.smtpServerPort::
linkgit:git-send-email[1] command-line options. See its
documentation for details.
-sendemail.signedoffcc (deprecated)::
- Deprecated alias for `sendemail.signedoffbycc`.
+sendemail.signedOffCc (deprecated)::
+ Deprecated alias for `sendemail.signedOffByCc`.
sendemail.smtpBatchSize::
Number of messages to be sent per connection, after that a relogin
information from the remote server (if advertised) and download
bundles before continuing the clone through the Git protocol.
Defaults to `false`.
+
+transfer.advertiseObjectInfo::
+ When `true`, the `object-info` capability is advertised by
+ servers. Defaults to false.
to ignore removed files; use `--no-all` option if you want
to add modified or new files but ignore removed ones.
+
-For more details about the <pathspec> syntax, see the 'pathspec' entry
+For more details about the _<pathspec>_ syntax, see the 'pathspec' entry
in linkgit:gitglossary[7].
-n::
-u::
--update::
Update the index just where it already has an entry matching
- <pathspec>. This removes as well as modifies index entries to
+ _<pathspec>_. This removes as well as modifies index entries to
match the working tree, but adds no new files.
+
-If no <pathspec> is given when `-u` option is used, all
+If no _<pathspec>_ is given when `-u` option is used, all
tracked files in the entire working tree are updated (old versions
of Git used to limit the update to the current directory and its
subdirectories).
--all::
--no-ignore-removal::
Update the index not only where the working tree has a file
- matching <pathspec> but also where the index already has an
+ matching _<pathspec>_ but also where the index already has an
entry. This adds, modifies, and removes index entries to
match the working tree.
+
-If no <pathspec> is given when `-A` option is used, all
+If no _<pathspec>_ is given when `-A` option is used, all
files in the entire working tree are updated (old versions
of Git used to limit the update to the current directory and its
subdirectories).
Update the index by adding new files that are unknown to the
index and files modified in the working tree, but ignore
files that have been removed from the working tree. This
- option is a no-op when no <pathspec> is used.
+ option is a no-op when no _<pathspec>_ is used.
+
This option is primarily to help users who are used to older
-versions of Git, whose "git add <pathspec>..." was a synonym
-for "git add --no-all <pathspec>...", i.e. ignored removed files.
+versions of Git, whose "git add _<pathspec>_..." was a synonym
+for "git add --no-all _<pathspec>_...", i.e. ignored removed files.
-N::
--intent-to-add::
unchanged.
--pathspec-from-file=<file>::
- Pathspec is passed in `<file>` instead of commandline args. If
- `<file>` is exactly `-` then standard input is used. Pathspec
+ Pathspec is passed in _<file>_ instead of commandline args. If
+ _<file>_ is exactly `-` then standard input is used. Pathspec
elements are separated by LF or CR/LF. Pathspec elements can be
quoted as explained for the configuration variable `core.quotePath`
(see linkgit:git-config[1]). See also `--pathspec-file-nul` and
These flags are passed to the 'git apply' (see linkgit:git-apply[1])
program that applies
the patch.
++
+Valid <action> for the `--whitespace` option are:
+`nowarn`, `warn`, `fix`, `error`, and `error-all`.
--patch-format::
By default the command will try to detect the patch format
--force::
If the Git configuration variable clean.requireForce is not set
to false, 'git clean' will refuse to delete files or directories
- unless given -f or -i. Git will refuse to modify untracked
+ unless given -f. Git will refuse to modify untracked
nested git repositories (directories with a .git subdirectory)
unless a second -f is given.
--interactive::
Show what would be done and clean files interactively. See
``Interactive mode'' for details.
+ Configuration variable `clean.requireForce` is ignored, as
+ this mode gives its own safety protection by going interactive.
-n::
--dry-run::
Don't actually remove anything, just show what would be done.
+ Configuration variable `clean.requireForce` is ignored, as
+ nothing will be deleted anyway.
-q::
--quiet::
The result is Git repository can be separated from working
tree.
---ref-format=<ref-format::
+--ref-format=<ref-format>::
Specify the given ref storage format for the repository. The valid values are:
+
`merge.tool` until a tool is found.
--[no-]trust-exit-code::
- 'git-difftool' invokes a diff tool individually on each file.
Errors reported by the diff tool are ignored by default.
Use `--trust-exit-code` to make 'git-difftool' exit when an
invoked diff tool returns a non-zero exit code.
when encountering such a tag. With 'drop' it will omit such tags from
the output. With 'rewrite', if the tagged object is a commit, it will
rewrite the tag to tag an ancestor commit (via parent rewriting; see
-linkgit:git-rev-list[1])
+linkgit:git-rev-list[1]).
-M::
-C::
[verse]
'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
[(--sort=<key>)...] [--format=<format>]
- [ --stdin | <pattern>... ]
+ [--include-root-refs] [ --stdin | <pattern>... ]
[--points-at=<object>]
[--merged[=<object>]] [--no-merged[=<object>]]
[--contains[=<object>]] [--no-contains[=<object>]]
any excluded pattern(s) are shown. Matching is done using the
same rules as `<pattern>` above.
+--include-root-refs::
+ List root refs (HEAD and pseudorefs) apart from regular refs.
+
FIELD NAMES
-----------
share no common history. This flag can be given to override that
check and make the merge proceed anyway.
---merge-base=<commit>::
+--merge-base=<tree-ish>::
Instead of finding the merge-bases for <branch1> and <branch2>,
specify a merge-base for the merge, and specifying multiple bases is
currently not supported. This option is incompatible with `--stdin`.
++
+As the merge-base is provided directly, <branch1> and <branch2> do not need
+to specify commits; trees are enough.
[[OUTPUT]]
OUTPUT
linkgit:git-commit[1], which take the target commit as an argument and
automatically fill in the subject line of the new commit from that.
+
-Settting configuration variable `rebase.autoSquash` to true enables
+Setting configuration variable `rebase.autoSquash` to true enables
auto-squashing by default for interactive rebase. The `--no-autosquash`
option can be used to override that setting.
+
--------
[verse]
'git reflog' [show] [<log-options>] [<ref>]
+'git reflog list'
'git reflog expire' [--expire=<time>] [--expire-unreachable=<time>]
[--rewrite] [--updateref] [--stale-fix]
[--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]
`git reflog show` is an alias for `git log -g --abbrev-commit
--pretty=oneline`; see linkgit:git-log[1] for more information.
+The "list" subcommand lists all refs which have a corresponding reflog.
+
The "expire" subcommand prunes older reflog entries. Entries older
than `expire` time, or entries older than `expire-unreachable` time
and not reachable from the current tip, are removed from the reflog.
-v::
--verbose::
Be a little more verbose and show remote url after name.
- For promisor remotes, also show which filter (`blob:none` etc.)
+ For promisor remotes, also show which filters (`blob:none` etc.)
are configured.
NOTE: This must be placed between `remote` and subcommand.
SYNOPSIS
--------
[verse]
-'git rev-parse' [<options>] <args>...
+'git rev-parse' [<options>] <arg>...
DESCRIPTION
-----------
'git diff-{asterisk}'). In contrast to the `--sq-quote` option,
the command input is still interpreted as usual.
---short[=length]::
+--short[=<length>]::
Same as `--verify` but shortens the object name to a unique
prefix with at least `length` characters. The minimum length
is 4, the default is the effective value of the `core.abbrev`
--all::
Show all refs found in `refs/`.
---branches[=pattern]::
---tags[=pattern]::
---remotes[=pattern]::
+--branches[=<pattern>]::
+--tags[=<pattern>]::
+--remotes[=<pattern>]::
Show all branches, tags, or remote-tracking branches,
respectively (i.e., refs found in `refs/heads`,
`refs/tags`, or `refs/remotes`, respectively).
shown. If the pattern does not contain a globbing character (`?`,
`*`, or `[`), it is turned into a prefix match by appending `/*`.
---glob=pattern::
+--glob=<pattern>::
Show all refs matching the shell glob pattern `pattern`. If
the pattern does not start with `refs/`, this is automatically
prepended. If the pattern does not contain a globbing
or `--all`. If a trailing '/{asterisk}' is intended, it must be given
explicitly.
---exclude-hidden=[fetch|receive|uploadpack]::
+--exclude-hidden=(fetch|receive|uploadpack)::
Do not include refs that would be hidden by `git-fetch`,
`git-receive-pack` or `git-upload-pack` by consulting the appropriate
`fetch.hideRefs`, `receive.hideRefs` or `uploadpack.hideRefs`
Other Options
~~~~~~~~~~~~~
---since=datestring::
---after=datestring::
+--since=<datestring>::
+--after=<datestring>::
Parse the date string, and output the corresponding
--max-age= parameter for 'git rev-list'.
---until=datestring::
---before=datestring::
+--until=<datestring>::
+--before=<datestring>::
Parse the date string, and output the corresponding
--min-age= parameter for 'git rev-list'.
-<args>...::
+<arg>...::
Flags and parameters to be parsed.
--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.
Specify a command to run to send the email. The command should
be sendmail-like; specifically, it must support the `-i` option.
The command will be executed in the shell if necessary. Default
- is the value of `sendemail.sendmailcmd`. If unspecified, and if
+ is the value of `sendemail.sendmailCmd`. If unspecified, and if
--smtp-server is also unspecified, git-send-email will search
for `sendmail` in `/usr/sbin`, `/usr/lib` and $PATH.
certificates concatenated together: see verify(1) -CAfile and
-CApath for more information on these). Set it to an empty string
to disable certificate verification. Defaults to the value of the
- `sendemail.smtpsslcertpath` configuration variable, if set, or the
+ `sendemail.smtpSSLCertPath` configuration variable, if set, or the
backing SSL library's compiled-in default otherwise (which should
be the best choice on most platforms).
Specify a command to execute once per patch file which
should generate patch file specific "To:" entries.
Output of this command must be single email address per line.
- Default is the value of 'sendemail.tocmd' configuration value.
+ Default is the value of 'sendemail.toCmd' configuration value.
--cc-cmd=<command>::
Specify a command to execute once per patch file which
--[no-]signed-off-by-cc::
If this is set, add emails found in the `Signed-off-by` trailer or Cc: lines to the
- cc list. Default is the value of `sendemail.signedoffbycc` configuration
+ cc list. Default is the value of `sendemail.signedOffByCc` configuration
value; if that is unspecified, default to --signed-off-by-cc.
--[no-]cc-cover::
If this is set, emails found in Cc: headers in the first patch of
the series (typically the cover letter) are added to the cc list
- for each email set. Default is the value of 'sendemail.cccover'
+ for each email set. Default is the value of 'sendemail.ccCover'
configuration value; if that is unspecified, default to --no-cc-cover.
--[no-]to-cover::
If this is set, emails found in To: headers in the first patch of
the series (typically the cover letter) are added to the to list
- for each email set. Default is the value of 'sendemail.tocover'
+ for each email set. Default is the value of 'sendemail.toCover'
configuration value; if that is unspecified, default to --no-to-cover.
--suppress-cc=<category>::
- 'all' will suppress all auto cc values.
--
+
-Default is the value of `sendemail.suppresscc` configuration value; if
+Default is the value of `sendemail.suppressCc` configuration value; if
that is unspecified, default to 'self' if --suppress-from is
specified, as well as 'body' if --no-signed-off-cc is specified.
Instead of the normal operation, dump the shorthand alias names from
the configured alias file(s), one per line in alphabetical order. Note
that this only includes the alias name and not its expanded email addresses.
- See 'sendemail.aliasesfile' for more information about aliases.
+ See 'sendemail.aliasesFile' for more information about aliases.
CONFIGURATION
directory.
--no-replace-objects::
- Do not use replacement refs to replace Git objects. See
- linkgit:git-replace[1] for more information.
+ Do not use replacement refs to replace Git objects.
+ This is equivalent to exporting the `GIT_NO_REPLACE_OBJECTS`
+ environment variable with any value.
+ See linkgit:git-replace[1] for more information.
+
+--no-lazy-fetch::
+ Do not fetch missing objects from the promisor remote on
+ demand. Useful together with `git cat-file -e <object>` to
+ see if the object is locally available.
+ This is equivalent to setting the `GIT_NO_LAZY_FETCH`
+ environment variable to `1`.
--literal-pathspecs::
Treat pathspecs literally (i.e. no globbing, no pathspec magic).
header and packfile URIs. Set this Boolean environment variable to false to prevent this
redaction.
+`GIT_NO_REPLACE_OBJECTS`::
+ Setting and exporting this environment variable tells Git to
+ ignore replacement refs and do not replace Git objects.
+
`GIT_LITERAL_PATHSPECS`::
Setting this Boolean environment variable to true will cause Git to treat all
pathspecs literally, rather than as glob patterns. For example,
Setting this Boolean environment variable to true will cause Git to treat all
pathspecs as case-insensitive.
+`GIT_NO_LAZY_FETCH`::
+ Setting this Boolean environment variable to true tells Git
+ not to lazily fetch missing objects from the promisor remote
+ on demand.
+
`GIT_REFLOG_ACTION`::
When a ref is updated, reflog entries are created to keep
track of the reason why the ref was updated (which is
Here are the rules regarding the "flags" that you should follow when you are
scripting Git:
- * It's preferred to use the non-dashed form of Git commands, which means that
- you should prefer `git foo` to `git-foo`.
-
* Splitting short options to separate words (prefer `git foo -a -b`
to `git foo -ab`, the latter may not even work).
want-ref <ref>
Indicates to the server that the client wants to retrieve a
particular ref, where <ref> is the full name of a ref on the
- server.
+ server. It is a protocol error to send want-ref for the
+ same ref more than once.
If the 'sideband-all' feature is advertised, the following argument can be
included in the client's request:
If the 'packfile-uris' feature is advertised, the following argument
can be included in the client's request as well as the potential
addition of the 'packfile-uris' section in the server's response as
-explained below.
+explained below. Note that at most one `packfile-uris` line can be sent
+to the server.
packfile-uris <comma-separated-list-of-protocols>
Indicates to the server that the client is willing to receive
When using these variants, in order to specify a custom layout you will have to
set configuration variables `mergetool.gvimdiff.layout` and
-`mergetool.nvimdiff.layout` instead of `mergetool.vimdiff.layout`
+`mergetool.nvimdiff.layout` instead of `mergetool.vimdiff.layout` (though the
+latter will be used as fallback if the variant-specific one is not set).
In addition, for backwards compatibility with previous Git versions, you can
also append `1`, `2` or `3` to either `vimdiff` or any of the variants (ex:
* `files` for loose files with packed-refs. This is the default.
+* `reftable` for the reftable format. This format is experimental and its
+ internals are subject to change.
Under `--pretty=reference`, this information will not be shown at all.
--merge::
- After a failed merge, show refs that touch files having a
- conflict and don't exist on all heads to merge.
+ Show commits touching conflicted paths in the range `HEAD...<other>`,
+ where `<other>` is the first existing pseudoref in `MERGE_HEAD`,
+ `CHERRY_PICK_HEAD`, `REVERT_HEAD` or `REBASE_HEAD`. Only works
+ when the index has unmerged entries. This option can be used to show
+ relevant commits when resolving conflicts from a 3-way merge.
--boundary::
Output excluded boundary commits. Boundary commits are
+
The form '--missing=print' is like 'allow-any', but will also print a
list of the missing objects. Object IDs are prefixed with a ``?'' character.
++
+If some tips passed to the traversal are missing, they will be
+considered as missing too, and the traversal will ignore them. In case
+we cannot get their Object ID though, an error will be raised.
--exclude-promisor-objects::
(For internal use only.) Prefilter object traversal at
==== `refStorage`
-Specifies the file format for the ref database. The only valid value
-is `files` (loose references with a packed-refs file).
+Specifies the file format for the ref database. The valid values are
+`files` (loose references with a packed-refs file) and `reftable` (see
+Documentation/technical/reftable.txt).
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.44.0-rc1
+DEF_VER=v2.44.GIT
LF='
'
LIB_OBJS += refs.o
LIB_OBJS += refs/debug.o
LIB_OBJS += refs/files-backend.o
+LIB_OBJS += refs/reftable-backend.o
LIB_OBJS += refs/iterator.o
LIB_OBJS += refs/packed-backend.o
LIB_OBJS += refs/ref-cache.o
-Documentation/RelNotes/2.44.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.45.0.txt
\ No newline at end of file
if (mode == ADD_P_STASH)
s.mode = &patch_mode_stash;
else if (mode == ADD_P_RESET) {
- /*
- * NEEDSWORK: Instead of comparing to the literal "HEAD",
- * compare the commit objects instead so that other ways of
- * saying the same thing (such as "@") are also handled
- * appropriately.
- *
- * This applies to the cases below too.
- */
if (!revision || !strcmp(revision, "HEAD"))
s.mode = &patch_mode_reset_head;
else
[ADVICE_STATUS_U_OPTION] = { "statusUoption" },
[ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated" },
[ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie" },
+ [ADVICE_SUBMODULE_MERGE_CONFLICT] = { "submoduleMergeConflict" },
[ADVICE_SUGGEST_DETACHING_HEAD] = { "suggestDetachingHead" },
[ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath" },
[ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor" },
ADVICE_STATUS_U_OPTION,
ADVICE_SUBMODULES_NOT_UPDATED,
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
+ ADVICE_SUBMODULE_MERGE_CONFLICT,
ADVICE_SUGGEST_DETACHING_HEAD,
ADVICE_UPDATE_SPARSE_PATH,
ADVICE_WAITING_FOR_EDITOR,
return 0;
}
/*
- * Please update $__git_whitespacelist in git-completion.bash
+ * Please update $__git_whitespacelist in git-completion.bash,
+ * Documentation/git-apply.txt, and Documentation/git-am.txt
* when you add new options.
*/
return error(_("unrecognized whitespace option '%s'"), option);
struct fragment *frag = p->fragments;
SWAP(p->new_name, p->old_name);
- SWAP(p->new_mode, p->old_mode);
+ if (p->new_mode)
+ SWAP(p->new_mode, p->old_mode);
SWAP(p->is_new, p->is_delete);
SWAP(p->lines_added, p->lines_deleted);
SWAP(p->old_oid_prefix, p->new_oid_prefix);
return error_errno("%s", old_name);
}
- if (!state->cached && !previous)
- st_mode = ce_mode_from_stat(*ce, st->st_mode);
+ if (!state->cached && !previous) {
+ if (*ce && !(*ce)->ce_mode)
+ BUG("ce_mode == 0 for path '%s'", old_name);
+
+ if (trust_executable_bit)
+ st_mode = ce_mode_from_stat(*ce, st->st_mode);
+ else if (*ce)
+ st_mode = (*ce)->ce_mode;
+ else
+ st_mode = patch->old_mode;
+ }
if (patch->is_new < 0)
patch->is_new = 0;
int i;
for (i = 0; i < nr_tar_filters; i++) {
struct archiver *ar = tar_filters[i];
- if (!strncmp(ar->name, name, len) && !ar->name[len])
+ if (!xstrncmpz(ar->name, name, len))
return ar;
}
return NULL;
const char *subject_start;
int subject_len;
+ if (!buf)
+ die(_("unable to read %s"), oid_to_hex(&commit->object.oid));
+
fprintf(stderr, "%c%c%c ",
(commit_flags & TREESAME) ? ' ' : 'T',
(commit_flags & UNINTERESTING) ? 'U' : ' ',
static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int no_checkout)
{
enum bisect_error res = BISECT_OK;
- struct commit_list *result;
+ struct commit_list *result = NULL;
- result = repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1,
- rev + 1);
+ if (repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1,
+ rev + 1, &result) < 0)
+ exit(128);
for (; result; result = result->next) {
const struct object_id *mb = &result->item->object.oid;
int i, ret = 0;
char *skip_worktree_seen = NULL;
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
- int flags = REFRESH_IGNORE_SKIP_WORKTREE |
+ unsigned int flags = REFRESH_IGNORE_SKIP_WORKTREE |
(verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET);
seen = xcalloc(pathspec->nr, 1);
merged = reference_rev ? repo_in_merge_bases(the_repository, rev,
reference_rev) : 0;
+ if (merged < 0)
+ exit(128);
/*
* After the safety valve is fully redefined to "check with
* any of the following code, but during the transition period,
* a gentle reminder is in order.
*/
- if ((head_rev != reference_rev) &&
- (head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0) != merged) {
- if (merged)
+ if (head_rev != reference_rev) {
+ int expect = head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0;
+ if (expect < 0)
+ exit(128);
+ if (expect == merged)
+ ; /* okay */
+ else if (merged)
warning(_("deleting branch '%s' that has been merged to\n"
" '%s', but not yet merged to HEAD"),
name, reference_name);
&type,
&size);
const char *target;
+
+ if (!buffer)
+ die(_("unable to read %s"), oid_to_hex(&oid));
+
if (!skip_prefix(buffer, "object ", &target) ||
get_oid_hex(target, &blob_oid))
die("%s not a valid tag", oid_to_hex(&oid));
contents = repo_read_object_file(the_repository, oid, &type,
&size);
+ if (!contents)
+ die("object %s disappeared", oid_to_hex(oid));
if (use_mailmap) {
size_t s = size;
size = cast_size_t_to_ulong(s);
}
- if (!contents)
- die("object %s disappeared", oid_to_hex(oid));
if (type != data->type)
die("object %s changed type!?", oid_to_hex(oid));
if (data->info.sizep && size != data->size && !use_mailmap)
buf = repo_read_object_file(the_repository, &data->oid, &data->type,
&data->size);
+ if (!buf)
+ die(_("unable to read %s"), oid_to_hex(&data->oid));
buf = replace_idents_using_mailmap(buf, &s);
data->size = cast_size_t_to_ulong(s);
init_checkout_metadata(&opts.meta, info->refname,
info->commit ? &info->commit->object.oid : null_oid(),
NULL);
- parse_tree(tree);
+ if (parse_tree(tree) < 0)
+ return 128;
init_tree_desc(&tree_desc, tree->buffer, tree->size);
switch (unpack_trees(1, &tree_desc, &opts)) {
case -2:
if (new_branch_info->commit)
BUG("'switch --orphan' should never accept a commit as starting point");
new_tree = parse_tree_indirect(the_hash_algo->empty_tree);
- } else
+ if (!new_tree)
+ BUG("unable to read empty tree");
+ } else {
new_tree = repo_get_commit_tree(the_repository,
new_branch_info->commit);
+ if (!new_tree)
+ return error(_("unable to read tree (%s)"),
+ oid_to_hex(&new_branch_info->commit->object.oid));
+ }
if (opts->discard_changes) {
ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info);
if (ret)
oid_to_hex(old_commit_oid));
init_tree_desc(&trees[0], tree->buffer, tree->size);
- parse_tree(new_tree);
+ if (parse_tree(new_tree) < 0)
+ exit(128);
tree = new_tree;
init_tree_desc(&trees[1], tree->buffer, tree->size);
struct tree **source_tree = &opts->source_tree;
struct object_id branch_rev;
- new_branch_info->name = xstrdup(arg);
+ /* treat '@' as a shortcut for 'HEAD' */
+ new_branch_info->name = !strcmp(arg, "@") ? xstrdup("HEAD") :
+ xstrdup(arg);
setup_branch_path(new_branch_info);
if (!check_refname_format(new_branch_info->path, 0) &&
if (!new_branch_info->commit) {
/* not a commit */
*source_tree = parse_tree_indirect(rev);
+ if (!*source_tree)
+ die(_("unable to read tree (%s)"), oid_to_hex(rev));
} else {
parse_commit_or_die(new_branch_info->commit);
*source_tree = repo_get_commit_tree(the_repository,
new_branch_info->commit);
+ if (!*source_tree)
+ die(_("unable to read tree (%s)"),
+ oid_to_hex(&new_branch_info->commit->object.oid));
}
}
#include "help.h"
#include "prompt.h"
-static int force = -1; /* unset */
+static int require_force = -1; /* unset */
static int interactive;
static struct string_list del_list = STRING_LIST_INIT_DUP;
static unsigned int colopts;
}
if (!strcmp(var, "clean.requireforce")) {
- force = !git_config_bool(var, value);
+ require_force = git_config_bool(var, value);
return 0;
}
{
int i, res;
int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
- int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
+ int ignored_only = 0, force = 0, errors = 0, gone = 1;
int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
struct strbuf abs_path = STRBUF_INIT;
struct dir_struct dir = DIR_INIT;
};
git_config(git_clean_config, NULL);
- if (force < 0)
- force = 0;
- else
- config_set = 1;
argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
0);
- if (!interactive && !dry_run && !force) {
- if (config_set)
- die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
- "refusing to clean"));
- else
- die(_("clean.requireForce defaults to true and neither -i, -n, nor -f given;"
- " refusing to clean"));
- }
+ if (require_force != 0 && !force && !interactive && !dry_run)
+ die(_("clean.requireForce is true and -f not given: refusing to clean"));
if (force > 1)
rm_flags = 0;
tree = parse_tree_indirect(&oid);
if (!tree)
die(_("unable to parse commit %s"), oid_to_hex(&oid));
- parse_tree(tree);
+ if (parse_tree(tree) < 0)
+ exit(128);
init_tree_desc(&t, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts) < 0)
die(_("unable to checkout working tree"));
struct ref *mapped_refs = NULL;
const struct ref *ref;
struct strbuf key = STRBUF_INIT;
+ struct strbuf buf = STRBUF_INIT;
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
struct transport *transport = NULL;
const char *src_ref_prefix = "refs/heads/";
git_dir = real_git_dir;
}
+ /*
+ * We have a chicken-and-egg situation between initializing the refdb
+ * and spawning transport helpers:
+ *
+ * - Initializing the refdb requires us to know about the object
+ * format. We thus have to spawn the transport helper to learn
+ * about it.
+ *
+ * - The transport helper may want to access the Git repository. But
+ * because the refdb has not been initialized, we don't have "HEAD"
+ * or "refs/". Thus, the helper cannot find the Git repository.
+ *
+ * Ideally, we would have structured the helper protocol such that it's
+ * mandatory for the helper to first announce its capabilities without
+ * yet assuming a fully initialized repository. Like that, we could
+ * have added a "lazy-refdb-init" capability that announces whether the
+ * helper is ready to handle not-yet-initialized refdbs. If any helper
+ * didn't support them, we would have fully initialized the refdb with
+ * the SHA1 object format, but later on bailed out if we found out that
+ * the remote repository used a different object format.
+ *
+ * But we didn't, and thus we use the following workaround to partially
+ * initialize the repository's refdb such that it can be discovered by
+ * Git commands. To do so, we:
+ *
+ * - Create an invalid HEAD ref pointing at "refs/heads/.invalid".
+ *
+ * - Create the "refs/" directory.
+ *
+ * - Set up the ref storage format and repository version as
+ * required.
+ *
+ * This is sufficient for Git commands to discover the Git directory.
+ */
+ initialize_repository_version(GIT_HASH_UNKNOWN,
+ the_repository->ref_storage_format, 1);
+
+ strbuf_addf(&buf, "%s/HEAD", git_dir);
+ write_file(buf.buf, "ref: refs/heads/.invalid");
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "%s/refs", git_dir);
+ safe_create_dir(buf.buf, 1);
+
/*
* additional config can be injected with -c, make sure it's included
* after init_db, which clears the entire config environment.
free(remote_name);
strbuf_release(&reflog_msg);
strbuf_release(&branch_top);
+ strbuf_release(&buf);
strbuf_release(&key);
free_refs(mapped_refs);
free_refs(remote_head_points_at);
memset(&copts, 0, sizeof(copts));
copts.padding = 1;
argc = parse_options(argc, argv, prefix, options, builtin_column_usage, 0);
+ if (copts.padding < 0)
+ die(_("%s must be non-negative"), "--padding");
if (argc)
usage_with_options(builtin_column_usage, options);
if (real_command || command) {
tree = parse_tree_indirect(¤t_head->object.oid);
if (!tree)
die(_("failed to unpack HEAD tree object"));
- parse_tree(tree);
+ if (parse_tree(tree) < 0)
+ exit(128);
init_tree_desc(&t, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts))
exit(128); /* We've already reported the error, finish dying */
const char *hook_arg2 = NULL;
int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE);
int old_display_comment_prefix;
- int merge_contains_scissors = 0;
int invoked_hook;
/* This checks and barfs if author is badly specified */
wt_status_locate_end(sb.buf + merge_msg_start,
sb.len - merge_msg_start) <
sb.len - merge_msg_start)
- merge_contains_scissors = 1;
+ s->added_cut_line = 1;
} else if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0)
die_errno(_("could not read SQUASH_MSG"));
" yourself if you want to.\n"
"An empty message aborts the commit.\n");
if (whence != FROM_COMMIT) {
- if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
- !merge_contains_scissors)
- wt_status_add_cut_line(s->fp);
+ if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS)
+ wt_status_add_cut_line(s);
status_printf_ln(
s, GIT_COLOR_NORMAL,
whence == FROM_MERGE ?
if (cleanup_mode == COMMIT_MSG_CLEANUP_ALL)
status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_all, comment_line_char);
else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
- if (whence == FROM_COMMIT && !merge_contains_scissors)
- wt_status_add_cut_line(s->fp);
+ if (whence == FROM_COMMIT)
+ wt_status_add_cut_line(s);
} else /* COMMIT_MSG_CLEANUP_SPACE, that is. */
status_printf(s, GIT_COLOR_NORMAL, hint_cleanup_space, comment_line_char);
a = container_of(eptr, const struct anonymized_entry, hash);
if (keydata) {
const struct anonymized_entry_key *key = keydata;
- int equal = !strncmp(a->orig, key->orig, key->orig_len) &&
- !a->orig[key->orig_len];
+ int equal = !xstrncmpz(a->orig, key->orig, key->orig_len);
return !equal;
}
oidclr(&old_oid);
if (!force_update && !is_null_oid(&old_oid)) {
struct commit *old_cmit, *new_cmit;
+ int ret;
old_cmit = lookup_commit_reference_gently(the_repository,
&old_oid, 0);
if (!old_cmit || !new_cmit)
return error("Branch %s is missing commits.", b->name);
- if (!repo_in_merge_bases(the_repository, old_cmit, new_cmit)) {
+ ret = repo_in_merge_bases(the_repository, old_cmit, new_cmit);
+ if (ret < 0)
+ exit(128);
+ if (!ret) {
warning("Not updating %s"
" (new tip %s does not contain %s)",
b->name, oid_to_hex(&b->oid),
continue;
if (!rs->items[i].dst ||
(rs->items[i].src &&
- !strncmp(rs->items[i].src,
- ref_namespace[NAMESPACE_TAGS].ref,
- strlen(ref_namespace[NAMESPACE_TAGS].ref)))) {
+ starts_with(rs->items[i].src,
+ ref_namespace[NAMESPACE_TAGS].ref))) {
int j;
free(rs->items[i].src);
uint64_t t_before = getnanotime();
fast_forward = repo_in_merge_bases(the_repository, current,
updated);
+ if (fast_forward < 0)
+ exit(128);
forced_updates_ms += (getnanotime() - t_before) / 1000000;
} else {
fast_forward = 1;
{
struct ref_sorting *sorting;
struct string_list sorting_options = STRING_LIST_INIT_DUP;
- int icase = 0;
+ int icase = 0, include_root_refs = 0, from_stdin = 0;
struct ref_filter filter = REF_FILTER_INIT;
struct ref_format format = REF_FORMAT_INIT;
- int from_stdin = 0;
+ unsigned int flags = FILTER_REFS_REGULAR;
struct strvec vec = STRVEC_INIT;
struct option opts[] = {
OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")),
OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
OPT_BOOL(0, "stdin", &from_stdin, N_("read reference patterns from stdin")),
+ OPT_BOOL(0, "include-root-refs", &include_root_refs, N_("also include HEAD ref and pseudorefs")),
OPT_END(),
};
filter.name_patterns = argv;
}
+ if (include_root_refs)
+ flags |= FILTER_REFS_ROOT_REFS;
+
filter.match_as_path = 1;
- filter_and_format_refs(&filter, FILTER_REFS_ALL, sorting, &format);
+ filter_and_format_refs(&filter, flags, sorting, &format);
ref_filter_clear(&filter);
ref_sorting_release(sorting);
return 0;
}
-static int fsck_handle_reflog(const char *logname,
- const struct object_id *oid UNUSED,
- int flag UNUSED, void *cb_data)
+static int fsck_handle_reflog(const char *logname, void *cb_data)
{
struct strbuf refname = STRBUF_INIT;
data = repo_read_object_file(the_repository, &ce->oid,
&type, &size);
+ if (!data)
+ die(_("unable to read tree %s"), oid_to_hex(&ce->oid));
init_tree_desc(&tree, data, size);
hit |= grep_tree(opt, pathspec, &tree, &name, 0, 0);
{
struct commit *base = NULL;
struct commit **rev;
- int i = 0, rev_nr = 0, auto_select, die_on_failure;
+ int i = 0, rev_nr = 0, auto_select, die_on_failure, ret;
switch (auto_base) {
case AUTO_BASE_NEVER:
struct branch *curr_branch = branch_get(NULL);
const char *upstream = branch_get_upstream(curr_branch, NULL);
if (upstream) {
- struct commit_list *base_list;
+ struct commit_list *base_list = NULL;
struct commit *commit;
struct object_id oid;
return NULL;
}
commit = lookup_commit_or_die(&oid, "upstream base");
- base_list = repo_get_merge_bases_many(the_repository,
- commit, total,
- list);
- /* There should be one and only one merge base. */
- if (!base_list || base_list->next) {
+ if (repo_get_merge_bases_many(the_repository,
+ commit, total,
+ list,
+ &base_list) < 0 ||
+ /* There should be one and only one merge base. */
+ !base_list || base_list->next) {
if (die_on_failure) {
die(_("could not find exact merge base"));
} else {
*/
while (rev_nr > 1) {
for (i = 0; i < rev_nr / 2; i++) {
- struct commit_list *merge_base;
- merge_base = repo_get_merge_bases(the_repository,
- rev[2 * i],
- rev[2 * i + 1]);
- if (!merge_base || merge_base->next) {
+ struct commit_list *merge_base = NULL;
+ if (repo_get_merge_bases(the_repository,
+ rev[2 * i],
+ rev[2 * i + 1], &merge_base) < 0 ||
+ !merge_base || merge_base->next) {
if (die_on_failure) {
die(_("failed to find exact merge base"));
} else {
rev_nr = DIV_ROUND_UP(rev_nr, 2);
}
- if (!repo_in_merge_bases(the_repository, base, rev[0])) {
+ ret = repo_in_merge_bases(the_repository, base, rev[0]);
+ if (ret < 0)
+ exit(128);
+ if (!ret) {
if (die_on_failure) {
die(_("base commit should be the ancestor of revision list"));
} else {
static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
{
- struct commit_list *result, *r;
+ struct commit_list *result = NULL, *r;
- result = repo_get_merge_bases_many_dirty(the_repository, rev[0],
- rev_nr - 1, rev + 1);
+ if (repo_get_merge_bases_many_dirty(the_repository, rev[0],
+ rev_nr - 1, rev + 1, &result) < 0) {
+ free_commit_list(result);
+ return -1;
+ }
if (!result)
return 1;
static int handle_octopus(int count, const char **args, int show_all)
{
struct commit_list *revs = NULL;
- struct commit_list *result, *rev;
+ struct commit_list *result = NULL, *rev;
int i;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
- result = get_octopus_merge_bases(revs);
+ if (get_octopus_merge_bases(revs, &result) < 0) {
+ free_commit_list(revs);
+ free_commit_list(result);
+ return 128;
+ }
free_commit_list(revs);
reduce_heads_replace(&result);
static int handle_is_ancestor(int argc, const char **argv)
{
struct commit *one, *two;
+ int ret;
if (argc != 2)
die("--is-ancestor takes exactly two commits");
one = get_commit_reference(argv[0]);
two = get_commit_reference(argv[1]);
- if (repo_in_merge_bases(the_repository, one, two))
+ ret = repo_in_merge_bases(the_repository, one, two);
+ if (ret < 0)
+ exit(128);
+ if (ret)
return 0;
else
return 1;
struct merge_options opt;
copy_merge_options(&opt, &o->merge_options);
- parent1 = get_merge_parent(branch1);
- if (!parent1)
- help_unknown_ref(branch1, "merge-tree",
- _("not something we can merge"));
-
- parent2 = get_merge_parent(branch2);
- if (!parent2)
- help_unknown_ref(branch2, "merge-tree",
- _("not something we can merge"));
-
opt.show_rename_progress = 0;
opt.branch1 = branch1;
opt.branch2 = branch2;
if (merge_base) {
- struct commit *base_commit;
struct tree *base_tree, *parent1_tree, *parent2_tree;
- base_commit = lookup_commit_reference_by_name(merge_base);
- if (!base_commit)
- die(_("could not lookup commit '%s'"), merge_base);
+ /*
+ * We actually only need the trees because we already
+ * have a merge base.
+ */
+ struct object_id base_oid, head_oid, merge_oid;
+
+ if (repo_get_oid_treeish(the_repository, merge_base, &base_oid))
+ die(_("could not parse as tree '%s'"), merge_base);
+ base_tree = parse_tree_indirect(&base_oid);
+ if (!base_tree)
+ die(_("unable to read tree (%s)"), oid_to_hex(&base_oid));
+ if (repo_get_oid_treeish(the_repository, branch1, &head_oid))
+ die(_("could not parse as tree '%s'"), branch1);
+ parent1_tree = parse_tree_indirect(&head_oid);
+ if (!parent1_tree)
+ die(_("unable to read tree (%s)"), oid_to_hex(&head_oid));
+ if (repo_get_oid_treeish(the_repository, branch2, &merge_oid))
+ die(_("could not parse as tree '%s'"), branch2);
+ parent2_tree = parse_tree_indirect(&merge_oid);
+ if (!parent2_tree)
+ die(_("unable to read tree (%s)"), oid_to_hex(&merge_oid));
opt.ancestor = merge_base;
- base_tree = repo_get_commit_tree(the_repository, base_commit);
- parent1_tree = repo_get_commit_tree(the_repository, parent1);
- parent2_tree = repo_get_commit_tree(the_repository, parent2);
merge_incore_nonrecursive(&opt, base_tree, parent1_tree, parent2_tree, &result);
} else {
+ parent1 = get_merge_parent(branch1);
+ if (!parent1)
+ help_unknown_ref(branch1, "merge-tree",
+ _("not something we can merge"));
+
+ parent2 = get_merge_parent(branch2);
+ if (!parent2)
+ help_unknown_ref(branch2, "merge-tree",
+ _("not something we can merge"));
+
/*
* Get the merge bases, in reverse order; see comment above
* merge_incore_recursive in merge-ort.h
*/
- merge_bases = repo_get_merge_bases(the_repository, parent1,
- parent2);
+ if (repo_get_merge_bases(the_repository, parent1,
+ parent2, &merge_bases) < 0)
+ exit(128);
if (!merge_bases && !o->allow_unrelated_histories)
die(_("refusing to merge unrelated histories"));
merge_bases = reverse_commit_list(merge_bases);
int j, found = 0;
struct cmdname *ent = main_cmds.names[i];
for (j = 0; !found && j < ARRAY_SIZE(all_strategy); j++)
- if (!strncmp(ent->name, all_strategy[j].name, ent->len)
- && !all_strategy[j].name[ent->len])
+ if (!xstrncmpz(all_strategy[j].name, ent->name, ent->len))
found = 1;
if (!found)
add_cmdname(¬_strategies, ent->name, ent->len);
if (!remoteheads)
; /* already up-to-date */
- else if (!remoteheads->next)
- common = repo_get_merge_bases(the_repository, head_commit,
- remoteheads->item);
- else {
+ else if (!remoteheads->next) {
+ if (repo_get_merge_bases(the_repository, head_commit,
+ remoteheads->item, &common) < 0) {
+ ret = 2;
+ goto done;
+ }
+ } else {
struct commit_list *list = remoteheads;
commit_list_insert(head_commit, &list);
- common = get_octopus_merge_bases(list);
+ if (get_octopus_merge_bases(list, &common) < 0) {
+ free(list);
+ ret = 2;
+ goto done;
+ }
free(list);
}
struct commit_list *j;
for (j = remoteheads; j; j = j->next) {
- struct commit_list *common_one;
+ struct commit_list *common_one = NULL;
struct commit *common_item;
/*
* merge_bases again, otherwise "git merge HEAD^
* HEAD^^" would be missed.
*/
- common_one = repo_get_merge_bases(the_repository,
- head_commit,
- j->item);
+ if (repo_get_merge_bases(the_repository, head_commit,
+ j->item, &common_one) < 0)
+ exit(128);
+
common_item = common_one->item;
free_commit_list(common_one);
if (!oideq(&common_item->object.oid, &j->item->object.oid)) {
#include "commit-slab.h"
#include "commit-graph.h"
#include "wildmatch.h"
+#include "mem-pool.h"
/*
* One day. See the 'name a rev shortly after epoch' test in t6120 when
return name;
}
-static char *get_parent_name(const struct rev_name *name, int parent_number)
+static char *get_parent_name(const struct rev_name *name, int parent_number,
+ struct mem_pool *string_pool)
{
- struct strbuf sb = STRBUF_INIT;
size_t len;
strip_suffix(name->tip_name, "^0", &len);
if (name->generation > 0) {
- strbuf_grow(&sb, len +
- 1 + decimal_width(name->generation) +
- 1 + decimal_width(parent_number));
- strbuf_addf(&sb, "%.*s~%d^%d", (int)len, name->tip_name,
- name->generation, parent_number);
+ return mem_pool_strfmt(string_pool, "%.*s~%d^%d",
+ (int)len, name->tip_name,
+ name->generation, parent_number);
} else {
- strbuf_grow(&sb, len +
- 1 + decimal_width(parent_number));
- strbuf_addf(&sb, "%.*s^%d", (int)len, name->tip_name,
- parent_number);
+ return mem_pool_strfmt(string_pool, "%.*s^%d",
+ (int)len, name->tip_name, parent_number);
}
- return strbuf_detach(&sb, NULL);
}
static void name_rev(struct commit *start_commit,
const char *tip_name, timestamp_t taggerdate,
- int from_tag, int deref)
+ int from_tag, int deref, struct mem_pool *string_pool)
{
struct prio_queue queue;
struct commit *commit;
if (!start_name)
return;
if (deref)
- start_name->tip_name = xstrfmt("%s^0", tip_name);
+ start_name->tip_name = mem_pool_strfmt(string_pool, "%s^0",
+ tip_name);
else
- start_name->tip_name = xstrdup(tip_name);
+ start_name->tip_name = mem_pool_strdup(string_pool, tip_name);
memset(&queue, 0, sizeof(queue)); /* Use the prio_queue as LIFO */
prio_queue_put(&queue, start_commit);
if (parent_number > 1)
parent_name->tip_name =
get_parent_name(name,
- parent_number);
+ parent_number,
+ string_pool);
else
parent_name->tip_name = name->tip_name;
ALLOC_GROW(parents_to_queue,
return 0;
}
-static void name_tips(void)
+static void name_tips(struct mem_pool *string_pool)
{
int i;
struct tip_table_entry *e = &tip_table.table[i];
if (e->commit) {
name_rev(e->commit, e->refname, e->taggerdate,
- e->from_tag, e->deref);
+ e->from_tag, e->deref, string_pool);
}
}
}
int cmd_name_rev(int argc, const char **argv, const char *prefix)
{
+ struct mem_pool string_pool;
struct object_array revs = OBJECT_ARRAY_INIT;
int all = 0, annotate_stdin = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
OPT_END(),
};
+ mem_pool_init(&string_pool, 0);
init_commit_rev_name(&rev_names);
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
adjust_cutoff_timestamp_for_slop();
for_each_ref(name_ref, &data);
- name_tips();
+ name_tips(&string_pool);
if (annotate_stdin) {
struct strbuf sb = STRBUF_INIT;
always, allow_undefined, data.name_only);
}
+ UNLEAK(string_pool);
UNLEAK(revs);
return 0;
}
struct strbuf buf = STRBUF_INIT;
char *prev_buf = repo_read_object_file(the_repository, note, &type, &size);
- if (prev_buf && size)
+ if (!prev_buf)
+ die(_("unable to read %s"), oid_to_hex(note));
+ if (size)
strbuf_add(&buf, prev_buf, size);
- if (d.buf.len && prev_buf && size)
+ if (d.buf.len && size)
append_separator(&buf);
strbuf_insert(&d.buf, 0, buf.buf, buf.len);
const struct object_id *merge_head,
const struct object_id *fork_point)
{
- struct commit_list *revs = NULL, *result;
+ struct commit_list *revs = NULL, *result = NULL;
commit_list_insert(lookup_commit_reference(the_repository, curr_head),
&revs);
commit_list_insert(lookup_commit_reference(the_repository, fork_point),
&revs);
- result = get_octopus_merge_bases(revs);
+ if (get_octopus_merge_bases(revs, &result) < 0)
+ exit(128);
free_commit_list(revs);
reduce_heads_replace(&result);
merge_head = lookup_commit_reference(the_repository, orig_merge_head);
ret = repo_is_descendant_of(the_repository, merge_head, list);
free_commit_list(list);
+ if (ret < 0)
+ exit(128);
return ret;
}
commit_list_insert(theirs, &list);
ok = repo_is_descendant_of(the_repository, ours, list);
free_commit_list(list);
+ if (ok < 0)
+ exit(128);
if (!ok)
return 0;
}
cache_tree_free(&the_index.cache_tree);
for (i = 0; i < nr_trees; i++) {
struct tree *tree = trees[i];
- parse_tree(tree);
+ if (parse_tree(tree) < 0)
+ return 128;
init_tree_desc(t+i, tree->buffer, tree->size);
}
if (unpack_trees(nr_trees, t, &opts))
if (!upstream)
goto done;
- merge_bases = repo_get_merge_bases(the_repository, upstream, head);
+ if (repo_get_merge_bases(the_repository, upstream, head, &merge_bases) < 0)
+ exit(128);
if (!merge_bases || merge_bases->next)
goto done;
{
struct commit_list *merge_bases = NULL;
- merge_bases = repo_get_merge_bases(the_repository, options->onto,
- options->orig_head);
+ if (repo_get_merge_bases(the_repository, options->onto,
+ options->orig_head, &merge_bases) < 0)
+ exit(128);
if (!merge_bases || merge_bases->next)
oidcpy(branch_base, null_oid());
else
die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
if (options.action != ACTION_NONE && !in_progress)
- die(_("No rebase in progress?"));
+ die(_("no rebase in progress"));
if (options.action == ACTION_EDIT_TODO && !is_merge(&options))
die(_("The --edit-todo action can only be used during "
return strbuf_detach(&buf, NULL);
}
-static char *find_header(const char *msg, size_t len, const char *key,
- const char **next_line)
-{
- size_t out_len;
- const char *val = find_header_mem(msg, len, key, &out_len);
-
- if (!val)
- return NULL;
-
- if (next_line)
- *next_line = val + out_len + 1;
-
- return xmemdupz(val, out_len);
-}
-
/*
* Return zero if a and b are equal up to n bytes and nonzero if they are not.
* This operation is guaranteed to run in constant time to avoid leaking data.
return res;
}
-static const char *check_nonce(const char *buf, size_t len)
+static const char *check_nonce(const char *buf)
{
- char *nonce = find_header(buf, len, "nonce", NULL);
+ size_t noncelen;
+ const char *found = find_commit_header(buf, "nonce", &noncelen);
+ char *nonce = found ? xmemdupz(found, noncelen) : NULL;
timestamp_t stamp, ostamp;
char *bohmac, *expect = NULL;
const char *retval = NONCE_BAD;
- size_t noncelen;
if (!nonce) {
retval = NONCE_MISSING;
goto leave;
}
- noncelen = strlen(nonce);
expect = prepare_push_cert_nonce(service_dir, stamp);
if (noncelen != strlen(expect)) {
/* This is not even the right size. */
static int check_cert_push_options(const struct string_list *push_options)
{
const char *buf = push_cert.buf;
- int len = push_cert.len;
- char *option;
- const char *next_line;
+ const char *option;
+ size_t optionlen;
int options_seen = 0;
int retval = 1;
- if (!len)
+ if (!*buf)
return 1;
- while ((option = find_header(buf, len, "push-option", &next_line))) {
- len -= (next_line - buf);
- buf = next_line;
+ while ((option = find_commit_header(buf, "push-option", &optionlen))) {
+ buf = option + optionlen + 1;
options_seen++;
if (options_seen > push_options->nr
- || strcmp(option,
- push_options->items[options_seen - 1].string)) {
- retval = 0;
- goto leave;
- }
- free(option);
+ || xstrncmpz(push_options->items[options_seen - 1].string,
+ option, optionlen))
+ return 0;
}
if (options_seen != push_options->nr)
retval = 0;
-leave:
- free(option);
return retval;
}
check_signature(&sigcheck, push_cert.buf + bogs,
push_cert.len - bogs);
- nonce_status = check_nonce(push_cert.buf, bogs);
+ nonce_status = check_nonce(sigcheck.payload);
}
if (!is_null_oid(&push_cert_oid)) {
strvec_pushf(&proc->env, "GIT_PUSH_CERT=%s",
starts_with(name, "refs/heads/")) {
struct object *old_object, *new_object;
struct commit *old_commit, *new_commit;
+ int ret2;
old_object = parse_object(the_repository, old_oid);
new_object = parse_object(the_repository, new_oid);
}
old_commit = (struct commit *)old_object;
new_commit = (struct commit *)new_object;
- if (!repo_in_merge_bases(the_repository, old_commit, new_commit)) {
+ ret2 = repo_in_merge_bases(the_repository, old_commit, new_commit);
+ if (ret2 < 0)
+ exit(128);
+ if (!ret2) {
rp_error("denying non-fast-forward %s"
" (you should pull first)", name);
ret = "non-fast-forward";
#include "wildmatch.h"
#include "worktree.h"
#include "reflog.h"
+#include "refs.h"
#include "parse-options.h"
#define BUILTIN_REFLOG_SHOW_USAGE \
N_("git reflog [show] [<log-options>] [<ref>]")
+#define BUILTIN_REFLOG_LIST_USAGE \
+ N_("git reflog list")
+
#define BUILTIN_REFLOG_EXPIRE_USAGE \
N_("git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" \
" [--rewrite] [--updateref] [--stale-fix]\n" \
NULL,
};
+static const char *const reflog_list_usage[] = {
+ BUILTIN_REFLOG_LIST_USAGE,
+ NULL,
+};
+
static const char *const reflog_expire_usage[] = {
BUILTIN_REFLOG_EXPIRE_USAGE,
NULL
static const char *const reflog_usage[] = {
BUILTIN_REFLOG_SHOW_USAGE,
+ BUILTIN_REFLOG_LIST_USAGE,
BUILTIN_REFLOG_EXPIRE_USAGE,
BUILTIN_REFLOG_DELETE_USAGE,
BUILTIN_REFLOG_EXISTS_USAGE,
struct string_list reflogs;
};
-static int collect_reflog(const char *ref, const struct object_id *oid UNUSED,
- int flags UNUSED, void *cb_data)
+static int collect_reflog(const char *ref, void *cb_data)
{
struct worktree_reflogs *cb = cb_data;
struct worktree *worktree = cb->worktree;
reflog_expire_cfg_tail = &reflog_expire_cfg;
for (ent = reflog_expire_cfg; ent; ent = ent->next)
- if (!strncmp(ent->pattern, pattern, len) &&
- ent->pattern[len] == '\0')
+ if (!xstrncmpz(ent->pattern, pattern, len))
return ent;
FLEX_ALLOC_MEM(ent, pattern, pattern, len);
return cmd_log_reflog(argc, argv, prefix);
}
+static int show_reflog(const char *refname, void *cb_data UNUSED)
+{
+ printf("%s\n", refname);
+ return 0;
+}
+
+static int cmd_reflog_list(int argc, const char **argv, const char *prefix)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ struct ref_store *ref_store;
+
+ argc = parse_options(argc, argv, prefix, options, reflog_list_usage, 0);
+ if (argc)
+ return error(_("%s does not accept arguments: '%s'"),
+ "list", argv[0]);
+
+ ref_store = get_main_ref_store(the_repository);
+
+ return refs_for_each_reflog(ref_store, show_reflog, NULL);
+}
+
static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
{
struct cmd_reflog_expire_cb cmd = { 0 };
parse_opt_subcommand_fn *fn = NULL;
struct option options[] = {
OPT_SUBCOMMAND("show", &fn, cmd_reflog_show),
+ OPT_SUBCOMMAND("list", &fn, cmd_reflog_list),
OPT_SUBCOMMAND("expire", &fn, cmd_reflog_expire),
OPT_SUBCOMMAND("delete", &fn, cmd_reflog_delete),
OPT_SUBCOMMAND("exists", &fn, cmd_reflog_exists),
if (reset_type == MIXED || reset_type == HARD) {
tree = parse_tree_indirect(oid);
+ if (!tree) {
+ error(_("unable to read tree (%s)"), oid_to_hex(oid));
+ goto out;
+ }
prime_cache_tree(the_repository, the_repository->index, tree);
}
verify_filename(prefix, argv[0], 1);
}
}
- *rev_ret = rev;
+
+ /* treat '@' as a shortcut for 'HEAD' */
+ *rev_ret = !strcmp("@", rev) ? "HEAD" : rev;
parse_pathspec(pathspec, 0,
PATHSPEC_PREFER_FULL |
*
* Let "--missing" to conditionally set fetch_if_missing.
*/
+ /*
+ * NEEDSWORK: These loops that attempt to find presence of
+ * options without understanding that the options they are
+ * skipping are broken (e.g., it would not know "--grep
+ * --exclude-promisor-objects" is not triggering
+ * "--exclude-promisor-objects" option). We really need
+ * setup_revisions() to have a mechanism to allow and disallow
+ * some sets of options for different commands (like rev-list,
+ * replay, etc). Such a mechanism should do an early parsing
+ * of options and be able to manage the `--missing=...` and
+ * `--exclude-promisor-objects` options below.
+ */
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--exclude-promisor-objects")) {
if (arg_print_omitted)
oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
- if (arg_missing_action == MA_PRINT)
+ if (arg_missing_action == MA_PRINT) {
oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE);
+ /* Add missing tips */
+ oidset_insert_from_set(&missing_objects, &revs.missing_commits);
+ oidset_clear(&revs.missing_commits);
+ }
traverse_commit_list_filtered(
&revs, show_commit, show_object, &info,
show_rev(NORMAL, &end_oid, end);
show_rev(symmetric ? NORMAL : REVERSED, &start_oid, start);
if (symmetric) {
- struct commit_list *exclude;
+ struct commit_list *exclude = NULL;
struct commit *a, *b;
a = lookup_commit_reference(the_repository, &start_oid);
b = lookup_commit_reference(the_repository, &end_oid);
*dotdot = '.';
return 0;
}
- exclude = repo_get_merge_bases(the_repository, a, b);
+ if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0)
+ exit(128);
while (exclude) {
struct commit *commit = pop_commit(&exclude);
show_rev(REVERSED, &commit->object.oid, NULL);
struct column_options copts;
memset(&copts, 0, sizeof(copts));
copts.padding = 2;
- run_column_filter(colopts, &copts);
+ if (run_column_filter(colopts, &copts))
+ die(_("could not start 'git column'"));
}
filter.name_patterns = argv;
ret = list_tags(&filter, sorting, &format);
#include "replace-object.h"
#include "upload-pack.h"
#include "serve.h"
+#include "commit.h"
static const char * const upload_pack_usage[] = {
N_("git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
packet_trace_identity("upload-pack");
disable_replace_refs();
+ save_commit_buffer = 0;
argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);
struct cache_tree_sub *sub;
struct tree *subtree = lookup_tree(r, &entry.oid);
- if (!subtree->object.parsed)
- parse_tree(subtree);
+ if (parse_tree(subtree) < 0)
+ exit(128);
sub = cache_tree_sub(it, entry.path);
sub->cache_tree = cache_tree();
MAKEFLAGS="$MAKEFLAGS NO_REGEX=Yes ICONV_OMITS_BOM=Yes"
MAKEFLAGS="$MAKEFLAGS GIT_TEST_UTF8_LOCALE=C.UTF-8"
;;
-linux-leaks)
+linux-leaks|linux-reftable-leaks)
export SANITIZE=leak
export GIT_TEST_PASSING_SANITIZE_LEAK=true
export GIT_TEST_SANITIZE_LEAK_LOG=true
linux-sha256)
export GIT_TEST_DEFAULT_HASH=sha256
;;
+linux-reftable|linux-reftable-leaks|osx-reftable)
+ export GIT_TEST_DEFAULT_REF_FORMAT=reftable
+ ;;
pedantic)
# Don't run the tests; we only care about whether Git can be
# built.
{
struct column_options nopts;
+ if (opts && (0 > opts->padding))
+ BUG("padding must be non-negative");
if (!list->nr)
return;
assert((colopts & COL_ENABLE_MASK) != COL_AUTO);
{
struct strvec *argv;
+ if (opts && (0 > opts->padding))
+ BUG("padding must be non-negative");
if (fd_out != -1)
return -1;
free_filespec(df);
} else {
blob = repo_read_object_file(r, oid, &type, size);
+ if (!blob)
+ die(_("unable to read %s"), oid_to_hex(oid));
if (type != OBJ_BLOB)
die("object '%s' is not a blob!", oid_to_hex(oid));
}
}
/* all input commits in one and twos[] must have been parsed! */
-static struct commit_list *paint_down_to_common(struct repository *r,
- struct commit *one, int n,
- struct commit **twos,
- timestamp_t min_generation)
+static int paint_down_to_common(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ timestamp_t min_generation,
+ int ignore_missing_commits,
+ struct commit_list **result)
{
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
- struct commit_list *result = NULL;
int i;
timestamp_t last_gen = GENERATION_NUMBER_INFINITY;
one->object.flags |= PARENT1;
if (!n) {
- commit_list_append(one, &result);
- return result;
+ commit_list_append(one, result);
+ return 0;
}
prio_queue_put(&queue, one);
if (flags == (PARENT1 | PARENT2)) {
if (!(commit->object.flags & RESULT)) {
commit->object.flags |= RESULT;
- commit_list_insert_by_date(commit, &result);
+ commit_list_insert_by_date(commit, result);
}
/* Mark parents of a found merge stale */
flags |= STALE;
parents = parents->next;
if ((p->object.flags & flags) == flags)
continue;
- if (repo_parse_commit(r, p))
- return NULL;
+ if (repo_parse_commit(r, p)) {
+ clear_prio_queue(&queue);
+ free_commit_list(*result);
+ *result = NULL;
+ /*
+ * At this stage, we know that the commit is
+ * missing: `repo_parse_commit()` uses
+ * `OBJECT_INFO_DIE_IF_CORRUPT` and therefore
+ * corrupt commits would already have been
+ * dispatched with a `die()`.
+ */
+ if (ignore_missing_commits)
+ return 0;
+ return error(_("could not parse commit %s"),
+ oid_to_hex(&p->object.oid));
+ }
p->object.flags |= flags;
prio_queue_put(&queue, p);
}
}
clear_prio_queue(&queue);
- return result;
+ return 0;
}
-static struct commit_list *merge_bases_many(struct repository *r,
- struct commit *one, int n,
- struct commit **twos)
+static int merge_bases_many(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ struct commit_list **result)
{
struct commit_list *list = NULL;
- struct commit_list *result = NULL;
int i;
for (i = 0; i < n; i++) {
- if (one == twos[i])
+ if (one == twos[i]) {
/*
* We do not mark this even with RESULT so we do not
* have to clean it up.
*/
- return commit_list_insert(one, &result);
+ *result = commit_list_insert(one, result);
+ return 0;
+ }
}
+ if (!one)
+ return 0;
if (repo_parse_commit(r, one))
- return NULL;
+ return error(_("could not parse commit %s"),
+ oid_to_hex(&one->object.oid));
for (i = 0; i < n; i++) {
+ if (!twos[i])
+ return 0;
if (repo_parse_commit(r, twos[i]))
- return NULL;
+ return error(_("could not parse commit %s"),
+ oid_to_hex(&twos[i]->object.oid));
}
- list = paint_down_to_common(r, one, n, twos, 0);
+ if (paint_down_to_common(r, one, n, twos, 0, 0, &list)) {
+ free_commit_list(list);
+ return -1;
+ }
while (list) {
struct commit *commit = pop_commit(&list);
if (!(commit->object.flags & STALE))
- commit_list_insert_by_date(commit, &result);
+ commit_list_insert_by_date(commit, result);
}
- return result;
+ return 0;
}
-struct commit_list *get_octopus_merge_bases(struct commit_list *in)
+int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result)
{
- struct commit_list *i, *j, *k, *ret = NULL;
+ struct commit_list *i, *j, *k;
if (!in)
- return ret;
+ return 0;
- commit_list_insert(in->item, &ret);
+ commit_list_insert(in->item, result);
for (i = in->next; i; i = i->next) {
struct commit_list *new_commits = NULL, *end = NULL;
- for (j = ret; j; j = j->next) {
- struct commit_list *bases;
- bases = repo_get_merge_bases(the_repository, i->item,
- j->item);
+ for (j = *result; j; j = j->next) {
+ struct commit_list *bases = NULL;
+ if (repo_get_merge_bases(the_repository, i->item,
+ j->item, &bases) < 0) {
+ free_commit_list(bases);
+ free_commit_list(*result);
+ *result = NULL;
+ return -1;
+ }
if (!new_commits)
new_commits = bases;
else
for (k = bases; k; k = k->next)
end = k;
}
- free_commit_list(ret);
- ret = new_commits;
+ free_commit_list(*result);
+ *result = new_commits;
}
- return ret;
+ return 0;
}
static int remove_redundant_no_gen(struct repository *r,
for (i = 0; i < cnt; i++)
repo_parse_commit(r, array[i]);
for (i = 0; i < cnt; i++) {
- struct commit_list *common;
+ struct commit_list *common = NULL;
timestamp_t min_generation = commit_graph_generation(array[i]);
if (redundant[i])
if (curr_generation < min_generation)
min_generation = curr_generation;
}
- common = paint_down_to_common(r, array[i], filled,
- work, min_generation);
+ if (paint_down_to_common(r, array[i], filled,
+ work, min_generation, 0, &common)) {
+ clear_commit_marks(array[i], all_flags);
+ clear_commit_marks_many(filled, work, all_flags);
+ free_commit_list(common);
+ free(work);
+ free(redundant);
+ free(filled_index);
+ return -1;
+ }
if (array[i]->object.flags & PARENT2)
redundant[i] = 1;
for (j = 0; j < filled; j++)
return remove_redundant_no_gen(r, array, cnt);
}
-static struct commit_list *get_merge_bases_many_0(struct repository *r,
- struct commit *one,
- int n,
- struct commit **twos,
- int cleanup)
+static int get_merge_bases_many_0(struct repository *r,
+ struct commit *one,
+ int n,
+ struct commit **twos,
+ int cleanup,
+ struct commit_list **result)
{
struct commit_list *list;
struct commit **rslt;
- struct commit_list *result;
int cnt, i;
- result = merge_bases_many(r, one, n, twos);
+ if (merge_bases_many(r, one, n, twos, result) < 0)
+ return -1;
for (i = 0; i < n; i++) {
if (one == twos[i])
- return result;
+ return 0;
}
- if (!result || !result->next) {
+ if (!*result || !(*result)->next) {
if (cleanup) {
clear_commit_marks(one, all_flags);
clear_commit_marks_many(n, twos, all_flags);
}
- return result;
+ return 0;
}
/* There are more than one */
- cnt = commit_list_count(result);
+ cnt = commit_list_count(*result);
CALLOC_ARRAY(rslt, cnt);
- for (list = result, i = 0; list; list = list->next)
+ for (list = *result, i = 0; list; list = list->next)
rslt[i++] = list->item;
- free_commit_list(result);
+ free_commit_list(*result);
+ *result = NULL;
clear_commit_marks(one, all_flags);
clear_commit_marks_many(n, twos, all_flags);
cnt = remove_redundant(r, rslt, cnt);
- result = NULL;
+ if (cnt < 0) {
+ free(rslt);
+ return -1;
+ }
for (i = 0; i < cnt; i++)
- commit_list_insert_by_date(rslt[i], &result);
+ commit_list_insert_by_date(rslt[i], result);
free(rslt);
- return result;
+ return 0;
}
-struct commit_list *repo_get_merge_bases_many(struct repository *r,
- struct commit *one,
- int n,
- struct commit **twos)
+int repo_get_merge_bases_many(struct repository *r,
+ struct commit *one,
+ int n,
+ struct commit **twos,
+ struct commit_list **result)
{
- return get_merge_bases_many_0(r, one, n, twos, 1);
+ return get_merge_bases_many_0(r, one, n, twos, 1, result);
}
-struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
- struct commit *one,
- int n,
- struct commit **twos)
+int repo_get_merge_bases_many_dirty(struct repository *r,
+ struct commit *one,
+ int n,
+ struct commit **twos,
+ struct commit_list **result)
{
- return get_merge_bases_many_0(r, one, n, twos, 0);
+ return get_merge_bases_many_0(r, one, n, twos, 0, result);
}
-struct commit_list *repo_get_merge_bases(struct repository *r,
- struct commit *one,
- struct commit *two)
+int repo_get_merge_bases(struct repository *r,
+ struct commit *one,
+ struct commit *two,
+ struct commit_list **result)
{
- return get_merge_bases_many_0(r, one, 1, &two, 1);
+ return get_merge_bases_many_0(r, one, 1, &two, 1, result);
}
/*
} else {
while (with_commit) {
struct commit *other;
+ int ret;
other = with_commit->item;
with_commit = with_commit->next;
- if (repo_in_merge_bases_many(r, other, 1, &commit))
- return 1;
+ ret = repo_in_merge_bases_many(r, other, 1, &commit, 0);
+ if (ret)
+ return ret;
}
return 0;
}
* Is "commit" an ancestor of one of the "references"?
*/
int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
- int nr_reference, struct commit **reference)
+ int nr_reference, struct commit **reference,
+ int ignore_missing_commits)
{
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
int ret = 0, i;
timestamp_t generation, max_generation = GENERATION_NUMBER_ZERO;
if (repo_parse_commit(r, commit))
- return ret;
+ return ignore_missing_commits ? 0 : -1;
for (i = 0; i < nr_reference; i++) {
if (repo_parse_commit(r, reference[i]))
- return ret;
+ return ignore_missing_commits ? 0 : -1;
generation = commit_graph_generation(reference[i]);
if (generation > max_generation)
if (generation > max_generation)
return ret;
- bases = paint_down_to_common(r, commit,
- nr_reference, reference,
- generation);
- if (commit->object.flags & PARENT2)
+ if (paint_down_to_common(r, commit,
+ nr_reference, reference,
+ generation, ignore_missing_commits, &bases))
+ ret = -1;
+ else if (commit->object.flags & PARENT2)
ret = 1;
clear_commit_marks(commit, all_flags);
clear_commit_marks_many(nr_reference, reference, all_flags);
}
}
num_head = remove_redundant(the_repository, array, num_head);
+ if (num_head < 0) {
+ free(array);
+ return NULL;
+ }
for (i = 0; i < num_head; i++)
tail = &commit_list_insert(array[i], tail)->next;
free(array);
commit_list_insert(old_commit, &old_commit_list);
ret = repo_is_descendant_of(the_repository,
new_commit, old_commit_list);
+ if (ret < 0)
+ exit(128);
free_commit_list(old_commit_list);
return ret;
}
struct object_id;
struct object_array;
-struct commit_list *repo_get_merge_bases(struct repository *r,
- struct commit *rev1,
- struct commit *rev2);
-struct commit_list *repo_get_merge_bases_many(struct repository *r,
- struct commit *one, int n,
- struct commit **twos);
+int repo_get_merge_bases(struct repository *r,
+ struct commit *rev1,
+ struct commit *rev2,
+ struct commit_list **result);
+int repo_get_merge_bases_many(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ struct commit_list **result);
/* To be used only when object flags after this call no longer matter */
-struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
- struct commit *one, int n,
- struct commit **twos);
+int repo_get_merge_bases_many_dirty(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ struct commit_list **result);
-struct commit_list *get_octopus_merge_bases(struct commit_list *in);
+int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result);
int repo_is_descendant_of(struct repository *r,
struct commit *commit,
struct commit *reference);
int repo_in_merge_bases_many(struct repository *r,
struct commit *commit,
- int nr_reference, struct commit **reference);
+ int nr_reference, struct commit **reference,
+ int ignore_missing_commits);
/*
* Takes a list of commits and returns a new list where those
{
struct object_id oid;
struct rev_collect revs;
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
int i;
struct commit *ret = NULL;
char *full_refname;
for (i = 0; i < revs.nr; i++)
revs.commit[i]->object.flags &= ~TMP_MARK;
- bases = repo_get_merge_bases_many(the_repository, commit, revs.nr,
- revs.commit);
+ if (repo_get_merge_bases_many(the_repository, commit, revs.nr,
+ revs.commit, &bases) < 0)
+ exit(128);
/*
* There should be one and only one merge base, when we found
#ifndef COMPILER_H
#define COMPILER_H
-#include "git-compat-util.h"
#include "strbuf.h"
#ifdef __GLIBC__
#ifndef COMPAT_DISK_H
#define COMPAT_DISK_H
-#include "git-compat-util.h"
#include "abspath.h"
#include "gettext.h"
--- /dev/null
+@@
+expression S, T, L;
+@@
+(
+- strncmp(S, T, L) || S[L]
++ !!xstrncmpz(S, T, L)
+|
+- strncmp(S, T, L) || S[L] != '\0'
++ !!xstrncmpz(S, T, L)
+|
+- strncmp(S, T, L) || T[L]
++ !!xstrncmpz(T, S, L)
+|
+- strncmp(S, T, L) || T[L] != '\0'
++ !!xstrncmpz(T, S, L)
+|
+- !strncmp(S, T, L) && !S[L]
++ !xstrncmpz(S, T, L)
+|
+- !strncmp(S, T, L) && S[L] == '\0'
++ !xstrncmpz(S, T, L)
+|
+- !strncmp(S, T, L) && !T[L]
++ !xstrncmpz(T, S, L)
+|
+- !strncmp(S, T, L) && T[L] == '\0'
++ !xstrncmpz(T, S, L)
+)
__git_config_vars="$(git help --config-for-completion)"
}
+__git_config_vars_all=
+__git_compute_config_vars_all ()
+{
+ test -n "$__git_config_vars_all" ||
+ __git_config_vars_all="$(git --no-pager help --config)"
+}
+
+__git_compute_first_level_config_vars_for_section ()
+{
+ local section="$1"
+ __git_compute_config_vars
+ local this_section="__git_first_level_config_vars_for_section_${section}"
+ test -n "${!this_section}" ||
+ printf -v "__git_first_level_config_vars_for_section_${section}" %s \
+ "$(echo "$__git_config_vars" | awk -F. "/^${section}\.[a-z]/ { print \$2 }")"
+}
+
+__git_compute_second_level_config_vars_for_section ()
+{
+ local section="$1"
+ __git_compute_config_vars_all
+ local this_section="__git_second_level_config_vars_for_section_${section}"
+ test -n "${!this_section}" ||
+ printf -v "__git_second_level_config_vars_for_section_${section}" %s \
+ "$(echo "$__git_config_vars_all" | awk -F. "/^${section}\.</ { print \$3 }")"
+}
+
__git_config_sections=
__git_compute_config_sections ()
{
done
case "$cur_" in
- branch.*.*)
+ branch.*.*|guitool.*.*|difftool.*.*|man.*.*|mergetool.*.*|remote.*.*|submodule.*.*|url.*.*)
local pfx="${cur_%.*}."
cur_="${cur_##*.}"
- __gitcomp "remote pushRemote merge mergeOptions rebase" "$pfx" "$cur_" "$sfx"
+ local section="${pfx%.*.}"
+ __git_compute_second_level_config_vars_for_section "${section}"
+ local this_section="__git_second_level_config_vars_for_section_${section}"
+ __gitcomp "${!this_section}" "$pfx" "$cur_" "$sfx"
return
;;
branch.*)
local pfx="${cur_%.*}."
cur_="${cur_#*.}"
+ local section="${pfx%.}"
__gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
- __gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_" "${sfx- }"
- return
- ;;
- guitool.*.*)
- local pfx="${cur_%.*}."
- cur_="${cur_##*.}"
- __gitcomp "
- argPrompt cmd confirm needsFile noConsole noRescan
- prompt revPrompt revUnmerged title
- " "$pfx" "$cur_" "$sfx"
- return
- ;;
- difftool.*.*)
- local pfx="${cur_%.*}."
- cur_="${cur_##*.}"
- __gitcomp "cmd path" "$pfx" "$cur_" "$sfx"
- return
- ;;
- man.*.*)
- local pfx="${cur_%.*}."
- cur_="${cur_##*.}"
- __gitcomp "cmd path" "$pfx" "$cur_" "$sfx"
- return
- ;;
- mergetool.*.*)
- local pfx="${cur_%.*}."
- cur_="${cur_##*.}"
- __gitcomp "cmd path trustExitCode" "$pfx" "$cur_" "$sfx"
+ __git_compute_first_level_config_vars_for_section "${section}"
+ local this_section="__git_first_level_config_vars_for_section_${section}"
+ __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }"
return
;;
pager.*)
local pfx="${cur_%.*}."
cur_="${cur_#*.}"
__git_compute_all_commands
- __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" "${sfx- }"
- return
- ;;
- remote.*.*)
- local pfx="${cur_%.*}."
- cur_="${cur_##*.}"
- __gitcomp "
- url proxy fetch push mirror skipDefaultUpdate
- receivepack uploadpack tagOpt pushurl
- " "$pfx" "$cur_" "$sfx"
+ __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" "${sfx:- }"
return
;;
remote.*)
local pfx="${cur_%.*}."
cur_="${cur_#*.}"
+ local section="${pfx%.}"
__gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
- __gitcomp_nl_append "pushDefault" "$pfx" "$cur_" "${sfx- }"
+ __git_compute_first_level_config_vars_for_section "${section}"
+ local this_section="__git_first_level_config_vars_for_section_${section}"
+ __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }"
return
;;
- url.*.*)
+ submodule.*)
local pfx="${cur_%.*}."
- cur_="${cur_##*.}"
- __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_" "$sfx"
+ cur_="${cur_#*.}"
+ local section="${pfx%.}"
+ __gitcomp_nl "$(__git config -f "$(__git rev-parse --show-toplevel)/.gitmodules" --get-regexp 'submodule.*.path' | awk -F. '{print $2}')" "$pfx" "$cur_" "."
+ __git_compute_first_level_config_vars_for_section "${section}"
+ local this_section="__git_first_level_config_vars_for_section_${section}"
+ __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }"
return
;;
*.*)
if (g_strv_length(parts) >= 1) {
g_free(c->password);
c->password = g_strdup(parts[0]);
+ } else {
+ g_free(c->password);
+ c->password = g_strdup("");
}
for (int i = 1; i < g_strv_length(parts); i++) {
if (g_str_has_prefix(parts[i], "password_expiry_utc=")) {
# create the links to the original repo. explicitly exclude index, HEAD and
# logs/HEAD from the list since they are purely related to the current working
# directory, and should not be shared.
-for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn
+for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache svn reftable
do
# create a containing directory if needed
case $x in
if (parse_config_key(var, "filter", &name, &namelen, &key) < 0 || !name)
return 0;
for (drv = user_convert; drv; drv = drv->next)
- if (!strncmp(drv->name, name, namelen) && !drv->name[namelen])
+ if (!xstrncmpz(drv->name, name, namelen))
break;
if (!drv) {
CALLOC_ARRAY(drv, 1);
{
int i;
struct commit *mb_child[2] = {0};
- struct commit_list *merge_bases;
+ struct commit_list *merge_bases = NULL;
for (i = 0; i < revs->pending.nr; i++) {
struct object *obj = revs->pending.objects[i].item;
mb_child[1] = lookup_commit_reference(the_repository, &oid);
}
- merge_bases = repo_get_merge_bases(the_repository, mb_child[0], mb_child[1]);
+ if (repo_get_merge_bases(the_repository, mb_child[0], mb_child[1], &merge_bases) < 0)
+ exit(128);
if (!merge_bases)
die(_("no merge base found"));
if (merge_bases->next)
OPT_BITOP(0, "shortstat", &options->output_format,
N_("output only the last line of --stat"),
DIFF_FORMAT_SHORTSTAT, DIFF_FORMAT_NO_OUTPUT),
- OPT_CALLBACK_F('X', "dirstat", options, N_("<param1,param2>..."),
+ OPT_CALLBACK_F('X', "dirstat", options, N_("<param1>,<param2>..."),
N_("output the distribution of relative amount of changes for each sub-directory"),
PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
diff_opt_dirstat),
N_("synonym for --dirstat=cumulative"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG,
diff_opt_dirstat),
- OPT_CALLBACK_F(0, "dirstat-by-file", options, N_("<param1,param2>..."),
- N_("synonym for --dirstat=files,param1,param2..."),
+ OPT_CALLBACK_F(0, "dirstat-by-file", options, N_("<param1>,<param2>..."),
+ N_("synonym for --dirstat=files,<param1>,<param2>..."),
PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
diff_opt_dirstat),
OPT_BIT_F(0, "check", &options->output_format,
#include "dir.h"
#include "iterator.h"
#include "dir-iterator.h"
+#include "string-list.h"
struct dir_iterator_level {
DIR *dir;
+ /*
+ * The directory entries of the current level. This list will only be
+ * populated when the iterator is ordered. In that case, `dir` will be
+ * set to `NULL`.
+ */
+ struct string_list entries;
+ size_t entries_idx;
+
/*
* The length of the directory part of path at this level
* (including a trailing '/'):
unsigned int flags;
};
+static int next_directory_entry(DIR *dir, const char *path,
+ struct dirent **out)
+{
+ struct dirent *de;
+
+repeat:
+ errno = 0;
+ de = readdir(dir);
+ if (!de) {
+ if (errno) {
+ warning_errno("error reading directory '%s'",
+ path);
+ return -1;
+ }
+
+ return 1;
+ }
+
+ if (is_dot_or_dotdot(de->d_name))
+ goto repeat;
+
+ *out = de;
+ return 0;
+}
+
/*
* Push a level in the iter stack and initialize it with information from
* the directory pointed by iter->base->path. It is assumed that this
return -1;
}
+ string_list_init_dup(&level->entries);
+ level->entries_idx = 0;
+
+ /*
+ * When the iterator is sorted we read and sort all directory entries
+ * directly.
+ */
+ if (iter->flags & DIR_ITERATOR_SORTED) {
+ struct dirent *de;
+
+ while (1) {
+ int ret = next_directory_entry(level->dir, iter->base.path.buf, &de);
+ if (ret < 0) {
+ if (errno != ENOENT &&
+ iter->flags & DIR_ITERATOR_PEDANTIC)
+ return -1;
+ continue;
+ } else if (ret > 0) {
+ break;
+ }
+
+ string_list_append(&level->entries, de->d_name);
+ }
+ string_list_sort(&level->entries);
+
+ closedir(level->dir);
+ level->dir = NULL;
+ }
+
return 0;
}
warning_errno("error closing directory '%s'",
iter->base.path.buf);
level->dir = NULL;
+ string_list_clear(&level->entries, 0);
return --iter->levels_nr;
}
/*
* Populate iter->base with the necessary information on the next iteration
- * entry, represented by the given dirent de. Return 0 on success and -1
+ * entry, represented by the given name. Return 0 on success and -1
* otherwise, setting errno accordingly.
*/
static int prepare_next_entry_data(struct dir_iterator_int *iter,
- struct dirent *de)
+ const char *name)
{
int err, saved_errno;
- strbuf_addstr(&iter->base.path, de->d_name);
+ strbuf_addstr(&iter->base.path, name);
/*
* We have to reset these because the path strbuf might have
* been realloc()ed at the previous strbuf_addstr().
struct dirent *de;
struct dir_iterator_level *level =
&iter->levels[iter->levels_nr - 1];
+ const char *name;
strbuf_setlen(&iter->base.path, level->prefix_len);
- errno = 0;
- de = readdir(level->dir);
- if (!de) {
- if (errno) {
- warning_errno("error reading directory '%s'",
- iter->base.path.buf);
+ if (level->dir) {
+ int ret = next_directory_entry(level->dir, iter->base.path.buf, &de);
+ if (ret < 0) {
if (iter->flags & DIR_ITERATOR_PEDANTIC)
goto error_out;
- } else if (pop_level(iter) == 0) {
- return dir_iterator_abort(dir_iterator);
+ continue;
+ } else if (ret > 0) {
+ if (pop_level(iter) == 0)
+ return dir_iterator_abort(dir_iterator);
+ continue;
}
- continue;
- }
- if (is_dot_or_dotdot(de->d_name))
- continue;
+ name = de->d_name;
+ } else {
+ if (level->entries_idx >= level->entries.nr) {
+ if (pop_level(iter) == 0)
+ return dir_iterator_abort(dir_iterator);
+ continue;
+ }
- if (prepare_next_entry_data(iter, de)) {
+ name = level->entries.items[level->entries_idx++].string;
+ }
+
+ if (prepare_next_entry_data(iter, name)) {
if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC)
goto error_out;
continue;
warning_errno("error closing directory '%s'",
iter->base.path.buf);
}
+
+ string_list_clear(&level->entries, 0);
}
free(iter->levels);
* and ITER_ERROR is returned immediately. In both cases, a meaningful
* warning is emitted. Note: ENOENT errors are always ignored so that
* the API users may remove files during iteration.
+ *
+ * - DIR_ITERATOR_SORTED: sort directory entries alphabetically.
*/
#define DIR_ITERATOR_PEDANTIC (1 << 0)
+#define DIR_ITERATOR_SORTED (1 << 1)
struct dir_iterator {
/* The current path: */
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
if (shallow_file)
set_alternate_shallow_file(the_repository, shallow_file, 0);
+
+ if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
+ fetch_if_missing = 0;
}
int is_bare_repository(void)
#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
#define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
+#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
#define GITATTRIBUTES_FILE ".gitattributes"
#define INFOATTRIBUTES_FILE "info/attributes"
#define ATTRIBUTE_MACRO_PREFIX "[attr]"
# ignore the error from the above --- run_merge_tool
# will diagnose unusable tool by itself
run_merge_tool "$merge_tool" false
+
+ status=$?
+ if test $status -ge 126
+ then
+ # Command not found (127), not executable (126) or
+ # exited via a signal (>= 128).
+ exit $status
+ fi
+
+ if test "$GIT_DIFFTOOL_TRUST_EXIT_CODE" = true
+ then
+ exit $status
+ fi
else
# Launch the merge tool on each path provided by 'git diff'
while test $# -gt 6
#include "exec-cmd.h"
#include "gettext.h"
#include "help.h"
+#include "object-file.h"
#include "pager.h"
#include "read-cache-ll.h"
#include "run-command.h"
use_pager = 0;
if (envchanged)
*envchanged = 1;
+ } else if (!strcmp(cmd, "--no-lazy-fetch")) {
+ fetch_if_missing = 0;
+ setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1);
+ if (envchanged)
+ *envchanged = 1;
} else if (!strcmp(cmd, "--no-replace-objects")) {
disable_replace_refs();
setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
struct commit *head = lookup_commit_or_die(head_oid, "HEAD");
struct commit *branch = lookup_commit_or_die(&remote->old_oid,
remote->name);
+ int ret = repo_in_merge_bases(the_repository, branch, head);
- return repo_in_merge_bases(the_repository, branch, head);
+ if (ret < 0)
+ exit(128);
+ return ret;
}
static int delete_remote_branch(const char *pattern, int force)
free(d);
}
-static void add_all(struct oidset *dest, struct oidset *src) {
- struct oidset_iter iter;
- struct object_id *src_oid;
-
- oidset_iter_init(src, &iter);
- while ((src_oid = oidset_iter_next(&iter)) != NULL)
- oidset_insert(dest, src_oid);
-}
-
static void filter_combine__finalize_omits(
struct oidset *omits,
void *filter_data)
size_t sub;
for (sub = 0; sub < d->nr; sub++) {
- add_all(omits, &d->sub[sub].omits);
+ oidset_insert_from_set(omits, &d->sub[sub].omits);
oidset_clear(&d->sub[sub].omits);
}
}
struct object_id *oid)
{
struct merge_options o;
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
struct merge_result res = {0};
struct pretty_print_context ctx = {0};
struct commit *parent1 = parents->item;
/* Parse the relevant commits and get the merge bases */
parse_commit_or_die(parent1);
parse_commit_or_die(parent2);
- bases = repo_get_merge_bases(the_repository, parent1, parent2);
+ if (repo_get_merge_bases(the_repository, parent1, parent2, &bases) < 0)
+ exit(128);
/* Re-merge the parents */
merge_incore_recursive(&o, bases, parent1, parent2, &res);
return r;
}
+static char *mem_pool_strvfmt(struct mem_pool *pool, const char *fmt,
+ va_list ap)
+{
+ struct mp_block *block = pool->mp_block;
+ char *next_free = block ? block->next_free : NULL;
+ size_t available = block ? block->end - block->next_free : 0;
+ va_list cp;
+ int len, len2;
+ char *ret;
+
+ va_copy(cp, ap);
+ len = vsnprintf(next_free, available, fmt, cp);
+ va_end(cp);
+ if (len < 0)
+ BUG("your vsnprintf is broken (returned %d)", len);
+
+ ret = mem_pool_alloc(pool, len + 1); /* 1 for NUL */
+
+ /* Shortcut; relies on mem_pool_alloc() not touching buffer contents. */
+ if (ret == next_free)
+ return ret;
+
+ len2 = vsnprintf(ret, len + 1, fmt, ap);
+ if (len2 != len)
+ BUG("your vsnprintf is broken (returns inconsistent lengths)");
+ return ret;
+}
+
+char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = mem_pool_strvfmt(pool, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size)
{
size_t len = st_mult(count, size);
char *mem_pool_strdup(struct mem_pool *pool, const char *str);
char *mem_pool_strndup(struct mem_pool *pool, const char *str, size_t len);
+/*
+ * Allocate memory from the memory pool and format a string into it.
+ */
+char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...);
+
/*
* Move the memory associated with the 'src' pool to the 'dst' pool. The 'src'
* pool will be empty and not contain any memory. It still needs to be free'd
* after seeing merge.<name>.var1.
*/
for (fn = ll_user_merge; fn; fn = fn->next)
- if (!strncmp(fn->name, name, namelen) && !fn->name[namelen])
+ if (!xstrncmpz(fn->name, name, namelen))
break;
if (!fn) {
CALLOC_ARRAY(fn, 1);
#include "merge-ort.h"
#include "alloc.h"
+#include "advice.h"
#include "attr.h"
#include "cache-tree.h"
#include "commit.h"
CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE,
CONFLICT_SUBMODULE_MAY_HAVE_REWINDS,
CONFLICT_SUBMODULE_NULL_MERGE_BASE,
+ CONFLICT_SUBMODULE_CORRUPT,
/* Keep this entry _last_ in the list */
NB_CONFLICT_TYPES,
[CONFLICT_SUBMODULE_MAY_HAVE_REWINDS] =
"CONFLICT (submodule may have rewinds)",
[CONFLICT_SUBMODULE_NULL_MERGE_BASE] =
- "CONFLICT (submodule lacks merge base)"
+ "CONFLICT (submodule lacks merge base)",
+ [CONFLICT_SUBMODULE_CORRUPT] =
+ "CONFLICT (submodule corrupt)"
};
struct logical_conflict_info {
info.data = opt;
info.show_all_errors = 1;
- parse_tree(merge_base);
- parse_tree(side1);
- parse_tree(side2);
+ if (parse_tree(merge_base) < 0 ||
+ parse_tree(side1) < 0 ||
+ parse_tree(side2) < 0)
+ return -1;
init_tree_desc(t + 0, merge_base->buffer, merge_base->size);
init_tree_desc(t + 1, side1->buffer, side1->size);
init_tree_desc(t + 2, side2->buffer, side2->size);
die("revision walk setup failed");
while ((commit = get_revision(&revs)) != NULL) {
struct object *o = &(commit->object);
- if (repo_in_merge_bases(repo, b, commit))
+ int ret = repo_in_merge_bases(repo, b, commit);
+
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret > 0)
add_object_array(o, NULL, &merges);
}
reset_revision_walk();
contains_another = 0;
for (j = 0; j < merges.nr; j++) {
struct commit *m2 = (struct commit *) merges.objects[j].item;
- if (i != j && repo_in_merge_bases(repo, m2, m1)) {
- contains_another = 1;
- break;
+ if (i != j) {
+ int ret = repo_in_merge_bases(repo, m2, m1);
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret > 0) {
+ contains_another = 1;
+ break;
+ }
}
}
{
struct repository subrepo;
struct strbuf sb = STRBUF_INIT;
- int ret = 0;
+ int ret = 0, ret2;
struct commit *commit_o, *commit_a, *commit_b;
int parent_count;
struct object_array merges;
}
/* check whether both changes are forward */
- if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) ||
- !repo_in_merge_bases(&subrepo, commit_o, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_a);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (ret2 > 0)
+ ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_b);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (!ret2) {
path_msg(opt, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, 0,
path, NULL, NULL, NULL,
_("Failed to merge submodule %s "
}
/* Case #1: a is contained in b or vice versa */
- if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (ret2 > 0) {
oidcpy(result, b);
path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
path, NULL, NULL, NULL,
ret = 1;
goto cleanup;
}
- if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (ret2 > 0) {
oidcpy(result, a);
path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
path, NULL, NULL, NULL,
parent_count = find_first_merges(&subrepo, path, commit_a, commit_b,
&merges);
switch (parent_count) {
+ case -1:
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ ret = -1;
+ break;
case 0:
path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE, 0,
path, NULL, NULL, NULL,
unpack_opts.verbose_update = (opt->verbosity > 2);
unpack_opts.fn = twoway_merge;
unpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */
- parse_tree(prev);
+ if (parse_tree(prev) < 0)
+ return -1;
init_tree_desc(&trees[0], prev->buffer, prev->size);
- parse_tree(next);
+ if (parse_tree(next) < 0)
+ return -1;
init_tree_desc(&trees[1], next->buffer, next->size);
ret = unpack_trees(2, trees, &unpack_opts);
" - commit the resulting index in the superproject\n"),
tmp.buf, subs.buf);
- printf("%s", msg.buf);
+ advise_if_enabled(ADVICE_SUBMODULE_MERGE_CONFLICT, "%s", msg.buf);
strbuf_release(&subs);
strbuf_release(&tmp);
if (result->clean >= 0) {
result->tree = parse_tree_indirect(&working_tree_oid);
+ if (!result->tree)
+ die(_("unable to read tree (%s)"),
+ oid_to_hex(&working_tree_oid));
/* existence of conflicted entries implies unclean */
result->clean &= strmap_empty(&opt->priv->conflicted);
}
struct strbuf merge_base_abbrev = STRBUF_INIT;
if (!merge_bases) {
- merge_bases = repo_get_merge_bases(the_repository, h1, h2);
+ if (repo_get_merge_bases(the_repository, h1, h2,
+ &merge_bases) < 0) {
+ result->clean = -1;
+ return;
+ }
/* See merge-ort.h:merge_incore_recursive() declaration NOTE */
merge_bases = reverse_commit_list(merge_bases);
}
static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
{
- parse_tree(tree);
+ if (parse_tree(tree) < 0)
+ exit(128);
init_tree_desc(desc, tree->buffer, tree->size);
}
die("revision walk setup failed");
while ((commit = get_revision(&revs)) != NULL) {
struct object *o = &(commit->object);
- if (repo_in_merge_bases(repo, b, commit))
+ int ret = repo_in_merge_bases(repo, b, commit);
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret)
add_object_array(o, NULL, &merges);
}
reset_revision_walk();
contains_another = 0;
for (j = 0; j < merges.nr; j++) {
struct commit *m2 = (struct commit *) merges.objects[j].item;
- if (i != j && repo_in_merge_bases(repo, m2, m1)) {
- contains_another = 1;
- break;
+ if (i != j) {
+ int ret = repo_in_merge_bases(repo, m2, m1);
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret > 0) {
+ contains_another = 1;
+ break;
+ }
}
}
const struct object_id *b)
{
struct repository subrepo;
- int ret = 0;
+ int ret = 0, ret2;
struct commit *commit_base, *commit_a, *commit_b;
int parent_count;
struct object_array merges;
}
/* check whether both changes are forward */
- if (!repo_in_merge_bases(&subrepo, commit_base, commit_a) ||
- !repo_in_merge_bases(&subrepo, commit_base, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_a);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (ret2 > 0)
+ ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_b);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (!ret2) {
output(opt, 1, _("Failed to merge submodule %s (commits don't follow merge-base)"), path);
goto cleanup;
}
/* Case #1: a is contained in b or vice versa */
- if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (ret2) {
oidcpy(result, b);
if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
ret = 1;
goto cleanup;
}
- if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ ret = -1;
+ goto cleanup;
+ }
+ if (ret2) {
oidcpy(result, a);
if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
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;
/* FIXME: bug, what if modes didn't match? */
result->clean = (merge_status == 0);
} else if (S_ISGITLINK(a->mode)) {
- result->clean = merge_submodule(opt, &result->blob.oid,
- o->path,
- &o->oid,
- &a->oid,
- &b->oid);
+ int clean = merge_submodule(opt, &result->blob.oid,
+ o->path,
+ &o->oid,
+ &a->oid,
+ &b->oid);
+ if (clean < 0)
+ return -1;
+ result->clean = clean;
} else if (S_ISLNK(a->mode)) {
switch (opt->recursive_variant) {
case MERGE_VARIANT_NORMAL:
}
if (!merge_bases) {
- merge_bases = repo_get_merge_bases(the_repository, h1, h2);
+ if (repo_get_merge_bases(the_repository, h1, h2,
+ &merge_bases) < 0)
+ return -1;
merge_bases = reverse_commit_list(merge_bases);
}
return -1;
}
for (i = 0; i < nr_trees; i++) {
- parse_tree(trees[i]);
+ if (parse_tree(trees[i]) < 0) {
+ rollback_lock_file(&lock_file);
+ return -1;
+ }
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
}
merge_cmd () {
- layout=$(git config mergetool.vimdiff.layout)
+ TOOL=$1
- case "$1" in
+ layout=$(git config "mergetool.$TOOL.layout")
+
+ # backward compatibility:
+ if test -z "$layout"
+ then
+ layout=$(git config mergetool.vimdiff.layout)
+ fi
+
+ case "$TOOL" in
*vimdiff)
if test -z "$layout"
then
assert(local && remote);
/* Find merge bases */
- bases = repo_get_merge_bases(the_repository, local, remote);
+ if (repo_get_merge_bases(the_repository, local, remote, &bases) < 0)
+ exit(128);
if (!bases) {
base_oid = null_oid();
base_tree_oid = the_hash_algo->empty_tree;
len, str,
show_date(co_time, co_tz, DATE_MODE(RFC2822)));
}
+ } else if (nth == co_cnt && !is_null_oid(oid)) {
+ /*
+ * We were asked for the Nth reflog (counting
+ * from 0), but there were only N entries.
+ * read_ref_at() will have returned "1" to tell
+ * us it did not find an entry, but it did
+ * still fill in the oid with the "old" value,
+ * which we can use.
+ */
} else {
if (flags & GET_OID_QUIETLY) {
exit(128);
struct object_id *oid)
{
struct commit *one, *two;
- struct commit_list *mbs;
+ struct commit_list *mbs = NULL;
struct object_id oid_tmp;
const char *dots;
int st;
two = lookup_commit_reference_gently(r, &oid_tmp, 0);
if (!two)
return -1;
- mbs = repo_get_merge_bases(r, one, two);
+ if (repo_get_merge_bases(r, one, two, &mbs) < 0) {
+ free_commit_list(mbs);
+ return -1;
+ }
if (!mbs || mbs->next)
st = -1;
else {
len = strlen(str);
for (i = 1; i < ARRAY_SIZE(object_type_strings); i++)
- if (!strncmp(str, object_type_strings[i], len) &&
- object_type_strings[i][len] == '\0')
+ if (!xstrncmpz(object_type_strings[i], str, len))
return i;
if (gentle)
enum parse_object_flags flags)
{
int skip_hash = !!(flags & PARSE_OBJECT_SKIP_HASH_CHECK);
+ int discard_tree = !!(flags & PARSE_OBJECT_DISCARD_TREE);
unsigned long size;
enum object_type type;
int eaten;
return lookup_object(r, oid);
}
+ /*
+ * If the caller does not care about the tree buffer and does not
+ * care about checking the hash, we can simply verify that we
+ * have the on-disk object with the correct type.
+ */
+ if (skip_hash && discard_tree &&
+ (!obj || obj->type == OBJ_TREE) &&
+ oid_object_info(r, oid, NULL) == OBJ_TREE) {
+ return &lookup_tree(r, oid)->object;
+ }
+
buffer = repo_read_object_file(r, oid, &type, &size);
if (buffer) {
if (!skip_hash &&
buffer, &eaten);
if (!eaten)
free(buffer);
+ if (discard_tree && type == OBJ_TREE)
+ free_tree_buffer((struct tree *)obj);
return obj;
}
return NULL;
*/
enum parse_object_flags {
PARSE_OBJECT_SKIP_HASH_CHECK = 1 << 0,
+ PARSE_OBJECT_DISCARD_TREE = 1 << 1,
};
struct object *parse_object(struct repository *r, const struct object_id *oid);
struct object *parse_object_with_flags(struct repository *r,
return !added;
}
+void oidset_insert_from_set(struct oidset *dest, struct oidset *src)
+{
+ struct oidset_iter iter;
+ struct object_id *src_oid;
+
+ oidset_iter_init(src, &iter);
+ while ((src_oid = oidset_iter_next(&iter)))
+ oidset_insert(dest, src_oid);
+}
+
int oidset_remove(struct oidset *set, const struct object_id *oid)
{
khiter_t pos = kh_get_oid_set(&set->set, *oid);
*/
int oidset_insert(struct oidset *set, const struct object_id *oid);
+/**
+ * Insert all the oids that are in set 'src' into set 'dest'; a copy
+ * is made of each oid inserted into set 'dest'.
+ */
+void oidset_insert_from_set(struct oidset *dest, struct oidset *src);
+
/**
* Remove the oid from the set.
*
return NULL;
}
-static int calc_shared_perm(int mode)
+int calc_shared_perm(int mode)
{
int tweak;
int ends_with_path_components(const char *path, const char *components);
int validate_headref(const char *ref);
+int calc_shared_perm(int mode);
int adjust_shared_perm(const char *path);
char *interpolate_path(const char *path, int real_home);
# Bulgarian translation of git po-file.
-# Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Alexander Shopov <ash@kambanaria.org>.
+# Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Alexander Shopov <ash@kambanaria.org>.
# This file is distributed under the same license as the git package.
-# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024.
# ========================
# DICTIONARY TO MERGE IN GIT GUI
# ------------------------
# midx, multi-pack index - файл с индекса за множество пакети
# overlay mode - припокриващ режим (при изтеглянe)
# incremental file нарастващ файл
+# commit-graph граф с подавания
+# commit-graph chain верига на гра̀фа с подавания
# split (commit-graphr) раздробен (граф с подавания)
# clobber (a tag) презаписвам (етикет)
# blame извеждане на авторство
# master/main branch основен клон
# unborn/orphan branch неродѐн клон (а не несъздаден) - клон без никакви подавания, включително и началното
# parse анализ, анализирам
+# reinitialize repository зануляване на хранилището и инициализиране
+# replay изпълняване/прилагане наново
+# BTMP chunk откъс за побитова маска
+# OID fanout chunk откъс за разпределянето
+# OID lookup chunk откъс за търсенето
+# autostash автоматично скатано
+# symref файл с указател (regular file that stores a string that begins with ref: refs/)
+#
+#
#
# ------------------------
# „$var“ - може да не сработва за shell има gettext и eval_gettext - проверка - намират се лесно по „$
# for i in `sort -u FILES`; do cnt=`grep $i FILES | wc -l`; echo $cnt $i ;done | sort -n
msgid ""
msgstr ""
-"Project-Id-Version: git 2.43\n"
+"Project-Id-Version: git 2.44\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-17 15:49+0100\n"
-"PO-Revision-Date: 2023-11-18 13:23+0100\n"
+"POT-Creation-Date: 2024-02-16 09:33+0100\n"
+"PO-Revision-Date: 2024-02-16 09:38+0100\n"
"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
msgid "Unexpected option --output"
msgstr "Неочаквана опция „--output“"
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "излишна опция или стойност на командния ред: „%s“"
+
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Непознат формат на архив: „%s“"
"неправилна стойност за опцията „--attr-source“ или променливата "
"„GIT_ATTR_SOURCE“"
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "„stat“ не може да се изпълни върху „%s“"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "обектът „%s“ не може да бъде прочетен"
+
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "Неправилно цитирано съдържание във файла „%s“: %s"
msgstr "обектът-подаване за „%s“ не може да се открие"
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
+msgid "the branch '%s' is not fully merged"
+msgstr "клонът „%s“ не е слят напълно"
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
msgstr ""
-"клонът „%s“ не е слят напълно. Ако сте сигурни, че искате\n"
-"да го изтриете, изпълнете:\n"
+"Ако сте сигурни, че искате да го изтриете, изпълнете:\n"
"\n"
" git branch -D %s"
#, c-format
msgid "HEAD (%s) points outside of refs/heads/"
-msgstr "„HEAD“ (%s) сочи извън директорията „refs/heads“"
+msgstr "„HEAD“ (%s) сочи извън директорията „refs/heads/“"
#, c-format
msgid "branch %s is being rebased at %s"
msgid "new-branch"
msgstr "НОВ_КЛОН"
-msgid "new unparented branch"
-msgstr "нов клон без Ñ\80одиÑ\82ел"
+msgid "new unborn branch"
+msgstr "нов неÑ\80одеÌ\80н клон"
msgid "update ignored files (default)"
msgstr "обновяване на игнорираните файлове (стандартно)"
"което изисква някоя от опциите „-i“, „-n“ или „-f“. Няма да се извърши "
"изчистване"
-msgid "-x and -X cannot be used together"
-msgstr "опциите „-x“ и „-X“ са несъвместими"
-
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [ОПЦИЯ…] [--] ХРАНИЛИЩЕ [ДИРЕКТОРИЯ]"
msgid "separate git dir from working tree"
msgstr "отделна СЛУЖЕБНА_ДИРЕКТОРИЯ за git извън работното дърво"
+msgid "specify the reference format to use"
+msgstr "указване на форма̀та за указател"
+
msgid "key=value"
msgstr "КЛЮЧ=СТОЙНОСТ"
msgid "You must specify a repository to clone."
msgstr "Трябва да укажете кое хранилище искате да клонирате."
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"опцията „--bundle-uri“ е несъвместима с „--depth“, „--shallow-since“ и „--"
-"shallow-exclude“"
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "непознат формат на съхранение: „%s“"
#, c-format
msgid "repository '%s' does not exist"
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir ДИРЕКТОРИЯ] [--append]\n"
" [--split[=СТРАТЕГИЯ]] [--reachable|--stdin-packs|--"
msgid "unable to read tree (%s)"
msgstr "дървото не може да бъде прочетено (%s)"
+#, c-format
+msgid "unable to read tree %s"
+msgstr "дървото не може да бъде прочетено: %s"
+
#, c-format
msgid "unable to grep from object of type %s"
msgstr "не може да се изпълни „grep“ от обект от вида %s"
msgstr ""
"СЪВПАДЕНИЕ НА СТОЙНОСТИТЕ ЗА СУМИТЕ ЗА SHA1: „%s“ НА ДВА РАЗЛИЧНИ ОБЕКТА!"
-#, c-format
-msgid "unable to read %s"
-msgstr "обектът „%s“ не може да бъде прочетен"
-
#, c-format
msgid "cannot read existing object info %s"
msgstr "съществуващият обект в „%s“ не може да бъде прочетен"
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 merge-file [ОПЦИЯ…] [-L ИМЕ_1 [-L ОРИГИНАЛ [-L ИМЕ_2]]] ФАЙЛ_1 ОРИГ_ФАЙЛ "
"ФАЙЛ_2"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"опцията приема следните варианти за алгоритъм за разлики: „myers“ (по "
+"Майерс), „minimal“ (минимизиране на разликите), „patience“ (пасианс) и "
+"„histogram“ (хистограмен)"
+
msgid "send results to standard output"
msgstr "извеждане на резултатите на стандартния изход"
msgid "for conflicts, use a union version"
msgstr "при конфликти да се ползва обединена версия"
+msgid "<algorithm>"
+msgstr "АЛГОРИТЪМ"
+
+msgid "choose a diff algorithm"
+msgstr "избор на АЛГОРИТЪМа за разлики"
+
msgid "for conflicts, use this marker size"
msgstr "при конфликти да се ползва маркер с такъв БРОЙ знаци"
msgid "unknown strategy option: -X%s"
msgstr "непозната опция за стратегия: -X%s"
-msgid "--merge-base is incompatible with --stdin"
-msgstr "опциите „--merge-base“ и „--stdin“ са несъвместими"
-
#, c-format
msgid "malformed input line: '%s'."
msgstr "входен ред с неправилен формат: „%s“."
msgid "add (at most <n>) entries from shortlog to merge commit message"
msgstr ""
"добавяне (на максимум такъв БРОЙ) записи от съкратения журнал в съобщението "
-"за подаване"
+"за подаване със сливане"
msgid "create a single commit instead of doing a merge"
msgstr "създаване на едно подаване вместо извършване на сливане"
msgid "inconsistency with delta count"
msgstr "неправилен брой разлики"
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr ""
+"неправилна стойност за преизползването на пакети „pack.allowPackReuse“: „%s“"
+
#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Общо: %<PRIu32> (разлики: %<PRIu32>), преизползвани: %<PRIu32> (разлики: "
-"%<PRIu32>), преизползвани при пакетиране: %<PRIu32>"
+"%<PRIu32>), преизползвани при пакетиране: %<PRIu32> (от %<PRIuMAX>)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
msgid "switch `C' expects a numerical value"
msgstr "опцията „C“ очаква число за аргумент"
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"опциите за прилагане са несъвместими с „rebase.autoSquash“. Пробвайте да "
-"добавите опцията „--no-autosquash“"
-
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"no-rebase-merges"
msgid "only one pattern can be given with -l"
msgstr "опцията „-l“ приема точно един шаблон"
+msgid "need some commits to replay"
+msgstr "необходимо е да има подавания за прилагане отново"
+
+msgid "--onto and --advance are incompatible"
+msgstr "опциите „--onto“ и „--advance“ са несъвместими"
+
+msgid "all positive revisions given must be references"
+msgstr "всички зададени положителни версии трябва да са указатели"
+
+msgid "argument to --advance must be a reference"
+msgstr "аргументът към „--advance“ трябва да е указател"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"цели с множество източници не може да се придвижат напред, защото подредбата "
+"не е добре дефинирана"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr ""
+"не може да се определи дали това действие е за „--advance“ или „--onto“"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"цели с множество клони-източници не може да се придвижат напред, защото "
+"подредбата не е добре дефинирана"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "правилната база за „--onto“ не може да се определи"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(ЕКСПЕРИМЕНТАЛНО!) git replay ([--contained] --onto НОВА_БАЗА | --advance "
+"КЛОН) ДИАПАЗОН_ПОДАВАНИЯ…"
+
+msgid "make replay advance given branch"
+msgstr "прилагането наново придвижва дадения КЛОН напред"
+
+msgid "replay onto given commit"
+msgstr "прилагането наново върху даденото ПОДАВАНЕ"
+
+msgid "advance all branches contained in revision-range"
+msgstr "придвижване на всички КЛОНи в ДИАПАЗОНа_ПОДАВАНИЯ"
+
+msgid "option --onto or --advance is mandatory"
+msgstr "изисква се някоя от опциите „--onto“ или „--advance“"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"някои опции за проследяване на указатели ще бъдат променени, защото битът "
+"„%s“ в структурата „struct rev_info“ има превес"
+
+msgid "error preparing revisions"
+msgstr "грешка при подготовката на версии"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "не се поддържа прилагане наново и на началното подаване!"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "не се поддържа прилагане наново и на подавания със сливане!"
+
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr "git rerere [clear|forget ПЪТ…|diff|status|remaining|gc]"
msgid "unknown mode for --abbrev-ref: %s"
msgstr "непознат режим за „--abbrev-ref“: „%s“"
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "опциите „--exclude-hidden“ и „--branches“ са несъвместими"
-
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "опциите „--exclude-hidden“ и „--tags“ са несъвместими"
-
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "опциите „--exclude-hidden“ и „--remotes“ са несъвместими"
-
msgid "this operation must be run in a work tree"
msgstr "тази команда трябва да се изпълни в работно дърво"
msgstr "git shortlog [ОПЦИЯ…] [ДИАПАЗОН_НА_ВЕРСИИТЕ] [[--] [ПЪТ…]]"
msgid "git log --pretty=short | git shortlog [<options>]"
-msgstr "git log --pretty=short|git shortlog [ОПЦИЯ…]"
+msgstr "git log --pretty=short | git shortlog [ОПЦИЯ…]"
msgid "using multiple --group options with stdin is not supported"
msgstr "повече от една опции „--group“ са несъвместими със стандартния вход"
"извеждане на указателите приети от стандартния вход, които липсват в "
"локалното хранилище"
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "опциите „%s“, „%s“ и „%s“ са несъвместими"
-
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
"rules) [<options>]"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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"
msgid "initializing"
msgstr "инициализация"
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "създаденото в „%s“ работно дърво липсва"
+
#, c-format
msgid "Preparing worktree (new branch '%s')"
msgstr "Приготвяне на работното дърво (нов клон „%s“)"
"доставете\n"
"обектите от отдалеченото хранилище"
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "опциите „%s“ и „%s“ са несъвместими"
-
msgid "checkout <branch> even if already checked out in other worktree"
msgstr "Изтегляне КЛОНа, дори и да е изтеглен в друго работно дърво"
msgid "create or reset a branch"
msgstr "създаване или зануляване на клони"
-msgid "create unborn/orphaned branch"
+msgid "create unborn branch"
msgstr "създаване на неродѐн клон"
msgid "populate the new working tree"
msgstr "опциите „%s“, „%s“ и „%s“ са несъвместими"
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "опциите „%s“ и „%s“ са несъвместими"
-
-msgid "<commit-ish>"
-msgstr "ПОДАВАНЕ"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "опциите „%s“ и указателите към подавания са несъвместими"
msgid "added with --lock"
msgstr "добавена с „--lock“"
msgid "Create, list, delete refs to replace objects"
msgstr "Създаване, извеждане, изтриване на указатели за замяна на обекти"
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"ЕКСПЕРИМЕНТАЛНО: прилагане на подавания върху нова база, работи и с голи "
+"хранилища"
+
msgid "Generates a summary of pending changes"
msgstr "Обобщение на предстоящите промѐни"
msgid "commit-graph file is too small"
msgstr "файлът за гра̀фа с подаванията е твърде малък"
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "откъсът за разпределянето в гра̀фа с подаванията е прекалено малък"
+
+msgid "commit-graph fanout values out of order"
+msgstr ""
+"стойностите за откъс за разпределяне в гра̀фа с подаванията не са подредени"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "откъсът за търсенето в гра̀фа с подаванията е прекалено малък"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr ""
+"откъсът за данните за подаванията в гра̀фа с подаванията е с неправилен размер"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr "откъсът за поколенията в гра̀фа с подаванията е с неправилен размер"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr ""
+"откъсът за индекса с промѐни в пътищата в гра̀фа с подаванията е прекалено "
+"малък"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"прескачане на прекалено малък откъс за индекса с промѐни (%<PRIuMAX> < "
+"%<PRIuMAX>) в пътищата в гра̀фа с подаванията"
+
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgstr "отпечатъкът на гра̀фа с подаванията %X не съвпада с %X"
msgid "commit-graph file is too small to hold %u chunks"
msgstr "файлът с гра̀фа на подаванията е твърде малък, за да съдържа %u откъси"
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr ""
+"откъсът за разпределянето необходимо на гра̀фа с подаванията липсва или е "
+"повреден"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr ""
+"откъсът за търсенето необходимо на гра̀фа с подаванията липсва или е повреден"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr ""
+"откъсът за данните необходими на гра̀фа с подаванията липсва или е повреден"
+
msgid "commit-graph has no base graphs chunk"
msgstr "базовият откъс липсва в гра̀фа с подаванията"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "броят подавания в основния граф е прекалено голям: %<PRIuMAX>"
+msgid "commit-graph chain file too small"
+msgstr "веригата на гра̀фа с подаванията е твърде малка"
+
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr ""
msgid "commit-graph requires overflow generation data but has none"
msgstr ""
-"графът с подаванията изисква генериране на данни за отместването, но такива "
-"липсват"
+"графът с подаванията изисква данни за прелелите поколения, но такива липсват"
msgid "commit-graph overflow generation data is too small"
msgstr "прекалено малко данни за прелелите поколения в гра̀фа с подаванията"
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr ""
+"указателят за допълнителните ребра в гра̀фа с подаванията е извън позволения "
+"диапазон"
+
msgid "Loading known commits in commit graph"
msgstr "Зареждане на познатите подавания в гра̀фа с подаванията"
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "Непозната стойност „%s“ за настройката „diff.submodule“"
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "непозната стойност за настройката „%s“: „%s“"
+
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "неправилен режим „%s“ за „ --color-moved-ws“"
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"опцията приема следните варианти за алгоритъм за разлики: „myers“ (по "
-"Майерс), „minimal“ (минимизиране на разликите), „patience“ (пасианс) и "
-"„histogram“ (хистограмен)"
-
#, c-format
msgid "invalid argument to %s"
msgstr "неправилен аргумент към „%s“"
msgid "output only the last line of --stat"
msgstr "извеждане само на последния ред на „--stat“"
-msgid "<param1,param2>..."
-msgstr "ПАРАМЕТЪР_1, ПАРАМЕТЪР_2, …"
+msgid "<param1>,<param2>..."
+msgstr "ПАРАМЕТЪР_1,ПАРАМЕТЪР_2,…"
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
msgid "synonym for --dirstat=cumulative"
msgstr "псевдоним на „--dirstat=cumulative“"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "псевдоним на „--dirstat=ФАЙЛ…,ПАРАМЕТЪР_1,ПАРАМЕТЪР_2,…“"
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "псевдоним на „--dirstat=files,ПАРАМЕТЪР_1,ПАРАМЕТЪР_2,…“"
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr ""
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "разлика по хистограмния алгоритъм"
-msgid "<algorithm>"
-msgstr "АЛГОРИТЪМ"
-
-msgid "choose a diff algorithm"
-msgstr "избор на АЛГОРИТЪМа за разлики"
-
msgid "<text>"
msgstr "ТЕКСТ"
msgstr ""
"неправилен размер на откъса за разпределянето в индекса за множество пакети"
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"неправилна подредба на откъси (OID fanout): fanout[%d] = %<PRIx32> > "
+"%<PRIx32> = fanout[%d]"
+
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "неправилен размер на откъса за търсенето в индекса за множество пакети"
msgstr ""
"неправилен идентификатор на пакет (pack-int-id): %u (от общо %u пакети)"
+msgid "MIDX does not contain the BTMP chunk"
+msgstr ""
+"липсва откъс за побитова маска във файла за индекса за множество пакети"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "пакетът за битови маски %<PRIu32> не може да се отвори"
+
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr ""
"индексът за множество пакети съдържа 64-битови отмествания, но размерът на "
msgid "Looking for referenced packfiles"
msgstr "Търсене на указаните пакетни файлове"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr ""
-"неправилна подредба на откъси (OID fanout): fanout[%d] = %<PRIx32> > "
-"%<PRIx32> = fanout[%d]"
-
msgid "the midx contains no oid"
msgstr "във файла с индекса за множество пакети няма идентификатори на обекти"
msgid "could not open pack %s"
msgstr "пакетът „%s“ не може да се отвори"
+msgid "could not determine MIDX preferred pack"
+msgstr ""
+"предпочитаният пакет за файла с индекса за множество пакети не може да се "
+"определи"
+
#, c-format
msgid "preferred pack (%s) is invalid"
msgstr "предпочитаният пакет „%s“ е неправилен"
"повредена битова маска във формат EWAH: отрязана заглавна част за битовата "
"маска на подаване „%s“"
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr ""
+"пакетът не може да се зареди: „%s“, преизползването на пакети се изключва"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "обектът „%s“ липсва в битовата маска на видовете"
msgstr ""
"неправилен размер на откъс за обратен индекс в индекса за множество пакети"
+msgid "could not determine preferred pack"
+msgstr "предпочитаният пакет не може да се определи"
+
msgid "cannot both write and verify reverse index"
msgstr "обратният индекс не може едновременно да се записва и да се проверява"
msgstr ""
"„%s“ очаква неотрицателно цяло число, евентуално със суфикс „k“/„m“/„g“"
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "опциите „%s“ и „%s“ са несъвместими"
-
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgstr "нееднозначна опция: „%s“ (може да е „--%s%s“ или „--%s%s“)"
msgid "unable to add '%s' to index"
msgstr "„%s“ не може да се добави в индекса"
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "„stat“ не може да се изпълни върху „%s“"
-
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgstr "„%s“ съществува и като файл, и като директория"
#, c-format
msgid "ignoring dangling symref %s"
-msgstr "игнориране на указател на обект извън клон „%s“"
+msgstr "игноÑ\80иÑ\80ане на Ñ\84айл Ñ\81 Ñ\83казаÑ\82ел на обекÑ\82 извÑ\8aн клон â\80\9e%sâ\80\9c"
#, c-format
msgid "log for ref %s has gap after %s"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "невъзможно е едновременно да се обработват „%s“ и „%s“"
-#, c-format
-msgid "could not remove reference %s"
-msgstr "Указателят „%s“ не може да бъде изтрит"
-
#, c-format
msgid "could not delete reference %s: %s"
msgstr "Указателят „%s“ не може да бъде изтрит: %s"
msgid "Autostash exists; creating a new stash entry."
msgstr "Вече има запис за автоматично скатано, затова се създава нов запис."
+msgid "autostash reference is a symref"
+msgstr "указателят за автоматично скатано e файл с указател"
+
msgid "could not detach HEAD"
msgstr "указателят „HEAD“ не може да се отдели"
msgid "invalid initial branch name: '%s'"
msgstr "неправилно име на първоначалния клон: „%s“"
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init: „--initial-branch=%s“ се пропуска"
+
#, c-format
msgid "unable to handle file type %d"
msgstr "файлове от вид %d не се поддържат"
msgid "attempt to reinitialize repository with different hash"
msgstr ""
-"опит за повторно задаване на първото подаване в хранилището с различна "
-"контролна сума"
+"опит за зануляване на хранилището и инициализиране с различна контролна сума"
+
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr ""
+"опит за зануляване на хранилището и инициализиране с различен формат на "
+"съхраняване"
#, c-format
msgid "%s already exists"
msgstr "Директорията „%s“ вече съществува"
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init: „--initial-branch=%s“ се пропуска"
-
#, c-format
msgid "Reinitialized existing shared Git repository in %s%s\n"
msgstr ""
"какъв брой записи в кеша на обектите-дървета да се отбележат като невалидни "
"(стандартно е 0)"
-msgid "unhandled options"
-msgstr "неподдържани опции"
-
-msgid "error preparing revisions"
-msgstr "грешка при подготовката на версии"
-
#, c-format
msgid "commit %s is not marked reachable"
msgstr "подаването „%s“ не е отбелязано като достижимо"
msgid "invalid remote service path"
msgstr "неправилен път на отдалечената услуга"
-msgid "operation not supported by protocol"
-msgstr "опцията не се поддържа от протокола"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "неуспешно свързване към подуслугата „%s“"
msgid "support for protocol v2 not implemented yet"
msgstr "протокол версия 2 все още не се поддържа"
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "непозната стойност за настройката „%s“: „%s“"
-
#, c-format
msgid "transport '%s' not allowed"
msgstr "преносът по „%s“ не е позволен"
"спъсъкът с адреси на пратки обявени за налични от сървъра не може да се "
"получи "
+msgid "operation not supported by protocol"
+msgstr "опцията не се поддържа от протокола"
+
msgid "too-short tree object"
msgstr "прекалено кратък обект-дърво"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "не може да извършите „%s“, защото в индекса има неподадени промѐни."
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "непознат стил „%s“ за „%s“"
+
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
# Catalan translations for Git.
# This file is distributed under the same license as the Git package.
# Alex Henrie <alexhenrie24@gmail.com>, 2014-2016.
-# Jordi Mas i Hernàndez <jmas@softcatala.org>, 2016-2023
+# Jordi Mas i Hernàndez <jmas@softcatala.org>, 2016-2024
#
# Terminologia
#
# Anglès | Català
# -----------------+---------------------------------
# blame | «blame»
+# fanout | «fanout»
# HEAD | HEAD (f, la branca actual) - (no s'apostrofa)
# cherry pick | «cherry pick»
# promisor | «promisor»
#
# Criteris
# - Mantingueu en anglès les referències a seccions de la documentació, ja que no està traduïda.
-# - Usem la convenció valenciana per a «per / per a», que inclou l'ús de «per a» davant d'infintiu
+# - Usem la convenció valenciana per a «per / per a», que inclou l'ús de «per a» davant d'infinitiu
#
msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-13 18:55+0100\n"
-"PO-Revision-Date: 2023-11-13 19:00-0600\n"
+"POT-Creation-Date: 2024-02-16 07:14+0100\n"
+"PO-Revision-Date: 2024-02-16 07:16+0100\n"
"Last-Translator: Jordi Mas i Hernàndez <jmas@softcatala.org>\n"
"Language-Team: Catalan\n"
"Language: ca\n"
#. Consider translating (saying "no" discards!) as
#. (saying "n" for "no" discards!) if the translation
#. of the word "no" does not start with n.
+#.
msgid ""
"Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
msgstr ""
msgid "Unexpected option --output"
msgstr "Opció inesperada --output"
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "paràmetre extra de la línia d'ordres «%s»"
+
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Format d'arxiu desconegut «%s»"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "--attr-source incorrecte o GIT_ATTR_SOURCE"
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "no s'ha pogut fer «stat» a «%s»"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "no s'ha pogut llegir %s"
+
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "Comentari amb cometes errònies en el fitxer «%s»: %s"
#. TRANSLATORS: the last %s will be replaced with "(roughly %d
#. steps)" translation.
+#.
#, 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"
#. 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
#. around.
+#.
#, c-format
msgid " %s\n"
msgstr " %s\n"
#. TRANSLATORS: The second argument is a \n-delimited list of
#. duplicate refspecs, composed above.
+#.
#, c-format
msgid ""
"There are multiple remotes whose fetch refspecs map to the remote\n"
#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
#. in your translation. The program will only accept English
#. input at this point.
+#.
#, c-format
msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "
msgstr ""
#. TRANSLATORS: Make sure to include [Y] and [n] in your
#. translation. The program will only accept English input
#. at this point.
+#.
msgid "Are you sure [Y/n]? "
msgstr "N'esteu segur [Y/n]? "
#. TRANSLATORS: Make sure to include [Y] and [n] in your
#. translation. The program will only accept English input
#. at this point.
+#.
msgid "Do you want me to do it for you [Y/n]? "
msgstr "Voleu que ho faci per vostè [Y/n]? "
#. among various forms of relative timestamps, but
#. your language may need more or fewer display
#. columns.
+#.
msgid "4 years, 11 months ago"
msgstr "fa 4 anys i 11 mesos"
msgstr "no s'ha pogut cercar l'objecte de comissió per a «%s»"
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
-msgstr ""
-"la branca «%s» no està completament fusionada.\n"
-"Si esteu segur que voleu suprimir-la, executeu «git branch -D %s»"
+msgid "the branch '%s' is not fully merged"
+msgstr "la branca «%s» no està completament fusionada"
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "Si esteu segur que voleu suprimir-la, executeu «git branch -D %s»"
msgid "update of config-file failed"
msgstr "ha fallat l'actualització del fitxer de configuració"
msgid "new-branch"
msgstr "branca-nova"
-msgid "new unparented branch"
-msgstr "branca òrfena nova"
+msgid "new unborn branch"
+msgstr "branca no nascuda nova"
msgid "update ignored files (default)"
msgstr "actualitza els fitxers ignorats (per defecte)"
"clean.requireForce és per defecte cert i ni -i, -n ni -f s'han indicat; "
"refusant netejar"
-msgid "-x and -X cannot be used together"
-msgstr "-x i -X no es poden usar junts"
-
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<opcions>] [--] <repositori> [<directori>]"
msgid "separate git dir from working tree"
msgstr "separa el directori de git de l'arbre de treball"
+msgid "specify the reference format to use"
+msgstr "especifiqueu el format de referència a usar"
+
msgid "key=value"
msgstr "clau=valor"
msgid "You must specify a repository to clone."
msgstr "Heu d'especificar un repositori per a clonar."
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"--bundle-uri és incompatible amb --depth, --shallow-since i --shallow-exclude"
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "el format d'emmagatzematge de referència «%s» és desconegut"
#, c-format
msgid "repository '%s' does not exist"
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <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>"
+" <split-options>"
msgid "dir"
msgstr "directori"
#. TRANSLATORS: Leave "[(amend|reword):]" as-is,
#. and only translate <commit>.
+#.
msgid "[(amend|reword):]commit"
msgstr "[(amend|reword):]commit"
#, c-format
msgid "option '%s' and commit-ishes cannot be used together"
-msgstr "les opcions «%s» i de comissió no es poden usar juntes"
+msgstr "opció «%s» i les de comissió no es poden usar juntes"
msgid ""
"git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
#. TRANSLATORS: %s is the configuration
#. variable for tweaking threads, currently
#. grep.threads
+#.
#, c-format
msgid "no threads support, ignoring %s"
msgstr "no s'admeten fils, s'ignorarà %s"
msgid "unable to read tree (%s)"
msgstr "no s'ha pogut llegir l'arbre (%s)"
+#, c-format
+msgid "unable to read tree %s"
+msgstr "no s'ha pogut llegir l'arbre %s"
+
#, c-format
msgid "unable to grep from object of type %s"
msgstr "no es pot fer grep des d'un objecte de tipus %s"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "S'HA TROBAT UNA COL·LISIÓ SHA1 AMB %s !"
-#, c-format
-msgid "unable to read %s"
-msgstr "no s'ha pogut llegir %s"
-
#, c-format
msgid "cannot read existing object info %s"
msgstr "no es pot llegir la informació d'objecte existent %s"
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>]"
"git merge-file [<opcions>] [-L <nom1> [-L <original> [-L <nom2>]]] <fitxer1> "
"<fitxer-original> <fitxer2>"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"l'opció diff-algorithm accepta «myers», «minimal», «patience» i «histogram»"
+
msgid "send results to standard output"
msgstr "envia els resultats a la sortida estàndard"
msgid "for conflicts, use a union version"
msgstr "en conflictes, usa una versió d'unió"
+msgid "<algorithm>"
+msgstr "<algorisme>"
+
+msgid "choose a diff algorithm"
+msgstr "trieu un algorisme per al diff"
+
msgid "for conflicts, use this marker size"
msgstr "en conflictes, usa aquesta mida de marcador"
msgid "unknown strategy option: -X%s"
msgstr "opció d'estratègia desconeguda: -X%s"
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base és incompatible amb --stdin"
-
#, c-format
msgid "malformed input line: '%s'."
msgstr "línia d'entrada mal formada: «%s»."
#. TRANSLATORS: the first %s will be replaced by a git
#. notes command: 'add', 'merge', 'remove', etc.
+#.
#, c-format
msgid "refusing to %s notes in %s (outside of refs/notes/)"
msgstr "s'està refusant %s les notes en %s (fora de refs/notes/)"
msgid "inconsistency with delta count"
msgstr "inconsistència amb el comptador de diferències"
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "valor pack.allowPackReuse value no vàlid: «%s»"
+
#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Total %<PRIu32> (%<PRIu32> diferències), reusats %<PRIu32> (%<PRIu32> "
-"diferències), paquets reusats %<PRIu32>"
+"diferències), paquets reusats %<PRIu32> (de %<PRIuMAX>)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
msgid "switch `C' expects a numerical value"
msgstr "«switch» «c» espera un valor numèric"
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"les opcions «apply» són incompatibles amb rebase.autoSquash. Considereu "
-"afegir-hi --no-autosquash"
-
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"no-rebase-merges"
#. TRANSLATORS: the colon ':' should align
#. with the one in " Fetch URL: %s"
#. translation.
+#.
#, c-format
msgid " Push URL: %s"
msgstr " URL de pujada: %s"
msgid "only one pattern can be given with -l"
msgstr "només es pot especificar un patró amb -l"
+msgid "need some commits to replay"
+msgstr "calen algunes comissions per tornar a reproduir"
+
+msgid "--onto and --advance are incompatible"
+msgstr "--onto i --advance són incompatibles"
+
+msgid "all positive revisions given must be references"
+msgstr "totes les revisions positives que s'han donat han de ser referències"
+
+msgid "argument to --advance must be a reference"
+msgstr "l'argument per a --advance ha de ser una referència"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"no es pot avançar l'objectiu amb múltiples fonts perquè l'ordenació no "
+"estaria definida correctament"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr ""
+"no es pot determinar implícitament si aquesta és una operació --advance o --"
+"onto"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"no es pot avançar l'objectiu amb múltiples branques d'origen perquè "
+"l'ordenació no estaria definida correctament"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "no es pot determinar implícitament la base correcta per a --onto"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+
+msgid "make replay advance given branch"
+msgstr "fes avançar la repetició de la branca donada"
+
+msgid "replay onto given commit"
+msgstr "torna a reproduir a la comissió donada"
+
+msgid "advance all branches contained in revision-range"
+msgstr "avança totes les branques contingudes a l'interval de revisions"
+
+msgid "option --onto or --advance is mandatory"
+msgstr "l'opció --onto o --advance és obligatòria"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"algunes opcions de referència se sobreescriuran de forma forçada com a «%s» "
+"bits a «struct rev_info»"
+
+msgid "error preparing revisions"
+msgstr "s'ha produït un error en preparar les revisions"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "encara no s'admet la reproducció cap avall en una comissió arrel"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "encara no s'admet la repetició de les comissió de fusió"
+
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr ""
msgid "unknown mode for --abbrev-ref: %s"
msgstr "mode desconegut per a --abbrev-ref: %s"
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden no es pot utilitzar juntament amb --branches"
-
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden no es pot utilitzar juntament amb --tags"
-
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden no es pot utilitzar juntament amb --remotes"
-
msgid "this operation must be run in a work tree"
msgstr "aquesta operació s'ha d'executar en un arbre de treball"
msgid "show refs from stdin that aren't in local repository"
msgstr "mostra les referències de stdin que no siguin en el repositori local"
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "només es poden donar les opcions «%s», «%s», o «%s»"
-
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
"rules) [<options>]"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Si voleu crear un arbre de treball que contingui una branca orfe nova\n"
-"(branca sense comissions) per a aquest repositori, podeu fer-ho\n"
+"Si voleu crear un arbre de treball que contingui una branca no nascuda\n"
+"nova (branca sense comissions) per a aquest repositori, podeu fer-ho\n"
"utilitzant l'argument --orphan:\n"
"\n"
" git worktree add --orphan -b %s %s\n"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Si voleu crear un arbre de treball que contingui una branca orfe nova\n"
-"(branca sense comissions) per a aquest repositori, podeu fer-ho\n"
+"Si voleu crear un arbre de treball que contingui una branca no nascuda\n"
+"nova (branca sense comissions) per a aquest repositori, podeu fer-ho\n"
"utilitzant l'argument --orphan:\n"
"\n"
" git worktree add --orphan %s\n"
msgid "initializing"
msgstr "s'està inicialitzant"
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "no s'ha pogut trobar l'arbre de treball creat «%s»"
+
#, c-format
msgid "Preparing worktree (new branch '%s')"
msgstr "S'està preparant l'arbre de treball (branca nova «%s»)"
"No hi ha referències locals o remotes malgrat hi existeix almenys un\n"
"remot, aturada; useu «add -f» per a anul·lar o obtenir primer un remot"
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "les opcions «%s» i «%s» no es poden usar juntes"
-
msgid "checkout <branch> even if already checked out in other worktree"
msgstr "agafa <branca> encara que sigui agafada en altre arbre de treball"
msgid "create or reset a branch"
msgstr "crea o restableix una branca"
-msgid "create unborn/orphaned branch"
-msgstr "crea una branca no nascuda/òrfena"
+msgid "create unborn branch"
+msgstr "crea una branca no nascuda"
msgid "populate the new working tree"
msgstr "emplena l'arbre de treball nou"
msgstr "les opcions «%s», «%s», i «%s» no es poden usar juntes"
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "les opcions «%s» i «%s» no es poden usar juntes"
-
-msgid "<commit-ish>"
-msgstr "<commit-ish>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "opció «%s» i les de comissió no es poden usar juntes"
msgid "added with --lock"
msgstr "afegit amb --lock"
msgid "Create, list, delete refs to replace objects"
msgstr "Crea, llista i esborra referències per a substituir objectes"
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"EXPERIMENTAL: torna a reproduir comissions sobre una nova base, també "
+"funciona amb repositoris nus"
+
msgid "Generates a summary of pending changes"
msgstr "Genera un resum dels canvis pendents"
msgid "commit-graph file is too small"
msgstr "el fitxer del graf de comissions és massa petit"
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr ""
+"el fragment de «fanout» de l'oid del graf de comissions és de mida incorrecta"
+
+msgid "commit-graph fanout values out of order"
+msgstr "valors de graf de comissions de «fanout» estan fora d'ordre"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "el fragment de cerca OID és de mida incorrecta"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "el fragment de dades del graf de comissions és de mida incorrecta"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr ""
+"el fragment de les generacions del graf de comissions és de mida incorrecta"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr ""
+"el fragment d'índex del canvi del camí del graf de comissions és massa petit"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"s'ignorarà un fragment massa petit de camí canviat (%<PRIuMAX> < %<PRIuMAX>) "
+"al fitxer del graf de comissions"
+
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgstr ""
msgstr ""
"el fitxer del graf de comissions és massa petit per a guardar %u fragments"
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr ""
+"manca o està malmès el fragment del «fanout» OID requerit al graf de "
+"comissions"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr ""
+"manca o està malmès el fragment de cerca d'OID requerit al graf de comissions"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr ""
+"manca o està corromput el fragment de dades de publicació requerit al graf "
+"de comissions"
+
msgid "commit-graph has no base graphs chunk"
msgstr "el fragment del graf de comissions no té grafs de base"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "el nombre de comissions en el graf base és massa alt: %<PRIuMAX>"
+msgid "commit-graph chain file too small"
+msgstr "el fitxer de cadena del graf de comissions és massa petit"
+
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr ""
"les dades de generació de desbordament del graf de comissions són massa "
"petites"
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "punter de vores extra del graf de comissió està fora dels límits"
+
msgid "Loading known commits in commit graph"
msgstr "S'estan carregant comissions conegudes al graf de comissions"
msgstr ""
"Valor desconegut de la variable de configuració de «diff.submodule»: «%s»"
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "valor desconegut per al config «%s»': %s"
+
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "mode «%s» no vàlid en --color-moved-ws"
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"l'opció diff-algorithm accepta «myers», «minimal», «patience» i «histogram»"
-
#, c-format
msgid "invalid argument to %s"
msgstr "argument no vàlid a %s"
msgid "output only the last line of --stat"
msgstr "mostra només l'última línia de --stat"
-msgid "<param1,param2>..."
-msgstr "<param1,param2>..."
+msgid "<param1>,<param2>..."
+msgstr "<param1>,<param2>..."
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
msgid "synonym for --dirstat=cumulative"
msgstr "sinònim de --dirstat=cumulative"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "sinònim de --dirstat=files,param1,param2..."
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "sinònim de --dirstat=files,<param1>,<param2>..."
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr ""
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "genera diff usant l'algorisme «histogram diff»"
-msgid "<algorithm>"
-msgstr "<algorisme>"
-
-msgid "choose a diff algorithm"
-msgstr "trieu un algorisme per al diff"
-
msgid "<text>"
msgstr "<text>"
#. TRANSLATORS: The parameter will be 'ready', a protocol
#. keyword.
+#.
#, c-format
msgid "expected packfile to be sent after '%s'"
msgstr "s'esperava que el fitxer de paquet s'enviés després de «%s»"
#. TRANSLATORS: The parameter will be 'ready', a protocol
#. keyword.
+#.
#, c-format
msgid "expected no other sections to be sent after no '%s'"
msgstr "no s'esperava que cap altra secció s'enviés després de «%s»"
#. name, and the second argument is the abbreviated id of the
#. commit that needs to be merged. For example:
#. - go to submodule (mysubmodule), and either merge commit abc1234"
+#.
#, c-format
msgid ""
" - go to submodule (%s), and either merge commit %s\n"
#. TRANSLATORS: The %s arguments are: 1) tree hash of a merge
#. base, and 2-3) the trees for the two trees we're merging.
+#.
#, c-format
msgid "collecting merge info failed for trees %s, %s, %s"
msgstr ""
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "l'OID «fanout» de l'índex multipaquet és d'una mida incorrecta"
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"oid «fanout» desordenat: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "El fragment de cerca OID índex multipaquet és de mida incorrecta"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "pack-int-id: %u incorrecte (%u paquets en total)"
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX no conté el fragment BTMP"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "no s'ha pogut carregar el paquet amb bits %<PRIu32>"
+
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr ""
"l'índex multipaquet emmagatzema un desplaçament de 64 bits, però off_t és "
msgid "Looking for referenced packfiles"
msgstr "S'estan cercant fitxers empaquetats referenciats"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr "oid fanout desordenat: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-
msgid "the midx contains no oid"
msgstr "el midx no conté cap oid"
#. TRANSLATORS: The first %s is the name of
#. the environment variable, the second %s is
#. its value.
+#.
#, c-format
msgid "Bad %s value: '%s'"
msgstr "Valor erroni de %s: «%s»"
#. 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]".
+#.
#, c-format
msgid "%s [bad object]"
msgstr "%s [objecte incorrecte]"
#. object output. E.g.:
#. *
#. "deadbeef commit 2021-01-01 - Some Commit Message"
+#.
#, c-format
msgid "%s commit %s - %s"
msgstr "%s comissió %s - %s"
#. *
#. The third argument is the "tag" string
#. from object.c.
+#.
#, c-format
msgid "%s tag %s - %s"
msgstr "%s etiqueta %s - %s"
#. the tag itself. E.g.:
#. *
#. "deadbeef [bad tag, could not parse it]"
+#.
#, c-format
msgid "%s [bad tag, could not parse it]"
msgstr "%s [etiqueta malmesa, no s'ha pogut analitzar]"
#. TRANSLATORS: This is a line of ambiguous <type>
#. object output. E.g. "deadbeef tree".
+#.
#, c-format
msgid "%s tree"
msgstr "arbre %s"
#. TRANSLATORS: This is a line of ambiguous <type>
#. object output. E.g. "deadbeef blob".
+#.
#, c-format
msgid "%s blob"
msgstr "blob %s"
#. TRANSLATORS: The argument is the list of ambiguous
#. objects composed in show_ambiguous_object(). See
#. its "TRANSLATORS" comments for details.
+#.
#, c-format
msgid ""
"The candidates are:\n"
msgid "could not open pack %s"
msgstr "no s'ha pogut obrir el paquet %s"
+msgid "could not determine MIDX preferred pack"
+msgstr "no s'ha pogut determinar el paquet preferit MIDX"
+
#, c-format
msgid "preferred pack (%s) is invalid"
msgstr "el paquet preferit (%s) no és vàlid"
"mapa de bits ewah malmès: capçalera truncada per al mapa de bits de la "
"comissió «%s»"
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr ""
+"no s'ha pogut carregar el paquet: «%s», s'està inhabilitant lareutilització "
+"de paquets"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "no s'ha trobat l'objecte «%s» als tipus de mapes de bits"
msgstr ""
"el fragment de l'index invers de l'índex multipaquet és de mida incorrecta"
+msgid "could not determine preferred pack"
+msgstr "no s'ha pogut determinar el paquet preferit"
+
msgid "cannot both write and verify reverse index"
msgstr "no es pot escriure i verificar l'índex invers"
msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
msgstr "%s espera un valor enter no negatiu amb un sufix opcional k/m/g"
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s és incompatible amb %s"
-
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgstr "opció ambigua: %s (pot ser --%s%s o --%s%s)"
#. TRANSLATORS: the colon here should align with the
#. one in "usage: %s" translation.
+#.
#, c-format
msgid " or: %s"
msgstr " o: %s"
#. function. The "%s" is a line in the (hopefully already
#. translated) N_() usage string, which contained embedded
#. newlines before we split it up.
+#.
#, c-format
msgid "%*s%s"
msgstr "%*s%s"
msgid "unable to add '%s' to index"
msgstr "no s'ha pogut afegir «%s» a l'índex"
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "no s'ha pogut fer «stat» a «%s»"
-
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgstr "«%s» apareix com a fitxer i com a directori"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "no es poden processar «%s» i «%s» a la vegada"
-#, c-format
-msgid "could not remove reference %s"
-msgstr "no s'ha pogut eliminar la referència %s"
-
#, c-format
msgid "could not delete reference %s: %s"
msgstr "no s'ha pogut suprimir la referència %s: %s"
#. TRANSLATORS: "matches '%s'%" is the <dst> part of "git push
#. <remote> <src>:<dst>" push, and "being pushed ('%s')" is
#. the <src>.
+#.
#, c-format
msgid ""
"The destination you provided is not a full refname (i.e.,\n"
"'%s:refs/tags/%s'?"
msgstr ""
"La part <src> de l'especificació de la referència és un objecte d'etiqueta.\n"
-"Voleu crear una etiqueta pujant-la a «%srefs/tags/%s»?"
+"Voleu crear una etiqueta pujant-la a «%s:refs/tags/%s»?"
#, c-format
msgid ""
"'%s:refs/tags/%s'?"
msgstr ""
"La part <src> de l'especificació de la referència és un objecte d'arbre.\n"
-"Voleu crear una etiqueta pujant-la a «%srefs/tags/%s»?"
+"Voleu crear una etiqueta pujant-la a «%s:refs/tags/%s»?"
#, c-format
msgid ""
#. TRANSLATORS: %s will be "revert", "cherry-pick" or
#. "rebase".
+#.
#, c-format
msgid "%s: Unable to write new index file"
msgstr "%s: No s'ha pogut escriure un fitxer d'índex nou"
msgstr ""
"El «stash» automàtic ja existeix; s'està creant una entrada «stash» nova."
+msgid "autostash reference is a symref"
+msgstr "la referència d'autostash és un symref"
+
msgid "could not detach HEAD"
msgstr "no s'ha pogut separar HEAD"
"not a git repository (or any parent up to mount point %s)\n"
"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)."
msgstr ""
-"no és un repositori de git (ni cap pare fins al punt de muntatge %s)\n"
+"no és un repositori de git (ni existeix cap pare fins al punt de muntatge "
+"%s)\n"
"S'atura a la frontera de sistema de fitxers (GIT_DISCOVERY_ACROSS_FILESYSTEM "
"no està establert)."
msgid "invalid initial branch name: '%s'"
msgstr "nom de branca inicial no vàlid: «%s»"
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "reinicialització: s'ha ignorat --initial-branch=%s"
+
#, c-format
msgid "unable to handle file type %d"
msgstr "no s'ha pogut gestionar el tipus de fitxer %d"
msgid "attempt to reinitialize repository with different hash"
msgstr "s'ha intentat reinicialitzar el repositori amb un resum diferent"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr ""
+"s'ha intentat reactivar el repositori amb un format d'emmagatzematge de "
+"referència diferent"
+
#, c-format
msgid "%s already exists"
msgstr "%s ja existeix"
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "reinicialització: s'ha ignorat --initial-branch=%s"
-
#, c-format
msgid "Reinitialized existing shared Git repository in %s%s\n"
msgstr "S'ha reinicialitzat el repositori compartit existent del Git en %s%s\n"
msgstr ""
"nombre d'entrades a l'arbre de la memòria cau a invalidar (per defecte 0)"
-msgid "unhandled options"
-msgstr "opcions no gestionades"
-
-msgid "error preparing revisions"
-msgstr "s'ha produït un error en preparar les revisions"
-
#, c-format
msgid "commit %s is not marked reachable"
msgstr "la comissió %s no està marcada com abastable"
msgid "invalid remote service path"
msgstr "el camí del servei remot no és vàlid"
-msgid "operation not supported by protocol"
-msgstr "opció no admesa pel protocol"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "no es pot connectar al subservei %s"
msgstr ""
"encara no s'ha implementat la compatibilitat amb la versió v2 del protocol"
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "valor desconegut per al config «%s»': %s"
-
#, c-format
msgid "transport '%s' not allowed"
msgstr "no es permet el transport «%s»"
msgstr ""
"no s'ha pogut recuperar la llista de paquets d'URI anunciats pel servidor"
+msgid "operation not supported by protocol"
+msgstr "opció no admesa pel protocol"
+
msgid "too-short tree object"
msgstr "objecte d'arbre massa curt"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "no es pot %s: El vostre índex conté canvis sense cometre."
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "estil desconegut «%s» donat per a «%s»"
+
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
#, perl-format
msgid "Do you really want to send %s? [y|N]: "
msgstr "Esteu segur que voleu enviar %s? [y|N]: "
-
-#, c-format
-#~ msgid "options '%s=%s' and '%s=%s' cannot be used together"
-#~ msgstr "les opcions «%s=%s» i «%s=%s» no es poden usar juntes"
-
-#, c-format
-#~ msgid "%s : incompatible with something else"
-#~ msgstr "%s: és incompatible amb alguna altra cosa"
-
-#~ msgid "Could not write patch"
-#~ msgstr "No s'ha pogut escriure el pedaç"
-
-#, c-format
-#~ msgid "Could not stat '%s'"
-#~ msgstr "No s'ha pogut fer stat a «%s»"
-
-#, c-format
-#~ msgid "Cannot delete branch '%s' checked out at '%s'"
-#~ msgstr "No es pot suprimir la branca «%s» agafada a «%s»"
-
-#~ msgid "unable to write new_index file"
-#~ msgstr "no s'ha pogut escriure el fitxer new_index"
-
-#~ msgid "do not apply config rules"
-#~ msgstr "no apliquis les regles de configuració"
-
-#~ msgid "join whitespace-continued values"
-#~ msgstr "uneix els valors continus amb espais en blanc"
-
-#~ msgid "set parsing options"
-#~ msgstr "estableix les opcions d'anàlisi"
-
-#~ msgid "cannot move directory over file"
-#~ msgstr "no es pot moure un directori sobre un fitxer"
-
-#~ msgid "cannot use --filter without --stdout"
-#~ msgstr "no es pot utilitzar --filter sense --stdout"
-
-#~ msgid "cannot use --max-pack-size with --cruft"
-#~ msgstr "no es pot usar --max-pack-size amb --cruft"
-
-#~ msgid "--strategy requires --merge or --interactive"
-#~ msgstr "--strategy requereix --merge o --interactive"
-
-#, c-format
-#~ msgid ""
-#~ "commit-graph has generation number zero for commit %s, but non-zero "
-#~ "elsewhere"
-#~ msgstr ""
-#~ "el graf de comissions té nombre de generació zero per a la comissió %s, "
-#~ "però té no zero en altres llocs"
-
-#~ msgid "--merge-base only works with commits"
-#~ msgstr "--merge-base només funciona amb comissions"
-
-#~ msgid "scalar clone [<options>] [--] <repo> [<dir>]"
-#~ msgstr "scalar clone [<opcions>] [--] <repositori> [<dir>]"
-
-#, c-format
-#~ msgid "could not rename '%s' to '%s'"
-#~ msgstr "no s'ha pogut canviar el nom «%s» a «%s»"
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-09 11:29+0100\n"
-"PO-Revision-Date: 2023-11-10 14:28+0100\n"
+"POT-Creation-Date: 2024-02-17 18:07+0100\n"
+"PO-Revision-Date: 2024-02-17 18:14+0100\n"
"Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n"
"Language-Team: German\n"
"Language: de\n"
msgid "Unexpected option --output"
msgstr "Unerwartete Option --output"
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "zusätzlicher Befehlszeilenparameter '%s'"
+
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Unbekanntes Archivformat '%s'"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "ungültiges --attr-source oder GIT_ATTR_SOURCE"
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "konnte '%s' nicht lesen"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "kann %s nicht lesen"
+
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "Ungültiger Inhalt bzgl. Anführungszeichen in Datei '%s': %s"
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
msgstr "konnte Commit-Objekt für '%s' nicht nachschlagen"
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
+msgid "the branch '%s' is not fully merged"
+msgstr "der Branch '%s' ist nicht vollständig zusammengeführt"
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
msgstr ""
-"Der Branch '%s' ist nicht vollständig zusammengeführt.\n"
-"Wenn Sie sicher sind diesen Branch zu entfernen, führen Sie 'git branch -D "
-"%s' aus."
+"Wenn Sie sicher sind, dass Sie den Branch löschen wollen, führen Sie 'git "
+"branch -D %s' aus."
msgid "update of config-file failed"
msgstr "Aktualisierung der Konfigurationsdatei fehlgeschlagen."
msgid "new-branch"
msgstr "neuer Branch"
-msgid "new unparented branch"
-msgstr "neuer Branch ohne Eltern-Commit"
+msgid "new unborn branch"
+msgstr "neuer ungeborener Branch"
msgid "update ignored files (default)"
msgstr "ignorierte Dateien aktualisieren (Standard)"
"clean.requireForce standardmäßig auf \"true\" gesetzt und weder -i, -n noch -"
"f gegeben; \"clean\" verweigert"
-msgid "-x and -X cannot be used together"
-msgstr "-x und -X können nicht gemeinsam verwendet werden"
-
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<Optionen>] [--] <Repository> [<Verzeichnis>]"
msgid "separate git dir from working tree"
msgstr "Git-Verzeichnis vom Arbeitsverzeichnis separieren"
+msgid "specify the reference format to use"
+msgstr "das zu verwendende Referenzformat angeben"
+
msgid "key=value"
msgstr "Schlüssel=Wert"
msgid "You must specify a repository to clone."
msgstr "Sie müssen ein Repository zum Klonen angeben."
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"--bundle-uri ist inkompatibel mit --depth, --shallow-since und --shallow-"
-"exclude"
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "unbekanntes Speicherformat für Referenzen '%s'"
#, c-format
msgid "repository '%s' does not exist"
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir <Verzeichnis>] [--append]\n"
" [--split[=<Strategie>]] [--reachable | --stdin-packs "
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
msgid "unable to read tree (%s)"
msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen"
+#, c-format
+msgid "unable to read tree %s"
+msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen"
+
#, c-format
msgid "unable to grep from object of type %s"
msgstr "kann \"grep\" nicht mit Objekten des Typs %s durchführen"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "SHA1 KOLLISION MIT %s GEFUNDEN !"
-#, c-format
-msgid "unable to read %s"
-msgstr "kann %s nicht lesen"
-
#, c-format
msgid "cannot read existing object info %s"
msgstr "Kann existierende Informationen zu Objekt %s nicht lesen."
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=<Vorlagenverzeichnis>]\n"
" [--separate-git-dir <Git-Verzeichnis>] [--object-format=<Format>]\n"
+" [--ref-format=<Format>]\n"
" [-b <Branchname> | --initial-branch=<Branchname>]\n"
" [--shared[=<Berechtigungen>]] [<Verzeichnis>]"
"git merge-file [<Optionen>] [-L <Name1> [-L <orig> [-L <Name2>]]] <Datei1> "
"<orig-Datei> <Datei2>"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"Option diff-algorithm akzeptiert: \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+
msgid "send results to standard output"
msgstr "Ergebnisse zur Standard-Ausgabe senden"
msgid "for conflicts, use a union version"
msgstr "bei Konflikten eine gemeinsame Variante verwenden"
+msgid "<algorithm>"
+msgstr "<Algorithmus>"
+
+msgid "choose a diff algorithm"
+msgstr "einen Algorithmus für Änderungen wählen"
+
msgid "for conflicts, use this marker size"
msgstr "bei Konflikten diese Kennzeichnungslänge verwenden"
msgid "unknown strategy option: -X%s"
msgstr "unbekannte Strategie-Option: -X%s"
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base ist inkompatibel mit --stdin"
-
#, c-format
msgid "malformed input line: '%s'."
msgstr "Fehlerhafte Eingabezeile: '%s'."
msgid "inconsistency with delta count"
msgstr "Inkonsistenz mit der Anzahl von Deltas"
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "ungültiger Wert für pack.allowPackReuse: '%s'"
+
#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Gesamt %<PRIu32> (Delta %<PRIu32>), Wiederverwendet %<PRIu32> (Delta "
-"%<PRIu32>), Pack wiederverwendet %<PRIu32>"
+"%<PRIu32>), Paket wiederverwendet %<PRIu32> (von %<PRIuMAX>)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
msgid "switch `C' expects a numerical value"
msgstr "Schalter `C' erwartet einen numerischen Wert."
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"apply-Optionen sind mit rebase.autoSquash nicht kompatibel. Erwägen Sie das "
-"Hinzufügen von --no-autosquash"
-
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"no-rebase-merges"
msgid "only one pattern can be given with -l"
msgstr "Mit -l kann nur ein Muster angegeben werden"
+msgid "need some commits to replay"
+msgstr "zum erneuten Abspielen werden Commits benötigt"
+
+msgid "--onto and --advance are incompatible"
+msgstr "--onto und --advance sind inkompatibel"
+
+msgid "all positive revisions given must be references"
+msgstr "alle angegebenen positiven Commits müssen Referenzen sein"
+
+msgid "argument to --advance must be a reference"
+msgstr "Argument für --advance muss eine Referenz sein"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"kann Ziel nicht mit mehreren Quellen erweitern, da die Reihenfolge unklar "
+"wäre"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr ""
+"kann nicht implizit bestimmen, ob es sich um eine --advance oder --onto "
+"Operation handelt"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"kann Ziel nicht mit mehreren Quell-Branches erweitern, da die Reihenfolge "
+"unklar wäre"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "kann nicht implizit die richtige Basis für --onto bestimmen"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(EXPERIMENTELL!) git replay ([--contained] --onto <neue-Basis> | --advance "
+"<Branch>) <Commitbereich>..."
+
+msgid "make replay advance given branch"
+msgstr "angegebenen Branch durch neues Abspielen erweitern"
+
+msgid "replay onto given commit"
+msgstr "auf angegebenen Commit neu abspielen"
+
+msgid "advance all branches contained in revision-range"
+msgstr "alle Branches erweitern, die in Commitbereich liegen"
+
+msgid "option --onto or --advance is mandatory"
+msgstr "Option --onto oder --advance erforderlich"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"einige Optionen für das Abgehen von Commits werden außer Kraft gesetzt, da "
+"das '%s' Bit in 'struct rev_info' erzwungen wird"
+
+msgid "error preparing revisions"
+msgstr "Fehler beim Vorbereiten der Commits"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "erneutes Abspielen bis zum Root-Commit wird noch nicht unterstützt!"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "erneutes Abspielen von Merge-Commits wird noch nicht unterstützt!"
+
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr ""
msgid "unknown mode for --abbrev-ref: %s"
msgstr "unbekannter Modus für --abbrev-ref: %s"
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden kann nicht zusammen mit --branches verwendet werden"
-
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden kann nicht zusammen mit --tags verwendet werden"
-
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden kann nicht zusammen mit --remotes verwendet werden"
-
msgid "this operation must be run in a work tree"
msgstr "Diese Operation muss in einem Arbeitsverzeichnis ausgeführt werden."
"Referenzen von der Standard-Eingabe anzeigen, die sich nicht im lokalen "
"Repository befinden"
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "es kann nur eines von '%s', '%s' oder '%s' angegeben werden"
-
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
"rules) [<options>]"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Wenn Sie ein Arbeitsverzeichnis erstellen möchten, um einen neuen verwaisten "
-"Branch\n"
-"(Branch ohne Commits) für dieses Repository zu erstellen, können Sie dies "
-"mit\n"
-"der Option --orphan tun:\n"
+"Wenn Sie ein Arbeitsverzeichnis erstellen möchten, welches einen neuen\n"
+"ungeborenen Branch (Branch ohne Commits) für dieses Repository erzeugt,\n"
+"können Sie dies mit der Option --orphan tun:\n"
"\n"
" git worktree add --orphan -b %s %s\n"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Wenn Sie ein Arbeitsverzeichnis erstellen möchten, um einen neuen verwaisten "
-"Branch\n"
-"(Branch ohne Commits) für dieses Repository zu erstellen, können Sie dies "
-"mit\n"
-"der Option --orphan tun:\n"
+"Wenn Sie ein Arbeitsverzeichnis erstellen möchten, welches einen neuen\n"
+"ungeborenen Branch (Branch ohne Commits) für dieses Repository erzeugt,\n"
+"können Sie dies mit der Option --orphan tun:\n"
"\n"
" git worktree add --orphan %s\n"
msgid "initializing"
msgstr "initialisiere"
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "konnte erstelltes Arbeitsverzeichnis '%s' nicht finden"
+
#, c-format
msgid "Preparing worktree (new branch '%s')"
msgstr "Bereite Arbeitsverzeichnis vor (neuer Branch '%s')"
"Referenz zu überschreiben\n"
"oder rufen Sie diese zuerst ab"
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "'%s' und '%s' können nicht zusammen verwendet werden"
-
msgid "checkout <branch> even if already checked out in other worktree"
msgstr ""
"<Branch> auschecken, auch wenn dieser bereits in einem anderen "
msgid "create or reset a branch"
msgstr "Branch erstellen oder umsetzen"
-msgid "create unborn/orphaned branch"
-msgstr "ungeborenen/verwaisten Branch erstellen"
+msgid "create unborn branch"
+msgstr "ungeborenen Branch erzeugen"
msgid "populate the new working tree"
msgstr "das neue Arbeitsverzeichnis auschecken"
"die Optionen '%s', '%s' und '%s' können nicht gemeinsam verwendet werden"
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "die Optionen '%s' und '%s' können nicht gemeinsam verwendet werden"
-
-msgid "<commit-ish>"
-msgstr "<Commit-Angabe>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "Option '%s' und commit-ish können nicht gemeinsam verwendet werden"
msgid "added with --lock"
msgstr "mit --lock hinzugefügt"
msgid "Create, list, delete refs to replace objects"
msgstr "Referenzen für ersetzende Objekte erstellen, auflisten, löschen"
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"EXPERIMENTELL: Commits auf neuer Basis abspielen, funktioniert auch mit Bare-"
+"Repositories"
+
msgid "Generates a summary of pending changes"
msgstr "eine Übersicht über ausstehende Änderungen generieren"
msgid "commit-graph file is too small"
msgstr "Commit-Graph-Datei ist zu klein"
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "Commit-Graph OID fanout Chunk hat die falsche Größe"
+
+msgid "commit-graph fanout values out of order"
+msgstr "Commit-Graph fanout-Werte sind nicht in Ordnung"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "Commit-Graph OID Lookup Chunk hat die falsche Größe"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "Commit-Graph Commit Daten Chunk hat die falsche Größe"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr "Commit-Graph Generations Chunk hat die falsche Größe"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "Commit-Graph changed-path Index Chunk ist zu klein"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"ignoriere zu kleinen Chunk für geänderte Pfade (%<PRIuMAX> < %<PRIuMAX>) in "
+"Commit-Graph-Datei"
+
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgstr "Commit-Graph-Signatur %X stimmt nicht mit Signatur %X überein"
msgid "commit-graph file is too small to hold %u chunks"
msgstr "Commit-Graph-Datei ist zu klein, um %u Chunks zu enthalten"
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr "Commit-Graph benötigter OID fanout Chunk fehlt oder ist beschädigt"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr "Commit-Graph benötigter OID lookup Chunk fehlt oder ist beschädigt"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr ""
+"Commit-Graph erforderlicher Commit-Daten Chunk fehlt oder ist beschädigt"
+
msgid "commit-graph has no base graphs chunk"
msgstr "Commit-Graph hat keinen Basis-Graph-Chunk"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "Anzahl der Commits im Basisgraph zu hoch: %<PRIuMAX>"
+msgid "commit-graph chain file too small"
+msgstr "Commit-Graph Chain-Datei zu klein"
+
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr "Ungültige Commit-Graph Verkettung: Zeile '%s' ist kein Hash"
msgid "commit-graph overflow generation data is too small"
msgstr "Commit-Graph Überlaufgenerierungsdaten sind zu klein"
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "commit-graph extra-edges Zeiger außerhalb der Grenzen"
+
msgid "Loading known commits in commit graph"
msgstr "Lade bekannte Commits in Commit-Graph"
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "Unbekannter Wert in Konfigurationsvariable 'diff.submodule': '%s'"
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "Unbekannter Wert für Konfiguration '%s': %s"
+
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "ungültiger Modus '%s' in --color-moved-ws"
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"Option diff-algorithm akzeptiert: \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-
#, c-format
msgid "invalid argument to %s"
msgstr "ungültiges Argument für %s"
msgid "output only the last line of --stat"
msgstr "nur die letzte Zeile von --stat ausgeben"
-msgid "<param1,param2>..."
-msgstr "<Parameter1,Parameter2>..."
+msgid "<param1>,<param2>..."
+msgstr "<Parameter1>,<Parameter2>..."
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
msgid "synonym for --dirstat=cumulative"
msgstr "Synonym für --dirstat=cumulative"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "Synonym für --dirstat=files,Parameter1,Parameter2..."
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "Synonym für --dirstat=files,<Parameter1>,<Parameter2>..."
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr ""
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "Änderungen durch Nutzung des Algorithmus \"Histogram Diff\" erzeugen"
-msgid "<algorithm>"
-msgstr "<Algorithmus>"
-
-msgid "choose a diff algorithm"
-msgstr "einen Algorithmus für Änderungen wählen"
-
msgid "<text>"
msgstr "<Text>"
#. conflict in a submodule. The first argument is the submodule
#. name, and the second argument is the abbreviated id of the
#. commit that needs to be merged. For example:
-#. - go to submodule (mysubmodule), and either merge commit abc1234"
+#. - go to submodule (mysubmodule), and either merge commit abc1234"
#.
#, c-format
msgid ""
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "Multi-Pack-Index OID fanout hat die falsche Größe"
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"Ungültige oid fanout Reihenfolge: fanout[%d] = %<PRIx32> > %<PRIx32> = "
+"fanout[%d]"
+
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "multi-pack-index OID-Lookup-Chunk hat die falsche Größe"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "Ungültige pack-int-id: %u (%u Pakete insgesamt)"
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX enthält keinen BTMP-Chunk"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "konnte Bitmap-Paket nicht laden %<PRIu32>"
+
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr ""
"Multi-Pack-Index speichert einen 64-Bit Offset, aber off_t ist zu klein"
msgid "Looking for referenced packfiles"
msgstr "Suche nach referenzierten Pack-Dateien"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr ""
-"Ungültige oid fanout Reihenfolge: fanout[%d] = %<PRIx32> > %<PRIx32> = "
-"fanout[%d]"
-
msgid "the midx contains no oid"
msgstr "das midx enthält keine oid"
#. TRANSLATORS: This is a line of ambiguous commit
#. object output. E.g.:
#. *
-#. "deadbeef commit 2021-01-01 - Some Commit Message"
+#. "deadbeef commit 2021-01-01 - Some Commit Message"
#.
#, c-format
msgid "%s commit %s - %s"
#. TRANSLATORS: This is a line of ambiguous
#. tag object output. E.g.:
#. *
-#. "deadbeef tag 2022-01-01 - Some Tag Message"
+#. "deadbeef tag 2022-01-01 - Some Tag Message"
#. *
#. The second argument is the YYYY-MM-DD found
#. in the tag.
#. tag object output where we couldn't parse
#. the tag itself. E.g.:
#. *
-#. "deadbeef [bad tag, could not parse it]"
+#. "deadbeef [bad tag, could not parse it]"
#.
#, c-format
msgid "%s [bad tag, could not parse it]"
msgid "could not open pack %s"
msgstr "konnte Paket '%s' nicht öffnen"
+msgid "could not determine MIDX preferred pack"
+msgstr "konnte das von MIDX bevorzugte Paket nicht ermitteln"
+
#, c-format
msgid "preferred pack (%s) is invalid"
msgstr "bevorzugtes Paket (%s) ist ungültig"
msgstr ""
"fehlerhafte ewah-Bitmap: abgeschnittener Header für Bitmap des Commits \"%s\""
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr ""
+"Paket kann nicht geladen werden: '%s', Deaktivierung der Paket-"
+"Wiederverwendung"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "Objekt '%s' nicht im Typ Bitmaps gefunden"
msgid "multi-pack-index reverse-index chunk is the wrong size"
msgstr "multi-pack-index Reverse-Index Chunk hat die falsche Größe"
+msgid "could not determine preferred pack"
+msgstr "konnte das bevorzugte Paket nicht bestimmen"
+
msgid "cannot both write and verify reverse index"
msgstr ""
"Reverse-Index kann nicht gleichzeitig geschrieben und verifiziert werden"
"%s erwartet einen nicht-negativen Integer-Wert mit einem optionalen k/m/g "
"Suffix"
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s ist inkompatibel mit %s."
-
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgstr "Mehrdeutige Option: %s (kann --%s%s oder --%s%s sein)"
msgid "unable to add '%s' to index"
msgstr "Konnte '%s' nicht dem Index hinzufügen."
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "konnte '%s' nicht lesen"
-
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgstr "'%s' scheint eine Datei und ein Verzeichnis zu sein"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "kann '%s' und '%s' nicht zur selben Zeit verarbeiten"
-#, c-format
-msgid "could not remove reference %s"
-msgstr "konnte Referenz %s nicht löschen"
-
#, c-format
msgid "could not delete reference %s: %s"
msgstr "konnte Referenz %s nicht entfernen: %s"
"\n"
"Neither worked, so we gave up. You must fully qualify the ref."
msgstr ""
-"Das angegebene Ziel ist kein vollständiger Referenzname (startet mit \"refs/"
-"\").\n"
-"Wir versuchten zu erraten, was Sie meinten, mit:\n"
+"Das angegebene Ziel ist kein vollständiger Referenzname (startet mit\n"
+"\"refs/\"). Wir versuchten zu erraten, was Sie meinten, mit:\n"
"\n"
"- Suche einer Referenz, die mit '%s' übereinstimmt, auf der Remote-Seite\n"
-"- Prüfung, ob die versendete <Quelle> ('%s') eine Referenz in \"refs/{heads,"
-"tags}\"\n"
-" ist, in dessen Falle wir einen entsprechenden refs/{heads,tags} Präfix "
-"auf\n"
-" der Remote-Seite hinzufügen würden.\n"
+"- Prüfung, ob die versendete <Quelle> ('%s') eine Referenz in\n"
+" \"refs/{heads,tags}/\" ist, in dessen Falle wir einen entsprechenden\n"
+" refs/{heads,tags}/ Präfix auf der Remote-Seite hinzufügen würden.\n"
"\n"
"Keines hat funktioniert, sodass wir aufgegeben haben. Sie müssen die\n"
"Referenz mit vollqualifizierten Namen angeben."
msgid "Autostash exists; creating a new stash entry."
msgstr "Automatischer Stash existiert; ein neuer Stash-Eintrag wird erstellt."
+msgid "autostash reference is a symref"
+msgstr "Referenz für autostash ist eine symbolische Referenz"
+
msgid "could not detach HEAD"
msgstr "konnte HEAD nicht loslösen"
msgid "invalid initial branch name: '%s'"
msgstr "ungültiger initialer Branchname: '%s'"
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "Neu-Initialisierung: --initial-branch=%s ignoriert"
+
#, c-format
msgid "unable to handle file type %d"
msgstr "kann nicht mit Dateityp %d umgehen"
msgid "attempt to reinitialize repository with different hash"
msgstr "Versuch, das Repository mit einem anderen Hash zu reinitialisieren"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr ""
+"Versuch, das Repository mit einem anderen Referenzspeicherformat neu zu "
+"initialisieren"
+
#, c-format
msgid "%s already exists"
msgstr "%s existiert bereits"
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "Neu-Initialisierung: --initial-branch=%s ignoriert"
-
#, c-format
msgid "Reinitialized existing shared Git repository in %s%s\n"
msgstr "Bestehendes verteiltes Git-Repository in %s%s neuinitialisiert\n"
"Anzahl der Einträge im Cache-Verzeichnis, die ungültig gemacht werden sollen "
"(Standardwert 0)"
-msgid "unhandled options"
-msgstr "unbehandelte Optionen"
-
-msgid "error preparing revisions"
-msgstr "Fehler beim Vorbereiten der Commits"
-
#, c-format
msgid "commit %s is not marked reachable"
msgstr "Commit %s ist nicht als erreichbar gekennzeichnet."
msgid "invalid remote service path"
msgstr "ungültiger Remote-Service Pfad."
-msgid "operation not supported by protocol"
-msgstr "die Operation wird von dem Protokoll nicht unterstützt"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "kann keine Verbindung zu Subservice %s herstellen"
msgid "support for protocol v2 not implemented yet"
msgstr "Unterstützung für Protokoll v2 noch nicht implementiert."
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "Unbekannter Wert für Konfiguration '%s': %s"
-
#, c-format
msgid "transport '%s' not allowed"
msgstr "Übertragungsart '%s' nicht erlaubt."
msgid "could not retrieve server-advertised bundle-uri list"
msgstr "konnte die vom Server angekündigte bundle-uri-Liste nicht abrufen"
+msgid "operation not supported by protocol"
+msgstr "die Operation wird von dem Protokoll nicht unterstützt"
+
msgid "too-short tree object"
msgstr "zu kurzes Tree-Objekt"
msgstr ""
"%s nicht möglich: Die Staging-Area enthält nicht committete Änderungen."
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "unbekannter Stil '%s' für '%s' angegeben"
+
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
msgstr ""
"Project-Id-Version: git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-08 04:57+0000\n"
-"PO-Revision-Date: 2023-11-11 10:00+0100\n"
+"POT-Creation-Date: 2024-02-16 19:18+0100\n"
+"PO-Revision-Date: 2024-02-16 19:19+0100\n"
"Last-Translator: Cédric Malard <c.malard-git@valdun.net>\n"
"Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n"
"Language: fr\n"
msgid "Unexpected option --output"
msgstr "Option --output inattendue"
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "paramètre de commande supplémentaire '%s'"
+
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Format d'archive inconnu '%s'"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "mauvais --attr-source ou GIT_ATTR_SOURCE"
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "fstat de '%s' impossible"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "impossible de lire %s"
+
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "Contenu mal cité dans le fichier '%s' : %s"
msgstr "impossible de rechercher l'objet commit pour '%s'"
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
-msgstr ""
-"la branche '%s' n'est pas totalement fusionnée.\n"
-"Si vous souhaitez réellement la supprimer, lancez 'git branch -D %s'"
+msgid "the branch '%s' is not fully merged"
+msgstr "la branche '%s' n'est pas complètement fusionnée"
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "Si vous souhaitez réellement la supprimer, lancez 'git branch -D %s'"
msgid "update of config-file failed"
msgstr "échec de la mise à jour du fichier de configuration"
msgid "new-branch"
msgstr "nouvelle branche"
-msgid "new unparented branch"
-msgstr "nouvelle branche sans parent"
+msgid "new unborn branch"
+msgstr "nouvelle branche non née"
msgid "update ignored files (default)"
msgstr "mettre à jour les fichiers ignorés (par défaut)"
"clean.requireForce à true par défaut et ni -i, -n ou -f fourni ; refus de "
"nettoyer"
-msgid "-x and -X cannot be used together"
-msgstr "-x et -X ne peuvent pas être utilisés ensemble"
-
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<options>] [--] <dépôt> [<répertoire>]"
msgid "separate git dir from working tree"
msgstr "séparer le répertoire git de la copie de travail"
+msgid "specify the reference format to use"
+msgstr "spécifier le format de réference à utiliser"
+
msgid "key=value"
msgstr "clé=valeur"
msgid "You must specify a repository to clone."
msgstr "Vous devez spécifier un dépôt à cloner."
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"--bundle-uri est incompatible avec --depth, --shallow-since, et --shallow-"
-"exclude"
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "Format de stockage de réf inconnu '%s'"
#, c-format
msgid "repository '%s' does not exist"
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir <rép>] [--append]\n"
" [--split[=<stratégie>]] [--reachable | --stdin-packs "
"| --stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <options de division>"
+" <options-de-division>"
msgid "dir"
msgstr "répertoire"
msgid "unable to read tree (%s)"
msgstr "impossible de lire l'arbre (%s)"
+#, c-format
+msgid "unable to read tree %s"
+msgstr "impossible de lire l'arbre %s"
+
#, c-format
msgid "unable to grep from object of type %s"
msgstr "impossible de faire un grep sur un objet de type %s"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "COLLISION SHA1 TROUVÉE AVEC %s !"
-#, c-format
-msgid "unable to read %s"
-msgstr "impossible de lire %s"
-
#, c-format
msgid "cannot read existing object info %s"
msgstr "impossible de lire l'information existante de l'objet %s"
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=<répertoire-modèle>]\n"
-" [--separate-git-dir <rép-git>] [--object-format=<format>]\\n\"\n"
-" [-b <nom-de-branche> | --initial-branch=<nom-de-branche>]\\n\"\n"
+"git init [-q | --quiet] [--bare] [--template=<répertoire-de-modèles>]\n"
+" [--separate-git-dir <rép-git>] [--object-format=<format>]\n"
+" [--ref-format=<format>]\n"
+" [-b <nom-de-branch> | --initial-branch=<nom-de-branche>]\n"
" [--shared[=<permissions>]] [<répertoire>]"
msgid "permissions"
"git merge-file [<options>] [-L <nom1> [-L <orig> [-L <nom2>]]] <fichier1> "
"<fichier-orig> <fichier2>"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"l'option diff-algorithm accept \"myers\", \"minimal\", \"patience\" et "
+"\"histogram\""
+
msgid "send results to standard output"
msgstr "envoyer les résultats sur la sortie standard"
msgid "for conflicts, use a union version"
msgstr "pour les conflits, utiliser l'ensemble des versions"
+msgid "<algorithm>"
+msgstr "<algorithme>"
+
+msgid "choose a diff algorithm"
+msgstr "choisir un algorithme de différence"
+
msgid "for conflicts, use this marker size"
msgstr "pour les conflits, utiliser cette taille de marqueur"
msgid "unknown strategy option: -X%s"
msgstr "option de stratégie inconnue : -X%s"
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base est incompatible avec --stdin"
-
#, c-format
msgid "malformed input line: '%s'."
msgstr "ligne en entrée malformée : '%s'."
msgid "inconsistency with delta count"
msgstr "inconsistance dans le compte de delta"
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "valeur invalide de pack.allowPackReuse : '%s'"
+
#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Total %<PRIu32> (delta %<PRIu32>), réutilisés %<PRIu32> (delta %<PRIu32>), "
-"réutilisés du pack %<PRIu32>"
+"réutilisés du paquet %<PRIu32> (depuis %<PRIuMAX>)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
msgid "switch `C' expects a numerical value"
msgstr "l'option `C' attend un valeur numérique"
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"les options d'application sont incompatibles avec rebase.autoSquash. "
-"Considérez l'ajout de --no-autosquash"
-
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"no-rebase-merges"
msgid "only one pattern can be given with -l"
msgstr "-l n'accepte qu'un motifs"
+msgid "need some commits to replay"
+msgstr "commits requis pour pouvoir rejouer"
+
+msgid "--onto and --advance are incompatible"
+msgstr "--onto et --advance sont incompatibles"
+
+msgid "all positive revisions given must be references"
+msgstr "toutes les révisions positives fournies doivent être des références"
+
+msgid "argument to --advance must be a reference"
+msgstr "l'argument de --advance doit être une référence"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"impossible d'avancer la cible avec des sources multiples parce l'ordre ne "
+"serait pas total"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr ""
+"impossible de déterminer implicitement s'il y a une opération --advance ou --"
+"onto"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"impossible d'avancer la cible sur des branches sources multiples parce que "
+"l'ordre ne serait pas total"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "impossible de déterminer implicitement une base correcte pour --onto"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <nouvelle-base> | --advance "
+"<branche>) <plage-de-révision>..."
+
+msgid "make replay advance given branch"
+msgstr "faire rejouer en avançant la branche indiquée"
+
+msgid "replay onto given commit"
+msgstr "rejouer par-dessus le commit indiqué"
+
+msgid "advance all branches contained in revision-range"
+msgstr "avancer toutes les branches contenues dans la plage-de-révisions"
+
+msgid "option --onto or --advance is mandatory"
+msgstr "une option --onto ou --advance est obligatoire"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"certaines options de parcours de révs seront surchargées car le bit '%s' "
+"dans 'struct rev_info' sera forcé"
+
+msgid "error preparing revisions"
+msgstr "erreur lors de la préparation des révisions"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "rejouer jusqu'au commit racine n'est pas encore géré !"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "rejouer des commits de fusion n'est pas encore géré !"
+
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr ""
msgid "unknown mode for --abbrev-ref: %s"
msgstr "mode inconnu pour --abbrev-ref : %s"
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden ne peut être utilisé avec --branches"
-
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden ne peut pas être utilisé avec --tags"
-
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden ne peut pas être utilisé avec --remotes"
-
msgid "this operation must be run in a work tree"
msgstr "cette opération doit être effectuée dans un arbre de travail"
"afficher les références de l'entrée standard qui ne sont pas dans le dépôt "
"local"
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "les options '%s', '%s' et '%s' sont mutuellement exclusives"
-
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
"rules) [<options>]"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
"Si vous vouliez créer un arbre-de-travail contenant une nouvelle branche\n"
-"orpheline (une branche sans commit) pour ce dépôt, vous pouvez le faire\n"
+"non-née (une branche sans commit) pour ce dépôt, vous pouvez le faire\n"
"en utilisant le drapeau --orphan :\n"
"\n"
" git worktree add --orphan -b %s %s\n"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
"Si vous vouliez créer un arbre-de-travail contenant une nouvelle branche\n"
-"orpheline (une branche sans commit) pour ce dépôt, vous pouvez le faire\n"
+"non-née (une branche sans commit) pour ce dépôt, vous pouvez le faire\n"
"en utilisant le drapeau --orphan :\n"
"\n"
" git worktree add --orphan %s\n"
msgid "initializing"
msgstr "initialisation"
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "impossible de trouver l'arbre-de-travail créé '%s'"
+
#, c-format
msgid "Preparing worktree (new branch '%s')"
msgstr "Préparation de l'arbre de travail (nouvelle branche '%s')"
"on arrête ; utilisez 'add -f' pour passe outre ou récupérer le distant en "
"premier"
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "'%s' et '%s' ne peuvent pas être utilisées ensemble"
-
msgid "checkout <branch> even if already checked out in other worktree"
msgstr ""
"extraire la <branche> même si elle est déjà extraite dans une autre copie de "
msgid "create or reset a branch"
msgstr "créer ou réinitialiser une branche"
-msgid "create unborn/orphaned branch"
-msgstr "créer une branche non née/orpheline"
+msgid "create unborn branch"
+msgstr "créer une branche non née"
msgid "populate the new working tree"
msgstr "remplissage de la nouvelle copie de travail"
msgstr "les options '%s', '%s' et '%s' ne peuvent pas être utilisées ensemble"
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "les options '%s' et '%s' ne peuvent pas être utilisées ensemble"
-
-msgid "<commit-ish>"
-msgstr "<commit-esque>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr ""
+"l'option '%s' et des commit-esques ne peuvent pas être utilisés ensemble"
msgid "added with --lock"
msgstr "ajouté avec --lock"
msgid "Create, list, delete refs to replace objects"
msgstr "Créer, lister, supprimer des référence pour remplacer des objets"
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"EXPÉRIMENTAL ; rejoue des commits sur une nouvelle base, fonctionne aussi "
+"avec les dépôts nus"
+
msgid "Generates a summary of pending changes"
msgstr "Générer une résumé des modifications en attentes"
msgid "commit-graph file is too small"
msgstr "le graphe de commit est trop petit"
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr ""
+"le tronçon de distribution d'oid du graphe de commit n'a pas la bonne taille"
+
+msgid "commit-graph fanout values out of order"
+msgstr "les valeurs de distribution du graphe de commit sont désordonnées"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr ""
+"le tronçon de recherche de l'OID du graphe de commits n'a pas la bonne taille"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "le tronçon de données du graphe de commit n'a pas la bonne taille"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr "le tronçon des générations du graphe de commit n'a pas la bonne taille"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr ""
+"le tronçon d'index des chemins modifiés du graphe de commit est trop petit"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"tronçon de chemin modifié dans le fichier de graphe de commits trop petit "
+"((%<PRIuMAX> < %<PRIuMAX>)) ignoré"
+
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgstr ""
msgid "commit-graph file is too small to hold %u chunks"
msgstr "le graphe de commit est trop petit pour contenir %u tronçons"
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr ""
+"le tronçon de distribution des OID requis du graphe de commits est manquant "
+"ou corrompu"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr ""
+"le tronçon de recherche OID requis par le graphe de commits est manquant ou "
+"corrompu"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr ""
+"le tronçon d'étalement OID requis par le graphe de commits est manquant ou "
+"corrompu"
+
msgid "commit-graph has no base graphs chunk"
msgstr "le graphe de commit n'a pas de tronçon de graphes de base"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "nombre de commits dans le graphe de base trop haut : %<PRIuMAX>"
+msgid "commit-graph chain file too small"
+msgstr "la chaine du graphe de commit est trop petite"
+
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr ""
"les données de génération de débordement du graphe de commits sont trop "
"petites"
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "pointeur hors-gamme d'arêtes supplémentaires du graphe de commits"
+
msgid "Loading known commits in commit graph"
msgstr "Lecture des commits connus dans un graphe de commit"
msgstr ""
"Valeur inconnue pour la variable de configuration 'diff.submodule' : '%s'"
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "valeur inconnue pour la config '%s' : %s"
+
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "mode invalide '%s' dans --color-moved-ws"
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"l'option diff-algorithm accept \"myers\", \"minimal\", \"patience\" et "
-"\"histogram\""
-
#, c-format
msgid "invalid argument to %s"
msgstr "argument invalide pour %s"
msgid "output only the last line of --stat"
msgstr "afficher seulement la dernière ligne de --stat"
-msgid "<param1,param2>..."
-msgstr "<param1,param2>..."
+msgid "<param1>,<param2>..."
+msgstr "<param1>,<param2>..."
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
msgid "synonym for --dirstat=cumulative"
msgstr "synonyme pour --dirstat=cumulative"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "synonyme pour --dirstat=files,param1,param2..."
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "synonyme pour --dirstat=files,<param1>,<param2>..."
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr ""
msgstr ""
"générer un diff en utilisant l'algorithme de différence \"histogramme\""
-msgid "<algorithm>"
-msgstr "<algorithme>"
-
-msgid "choose a diff algorithm"
-msgstr "choisir un algorithme de différence"
-
msgid "<text>"
msgstr "<texte>"
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "l'étalement de l'OID d'index multi-paquet n'a pas la bonne taille"
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"étalement oid en désordre : étalement[%d] = %<PRIx32> > %<PRIx32> = "
+"étalement[%d]"
+
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr ""
"le tronçon de recherche de l'OID d'index multi-paquet n'a pas la bonne taille"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "mauvais pack-int-id : %u (%u paquets au total)"
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "le MIDX ne contient pas de tronçon BTMP"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "impossible d'ouvrir le paquet bitmappé %<PRIu32>"
+
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr ""
"l'index multi-paquet stocke un décalage en 64-bit, mais off_t est trop petit"
msgid "Looking for referenced packfiles"
msgstr "Recherche de fichiers paquets référencés"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr ""
-"étalement oid en désordre : étalement[%d] = %<PRIx32> > %<PRIx32> = "
-"étalement[%d]"
-
msgid "the midx contains no oid"
msgstr "le midx ne contient aucun oid"
msgid "could not open pack %s"
msgstr "impossible d'ouvrir le paquet '%s'"
+msgid "could not determine MIDX preferred pack"
+msgstr "impossible de déterminer le paquet préféré de MIDX"
+
#, c-format
msgid "preferred pack (%s) is invalid"
msgstr "le paquet préféré (%s) est invalide"
msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
msgstr "bitmap ewah corrompue : entête tronqué pour la bitmap du commit '%s'"
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr "impossible de charger le paquet : '%s', pack-reuse désactivé"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "objet '%s' non trouvé dans les bitmaps de type"
msgstr ""
"le tronçon d'index inversé de l'index multi-paquet n'a pas la bonne taille"
+msgid "could not determine preferred pack"
+msgstr "impossible de déterminer le paquet préféré"
+
msgid "cannot both write and verify reverse index"
msgstr "impossible de lire et vérifier à la fois l'index inverse"
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"
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s est incompatible avec %s"
-
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgstr "option ambigüe : %s (devrait être --%s%s ou --%s%s)"
msgid "unable to add '%s' to index"
msgstr "impossible d'ajouter '%s' à l'index"
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "fstat de '%s' impossible"
-
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgstr "'%s' existe à la fois comme un fichier et un répertoire"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "impossible de traiter '%s' et '%s' en même temps"
-#, c-format
-msgid "could not remove reference %s"
-msgstr "impossible de supprimer la référence %s"
-
#, c-format
msgid "could not delete reference %s: %s"
msgstr "impossible de supprimer la référence %s : %s"
"Neither worked, so we gave up. You must fully qualify the ref."
msgstr ""
"La destination que vous avez fournie n'est pas un nom de référence complète\n"
-"(c'est-à-dire commençant par \"ref/\"). Essai d'approximation par :\n"
+"(c'est-à-dire commençant par \"refs/\"). Essai d'approximation par :\n"
"\n"
"- Recherche d'une référence qui correspond à '%s' sur le serveur distant.\n"
"- Vérification si la <source> en cours de poussée ('%s')\n"
msgstr ""
"Un remisage automatique existe ; création d'une nouvelle entrée de remisage."
+msgid "autostash reference is a symref"
+msgstr "la référence d'auto-remisage est une symref"
+
msgid "could not detach HEAD"
msgstr "impossible de détacher HEAD"
msgid "invalid initial branch name: '%s'"
msgstr "nom de branche initiale invalide : '%s'"
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-initialisation : --initial-branch=%s ignoré"
+
#, c-format
msgid "unable to handle file type %d"
msgstr "impossible de traiter le fichier de type %d"
msgid "attempt to reinitialize repository with different hash"
msgstr "essai de réinitialisation du dépôt avec une empreinte différente"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr ""
+"essai de réinitialisation du dépôt avec un format de stockage de références "
+"différent"
+
#, c-format
msgid "%s already exists"
msgstr "%s existe déjà"
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-initialisation : --initial-branch=%s ignoré"
-
#, c-format
msgid "Reinitialized existing shared Git repository in %s%s\n"
msgstr "Dépôt Git existant partagé réinitialisé dans %s%s\n"
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 "unhandled options"
-msgstr "options non gérées"
-
-msgid "error preparing revisions"
-msgstr "erreur lors de la préparation des révisions"
-
#, c-format
msgid "commit %s is not marked reachable"
msgstr "le commit %s n'est pas marqué joignable"
msgid "invalid remote service path"
msgstr "chemin de service distant invalide"
-msgid "operation not supported by protocol"
-msgstr "option non supportée par le protocole"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "impossible de se connecter au sous-service %s"
msgid "support for protocol v2 not implemented yet"
msgstr "le support du protocole v2 n'est pas encore implanté"
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "valeur inconnue pour la config '%s' : %s"
-
#, c-format
msgid "transport '%s' not allowed"
msgstr "transport '%s' non permis"
msgstr ""
"impossible de récupérer la liste de bundle-uris annoncée par le serveur"
+msgid "operation not supported by protocol"
+msgstr "option non supportée par le protocole"
+
msgid "too-short tree object"
msgstr "objet arbre trop court"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "%s impossible : votre index contient des modifications non validées."
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "style inconnu '%s' pour '%s'"
+
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
msgid "Do you really want to send %s? [y|N]: "
msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : "
+#~ msgid "-x and -X cannot be used together"
+#~ msgstr "-x et -X ne peuvent pas être utilisés ensemble"
+
+#~ msgid ""
+#~ "--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
+#~ "exclude"
+#~ msgstr ""
+#~ "--bundle-uri est incompatible avec --depth, --shallow-since, et --shallow-"
+#~ "exclude"
+
+#~ msgid "--merge-base is incompatible with --stdin"
+#~ msgstr "--merge-base est incompatible avec --stdin"
+
+#~ msgid ""
+#~ "apply options are incompatible with rebase.autoSquash. Consider adding --"
+#~ "no-autosquash"
+#~ msgstr ""
+#~ "les options d'application sont incompatibles avec rebase.autoSquash. "
+#~ "Considérez l'ajout de --no-autosquash"
+
+#~ msgid "--exclude-hidden cannot be used together with --branches"
+#~ msgstr "--exclude-hidden ne peut être utilisé avec --branches"
+
+#~ msgid "--exclude-hidden cannot be used together with --tags"
+#~ msgstr "--exclude-hidden ne peut pas être utilisé avec --tags"
+
+#~ msgid "--exclude-hidden cannot be used together with --remotes"
+#~ msgstr "--exclude-hidden ne peut pas être utilisé avec --remotes"
+
+#, c-format
+#~ msgid "only one of '%s', '%s' or '%s' can be given"
+#~ msgstr "les options '%s', '%s' et '%s' sont mutuellement exclusives"
+
+#, c-format
+#~ msgid "'%s' and '%s' cannot be used together"
+#~ msgstr "'%s' et '%s' ne peuvent pas être utilisées ensemble"
+
+#, c-format
+#~ msgid "options '%s', and '%s' cannot be used together"
+#~ msgstr "les options '%s' et '%s' ne peuvent pas être utilisées ensemble"
+
+#~ msgid "<commit-ish>"
+#~ msgstr "<commit-esque>"
+
+#, c-format
+#~ msgid "%s is incompatible with %s"
+#~ msgstr "%s est incompatible avec %s"
+
+#, c-format
+#~ msgid "could not remove reference %s"
+#~ msgstr "impossible de supprimer la référence %s"
+
+#~ msgid "unhandled options"
+#~ msgstr "options non gérées"
+
#, c-format
#~ msgid "options '%s=%s' and '%s=%s' cannot be used together"
#~ msgstr ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-12 20:04+0700\n"
-"PO-Revision-Date: 2023-11-12 20:30+0700\n"
+"POT-Creation-Date: 2024-02-16 09:36+0700\n"
+"PO-Revision-Date: 2024-02-16 10:45+0700\n"
"Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n"
"Language-Team: Indonesian\n"
"Language: id\n"
msgstr "tanda kutip tak ditutup"
#: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c
-#: builtin/receive-pack.c builtin/tag.c
+#: builtin/receive-pack.c builtin/tag.c t/helper/test-pkt-line.c
msgid "too many arguments"
msgstr "terlalu banyak argumen"
msgstr "opsi abai spasi putih tidak dikenal '%s'"
#: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c
-#: builtin/checkout.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.c
-#: builtin/pack-objects.c builtin/push.c builtin/rebase.c builtin/repack.c
-#: builtin/reset.c builtin/rev-list.c builtin/show-branch.c builtin/stash.c
+#: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c
+#: builtin/describe.c builtin/diff-tree.c builtin/difftool.c
+#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c
+#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c
+#: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c
+#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-list.c
+#: builtin/rev-parse.c builtin/show-branch.c builtin/stash.c
#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c
#: range-diff.c revision.c
#, c-format
msgid "Unexpected option --output"
msgstr "Opsi --output tak diharapkan"
+#: archive.c
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "parameter konfigurasi tambahan: '%s'"
+
#: archive.c
#, c-format
msgid "Unknown archive format '%s'"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "--attr-source atau GIT_ATTR_SOURCE jelek"
+#: attr.c read-cache.c
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "tidak dapat men-stat '%s'"
+
+#: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c
+#: builtin/pack-objects.c combine-diff.c rerere.c
+#, c-format
+msgid "unable to read %s"
+msgstr "tidak dapat membaca %s"
+
#: bisect.c
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "tindakan jelek '%s' untuk '%s'"
#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c diff-merges.c gpg-interface.c ls-refs.c parallel-checkout.c
-#: sequencer.c setup.c
+#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c
+#: parallel-checkout.c sequencer.c setup.c
#, c-format
msgid "invalid value for '%s': '%s'"
msgstr "nilai tidak valid untuk '%s': '%s'"
msgid "applying to an empty history"
msgstr "menerapkan ke sebuah riwayat kosong"
-#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c
-#: t/helper/test-fast-rebase.c
+#: builtin/am.c builtin/commit.c builtin/merge.c builtin/replay.c sequencer.c
msgid "failed to write commit object"
msgstr "gagal menulis objek komit"
msgstr "n"
#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
-#: builtin/diagnose.c builtin/for-each-ref.c builtin/ls-files.c
-#: builtin/ls-tree.c builtin/replace.c builtin/tag.c builtin/verify-tag.c
+#: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c
+#: builtin/ls-files.c builtin/ls-tree.c builtin/replace.c builtin/tag.c
+#: builtin/verify-tag.c
msgid "format"
msgstr "format"
#: builtin/branch.c
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
-msgstr ""
-"cabang '%s' belum sepenuhnya tergabung.\n"
-"kalau Anda yakin ingin menghapusnya, jalankan 'git branch -D %s'"
+msgid "the branch '%s' is not fully merged"
+msgstr "cabang '%s' belum sepenuhnya digabungkan"
+
+#: builtin/branch.c
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "Jika anda yakin untuk menghapusnya, lakukan 'git branch -D %s'"
#: builtin/branch.c
msgid "update of config-file failed"
msgid "HEAD is now at"
msgstr "HEAD sekarang berada di"
-#: builtin/checkout.c builtin/clone.c t/helper/test-fast-rebase.c
+#: builtin/checkout.c builtin/clone.c
msgid "unable to update HEAD"
msgstr "tidak dapat memperbarui HEAD"
msgstr "cabang baru"
#: builtin/checkout.c
-msgid "new unparented branch"
-msgstr "cabang baru tanpa induk"
+msgid "new unborn branch"
+msgstr "cabang yatim baru"
#: builtin/checkout.c builtin/merge.c
msgid "update ignored files (default)"
msgid "you must specify path(s) to restore"
msgstr "Anda harus sebutkan jalur untuk dipulihkan"
-#: builtin/checkout.c builtin/clone.c builtin/remote.c
+#: builtin/checkout.c builtin/clone.c builtin/remote.c builtin/replay.c
#: builtin/submodule--helper.c builtin/worktree.c
msgid "branch"
msgstr "cabang"
"clean.requireForce asal ke true dan baik -i, -n, atau -f tidak diberikan; "
"menolak membersihkan"
-#: builtin/clean.c
-msgid "-x and -X cannot be used together"
-msgstr "-x dan -X tidak dapat digunakan bersamaan"
-
#: builtin/clone.c
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<opsi>] [--] <repo> [<direktori>]"
msgstr "buat klon dangkal sejak waktu yang disebutkan"
#: builtin/clone.c builtin/fetch.c builtin/pull.c builtin/rebase.c
+#: builtin/replay.c
msgid "revision"
msgstr "revisi"
msgid "separate git dir from working tree"
msgstr "pisahkan direktori git dari pohon kerja"
+#: builtin/clone.c builtin/init-db.c
+msgid "specify the reference format to use"
+msgstr "sebutkan format referensi untuk digunakan"
+
#: builtin/clone.c
msgid "key=value"
msgstr "kunci=nilai"
msgid "You must specify a repository to clone."
msgstr "Anda harus sebutkan repositori untuk diklon."
-#: builtin/clone.c
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"--bundle-uri tidak kompatibel dengan --depth, --shallow-since, dan --shallow-"
-"exclude"
+#: builtin/clone.c builtin/init-db.c setup.c
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "format penyimpanan referensi tidak dikenal '%s'"
#: builtin/clone.c
#, c-format
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir <direktori>] [--append]\n"
" [--split[=<strategi>]] [--reachable | --stdin-packs | "
"--stdin-commits]\n"
-" [--changed-paths] [--[no-]max-new-filters <n>] [--[-"
-"no-]progress]\n"
+" [--changed-paths] [--[no-]max-new-filters <n>] [--"
+"[no-]progress]\n"
" <opsi pemisahan>"
#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c
msgid "unable to read tree (%s)"
msgstr "tidak dapat membaca pohon (%s)"
+#: builtin/grep.c
+#, c-format
+msgid "unable to read tree %s"
+msgstr "tidak dapat membaca pohon %s"
+
#: builtin/grep.c
#, c-format
msgid "unable to grep from object of type %s"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "TUMBUKAN SHA1 DITEMUKAN DENGAN %s !"
-#: builtin/index-pack.c builtin/pack-objects.c
-#, c-format
-msgid "unable to read %s"
-msgstr "tidak dapat membaca %s"
-
#: builtin/index-pack.c
#, c-format
msgid "cannot read existing object info %s"
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=<direktori templat>]\n"
" [--separate-git-dir <direktori git>] [--object-format=<format>]\n"
+"\t [--ref-format=<format>]\n"
" [-b <nama cabang> | --initial-branch=<nama cabang>]\n"
" [--shared[=<perizinan>]] [<direktori>]"
"lacak evolusi rentang baris <awal>,<akhir> atau fungsi :<nama fungsi> dalam "
"<berkas>"
-#: builtin/log.c builtin/shortlog.c bundle.c
+#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c
#, c-format
msgid "unrecognized argument: %s"
msgstr "argumen tidak dikenal: %s"
"git merge-file [<opsi>] [-L <nama 1> [-L <asli> [-L <nama 2>]]] <berkas 1> "
"<berkas asli> <berkas 2>"
+#: builtin/merge-file.c diff.c
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"opsi diff-algorithm terima \"myers\", \"minimal\", \"patience\" dan "
+"\"histogram\""
+
#: builtin/merge-file.c
msgid "send results to standard output"
msgstr "kirim hasil ke keluaran standar"
msgid "for conflicts, use a union version"
msgstr "untuk konflik, gunakan versi bersatu"
+#: builtin/merge-file.c diff.c
+msgid "<algorithm>"
+msgstr "<algoritma>"
+
+#: builtin/merge-file.c diff.c
+msgid "choose a diff algorithm"
+msgstr "pilih algoritma diff"
+
#: builtin/merge-file.c
msgid "for conflicts, use this marker size"
msgstr "untuk konflik, gunakan ukuran penanda ini"
msgid "unknown strategy option: -X%s"
msgstr "opsi strategi tidak dikenal: -X%s"
-#: builtin/merge-tree.c
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base tidak kompatibel dengan --stdin"
-
#: builtin/merge-tree.c builtin/notes.c
#, c-format
msgid "malformed input line: '%s'."
msgid "Bad branch.%s.mergeoptions string: %s"
msgstr "Untai branch.%s.mergeoptions jelek: %s"
-#: builtin/merge.c builtin/stash.c merge-recursive.c
+#: builtin/merge.c merge-recursive.c
msgid "Unable to write index."
msgstr "Tidak dapat menulis indeks."
msgid "Not handling anything other than two heads merge."
msgstr "Tak tangani apapun selain penggabungan dua kepala."
-#: builtin/merge.c t/helper/test-fast-rebase.c
+#: builtin/merge.c
#, c-format
msgid "unable to write %s"
msgstr "tidak dapat menulis %s"
msgid "inconsistency with delta count"
msgstr "ketidakkonsistenan dengan hitungan delta"
+#: builtin/pack-objects.c
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "nilai pack.allowPackReuse tidak valid: '%s'"
+
#: builtin/pack-objects.c
#, c-format
msgid ""
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Total %<PRIu32> (delta %<PRIu32>), digunakan ulang %<PRIu32> (delta "
-"%<PRIu32>), pak yang digunakan ulang %<PRIu32>"
+"%<PRIu32>), pak yang digunakan ulang %<PRIu32> (dari %<PRIuMAX>)"
#: builtin/pack-redundant.c
msgid ""
msgstr ""
"Aksi --edit-todo hanya dapat digunakan selama pendasaran ulang interaktif."
-#: builtin/rebase.c t/helper/test-fast-rebase.c
+#: builtin/rebase.c
msgid "Cannot read HEAD"
msgstr "Tidak dapat membaca HEAD"
msgid "switch `C' expects a numerical value"
msgstr "tombol `C' harap nilai numerik"
-#: builtin/rebase.c
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"opsi penerapan tidak kompatibel dengan rebase.autoSquash. "
-"Pertimbangkanmenambahkan --no-autosquash"
-
#: builtin/rebase.c
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
"to delete them, use:"
msgstr[0] ""
-"Catatan: Sebuah cabang diluar hierarki refs/remotes tidak dihapus;\n"
+"Catatan: Sebuah cabang diluar hierarki refs/remotes/ tidak dihapus;\n"
"untuk menghapusnya, gunakan:"
msgstr[1] ""
-"Catatan: Beberapa cabang diluar hierarki refs/remotes tidak dihapus;\n"
+"Catatan: Beberapa cabang diluar hierarki refs/remotes/ tidak dihapus;\n"
"untuk menghapusnya, gunakan:"
#: builtin/remote.c
msgid "only one pattern can be given with -l"
msgstr "hanya satu pola yang dapat diberikan dengan -l"
+#: builtin/replay.c
+msgid "need some commits to replay"
+msgstr "butuh beberapa komit untuk dimainkan ulang"
+
+#: builtin/replay.c
+msgid "--onto and --advance are incompatible"
+msgstr "--onto dan --advance tidak kompatibel"
+
+#: builtin/replay.c
+msgid "all positive revisions given must be references"
+msgstr "semua revisi positif yang diberikan haruslah referensi"
+
+#: builtin/replay.c
+msgid "argument to --advance must be a reference"
+msgstr "argumen pada --advance harus sebuah referensi"
+
+#: builtin/replay.c
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"tidak dapat memajukan target dengan banyak sumber karena pengurutannya akan "
+"menjadi tidak jelas"
+
+#: builtin/replay.c
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr ""
+"tidak dapat menentukan secara tidak langsung apakah ini operasi --advance "
+"atau --onto"
+
+#: builtin/replay.c
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"tidak dapat memajukan target dengan banyak cabang sumber karena "
+"pengurutannya akan menjadi tidak jelas"
+
+#: builtin/replay.c
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "tidak dapat menentukan secara tidak langsung dasar untuk --onto"
+
+#: builtin/replay.c
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(EKSPERIMENTAL!) git replay ([--contained] --onto <dasar baru> | --advance "
+"<cabang>) <rentang revisi>..."
+
+#: builtin/replay.c
+msgid "make replay advance given branch"
+msgstr "buat pemainan ulang memajukan caban yang diberikan"
+
+#: builtin/replay.c
+msgid "replay onto given commit"
+msgstr "mainkan ulang pada komit yang diberikan"
+
+#: builtin/replay.c
+msgid "advance all branches contained in revision-range"
+msgstr "majukan semua cabang yang berada pada rentang komit"
+
+#: builtin/replay.c
+msgid "option --onto or --advance is mandatory"
+msgstr "opsi --onto atau --advance diwajibkan"
+
+#: builtin/replay.c
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"beberapa opsi jalan revisi akan ditimpa oleh karena bit '%s' di 'struct "
+"rev_info' akan dipaksakan"
+
+#: builtin/replay.c
+msgid "error preparing revisions"
+msgstr "kesalahan menyiapkan revisi"
+
+#: builtin/replay.c
+msgid "replaying down to root commit is not supported yet!"
+msgstr "memainkan ulang ke komit akar belum didukung!"
+
+#: builtin/replay.c
+msgid "replaying merge commits is not supported yet!"
+msgstr "memainkan ulang komit penggabungan belum didukung!"
+
#: builtin/rerere.c
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgid "unknown mode for --abbrev-ref: %s"
msgstr "mode untuk --abbrev-ref tidak dikenal: %s"
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden tidak dapat digunakan bersamaan dengan --branches"
-
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden tidak dapat digunakan bersamaan dengan --tags"
-
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden tidak dapat digunakan dengan --remotes"
-
#: builtin/rev-parse.c setup.c
msgid "this operation must be run in a work tree"
msgstr "operasi ini harus dijalankan di dalam pohon kerja"
"perlihatkan referensi dari masukan standar yang tidak ada dalam repositori "
"lokal"
-#: builtin/show-ref.c
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "hanya salah satu dari '%s', '%s', dan '%s' dapat diberikan"
-
#: builtin/sparse-checkout.c
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
#: builtin/worktree.c
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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"
#: builtin/worktree.c
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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"
msgid "initializing"
msgstr "menginisialisasi"
+#: builtin/worktree.c
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "tidak dapat menemukan pohon kerja yang dibuat '%s'"
+
#: builtin/worktree.c
#, c-format
msgid "Preparing worktree (new branch '%s')"
"ada, berhenti; gunakan 'add -f' untuk menimpa atau mengambil remote\n"
"terlebih dahulu"
-#: builtin/worktree.c
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "'%s' dan '%s' tidak dapat digunakan bersamaan"
-
#: builtin/worktree.c
msgid "checkout <branch> even if already checked out in other worktree"
msgstr ""
msgstr "buat atau setel ulang sebuah cabang"
#: builtin/worktree.c
-msgid "create unborn/orphaned branch"
+msgid "create unborn branch"
msgstr "buat cabang belum lahir/yatim"
#: builtin/worktree.c
#: builtin/worktree.c
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "Opsi '%s', dan '%s' tidak dapat digunakan bersamaan"
-
-#: builtin/worktree.c
-msgid "<commit-ish>"
-msgstr "<mirip-komit>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "opsi '%s' dan mirip-komit tidak dapat digunakan bersamaan"
#: builtin/worktree.c
msgid "added with --lock"
msgid "Create, list, delete refs to replace objects"
msgstr "Buat, daftar, hapus referensi untuk mengganti objek"
+#: command-list.h
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"EKSPERIMENTAL: Mainkan ulang komit pada dasar baru, dan juga bekerja pada "
+"repositori bare"
+
#: command-list.h
msgid "Generates a summary of pending changes"
msgstr "Buat ringkasan perubahan tertunda"
msgid "commit-graph file is too small"
msgstr "berkas grafik komit terlalu kecil"
+#: commit-graph.c
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "bingkah oid grafik komit kipas keluar salah ukuran"
+
+#: commit-graph.c
+msgid "commit-graph fanout values out of order"
+msgstr "nilai kipas keluar grafik komit tidak berurutan"
+
+#: commit-graph.c
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "bingkah OID pencarian grafik komit salah ukuran"
+
+#: commit-graph.c
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "bingkah data grafik komit salah ukuran"
+
+#: commit-graph.c
+msgid "commit-graph generations chunk is wrong size"
+msgstr "bingkah generasi grafik komit salah ukuran"
+
+#: commit-graph.c
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "bingkah indeks grafik komit jalur berubah terlalu kecil"
+
+#: commit-graph.c
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"mengabaikan bingkah jalur berubah yang terlalu kecil (%<PRIuMAX> < "
+"%<PRIuMAX>) di dalam berkas grafik komit"
+
#: commit-graph.c
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgid "commit-graph file is too small to hold %u chunks"
msgstr "berkas grafik komit terlalu kecil untuk menyimpan %u bingkah"
+#: commit-graph.c
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr ""
+"bingkah grafik komit OID kipas keluar yang diperlukan hilang atau rusak"
+
+#: commit-graph.c
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr "bingkah grafik komit OID pencarian yang diperlukan hilang atau rusak"
+
+#: commit-graph.c
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr "bingkah grafik komit data komit yang diperlukan hilang atau rusak"
+
#: commit-graph.c
msgid "commit-graph has no base graphs chunk"
msgstr "grafik komit tidak punya bingkah grafik dasar"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "jumlah komit pada grafik dasar terlalu tinggi: %<PRIuMAX>"
+#: commit-graph.c
+msgid "commit-graph chain file too small"
+msgstr "berkas rantai grafik komit terlalu kecil"
+
#: commit-graph.c
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgid "commit-graph overflow generation data is too small"
msgstr "data generasi luapan grafik komit terlalu kecil"
+#: commit-graph.c
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "penunjuk tepi tambahan grafik komit di luar batas"
+
#: commit-graph.c
msgid "Loading known commits in commit graph"
msgstr "Memuat komit yang dikenal di grafik komit"
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "Nilai tidak dikenal untuk variabel konfigurasi 'diff.submodule': '%s'"
+#: diff.c transport.c
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "nilai tidak dikenal untuk konfigurasi '%s': %s"
+
#: diff.c
#, c-format
msgid ""
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "mode tidak valid '%s' dalam --color-moved-ws"
-#: diff.c
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"opsi diff-algorithm terima \"myers\", \"minimal\", \"patience\" dan "
-"\"histogram\""
-
#: diff.c
#, c-format
msgid "invalid argument to %s"
msgstr "keluarkan hanya baris terakhir --stat"
#: diff.c
-msgid "<param1,param2>..."
-msgstr "<parameter 1,parameter 2>..."
+msgid "<param1>,<param2>..."
+msgstr "<parameter 1>,<parameter 2>..."
#: diff.c
msgid ""
msgstr "sinonim untuk --dirstat=cumulative"
#: diff.c
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "sinonim untuk --dirstat=files,param1,param2..."
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "sinonim untuk --dirstat=files,<parameter 1>,<parameter 2>..."
#: diff.c
msgid "warn if changes introduce conflict markers or whitespace errors"
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "buat diff menggunakan algoritma \"diff histogram\""
-#: diff.c
-msgid "<algorithm>"
-msgstr "<algoritma>"
-
-#: diff.c
-msgid "choose a diff algorithm"
-msgstr "pilih algoritma diff"
-
#: diff.c
msgid "<text>"
msgstr "<teks>"
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "OID kipas-keluar indeks multipak salah ukuran"
+#: midx.c
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"kipas-keluar oid tidak berurutan: fanout[%d] =%<PRIx32> > %<PRIx32> = "
+"fanout[%d]"
+
#: midx.c
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "bingkah pencarian OID kipas-keluar indeks multipak salah ukuran"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "pack-int-id jelek: %u (total pak %u)"
+#: midx.c
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX tidak berisi bingkah BTMP"
+
+#: midx.c
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "tidak dapat membuka pak terbitmap %<PRIu32>"
+
#: midx.c
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr "indeks multipak simpan offset 64-bit, tapi off_t terlalu kecil"
msgid "Looking for referenced packfiles"
msgstr "Mencari berkas pak yang direferensikan"
-#: midx.c
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr ""
-"kipas-keluar oid tidak berurutan: fanout[%d] =%<PRIx32> > %<PRIx32> = "
-"fanout[%d]"
-
#: midx.c
msgid "the midx contains no oid"
msgstr "midx tidak berisi oid"
msgid "could not open pack %s"
msgstr "tidak dapat membuka '%s'"
+#: pack-bitmap.c t/helper/test-read-midx.c
+msgid "could not determine MIDX preferred pack"
+msgstr "tidak dapat menentukan pak MIDX terpilih"
+
#: pack-bitmap.c
#, c-format
msgid "preferred pack (%s) is invalid"
msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
msgstr "bitmap ewah rusak: kepala terpotong untuk bitmap komit \"%s\""
+#: pack-bitmap.c
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr "tidak dapat memuat pak: '%s', mematikan penggunaan ulang pak"
+
#: pack-bitmap.c
#, c-format
msgid "object '%s' not found in type bitmaps"
msgid "multi-pack-index reverse-index chunk is the wrong size"
msgstr "bingkah indeks balik multipak salah ukuran"
+#: pack-revindex.c
+msgid "could not determine preferred pack"
+msgstr "tidak dapat menentukan pak terpilih"
+
#: pack-write.c
msgid "cannot both write and verify reverse index"
msgstr "tidak dapat kedua-duanya menulis dan memverifikasi indeks balik"
"%s mengharapkan nilai bilangan bulat non negatif dengan akhiran opsional k/m/"
"g"
-#: parse-options.c
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s tidak kompatibel dengan %s"
-
#: parse-options.c
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgid "unable to add '%s' to index"
msgstr "tidak dapat menambahkan '%s' ke indeks"
-#: read-cache.c
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "tidak dapat men-stat '%s'"
-
#: read-cache.c
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "tidak dapat memproses '%s' dan '%s' pada waktu yang bersamaan"
-#: refs/files-backend.c
-#, c-format
-msgid "could not remove reference %s"
-msgstr "tidak dapat menghapus referensi %s"
-
-#: refs/files-backend.c refs/packed-backend.c
+#: refs.c
#, c-format
msgid "could not delete reference %s: %s"
msgstr "tidak dapat menghapus referensi %s: %s"
-#: refs/files-backend.c refs/packed-backend.c
+#: refs.c
#, c-format
msgid "could not delete references: %s"
msgstr "tidak dapat menghapus referensi: %s"
msgstr ""
"Tujuan yang Anda berikan bukan nama referensi penuh (seperti \n"
"dimulai dengan \"refs/\"). Kami mencoba menebak maksud Anda dengan:\n"
-"- Cari referensi yang cocok dengan '%s' pada sisi remote.\n"
-"- Perika apakah <src> yang sedang didorong ('%s') adalah \n"
-" referensi pada \"refs/{heads,tags}\". Bila demikian kami \n"
+"- mencari referensi yang cocok dengan '%s' pada sisi remote.\n"
+"- memeriksa apakah <src> yang sedang didorong ('%s') adalah \n"
+" referensi pada \"refs/{heads,tags}/\". Bila demikian kami \n"
" menambahkan awalan refs/{heads,tags}/ yang bersesuaian pada sisi \n"
" remote.\n"
"\n"
msgid "corrupt author: missing date information"
msgstr "pengarang rusak: informasi tanggal hilang"
-#: sequencer.c t/helper/test-fast-rebase.c
+#: sequencer.c
#, c-format
msgid "could not update %s"
msgstr "tidak dapat memperbarui %s"
msgid "Autostash exists; creating a new stash entry."
msgstr "Stase otomatis sudah ada; membuat entri stase baru."
+#: sequencer.c
+msgid "autostash reference is a symref"
+msgstr "referensi autostase itu referensi simbolik"
+
#: sequencer.c
msgid "could not detach HEAD"
msgstr "tidak dapat melepas HEAD"
msgid "invalid initial branch name: '%s'"
msgstr "nama cabang asal salah: '%s'"
+#: setup.c
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init: --initial-branch=%s diabaikan"
+
#: setup.c
#, c-format
msgid "unable to handle file type %d"
msgstr "mencoba menginisialisasi ulang repositori dengan hash yang berbeda"
#: setup.c
-#, c-format
-msgid "%s already exists"
-msgstr "%s sudah ada"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr ""
+"mencoba menginisialisasi ulang repositori dengan format penyimpanan "
+"referensi yang berbeda"
#: setup.c
#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init: --initial-branch=%s diabaikan"
+msgid "%s already exists"
+msgstr "%s sudah ada"
#: setup.c
#, c-format
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-fast-rebase.c
-msgid "unhandled options"
-msgstr "opsi tak tertangani"
-
-#: t/helper/test-fast-rebase.c
-msgid "error preparing revisions"
-msgstr "kesalahan menyiapkan revisi"
-
#: t/helper/test-reach.c
#, c-format
msgid "commit %s is not marked reachable"
msgid "invalid remote service path"
msgstr "jalur layanan remote tidak valid"
-#: transport-helper.c transport.c
-msgid "operation not supported by protocol"
-msgstr "operasi tidak didukung oleh protokol"
-
#: transport-helper.c
#, c-format
msgid "can't connect to subservice %s"
msgid "support for protocol v2 not implemented yet"
msgstr "dukungan untuk protokol v2 belum diterapkan"
-#: transport.c
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "nilai tidak dikenal untuk konfigurasi '%s': %s"
-
#: transport.c
#, c-format
msgid "transport '%s' not allowed"
msgid "could not retrieve server-advertised bundle-uri list"
msgstr "tidak dapat menerima daftar bundle-uri teriklankan server"
+#: transport.c
+msgid "operation not supported by protocol"
+msgstr "operasi tidak didukung oleh protokol"
+
#: tree-walk.c
msgid "too-short tree object"
msgstr "objek pohon terlalu pendek"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "tidak dapat %s: indeks Anda berisi perubahan yang belum dikomit."
+#: xdiff-interface.c
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "nilai gaya tidak dikenal '%s' diberikan untuk '%s'"
+
#: git-merge-octopus.sh git-merge-resolve.sh
msgid ""
"Error: Your local changes to the following files would be overwritten by "
# Swedish translations for Git.
-# Copyright (C) 2010-2023 Peter Krefting <peter@softwolves.pp.se>
+# Copyright (C) 2010-2024 Peter Krefting <peter@softwolves.pp.se>
# This file is distributed under the same license as the Git package.
-# Peter Krefting <peter@softwolves.pp.se>, 2010-2023.
+# Peter Krefting <peter@softwolves.pp.se>, 2010-2024.
#
msgid ""
msgstr ""
-"Project-Id-Version: git 2.43.0\n"
+"Project-Id-Version: git 2.44.0\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-09 14:12+0100\n"
-"PO-Revision-Date: 2023-11-09 14:28+0100\n"
+"POT-Creation-Date: 2024-02-16 07:58+0100\n"
+"PO-Revision-Date: 2024-02-16 07:59+0100\n"
"Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
"Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
msgid "Unexpected option --output"
msgstr "Oväntad flagga --output"
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "falsk konfigureringsparameter: ”%s”"
+
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Okänt arkivformat ”%s”"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "felaktig --attr-source eller GIT_ATTR_SOURCE"
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "kan inte ta status på ”%s”"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "kunde inte läsa %s"
+
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "Felaktigt citerat innehåll i filen ”%s”: %s"
msgstr "visa inte objektnamn för gränsincheckningar (Standard: av)"
msgid "do not treat root commits as boundaries (Default: off)"
-msgstr "vehandla inte rotincheckningar som gränser (Standard: av)"
+msgstr "behandla inte rotincheckningar som gränser (Standard: av)"
msgid "show work cost statistics"
msgstr "visa statistik över arbetskostnad"
msgstr "kunde inte slå upp incheckningsobjekt för ”%s”"
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
-msgstr ""
-"grenen ”%s” har inte slagits samman i sin helhet.\n"
-"Om du är säker på att du vill ta bort den, kör ”git branch -D %s”"
+msgid "the branch '%s' is not fully merged"
+msgstr "grenen ”%s” har inte slagits samman i sin helhet"
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "Om du är säker på att du vill ta bort den, kör ”git branch -D %s”"
msgid "update of config-file failed"
msgstr "misslyckades uppdatera konfigurationsfil"
msgid "new-branch"
msgstr "ny-gren"
-msgid "new unparented branch"
-msgstr "ny gren utan förälder"
+msgid "new unborn branch"
+msgstr "ny ofödd gren"
msgid "update ignored files (default)"
msgstr "uppdatera ignorerade filer (standard)"
"clean.requireForce har standardvärdet true och varken -i, -n eller -f "
"angavs; vägrar städa"
-msgid "-x and -X cannot be used together"
-msgstr "-x och -X kan inte användas samtidigt"
-
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<flaggor>] [--] <arkiv> [<kat>]"
msgid "separate git dir from working tree"
msgstr "separera gitkatalogen från arbetskatalogen"
+msgid "specify the reference format to use"
+msgstr "använd referensformatet som ska användas"
+
msgid "key=value"
msgstr "nyckel=värde"
msgid "You must specify a repository to clone."
msgstr "Du måste ange ett arkiv att klona."
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"--bundle-uri är inkompatibelt med --depth, --shallow-since och --shallow-"
-"exclude"
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "okänt format för lagring av referenser ”%s”"
#, c-format
msgid "repository '%s' does not exist"
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir <kat>] [--append]\n"
" [--split[=<strategi>]] [--reachable | --stdin-packs | "
msgid "unable to read tree (%s)"
msgstr "kunde inte läsa träd (%s)"
+#, c-format
+msgid "unable to read tree %s"
+msgstr "kunde inte läsa trädet %s"
+
#, c-format
msgid "unable to grep from object of type %s"
msgstr "kunde inte ”grep” från objekt av typen %s"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "SHA1-KOLLISION UPPTÄCKT VID %s !"
-#, c-format
-msgid "unable to read %s"
-msgstr "kunde inte läsa %s"
-
#, c-format
msgid "cannot read existing object info %s"
msgstr "kan inte läsa information om befintligt objekt %s"
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=<mallkatalog>]\n"
" [--separate-git-dir <git-kat>] [--object-format=<format>]\n"
+" [--ref-format=<format>]\n"
" [-b <grennamn> | --initial-branch=<grennamn>]\n"
" [--shared[=<behörigheter>]] [<katalog>]"
"git merge-file [<alternativ>] [-L <namn1> [-L <orig> [-L <namn2>]]] <fil1> "
"<origfil> <fil2>"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"flaggan diff-algorithm godtar ”myers”, ”minimal”, ”patience” och ”histogram”"
+
msgid "send results to standard output"
msgstr "sänd resultat till standard ut"
msgid "for conflicts, use a union version"
msgstr "för konflikter, använd en förenad version"
+msgid "<algorithm>"
+msgstr "<algoritm>"
+
+msgid "choose a diff algorithm"
+msgstr "välj en diff-algoritm"
+
msgid "for conflicts, use this marker size"
msgstr "för konflikter, använd denna markörstorlek"
msgid "unknown strategy option: -X%s"
msgstr "okänd strategiflagga: -X%s"
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base är inkompatibel med --stdin"
-
#, c-format
msgid "malformed input line: '%s'."
msgstr "felaktig indatarad: ”%s”."
msgid "inconsistency with delta count"
msgstr "deltaräknaren är inkonsekvent"
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "felaktigt värde för pack.allowPackReuse: ”%s”"
+
#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Totalt %<PRIu32> (delta %<PRIu32>), återanvände %<PRIu32> (delta %<PRIu32>), "
-"paket-återanvända %<PRIu32>"
+"paket-återanvända %<PRIu32> (från %<PRIuMAX>)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
msgid "switch `C' expects a numerical value"
msgstr "flaggan ”C” förväntar ett numeriskt värde"
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"argument för ”apply” är inkompatibla med rebase.autoSquash. Överväg att "
-"lägga till --no-autosquash"
-
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"no-rebase-merges"
msgid "only one pattern can be given with -l"
msgstr "endast ett mönster kan anges med -l"
+msgid "need some commits to replay"
+msgstr "behöver några incheckningar för omspelning"
+
+msgid "--onto and --advance are incompatible"
+msgstr "--onto och --advance kan inte kombineras"
+
+msgid "all positive revisions given must be references"
+msgstr "alla positiva revisioner som anges måste vara referenser"
+
+msgid "argument to --advance must be a reference"
+msgstr "argumentet till --advance måste vara en referens"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"kan inte flytta målet framåt när det finns flera källor eftersom ordningen "
+"inte kan fastställas"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr ""
+"kan inte avgöra om den underförstådda processen är --advance eller --onto"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"kan inte flytta målet framåt när det finns flera källgrenar eftersom "
+"ordningen inte kan fastställas"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "kan inte avgöra den underförstådda basen för --onto"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(EXPERIMENTELLT!) git replay ([--contained] --onto <nybas> | --advance "
+"<gren>) <revisions-intervall>..."
+
+msgid "make replay advance given branch"
+msgstr "låt omspelningen flytta den givna grenen framåt"
+
+msgid "replay onto given commit"
+msgstr "spela om ovanpå en given incheckning"
+
+msgid "advance all branches contained in revision-range"
+msgstr "flytta alla grenar som finns i revisionsintervallet framåt"
+
+msgid "option --onto or --advance is mandatory"
+msgstr "flaggan --onto eller --advance måste anges"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"några flaggor för revisionstraversering kommer överstyras eftersom ”%s”-"
+"biten i ”struct rev_info” kommer att tvingas"
+
+msgid "error preparing revisions"
+msgstr "fel när revisioner skulle förberedas"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "kan ännu inte spela om hela vägen ned till rotincheckningen!"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "kan ännu inte spela om sammanslagningsincheckningar!"
+
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr ""
msgid "unknown mode for --abbrev-ref: %s"
msgstr "okänt läge för --abbrev-ref: %s"
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden kan endast användas tillsammans med --branches"
-
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden kan kan inte användas tillsammans med --tags"
-
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden kan kan inte användas tillsammans med --remotes"
-
msgid "this operation must be run in a work tree"
msgstr "funktionen måste köras i en arbetskatalog"
msgid "show refs from stdin that aren't in local repository"
msgstr "visa referenser från standard in som inte finns i lokalt arkiv"
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "endast en av ”%s”, ”%s” och ”%s” kan anges"
-
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
"rules) [<options>]"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Om meningen var att skapa en arbetskatalog från en ny föräldrals\n"
+"Om meningen var att skapa en arbetskatalog från en ny ofödd\n"
"gren (gren utan incheckningar) för det här arkivet kan du göra\n"
"det med flaggan --orphan:\n"
"\n"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Om meningen var att skapa en arbetskatalog från en ny föräldrals\n"
+"Om meningen var att skapa en arbetskatalog från en ny ofödd\n"
"gren (gren utan incheckningar) för det här arkivet kan du göra\n"
"det med flaggan --orphan:\n"
"\n"
msgid "initializing"
msgstr "initierar"
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "kunde inte hitta den skapade arbetskatalogen ”%s”"
+
#, c-format
msgid "Preparing worktree (new branch '%s')"
msgstr "Förbereder arbetskatalog (ny gren ”%s”)"
"finns, avslutar; använd ”add -f” för att överstyra eller hämta från en fjärr "
"först"
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "”%s” och ”%s” kan inte användas samtidigt"
-
msgid "checkout <branch> even if already checked out in other worktree"
msgstr ""
"checka ut <gren> även om den redan är utcheckad i en annan arbetskatalog"
msgid "create or reset a branch"
msgstr "skapa eller återställ en gren"
-msgid "create unborn/orphaned branch"
-msgstr "skapa en ofödd/övergiven gren"
+msgid "create unborn branch"
+msgstr "skapa en ofödd gren"
msgid "populate the new working tree"
msgstr "befolka den nya arbetskatalogen"
msgstr "flaggorna ”%s”, ”%s” och ”%s” kan inte användas samtidigt"
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "flaggorna ”%s” och ”%s” kan inte användas samtidigt"
-
-msgid "<commit-ish>"
-msgstr "<incheckning-igt>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "flaggorna ”%s” och incheckning-igt kan inte användas samtidigt"
msgid "added with --lock"
msgstr "lagt till med --lock"
msgid "Create, list, delete refs to replace objects"
msgstr "Skapa, visa, ta bort referenser för att ersätta objekt"
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"EXPERIMENTELLT: Spela om incheckningar ovanpå en ny bas, fungerar även med "
+"nakna arkiv"
+
msgid "Generates a summary of pending changes"
msgstr "Skapar en sammanfattning av väntande ändringar"
msgid "commit-graph file is too small"
msgstr "incheckningsgraffilen %s är för liten"
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "incheckningsgrafens oid-utbredningsstycke har fel storlek"
+
+msgid "commit-graph fanout values out of order"
+msgstr "incheckningsgrafens utbredningsvärden är i fel ordning"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "incheckningsgrafens OID-uppslagningsstycket har fel storlek"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "incheckningsgrafens incheckningsdatastycke har fel storlek"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr "incheckningsgrafens generationsstycke har fel storlek"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "incheckningsgrafens ändrade-sökvägar-indexstycke är förö litet"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"ignorerar för litet ändrade-sökvägar-stycke (%<PRIuMAX> < %<PRIuMAX>) i "
+"incheckningsgraffilen"
+
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgstr "incheckningsgrafens signatur %X stämmer inte med signaturen %X"
msgid "commit-graph file is too small to hold %u chunks"
msgstr "incheckningsgraffilen är för liten för att innehålla %u stycken"
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr ""
+"incheckningsgrafens nödvändiga OID-utbredningsstycke saknas eller är trasigt"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr ""
+"incheckningsgrafens nödvändiga OID-uppslagningsstycke saknas eller är trasigt"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr ""
+"incheckningsgrafens nödvändiga incheckningsdatastycke saknas eller är trasigt"
+
msgid "commit-graph has no base graphs chunk"
msgstr "incheckningsgrafen har inga bas-graf-stycken"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "antalet incheckningar i basgrafen för högt: %<PRIuMAX>"
+msgid "commit-graph chain file too small"
+msgstr "incheckningsgrafens kedjefil är för liten"
+
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr "ogiltig incheckingsgrafkedja: rad ”%s” är inte ett hash-värde"
msgid "commit-graph overflow generation data is too small"
msgstr "incheckningsgrafens spillgenerationsdata är för liten"
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "incheckningsgrafens extra-kant-pekare är utanför intervallet"
+
msgid "Loading known commits in commit graph"
msgstr "Läser in kända incheckningar i incheckningsgraf"
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "Okänt värde för konfigurationsvariabeln ”diff.submodule”: ”%s”"
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "okänt värde för inställningen ”%s”: %s"
+
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "ogiltigt läge %s” i --color-moved-ws"
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"flaggan diff-algorithm godtar ”myers”, ”minimal”, ”patience” och ”histogram”"
-
#, c-format
msgid "invalid argument to %s"
msgstr "ogiltigt argument för %s"
msgid "output only the last line of --stat"
msgstr "skriv bara ut den sista raden för --stat"
-msgid "<param1,param2>..."
-msgstr "<param1,param2>..."
+msgid "<param1>,<param2>..."
+msgstr "<param1>,<param2>..."
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
msgid "synonym for --dirstat=cumulative"
msgstr "synonym för --dirstat=cumulative"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "synonym för --dirstat=filer,param1,param2..."
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "synonym för --dirstat=filer,<param1>,<param2>..."
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr "varna om ändringar introducerar konfliktmarkörer eller blankstegsfel"
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "skapa diffar med algoritmen ”histogram diff”"
-msgid "<algorithm>"
-msgstr "<algoritm>"
-
-msgid "choose a diff algorithm"
-msgstr "välj en diff-algoritm"
-
msgid "<text>"
msgstr "<text>"
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "OID-utbredning för multi-pack-index har fel storlek"
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"oid-utbredning i fel ordning: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "OID-uppslagningsstycket för multi-pack-index har fel storlek"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "bad pack-int-id: %u (%u paket totalt)"
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX innehåller inte BTMP-stycket"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "kunde inte läsa det bitmappade paketet %<PRIu32>"
+
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr "multi-pack-index innehåller 64-bitars offset, men off_t är för liten"
msgid "Looking for referenced packfiles"
msgstr "Ser efter refererade packfiler"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr ""
-"oid-utbredning i fel ordning: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-
msgid "the midx contains no oid"
msgstr "midx saknar oid"
msgid "could not open pack %s"
msgstr "kunde inte öppna paketfilen %s"
+msgid "could not determine MIDX preferred pack"
+msgstr "kunde inte bestämma det föredragna MIDX-paketet"
+
#, c-format
msgid "preferred pack (%s) is invalid"
msgstr "föredragen paketfil (%s) är ogiltig"
msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
msgstr "trasig ewah-bitkarta: avhugget huvud för bitkarta för incheckning ”%s”"
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr "kunde inte läsa paketet: ”%s”, inaktiverar återanvändning av paket"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "objektet ”%s” hittades inte i typbitkartor"
msgid "multi-pack-index reverse-index chunk is the wrong size"
msgstr "baklängesindex-stycke för multi-pack-index har fel storlek"
+msgid "could not determine preferred pack"
+msgstr "kunde inte bestämma föredraget paket"
+
msgid "cannot both write and verify reverse index"
msgstr "kan inte både skriva och bekräfta reverse-index"
msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
msgstr "%s förväntar ett icke-negativt heltalsvärde, med valfritt k/m/g-suffix"
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s är inkompatibel med %s"
-
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgstr "tvetydig flagga: %s (kan vara --%s%s eller --%s%s)"
msgid "unable to add '%s' to index"
msgstr "kan inte lägga till ”%s” till indexet"
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "kan inte ta status på ”%s”"
-
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgstr "”%s” finns både som en fil och en katalog"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "kan inte hantera ”%s” och ”%s” samtidigt"
-#, c-format
-msgid "could not remove reference %s"
-msgstr "kunde inte ta bort referensen %s"
-
#, c-format
msgid "could not delete reference %s: %s"
msgstr "kunde inte ta bort referensen %s: %s"
"- Se efter en referens som motsvarar ”%s” på fjärrsidan.\n"
"- Se om <källan> som sänds (”%s”)\n"
" är en referens i ”refs/{heads,tags}/”. Om så lägger vi till\n"
-" motsvarande refs/{heads,tags}/-prefix på fjärrsidan.\n"
+" motsvarande ”refs/{heads,tags}/”-prefix på fjärrsidan.\n"
"\n"
"Inget av dem fungerade, så vi gav upp. Ange fullständig referens."
msgid "Autostash exists; creating a new stash entry."
msgstr "Autostash finns; skapar ny stash-post."
+msgid "autostash reference is a symref"
+msgstr "autostash-referensen är en symbolisk referens"
+
msgid "could not detach HEAD"
msgstr "kunde inte koppla från HEAD"
msgid "invalid initial branch name: '%s'"
msgstr "ogiltigt namn på första gren: ”%s”"
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init: ignorerade --initial-branch=%s"
+
#, c-format
msgid "unable to handle file type %d"
msgstr "kan inte hantera filtyp %d"
msgid "attempt to reinitialize repository with different hash"
msgstr "försöker initiera arkivet på nytt med annan hash"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr "försöker initiera arkivet på nytt med annat referenslagringsformat"
+
#, c-format
msgid "%s already exists"
msgstr "%s finns redan"
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init: ignorerade --initial-branch=%s"
-
#, c-format
msgid "Reinitialized existing shared Git repository in %s%s\n"
msgstr "Ominitierade befintligt delat Git-arkiv i %s%s\n"
msgid "number of entries in the cache tree to invalidate (default 0)"
msgstr "antal poster i cacheträdet att ogiltigförklara (förval är 0)"
-msgid "unhandled options"
-msgstr "flaggor som inte hanterats"
-
-msgid "error preparing revisions"
-msgstr "fel när revisioner skulle förberedas"
-
#, c-format
msgid "commit %s is not marked reachable"
msgstr "incheckning %s är inte märkt nåbar"
msgid "invalid remote service path"
msgstr "felaktig sökväg till fjärrtjänst"
-msgid "operation not supported by protocol"
-msgstr "funktionen stöds inte av protokollet"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "kan inte ansluta till undertjänsten %s"
msgid "support for protocol v2 not implemented yet"
msgstr "stöd för protokoll v2 ännu ej implementerat"
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "okänt värde för inställningen ”%s”: %s"
-
#, c-format
msgid "transport '%s' not allowed"
msgstr "transporten ”%s” tillåts inte"
msgid "could not retrieve server-advertised bundle-uri list"
msgstr "kunde inte hämta bundle-uri-listan som servern annonserade"
+msgid "operation not supported by protocol"
+msgstr "funktionen stöds inte av protokollet"
+
msgid "too-short tree object"
msgstr "trädobjekt för kort"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "kan inte %s: Ditt index innehåller ändringar som inte checkats in."
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "okänd stil ”%s” angavs för ”%s”"
+
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
# Turkish translations for Git
# Git Türkçe çevirileri
-# Copyright (C) 2020-2023 Emir SARI <emir_sari@icloud.com>
+# Copyright (C) 2020-2024 Emir SARI <emir_sari@icloud.com>
# This file is distributed under the same license as the Git package.
-# Emir SARI <emir_sari@icloud.com>, 2020-2023
+# Emir SARI <emir_sari@icloud.com>, 2020-2024
#
# ######################################################### #
# Git Türkçe kavramlar dizini / Git Turkish Glossary #
# detached HEAD | ayrık HEAD #
# dirty | kirli #
# evil merge | uğursuz birleştirme #
+# fanout | çıkış sayısı #
# fast-forward | ileri sarım/sarmak #
# fetch | getirme(k) #
# fixup | düzeltmek #
# pathspec | yol belirteci #
# pattern | dizgi #
# porcelain | okunabilir #
-# prune | budamak #
+# prune | buda(mak) #
# pseudoref | yalancıktan başvuru #
-# pull | çekme(k) #
-# push | itme(k) #
+# pull | çek(mek) #
+# push | it(mek) #
# rebase | yeniden temellendirme(k) #
# record | kayıt yaz(mak) #
# ref | başvuru #
# trailer | artbilgi #
# tree | ağaç #
# treeish | ağacımsı #
+# unborn | henüz doğmamış (dal) #
# unstage | hazırlıktan çıkar(mak) #
# upstream | üstkaynak #
# worktree/working tree | çalışma ağacı #
msgstr ""
"Project-Id-Version: Git Turkish Localization Project\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-09 11:15+0300\n"
-"PO-Revision-Date: 2023-11 13:00+0300\n"
+"POT-Creation-Date: 2024-02-16 22:04+0300\n"
+"PO-Revision-Date: 2024-02-16 22: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"
msgid "Unexpected option --output"
msgstr "Beklenmedik seçenek --output"
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "fazladan komut satırı parametresi '%s'"
+
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Bilinmeyen arşiv biçimi '%s'"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "hatalı --attr-source veya GIT_ATTR_SOURCE"
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "'%s' dosyasının bilgileri alınamıyor"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "%s okunamıyor"
+
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "'%s' dosyasında hatalı tırnağa alınmış içerik: %s"
msgstr "'%s' için işleme nesnesi aranamadı"
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
-msgstr ""
-"'%s' dalı tümüyle birleştirilmemiş.\n"
-"Eğer silmek istediğinizden eminseniz 'git branch -D %s' çalıştırın."
+msgid "the branch '%s' is not fully merged"
+msgstr "'%s' dalı tümüyle birleştirilmedi"
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "Onu silmek istediğinizden eminseniz 'git branch -D %s' çalıştırın."
msgid "update of config-file failed"
msgstr "config-file güncellenemedi"
msgid "new-branch"
msgstr "yeni dal"
-msgid "new unparented branch"
-msgstr "yeni üst ögesi olmayan dal"
+msgid "new unborn branch"
+msgstr "yeni henüz doğmamış dal"
msgid "update ignored files (default)"
msgstr "yok sayılan dosyaları güncelle (öntanımlı)"
"clean.requireForce öntanımlı olarak 'true' ve ne -i ne -n ne de -f verilmiş; "
"temizleme reddediliyor"
-msgid "-x and -X cannot be used together"
-msgstr "-x ve -X birlikte kullanılamaz"
-
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<seçenekler>] [--] <depo> [<dizin>]"
msgid "separate git dir from working tree"
msgstr "git dizinini çalışma ağacından ayır"
+msgid "specify the reference format to use"
+msgstr "kullanılacak başvuru biçimini belirt"
+
msgid "key=value"
msgstr "anahtar=değer"
msgid "You must specify a repository to clone."
msgstr "Klonlamak için bir depo belirtmelisiniz."
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"--bundle-uri; --depth, --shallow-since ve --shallow-exclude ile uyumsuz"
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "bilinmeyen başvuru depolama biçimi '%s'"
#, c-format
msgid "repository '%s' does not exist"
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir <dizin>] [--append]\n"
-" [--split[=<<strateji>]] [--reachable | --stdin-packs "
-"| --stdin-commits]\n"
+" [--split[=<strateji>]] [--reachable | --stdin-packs | "
+"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
" <bölme-seçenekleri>"
msgid "unable to read tree (%s)"
msgstr "ağaç okunamıyor (%s)"
+#, c-format
+msgid "unable to read tree %s"
+msgstr "%s ağacı okunamıyor"
+
#, c-format
msgid "unable to grep from object of type %s"
msgstr "%s türündeki bir nesneden grep yapılamıyor"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "%s İLE SHA1 ÇARPIŞMASI BULUNDU!"
-#, c-format
-msgid "unable to read %s"
-msgstr "%s okunamıyor"
-
#, c-format
msgid "cannot read existing object info %s"
msgstr "var olan nesne bilgisi %s okunamıyor"
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=<şablon-dizini>]\n"
" [--separate-git-dir <git-dizini>] [--object-format=<biçim>]\n"
+" [--ref-format=<biçim>]\n"
" [-b <dal-adı> | --initial-branch=<dal-adı>]\n"
-" [--shared[=<izinler>]] [<dizin>]"
+" [--shared[=<izin>]] [<dizin>]"
msgid "permissions"
msgstr "izinler"
"git merge-file [<seçenekler>] [-L <ad1> [-L <orij> [-L <ad2>]]] <dosya1> "
"<orij-dosya> <dosya2>"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"diff-algorithm seçeneği şunları kabul eder: \"myers\", \"minimal\", "
+"\"patience\" ve \"histogram\""
+
msgid "send results to standard output"
msgstr "sonuçları standart çıktıya gönder"
msgid "for conflicts, use a union version"
msgstr "çakışmalarda birlik olmuş bir sürüm kullan"
+msgid "<algorithm>"
+msgstr "<algoritma>"
+
+msgid "choose a diff algorithm"
+msgstr "bir diff algoritması seç"
+
msgid "for conflicts, use this marker size"
msgstr "çakışmalarda bu imleyici boyutunu kullan"
msgid "unknown strategy option: -X%s"
msgstr "bilinmeyen strateji seçeneği: -X%s"
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base, --stdin ile uyumsuz"
-
#, c-format
msgid "malformed input line: '%s'."
msgstr "hatalı oluşturulmuş girdi satırı: '%s'."
msgid "inconsistency with delta count"
msgstr "delta sayımında tutarsızlık"
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "geçersiz pack.allowPackReuse değeri: '%s'"
+
#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Toplam %<PRIu32> (delta %<PRIu32>), yeniden kullanılan %<PRIu32> (delta "
-"%<PRIu32>), yeniden kullanılan paket %<PRIu32>"
+"%<PRIu32>), yeniden kullanılan paket %<PRIu32> (%<PRIuMAX> konumundan)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
msgid "switch `C' expects a numerical value"
msgstr "'C' anahtarı sayısal bir değer bekliyor"
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"seçenekleri uygula, rebase.autoSquash ile uyumlu değil. --no-autosquash "
-"eklemeyi düşünün"
-
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"no-rebase-merges"
"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
"to delete them, use:"
msgstr[0] ""
-"Not: refs/remotes hiyerarşisi dışındaki bir dal kaldırılmadı;\n"
+"Not: refs/remotes/ hiyerarşisi dışındaki bir dal kaldırılmadı;\n"
"onu silmek için şunu kullanın:"
msgstr[1] ""
-"Not: refs/remotes hiyerarşisi dışındaki bazı dallar kaldırılmadı;\n"
+"Not: refs/remotes/ hiyerarşisi dışındaki bazı dallar kaldırılmadı;\n"
"onları silmek için şunu kullanın:"
#, c-format
msgid "only one pattern can be given with -l"
msgstr "-l ile yalnızca bir dizgi verilebilir"
+msgid "need some commits to replay"
+msgstr "yeniden oynatmak için birkaç işleme gerekli"
+
+msgid "--onto and --advance are incompatible"
+msgstr "--onto ve --advance birbiriyle uyumsuz"
+
+msgid "all positive revisions given must be references"
+msgstr "verilen tüm pozitif revizyonlar, başvuru olmalı"
+
+msgid "argument to --advance must be a reference"
+msgstr "--advance'a olan argüman bir başvuru olmalı"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"birden çok kaynaklı hedef ilerletilemiyor; çünkü sıralama hatalı tanımlanmış "
+"olurdu"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr ""
+"bunun --advance veya --onto işlemi olup olmadığı örtük olarak algılanamıyor"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"birden çok kaynak dallı hedef ilerletilemiyor; çünkü sıralama hatalı "
+"tanımlanmış olurdu"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "--onto için olan doğru temel örtük olarak algılanamıyor"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(DENEYSEL!) git replay ([--contained] --onto <yeni-temel> | --advance <dal>) "
+"<revizyon-erimi>..."
+
+msgid "make replay advance given branch"
+msgstr "verilen dalı önceden yeniden oynat"
+
+msgid "replay onto given commit"
+msgstr "verilen işlemeye yeniden oynat"
+
+msgid "advance all branches contained in revision-range"
+msgstr "revizyon eriminde içerilen tüm dalları ilerlet"
+
+msgid "option --onto or --advance is mandatory"
+msgstr "--onto veya --advance seçeneğinin kullanımı zorunlu"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"'struct rev_info' içindeki '%s' biti zorlanacağından kimi revizyon yürütme "
+"seçenekleri geçersiz kılınacak"
+
+msgid "error preparing revisions"
+msgstr "revizyonlar hazırlanırken hata"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "kök işlemeye kadar yeniden oynatma henüz desteklenmiyor!"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "birleştirme işlemelerini yeniden oynatma henüz desteklenmiyor!"
+
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr ""
msgid "unknown mode for --abbrev-ref: %s"
msgstr "--abbrev-ref için bilinmeyen kip: %s"
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden, --branches ile birlikte kullanılamıyor"
-
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden, --tags ile birlikte kullanılamıyor"
-
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden, --remotes ile birlikte kullanılamıyor"
-
msgid "this operation must be run in a work tree"
msgstr "bu işlem bir çalışma ağacı içinde çalıştırılmalı"
msgid "show refs from stdin that aren't in local repository"
msgstr "stdin'den yerel bir depoda olmayan başvuruları göster"
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "yalnızca '%s', '%s' veya '%s' arasından biri verilebilir"
-
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
"rules) [<options>]"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Bu depo için yeni bir yetim dal içeren (işlemesiz dal) bir\n"
-"çalışma ağacı oluşturmak istediyseniz bunu --orphan bayrağı\n"
-"ile yapabilirsiniz:\n"
+"Bu depo için henüz doğmamış bir dal (işleme içermeyen dal) içeren\n"
+"bir çalışma ağacı oluşturmak istediyseniz bunu --orphan bayrağını\n"
+"kullanarak yapabilirsiniz:\n"
"\n"
" git worktree add --orphan -b %s %s\n"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"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 ""
-"Bu depo için yeni bir yetim dal içeren (işlemesiz dal) bir\n"
-"çalışma ağacı oluşturmak istediyseniz bunu --orphan bayrağı\n"
-"ile yapabilirsiniz:\n"
+"Bu depo için henüz doğmamış bir dal (işleme içermeyen dal) içeren\n"
+"bir çalışma ağacı oluşturmak istediyseniz bunu --orphan bayrağını\n"
+"kullanarak yapabilirsiniz:\n"
"\n"
" git worktree add --orphan %s\n"
msgid "initializing"
msgstr "ilklendiriliyor"
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "oluşturulan '%s' çalışma ağacı bulunamadı"
+
#, c-format
msgid "Preparing worktree (new branch '%s')"
msgstr "Çalışma ağacı hazırlanıyor (yeni dal '%s')"
"Bir uzak konum olmasına rağmen hiçbir yerel/uzak başvuru yok, durduruluyor;\n"
"geçersiz kılmak veya önce bir uzak konum getirmek için 'add -f' kullanın"
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "'%s' ve '%s' birlikte kullanılamaz"
-
msgid "checkout <branch> even if already checked out in other worktree"
msgstr "diğer çalışma ağacında çıkış yapılmış olsa bile <dal> çıkışını yap"
msgid "create or reset a branch"
msgstr "yeni bir dal oluştur veya sıfırla"
-msgid "create unborn/orphaned branch"
-msgstr "doğmamış/yetim bırakılmış dal oluştur"
+msgid "create unborn branch"
+msgstr "henüz doğmamış dal oluştur"
msgid "populate the new working tree"
msgstr "yeni çalışma ağacını doldur"
msgstr "'%s', '%s' ve '%s' seçenekleri birlikte kullanılamaz"
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "'%s' ve '%s' seçenekleri birlikte kullanılamaz"
-
-msgid "<commit-ish>"
-msgstr "<işlememsi>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "'%s' seçeneği ve işlememsiler birlikte kullanılamaz"
msgid "added with --lock"
msgstr "--lock ile eklendi"
msgid "Create, list, delete refs to replace objects"
msgstr "Nesne değiştirmek için başvurular 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"
+
msgid "Generates a summary of pending changes"
msgstr "Bekleyen değişikliklerin bir özetini çıkart"
msgid "commit-graph file is too small"
msgstr "commit-graph dosyası pek küçük"
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "commit-graph OID çıkış sayısı iri parçası boyutu yanlış"
+
+msgid "commit-graph fanout values out of order"
+msgstr "commit-graph çıkış sayısı değerleri sırasız: fanout[%d] = %u != %u"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "commit-graph OID arama iri parçası boyutu yanlış"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "commit-graph işleme verisi iri parçası boyutu yanlış"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr "commit-graph kuşaklar iri parçası boyutu yanlış"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "commit-graph changed-path indeksi iri parçası boyutu pek küçük"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"commit-graph dosyasındaki pek küçük changed-path iri parçası (%<PRIuMAX> < "
+"%<PRIuMAX>) yok sayılıyor"
+
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgstr "commit-graph imzası %X, %X ile eşleşmiyor"
msgid "commit-graph file is too small to hold %u chunks"
msgstr "commit-graph dosyası %u iri parça tutmak için pek küçük"
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr ""
+"commit-graph'ten gerekli OID çıkış sayısı iri parçası eksik veya hasarlı"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr "commit-graph'ten gerekli OID arama iri parçası eksik veya hasarlı"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr ""
+"commit-graph'ten gerekli OID çıkış sayısı iri parçası eksik veya hasarlı"
+
msgid "commit-graph has no base graphs chunk"
msgstr "commit-graph temel grafiği iri parçasına iye değil"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "temel grafikteki işleme sayısı pek yüksek: %<PRIuMAX>"
+msgid "commit-graph chain file too small"
+msgstr "commit-graph zincir dosyası pek küçük"
+
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr "geçersiz commit-graph zinciri: '%s'. satır bir sağlama değil"
msgid "commit-graph overflow generation data is too small"
msgstr "commit-graph, taşım üretim verisi pek küçük"
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "commit-graph extra-edges işaretçisi sınırlar dışında"
+
msgid "Loading known commits in commit graph"
msgstr "İşleme grafiğindeki bilinen işlemeler yükleniyor"
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "'diff.submodule' yapılandırma değişkeni için bilinmeyen değer: '%s'"
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "'%s' yapılandırması için bilinmeyen değer: %s"
+
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "--color-moved-ws içinde geçersiz kip '%s'"
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"diff-algorithm seçeneği şunları kabul eder: \"myers\", \"minimal\", "
-"\"patience\" ve \"histogram\""
-
#, c-format
msgid "invalid argument to %s"
msgstr "%s için geçersiz argüman"
msgid "output only the last line of --stat"
msgstr "--stat'ın yalnızca son satırını çıktı ver"
-msgid "<param1,param2>..."
-msgstr "<param1,param2>..."
+msgid "<param1>,<param2>..."
+msgstr "<param1>,<param2>..."
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
msgid "synonym for --dirstat=cumulative"
msgstr "--dirstat=cumulative eşanlamlısı"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "--dirstat=files,param1,param2... eşanlamlısı"
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "--dirstat=files,<param1>,<param2>... eşanlamlısı"
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr ""
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "diff'i \"histogram diff\" algoritmasını kullanarak oluştur"
-msgid "<algorithm>"
-msgstr "<algoritma>"
-
-msgid "choose a diff algorithm"
-msgstr "bir diff algoritması seç"
-
msgid "<text>"
msgstr "<metin>"
msgstr "önbellek okunamadı"
msgid "multi-pack-index OID fanout is of the wrong size"
-msgstr "multi-pack-index OID ikiye bölümünün boyutu hatalı"
+msgstr "multi-pack-index OID çıkış sayısı boyutu yanlış"
+
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"oid çıkış sayısı sırasız: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "multi-pack-index OID arama iri parçası yanlış boyutlu"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "hatalı pack-int-id: %u (%u toplam paket)"
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX, BTMP iri parçasını içermiyor"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "biteşlemli %<PRIu32> paketi yüklenemedi"
+
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr "multi-pack-index bir 64 bit ofset depoluyor; ancak off_t pek küçük"
msgid "Looking for referenced packfiles"
msgstr "Başvurulmuş paket dosyaları aranıyor"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr "oid fanout sırasız: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-
msgid "the midx contains no oid"
msgstr "midx bir oid içermiyor"
msgid "could not open pack %s"
msgstr "%s paketi açılamadı"
+msgid "could not determine MIDX preferred pack"
+msgstr "MIDX yeğlenen paketi algılanamadı"
+
#, c-format
msgid "preferred pack (%s) is invalid"
-msgstr "tercih edilen (%s) paket geçersiz"
+msgstr "yeğlenen paket (%s) geçersiz"
msgid "corrupt bitmap lookup table: triplet position out of index"
msgstr "hasarlı biteşlem arama tablosu: üçlü konum indeks dışında"
msgstr ""
"hasarlı ewah biteşlemi: \"%s\" işlemesinin biteşleminde kısaltılmış üstbilgi"
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr "paket yüklenemiyor: '%s', pack-reuse devre dışı bırakılıyor"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "'%s' nesnesi, tür biteşlemlerinde bulunamadı"
msgid "multi-pack-index reverse-index chunk is the wrong size"
msgstr "multi-pack-index reverse-index iri parçası yanlış boyutlu"
+msgid "could not determine preferred pack"
+msgstr "yeğlenen paket algılanamadı"
+
msgid "cannot both write and verify reverse index"
msgstr "ters indeks dosyası hem yazılıp hem doğrulanamıyor"
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"
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s, %s ile uyumsuz"
-
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgstr "belirsiz seçenek: %s (--%s%s veya --%s%s olabilir)"
msgid "unable to add '%s' to index"
msgstr "'%s' indekse eklenemiyor"
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "'%s' dosyasının bilgileri alınamıyor"
-
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgstr "'%s' hem bir dosya hem de bir dizin olarak görünüyor"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "'%s' ve '%s' aynı anda işlenemiyor"
-#, c-format
-msgid "could not remove reference %s"
-msgstr "%s başvurusu kaldırılamadı"
-
#, c-format
msgid "could not delete reference %s: %s"
msgstr "%s başvurusu silinemedi: %s"
msgid "Autostash exists; creating a new stash entry."
msgstr "Kendiliğinden zulalama mevcut; yeni bir zula girdisi oluşturuluyor."
+msgid "autostash reference is a symref"
+msgstr "kendiliğinden zulalama başvurusu bir sembol başvurusu"
+
msgid "could not detach HEAD"
msgstr "HEAD ayrılamadı"
msgid "invalid initial branch name: '%s'"
msgstr "geçersiz başlangıç dalı adı: '%s'"
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init: --initial-branch=%s yok sayıldı"
+
#, c-format
msgid "unable to handle file type %d"
msgstr "%d dosya türü ele alınamıyor"
msgid "attempt to reinitialize repository with different hash"
msgstr "depoyu başka bir sağlama ile yeniden ilklendirme deneniyor"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr ""
+"depo başka bir başvuru depolama biçimiyle yeniden ilklendirilmeye çalışılıyor"
+
#, c-format
msgid "%s already exists"
msgstr "%s halihazırda var"
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init: --initial-branch=%s yok sayıldı"
-
#, c-format
msgid "Reinitialized existing shared Git repository in %s%s\n"
msgstr "%s%s içindeki var olan paylaşılan Git deposu yeniden ilklendirildi\n"
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 "unhandled options"
-msgstr "beklenmeyen seçenekler"
-
-msgid "error preparing revisions"
-msgstr "revizyonlar hazırlanırken hata"
-
#, c-format
msgid "commit %s is not marked reachable"
msgstr "%s işlemesi ulaşılabilir olarak imlenmedi"
msgid "invalid remote service path"
msgstr "geçersiz uzak konum servis yolu"
-msgid "operation not supported by protocol"
-msgstr "işlem protokol tarafından desteklenmiyor"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "%s altservisine bağlanılamıyor"
msgid "support for protocol v2 not implemented yet"
msgstr "protokol v2 desteği henüz yerine getirilmedi"
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "'%s' yapılandırması için bilinmeyen değer: %s"
-
#, c-format
msgid "transport '%s' not allowed"
msgstr "'%s' taşıyıcısına izin verilmiyor"
msgid "could not retrieve server-advertised bundle-uri list"
msgstr "sunucu tarafından tanıtılan bundle-uri listesi alınamadı"
+msgid "operation not supported by protocol"
+msgstr "işlem protokol tarafından desteklenmiyor"
+
msgid "too-short tree object"
msgstr "ağaç nesnesi çok kısa"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "%s yapılamıyor: İndeksiniz işlenmemiş değişiklikler içeriyor."
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "'%s' bilinmeyen biçemi şunun için verildi: '%s'"
+
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
"Project-Id-Version: Git v2.43\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
"POT-Creation-Date: 2023-11-09 14:26-0800\n"
-"PO-Revision-Date: 2023-11-09 14:34-0800\n"
+"PO-Revision-Date: 2024-02-11 09:26-0800\n"
"Last-Translator: Arkadii Yakovets <ark@cho.red>\n"
"Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n"
"Language: uk\n"
"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.4.1\n"
+"X-Generator: Poedit 3.4.2\n"
#, c-format
msgid "Huh (%s)?"
msgid "Unexpected option --output"
msgstr "Неочікувана опція --output"
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "зайвий параметр командного рядка: \"%s\""
+
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Невідомий формат архіву \"%s\""
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "невірний --attr-source або GIT_ATTR_SOURCE"
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "не вдалося виконати stat для \"%s\""
+
+#, c-format
+msgid "unable to read %s"
+msgstr "не вдалося прочитати %s"
+
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "Невірно процитований вміст у файлі \"%s\": %s"
msgid "not tracking: ambiguous information for ref '%s'"
msgstr "не відстежується: неоднозначна інформація для посилання \"%s\""
+#. #-#-#-#-# branch.c.po #-#-#-#-#
#. TRANSLATORS: This is a line listing a remote with duplicate
#. refspecs in the advice message below. For RTL languages you'll
#. probably want to swap the "%s" and leading " " space around.
#.
+#. #-#-#-#-# object-name.c.po #-#-#-#-#
#. TRANSLATORS: This is line item of ambiguous object output
#. from describe_ambiguous_object() above. For RTL languages
#. you'll probably want to swap the "%s" and leading " " space
"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-{old,good}=<термін>] "
+"git bisect start [--term-(new,bad)=<термін> --term-(old,good)=<термін>] "
"[--no-checkout] [--first-parent] [<поганий> [<добрий>...]] [--] "
"[<визначник шляху>...]"
msgstr "не вдалося знайти об’єкт коміту для \"%s\""
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
+msgid "the branch '%s' is not fully merged"
+msgstr "гілка \"%s\" злита не повністю"
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
msgstr ""
-"гілка \"%s\" злита не повністю.\n"
"Якщо ви впевнені, що хочете її видалити, виконайте \"git branch -D %s\""
msgid "update of config-file failed"
#, c-format
msgid "no commit on branch '%s' yet"
-msgstr "поки що немає комітів в гілці \"%s\""
+msgstr "поки що немає комітів у гілці \"%s\""
#, c-format
msgid "no branch named '%s'"
-msgstr "немає гілки з ім’ям \"%s\""
+msgstr "немає гілки з назвою \"%s\""
msgid "branch rename failed"
msgstr "не вдалося перейменувати гілку"
"'--set-upstream-to' instead"
msgstr ""
"опція \"--set-upstream\" більше не підтримується. Будь ласка, використовуйте "
-"\"--track\" або \"--set-upstream-to\""
+"\"--track\" або \"--set-upstream-to\" замість неї"
msgid "git version:\n"
msgstr "версія git:\n"
msgid "new-branch"
msgstr "нова-гілка"
-msgid "new unparented branch"
-msgstr "нова гÑ\96лка без джеÑ\80ела"
+msgid "new unborn branch"
+msgstr "нова ненаÑ\80оджена гÑ\96лка"
msgid "update ignored files (default)"
msgstr "оновити ігноровані файли (за замовчуванням)"
"clean.requireForce встановлено у true за замовчуванням і не задано ні -i, ні "
"-n, ні -f; відмовлено в прибиранні"
-msgid "-x and -X cannot be used together"
-msgstr "-x та -X не можна використовувати разом"
-
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<опції>] [--] <сховище> [<директорія>]"
msgid "separate git dir from working tree"
msgstr "відокремити git-директорію від робочого дерева"
+msgid "specify the reference format to use"
+msgstr "вкажіть формат посилання, який потрібно використовувати"
+
msgid "key=value"
msgstr "ключ=значення"
msgid "You must specify a repository to clone."
msgstr "Треба вказати сховище для клонування."
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr ""
-"--bundle-uri несумісний з --depth, --shallow-since та --shallow-exclude"
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "невідомий формат зберігання посилань \"%s\""
#, c-format
msgid "repository '%s' does not exist"
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir <директорія>] [--append] [--object-dir "
"<директорія>] [--append] [--object-dir <директорія>] [--append\n"
"| --stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <число>] [--"
"[no-]progress]\n"
-" <опції розділення>"
+" <опції-розділення>"
msgid "dir"
msgstr "директорія"
msgstr "планувальник для запуску обслуговування git"
msgid "failed to set up maintenance schedule"
-msgstr "не вдалося встановити графік обслуговування"
+msgstr "не вдалося встановити розклад обслуговування"
msgid "failed to add repo to global config"
msgstr "не вдалося додати сховище до глобальної конфігурації"
msgid "invalid number of threads specified (%d) for %s"
msgstr "невірно вказана кількість потоків (%d) для %s"
+#. #-#-#-#-# grep.c.po #-#-#-#-#
#. TRANSLATORS: %s is the configuration
#. variable for tweaking threads, currently
#. grep.threads
msgid "unable to read tree (%s)"
msgstr "не вдалося прочитати дерево (%s)"
+#, c-format
+msgid "unable to read tree %s"
+msgstr "не вдалося прочитати дерево %s"
+
#, c-format
msgid "unable to grep from object of type %s"
msgstr "не вдалося виконати grep для об’єкта типу %s"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "ВИЯВЛЕНО SHA1 КОЛІЗІЮ З %s!"
-#, c-format
-msgid "unable to read %s"
-msgstr "не вдалося прочитати %s"
-
#, c-format
msgid "cannot read existing object info %s"
msgstr "неможливо прочитати інформацію про існуючий об’єкт %s"
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=<шаблон-директорія>]\n"
" [--separate-git-dir <git-директорія>] [--object-format=<формат>]\n"
+" [--ref-format=<формат>]\n"
" [-b <назва-гілки> | --initial-branch=<назва-гілки>]\n"
" [--shared[=<дозволи>]] [<директорія>]"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<ключ>|<аліасКлюча>)"
-"[(=|:)<значення>])...]\n"
+" [(--trailer <ключ>|"
+"<аліасКлюча>[(=|:)<значення>])...]\n"
" [--parse] [<файл>...]"
msgid "edit files in place"
msgstr "обрізати порожні причепи"
msgid "placement"
-msgstr "розташування"
+msgstr "розміщення"
msgid "where to place the new trailer"
msgstr "де розмістити новий причіп"
"git merge-file [<опції>] [-L <назва1> [-L <оріг> [-L <назва2>]]] <файл1> "
"<оріг-файл> <файл2>"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"опція diff-algorithm приймає значення \"myers\", \"minimal\", \"patience\" "
+"та \"histogram\""
+
msgid "send results to standard output"
msgstr "надсилати результати до стандартного виводу"
msgid "use object IDs instead of filenames"
-msgstr "використовувати ID обʼєктів замість назв файлів"
+msgstr "використовувати ідентифікатори обʼєктів замість назв файлів"
msgid "use a diff3 based merge"
msgstr "використовувати злиття на основі diff3"
msgid "for conflicts, use a union version"
msgstr "у разі конфліктів використовувати об’єднану версію"
+msgid "<algorithm>"
+msgstr "<алгоритм>"
+
+msgid "choose a diff algorithm"
+msgstr "вибрати алгоритм різниці"
+
msgid "for conflicts, use this marker size"
msgstr "у разі конфліктів використовувати цей розмір маркера"
#, c-format
msgid "object '%s' does not exist"
-msgstr "обʼєкт \"%s\" не існує"
+msgstr "об’єкт \"%s\" не існує"
msgid "Could not write object file"
msgstr "Не вдалося записати файл обʼєкта"
msgid "unknown strategy option: -X%s"
msgstr "невідомий варіант стратегії: -X%s"
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base несумісна з --stdin"
-
#, c-format
msgid "malformed input line: '%s'."
msgstr "невірно сформований рядок вводу: \"%s\"."
msgid "inconsistency with delta count"
msgstr "неспівпадіння з підрахунком дельти"
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "неприпустиме значення pack.allowPackReuse: \"%s\""
+
#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"Всього %<PRIu32> (дельта %<PRIu32>), повторно використано %<PRIu32> (дельта "
-"%<PRIu32>), повторно використано пакунків %<PRIu32>"
+"%<PRIu32>), повторно використано пакунків %<PRIu32> (з %<PRIuMAX>)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
msgid "switch `C' expects a numerical value"
msgstr "перемикач \"C\" очікує числове значення"
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr ""
-"apply опції несумісні з rebase.autoSquash. Розгляньте можливість додавання "
-"--no-autosquash"
-
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
"no-rebase-merges"
msgstr "записати multi-pack-index результуючих пакунків"
msgid "pack prefix to store a pack containing pruned objects"
-msgstr "пÑ\80еÑ\84Ñ\96кÑ\81 пакÑ\83нка длÑ\8f збеÑ\80Ñ\96ганнÑ\8f пакÑ\83нка з обÑ\80Ñ\96заними обʼÑ\94кÑ\82ами"
+msgstr "префікс для зберігання пакунка з обрізаними обʼєктами"
msgid "pack prefix to store a pack containing filtered out objects"
msgstr "префікс для зберігання пакунка з відфільтрованими обʼєктами"
#, c-format
msgid "option '%s' can only be used along with '%s'"
-msgstr "опÑ\86Ñ\96Ñ\8e \"%s\" можна викоÑ\80иÑ\81Ñ\82овÑ\83ваÑ\82и тільки разом з \"%s\""
+msgstr "опÑ\86Ñ\96Ñ\8f \"%s\" може бÑ\83Ñ\82и викоÑ\80иÑ\81Ñ\82ана тільки разом з \"%s\""
msgid "Nothing new to pack."
msgstr "Немає нічого нового для пакування."
msgid "only one pattern can be given with -l"
msgstr "тільки один шаблон може бути заданий з -l"
+msgid "need some commits to replay"
+msgstr "потрібні деякі комміти для відтворення"
+
+msgid "--onto and --advance are incompatible"
+msgstr "--onto та --advance несумісні"
+
+msgid "all positive revisions given must be references"
+msgstr "всі надані позитивні ревізії мають бути посиланнями"
+
+msgid "argument to --advance must be a reference"
+msgstr "аргумент до --advance має бути посиланням"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr ""
+"неможливо просунути посилання з декількома джерелами, тому що впорядкування "
+"буде нечітко визначеним"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr "неможливо неявно визначити, чи це операція --advance або --onto"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr ""
+"неможливо просунути посилання з декількома джерельними гілками, тому що "
+"впорядкування буде нечітко визначеним"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "неможливо неявно визначити вірну базу для --onto"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(ЕКСПЕРИМЕНТАЛЬНО!) git replay ([--contained] --onto <нова-база> | --advance "
+"<гілка>) <діапазон-ревізій>..."
+
+msgid "make replay advance given branch"
+msgstr "зробити відтворення з просуванням даної гілки"
+
+msgid "replay onto given commit"
+msgstr "відтворити на заданий коміт"
+
+msgid "advance all branches contained in revision-range"
+msgstr "просунути всі гілки, що містяться в діапазоні ревізій"
+
+msgid "option --onto or --advance is mandatory"
+msgstr "опція --onto або --advance є обовʼязковою"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"деякі опції проходження по ревізіям будуть перевизначені, оскільки біт "
+"\"%s\" у \"struct rev_info\" буде примусово використано"
+
+msgid "error preparing revisions"
+msgstr "помилка при підготовці ревізій"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "відтворення до кореневого коміту поки що не підтримується!"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "відтворення коммітів злиття поки що не підтримується!"
+
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr ""
msgid "unknown mode for --abbrev-ref: %s"
msgstr "невідомий режим для --abbrev-ref: %s"
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden не можна використовувати разом з --branches"
-
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden неможливо використовувати разом з --tags"
-
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden неможливо використовувати разом з --remotes"
-
msgid "this operation must be run in a work tree"
msgstr "цю операцію треба виконувати в робочому дереві"
msgid "show refs from stdin that aren't in local repository"
msgstr "показати посилання з stdin, яких немає в локальному сховищі"
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "можна вказати тільки один з \"%s\", \"%s\" або \"%s\""
-
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
"rules) [<options>]"
"branch] [--] [<шлях>...]"
msgid "Failed to resolve HEAD as a valid ref."
-msgstr "Ð\9dе вдалоÑ\81Ñ\8f Ñ\80озпÑ\96знаÑ\82и HEAD Ñ\8fк дійсне посилання."
+msgstr "Ð\9dе вдалоÑ\81Ñ\8f Ñ\80озвʼÑ\8fзаÑ\82и HEAD в дійсне посилання."
msgid "git submodule absorbgitdirs [<options>] [<path>...]"
msgstr "git submodule absorbgitdirs [<опції>] [<шлях>...]"
#, c-format
msgid "index-version: was %d, set to %d"
-msgstr "index-version: було %d, стало %d"
+msgstr "версія індексу: була %d, стала %d"
msgid ""
"core.splitIndex is set to false; remove or change it, if you really want to "
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"If you meant to create a worktree containing a new unborn branch\n"
"(branch with no commits) for this repository, you can do so\n"
"using the --orphan flag:\n"
"\n"
" git worktree add --orphan -b %s %s\n"
msgstr ""
-"Якщо ви хочете створити робоче дерево, що містить нову сирітську гілку\n"
+"Якщо ви хочете створити робоче дерево, що містить нову ненароджену гілку\n"
"(гілку без комітів) для цього сховища, ви можете зробити це\n"
"за допомогою прапорця --orphan:\n"
"\n"
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"If you meant to create a worktree containing a new unborn branch\n"
"(branch with no commits) for this repository, you can do so\n"
"using the --orphan flag:\n"
"\n"
" git worktree add --orphan %s\n"
msgstr ""
-"Якщо ви хочете створити робоче дерево, що містить нову сирітську гілку\n"
+"Якщо ви хочете створити робоче дерево, що містить нову ненароджену гілку\n"
"(гілку без комітів) для цього сховища, ви можете зробити це\n"
"за допомогою прапорця --orphan:\n"
"\n"
msgid "initializing"
msgstr "ініціалізація"
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "не вдалося знайти створене робоче дерево \"%s\""
+
#, c-format
msgid "Preparing worktree (new branch '%s')"
msgstr "Підготовка робочого дерева (нова гілка \"%s\")"
msgstr ""
"Не існує локальних або віддалених посилань, незважаючи на наявність "
"принаймні одного віддаленого\n"
-"призначення, зупинка; скористайтесь \"add -f\" для перевизначення або "
-"спочатку виконайте отримання віддаленого посилання"
-
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "\"%s\" і \"%s\" не можна використовувати разом"
+"призначення, зупинка; скористайтесь \"add -f\", щоб перевизначити, або "
+"спочатку виконайте отримання з віддаленного сховища"
msgid "checkout <branch> even if already checked out in other worktree"
msgstr ""
msgid "create or reset a branch"
msgstr "створити або скинути гілку"
-msgid "create unborn/orphaned branch"
-msgstr "створити ненароджену/сирітську гілку"
+msgid "create unborn branch"
+msgstr "створити ненароджену гілку"
msgid "populate the new working tree"
msgstr "заповнити нове робоче дерево"
msgstr "опції \"%s\", \"%s\" та \"%s\" не можна використовувати разом"
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "опції \"%s\" і \"%s\" не можна використовувати разом"
-
-msgid "<commit-ish>"
-msgstr "<комітоподібне>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "опцію \"%s\" не можна використовувати разом з комітоподібними"
msgid "added with --lock"
msgstr "додано з --lock"
#, c-format
msgid "chunk id %<PRIx32> not %d-byte aligned"
-msgstr "шматок в id %<PRIx32> не %d-byte впорядкований"
+msgstr "шматок id %<PRIx32> не є %d-byte впорядкованим"
#, c-format
msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>"
msgstr "Перенести архів обʼєктів та посилань"
msgid "Provide contents or details of repository objects"
-msgstr "Ð\9fоказаÑ\82и вмÑ\96Ñ\81Ñ\82 або Ñ\96нÑ\84оÑ\80маÑ\86Ñ\96Ñ\8e пÑ\80о обʼÑ\94кÑ\82и сховища"
+msgstr "Ð\9dадаваÑ\82и вмÑ\96Ñ\81Ñ\82 або деÑ\82алÑ\96 обʼÑ\94кÑ\82Ñ\96в сховища"
msgid "Display gitattributes information"
msgstr "Відобразити інформацію про gitattributes"
msgid "Create, list, delete refs to replace objects"
msgstr "Створити, показати, видалити посилання для об’єктів заміни"
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"ЕКСПЕРИМЕНТАЛЬНО: Відтворення коммітів на новій базі також працює з "
+"порожніми сховищами"
+
msgid "Generates a summary of pending changes"
msgstr "Створює підсумок змін для розгляду"
msgstr "Показати інформацію про версію Git"
msgid "Show logs with differences each commit introduces"
-msgstr "Показати журнал з різницею, яку вносить кожен з комітів"
+msgstr "Показати журнал з різницями, які вносить кожен коміт"
msgid "Manage multiple working trees"
msgstr "Керувати кількома робочими деревами"
msgid "commit-graph file is too small"
msgstr "файл коміт-графа занадто малий"
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "шматок oid fanout коміт-графа має невірний розмір"
+
+msgid "commit-graph fanout values out of order"
+msgstr "значення fanout коміт-графа впорядковані невірно"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "шматок OID lookup коміт-графа має невірний розмір"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "шматок commit data коміт-графа має невірний розмір"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr "шматок generations коміт-графа має невірний розмір"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "шматок changed-path index коміт-графа має невірний розмір"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"ігнорування занадто малого шматка changed-path (%<PRIuMAX> < %<PRIuMAX>) "
+"файла коміт-графа"
+
#, c-format
msgid "commit-graph signature %X does not match signature %X"
msgstr "підпис коміт-графа %X не збігається з підписом %X"
msgid "commit-graph file is too small to hold %u chunks"
msgstr "файл коміт-графа занадто малий, щоб вмістити %u шматків"
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr "необхідний шматок OID fanout коміт-графа відсутній або пошкоджений"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr "необхідний шматок OID lookup коміт-графа відсутній або пошкоджений"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr "необхідний шматок commit data коміт-графа відсутній або пошкоджений"
+
msgid "commit-graph has no base graphs chunk"
msgstr "коміт-граф не має шматка базових графів"
msgid "commit-graph base graphs chunk is too small"
-msgstr "занадто малий шматок базових графів коміт-графа"
+msgstr "шматок base graphs коміт-графа занадто малий"
msgid "commit-graph chain does not match"
msgstr "ланцюжок коміт-графа не співпадає"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "кількість комітів у базовому графі занадто велика: %<PRIuMAX>"
+msgid "commit-graph chain file too small"
+msgstr "файл ланцюжка коміт-графа занадто малий"
+
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr "неприпустимий ланцюжок коміт-графа: рядок \"%s\" не є хешем"
msgstr "не вдалося знайти коміт %s"
msgid "commit-graph requires overflow generation data but has none"
-msgstr "коміт-граф потребує даних генерації переповнення, але їх немаєданих"
+msgstr "коміт-граф потребує даних генерації переповнення, але не має їх"
msgid "commit-graph overflow generation data is too small"
-msgstr "занадто мало даних про переповнення коміт-граф генерації"
+msgstr "занадто мало даних генерації переповнення коміт-графа"
+
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "extra-edges pointer коміт-графа виходить за межі"
msgid "Loading known commits in commit graph"
msgstr "Завантаження відомих комітів у коміт-графі"
"commit-graph has both zero and non-zero generations (e.g., commits '%s' and "
"'%s')"
msgstr ""
-"коміт-граф має як нульові, так і ненульові генерації (коміти \"%s\" і \"%s\")"
+"коміт-граф має як нульові, так і ненульові генерації (наприклад, коміти "
+"\"%s\" і \"%s\")"
msgid "Verifying commits in commit graph"
msgstr "Перевірка комітів у коміт-графі"
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "Невідоме значення конфігураційної змінної \"diff.submodule\": \"%s\""
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "невідоме значення для конфігурації \"%s\": %s"
+
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "неприпустимий режим \"%s\" у --color-moved-ws"
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"опція diff-algorithm приймає значення \"myers\", \"minimal\", \"patience\" "
-"та \"histogram\""
-
#, c-format
msgid "invalid argument to %s"
msgstr "неприпустимий аргумент до %s"
msgid "output only the last line of --stat"
msgstr "вивести лише останній рядок --stat"
-msgid "<param1,param2>..."
-msgstr "<параметр1,параметр2>..."
+msgid "<param1>,<param2>..."
+msgstr "<параметр1>,<параметр2>..."
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
msgid "synonym for --dirstat=cumulative"
msgstr "синонім для --dirstat=cumulative"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "синонім для --dirstat=files,параметр1,параметр2..."
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "синонім для --dirstat=files,<параметр1>,<параметр2>..."
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr ""
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "згенерувати різницю за алгоритмом \"histogram diff\""
-msgid "<algorithm>"
-msgstr "<алгоритм>"
-
-msgid "choose a diff algorithm"
-msgstr "вибрати алгоритм різниці"
-
msgid "<text>"
msgstr "<текст>"
#. conflict in a submodule. The first argument is the submodule
#. name, and the second argument is the abbreviated id of the
#. commit that needs to be merged. For example:
-#. - go to submodule (mysubmodule), and either merge commit abc1234"
+#. - go to submodule (mysubmodule), and either merge commit abc1234"
#.
#, c-format
msgid ""
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "multi-pack-index OID розсіювання має невірний розмір"
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr ""
+"невірна послідовність oid fanout: fanout[%d] = %<PRIx32> > %<PRIx32> = "
+"fanout[%d]"
+
msgid "multi-pack-index OID lookup chunk is the wrong size"
-msgstr "multi-pack-index шматок пошуку OID має невірний розмір"
+msgstr "multi-pack-index OID lookup шматок має невірний розмір"
msgid "multi-pack-index object offset chunk is the wrong size"
-msgstr ""
-"multi-pack-index необхідній шматок зміщення обʼєкта має невірний розмір"
+msgstr "multi-pack-index object offset шматок має невірний розмір"
#, c-format
msgid "multi-pack-index file %s is too small"
msgstr "версія хешу multi-pack-index %u не збігається з версією %u"
msgid "multi-pack-index required pack-name chunk missing or corrupted"
-msgstr ""
-"multi-pack-index необхідний шматок імені пакунка відсутній або пошкоджений"
+msgstr "необхідний шматок pack-name multi-pack-index відсутній або пошкоджений"
msgid "multi-pack-index required OID fanout chunk missing or corrupted"
msgstr ""
-"multi-pack-index необхідний шматок розсіювання OID відсутній або пошкоджений"
+"необхідний шматок OID fanout multi-pack-index відсутній або пошкоджений"
msgid "multi-pack-index required OID lookup chunk missing or corrupted"
msgstr ""
-"multi-pack-index необхідний шматок пошуку OID відсутній або пошкоджений"
+"необхідний шматок OID lookup multi-pack-index відсутній або пошкоджений"
msgid "multi-pack-index required object offsets chunk missing or corrupted"
msgstr ""
-"multi-pack-index необхідний шматок зміщення обʼєктів відсутній або "
-"пошкоджений"
+"необхідний шматок object offsets multi-pack-index відсутній або пошкоджений"
msgid "multi-pack-index pack-name chunk is too short"
-msgstr "multi-pack-index pack-name шматок занадто малий"
+msgstr "шматок pack-name multi-pack-index занадто малий"
#, c-format
msgid "multi-pack-index pack names out of order: '%s' before '%s'"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "невірний pack-int-id: %u (%u всього пакунків)"
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX не містить шматок BTMP"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "не вдалося завантажити бітмаповий пакунок %<PRIu32>"
+
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr ""
"multi-pack-index зберігає 64-бітне зміщення, але значення off_t занадто мале"
msgid "multi-pack-index large offset out of bounds"
-msgstr "multi-pack-index large зсув виходить за межі"
+msgstr "large offset multi-pack-index виходить за межі"
#, c-format
msgid "failed to add packfile '%s'"
msgid "Looking for referenced packfiles"
msgstr "Пошук файлів пакунків, на які є посилання"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr ""
-"невірна послідовність oid розсіювання: fanout[%d] = %<PRIx32> > %<PRIx32> = "
-"fanout[%d]"
-
msgid "the midx contains no oid"
msgstr "midx не містить oid"
#. TRANSLATORS: This is a line of ambiguous commit
#. object output. E.g.:
#. *
-#. "deadbeef commit 2021-01-01 - Some Commit Message"
+#. "deadbeef commit 2021-01-01 - Some Commit Message"
#.
#, c-format
msgid "%s commit %s - %s"
#. TRANSLATORS: This is a line of ambiguous
#. tag object output. E.g.:
#. *
-#. "deadbeef tag 2022-01-01 - Some Tag Message"
+#. "deadbeef tag 2022-01-01 - Some Tag Message"
#. *
#. The second argument is the YYYY-MM-DD found
#. in the tag.
#. tag object output where we couldn't parse
#. the tag itself. E.g.:
#. *
-#. "deadbeef [bad tag, could not parse it]"
+#. "deadbeef [bad tag, could not parse it]"
#.
#, c-format
msgid "%s [bad tag, could not parse it]"
msgid "could not open pack %s"
msgstr "не вдалося відкрити пакунок %s"
+msgid "could not determine MIDX preferred pack"
+msgstr "не вдалося визначити бажаний пакунок MIDX"
+
#, c-format
msgid "preferred pack (%s) is invalid"
msgstr "бажаний пакунок (%s) є неприпустимим"
msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
msgstr "пошкоджений ewah bitmap: урізаний заголовок для bitmap коміту \"%s\""
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr ""
+"не вдалося завантажити пакунок: \"%s\", вимкнення повторного використання "
+"пакунків"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "обʼєкт \"%s\" не знайдено в типах bitmap"
msgid "multi-pack-index reverse-index chunk is the wrong size"
msgstr "multi-pack-index reverse-index шматок має невірний розмір"
+msgid "could not determine preferred pack"
+msgstr "не вдалося визначити бажаний пакунок"
+
msgid "cannot both write and verify reverse index"
msgstr "неможливо одночасно записувати та звіряти зворотний індекс"
msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
msgstr "%s очікує невід'ємне ціле значення з опціональним суфіксом k/m/g"
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s несумісний з %s"
-
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgstr "неоднозначна опція: %s (може бути --%s%s або --%s%s)"
#, c-format
msgid "bad boolean environment value '%s' for '%s'"
-msgstr "невÑ\96Ñ\80не бÑ\83леве знаÑ\87еннÑ\8f конÑ\84Ñ\96гÑ\83Ñ\80аÑ\86Ñ\96Ñ\97 \"%s\" для \"%s\""
+msgstr "невÑ\96Ñ\80не бÑ\83леве знаÑ\87еннÑ\8f оÑ\82оÑ\87еннÑ\8f \"%s\" для \"%s\""
#, c-format
msgid "failed to parse %s"
msgid "unable to add '%s' to index"
msgstr "не вдалося додати \"%s\" до індексу"
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "не вдалося виконати stat для \"%s\""
-
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgstr "\"%s\" відображається як файл і як каталог"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "неможливо обробити \"%s\" і \"%s\" одночасно"
-#, c-format
-msgid "could not remove reference %s"
-msgstr "не вдалося видалити посилання %s"
-
#, c-format
msgid "could not delete reference %s: %s"
msgstr "не вдалося видалити посилання %s: %s"
msgid "Autostash exists; creating a new stash entry."
msgstr "Автосхов існує; створення нового запису схову."
+msgid "autostash reference is a symref"
+msgstr "посилання автосхову є символьним посиланням"
+
msgid "could not detach HEAD"
msgstr "не вдалося відʼєднати HEAD"
msgid "invalid initial branch name: '%s'"
msgstr "неприпустиме початкове ім’я гілки: \"%s\""
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init: ігноровано --initial-branch=%s"
+
#, c-format
msgid "unable to handle file type %d"
msgstr "не вдалося обробити тип файлу %d"
msgid "attempt to reinitialize repository with different hash"
msgstr "спроба переініціалізувати репозиторій з іншим хеш-алгоритмом"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr "спроба переініціалізувати сховище з іншим форматом зберігання"
+
#, c-format
msgid "%s already exists"
msgstr "%s вже існує"
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init: ігноровано --initial-branch=%s"
-
#, c-format
msgid "Reinitialized existing shared Git repository in %s%s\n"
msgstr "Переініціалізовано існуюче спільне Git сховище в %s%s\n"
msgstr ""
"кількість записів у дереві кешу, які потрібно анулювати (за замовчуванням 0)"
-msgid "unhandled options"
-msgstr "необроблені опції"
-
-msgid "error preparing revisions"
-msgstr "помилка при підготовці ревізій"
-
#, c-format
msgid "commit %s is not marked reachable"
msgstr "коміт %s не позначений як досяжний"
msgid "invalid remote service path"
msgstr "неприпустимий шлях до віддаленої служби"
-msgid "operation not supported by protocol"
-msgstr "операція не підтримується протоколом"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "неможливо підключитися до підсервісу %s"
msgid "support for protocol v2 not implemented yet"
msgstr "підтримка протоколу v2 ще не запроваджена"
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "невідоме значення для конфігурації \"%s\": %s"
-
#, c-format
msgid "transport '%s' not allowed"
msgstr "засіб передачі \"%s\" не дозволений"
msgid "could not retrieve server-advertised bundle-uri list"
msgstr "не вдалося отримати список адрес пакетів, оголошений сервером"
+msgid "operation not supported by protocol"
+msgstr "операція не підтримується протоколом"
+
msgid "too-short tree object"
msgstr "занадто короткий обʼєкт дерева"
msgstr "не вдалося отримати випадкові байти"
msgid "Unmerged paths:"
-msgstr "не злиті шляхи:"
+msgstr "Ð\9dе злиті шляхи:"
msgid " (use \"git restore --staged <file>...\" to unstage)"
msgstr ""
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "неможливо виконати %s: Ваш індекс містить незакомічені зміни."
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "невідомий стиль \"%s\" наданий для \"%s\""
+
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
# commit | 提交
# commit message | 提交说明
# commit object | 提交对象
+# commit-graph | 提交图
# commit-ish (also committish) | 提交号
# cone | 锥形(稀疏检出模型);锥(稀疏检出)
# conflict | 冲突
# plumbing | 管件(Git 底层核心命令的别称)
# porcelain | 瓷件(Git 上层封装命令的别称)
# precious-objects repo | 珍品仓库
+# preferred pack | 首选包(多包索引中引入的首选包概念)
# promisor | 承诺者
# prune | 清除
# pull | 拉,拉取
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-10 10:49+0800\n"
-"PO-Revision-Date: 2023-11-10 17:13+0800\n"
+"POT-Creation-Date: 2024-02-16 14:27+0800\n"
+"PO-Revision-Date: 2024-02-18 11:47+0800\n"
"Last-Translator: Teng Long <dyroneteng@gmail.com>\n"
"Language-Team: GitHub <https://github.com/dyrone/git/>\n"
"Language: zh_CN\n"
msgstr "未关闭的引号"
#: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c
-#: builtin/receive-pack.c builtin/tag.c
+#: builtin/receive-pack.c builtin/tag.c t/helper/test-pkt-line.c
msgid "too many arguments"
msgstr "太多参数"
msgstr "未能识别的空白字符忽略选项 '%s'"
#: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c
-#: builtin/checkout.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.c
-#: builtin/pack-objects.c builtin/push.c builtin/rebase.c builtin/repack.c
-#: builtin/reset.c builtin/rev-list.c builtin/show-branch.c builtin/stash.c
+#: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c
+#: builtin/describe.c builtin/diff-tree.c builtin/difftool.c
+#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c
+#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c
+#: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c
+#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-list.c
+#: builtin/rev-parse.c builtin/show-branch.c builtin/stash.c
#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c
#: range-diff.c revision.c
#, c-format
msgid "Unexpected option --output"
msgstr "未知参数 --output"
+#: archive.c
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "额外的命令行参数:'%s'"
+
#: archive.c
#, c-format
msgid "Unknown archive format '%s'"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "错误的 --attr-source 或 GIT_ATTR_SOURCE"
+#: attr.c read-cache.c
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "无法对 %s 执行 stat"
+
+#: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c
+#: builtin/pack-objects.c combine-diff.c rerere.c
+#, c-format
+msgid "unable to read %s"
+msgstr "不能读 %s"
+
#: bisect.c
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "'%2$s' 的错误动作 '%1$s'"
#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c diff-merges.c gpg-interface.c ls-refs.c parallel-checkout.c
-#: sequencer.c setup.c
+#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c
+#: parallel-checkout.c sequencer.c setup.c
#, c-format
msgid "invalid value for '%s': '%s'"
msgstr "'%s' 的值无效:'%s'"
msgid "applying to an empty history"
msgstr "正应用到一个空历史上"
-#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c
-#: t/helper/test-fast-rebase.c
+#: builtin/am.c builtin/commit.c builtin/merge.c builtin/replay.c sequencer.c
msgid "failed to write commit object"
msgstr "无法写提交对象"
msgstr "n"
#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
-#: builtin/diagnose.c builtin/for-each-ref.c builtin/ls-files.c
-#: builtin/ls-tree.c builtin/replace.c builtin/tag.c builtin/verify-tag.c
+#: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c
+#: builtin/ls-files.c builtin/ls-tree.c builtin/replace.c builtin/tag.c
+#: builtin/verify-tag.c
msgid "format"
msgstr "格式"
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-{old|good}=<术语>] [--no-checkout] [--first-parent] [<坏> [<好>...]] [--] [<路径规格>...]"
+msgstr ""
+"git bisect start [--term-{new|bad}=<术语> --term-{old|good}=<术语>] [--no-"
+"checkout] [--first-parent] [<坏> [<好>...]] [--] [<路径规格>...]"
#: builtin/bisect.c
msgid "git bisect (good|bad) [<rev>...]"
#: builtin/branch.c
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
-msgstr ""
-"分支 '%s' 没有完全合并。\n"
-"如果您确认要删除它,执行 'git branch -D %s'"
+msgid "the branch '%s' is not fully merged"
+msgstr "分支 '%s' 没有完全合并"
+
+#: builtin/branch.c
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "如果您确认要删除它,执行 'git branch -D %s'"
#: builtin/branch.c
msgid "update of config-file failed"
msgid "HEAD is now at"
msgstr "HEAD 目前位于"
-#: builtin/checkout.c builtin/clone.c t/helper/test-fast-rebase.c
+#: builtin/checkout.c builtin/clone.c
msgid "unable to update HEAD"
msgstr "不能更新 HEAD"
msgstr "新分支"
#: builtin/checkout.c
-msgid "new unparented branch"
-msgstr "æ\96°ç\9a\84没æ\9c\89ç\88¶æ\8f\90交的分支"
+msgid "new unborn branch"
+msgstr "æ\96°ç\9a\84æ\9cªè¯\9eç\94\9f的分支"
#: builtin/checkout.c builtin/merge.c
msgid "update ignored files (default)"
msgid "you must specify path(s) to restore"
msgstr "您必须指定要恢复的路径"
-#: builtin/checkout.c builtin/clone.c builtin/remote.c
+#: builtin/checkout.c builtin/clone.c builtin/remote.c builtin/replay.c
#: builtin/submodule--helper.c builtin/worktree.c
msgid "branch"
msgstr "分支"
msgstr ""
"clean.requireForce 默认为 true 且未提供 -i、-n 或 -f 选项,拒绝执行清理动作"
-#: builtin/clean.c
-msgid "-x and -X cannot be used together"
-msgstr "-x 和 -X 不能同时使用"
-
#: builtin/clone.c
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<选项>] [--] <仓库> [<路径>]"
msgstr "从一个特定时间创建一个浅克隆"
#: builtin/clone.c builtin/fetch.c builtin/pull.c builtin/rebase.c
+#: builtin/replay.c
msgid "revision"
msgstr "版本"
msgid "separate git dir from working tree"
msgstr "git目录和工作区分离"
+#: builtin/clone.c builtin/init-db.c
+msgid "specify the reference format to use"
+msgstr "指定要使用的引用格式"
+
#: builtin/clone.c
msgid "key=value"
msgstr "key=value"
msgid "You must specify a repository to clone."
msgstr "您必须指定一个仓库来克隆。"
-#: builtin/clone.c
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr "--bundle-uri 与 --depth、--shallow-since 和 --shallow-exclude 不兼容"
+#: builtin/clone.c builtin/init-db.c setup.c
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "未知的引用存储格式 '%s'"
#: builtin/clone.c
#, c-format
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <split-options>"
msgstr ""
"git commit-graph write [--object-dir <目录>] [--append]\n"
" [--split[=<策略>]] [--reachable | --stdin-packs | --"
#: builtin/commit-graph.c
msgid "if the commit-graph is split, only verify the tip file"
-msgstr "如果提交图形被拆分,只验证头一个文件"
+msgstr "如果提交图被拆分,只验证头一个文件"
#: builtin/commit-graph.c
#, c-format
msgid "Could not open commit-graph '%s'"
-msgstr "无法打开提交图形 '%s'"
+msgstr "无法打开提交图 '%s'"
#: builtin/commit-graph.c
#, c-format
msgid "could not open commit-graph chain '%s'"
-msgstr "无法打开提交图形链 '%s'"
+msgstr "无法打开提交图链 '%s'"
#: builtin/commit-graph.c
#, c-format
#: builtin/commit-graph.c
msgid "allow writing an incremental commit-graph file"
-msgstr "允许写一个增量提交图形文件"
+msgstr "允许写一个增量提交图文件"
#: builtin/commit-graph.c
msgid "maximum number of commits in a non-base split commit-graph"
-msgstr "在非基本拆分提交图形中的最大提交数"
+msgstr "在非基本拆分提交图中的最大提交数"
#: builtin/commit-graph.c
msgid "maximum ratio between two levels of a split commit-graph"
-msgstr "一个拆分提交图形的两个级别之间的最大比率"
+msgstr "一个拆分提交图的两个级别之间的最大比率"
#: builtin/commit-graph.c
msgid "only expire files older than a given date-time"
msgid "unable to read tree (%s)"
msgstr "无法读取树(%s)"
+#: builtin/grep.c
+#, c-format
+msgid "unable to read tree %s"
+msgstr "无法读取树 %s"
+
#: builtin/grep.c
#, c-format
msgid "unable to grep from object of type %s"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "发现 %s 出现 SHA1 冲突!"
-#: builtin/index-pack.c builtin/pack-objects.c
-#, c-format
-msgid "unable to read %s"
-msgstr "不能读 %s"
-
#: builtin/index-pack.c
#, c-format
msgid "cannot read existing object info %s"
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=<模板目录>]\n"
" [--separate-git-dir <git 目录>] [--object-format=<格式>]\n"
+" [--ref-format=<格式>]\n"
" [-b <分支名> | --initial-branch=<分支名>]\n"
" [--shared[=<权限>]] [<目录>]"
"<file>"
msgstr "跟踪 <文件> 中 <开始>,<结束> 范围内的行或函数 :<函数名> 的演变"
-#: builtin/log.c builtin/shortlog.c bundle.c
+#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c
#, c-format
msgid "unrecognized argument: %s"
msgstr "未能识别的参数:%s"
"git merge-file [<选项>] [-L <名字1> [-L <初始名字> [-L <名字2>]]] <文件1> <初"
"始文件> <文件2>"
+#: builtin/merge-file.c diff.c
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr "选项 diff-algorithm 接受参数 \"myers\"、\"minimal\"、\"patience\" 和 \"histogram\""
+
#: builtin/merge-file.c
msgid "send results to standard output"
msgstr "将结果发送到标准输出"
msgid "for conflicts, use a union version"
msgstr "如果冲突,使用联合版本"
+#: builtin/merge-file.c diff.c
+msgid "<algorithm>"
+msgstr "<算法>"
+
+#: builtin/merge-file.c diff.c
+msgid "choose a diff algorithm"
+msgstr "选择一个差异算法"
+
#: builtin/merge-file.c
msgid "for conflicts, use this marker size"
msgstr "如果冲突,使用指定长度的标记"
msgid "unknown strategy option: -X%s"
msgstr "未知的策略选项:-X%s"
-#: builtin/merge-tree.c
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base 与 --stdin 不兼容"
-
#: builtin/merge-tree.c builtin/notes.c
#, c-format
msgid "malformed input line: '%s'."
msgid "Bad branch.%s.mergeoptions string: %s"
msgstr "坏的 branch.%s.mergeoptions 字符串:%s"
-#: builtin/merge.c builtin/stash.c merge-recursive.c
+#: builtin/merge.c merge-recursive.c
msgid "Unable to write index."
msgstr "不能写入索引。"
msgid "Not handling anything other than two heads merge."
msgstr "未处理两个头合并之外的任何操作。"
-#: builtin/merge.c t/helper/test-fast-rebase.c
+#: builtin/merge.c
#, c-format
msgid "unable to write %s"
msgstr "不能写 %s"
msgid "inconsistency with delta count"
msgstr "不一致的差异计数"
+#: builtin/pack-objects.c
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "无效的 pack.allowPackReuse 值:'%s'"
+
#: builtin/pack-objects.c
#, c-format
msgid ""
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"总共 %<PRIu32>(差异 %<PRIu32>),复用 %<PRIu32>(差异 %<PRIu32>),包复用 "
-"%<PRIu32>"
+"%<PRIu32>(来自 %<PRIuMAX> 个包)"
#: builtin/pack-redundant.c
msgid ""
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr "动作 --edit-todo 只能用在交互式变基过程中。"
-#: builtin/rebase.c t/helper/test-fast-rebase.c
+#: builtin/rebase.c
msgid "Cannot read HEAD"
msgstr "不能读取 HEAD"
msgid "switch `C' expects a numerical value"
msgstr "开关 `C' 期望一个数字值"
-#: builtin/rebase.c
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr "应用的选项与 rebase.autoSquash 不兼容。考虑加上 --no-autosquash"
-
#: builtin/rebase.c
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
msgid_plural ""
"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
"to delete them, use:"
-msgstr[0] "注意:ref/remotes 层级之外的一个分支未被移除。要删除它,使用:"
-msgstr[1] "注意:ref/remotes 层级之外的一些分支未被移除。要删除它们,使用:"
+msgstr[0] "注意:refs/remotes/ 层级之外的一个分支未被移除。要删除它,使用:"
+msgstr[1] "注意:refs/remotes/ 层级之外的一些分支未被移除。要删除它们,使用:"
#: builtin/remote.c
#, c-format
msgid "only one pattern can be given with -l"
msgstr "只能为 -l 提供一个模式"
+#: builtin/replay.c
+msgid "need some commits to replay"
+msgstr "需要一些提交来重放"
+
+#: builtin/replay.c
+msgid "--onto and --advance are incompatible"
+msgstr "--onto 和 --advance 不兼容"
+
+#: builtin/replay.c
+msgid "all positive revisions given must be references"
+msgstr "提供的所有正向版本必须为引用"
+
+#: builtin/replay.c
+msgid "argument to --advance must be a reference"
+msgstr "--advance 的参数必须是引用"
+
+#: builtin/replay.c
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr "不能使用多个源推进目标,因为无法明确如何排序"
+
+#: builtin/replay.c
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr "不能隐式地确定这是 --advance 还是 --onto 的操作"
+
+#: builtin/replay.c
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr "不能使用多个源分支推进目标,因为无法明确如何排序"
+
+#: builtin/replay.c
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "不能隐式地确定 --onto 正确的基线"
+
+#: builtin/replay.c
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr "(试验中!)git replay ([--contained] --onto <新基线> | --advance <分支>) <版本范围>..."
+
+#: builtin/replay.c
+msgid "make replay advance given branch"
+msgstr "重放时演进给定的分支"
+
+#: builtin/replay.c
+msgid "replay onto given commit"
+msgstr "重放到给定提交"
+
+#: builtin/replay.c
+msgid "advance all branches contained in revision-range"
+msgstr "演进版本范围中包含的所有分支"
+
+#: builtin/replay.c
+msgid "option --onto or --advance is mandatory"
+msgstr "选项 --onto 或 --advance 必须指定其一"
+
+#: builtin/replay.c
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr "一些版本遍历选项将被覆盖,如 'struct rev_info' 中的 '%s' 位将被强制设定"
+
+#: builtin/replay.c
+msgid "error preparing revisions"
+msgstr "准备版本时错误"
+
+#: builtin/replay.c
+msgid "replaying down to root commit is not supported yet!"
+msgstr "目前还不支持重放到根提交!"
+
+#: builtin/replay.c
+msgid "replaying merge commits is not supported yet!"
+msgstr "目前还不支持重放到合并提交!"
+
#: builtin/rerere.c
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgid "unknown mode for --abbrev-ref: %s"
msgstr "未知的 --abbrev-ref 模式:%s"
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden 不能与 --branches 一起使用"
-
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden 不能与 --tags 一起使用"
-
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden 不能与 --remotes 一起使用"
-
#: builtin/rev-parse.c setup.c
msgid "this operation must be run in a work tree"
msgstr "该操作必须在一个工作区中运行"
msgid "show refs from stdin that aren't in local repository"
msgstr "显示从标准输入中读入的不在本地仓库中的引用"
-#: builtin/show-ref.c
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "选项 '%s'、'%s' 或 '%s' 只能使用其一"
-
#: builtin/sparse-checkout.c
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
#: builtin/worktree.c
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"If you meant to create a worktree containing a new unborn branch\n"
"(branch with no commits) for this repository, you can do so\n"
"using the --orphan flag:\n"
"\n"
" git worktree add --orphan -b %s %s\n"
msgstr ""
-"如果你打算为此仓库创建一个包含新的孤立分支\n"
-"(没有提交的分支)的工作区,你可以使用选项\n"
-"--orphan 来执行此操作:\n"
+"如果你打算为此仓库创建一个包含新的未诞生的\n"
+"分支(没有提交的分支)的工作区,你可以使用\n"
+"选项 --orphan 来执行此操作:\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 orphan branch\n"
+"If you meant to create a worktree containing a new unborn branch\n"
"(branch with no commits) for this repository, you can do so\n"
"using the --orphan flag:\n"
"\n"
" git worktree add --orphan %s\n"
msgstr ""
-"如果你打算为此仓库创建一个包含新的孤立分支\n"
-"(没有提交的分支)的工作区,你可以使用选项\n"
-"--orphan 来执行此操作:\n"
+"如果你打算为此仓库创建一个包含新的未诞生的\n"
+"分支(没有提交的分支)的工作区,你可以使用\n"
+"选项 --orphan 来执行此操作:\n"
"\n"
" git worktree add --orphan %s\n"
msgid "initializing"
msgstr "初始化"
+#: builtin/worktree.c
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "无法找到已创建的工作树 '%s'"
+
#: builtin/worktree.c
#, c-format
msgid "Preparing worktree (new branch '%s')"
"尽管已配置远程仓库,但不存在任何本地的或远程的引用,操作终止。\n"
"请先使用 'add -f' 来覆盖或拉取一个远程仓库"
-#: builtin/worktree.c
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "'%s' 和 '%s' 不能同时使用"
-
#: builtin/worktree.c
msgid "checkout <branch> even if already checked out in other worktree"
msgstr "检出 <分支>,即使已经被检出到其它工作区"
msgstr "创建或重置一个分支"
#: builtin/worktree.c
-msgid "create unborn/orphaned branch"
-msgstr "创建一个尚未诞生的/孤立的分支"
+msgid "create unborn branch"
+msgstr "创建一个尚未诞生的分支"
#: builtin/worktree.c
msgid "populate the new working tree"
#: builtin/worktree.c
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "选项 '%s' 与 '%s' 不能同时使用"
-
-#: builtin/worktree.c
-msgid "<commit-ish>"
-msgstr "<提交号>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "选项 '%s' 和提交号不能同时使用"
#: builtin/worktree.c
msgid "added with --lock"
msgid "Create, list, delete refs to replace objects"
msgstr "创建、列出、删除对象替换引用"
+#: command-list.h
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr "试验中:基于一个新基线重放提交,同样适用于纯仓库"
+
#: command-list.h
msgid "Generates a summary of pending changes"
msgstr "生成待定更改的摘要"
#: commit-graph.c
msgid "commit-graph file is too small"
-msgstr "提交图形文件太小"
+msgstr "提交图文件太小"
+
+#: commit-graph.c
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "提交图中对象 ID 的扇出块大小错误"
+
+#: commit-graph.c
+msgid "commit-graph fanout values out of order"
+msgstr "提交图的扇出值失序"
+
+#: commit-graph.c
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "提交图的对象 ID 查询块大小错误"
+
+#: commit-graph.c
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "提交图的提交数据块大小错误"
+
+#: commit-graph.c
+msgid "commit-graph generations chunk is wrong size"
+msgstr "提交图的世代块大小错误"
+
+#: commit-graph.c
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "提交图的变更路径的索引块太小"
+
+#: commit-graph.c
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr "忽略提交图文件中过小的更改路径块(%<PRIuMAX> < %<PRIuMAX>)"
#: commit-graph.c
#, c-format
msgid "commit-graph signature %X does not match signature %X"
-msgstr "提交图形签名 %X 和签名 %X 不匹配"
+msgstr "提交图签名 %X 和签名 %X 不匹配"
#: commit-graph.c
#, c-format
msgid "commit-graph version %X does not match version %X"
-msgstr "提交图形版本 %X 和版本 %X 不匹配"
+msgstr "提交图版本 %X 和版本 %X 不匹配"
#: commit-graph.c
#, c-format
msgid "commit-graph hash version %X does not match version %X"
-msgstr "æ\8f\90交å\9b¾å½¢å\93\88å¸\8cç\89\88æ\9c¬ %X å\92\8cç\89\88æ\9c¬ %X ä¸\8då\8c¹é\85\8d"
+msgstr "提交图哈希版本 %X 和版本 %X 不匹配"
#: commit-graph.c
#, c-format
msgid "commit-graph file is too small to hold %u chunks"
-msgstr "提交图形文件太小,容不下 %u 个块"
+msgstr "提交图文件太小,容不下 %u 个块"
+
+#: commit-graph.c
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr "提交图所需的对象 ID 扇出块缺失或损坏"
+
+#: commit-graph.c
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr "提交图所需的对象 ID 查询块缺失或损坏"
+
+#: commit-graph.c
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr "提交图所需的提交数据块缺失或损坏"
#: commit-graph.c
msgid "commit-graph has no base graphs chunk"
-msgstr "提交图形没有基础图形块"
+msgstr "提交图没有基础图形块"
#: commit-graph.c
msgid "commit-graph base graphs chunk is too small"
-msgstr "提交图形的基础图形块过小"
+msgstr "提交图的基础图形块过小"
#: commit-graph.c
msgid "commit-graph chain does not match"
-msgstr "提交图形链不匹配"
+msgstr "提交图链不匹配"
#: commit-graph.c
#, c-format
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "基础图形中的提交数量过高:%<PRIuMAX>"
+#: commit-graph.c
+msgid "commit-graph chain file too small"
+msgstr "提交图链文件太小"
+
#: commit-graph.c
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
-msgstr "无效的提交图形链:行 '%s' 不是一个哈希值"
+msgstr "无效的提交图链:行 '%s' 不是一个哈希值"
#: commit-graph.c
msgid "unable to find all commit-graph files"
-msgstr "无法找到所有提交图形文件"
+msgstr "无法找到所有提交图文件"
#: commit-graph.c
msgid "invalid commit position. commit-graph is likely corrupt"
-msgstr "æ\97 æ\95\88ç\9a\84æ\8f\90交ä½\8dç½®ã\80\82æ\8f\90交å\9b¾å½¢å\8f¯è\83½å·²æ\8d\9få\9d\8f"
+msgstr "无效的提交位置。提交图可能已损坏"
#: commit-graph.c
#, c-format
msgid "commit-graph overflow generation data is too small"
msgstr "提交图溢出世代数据过小"
+#: commit-graph.c
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "提交图额外边的指针越界"
+
#: commit-graph.c
msgid "Loading known commits in commit graph"
msgstr "正在加载提交图中的已知提交"
#: commit-graph.c
msgid "unable to open commit-graph chain file"
-msgstr "无法打开提交图形链文件"
+msgstr "无法打开提交图链文件"
#: commit-graph.c
msgid "failed to rename base commit-graph file"
-msgstr "无法重命名基础提交图形文件"
+msgstr "无法重命名基础提交图文件"
#: commit-graph.c
msgid "failed to rename temporary commit-graph file"
-msgstr "无法重命名临时提交图形文件"
+msgstr "无法重命名临时提交图文件"
#: commit-graph.c
#, c-format
msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits"
-msgstr ""
-"无法合并提交图形,总共已累加提交数:%<PRIuMAX>,当前待累加提交数:%<PRIuMAX>"
+msgstr "无法合并提交图,总共已累加提交数:%<PRIuMAX>,当前待累加提交数:%<PRIuMAX>"
#: commit-graph.c
#, c-format
msgid "cannot merge graph %s, too many commits: %<PRIuMAX>"
-msgstr "无法合并提交图形 %s, 提交过多:%<PRIuMAX>"
+msgstr "无法合并提交图 %s, 提交过多:%<PRIuMAX>"
#: commit-graph.c
msgid "Scanning merged commits"
#: commit-graph.c
msgid "Merging commit-graph"
-msgstr "正在合并提交图形"
+msgstr "正在合并提交图"
#: commit-graph.c
msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled"
#: commit-graph.c
#, c-format
msgid "commit-graph has incorrect OID order: %s then %s"
-msgstr "提交图形的对象 ID 顺序不正确:%s 然后 %s"
+msgstr "提交图的对象 ID 顺序不正确:%s 然后 %s"
#: commit-graph.c
#, c-format
msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u"
-msgstr "提交图形有不正确的扇出值:fanout[%d] = %u != %u"
+msgstr "提交图有不正确的扇出值:fanout[%d] = %u != %u"
#: commit-graph.c
#, c-format
msgid "failed to parse commit %s from commit-graph"
-msgstr "无法从提交图形中解析提交 %s"
+msgstr "无法从提交图中解析提交 %s"
#: commit-graph.c
#, c-format
msgid "failed to parse commit %s from object database for commit-graph"
-msgstr "无法从提交图形的对象库中解析提交 %s"
+msgstr "无法从提交图的对象库中解析提交 %s"
#: commit-graph.c
#, c-format
msgid "root tree OID for commit %s in commit-graph is %s != %s"
-msgstr "提交图形中的提交 %s 的根树对象 ID 是 %s != %s"
+msgstr "提交图中的提交 %s 的根树对象 ID 是 %s != %s"
#: commit-graph.c
#, c-format
msgid "commit-graph parent list for commit %s is too long"
-msgstr "提交 %s 的提交图形父提交列表太长了"
+msgstr "提交 %s 的提交图父提交列表太长了"
#: commit-graph.c
#, c-format
msgid "commit-graph parent for %s is %s != %s"
-msgstr "%s 的提交图形父提交是 %s != %s"
+msgstr "%s 的提交图父提交是 %s != %s"
#: commit-graph.c
#, c-format
msgid "commit-graph parent list for commit %s terminates early"
-msgstr "提交 %s 的提交图形父提交列表过早终止"
+msgstr "提交 %s 的提交图父提交列表过早终止"
#: commit-graph.c
#, c-format
msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>"
-msgstr "提交图形中的提交 %s 的世代号是 %<PRIuMAX> < %<PRIuMAX>"
+msgstr "提交图中的提交 %s 的世代号是 %<PRIuMAX> < %<PRIuMAX>"
#: commit-graph.c
#, c-format
msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
-msgstr "提交图形中提交 %s 的提交日期是 %<PRIuMAX> != %<PRIuMAX>"
+msgstr "提交图中提交 %s 的提交日期是 %<PRIuMAX> != %<PRIuMAX>"
#: commit-graph.c
#, c-format
msgid ""
"commit-graph has both zero and non-zero generations (e.g., commits '%s' and "
"'%s')"
-msgstr "æ\8f\90交å\9b¾å½¢å\85·æ\9c\89é\9b¶å\92\8cé\9d\9eé\9b¶ç\9a\84ä¸\96代ï¼\88ä¾\8bå¦\82ï¼\9aæ\8f\90交 '%s' å\92\8c '%s'ï¼\89"
+msgstr "提交图具有零和非零的世代(例如:提交 '%s' 和 '%s')"
#: commit-graph.c
msgid "Verifying commits in commit graph"
#: commit.c
#, c-format
msgid "commit %s exists in commit-graph but not in the object database"
-msgstr "提交 %s 存在于提交图形中,但不存在于对象数据库中"
+msgstr "提交 %s 存在于提交图中,但不存在于对象数据库中"
#: commit.c
#, c-format
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "配置变量 'diff.submodule' 未知的取值:'%s'"
+#: diff.c transport.c
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "配置 '%s' 未知的取值:%s"
+
#: diff.c
#, c-format
msgid ""
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "--color-moved-ws 中的无效模式 '%s' "
-#: diff.c
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"diff-algorithm 选项有 \"myers\"、\"minimal\"、\"patience\" 和 \"histogram\""
-
#: diff.c
#, c-format
msgid "invalid argument to %s"
msgstr "只输出 --stat 的最后一行"
#: diff.c
-msgid "<param1,param2>..."
-msgstr "<参数1,参数2>..."
+msgid "<param1>,<param2>..."
+msgstr "<参数1>,<参数2>..."
#: diff.c
msgid ""
msgstr "和 --dirstat=cumulative 同义"
#: diff.c
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "是 --dirstat=files,param1,param2... 的同义词"
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "是 --dirstat=files,<参数1>,<参数2>... 的同义词"
#: diff.c
msgid "warn if changes introduce conflict markers or whitespace errors"
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "使用 \"histogram diff\" 算法生成差异"
-#: diff.c
-msgid "<algorithm>"
-msgstr "<算法>"
-
-#: diff.c
-msgid "choose a diff algorithm"
-msgstr "选择一个差异算法"
-
#: diff.c
msgid "<text>"
msgstr "<文本>"
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "多包索引的对象 ID 扇出表大小错误"
+#: midx.c
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr "对象 ID 扇出失序:fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+
#: midx.c
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "多包索引的对象 ID 查询块大小错误"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "错的 pack-int-id:%u(共有 %u 个包)"
+#: midx.c
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "多包索引中未包含 BTMP 块"
+
+#: midx.c
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "不能打开已被位图索引的包 %<PRIu32>"
+
#: midx.c
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr "多包索引存储一个64位偏移,但是 off_t 太小"
msgid "Looking for referenced packfiles"
msgstr "正在查找引用的包文件"
-#: midx.c
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr "对象 ID 扇出无序:fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-
#: midx.c
msgid "the midx contains no oid"
msgstr "midx 不包含 oid"
msgid "could not open pack %s"
msgstr "不能打开包 %s"
+#: pack-bitmap.c t/helper/test-read-midx.c
+msgid "could not determine MIDX preferred pack"
+msgstr "不能确定多包索引的首选包"
+
#: pack-bitmap.c
#, c-format
msgid "preferred pack (%s) is invalid"
msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
msgstr "损坏的 EWAH 位图:提交 \"%s\" 位图的文件头被截断"
+#: pack-bitmap.c
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr "无法打开包:'%s',禁用包重用"
+
#: pack-bitmap.c
#, c-format
msgid "object '%s' not found in type bitmaps"
msgid "multi-pack-index reverse-index chunk is the wrong size"
msgstr "多包索引的反向索引块大小错误"
+#: pack-revindex.c
+msgid "could not determine preferred pack"
+msgstr "无法确定首选包"
+
#: pack-write.c
msgid "cannot both write and verify reverse index"
msgstr "无法同时写入和校验反向索引"
msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
msgstr "%s 期望一个非负整数和一个可选的 k/m/g 后缀"
-#: parse-options.c
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s 与 %s 不兼容"
-
#: parse-options.c
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgid "unable to add '%s' to index"
msgstr "无法在索引中添加 '%s'"
-#: read-cache.c
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "无法对 %s 执行 stat"
-
#: read-cache.c
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "无法同时处理 '%s' 和 '%s'"
-#: refs/files-backend.c
-#, c-format
-msgid "could not remove reference %s"
-msgstr "无法删除引用 %s"
-
-#: refs/files-backend.c refs/packed-backend.c
+#: refs.c
#, c-format
msgid "could not delete reference %s: %s"
msgstr "无法删除引用 %s:%s"
-#: refs/files-backend.c refs/packed-backend.c
+#: refs.c
#, c-format
msgid "could not delete references: %s"
msgstr "无法删除引用:%s"
msgid "corrupt author: missing date information"
msgstr "损坏的作者:缺失日期信息"
-#: sequencer.c t/helper/test-fast-rebase.c
+#: sequencer.c
#, c-format
msgid "could not update %s"
msgstr "不能更新 %s"
msgid "Autostash exists; creating a new stash entry."
msgstr "自动贮藏已经存在;正在创建一个新的贮藏条目。"
+#: sequencer.c
+msgid "autostash reference is a symref"
+msgstr "自动贮藏的引用是一个符号引用"
+
#: sequencer.c
msgid "could not detach HEAD"
msgstr "不能分离头指针"
msgid "invalid initial branch name: '%s'"
msgstr "无效的初始分支名:'%s'"
+#: setup.c
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init:已忽略 --initial-branch=%s"
+
#: setup.c
#, c-format
msgid "unable to handle file type %d"
msgstr "尝试用不同的哈希算法重新初始化仓库"
#: setup.c
-#, c-format
-msgid "%s already exists"
-msgstr "%s 已经存在"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr "尝试使用不同的引用存储格式重新初始化仓库"
#: setup.c
#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init:已忽略 --initial-branch=%s"
+msgid "%s already exists"
+msgstr "%s 已经存在"
#: setup.c
#, c-format
msgid "number of entries in the cache tree to invalidate (default 0)"
msgstr "缓存树中无效化的条目数量(默认 0)"
-#: t/helper/test-fast-rebase.c
-msgid "unhandled options"
-msgstr "未处理的选项"
-
-#: t/helper/test-fast-rebase.c
-msgid "error preparing revisions"
-msgstr "准备版本时错误"
-
#: t/helper/test-reach.c
#, c-format
msgid "commit %s is not marked reachable"
msgid "invalid remote service path"
msgstr "无效的远程服务路径"
-#: transport-helper.c transport.c
-msgid "operation not supported by protocol"
-msgstr "协议不支持该操作"
-
#: transport-helper.c
#, c-format
msgid "can't connect to subservice %s"
msgid "support for protocol v2 not implemented yet"
msgstr "协议 v2 的支持尚未实现"
-#: transport.c
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "配置 '%s' 的取值未知:%s"
-
#: transport.c
#, c-format
msgid "transport '%s' not allowed"
msgid "could not retrieve server-advertised bundle-uri list"
msgstr "无法获取服务器公布的 bundle-uri 列表"
+#: transport.c
+msgid "operation not supported by protocol"
+msgstr "协议不支持该操作"
+
#: tree-walk.c
msgid "too-short tree object"
msgstr "太短的树对象"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "不能%s:您的索引中包含未提交的变更。"
+#: xdiff-interface.c
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "'%2$s' 的未知风格取值 '%1$s'"
+
#: git-merge-octopus.sh git-merge-resolve.sh
msgid ""
"Error: Your local changes to the following files would be overwritten by "
# - Yichao Yu <yyc1992 AT gmail.com>
# - Zhuang Ya <zhuangya AT me.com>
#
-# Yi-Jyun Pan <pan93412@gmail.com>, 2021, 2022, 2023.
+# Yi-Jyun Pan <pan93412@gmail.com>, 2021, 2022, 2023, 2024.
# Kaiyang Wu <self@origincode.me>, 2022.
-# lumynou5 <lumynou5.tw@gmail.com>, 2023.
+# lumynou5 <lumynou5.tw@gmail.com>, 2023, 2024.
msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-19 22:29+0800\n"
-"PO-Revision-Date: 2023-11-19 23:34+0800\n"
+"POT-Creation-Date: 2024-02-18 20:48+0800\n"
+"PO-Revision-Date: 2024-02-18 20:50+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"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Poedit 3.4.1\n"
+"X-Generator: Poedit 3.4.2\n"
"X-ZhConverter: 繁化姬 dict-f4bc617e-r910 @ 2019/11/16 20:23:12 | https://"
"zhconvert.org\n"
msgstr "未閉合的引號"
#: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c
-#: builtin/receive-pack.c builtin/tag.c
+#: builtin/receive-pack.c builtin/tag.c t/helper/test-pkt-line.c
msgid "too many arguments"
msgstr "引數過多"
msgstr "空白字元忽略選項 “%s” 無法識別"
#: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c
-#: builtin/checkout.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.c
-#: builtin/pack-objects.c builtin/push.c builtin/rebase.c builtin/repack.c
-#: builtin/reset.c builtin/rev-list.c builtin/show-branch.c builtin/stash.c
+#: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c
+#: builtin/describe.c builtin/diff-tree.c builtin/difftool.c
+#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c
+#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c
+#: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c
+#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-list.c
+#: builtin/rev-parse.c builtin/show-branch.c builtin/stash.c
#: builtin/submodule--helper.c builtin/tag.c builtin/worktree.c parse-options.c
#: range-diff.c revision.c
#, c-format
#: apply.c
#, c-format
msgid "new mode (%o) of %s does not match old mode (%o)"
-msgstr "%2$s 的新模式 (%1$o) 和舊模式 (%3$o) 不符"
+msgstr "%2$s 的新模式(%1$o)和舊模式(%3$o)不符"
#: apply.c
#, c-format
msgid "new mode (%o) of %s does not match old mode (%o) of %s"
-msgstr "%2$s 的新模式 (%1$o) 和 %4$s 的舊模式 (%3$o) 不符"
+msgstr "%2$s 的新模式(%1$o)和 %4$s 的舊模式(%3$o)不符"
#: apply.c
#, c-format
msgid "Unexpected option --output"
msgstr "非預期選項 --output"
+#: archive.c
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "多出命令列參數 “%s”"
+
#: archive.c
#, c-format
msgid "Unknown archive format '%s'"
msgid "bad --attr-source or GIT_ATTR_SOURCE"
msgstr "無效的 --attr-source 或 GIT_ATTR_SOURCE"
+#: attr.c read-cache.c
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "無法對 %s 執行 stat"
+
+#: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c
+#: builtin/pack-objects.c combine-diff.c rerere.c
+#, c-format
+msgid "unable to read %s"
+msgstr "不能讀 %s"
+
#: bisect.c
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "“%s” 動作對 “%s” 無效"
#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c diff-merges.c gpg-interface.c ls-refs.c parallel-checkout.c
-#: sequencer.c setup.c
+#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c
+#: parallel-checkout.c sequencer.c setup.c
#, c-format
msgid "invalid value for '%s': '%s'"
msgstr "“%s” 的值無效:“%s”"
msgid "applying to an empty history"
msgstr "正在套用至空白歷史記錄上"
-#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c
-#: t/helper/test-fast-rebase.c
+#: builtin/am.c builtin/commit.c builtin/merge.c builtin/replay.c sequencer.c
msgid "failed to write commit object"
msgstr "無法寫入提交物件"
msgstr "n"
#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c
-#: builtin/diagnose.c builtin/for-each-ref.c builtin/ls-files.c
-#: builtin/ls-tree.c builtin/replace.c builtin/tag.c builtin/verify-tag.c
+#: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c
+#: builtin/ls-files.c builtin/ls-tree.c builtin/replace.c builtin/tag.c
+#: builtin/verify-tag.c
msgid "format"
msgstr "format"
#: builtin/branch.c
#, c-format
-msgid ""
-"the branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'"
-msgstr ""
-"分支 “%s” 沒有完全合併。\n"
-"如果確定要刪除它,請執行 “git branch -D %s”"
+msgid "the branch '%s' is not fully merged"
+msgstr "分支 “%s” 沒有完全合併"
+
+#: builtin/branch.c
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "如果確定要刪除它,請執行 “git branch -D %s”"
#: builtin/branch.c
msgid "update of config-file failed"
msgid "HEAD is now at"
msgstr "HEAD 目前位於"
-#: builtin/checkout.c builtin/clone.c t/helper/test-fast-rebase.c
+#: builtin/checkout.c builtin/clone.c
msgid "unable to update HEAD"
msgstr "無法更新 HEAD"
msgstr "new-branch"
#: builtin/checkout.c
-msgid "new unparented branch"
-msgstr "新的,沒有父提交的分支"
+msgid "new unborn branch"
+msgstr "新的未誕生分支"
#: builtin/checkout.c builtin/merge.c
msgid "update ignored files (default)"
msgid "you must specify path(s) to restore"
msgstr "您必須指定要還原的路徑"
-#: builtin/checkout.c builtin/clone.c builtin/remote.c
+#: builtin/checkout.c builtin/clone.c builtin/remote.c builtin/replay.c
#: builtin/submodule--helper.c builtin/worktree.c
msgid "branch"
msgstr "branch"
msgstr ""
"clean.requireForce 預設為 true 且未提供 -i、-n 或 -f 選項,拒絕執行清理動作"
-#: builtin/clean.c
-msgid "-x and -X cannot be used together"
-msgstr "-x 和 -X 不能同時使用"
-
#: builtin/clone.c
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<options>] [--] <repo> [<dir>]"
msgstr "建立從指定時間到現在的淺層複製"
#: builtin/clone.c builtin/fetch.c builtin/pull.c builtin/rebase.c
+#: builtin/replay.c
msgid "revision"
msgstr "revision"
msgid "separate git dir from working tree"
msgstr "git 目錄和工作區分離"
+#: builtin/clone.c builtin/init-db.c
+msgid "specify the reference format to use"
+msgstr "指定要使用的引用格式"
+
#: builtin/clone.c
msgid "key=value"
msgstr "key=value"
msgid "You must specify a repository to clone."
msgstr "您必須指定要複製的版本庫。"
-#: builtin/clone.c
-msgid ""
-"--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
-"exclude"
-msgstr "--bundle-uri 與 --depth、--shallow-since 和 --shallow-exclude 不相容"
+#: builtin/clone.c builtin/init-db.c setup.c
+#, c-format
+msgid "unknown ref storage format '%s'"
+msgstr "未知的引用儲存格式 “%s”"
#: builtin/clone.c
#, c-format
"--stdin-commits]\n"
" [--changed-paths] [--[no-]max-new-filters <n>] [--"
"[no-]progress]\n"
-" <split options>"
+" <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>"
+" <split-options>"
#: builtin/commit-graph.c builtin/fetch.c builtin/log.c builtin/repack.c
msgid "dir"
msgid "unable to read tree (%s)"
msgstr "無法讀取樹(%s)"
+#: builtin/grep.c
+#, c-format
+msgid "unable to read tree %s"
+msgstr "無法讀取 %s 樹狀物件"
+
#: builtin/grep.c
#, c-format
msgid "unable to grep from object of type %s"
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "發現 %s 出現 SHA1 衝突!"
-#: builtin/index-pack.c builtin/pack-objects.c
-#, c-format
-msgid "unable to read %s"
-msgstr "不能讀 %s"
-
#: builtin/index-pack.c
#, c-format
msgid "cannot read existing object info %s"
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>]"
"<file>"
msgstr "追蹤 <開始>,<結束> 範圍中橫列或 <檔案> 中> :<函數名稱> 的變化史"
-#: builtin/log.c builtin/shortlog.c bundle.c
+#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c
#, c-format
msgid "unrecognized argument: %s"
msgstr "無法識別的參數:%s"
"git merge-file [<選項>] [-L <檔案1> [-L <初始> [-L <名字2>]]] <檔案1> <初始文"
"件> <檔案2>"
+#: builtin/merge-file.c diff.c
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"diff-algorithm 選項有 \"myers\"、\"minimal\"、\"patience\" 和 \"histogram\""
+
#: builtin/merge-file.c
msgid "send results to standard output"
msgstr "將結果傳送到標準輸出"
msgid "for conflicts, use a union version"
msgstr "如果衝突,使用聯合版本"
+#: builtin/merge-file.c diff.c
+msgid "<algorithm>"
+msgstr "<演算法>"
+
+#: builtin/merge-file.c diff.c
+msgid "choose a diff algorithm"
+msgstr "選擇一個差異演算法"
+
#: builtin/merge-file.c
msgid "for conflicts, use this marker size"
msgstr "如果衝突,使用指定長度的標記"
msgid "unknown strategy option: -X%s"
msgstr "未知的策略選項:-X%s"
-#: builtin/merge-tree.c
-msgid "--merge-base is incompatible with --stdin"
-msgstr "--merge-base 與 --stdin 不相容"
-
#: builtin/merge-tree.c builtin/notes.c
#, c-format
msgid "malformed input line: '%s'."
msgid "Bad branch.%s.mergeoptions string: %s"
msgstr "壞的 branch.%s.mergeoptions 字串:%s"
-#: builtin/merge.c builtin/stash.c merge-recursive.c
+#: builtin/merge.c merge-recursive.c
msgid "Unable to write index."
msgstr "不能寫入索引。"
msgid "Not handling anything other than two heads merge."
msgstr "未處理兩個頭合併之外的任何動作。"
-#: builtin/merge.c t/helper/test-fast-rebase.c
+#: builtin/merge.c
#, c-format
msgid "unable to write %s"
msgstr "不能寫 %s"
msgid "inconsistency with delta count"
msgstr "不一致的差異計數"
+#: builtin/pack-objects.c
+#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "無效的 pack.allowPackReuse 值:“%s”"
+
#: builtin/pack-objects.c
#, c-format
msgid ""
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
"總共 %<PRIu32> (差異 %<PRIu32>),復用 %<PRIu32> (差異 %<PRIu32>),重用包 "
-"%<PRIu32>"
+"%<PRIu32> (總共 %<PRIuMAX>)"
#: builtin/pack-redundant.c
msgid ""
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr "動作 --edit-todo 只能用在互動式重定基底過程中。"
-#: builtin/rebase.c t/helper/test-fast-rebase.c
+#: builtin/rebase.c
msgid "Cannot read HEAD"
msgstr "不能讀取 HEAD"
msgid "switch `C' expects a numerical value"
msgstr "開關 `C' 期望一個數字值"
-#: builtin/rebase.c
-msgid ""
-"apply options are incompatible with rebase.autoSquash. Consider adding --no-"
-"autosquash"
-msgstr "apply 選項與 rebase.autoSquash 不相容。請考慮加上 --no-autosquash"
-
#: builtin/rebase.c
msgid ""
"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
msgid_plural ""
"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
"to delete them, use:"
-msgstr[0] "注意:ref/remotes 層級之外的一個分支未被移除。要刪除它,使用:"
+msgstr[0] "注意:refs/remotes/ 層級之外的一個分支未被移除。要刪除它,使用:"
#: builtin/remote.c
#, c-format
msgid "only one pattern can be given with -l"
msgstr "只能為 -l 提供一個模式"
+#: builtin/replay.c
+msgid "need some commits to replay"
+msgstr "需要一些提交才能重放"
+
+#: builtin/replay.c
+msgid "--onto and --advance are incompatible"
+msgstr "--onto 和 --advance 不相容"
+
+#: builtin/replay.c
+msgid "all positive revisions given must be references"
+msgstr "提供的所有正向修訂集必須為引用"
+
+#: builtin/replay.c
+msgid "argument to --advance must be a reference"
+msgstr "傳入 --advance 的引數必須為引用"
+
+#: builtin/replay.c
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr "無法用多個來源演進目的地,以免無法確定排序"
+
+#: builtin/replay.c
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr "無法假設這是 --advance 還是 --onto 動作"
+
+#: builtin/replay.c
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr "無法由多個來源分支演進目的地,以免無法確定排序"
+
+#: builtin/replay.c
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "無法假設 --onto 的正確基底"
+
+#: builtin/replay.c
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(實驗性功能!)git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+
+#: builtin/replay.c
+msgid "make replay advance given branch"
+msgstr "在指定分支上進行重放演進"
+
+#: builtin/replay.c
+msgid "replay onto given commit"
+msgstr "重放到指定提交"
+
+#: builtin/replay.c
+msgid "advance all branches contained in revision-range"
+msgstr "演進所有包含在 revision-range 中的分支"
+
+#: builtin/replay.c
+msgid "option --onto or --advance is mandatory"
+msgstr "必須傳入 --onto 或 --advance 選項"
+
+#: builtin/replay.c
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr "將覆寫部分修訂版遍歷選項,強制使用 “struct rev_info” 的 “%s” 位元"
+
+#: builtin/replay.c
+msgid "error preparing revisions"
+msgstr "無法準備修訂集"
+
+#: builtin/replay.c
+msgid "replaying down to root commit is not supported yet!"
+msgstr "尚不支援重放到根提交!"
+
+#: builtin/replay.c
+msgid "replaying merge commits is not supported yet!"
+msgstr "尚不支援重放合併提交!"
+
#: builtin/rerere.c
msgid ""
"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgid "unknown mode for --abbrev-ref: %s"
msgstr "--abbrev-ref 的模式未知:%s"
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --branches"
-msgstr "--exclude-hidden 無法與 --branches 同時使用"
-
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --tags"
-msgstr "--exclude-hidden 無法與 --tags 同時使用"
-
-#: builtin/rev-parse.c revision.c
-msgid "--exclude-hidden cannot be used together with --remotes"
-msgstr "--exclude-hidden 無法與 --remotes 同時使用"
-
#: builtin/rev-parse.c setup.c
msgid "this operation must be run in a work tree"
msgstr "該動作必須在一個工作區中執行"
msgid "show refs from stdin that aren't in local repository"
msgstr "顯示從標準輸入中讀入的不在本機版本庫中的引用"
-#: builtin/show-ref.c
-#, c-format
-msgid "only one of '%s', '%s' or '%s' can be given"
-msgstr "只能傳入 “%s”、“%s” 或 “%s”"
-
#: builtin/sparse-checkout.c
msgid ""
"git sparse-checkout (init | list | set | add | reapply | disable | check-"
#: builtin/worktree.c
#, c-format
msgid ""
-"If you meant to create a worktree containing a new orphan branch\n"
+"If you meant to create a worktree containing a new unborn branch\n"
"(branch with no commits) for this repository, you can do so\n"
"using the --orphan flag:\n"
"\n"
" git worktree add --orphan -b %s %s\n"
msgstr ""
"如果您是想要在這個版本庫建立一個工作區,裡面包含一個\n"
-"孤立分支(即沒有提交的分支),可以使用 --orphan 達到\n"
+"未誕生分支(即沒有提交的分支),可以使用 --orphan 達到\n"
"這個效果:\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 orphan branch\n"
+"If you meant to create a worktree containing a new unborn branch\n"
"(branch with no commits) for this repository, you can do so\n"
"using the --orphan flag:\n"
"\n"
" git worktree add --orphan %s\n"
msgstr ""
"如果您是想要在這個版本庫建立一個工作區,裡面包含一個\n"
-"孤立分支(即沒有提交的分支),可以使用 --orphan 達到\n"
+"未誕生分支(即沒有提交的分支),可以使用 --orphan 達到\n"
"這個效果:\n"
"\n"
" git worktree add --orphan %s\n"
msgid "initializing"
msgstr "正在初始化"
+#: builtin/worktree.c
+#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "找不到建立的工作區「%s」"
+
#: builtin/worktree.c
#, c-format
msgid "Preparing worktree (new branch '%s')"
"即使有提供一個遠端,卻不存在本機或遠端引用,\n"
"故停止。使用 “add -f” 先覆蓋或抓取遠端"
-#: builtin/worktree.c
-#, c-format
-msgid "'%s' and '%s' cannot be used together"
-msgstr "無法同時使用 “%s” 和 “%s”"
-
#: builtin/worktree.c
msgid "checkout <branch> even if already checked out in other worktree"
msgstr "簽出 <分支>,即使已經被簽出到其它工作區"
msgstr "建立或重設一個分支"
#: builtin/worktree.c
-msgid "create unborn/orphaned branch"
-msgstr "建立尚無內容(孤立)的分支"
+msgid "create unborn branch"
+msgstr "建立未誕生分支"
#: builtin/worktree.c
msgid "populate the new working tree"
#: builtin/worktree.c
#, c-format
-msgid "options '%s', and '%s' cannot be used together"
-msgstr "無法同時使用 “%s” 和 “%s” 選項"
-
-#: builtin/worktree.c
-msgid "<commit-ish>"
-msgstr "<提交指示元>"
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "“%s” 選項和提交號不得同時使用"
#: builtin/worktree.c
msgid "added with --lock"
msgid "Create, list, delete refs to replace objects"
msgstr "建立、列出、刪除物件取代引用"
+#: command-list.h
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr "實驗性功能:在新的基底重放提交,亦支援裸版本庫"
+
#: command-list.h
msgid "Generates a summary of pending changes"
msgstr "生成待定更改的摘要"
msgid "commit-graph file is too small"
msgstr "提交圖形檔案太小"
+#: commit-graph.c
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "提交圖形 OID 扇出區塊大小有誤"
+
+#: commit-graph.c
+msgid "commit-graph fanout values out of order"
+msgstr "提交圖形扇出的數值失序"
+
+#: commit-graph.c
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "提交圖形 OID 查詢區塊的大小有誤"
+
+#: commit-graph.c
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "提交圖形的提交資料區塊大小有誤"
+
+#: commit-graph.c
+msgid "commit-graph generations chunk is wrong size"
+msgstr "提交圖形的世代區塊大小有誤"
+
+#: commit-graph.c
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "提交圖形的更動路徑索引區塊過小"
+
+#: commit-graph.c
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr "忽略提交圖形檔案中過小的更動路徑區塊 (%<PRIuMAX> < %<PRIuMAX>)"
+
#: commit-graph.c
#, c-format
msgid "commit-graph signature %X does not match signature %X"
#: commit-graph.c
#, c-format
msgid "commit-graph file is too small to hold %u chunks"
-msgstr "commit-graph 檔案不夠放置 %u 個區塊"
+msgstr "提交圖形檔案不夠放置 %u 個區塊"
+
+#: commit-graph.c
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr "提交圖形需要的 OID 扇出區塊遺失或損壞"
+
+#: commit-graph.c
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr "提交圖形需要的 OID 查詢區塊遺失或損壞"
+
+#: commit-graph.c
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr "提交圖形需要的提交資料區塊遺失或損壞"
#: commit-graph.c
msgid "commit-graph has no base graphs chunk"
msgid "commit count in base graph too high: %<PRIuMAX>"
msgstr "基礎圖 (base graph) 中的提交數過多:%<PRIuMAX>"
+#: commit-graph.c
+msgid "commit-graph chain file too small"
+msgstr "提交圖形鏈檔案過小"
+
#: commit-graph.c
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
-msgstr "無效的提交圖形鏈:行 '%s' 不是一個雜湊值"
+msgstr "無效的提交圖形鏈:「%s」列不是雜湊值"
#: commit-graph.c
msgid "unable to find all commit-graph files"
msgid "commit-graph overflow generation data is too small"
msgstr "提交圖形的溢出世代資料過小"
+#: commit-graph.c
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "提交圖形的延伸邊界指針超出範圍"
+
#: commit-graph.c
msgid "Loading known commits in commit graph"
msgstr "正在載入提交圖中的已知提交"
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
msgstr "設定變數 'diff.submodule' 未知的取值:'%s'"
+#: diff.c transport.c
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "設定 '%s' 的取值未知:%s"
+
#: diff.c
#, c-format
msgid ""
msgid "invalid mode '%s' in --color-moved-ws"
msgstr "--color-moved-ws 中的無效模式 '%s'"
-#: diff.c
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"diff-algorithm 選項有 \"myers\"、\"minimal\"、\"patience\" 和 \"histogram\""
-
#: diff.c
#, c-format
msgid "invalid argument to %s"
msgstr "只輸出 --stat 的最後一行"
#: diff.c
-msgid "<param1,param2>..."
-msgstr "<參數1,參數2>..."
+#| msgid "<param1,param2>..."
+msgid "<param1>,<param2>..."
+msgstr "<param1>,<param2>..."
#: diff.c
msgid ""
msgstr "和 --dirstat=cumulative 同義"
#: diff.c
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "是 --dirstat=files,param1,param2... 的同義詞"
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "是 --dirstat=files,<param1>,<param2>... 的同義詞"
#: diff.c
msgid "warn if changes introduce conflict markers or whitespace errors"
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "使用 \"histogram diff\" 演算法生成差異"
-#: diff.c
-msgid "<algorithm>"
-msgstr "<演算法>"
-
-#: diff.c
-msgid "choose a diff algorithm"
-msgstr "選擇一個差異演算法"
-
#: diff.c
msgid "<text>"
msgstr "<文字>"
#. conflict in a submodule. The first argument is the submodule
#. name, and the second argument is the abbreviated id of the
#. commit that needs to be merged. For example:
-#. - go to submodule (mysubmodule), and either merge commit abc1234"
+#. - go to submodule (mysubmodule), and either merge commit abc1234"
#.
#: merge-ort.c
#, c-format
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "多包索引的物件 ID fanout 大小錯誤"
+#: midx.c
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr "物件 ID 扇出無序:fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+
#: midx.c
msgid "multi-pack-index OID lookup chunk is the wrong size"
msgstr "多包索引 OID 查詢區塊的大小有誤"
msgid "bad pack-int-id: %u (%u total packs)"
msgstr "錯的 pack-int-id:%u(共有 %u 個包)"
+#: midx.c
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX 未包含 BTMP 區塊"
+
+#: midx.c
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "無法載入位圖化 (bitmapped) 的封裝 %<PRIu32>"
+
#: midx.c
msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
msgstr "多包索引儲存一個64位位移,但是 off_t 太小"
msgid "Looking for referenced packfiles"
msgstr "正在尋找引用的 packfile"
-#: midx.c
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr "物件 ID 扇出無序:fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-
#: midx.c
msgid "the midx contains no oid"
msgstr "midx 沒有 oid"
#. TRANSLATORS: This is a line of ambiguous commit
#. object output. E.g.:
#. *
-#. "deadbeef commit 2021-01-01 - Some Commit Message"
+#. "deadbeef commit 2021-01-01 - Some Commit Message"
#.
#: object-name.c
#, c-format
#. TRANSLATORS: This is a line of ambiguous
#. tag object output. E.g.:
#. *
-#. "deadbeef tag 2022-01-01 - Some Tag Message"
+#. "deadbeef tag 2022-01-01 - Some Tag Message"
#. *
#. The second argument is the YYYY-MM-DD found
#. in the tag.
#. tag object output where we couldn't parse
#. the tag itself. E.g.:
#. *
-#. "deadbeef [bad tag, could not parse it]"
+#. "deadbeef [bad tag, could not parse it]"
#.
#: object-name.c
#, c-format
msgid "could not open pack %s"
msgstr "無法開啟封包 %s"
+#: pack-bitmap.c t/helper/test-read-midx.c
+msgid "could not determine MIDX preferred pack"
+msgstr "無法確定 MIDX 偏好的封裝"
+
#: pack-bitmap.c
#, c-format
msgid "preferred pack (%s) is invalid"
msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
msgstr "ewah 位圖損壞:提交 “%s” 之位圖的標頭遭截斷"
+#: pack-bitmap.c
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr "無法載入「%s」封裝,停用 pack-reuse"
+
#: pack-bitmap.c
#, c-format
msgid "object '%s' not found in type bitmaps"
msgid "multi-pack-index reverse-index chunk is the wrong size"
msgstr "多包索引的反向索引區塊大小有誤"
+#: pack-revindex.c
+msgid "could not determine preferred pack"
+msgstr "無法確定偏好封裝"
+
#: pack-write.c
msgid "cannot both write and verify reverse index"
msgstr "無法同時寫入和驗證倒排索引"
msgid "%s expects a non-negative integer value with an optional k/m/g suffix"
msgstr "%s 期望一個非負整數和一個可選的 k/m/g 後綴"
-#: parse-options.c
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s 與 %s 不相容"
-
#: parse-options.c
#, c-format
msgid "ambiguous option: %s (could be --%s%s or --%s%s)"
msgid "unable to add '%s' to index"
msgstr "無法在索引中新增 '%s'"
-#: read-cache.c
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "無法對 %s 執行 stat"
-
#: read-cache.c
#, c-format
msgid "'%s' appears as both a file and as a directory"
msgid "cannot process '%s' and '%s' at the same time"
msgstr "無法同時處理 '%s' 和 '%s'"
-#: refs/files-backend.c
-#, c-format
-msgid "could not remove reference %s"
-msgstr "無法刪除引用 %s"
-
-#: refs/files-backend.c refs/packed-backend.c
+#: refs.c
#, c-format
msgid "could not delete reference %s: %s"
msgstr "無法刪除引用 %s:%s"
-#: refs/files-backend.c refs/packed-backend.c
+#: refs.c
#, c-format
msgid "could not delete references: %s"
msgstr "無法刪除引用:%s"
msgid "corrupt author: missing date information"
msgstr "作者資訊損壞:缺少日期資訊"
-#: sequencer.c t/helper/test-fast-rebase.c
+#: sequencer.c
#, c-format
msgid "could not update %s"
msgstr "不能更新 %s"
msgid "Autostash exists; creating a new stash entry."
msgstr "已有自動貯存;建立新貯存項目。"
+#: sequencer.c
+msgid "autostash reference is a symref"
+msgstr "autostash 引用是符號引用"
+
#: sequencer.c
msgid "could not detach HEAD"
msgstr "不能分離開頭指標"
msgid "invalid initial branch name: '%s'"
msgstr "無效的初始分支名稱:'%s'"
+#: setup.c
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init: 忽略 --initial-branch=%s"
+
#: setup.c
#, c-format
msgid "unable to handle file type %d"
msgstr "嘗試以不同的雜湊值重新初始化版本庫"
#: setup.c
-#, c-format
-msgid "%s already exists"
-msgstr "%s 已經存在"
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr "嘗試以不同的引用儲存格式重新初始化版本庫"
#: setup.c
#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init: 忽略 --initial-branch=%s"
+msgid "%s already exists"
+msgstr "%s 已經存在"
#: setup.c
#, c-format
msgid "number of entries in the cache tree to invalidate (default 0)"
msgstr "在快取樹狀物件中,要使失效的項目數量(預設值為 0)"
-#: t/helper/test-fast-rebase.c
-msgid "unhandled options"
-msgstr "未處理選項"
-
-#: t/helper/test-fast-rebase.c
-msgid "error preparing revisions"
-msgstr "準備修訂版本時發生錯誤"
-
#: t/helper/test-reach.c
#, c-format
msgid "commit %s is not marked reachable"
msgid "invalid remote service path"
msgstr "無效的遠端服務路徑"
-#: transport-helper.c transport.c
-msgid "operation not supported by protocol"
-msgstr "協定不支援該動作"
-
#: transport-helper.c
#, c-format
msgid "can't connect to subservice %s"
msgid "support for protocol v2 not implemented yet"
msgstr "協定 v2 的支援尚未實現"
-#: transport.c
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "設定 '%s' 的取值未知:%s"
-
#: transport.c
#, c-format
msgid "transport '%s' not allowed"
msgid "could not retrieve server-advertised bundle-uri list"
msgstr "無法取得伺服器公佈的 bundle-uri 清單"
+#: transport.c
+msgid "operation not supported by protocol"
+msgstr "協定不支援該動作"
+
#: tree-walk.c
msgid "too-short tree object"
msgstr "太短的樹狀物件"
msgid "cannot %s: Your index contains uncommitted changes."
msgstr "不能%s:您的索引中包含未提交的變更。"
+#: xdiff-interface.c
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "給予「%2$s」的「%1$s」樣式未知"
+
#: git-merge-octopus.sh git-merge-resolve.sh
msgid ""
"Error: Your local changes to the following files would be overwritten by "
#, perl-format
msgid "Do you really want to send %s? [y|N]: "
msgstr "您真的要傳送 %s?[y|N]: "
+
+#~ msgid "-x and -X cannot be used together"
+#~ msgstr "-x 和 -X 不能同時使用"
+
+#~ msgid ""
+#~ "--bundle-uri is incompatible with --depth, --shallow-since, and --shallow-"
+#~ "exclude"
+#~ msgstr ""
+#~ "--bundle-uri 與 --depth、--shallow-since 和 --shallow-exclude 不相容"
+
+#~ msgid "--merge-base is incompatible with --stdin"
+#~ msgstr "--merge-base 與 --stdin 不相容"
+
+#~ msgid ""
+#~ "apply options are incompatible with rebase.autoSquash. Consider adding --"
+#~ "no-autosquash"
+#~ msgstr "apply 選項與 rebase.autoSquash 不相容。請考慮加上 --no-autosquash"
+
+#~ msgid "--exclude-hidden cannot be used together with --branches"
+#~ msgstr "--exclude-hidden 無法與 --branches 同時使用"
+
+#~ msgid "--exclude-hidden cannot be used together with --tags"
+#~ msgstr "--exclude-hidden 無法與 --tags 同時使用"
+
+#~ msgid "--exclude-hidden cannot be used together with --remotes"
+#~ msgstr "--exclude-hidden 無法與 --remotes 同時使用"
+
+#, c-format
+#~ msgid "only one of '%s', '%s' or '%s' can be given"
+#~ msgstr "只能傳入 “%s”、“%s” 或 “%s”"
+
+#, c-format
+#~ msgid "'%s' and '%s' cannot be used together"
+#~ msgstr "無法同時使用 “%s” 和 “%s”"
+
+#, c-format
+#~ msgid "options '%s', and '%s' cannot be used together"
+#~ msgstr "無法同時使用 “%s” 和 “%s” 選項"
+
+#~ msgid "<commit-ish>"
+#~ msgstr "<提交指示元>"
+
+#, c-format
+#~ msgid "%s is incompatible with %s"
+#~ msgstr "%s 與 %s 不相容"
+
+#, c-format
+#~ msgid "could not remove reference %s"
+#~ msgstr "無法刪除引用 %s"
+
+#~ msgid "unhandled options"
+#~ msgstr "未處理選項"
#include "pack-mtimes.h"
#include "config.h"
#include "run-command.h"
+#include "sequencer.h"
struct connectivity_progress {
struct progress *progress;
display_progress(cp->progress, cp->count);
}
+static void add_one_file(const char *path, struct rev_info *revs)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct object_id oid;
+ struct object *object;
+
+ if (!read_oneliner(&buf, path, READ_ONELINER_SKIP_IF_EMPTY)) {
+ strbuf_release(&buf);
+ return;
+ }
+ strbuf_trim(&buf);
+ if (!get_oid_hex(buf.buf, &oid)) {
+ object = parse_object_or_die(&oid, buf.buf);
+ add_pending_object(revs, object, "");
+ }
+ strbuf_release(&buf);
+}
+
+/* Mark objects recorded in rebase state files as reachable. */
+static void add_rebase_files(struct rev_info *revs)
+{
+ struct strbuf buf = STRBUF_INIT;
+ size_t len;
+ const char *path[] = {
+ "rebase-apply/autostash",
+ "rebase-apply/orig-head",
+ "rebase-merge/autostash",
+ "rebase-merge/orig-head",
+ };
+ struct worktree **worktrees = get_worktrees();
+
+ for (struct worktree **wt = worktrees; *wt; wt++) {
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, get_worktree_git_dir(*wt));
+ strbuf_complete(&buf, '/');
+ len = buf.len;
+ for (size_t i = 0; i < ARRAY_SIZE(path); i++) {
+ strbuf_setlen(&buf, len);
+ strbuf_addstr(&buf, path[i]);
+ add_one_file(buf.buf, revs);
+ }
+ }
+ strbuf_release(&buf);
+ free_worktrees(worktrees);
+}
+
static int add_one_ref(const char *path, const struct object_id *oid,
int flag, void *cb_data)
{
head_ref(add_one_ref, revs);
other_head_refs(add_one_ref, revs);
+ /* rebase autostash and orig-head */
+ add_rebase_files(revs);
+
/* Add all reflog info */
if (mark_reflog)
add_reflogs_to_pending(revs, 0);
each_ref_fn cb,
void *cb_data)
{
+ if (filter->kind == FILTER_REFS_KIND_MASK) {
+ /* In this case, we want to print all refs including root refs. */
+ return refs_for_each_include_root_refs(get_main_ref_store(the_repository),
+ cb, cb_data);
+ }
+
if (!filter->match_as_path) {
/*
* in this case, the patterns are applied after
return ref_kind[i].kind;
}
+ if (is_pseudoref(get_main_ref_store(the_repository), refname))
+ return FILTER_REFS_PSEUDOREFS;
+
return FILTER_REFS_OTHERS;
}
/* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
kind = filter_ref_kind(filter, refname);
- if (!(kind & filter->kind))
+
+ /*
+ * Generally HEAD refs are printed with special description denoting a rebase,
+ * detached state and so forth. This is useful when only printing the HEAD ref
+ * But when it is being printed along with other pseudorefs, it makes sense to
+ * keep the formatting consistent. So we mask the type to act like a pseudoref.
+ */
+ if (filter->kind == FILTER_REFS_KIND_MASK && kind == FILTER_REFS_DETACHED_HEAD)
+ kind = FILTER_REFS_PSEUDOREFS;
+ else if (!(kind & filter->kind))
return NULL;
if (!filter_pattern_match(filter, refname))
ret = for_each_fullref_in("refs/remotes/", fn, cb_data);
else if (filter->kind == FILTER_REFS_TAGS)
ret = for_each_fullref_in("refs/tags/", fn, cb_data);
- else if (filter->kind & FILTER_REFS_ALL)
+ else if (filter->kind & FILTER_REFS_REGULAR)
ret = for_each_fullref_in_pattern(filter, fn, cb_data);
- if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD))
+
+ /*
+ * When printing all ref types, HEAD is already included,
+ * so we don't want to print HEAD again.
+ */
+ if (!ret && (filter->kind != FILTER_REFS_KIND_MASK) &&
+ (filter->kind & FILTER_REFS_DETACHED_HEAD))
head_ref(fn, cb_data);
}
#define FILTER_REFS_BRANCHES 0x0004
#define FILTER_REFS_REMOTES 0x0008
#define FILTER_REFS_OTHERS 0x0010
-#define FILTER_REFS_ALL (FILTER_REFS_TAGS | FILTER_REFS_BRANCHES | \
+#define FILTER_REFS_REGULAR (FILTER_REFS_TAGS | FILTER_REFS_BRANCHES | \
FILTER_REFS_REMOTES | FILTER_REFS_OTHERS)
#define FILTER_REFS_DETACHED_HEAD 0x0020
-#define FILTER_REFS_KIND_MASK (FILTER_REFS_ALL | FILTER_REFS_DETACHED_HEAD)
+#define FILTER_REFS_PSEUDOREFS 0x0040
+#define FILTER_REFS_ROOT_REFS (FILTER_REFS_DETACHED_HEAD | FILTER_REFS_PSEUDOREFS)
+#define FILTER_REFS_KIND_MASK (FILTER_REFS_REGULAR | FILTER_REFS_DETACHED_HEAD | \
+ FILTER_REFS_PSEUDOREFS)
struct atom_value;
struct ref_sorting;
*/
static const struct ref_storage_be *refs_backends[] = {
[REF_STORAGE_FORMAT_FILES] = &refs_be_files,
+ [REF_STORAGE_FORMAT_REFTABLE] = &refs_be_reftable,
};
static const struct ref_storage_be *find_ref_storage_backend(unsigned int ref_storage_format)
return 1;
}
+int is_pseudoref(struct ref_store *refs, const char *refname)
+{
+ static const char *const irregular_pseudorefs[] = {
+ "AUTO_MERGE",
+ "BISECT_EXPECTED_REV",
+ "NOTES_MERGE_PARTIAL",
+ "NOTES_MERGE_REF",
+ "MERGE_AUTOSTASH",
+ };
+ struct object_id oid;
+ size_t i;
+
+ if (!is_pseudoref_syntax(refname))
+ return 0;
+
+ if (ends_with(refname, "_HEAD")) {
+ refs_resolve_ref_unsafe(refs, refname,
+ RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ &oid, NULL);
+ return !is_null_oid(&oid);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++)
+ if (!strcmp(refname, irregular_pseudorefs[i])) {
+ refs_resolve_ref_unsafe(refs, refname,
+ RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ &oid, NULL);
+ return !is_null_oid(&oid);
+ }
+
+ return 0;
+}
+
+int is_headref(struct ref_store *refs, const char *refname)
+{
+ if (!strcmp(refname, "HEAD"))
+ return refs_ref_exists(refs, refname);
+
+ return 0;
+}
+
static int is_current_worktree_ref(const char *ref) {
return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
}
const char *message, void *cb_data)
{
struct read_ref_at_cb *cb = cb_data;
- int reached_count;
cb->tz = tz;
cb->date = timestamp;
- /*
- * It is not possible for cb->cnt == 0 on the first iteration because
- * that special case is handled in read_ref_at().
- */
- if (cb->cnt > 0)
- cb->cnt--;
- reached_count = cb->cnt == 0 && !is_null_oid(ooid);
- if (timestamp <= cb->at_time || reached_count) {
+ if (timestamp <= cb->at_time || cb->cnt == 0) {
set_read_ref_cutoffs(cb, timestamp, tz, message);
/*
* we have not yet updated cb->[n|o]oid so they still
* hold the values for the previous record.
*/
- if (!is_null_oid(&cb->ooid) && !oideq(&cb->ooid, noid))
- warning(_("log for ref %s has gap after %s"),
+ if (!is_null_oid(&cb->ooid)) {
+ oidcpy(cb->oid, noid);
+ if (!oideq(&cb->ooid, noid))
+ warning(_("log for ref %s has gap after %s"),
cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822)));
- if (reached_count)
- oidcpy(cb->oid, ooid);
- else if (!is_null_oid(&cb->ooid) || cb->date == cb->at_time)
+ }
+ else if (cb->date == cb->at_time)
oidcpy(cb->oid, noid);
else if (!oideq(noid, cb->oid))
warning(_("log for ref %s unexpectedly ended on %s"),
cb->refname, show_date(cb->date, cb->tz,
DATE_MODE(RFC2822)));
+ cb->reccnt++;
+ oidcpy(&cb->ooid, ooid);
+ oidcpy(&cb->noid, noid);
cb->found_it = 1;
+ return 1;
}
cb->reccnt++;
oidcpy(&cb->ooid, ooid);
oidcpy(&cb->noid, noid);
- return cb->found_it;
-}
-
-static int read_ref_at_ent_newest(struct object_id *ooid UNUSED,
- struct object_id *noid,
- const char *email UNUSED,
- timestamp_t timestamp, int tz,
- const char *message, void *cb_data)
-{
- struct read_ref_at_cb *cb = cb_data;
-
- set_read_ref_cutoffs(cb, timestamp, tz, message);
- oidcpy(cb->oid, noid);
- /* We just want the first entry */
- return 1;
+ if (cb->cnt > 0)
+ cb->cnt--;
+ return 0;
}
static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
set_read_ref_cutoffs(cb, timestamp, tz, message);
oidcpy(cb->oid, ooid);
- if (is_null_oid(cb->oid))
+ if (cb->at_time && is_null_oid(cb->oid))
oidcpy(cb->oid, noid);
/* We just want the first entry */
return 1;
cb.cutoff_cnt = cutoff_cnt;
cb.oid = oid;
- if (cb.cnt == 0) {
- refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent_newest, &cb);
- return 0;
- }
-
refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb);
if (!cb.reccnt) {
+ if (cnt == 0) {
+ /*
+ * The caller asked for ref@{0}, and we had no entries.
+ * It's a bit subtle, but in practice all callers have
+ * prepped the "oid" field with the current value of
+ * the ref, which is the most reasonable fallback.
+ *
+ * We'll put dummy values into the out-parameters (so
+ * they're not just uninitialized garbage), and the
+ * caller can take our return value as a hint that
+ * we did not find any such reflog.
+ */
+ set_read_ref_cutoffs(&cb, 0, 0, "empty reflog");
+ return 1;
+ }
if (flags & GET_OID_QUIETLY)
exit(128);
else
if (trim)
iter = prefix_ref_iterator_begin(iter, "", trim);
- /* Sanity check for subclasses: */
- if (!iter->ordered)
- BUG("reference iterator is not ordered");
-
return iter;
}
return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
}
+int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
+ void *cb_data)
+{
+ return do_for_each_ref(refs, "", NULL, fn, 0,
+ DO_FOR_EACH_INCLUDE_ROOT_REFS, cb_data);
+}
+
static int qsort_strcmp(const void *va, const void *vb)
{
const char *a = *(const char **)va;
return ret;
}
-int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+struct do_for_each_reflog_help {
+ each_reflog_fn *fn;
+ void *cb_data;
+};
+
+static int do_for_each_reflog_helper(struct repository *r UNUSED,
+ const char *refname,
+ const struct object_id *oid UNUSED,
+ int flags,
+ void *cb_data)
+{
+ struct do_for_each_reflog_help *hp = cb_data;
+ return hp->fn(refname, hp->cb_data);
+}
+
+int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data)
{
struct ref_iterator *iter;
- struct do_for_each_ref_help hp = { fn, cb_data };
+ struct do_for_each_reflog_help hp = { fn, cb_data };
iter = refs->be->reflog_iterator_begin(refs);
return do_for_each_repo_ref_iterator(the_repository, iter,
- do_for_each_ref_helper, &hp);
+ do_for_each_reflog_helper, &hp);
}
-int for_each_reflog(each_ref_fn fn, void *cb_data)
+int for_each_reflog(each_reflog_fn fn, void *cb_data)
{
return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data);
}
int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data);
int for_each_rawref(each_ref_fn fn, void *cb_data);
+/*
+ * Iterates over all refs including root refs, i.e. pseudorefs and HEAD.
+ */
+int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
+ void *cb_data);
+
/*
* Normalizes partial refs to their fully qualified form.
* Will prepend <prefix> to the <pattern> if it doesn't start with 'refs/'.
struct strbuf *err);
int safe_create_reflog(const char *refname, struct strbuf *err);
-/** Reads log for the value of ref during at_time. **/
+/**
+ * Reads log for the value of ref during at_time (in which case "cnt" should be
+ * negative) or the reflog "cnt" entries from the top (in which case "at_time"
+ * should be 0).
+ *
+ * If we found the reflog entry in question, returns 0 (and details of the
+ * entry can be found in the out-parameters).
+ *
+ * If we ran out of reflog entries, the out-parameters are filled with the
+ * details of the oldest entry we did find, and the function returns 1. Note
+ * that there is one important special case here! If the reflog was empty
+ * and the caller asked for the 0-th cnt, we will return "1" but leave the
+ * "oid" field untouched.
+ **/
int read_ref_at(struct ref_store *refs,
const char *refname, unsigned int flags,
timestamp_t at_time, int cnt,
/* youngest entry first */
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data);
+/*
+ * The signature for the callback function for the {refs_,}for_each_reflog()
+ * functions below. The memory pointed to by the refname argument is only
+ * guaranteed to be valid for the duration of a single callback invocation.
+ */
+typedef int each_reflog_fn(const char *refname, void *cb_data);
+
/*
* Calls the specified function for each reflog file until it returns nonzero,
* and returns the value. Reflog file order is unspecified.
*/
-int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data);
-int for_each_reflog(each_ref_fn fn, void *cb_data);
+int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data);
+int for_each_reflog(each_reflog_fn fn, void *cb_data);
#define REFNAME_ALLOW_ONELEVEL 1
#define REFNAME_REFSPEC_PATTERN 2
*/
void update_ref_namespace(enum ref_namespace namespace, char *ref);
+int is_pseudoref(struct ref_store *refs, const char *refname);
+int is_headref(struct ref_store *refs, const char *refname);
+
#endif /* REFS_H */
trace_printf_key(&trace_refs, "iterator_advance: %s (0)\n",
diter->iter->refname);
- diter->base.ordered = diter->iter->ordered;
diter->base.refname = diter->iter->refname;
diter->base.oid = diter->iter->oid;
diter->base.flags = diter->iter->flags;
drefs->refs->be->iterator_begin(drefs->refs, prefix,
exclude_patterns, flags);
struct debug_ref_iterator *diter = xcalloc(1, sizeof(*diter));
- base_ref_iterator_init(&diter->base, &debug_ref_iterator_vtable, 1);
+ base_ref_iterator_init(&diter->base, &debug_ref_iterator_vtable);
diter->iter = res;
trace_printf_key(&trace_refs, "ref_iterator_begin: \"%s\" (0x%x)\n",
prefix, flags);
}
}
+static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
+ const char *refname,
+ struct ref_dir *dir)
+{
+ struct object_id oid;
+ int flag;
+
+ if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
+ &oid, &flag)) {
+ oidclr(&oid);
+ flag |= REF_ISBROKEN;
+ } else if (is_null_oid(&oid)) {
+ /*
+ * It is so astronomically unlikely
+ * that null_oid is the OID of an
+ * actual object that we consider its
+ * appearance in a loose reference
+ * file to be repo corruption
+ * (probably due to a software bug).
+ */
+ flag |= REF_ISBROKEN;
+ }
+
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
+ if (!refname_is_safe(refname))
+ die("loose refname is dangerous: %s", refname);
+ oidclr(&oid);
+ flag |= REF_BAD_NAME | REF_ISBROKEN;
+ }
+ add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
+}
+
/*
* Read the loose references from the namespace dirname into dir
* (without recursing). dirname must end with '/'. dir must be the
strbuf_add(&refname, dirname, dirnamelen);
while ((de = readdir(d)) != NULL) {
- struct object_id oid;
- int flag;
unsigned char dtype;
if (de->d_name[0] == '.')
create_dir_entry(dir->cache, refname.buf,
refname.len));
} else if (dtype == DT_REG) {
- if (!refs_resolve_ref_unsafe(&refs->base,
- refname.buf,
- RESOLVE_REF_READING,
- &oid, &flag)) {
- oidclr(&oid);
- flag |= REF_ISBROKEN;
- } else if (is_null_oid(&oid)) {
- /*
- * It is so astronomically unlikely
- * that null_oid is the OID of an
- * actual object that we consider its
- * appearance in a loose reference
- * file to be repo corruption
- * (probably due to a software bug).
- */
- flag |= REF_ISBROKEN;
- }
-
- if (check_refname_format(refname.buf,
- REFNAME_ALLOW_ONELEVEL)) {
- if (!refname_is_safe(refname.buf))
- die("loose refname is dangerous: %s", refname.buf);
- oidclr(&oid);
- flag |= REF_BAD_NAME | REF_ISBROKEN;
- }
- add_entry_to_dir(dir,
- create_ref_entry(refname.buf, &oid, flag));
+ loose_fill_ref_dir_regular_file(refs, refname.buf, dir);
}
strbuf_setlen(&refname, dirnamelen);
}
add_per_worktree_entries_to_dir(dir, dirname);
}
-static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
+/*
+ * Add pseudorefs to the ref dir by parsing the directory for any files
+ * which follow the pseudoref syntax.
+ */
+static void add_pseudoref_and_head_entries(struct ref_store *ref_store,
+ struct ref_dir *dir,
+ const char *dirname)
+{
+ struct files_ref_store *refs =
+ files_downcast(ref_store, REF_STORE_READ, "fill_ref_dir");
+ struct strbuf path = STRBUF_INIT, refname = STRBUF_INIT;
+ struct dirent *de;
+ size_t dirnamelen;
+ DIR *d;
+
+ files_ref_path(refs, &path, dirname);
+
+ d = opendir(path.buf);
+ if (!d) {
+ strbuf_release(&path);
+ return;
+ }
+
+ strbuf_addstr(&refname, dirname);
+ dirnamelen = refname.len;
+
+ while ((de = readdir(d)) != NULL) {
+ unsigned char dtype;
+
+ if (de->d_name[0] == '.')
+ continue;
+ if (ends_with(de->d_name, ".lock"))
+ continue;
+ strbuf_addstr(&refname, de->d_name);
+
+ dtype = get_dtype(de, &path, 1);
+ if (dtype == DT_REG && (is_pseudoref(ref_store, de->d_name) ||
+ is_headref(ref_store, de->d_name)))
+ loose_fill_ref_dir_regular_file(refs, refname.buf, dir);
+
+ strbuf_setlen(&refname, dirnamelen);
+ }
+ strbuf_release(&refname);
+ strbuf_release(&path);
+ closedir(d);
+}
+
+static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs,
+ unsigned int flags)
{
if (!refs->loose) {
+ struct ref_dir *dir;
+
/*
* Mark the top-level directory complete because we
* are about to read the only subdirectory that can
/* We're going to fill the top level ourselves: */
refs->loose->root->flag &= ~REF_INCOMPLETE;
+ dir = get_ref_dir(refs->loose->root);
+
+ if (flags & DO_FOR_EACH_INCLUDE_ROOT_REFS)
+ add_pseudoref_and_head_entries(dir->cache->ref_store, dir,
+ refs->loose->root->name);
+
/*
* Add an incomplete entry for "refs/" (to be filled
* lazily):
*/
- add_entry_to_dir(get_ref_dir(refs->loose->root),
- create_dir_entry(refs->loose, "refs/", 5));
+ add_entry_to_dir(dir, create_dir_entry(refs->loose, "refs/", 5));
}
return refs->loose;
}
* disk, and re-reads it if not.
*/
- loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs),
+ loose_iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, flags),
prefix, ref_store->repo, 1);
/*
CALLOC_ARRAY(iter, 1);
ref_iterator = &iter->base;
- base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable,
- overlay_iter->ordered);
+ base_ref_iterator_init(ref_iterator, &files_ref_iterator_vtable);
iter->iter0 = overlay_iter;
iter->repo = ref_store->repo;
iter->flags = flags;
packed_refs_lock(refs->packed_ref_store, LOCK_DIE_ON_ERROR, &err);
- iter = cache_ref_iterator_begin(get_loose_ref_cache(refs), NULL,
+ iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL,
the_repository, 0);
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
/*
struct files_reflog_iterator {
struct ref_iterator base;
-
struct ref_store *ref_store;
struct dir_iterator *dir_iterator;
- struct object_id oid;
};
static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
int ok;
while ((ok = dir_iterator_advance(diter)) == ITER_OK) {
- int flags;
-
if (!S_ISREG(diter->st.st_mode))
continue;
- if (diter->basename[0] == '.')
+ if (check_refname_format(diter->basename,
+ REFNAME_ALLOW_ONELEVEL))
continue;
- if (ends_with(diter->basename, ".lock"))
- continue;
-
- if (!refs_resolve_ref_unsafe(iter->ref_store,
- diter->relative_path, 0,
- &iter->oid, &flags)) {
- error("bad ref for %s", diter->path.buf);
- continue;
- }
iter->base.refname = diter->relative_path;
- iter->base.oid = &iter->oid;
- iter->base.flags = flags;
return ITER_OK;
}
strbuf_addf(&sb, "%s/logs", gitdir);
- diter = dir_iterator_begin(sb.buf, 0);
+ diter = dir_iterator_begin(sb.buf, DIR_ITERATOR_SORTED);
if (!diter) {
strbuf_release(&sb);
return empty_ref_iterator_begin();
CALLOC_ARRAY(iter, 1);
ref_iterator = &iter->base;
- base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable, 0);
+ base_ref_iterator_init(ref_iterator, &files_reflog_iterator_vtable);
iter->dir_iterator = diter;
iter->ref_store = ref_store;
strbuf_release(&sb);
return ref_iterator;
}
-static enum iterator_selection reflog_iterator_select(
- struct ref_iterator *iter_worktree,
- struct ref_iterator *iter_common,
- void *cb_data UNUSED)
-{
- if (iter_worktree) {
- /*
- * We're a bit loose here. We probably should ignore
- * common refs if they are accidentally added as
- * per-worktree refs.
- */
- return ITER_SELECT_0;
- } else if (iter_common) {
- if (parse_worktree_ref(iter_common->refname, NULL, NULL,
- NULL) == REF_WORKTREE_SHARED)
- return ITER_SELECT_1;
-
- /*
- * The main ref store may contain main worktree's
- * per-worktree refs, which should be ignored
- */
- return ITER_SKIP_1;
- } else
- return ITER_DONE;
-}
-
static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_store)
{
struct files_ref_store *refs =
return reflog_iterator_begin(ref_store, refs->gitcommondir);
} else {
return merge_ref_iterator_begin(
- 0, reflog_iterator_begin(ref_store, refs->base.gitdir),
+ reflog_iterator_begin(ref_store, refs->base.gitdir),
reflog_iterator_begin(ref_store, refs->gitcommondir),
- reflog_iterator_select, refs);
+ ref_iterator_select, refs);
}
}
}
void base_ref_iterator_init(struct ref_iterator *iter,
- struct ref_iterator_vtable *vtable,
- int ordered)
+ struct ref_iterator_vtable *vtable)
{
iter->vtable = vtable;
- iter->ordered = !!ordered;
iter->refname = NULL;
iter->oid = NULL;
iter->flags = 0;
struct empty_ref_iterator *iter = xcalloc(1, sizeof(*iter));
struct ref_iterator *ref_iterator = &iter->base;
- base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable, 1);
+ base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable);
return ref_iterator;
}
struct ref_iterator **current;
};
+enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
+ struct ref_iterator *iter_common,
+ void *cb_data UNUSED)
+{
+ if (iter_worktree && !iter_common) {
+ /*
+ * Return the worktree ref if there are no more common refs.
+ */
+ return ITER_SELECT_0;
+ } else if (iter_common) {
+ /*
+ * In case we have pending worktree and common refs we need to
+ * yield them based on their lexicographical order. Worktree
+ * refs that have the same name as common refs shadow the
+ * latter.
+ */
+ if (iter_worktree) {
+ int cmp = strcmp(iter_worktree->refname,
+ iter_common->refname);
+ if (cmp < 0)
+ return ITER_SELECT_0;
+ else if (!cmp)
+ return ITER_SELECT_0_SKIP_1;
+ }
+
+ /*
+ * We now know that the lexicographically-next ref is a common
+ * ref. When the common ref is a shared one we return it.
+ */
+ if (parse_worktree_ref(iter_common->refname, NULL, NULL,
+ NULL) == REF_WORKTREE_SHARED)
+ return ITER_SELECT_1;
+
+ /*
+ * Otherwise, if the common ref is a per-worktree ref we skip
+ * it because it would belong to the main worktree, not ours.
+ */
+ return ITER_SKIP_1;
+ } else {
+ return ITER_DONE;
+ }
+}
+
static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
{
struct merge_ref_iterator *iter =
};
struct ref_iterator *merge_ref_iterator_begin(
- int ordered,
struct ref_iterator *iter0, struct ref_iterator *iter1,
ref_iterator_select_fn *select, void *cb_data)
{
* references through only if they exist in both iterators.
*/
- base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable, ordered);
+ base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable);
iter->iter0 = iter0;
iter->iter1 = iter1;
iter->select = select;
} else if (is_empty_ref_iterator(back)) {
ref_iterator_abort(back);
return front;
- } else if (!front->ordered || !back->ordered) {
- BUG("overlay_ref_iterator requires ordered inputs");
}
- return merge_ref_iterator_begin(1, front, back,
- overlay_iterator_select, NULL);
+ return merge_ref_iterator_begin(front, back, overlay_iterator_select, NULL);
}
struct prefix_ref_iterator {
if (cmp > 0) {
/*
- * If the source iterator is ordered, then we
+ * As the source iterator is ordered, we
* can stop the iteration as soon as we see a
* refname that comes after the prefix:
*/
- if (iter->iter0->ordered) {
- ok = ref_iterator_abort(iter->iter0);
- break;
- } else {
- continue;
- }
+ ok = ref_iterator_abort(iter->iter0);
+ break;
}
if (iter->trim) {
CALLOC_ARRAY(iter, 1);
ref_iterator = &iter->base;
- base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable, iter0->ordered);
+ base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable);
iter->iter0 = iter0;
iter->prefix = xstrdup(prefix);
CALLOC_ARRAY(iter, 1);
ref_iterator = &iter->base;
- base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable, 1);
+ base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable);
if (exclude_patterns)
populate_excluded_jump_list(iter, snapshot, exclude_patterns);
CALLOC_ARRAY(iter, 1);
ref_iterator = &iter->base;
- base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable, 1);
+ base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable);
ALLOC_GROW(iter->levels, 10, iter->levels_alloc);
iter->levels_nr = 1;
* INCLUDE_BROKEN, since they are otherwise not included at all.
*/
DO_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2),
+
+ /*
+ * Include root refs i.e. HEAD and pseudorefs along with the regular
+ * refs.
+ */
+ DO_FOR_EACH_INCLUDE_ROOT_REFS = (1 << 3),
};
/*
*/
struct ref_iterator {
struct ref_iterator_vtable *vtable;
-
- /*
- * Does this `ref_iterator` iterate over references in order
- * by refname?
- */
- unsigned int ordered : 1;
-
const char *refname;
const struct object_id *oid;
unsigned int flags;
struct ref_iterator *iter0, struct ref_iterator *iter1,
void *cb_data);
+/*
+ * An implementation of ref_iterator_select_fn that merges worktree and common
+ * refs. Per-worktree refs from the common iterator are ignored, worktree refs
+ * override common refs. Refs are selected lexicographically.
+ */
+enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
+ struct ref_iterator *iter_common,
+ void *cb_data);
+
/*
* Iterate over the entries from iter0 and iter1, with the values
* interleaved as directed by the select function. The iterator takes
* ownership of iter0 and iter1 and frees them when the iteration is
- * over. A derived class should set `ordered` to 1 or 0 based on
- * whether it generates its output in order by reference name.
+ * over.
*/
struct ref_iterator *merge_ref_iterator_begin(
- int ordered,
struct ref_iterator *iter0, struct ref_iterator *iter1,
ref_iterator_select_fn *select, void *cb_data);
* As an convenience to callers, if prefix is the empty string and
* trim is zero, this function returns iter0 directly, without
* wrapping it.
- *
- * The resulting ref_iterator is ordered if iter0 is.
*/
struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
const char *prefix,
/*
* Base class constructor for ref_iterators. Initialize the
* ref_iterator part of iter, setting its vtable pointer as specified.
- * `ordered` should be set to 1 if the iterator will iterate over
- * references in order by refname; otherwise it should be set to 0.
* This is meant to be called only by the initializers of derived
* classes.
*/
void base_ref_iterator_init(struct ref_iterator *iter,
- struct ref_iterator_vtable *vtable,
- int ordered);
+ struct ref_iterator_vtable *vtable);
/*
* Base class destructor for ref_iterators. Destroy the ref_iterator
};
extern struct ref_storage_be refs_be_files;
+extern struct ref_storage_be refs_be_reftable;
extern struct ref_storage_be refs_be_packed;
/*
--- /dev/null
+#include "../git-compat-util.h"
+#include "../abspath.h"
+#include "../chdir-notify.h"
+#include "../environment.h"
+#include "../gettext.h"
+#include "../hash.h"
+#include "../hex.h"
+#include "../iterator.h"
+#include "../ident.h"
+#include "../lockfile.h"
+#include "../object.h"
+#include "../path.h"
+#include "../refs.h"
+#include "../reftable/reftable-stack.h"
+#include "../reftable/reftable-record.h"
+#include "../reftable/reftable-error.h"
+#include "../reftable/reftable-iterator.h"
+#include "../reftable/reftable-merged.h"
+#include "../setup.h"
+#include "../strmap.h"
+#include "refs-internal.h"
+
+/*
+ * Used as a flag in ref_update::flags when the ref_update was via an
+ * update to HEAD.
+ */
+#define REF_UPDATE_VIA_HEAD (1 << 8)
+
+struct reftable_ref_store {
+ struct ref_store base;
+
+ /*
+ * The main stack refers to the common dir and thus contains common
+ * refs as well as refs of the main repository.
+ */
+ struct reftable_stack *main_stack;
+ /*
+ * The worktree stack refers to the gitdir in case the refdb is opened
+ * via a worktree. It thus contains the per-worktree refs.
+ */
+ struct reftable_stack *worktree_stack;
+ /*
+ * Map of worktree stacks by their respective worktree names. The map
+ * is populated lazily when we try to resolve `worktrees/$worktree` refs.
+ */
+ struct strmap worktree_stacks;
+ struct reftable_write_options write_options;
+
+ unsigned int store_flags;
+ int err;
+};
+
+/*
+ * Downcast ref_store to reftable_ref_store. Die if ref_store is not a
+ * reftable_ref_store. required_flags is compared with ref_store's store_flags
+ * to ensure the ref_store has all required capabilities. "caller" is used in
+ * any necessary error messages.
+ */
+static struct reftable_ref_store *reftable_be_downcast(struct ref_store *ref_store,
+ unsigned int required_flags,
+ const char *caller)
+{
+ struct reftable_ref_store *refs;
+
+ if (ref_store->be != &refs_be_reftable)
+ BUG("ref_store is type \"%s\" not \"reftables\" in %s",
+ ref_store->be->name, caller);
+
+ refs = (struct reftable_ref_store *)ref_store;
+
+ if ((refs->store_flags & required_flags) != required_flags)
+ BUG("operation %s requires abilities 0x%x, but only have 0x%x",
+ caller, required_flags, refs->store_flags);
+
+ return refs;
+}
+
+/*
+ * Some refs are global to the repository (refs/heads/{*}), while others are
+ * local to the worktree (eg. HEAD, refs/bisect/{*}). We solve this by having
+ * multiple separate databases (ie. multiple reftable/ directories), one for
+ * the shared refs, one for the current worktree refs, and one for each
+ * additional worktree. For reading, we merge the view of both the shared and
+ * the current worktree's refs, when necessary.
+ *
+ * This function also optionally assigns the rewritten reference name that is
+ * local to the stack. This translation is required when using worktree refs
+ * like `worktrees/$worktree/refs/heads/foo` as worktree stacks will store
+ * those references in their normalized form.
+ */
+static struct reftable_stack *stack_for(struct reftable_ref_store *store,
+ const char *refname,
+ const char **rewritten_ref)
+{
+ const char *wtname;
+ int wtname_len;
+
+ if (!refname)
+ return store->main_stack;
+
+ switch (parse_worktree_ref(refname, &wtname, &wtname_len, rewritten_ref)) {
+ case REF_WORKTREE_OTHER: {
+ static struct strbuf wtname_buf = STRBUF_INIT;
+ struct strbuf wt_dir = STRBUF_INIT;
+ struct reftable_stack *stack;
+
+ /*
+ * We're using a static buffer here so that we don't need to
+ * allocate the worktree name whenever we look up a reference.
+ * This could be avoided if the strmap interface knew how to
+ * handle keys with a length.
+ */
+ strbuf_reset(&wtname_buf);
+ strbuf_add(&wtname_buf, wtname, wtname_len);
+
+ /*
+ * There is an edge case here: when the worktree references the
+ * current worktree, then we set up the stack once via
+ * `worktree_stacks` and once via `worktree_stack`. This is
+ * wasteful, but in the reading case it shouldn't matter. And
+ * in the writing case we would notice that the stack is locked
+ * already and error out when trying to write a reference via
+ * both stacks.
+ */
+ stack = strmap_get(&store->worktree_stacks, wtname_buf.buf);
+ if (!stack) {
+ strbuf_addf(&wt_dir, "%s/worktrees/%s/reftable",
+ store->base.repo->commondir, wtname_buf.buf);
+
+ store->err = reftable_new_stack(&stack, wt_dir.buf,
+ store->write_options);
+ assert(store->err != REFTABLE_API_ERROR);
+ strmap_put(&store->worktree_stacks, wtname_buf.buf, stack);
+ }
+
+ strbuf_release(&wt_dir);
+ return stack;
+ }
+ case REF_WORKTREE_CURRENT:
+ /*
+ * If there is no worktree stack then we're currently in the
+ * main worktree. We thus return the main stack in that case.
+ */
+ if (!store->worktree_stack)
+ return store->main_stack;
+ return store->worktree_stack;
+ case REF_WORKTREE_MAIN:
+ case REF_WORKTREE_SHARED:
+ return store->main_stack;
+ default:
+ BUG("unhandled worktree reference type");
+ }
+}
+
+static int should_write_log(struct ref_store *refs, const char *refname)
+{
+ if (log_all_ref_updates == LOG_REFS_UNSET)
+ log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
+
+ switch (log_all_ref_updates) {
+ case LOG_REFS_NONE:
+ return refs_reflog_exists(refs, refname);
+ case LOG_REFS_ALWAYS:
+ return 1;
+ case LOG_REFS_NORMAL:
+ if (should_autocreate_reflog(refname))
+ return 1;
+ return refs_reflog_exists(refs, refname);
+ default:
+ BUG("unhandled core.logAllRefUpdates value %d", log_all_ref_updates);
+ }
+}
+
+static void clear_reftable_log_record(struct reftable_log_record *log)
+{
+ switch (log->value_type) {
+ case REFTABLE_LOG_UPDATE:
+ /*
+ * When we write log records, the hashes are owned by the
+ * caller and thus shouldn't be free'd.
+ */
+ log->value.update.old_hash = NULL;
+ log->value.update.new_hash = NULL;
+ break;
+ case REFTABLE_LOG_DELETION:
+ break;
+ }
+ reftable_log_record_release(log);
+}
+
+static void fill_reftable_log_record(struct reftable_log_record *log)
+{
+ const char *info = git_committer_info(0);
+ struct ident_split split = {0};
+ int sign = 1;
+
+ if (split_ident_line(&split, info, strlen(info)))
+ BUG("failed splitting committer info");
+
+ reftable_log_record_release(log);
+ log->value_type = REFTABLE_LOG_UPDATE;
+ log->value.update.name =
+ xstrndup(split.name_begin, split.name_end - split.name_begin);
+ log->value.update.email =
+ xstrndup(split.mail_begin, split.mail_end - split.mail_begin);
+ log->value.update.time = atol(split.date_begin);
+ if (*split.tz_begin == '-') {
+ sign = -1;
+ split.tz_begin++;
+ }
+ if (*split.tz_begin == '+') {
+ sign = 1;
+ split.tz_begin++;
+ }
+
+ log->value.update.tz_offset = sign * atoi(split.tz_begin);
+}
+
+static int read_ref_without_reload(struct reftable_stack *stack,
+ const char *refname,
+ struct object_id *oid,
+ struct strbuf *referent,
+ unsigned int *type)
+{
+ struct reftable_ref_record ref = {0};
+ int ret;
+
+ ret = reftable_stack_read_ref(stack, refname, &ref);
+ if (ret)
+ goto done;
+
+ if (ref.value_type == REFTABLE_REF_SYMREF) {
+ strbuf_reset(referent);
+ strbuf_addstr(referent, ref.value.symref);
+ *type |= REF_ISSYMREF;
+ } else if (reftable_ref_record_val1(&ref)) {
+ oidread(oid, reftable_ref_record_val1(&ref));
+ } else {
+ /* We got a tombstone, which should not happen. */
+ BUG("unhandled reference value type %d", ref.value_type);
+ }
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ reftable_ref_record_release(&ref);
+ return ret;
+}
+
+static struct ref_store *reftable_be_init(struct repository *repo,
+ const char *gitdir,
+ unsigned int store_flags)
+{
+ struct reftable_ref_store *refs = xcalloc(1, sizeof(*refs));
+ struct strbuf path = STRBUF_INIT;
+ int is_worktree;
+ mode_t mask;
+
+ mask = umask(0);
+ umask(mask);
+
+ base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);
+ strmap_init(&refs->worktree_stacks);
+ refs->store_flags = store_flags;
+ refs->write_options.block_size = 4096;
+ refs->write_options.hash_id = repo->hash_algo->format_id;
+ refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);
+
+ /*
+ * Set up the main reftable stack that is hosted in GIT_COMMON_DIR.
+ * This stack contains both the shared and the main worktree refs.
+ *
+ * Note that we don't try to resolve the path in case we have a
+ * worktree because `get_common_dir_noenv()` already does it for us.
+ */
+ is_worktree = get_common_dir_noenv(&path, gitdir);
+ if (!is_worktree) {
+ strbuf_reset(&path);
+ strbuf_realpath(&path, gitdir, 0);
+ }
+ strbuf_addstr(&path, "/reftable");
+ refs->err = reftable_new_stack(&refs->main_stack, path.buf,
+ refs->write_options);
+ if (refs->err)
+ goto done;
+
+ /*
+ * If we're in a worktree we also need to set up the worktree reftable
+ * stack that is contained in the per-worktree GIT_DIR.
+ *
+ * Ideally, we would also add the stack to our worktree stack map. But
+ * we have no way to figure out the worktree name here and thus can't
+ * do it efficiently.
+ */
+ if (is_worktree) {
+ strbuf_reset(&path);
+ strbuf_addf(&path, "%s/reftable", gitdir);
+
+ refs->err = reftable_new_stack(&refs->worktree_stack, path.buf,
+ refs->write_options);
+ if (refs->err)
+ goto done;
+ }
+
+ chdir_notify_reparent("reftables-backend $GIT_DIR", &refs->base.gitdir);
+
+done:
+ assert(refs->err != REFTABLE_API_ERROR);
+ strbuf_release(&path);
+ return &refs->base;
+}
+
+static int reftable_be_init_db(struct ref_store *ref_store,
+ int flags UNUSED,
+ struct strbuf *err UNUSED)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "init_db");
+ struct strbuf sb = STRBUF_INIT;
+
+ strbuf_addf(&sb, "%s/reftable", refs->base.gitdir);
+ safe_create_dir(sb.buf, 1);
+ strbuf_reset(&sb);
+
+ strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir);
+ write_file(sb.buf, "ref: refs/heads/.invalid");
+ adjust_shared_perm(sb.buf);
+ strbuf_reset(&sb);
+
+ strbuf_addf(&sb, "%s/refs", refs->base.gitdir);
+ safe_create_dir(sb.buf, 1);
+ strbuf_reset(&sb);
+
+ strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir);
+ write_file(sb.buf, "this repository uses the reftable format");
+ adjust_shared_perm(sb.buf);
+
+ strbuf_release(&sb);
+ return 0;
+}
+
+struct reftable_ref_iterator {
+ struct ref_iterator base;
+ struct reftable_ref_store *refs;
+ struct reftable_iterator iter;
+ struct reftable_ref_record ref;
+ struct object_id oid;
+
+ const char *prefix;
+ size_t prefix_len;
+ unsigned int flags;
+ int err;
+};
+
+static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
+{
+ struct reftable_ref_iterator *iter =
+ (struct reftable_ref_iterator *)ref_iterator;
+ struct reftable_ref_store *refs = iter->refs;
+
+ while (!iter->err) {
+ int flags = 0;
+
+ iter->err = reftable_iterator_next_ref(&iter->iter, &iter->ref);
+ if (iter->err)
+ break;
+
+ /*
+ * The files backend only lists references contained in "refs/" unless
+ * the root refs are to be included. We emulate the same behaviour here.
+ */
+ if (!starts_with(iter->ref.refname, "refs/") &&
+ !(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
+ (is_pseudoref(&iter->refs->base, iter->ref.refname) ||
+ is_headref(&iter->refs->base, iter->ref.refname)))) {
+ continue;
+ }
+
+ if (iter->prefix_len &&
+ strncmp(iter->prefix, iter->ref.refname, iter->prefix_len)) {
+ iter->err = 1;
+ break;
+ }
+
+ if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
+ parse_worktree_ref(iter->ref.refname, NULL, NULL, NULL) !=
+ REF_WORKTREE_CURRENT)
+ continue;
+
+ switch (iter->ref.value_type) {
+ case REFTABLE_REF_VAL1:
+ oidread(&iter->oid, iter->ref.value.val1);
+ break;
+ case REFTABLE_REF_VAL2:
+ oidread(&iter->oid, iter->ref.value.val2.value);
+ break;
+ case REFTABLE_REF_SYMREF:
+ if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
+ RESOLVE_REF_READING, &iter->oid, &flags))
+ oidclr(&iter->oid);
+ break;
+ default:
+ BUG("unhandled reference value type %d", iter->ref.value_type);
+ }
+
+ if (is_null_oid(&iter->oid))
+ flags |= REF_ISBROKEN;
+
+ if (check_refname_format(iter->ref.refname, REFNAME_ALLOW_ONELEVEL)) {
+ if (!refname_is_safe(iter->ref.refname))
+ die(_("refname is dangerous: %s"), iter->ref.refname);
+ oidclr(&iter->oid);
+ flags |= REF_BAD_NAME | REF_ISBROKEN;
+ }
+
+ if (iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS &&
+ flags & REF_ISSYMREF &&
+ flags & REF_ISBROKEN)
+ continue;
+
+ if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
+ !ref_resolves_to_object(iter->ref.refname, refs->base.repo,
+ &iter->oid, flags))
+ continue;
+
+ iter->base.refname = iter->ref.refname;
+ iter->base.oid = &iter->oid;
+ iter->base.flags = flags;
+
+ break;
+ }
+
+ if (iter->err > 0) {
+ if (ref_iterator_abort(ref_iterator) != ITER_DONE)
+ return ITER_ERROR;
+ return ITER_DONE;
+ }
+
+ if (iter->err < 0) {
+ ref_iterator_abort(ref_iterator);
+ return ITER_ERROR;
+ }
+
+ return ITER_OK;
+}
+
+static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator,
+ struct object_id *peeled)
+{
+ struct reftable_ref_iterator *iter =
+ (struct reftable_ref_iterator *)ref_iterator;
+
+ if (iter->ref.value_type == REFTABLE_REF_VAL2) {
+ oidread(peeled, iter->ref.value.val2.target_value);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator)
+{
+ struct reftable_ref_iterator *iter =
+ (struct reftable_ref_iterator *)ref_iterator;
+ reftable_ref_record_release(&iter->ref);
+ reftable_iterator_destroy(&iter->iter);
+ free(iter);
+ return ITER_DONE;
+}
+
+static struct ref_iterator_vtable reftable_ref_iterator_vtable = {
+ .advance = reftable_ref_iterator_advance,
+ .peel = reftable_ref_iterator_peel,
+ .abort = reftable_ref_iterator_abort
+};
+
+static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_store *refs,
+ struct reftable_stack *stack,
+ const char *prefix,
+ int flags)
+{
+ struct reftable_merged_table *merged_table;
+ struct reftable_ref_iterator *iter;
+ int ret;
+
+ iter = xcalloc(1, sizeof(*iter));
+ base_ref_iterator_init(&iter->base, &reftable_ref_iterator_vtable);
+ iter->prefix = prefix;
+ iter->prefix_len = prefix ? strlen(prefix) : 0;
+ iter->base.oid = &iter->oid;
+ iter->flags = flags;
+ iter->refs = refs;
+
+ ret = refs->err;
+ if (ret)
+ goto done;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ goto done;
+
+ merged_table = reftable_stack_merged_table(stack);
+
+ ret = reftable_merged_table_seek_ref(merged_table, &iter->iter, prefix);
+ if (ret)
+ goto done;
+
+done:
+ iter->err = ret;
+ return iter;
+}
+
+static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_store,
+ const char *prefix,
+ const char **exclude_patterns,
+ unsigned int flags)
+{
+ struct reftable_ref_iterator *main_iter, *worktree_iter;
+ struct reftable_ref_store *refs;
+ unsigned int required_flags = REF_STORE_READ;
+
+ if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
+ required_flags |= REF_STORE_ODB;
+ refs = reftable_be_downcast(ref_store, required_flags, "ref_iterator_begin");
+
+ main_iter = ref_iterator_for_stack(refs, refs->main_stack, prefix, flags);
+
+ /*
+ * The worktree stack is only set when we're in an actual worktree
+ * right now. If we aren't, then we return the common reftable
+ * iterator, only.
+ */
+ if (!refs->worktree_stack)
+ return &main_iter->base;
+
+ /*
+ * Otherwise we merge both the common and the per-worktree refs into a
+ * single iterator.
+ */
+ worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix, flags);
+ return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base,
+ ref_iterator_select, NULL);
+}
+
+static int reftable_be_read_raw_ref(struct ref_store *ref_store,
+ const char *refname,
+ struct object_id *oid,
+ struct strbuf *referent,
+ unsigned int *type,
+ int *failure_errno)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ int ret;
+
+ if (refs->err < 0)
+ return refs->err;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ return ret;
+
+ ret = read_ref_without_reload(stack, refname, oid, referent, type);
+ if (ret < 0)
+ return ret;
+ if (ret > 0) {
+ *failure_errno = ENOENT;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int reftable_be_read_symbolic_ref(struct ref_store *ref_store,
+ const char *refname,
+ struct strbuf *referent)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_READ, "read_symbolic_ref");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct reftable_ref_record ref = {0};
+ int ret;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ return ret;
+
+ ret = reftable_stack_read_ref(stack, refname, &ref);
+ if (ret == 0 && ref.value_type == REFTABLE_REF_SYMREF)
+ strbuf_addstr(referent, ref.value.symref);
+ else
+ ret = -1;
+
+ reftable_ref_record_release(&ref);
+ return ret;
+}
+
+/*
+ * Return the refname under which update was originally requested.
+ */
+static const char *original_update_refname(struct ref_update *update)
+{
+ while (update->parent_update)
+ update = update->parent_update;
+ return update->refname;
+}
+
+struct reftable_transaction_update {
+ struct ref_update *update;
+ struct object_id current_oid;
+};
+
+struct write_transaction_table_arg {
+ struct reftable_ref_store *refs;
+ struct reftable_stack *stack;
+ struct reftable_addition *addition;
+ struct reftable_transaction_update *updates;
+ size_t updates_nr;
+ size_t updates_alloc;
+ size_t updates_expected;
+};
+
+struct reftable_transaction_data {
+ struct write_transaction_table_arg *args;
+ size_t args_nr, args_alloc;
+};
+
+static void free_transaction_data(struct reftable_transaction_data *tx_data)
+{
+ if (!tx_data)
+ return;
+ for (size_t i = 0; i < tx_data->args_nr; i++) {
+ reftable_addition_destroy(tx_data->args[i].addition);
+ free(tx_data->args[i].updates);
+ }
+ free(tx_data->args);
+ free(tx_data);
+}
+
+/*
+ * Prepare transaction update for the given reference update. This will cause
+ * us to lock the corresponding reftable stack for concurrent modification.
+ */
+static int prepare_transaction_update(struct write_transaction_table_arg **out,
+ struct reftable_ref_store *refs,
+ struct reftable_transaction_data *tx_data,
+ struct ref_update *update,
+ struct strbuf *err)
+{
+ struct reftable_stack *stack = stack_for(refs, update->refname, NULL);
+ struct write_transaction_table_arg *arg = NULL;
+ size_t i;
+ int ret;
+
+ /*
+ * Search for a preexisting stack update. If there is one then we add
+ * the update to it, otherwise we set up a new stack update.
+ */
+ for (i = 0; !arg && i < tx_data->args_nr; i++)
+ if (tx_data->args[i].stack == stack)
+ arg = &tx_data->args[i];
+
+ if (!arg) {
+ struct reftable_addition *addition;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ return ret;
+
+ ret = reftable_stack_new_addition(&addition, stack);
+ if (ret) {
+ if (ret == REFTABLE_LOCK_ERROR)
+ strbuf_addstr(err, "cannot lock references");
+ return ret;
+ }
+
+ ALLOC_GROW(tx_data->args, tx_data->args_nr + 1,
+ tx_data->args_alloc);
+ arg = &tx_data->args[tx_data->args_nr++];
+ arg->refs = refs;
+ arg->stack = stack;
+ arg->addition = addition;
+ arg->updates = NULL;
+ arg->updates_nr = 0;
+ arg->updates_alloc = 0;
+ arg->updates_expected = 0;
+ }
+
+ arg->updates_expected++;
+
+ if (out)
+ *out = arg;
+
+ return 0;
+}
+
+/*
+ * Queue a reference update for the correct stack. We potentially need to
+ * handle multiple stack updates in a single transaction when it spans across
+ * multiple worktrees.
+ */
+static int queue_transaction_update(struct reftable_ref_store *refs,
+ struct reftable_transaction_data *tx_data,
+ struct ref_update *update,
+ struct object_id *current_oid,
+ struct strbuf *err)
+{
+ struct write_transaction_table_arg *arg = NULL;
+ int ret;
+
+ if (update->backend_data)
+ BUG("reference update queued more than once");
+
+ ret = prepare_transaction_update(&arg, refs, tx_data, update, err);
+ if (ret < 0)
+ return ret;
+
+ ALLOC_GROW(arg->updates, arg->updates_nr + 1,
+ arg->updates_alloc);
+ arg->updates[arg->updates_nr].update = update;
+ oidcpy(&arg->updates[arg->updates_nr].current_oid, current_oid);
+ update->backend_data = &arg->updates[arg->updates_nr++];
+
+ return 0;
+}
+
+static int reftable_be_transaction_prepare(struct ref_store *ref_store,
+ struct ref_transaction *transaction,
+ struct strbuf *err)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE|REF_STORE_MAIN, "ref_transaction_prepare");
+ struct strbuf referent = STRBUF_INIT, head_referent = STRBUF_INIT;
+ struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
+ struct reftable_transaction_data *tx_data = NULL;
+ struct object_id head_oid;
+ unsigned int head_type = 0;
+ size_t i;
+ int ret;
+
+ ret = refs->err;
+ if (ret < 0)
+ goto done;
+
+ tx_data = xcalloc(1, sizeof(*tx_data));
+
+ /*
+ * Preprocess all updates. For one we check that there are no duplicate
+ * reference updates in this transaction. Second, we lock all stacks
+ * that will be modified during the transaction.
+ */
+ for (i = 0; i < transaction->nr; i++) {
+ ret = prepare_transaction_update(NULL, refs, tx_data,
+ transaction->updates[i], err);
+ if (ret)
+ goto done;
+
+ string_list_append(&affected_refnames,
+ transaction->updates[i]->refname);
+ }
+
+ /*
+ * Now that we have counted updates per stack we can preallocate their
+ * arrays. This avoids having to reallocate many times.
+ */
+ for (i = 0; i < tx_data->args_nr; i++) {
+ CALLOC_ARRAY(tx_data->args[i].updates, tx_data->args[i].updates_expected);
+ tx_data->args[i].updates_alloc = tx_data->args[i].updates_expected;
+ }
+
+ /*
+ * Fail if a refname appears more than once in the transaction.
+ * This code is taken from the files backend and is a good candidate to
+ * be moved into the generic layer.
+ */
+ string_list_sort(&affected_refnames);
+ if (ref_update_reject_duplicates(&affected_refnames, err)) {
+ ret = TRANSACTION_GENERIC_ERROR;
+ goto done;
+ }
+
+ ret = read_ref_without_reload(stack_for(refs, "HEAD", NULL), "HEAD", &head_oid,
+ &head_referent, &head_type);
+ if (ret < 0)
+ goto done;
+ ret = 0;
+
+ for (i = 0; i < transaction->nr; i++) {
+ struct ref_update *u = transaction->updates[i];
+ struct object_id current_oid = {0};
+ struct reftable_stack *stack;
+ const char *rewritten_ref;
+
+ stack = stack_for(refs, u->refname, &rewritten_ref);
+
+ /* Verify that the new object ID is valid. */
+ if ((u->flags & REF_HAVE_NEW) && !is_null_oid(&u->new_oid) &&
+ !(u->flags & REF_SKIP_OID_VERIFICATION) &&
+ !(u->flags & REF_LOG_ONLY)) {
+ struct object *o = parse_object(refs->base.repo, &u->new_oid);
+ if (!o) {
+ strbuf_addf(err,
+ _("trying to write ref '%s' with nonexistent object %s"),
+ u->refname, oid_to_hex(&u->new_oid));
+ ret = -1;
+ goto done;
+ }
+
+ if (o->type != OBJ_COMMIT && is_branch(u->refname)) {
+ strbuf_addf(err, _("trying to write non-commit object %s to branch '%s'"),
+ oid_to_hex(&u->new_oid), u->refname);
+ ret = -1;
+ goto done;
+ }
+ }
+
+ /*
+ * When we update the reference that HEAD points to we enqueue
+ * a second log-only update for HEAD so that its reflog is
+ * updated accordingly.
+ */
+ if (head_type == REF_ISSYMREF &&
+ !(u->flags & REF_LOG_ONLY) &&
+ !(u->flags & REF_UPDATE_VIA_HEAD) &&
+ !strcmp(rewritten_ref, head_referent.buf)) {
+ struct ref_update *new_update;
+
+ /*
+ * First make sure that HEAD is not already in the
+ * transaction. This check is O(lg N) in the transaction
+ * size, but it happens at most once per transaction.
+ */
+ if (string_list_has_string(&affected_refnames, "HEAD")) {
+ /* An entry already existed */
+ strbuf_addf(err,
+ _("multiple updates for 'HEAD' (including one "
+ "via its referent '%s') are not allowed"),
+ u->refname);
+ ret = TRANSACTION_NAME_CONFLICT;
+ goto done;
+ }
+
+ new_update = ref_transaction_add_update(
+ transaction, "HEAD",
+ u->flags | REF_LOG_ONLY | REF_NO_DEREF,
+ &u->new_oid, &u->old_oid, u->msg);
+ string_list_insert(&affected_refnames, new_update->refname);
+ }
+
+ ret = read_ref_without_reload(stack, rewritten_ref,
+ ¤t_oid, &referent, &u->type);
+ if (ret < 0)
+ goto done;
+ if (ret > 0 && (!(u->flags & REF_HAVE_OLD) || is_null_oid(&u->old_oid))) {
+ /*
+ * The reference does not exist, and we either have no
+ * old object ID or expect the reference to not exist.
+ * We can thus skip below safety checks as well as the
+ * symref splitting. But we do want to verify that
+ * there is no conflicting reference here so that we
+ * can output a proper error message instead of failing
+ * at a later point.
+ */
+ ret = refs_verify_refname_available(ref_store, u->refname,
+ &affected_refnames, NULL, err);
+ if (ret < 0)
+ goto done;
+
+ /*
+ * There is no need to write the reference deletion
+ * when the reference in question doesn't exist.
+ */
+ if (u->flags & REF_HAVE_NEW && !is_null_oid(&u->new_oid)) {
+ ret = queue_transaction_update(refs, tx_data, u,
+ ¤t_oid, err);
+ if (ret)
+ goto done;
+ }
+
+ continue;
+ }
+ if (ret > 0) {
+ /* The reference does not exist, but we expected it to. */
+ strbuf_addf(err, _("cannot lock ref '%s': "
+ "unable to resolve reference '%s'"),
+ original_update_refname(u), u->refname);
+ ret = -1;
+ goto done;
+ }
+
+ if (u->type & REF_ISSYMREF) {
+ /*
+ * The reftable stack is locked at this point already,
+ * so it is safe to call `refs_resolve_ref_unsafe()`
+ * here without causing races.
+ */
+ const char *resolved = refs_resolve_ref_unsafe(&refs->base, u->refname, 0,
+ ¤t_oid, NULL);
+
+ if (u->flags & REF_NO_DEREF) {
+ if (u->flags & REF_HAVE_OLD && !resolved) {
+ strbuf_addf(err, _("cannot lock ref '%s': "
+ "error reading reference"), u->refname);
+ ret = -1;
+ goto done;
+ }
+ } else {
+ struct ref_update *new_update;
+ int new_flags;
+
+ new_flags = u->flags;
+ if (!strcmp(rewritten_ref, "HEAD"))
+ new_flags |= REF_UPDATE_VIA_HEAD;
+
+ /*
+ * If we are updating a symref (eg. HEAD), we should also
+ * update the branch that the symref points to.
+ *
+ * This is generic functionality, and would be better
+ * done in refs.c, but the current implementation is
+ * intertwined with the locking in files-backend.c.
+ */
+ new_update = ref_transaction_add_update(
+ transaction, referent.buf, new_flags,
+ &u->new_oid, &u->old_oid, u->msg);
+ new_update->parent_update = u;
+
+ /*
+ * Change the symbolic ref update to log only. Also, it
+ * doesn't need to check its old OID value, as that will be
+ * done when new_update is processed.
+ */
+ u->flags |= REF_LOG_ONLY | REF_NO_DEREF;
+ u->flags &= ~REF_HAVE_OLD;
+
+ if (string_list_has_string(&affected_refnames, new_update->refname)) {
+ strbuf_addf(err,
+ _("multiple updates for '%s' (including one "
+ "via symref '%s') are not allowed"),
+ referent.buf, u->refname);
+ ret = TRANSACTION_NAME_CONFLICT;
+ goto done;
+ }
+ string_list_insert(&affected_refnames, new_update->refname);
+ }
+ }
+
+ /*
+ * Verify that the old object matches our expectations. Note
+ * that the error messages here do not make a lot of sense in
+ * the context of the reftable backend as we never lock
+ * individual refs. But the error messages match what the files
+ * backend returns, which keeps our tests happy.
+ */
+ if (u->flags & REF_HAVE_OLD && !oideq(¤t_oid, &u->old_oid)) {
+ if (is_null_oid(&u->old_oid))
+ strbuf_addf(err, _("cannot lock ref '%s': "
+ "reference already exists"),
+ original_update_refname(u));
+ else if (is_null_oid(¤t_oid))
+ strbuf_addf(err, _("cannot lock ref '%s': "
+ "reference is missing but expected %s"),
+ original_update_refname(u),
+ oid_to_hex(&u->old_oid));
+ else
+ strbuf_addf(err, _("cannot lock ref '%s': "
+ "is at %s but expected %s"),
+ original_update_refname(u),
+ oid_to_hex(¤t_oid),
+ oid_to_hex(&u->old_oid));
+ ret = -1;
+ goto done;
+ }
+
+ /*
+ * If all of the following conditions are true:
+ *
+ * - We're not about to write a symref.
+ * - We're not about to write a log-only entry.
+ * - Old and new object ID are different.
+ *
+ * Then we're essentially doing a no-op update that can be
+ * skipped. This is not only for the sake of efficiency, but
+ * also skips writing unneeded reflog entries.
+ */
+ if ((u->type & REF_ISSYMREF) ||
+ (u->flags & REF_LOG_ONLY) ||
+ (u->flags & REF_HAVE_NEW && !oideq(¤t_oid, &u->new_oid))) {
+ ret = queue_transaction_update(refs, tx_data, u,
+ ¤t_oid, err);
+ if (ret)
+ goto done;
+ }
+ }
+
+ transaction->backend_data = tx_data;
+ transaction->state = REF_TRANSACTION_PREPARED;
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ if (ret < 0) {
+ free_transaction_data(tx_data);
+ transaction->state = REF_TRANSACTION_CLOSED;
+ if (!err->len)
+ strbuf_addf(err, _("reftable: transaction prepare: %s"),
+ reftable_error_str(ret));
+ }
+ string_list_clear(&affected_refnames, 0);
+ strbuf_release(&referent);
+ strbuf_release(&head_referent);
+
+ return ret;
+}
+
+static int reftable_be_transaction_abort(struct ref_store *ref_store,
+ struct ref_transaction *transaction,
+ struct strbuf *err)
+{
+ struct reftable_transaction_data *tx_data = transaction->backend_data;
+ free_transaction_data(tx_data);
+ transaction->state = REF_TRANSACTION_CLOSED;
+ return 0;
+}
+
+static int transaction_update_cmp(const void *a, const void *b)
+{
+ return strcmp(((struct reftable_transaction_update *)a)->update->refname,
+ ((struct reftable_transaction_update *)b)->update->refname);
+}
+
+static int write_transaction_table(struct reftable_writer *writer, void *cb_data)
+{
+ struct write_transaction_table_arg *arg = cb_data;
+ struct reftable_merged_table *mt =
+ reftable_stack_merged_table(arg->stack);
+ uint64_t ts = reftable_stack_next_update_index(arg->stack);
+ struct reftable_log_record *logs = NULL;
+ size_t logs_nr = 0, logs_alloc = 0, i;
+ int ret = 0;
+
+ QSORT(arg->updates, arg->updates_nr, transaction_update_cmp);
+
+ reftable_writer_set_limits(writer, ts, ts);
+
+ for (i = 0; i < arg->updates_nr; i++) {
+ struct reftable_transaction_update *tx_update = &arg->updates[i];
+ struct ref_update *u = tx_update->update;
+
+ /*
+ * Write a reflog entry when updating a ref to point to
+ * something new in either of the following cases:
+ *
+ * - The reference is about to be deleted. We always want to
+ * delete the reflog in that case.
+ * - REF_FORCE_CREATE_REFLOG is set, asking us to always create
+ * the reflog entry.
+ * - `core.logAllRefUpdates` tells us to create the reflog for
+ * the given ref.
+ */
+ if (u->flags & REF_HAVE_NEW && !(u->type & REF_ISSYMREF) && is_null_oid(&u->new_oid)) {
+ struct reftable_log_record log = {0};
+ struct reftable_iterator it = {0};
+
+ /*
+ * When deleting refs we also delete all reflog entries
+ * with them. While it is not strictly required to
+ * delete reflogs together with their refs, this
+ * matches the behaviour of the files backend.
+ *
+ * Unfortunately, we have no better way than to delete
+ * all reflog entries one by one.
+ */
+ ret = reftable_merged_table_seek_log(mt, &it, u->refname);
+ while (ret == 0) {
+ struct reftable_log_record *tombstone;
+
+ ret = reftable_iterator_next_log(&it, &log);
+ if (ret < 0)
+ break;
+ if (ret > 0 || strcmp(log.refname, u->refname)) {
+ ret = 0;
+ break;
+ }
+
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ tombstone = &logs[logs_nr++];
+ tombstone->refname = xstrdup(u->refname);
+ tombstone->value_type = REFTABLE_LOG_DELETION;
+ tombstone->update_index = log.update_index;
+ }
+
+ reftable_log_record_release(&log);
+ reftable_iterator_destroy(&it);
+
+ if (ret)
+ goto done;
+ } else if (u->flags & REF_HAVE_NEW &&
+ (u->flags & REF_FORCE_CREATE_REFLOG ||
+ should_write_log(&arg->refs->base, u->refname))) {
+ struct reftable_log_record *log;
+
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ log = &logs[logs_nr++];
+ memset(log, 0, sizeof(*log));
+
+ fill_reftable_log_record(log);
+ log->update_index = ts;
+ log->refname = xstrdup(u->refname);
+ log->value.update.new_hash = u->new_oid.hash;
+ log->value.update.old_hash = tx_update->current_oid.hash;
+ log->value.update.message =
+ xstrndup(u->msg, arg->refs->write_options.block_size / 2);
+ }
+
+ if (u->flags & REF_LOG_ONLY)
+ continue;
+
+ if (u->flags & REF_HAVE_NEW && is_null_oid(&u->new_oid)) {
+ struct reftable_ref_record ref = {
+ .refname = (char *)u->refname,
+ .update_index = ts,
+ .value_type = REFTABLE_REF_DELETION,
+ };
+
+ ret = reftable_writer_add_ref(writer, &ref);
+ if (ret < 0)
+ goto done;
+ } else if (u->flags & REF_HAVE_NEW) {
+ struct reftable_ref_record ref = {0};
+ struct object_id peeled;
+ int peel_error;
+
+ ref.refname = (char *)u->refname;
+ ref.update_index = ts;
+
+ peel_error = peel_object(&u->new_oid, &peeled);
+ if (!peel_error) {
+ ref.value_type = REFTABLE_REF_VAL2;
+ memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
+ memcpy(ref.value.val2.value, u->new_oid.hash, GIT_MAX_RAWSZ);
+ } else if (!is_null_oid(&u->new_oid)) {
+ ref.value_type = REFTABLE_REF_VAL1;
+ memcpy(ref.value.val1, u->new_oid.hash, GIT_MAX_RAWSZ);
+ }
+
+ ret = reftable_writer_add_ref(writer, &ref);
+ if (ret < 0)
+ goto done;
+ }
+ }
+
+ /*
+ * Logs are written at the end so that we do not have intermixed ref
+ * and log blocks.
+ */
+ if (logs) {
+ ret = reftable_writer_add_logs(writer, logs, logs_nr);
+ if (ret < 0)
+ goto done;
+ }
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ for (i = 0; i < logs_nr; i++)
+ clear_reftable_log_record(&logs[i]);
+ free(logs);
+ return ret;
+}
+
+static int reftable_be_transaction_finish(struct ref_store *ref_store,
+ struct ref_transaction *transaction,
+ struct strbuf *err)
+{
+ struct reftable_transaction_data *tx_data = transaction->backend_data;
+ int ret = 0;
+
+ for (size_t i = 0; i < tx_data->args_nr; i++) {
+ ret = reftable_addition_add(tx_data->args[i].addition,
+ write_transaction_table, &tx_data->args[i]);
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_addition_commit(tx_data->args[i].addition);
+ if (ret < 0)
+ goto done;
+ }
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ free_transaction_data(tx_data);
+ transaction->state = REF_TRANSACTION_CLOSED;
+
+ if (ret) {
+ strbuf_addf(err, _("reftable: transaction failure: %s"),
+ reftable_error_str(ret));
+ return -1;
+ }
+ return ret;
+}
+
+static int reftable_be_initial_transaction_commit(struct ref_store *ref_store UNUSED,
+ struct ref_transaction *transaction,
+ struct strbuf *err)
+{
+ return ref_transaction_commit(transaction, err);
+}
+
+static int reftable_be_pack_refs(struct ref_store *ref_store,
+ struct pack_refs_opts *opts)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE | REF_STORE_ODB, "pack_refs");
+ struct reftable_stack *stack;
+ int ret;
+
+ if (refs->err)
+ return refs->err;
+
+ stack = refs->worktree_stack;
+ if (!stack)
+ stack = refs->main_stack;
+
+ ret = reftable_stack_compact_all(stack, NULL);
+ if (ret)
+ goto out;
+ ret = reftable_stack_clean(stack);
+ if (ret)
+ goto out;
+
+out:
+ return ret;
+}
+
+struct write_create_symref_arg {
+ struct reftable_ref_store *refs;
+ struct reftable_stack *stack;
+ const char *refname;
+ const char *target;
+ const char *logmsg;
+};
+
+static int write_create_symref_table(struct reftable_writer *writer, void *cb_data)
+{
+ struct write_create_symref_arg *create = cb_data;
+ uint64_t ts = reftable_stack_next_update_index(create->stack);
+ struct reftable_ref_record ref = {
+ .refname = (char *)create->refname,
+ .value_type = REFTABLE_REF_SYMREF,
+ .value.symref = (char *)create->target,
+ .update_index = ts,
+ };
+ struct reftable_log_record log = {0};
+ struct object_id new_oid;
+ struct object_id old_oid;
+ int ret;
+
+ reftable_writer_set_limits(writer, ts, ts);
+
+ ret = reftable_writer_add_ref(writer, &ref);
+ if (ret)
+ return ret;
+
+ /*
+ * Note that it is important to try and resolve the reference before we
+ * write the log entry. This is because `should_write_log()` will munge
+ * `core.logAllRefUpdates`, which is undesirable when we create a new
+ * repository because it would be written into the config. As HEAD will
+ * not resolve for new repositories this ordering will ensure that this
+ * never happens.
+ */
+ if (!create->logmsg ||
+ !refs_resolve_ref_unsafe(&create->refs->base, create->target,
+ RESOLVE_REF_READING, &new_oid, NULL) ||
+ !should_write_log(&create->refs->base, create->refname))
+ return 0;
+
+ fill_reftable_log_record(&log);
+ log.refname = xstrdup(create->refname);
+ log.update_index = ts;
+ log.value.update.message = xstrndup(create->logmsg,
+ create->refs->write_options.block_size / 2);
+ log.value.update.new_hash = new_oid.hash;
+ if (refs_resolve_ref_unsafe(&create->refs->base, create->refname,
+ RESOLVE_REF_READING, &old_oid, NULL))
+ log.value.update.old_hash = old_oid.hash;
+
+ ret = reftable_writer_add_log(writer, &log);
+ clear_reftable_log_record(&log);
+ return ret;
+}
+
+static int reftable_be_create_symref(struct ref_store *ref_store,
+ const char *refname,
+ const char *target,
+ const char *logmsg)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_symref");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct write_create_symref_arg arg = {
+ .refs = refs,
+ .stack = stack,
+ .refname = refname,
+ .target = target,
+ .logmsg = logmsg,
+ };
+ int ret;
+
+ ret = refs->err;
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ goto done;
+
+ ret = reftable_stack_add(stack, &write_create_symref_table, &arg);
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ if (ret)
+ error("unable to write symref for %s: %s", refname,
+ reftable_error_str(ret));
+ return ret;
+}
+
+struct write_copy_arg {
+ struct reftable_ref_store *refs;
+ struct reftable_stack *stack;
+ const char *oldname;
+ const char *newname;
+ const char *logmsg;
+ int delete_old;
+};
+
+static int write_copy_table(struct reftable_writer *writer, void *cb_data)
+{
+ struct write_copy_arg *arg = cb_data;
+ uint64_t deletion_ts, creation_ts;
+ struct reftable_merged_table *mt = reftable_stack_merged_table(arg->stack);
+ struct reftable_ref_record old_ref = {0}, refs[2] = {0};
+ struct reftable_log_record old_log = {0}, *logs = NULL;
+ struct reftable_iterator it = {0};
+ struct string_list skip = STRING_LIST_INIT_NODUP;
+ struct strbuf errbuf = STRBUF_INIT;
+ size_t logs_nr = 0, logs_alloc = 0, i;
+ int ret;
+
+ if (reftable_stack_read_ref(arg->stack, arg->oldname, &old_ref)) {
+ ret = error(_("refname %s not found"), arg->oldname);
+ goto done;
+ }
+ if (old_ref.value_type == REFTABLE_REF_SYMREF) {
+ ret = error(_("refname %s is a symbolic ref, copying it is not supported"),
+ arg->oldname);
+ goto done;
+ }
+
+ /*
+ * There's nothing to do in case the old and new name are the same, so
+ * we exit early in that case.
+ */
+ if (!strcmp(arg->oldname, arg->newname)) {
+ ret = 0;
+ goto done;
+ }
+
+ /*
+ * Verify that the new refname is available.
+ */
+ string_list_insert(&skip, arg->oldname);
+ ret = refs_verify_refname_available(&arg->refs->base, arg->newname,
+ NULL, &skip, &errbuf);
+ if (ret < 0) {
+ error("%s", errbuf.buf);
+ goto done;
+ }
+
+ /*
+ * When deleting the old reference we have to use two update indices:
+ * once to delete the old ref and its reflog, and once to create the
+ * new ref and its reflog. They need to be staged with two separate
+ * indices because the new reflog needs to encode both the deletion of
+ * the old branch and the creation of the new branch, and we cannot do
+ * two changes to a reflog in a single update.
+ */
+ deletion_ts = creation_ts = reftable_stack_next_update_index(arg->stack);
+ if (arg->delete_old)
+ creation_ts++;
+ reftable_writer_set_limits(writer, deletion_ts, creation_ts);
+
+ /*
+ * Add the new reference. If this is a rename then we also delete the
+ * old reference.
+ */
+ refs[0] = old_ref;
+ refs[0].refname = (char *)arg->newname;
+ refs[0].update_index = creation_ts;
+ if (arg->delete_old) {
+ refs[1].refname = (char *)arg->oldname;
+ refs[1].value_type = REFTABLE_REF_DELETION;
+ refs[1].update_index = deletion_ts;
+ }
+ ret = reftable_writer_add_refs(writer, refs, arg->delete_old ? 2 : 1);
+ if (ret < 0)
+ goto done;
+
+ /*
+ * When deleting the old branch we need to create a reflog entry on the
+ * new branch name that indicates that the old branch has been deleted
+ * and then recreated. This is a tad weird, but matches what the files
+ * backend does.
+ */
+ if (arg->delete_old) {
+ struct strbuf head_referent = STRBUF_INIT;
+ struct object_id head_oid;
+ int append_head_reflog;
+ unsigned head_type = 0;
+
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
+ fill_reftable_log_record(&logs[logs_nr]);
+ logs[logs_nr].refname = (char *)arg->newname;
+ logs[logs_nr].update_index = deletion_ts;
+ logs[logs_nr].value.update.message =
+ xstrndup(arg->logmsg, arg->refs->write_options.block_size / 2);
+ logs[logs_nr].value.update.old_hash = old_ref.value.val1;
+ logs_nr++;
+
+ ret = read_ref_without_reload(arg->stack, "HEAD", &head_oid, &head_referent, &head_type);
+ if (ret < 0)
+ goto done;
+ append_head_reflog = (head_type & REF_ISSYMREF) && !strcmp(head_referent.buf, arg->oldname);
+ strbuf_release(&head_referent);
+
+ /*
+ * The files backend uses `refs_delete_ref()` to delete the old
+ * branch name, which will append a reflog entry for HEAD in
+ * case it points to the old branch.
+ */
+ if (append_head_reflog) {
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ logs[logs_nr] = logs[logs_nr - 1];
+ logs[logs_nr].refname = "HEAD";
+ logs_nr++;
+ }
+ }
+
+ /*
+ * Create the reflog entry for the newly created branch.
+ */
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
+ fill_reftable_log_record(&logs[logs_nr]);
+ logs[logs_nr].refname = (char *)arg->newname;
+ logs[logs_nr].update_index = creation_ts;
+ logs[logs_nr].value.update.message =
+ xstrndup(arg->logmsg, arg->refs->write_options.block_size / 2);
+ logs[logs_nr].value.update.new_hash = old_ref.value.val1;
+ logs_nr++;
+
+ /*
+ * In addition to writing the reflog entry for the new branch, we also
+ * copy over all log entries from the old reflog. Last but not least,
+ * when renaming we also have to delete all the old reflog entries.
+ */
+ ret = reftable_merged_table_seek_log(mt, &it, arg->oldname);
+ if (ret < 0)
+ goto done;
+
+ while (1) {
+ ret = reftable_iterator_next_log(&it, &old_log);
+ if (ret < 0)
+ goto done;
+ if (ret > 0 || strcmp(old_log.refname, arg->oldname)) {
+ ret = 0;
+ break;
+ }
+
+ free(old_log.refname);
+
+ /*
+ * Copy over the old reflog entry with the new refname.
+ */
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ logs[logs_nr] = old_log;
+ logs[logs_nr].refname = (char *)arg->newname;
+ logs_nr++;
+
+ /*
+ * Delete the old reflog entry in case we are renaming.
+ */
+ if (arg->delete_old) {
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
+ logs[logs_nr].refname = (char *)arg->oldname;
+ logs[logs_nr].value_type = REFTABLE_LOG_DELETION;
+ logs[logs_nr].update_index = old_log.update_index;
+ logs_nr++;
+ }
+
+ /*
+ * Transfer ownership of the log record we're iterating over to
+ * the array of log records. Otherwise, the pointers would get
+ * free'd or reallocated by the iterator.
+ */
+ memset(&old_log, 0, sizeof(old_log));
+ }
+
+ ret = reftable_writer_add_logs(writer, logs, logs_nr);
+ if (ret < 0)
+ goto done;
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ reftable_iterator_destroy(&it);
+ string_list_clear(&skip, 0);
+ strbuf_release(&errbuf);
+ for (i = 0; i < logs_nr; i++) {
+ if (!strcmp(logs[i].refname, "HEAD"))
+ continue;
+ if (logs[i].value.update.old_hash == old_ref.value.val1)
+ logs[i].value.update.old_hash = NULL;
+ if (logs[i].value.update.new_hash == old_ref.value.val1)
+ logs[i].value.update.new_hash = NULL;
+ logs[i].refname = NULL;
+ reftable_log_record_release(&logs[i]);
+ }
+ free(logs);
+ reftable_ref_record_release(&old_ref);
+ reftable_log_record_release(&old_log);
+ return ret;
+}
+
+static int reftable_be_rename_ref(struct ref_store *ref_store,
+ const char *oldrefname,
+ const char *newrefname,
+ const char *logmsg)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "rename_ref");
+ struct reftable_stack *stack = stack_for(refs, newrefname, &newrefname);
+ struct write_copy_arg arg = {
+ .refs = refs,
+ .stack = stack,
+ .oldname = oldrefname,
+ .newname = newrefname,
+ .logmsg = logmsg,
+ .delete_old = 1,
+ };
+ int ret;
+
+ ret = refs->err;
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ goto done;
+ ret = reftable_stack_add(stack, &write_copy_table, &arg);
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ return ret;
+}
+
+static int reftable_be_copy_ref(struct ref_store *ref_store,
+ const char *oldrefname,
+ const char *newrefname,
+ const char *logmsg)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "copy_ref");
+ struct reftable_stack *stack = stack_for(refs, newrefname, &newrefname);
+ struct write_copy_arg arg = {
+ .refs = refs,
+ .stack = stack,
+ .oldname = oldrefname,
+ .newname = newrefname,
+ .logmsg = logmsg,
+ };
+ int ret;
+
+ ret = refs->err;
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ goto done;
+ ret = reftable_stack_add(stack, &write_copy_table, &arg);
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ return ret;
+}
+
+struct reftable_reflog_iterator {
+ struct ref_iterator base;
+ struct reftable_ref_store *refs;
+ struct reftable_iterator iter;
+ struct reftable_log_record log;
+ char *last_name;
+ int err;
+};
+
+static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator)
+{
+ struct reftable_reflog_iterator *iter =
+ (struct reftable_reflog_iterator *)ref_iterator;
+
+ while (!iter->err) {
+ iter->err = reftable_iterator_next_log(&iter->iter, &iter->log);
+ if (iter->err)
+ break;
+
+ /*
+ * We want the refnames that we have reflogs for, so we skip if
+ * we've already produced this name. This could be faster by
+ * seeking directly to reflog@update_index==0.
+ */
+ if (iter->last_name && !strcmp(iter->log.refname, iter->last_name))
+ continue;
+
+ if (check_refname_format(iter->log.refname,
+ REFNAME_ALLOW_ONELEVEL))
+ continue;
+
+ free(iter->last_name);
+ iter->last_name = xstrdup(iter->log.refname);
+ iter->base.refname = iter->log.refname;
+
+ break;
+ }
+
+ if (iter->err > 0) {
+ if (ref_iterator_abort(ref_iterator) != ITER_DONE)
+ return ITER_ERROR;
+ return ITER_DONE;
+ }
+
+ if (iter->err < 0) {
+ ref_iterator_abort(ref_iterator);
+ return ITER_ERROR;
+ }
+
+ return ITER_OK;
+}
+
+static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator,
+ struct object_id *peeled)
+{
+ BUG("reftable reflog iterator cannot be peeled");
+ return -1;
+}
+
+static int reftable_reflog_iterator_abort(struct ref_iterator *ref_iterator)
+{
+ struct reftable_reflog_iterator *iter =
+ (struct reftable_reflog_iterator *)ref_iterator;
+ reftable_log_record_release(&iter->log);
+ reftable_iterator_destroy(&iter->iter);
+ free(iter->last_name);
+ free(iter);
+ return ITER_DONE;
+}
+
+static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
+ .advance = reftable_reflog_iterator_advance,
+ .peel = reftable_reflog_iterator_peel,
+ .abort = reftable_reflog_iterator_abort
+};
+
+static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs,
+ struct reftable_stack *stack)
+{
+ struct reftable_merged_table *merged_table;
+ struct reftable_reflog_iterator *iter;
+ int ret;
+
+ iter = xcalloc(1, sizeof(*iter));
+ base_ref_iterator_init(&iter->base, &reftable_reflog_iterator_vtable);
+ iter->refs = refs;
+
+ ret = refs->err;
+ if (ret)
+ goto done;
+
+ ret = reftable_stack_reload(refs->main_stack);
+ if (ret < 0)
+ goto done;
+
+ merged_table = reftable_stack_merged_table(stack);
+
+ ret = reftable_merged_table_seek_log(merged_table, &iter->iter, "");
+ if (ret < 0)
+ goto done;
+
+done:
+ iter->err = ret;
+ return iter;
+}
+
+static struct ref_iterator *reftable_be_reflog_iterator_begin(struct ref_store *ref_store)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_iterator_begin");
+ struct reftable_reflog_iterator *main_iter, *worktree_iter;
+
+ main_iter = reflog_iterator_for_stack(refs, refs->main_stack);
+ if (!refs->worktree_stack)
+ return &main_iter->base;
+
+ worktree_iter = reflog_iterator_for_stack(refs, refs->worktree_stack);
+
+ return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base,
+ ref_iterator_select, NULL);
+}
+
+static int yield_log_record(struct reftable_log_record *log,
+ each_reflog_ent_fn fn,
+ void *cb_data)
+{
+ struct object_id old_oid, new_oid;
+ const char *full_committer;
+
+ oidread(&old_oid, log->value.update.old_hash);
+ oidread(&new_oid, log->value.update.new_hash);
+
+ /*
+ * When both the old object ID and the new object ID are null
+ * then this is the reflog existence marker. The caller must
+ * not be aware of it.
+ */
+ if (is_null_oid(&old_oid) && is_null_oid(&new_oid))
+ return 0;
+
+ full_committer = fmt_ident(log->value.update.name, log->value.update.email,
+ WANT_COMMITTER_IDENT, NULL, IDENT_NO_DATE);
+ return fn(&old_oid, &new_oid, full_committer,
+ log->value.update.time, log->value.update.tz_offset,
+ log->value.update.message, cb_data);
+}
+
+static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
+ const char *refname,
+ each_reflog_ent_fn fn,
+ void *cb_data)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent_reverse");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct reftable_merged_table *mt = NULL;
+ struct reftable_log_record log = {0};
+ struct reftable_iterator it = {0};
+ int ret;
+
+ if (refs->err < 0)
+ return refs->err;
+
+ mt = reftable_stack_merged_table(stack);
+ ret = reftable_merged_table_seek_log(mt, &it, refname);
+ while (!ret) {
+ ret = reftable_iterator_next_log(&it, &log);
+ if (ret < 0)
+ break;
+ if (ret > 0 || strcmp(log.refname, refname)) {
+ ret = 0;
+ break;
+ }
+
+ ret = yield_log_record(&log, fn, cb_data);
+ if (ret)
+ break;
+ }
+
+ reftable_log_record_release(&log);
+ reftable_iterator_destroy(&it);
+ return ret;
+}
+
+static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
+ const char *refname,
+ each_reflog_ent_fn fn,
+ void *cb_data)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct reftable_merged_table *mt = NULL;
+ struct reftable_log_record *logs = NULL;
+ struct reftable_iterator it = {0};
+ size_t logs_alloc = 0, logs_nr = 0, i;
+ int ret;
+
+ if (refs->err < 0)
+ return refs->err;
+
+ mt = reftable_stack_merged_table(stack);
+ ret = reftable_merged_table_seek_log(mt, &it, refname);
+ while (!ret) {
+ struct reftable_log_record log = {0};
+
+ ret = reftable_iterator_next_log(&it, &log);
+ if (ret < 0)
+ goto done;
+ if (ret > 0 || strcmp(log.refname, refname)) {
+ reftable_log_record_release(&log);
+ ret = 0;
+ break;
+ }
+
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ logs[logs_nr++] = log;
+ }
+
+ for (i = logs_nr; i--;) {
+ ret = yield_log_record(&logs[i], fn, cb_data);
+ if (ret)
+ goto done;
+ }
+
+done:
+ reftable_iterator_destroy(&it);
+ for (i = 0; i < logs_nr; i++)
+ reftable_log_record_release(&logs[i]);
+ free(logs);
+ return ret;
+}
+
+static int reftable_be_reflog_exists(struct ref_store *ref_store,
+ const char *refname)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_exists");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
+ struct reftable_log_record log = {0};
+ struct reftable_iterator it = {0};
+ int ret;
+
+ ret = refs->err;
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_stack_reload(stack);
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_merged_table_seek_log(mt, &it, refname);
+ if (ret < 0)
+ goto done;
+
+ /*
+ * Check whether we get at least one log record for the given ref name.
+ * If so, the reflog exists, otherwise it doesn't.
+ */
+ ret = reftable_iterator_next_log(&it, &log);
+ if (ret < 0)
+ goto done;
+ if (ret > 0) {
+ ret = 0;
+ goto done;
+ }
+
+ ret = strcmp(log.refname, refname) == 0;
+
+done:
+ reftable_iterator_destroy(&it);
+ reftable_log_record_release(&log);
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+struct write_reflog_existence_arg {
+ struct reftable_ref_store *refs;
+ const char *refname;
+ struct reftable_stack *stack;
+};
+
+static int write_reflog_existence_table(struct reftable_writer *writer,
+ void *cb_data)
+{
+ struct write_reflog_existence_arg *arg = cb_data;
+ uint64_t ts = reftable_stack_next_update_index(arg->stack);
+ struct reftable_log_record log = {0};
+ int ret;
+
+ ret = reftable_stack_read_log(arg->stack, arg->refname, &log);
+ if (ret <= 0)
+ goto done;
+
+ reftable_writer_set_limits(writer, ts, ts);
+
+ /*
+ * The existence entry has both old and new object ID set to the the
+ * null object ID. Our iterators are aware of this and will not present
+ * them to their callers.
+ */
+ log.refname = xstrdup(arg->refname);
+ log.update_index = ts;
+ log.value_type = REFTABLE_LOG_UPDATE;
+ ret = reftable_writer_add_log(writer, &log);
+
+done:
+ assert(ret != REFTABLE_API_ERROR);
+ reftable_log_record_release(&log);
+ return ret;
+}
+
+static int reftable_be_create_reflog(struct ref_store *ref_store,
+ const char *refname,
+ struct strbuf *errmsg)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_reflog");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct write_reflog_existence_arg arg = {
+ .refs = refs,
+ .stack = stack,
+ .refname = refname,
+ };
+ int ret;
+
+ ret = refs->err;
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ goto done;
+
+ ret = reftable_stack_add(stack, &write_reflog_existence_table, &arg);
+
+done:
+ return ret;
+}
+
+struct write_reflog_delete_arg {
+ struct reftable_stack *stack;
+ const char *refname;
+};
+
+static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_data)
+{
+ struct write_reflog_delete_arg *arg = cb_data;
+ struct reftable_merged_table *mt =
+ reftable_stack_merged_table(arg->stack);
+ struct reftable_log_record log = {0}, tombstone = {0};
+ struct reftable_iterator it = {0};
+ uint64_t ts = reftable_stack_next_update_index(arg->stack);
+ int ret;
+
+ reftable_writer_set_limits(writer, ts, ts);
+
+ /*
+ * In order to delete a table we need to delete all reflog entries one
+ * by one. This is inefficient, but the reftable format does not have a
+ * better marker right now.
+ */
+ ret = reftable_merged_table_seek_log(mt, &it, arg->refname);
+ while (ret == 0) {
+ ret = reftable_iterator_next_log(&it, &log);
+ if (ret < 0)
+ break;
+ if (ret > 0 || strcmp(log.refname, arg->refname)) {
+ ret = 0;
+ break;
+ }
+
+ tombstone.refname = (char *)arg->refname;
+ tombstone.value_type = REFTABLE_LOG_DELETION;
+ tombstone.update_index = log.update_index;
+
+ ret = reftable_writer_add_log(writer, &tombstone);
+ }
+
+ reftable_log_record_release(&log);
+ reftable_iterator_destroy(&it);
+ return ret;
+}
+
+static int reftable_be_delete_reflog(struct ref_store *ref_store,
+ const char *refname)
+{
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "delete_reflog");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct write_reflog_delete_arg arg = {
+ .stack = stack,
+ .refname = refname,
+ };
+ int ret;
+
+ ret = reftable_stack_reload(stack);
+ if (ret)
+ return ret;
+ ret = reftable_stack_add(stack, &write_reflog_delete_table, &arg);
+
+ assert(ret != REFTABLE_API_ERROR);
+ return ret;
+}
+
+struct reflog_expiry_arg {
+ struct reftable_stack *stack;
+ struct reftable_log_record *records;
+ struct object_id update_oid;
+ const char *refname;
+ size_t len;
+};
+
+static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_data)
+{
+ struct reflog_expiry_arg *arg = cb_data;
+ uint64_t ts = reftable_stack_next_update_index(arg->stack);
+ uint64_t live_records = 0;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < arg->len; i++)
+ if (arg->records[i].value_type == REFTABLE_LOG_UPDATE)
+ live_records++;
+
+ reftable_writer_set_limits(writer, ts, ts);
+
+ if (!is_null_oid(&arg->update_oid)) {
+ struct reftable_ref_record ref = {0};
+ struct object_id peeled;
+
+ ref.refname = (char *)arg->refname;
+ ref.update_index = ts;
+
+ if (!peel_object(&arg->update_oid, &peeled)) {
+ ref.value_type = REFTABLE_REF_VAL2;
+ memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
+ memcpy(ref.value.val2.value, arg->update_oid.hash, GIT_MAX_RAWSZ);
+ } else {
+ ref.value_type = REFTABLE_REF_VAL1;
+ memcpy(ref.value.val1, arg->update_oid.hash, GIT_MAX_RAWSZ);
+ }
+
+ ret = reftable_writer_add_ref(writer, &ref);
+ if (ret < 0)
+ return ret;
+ }
+
+ /*
+ * When there are no more entries left in the reflog we empty it
+ * completely, but write a placeholder reflog entry that indicates that
+ * the reflog still exists.
+ */
+ if (!live_records) {
+ struct reftable_log_record log = {
+ .refname = (char *)arg->refname,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .update_index = ts,
+ };
+
+ ret = reftable_writer_add_log(writer, &log);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < arg->len; i++) {
+ ret = reftable_writer_add_log(writer, &arg->records[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int reftable_be_reflog_expire(struct ref_store *ref_store,
+ const char *refname,
+ unsigned int flags,
+ reflog_expiry_prepare_fn prepare_fn,
+ reflog_expiry_should_prune_fn should_prune_fn,
+ reflog_expiry_cleanup_fn cleanup_fn,
+ void *policy_cb_data)
+{
+ /*
+ * For log expiry, we write tombstones for every single reflog entry
+ * that is to be expired. This means that the entries are still
+ * retrievable by delving into the stack, and expiring entries
+ * paradoxically takes extra memory. This memory is only reclaimed when
+ * compacting the reftable stack.
+ *
+ * It would be better if the refs backend supported an API that sets a
+ * criterion for all refs, passing the criterion to pack_refs().
+ *
+ * On the plus side, because we do the expiration per ref, we can easily
+ * insert the reflog existence dummies.
+ */
+ struct reftable_ref_store *refs =
+ reftable_be_downcast(ref_store, REF_STORE_WRITE, "reflog_expire");
+ struct reftable_stack *stack = stack_for(refs, refname, &refname);
+ struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
+ struct reftable_log_record *logs = NULL;
+ struct reftable_log_record *rewritten = NULL;
+ struct reftable_ref_record ref_record = {0};
+ struct reftable_iterator it = {0};
+ struct reftable_addition *add = NULL;
+ struct reflog_expiry_arg arg = {0};
+ struct object_id oid = {0};
+ uint8_t *last_hash = NULL;
+ size_t logs_nr = 0, logs_alloc = 0, i;
+ int ret;
+
+ if (refs->err < 0)
+ return refs->err;
+
+ ret = reftable_stack_reload(stack);
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_merged_table_seek_log(mt, &it, refname);
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_stack_new_addition(&add, stack);
+ if (ret < 0)
+ goto done;
+
+ ret = reftable_stack_read_ref(stack, refname, &ref_record);
+ if (ret < 0)
+ goto done;
+ if (reftable_ref_record_val1(&ref_record))
+ oidread(&oid, reftable_ref_record_val1(&ref_record));
+ prepare_fn(refname, &oid, policy_cb_data);
+
+ while (1) {
+ struct reftable_log_record log = {0};
+ struct object_id old_oid, new_oid;
+
+ ret = reftable_iterator_next_log(&it, &log);
+ if (ret < 0)
+ goto done;
+ if (ret > 0 || strcmp(log.refname, refname)) {
+ reftable_log_record_release(&log);
+ break;
+ }
+
+ oidread(&old_oid, log.value.update.old_hash);
+ oidread(&new_oid, log.value.update.new_hash);
+
+ /*
+ * Skip over the reflog existence marker. We will add it back
+ * in when there are no live reflog records.
+ */
+ if (is_null_oid(&old_oid) && is_null_oid(&new_oid)) {
+ reftable_log_record_release(&log);
+ continue;
+ }
+
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ logs[logs_nr++] = log;
+ }
+
+ /*
+ * We need to rewrite all reflog entries according to the pruning
+ * callback function:
+ *
+ * - If a reflog entry shall be pruned we mark the record for
+ * deletion.
+ *
+ * - Otherwise we may have to rewrite the chain of reflog entries so
+ * that gaps created by just-deleted records get backfilled.
+ */
+ CALLOC_ARRAY(rewritten, logs_nr);
+ for (i = logs_nr; i--;) {
+ struct reftable_log_record *dest = &rewritten[i];
+ struct object_id old_oid, new_oid;
+
+ *dest = logs[i];
+ oidread(&old_oid, logs[i].value.update.old_hash);
+ oidread(&new_oid, logs[i].value.update.new_hash);
+
+ if (should_prune_fn(&old_oid, &new_oid, logs[i].value.update.email,
+ (timestamp_t)logs[i].value.update.time,
+ logs[i].value.update.tz_offset,
+ logs[i].value.update.message,
+ policy_cb_data)) {
+ dest->value_type = REFTABLE_LOG_DELETION;
+ } else {
+ if ((flags & EXPIRE_REFLOGS_REWRITE) && last_hash)
+ dest->value.update.old_hash = last_hash;
+ last_hash = logs[i].value.update.new_hash;
+ }
+ }
+
+ if (flags & EXPIRE_REFLOGS_UPDATE_REF && last_hash &&
+ reftable_ref_record_val1(&ref_record))
+ oidread(&arg.update_oid, last_hash);
+
+ arg.records = rewritten;
+ arg.len = logs_nr;
+ arg.stack = stack,
+ arg.refname = refname,
+
+ ret = reftable_addition_add(add, &write_reflog_expiry_table, &arg);
+ if (ret < 0)
+ goto done;
+
+ /*
+ * Future improvement: we could skip writing records that were
+ * not changed.
+ */
+ if (!(flags & EXPIRE_REFLOGS_DRY_RUN))
+ ret = reftable_addition_commit(add);
+
+done:
+ if (add)
+ cleanup_fn(policy_cb_data);
+ assert(ret != REFTABLE_API_ERROR);
+
+ reftable_ref_record_release(&ref_record);
+ reftable_iterator_destroy(&it);
+ reftable_addition_destroy(add);
+ for (i = 0; i < logs_nr; i++)
+ reftable_log_record_release(&logs[i]);
+ free(logs);
+ free(rewritten);
+ return ret;
+}
+
+struct ref_storage_be refs_be_reftable = {
+ .name = "reftable",
+ .init = reftable_be_init,
+ .init_db = reftable_be_init_db,
+ .transaction_prepare = reftable_be_transaction_prepare,
+ .transaction_finish = reftable_be_transaction_finish,
+ .transaction_abort = reftable_be_transaction_abort,
+ .initial_transaction_commit = reftable_be_initial_transaction_commit,
+
+ .pack_refs = reftable_be_pack_refs,
+ .create_symref = reftable_be_create_symref,
+ .rename_ref = reftable_be_rename_ref,
+ .copy_ref = reftable_be_copy_ref,
+
+ .iterator_begin = reftable_be_iterator_begin,
+ .read_raw_ref = reftable_be_read_raw_ref,
+ .read_symbolic_ref = reftable_be_read_symbolic_ref,
+
+ .reflog_iterator_begin = reftable_be_reflog_iterator_begin,
+ .for_each_reflog_ent = reftable_be_for_each_reflog_ent,
+ .for_each_reflog_ent_reverse = reftable_be_for_each_reflog_ent_reverse,
+ .reflog_exists = reftable_be_reflog_exists,
+ .create_reflog = reftable_be_create_reflog,
+ .delete_reflog = reftable_be_delete_reflog,
+ .reflog_expire = reftable_be_reflog_expire,
+};
/* the restart key is verbatim in the block, so this could avoid the
alloc for decoding the key */
struct strbuf rkey = STRBUF_INIT;
- struct strbuf last_key = STRBUF_INIT;
uint8_t unused_extra;
- int n = reftable_decode_key(&rkey, &unused_extra, last_key, in);
+ int n = reftable_decode_key(&rkey, &unused_extra, in);
int result;
if (n < 0) {
a->error = 1;
if (it->next_off >= it->br->block_len)
return 1;
- n = reftable_decode_key(&it->key, &extra, it->last_key, in);
+ n = reftable_decode_key(&it->last_key, &extra, in);
if (n < 0)
return -1;
-
- if (!it->key.len)
+ if (!it->last_key.len)
return REFTABLE_FORMAT_ERROR;
string_view_consume(&in, n);
- n = reftable_record_decode(rec, it->key, extra, in, it->br->hash_size);
+ n = reftable_record_decode(rec, it->last_key, extra, in, it->br->hash_size);
if (n < 0)
return -1;
string_view_consume(&in, n);
- strbuf_reset(&it->last_key);
- strbuf_addbuf(&it->last_key, &it->key);
it->next_off += start.len - in.len;
return 0;
}
int block_reader_first_key(struct block_reader *br, struct strbuf *key)
{
- struct strbuf empty = STRBUF_INIT;
- int off = br->header_off + 4;
+ int off = br->header_off + 4, n;
struct string_view in = {
.buf = br->block.data + off,
.len = br->block_len - off,
};
-
uint8_t extra = 0;
- int n = reftable_decode_key(key, &extra, empty, in);
+
+ strbuf_reset(key);
+
+ n = reftable_decode_key(key, &extra, in);
if (n < 0)
return n;
if (!key->len)
void block_iter_close(struct block_iter *it)
{
strbuf_release(&it->last_key);
- strbuf_release(&it->key);
}
int block_reader_seek(struct block_reader *br, struct block_iter *it,
if (err < 0)
goto done;
- reftable_record_key(&rec, &it->key);
- if (err > 0 || strbuf_cmp(&it->key, want) >= 0) {
+ reftable_record_key(&rec, &it->last_key);
+ if (err > 0 || strbuf_cmp(&it->last_key, want) >= 0) {
err = 0;
goto done;
}
/* key for last entry we read. */
struct strbuf last_key;
- struct strbuf key;
};
#define BLOCK_ITER_INIT { \
.last_key = STRBUF_INIT, \
- .key = STRBUF_INIT, \
}
/* initializes a block reader. */
#include "reader.h"
#include "reftable-error.h"
-int iterator_is_null(struct reftable_iterator *it)
-{
- return !it->ops;
-}
-
static void filtering_ref_iterator_close(void *iter_arg)
{
struct filtering_ref_iterator *fri = iter_arg;
#include "reftable-iterator.h"
#include "reftable-generic.h"
-/* Returns true for a zeroed out iterator, such as the one returned from
- * iterator_destroy. */
-int iterator_is_null(struct reftable_iterator *it);
-
/* iterator that produces only ref records that point to `oid` */
struct filtering_ref_iterator {
int double_check;
#include "reftable-error.h"
#include "system.h"
+struct merged_subiter {
+ struct reftable_iterator iter;
+ struct reftable_record rec;
+};
+
+struct merged_iter {
+ struct merged_subiter *subiters;
+ struct merged_iter_pqueue pq;
+ uint32_t hash_id;
+ size_t stack_len;
+ uint8_t typ;
+ int suppress_deletions;
+ ssize_t advance_index;
+};
+
static int merged_iter_init(struct merged_iter *mi)
{
for (size_t i = 0; i < mi->stack_len; i++) {
struct pq_entry e = {
.index = i,
+ .rec = &mi->subiters[i].rec,
};
int err;
- reftable_record_init(&e.rec, mi->typ);
- err = iterator_next(&mi->stack[i], &e.rec);
+ reftable_record_init(&mi->subiters[i].rec, mi->typ);
+ err = iterator_next(&mi->subiters[i].iter,
+ &mi->subiters[i].rec);
if (err < 0)
return err;
- if (err > 0) {
- reftable_iterator_destroy(&mi->stack[i]);
- reftable_record_release(&e.rec);
+ if (err > 0)
continue;
- }
merged_iter_pqueue_add(&mi->pq, &e);
}
struct merged_iter *mi = p;
merged_iter_pqueue_release(&mi->pq);
- for (size_t i = 0; i < mi->stack_len; i++)
- reftable_iterator_destroy(&mi->stack[i]);
- reftable_free(mi->stack);
- strbuf_release(&mi->key);
- strbuf_release(&mi->entry_key);
+ for (size_t i = 0; i < mi->stack_len; i++) {
+ reftable_iterator_destroy(&mi->subiters[i].iter);
+ reftable_record_release(&mi->subiters[i].rec);
+ }
+ reftable_free(mi->subiters);
}
-static int merged_iter_advance_nonnull_subiter(struct merged_iter *mi,
- size_t idx)
+static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx)
{
struct pq_entry e = {
.index = idx,
+ .rec = &mi->subiters[idx].rec,
};
int err;
- reftable_record_init(&e.rec, mi->typ);
- err = iterator_next(&mi->stack[idx], &e.rec);
- if (err < 0)
+ err = iterator_next(&mi->subiters[idx].iter, &mi->subiters[idx].rec);
+ if (err)
return err;
- if (err > 0) {
- reftable_iterator_destroy(&mi->stack[idx]);
- reftable_record_release(&e.rec);
- return 0;
- }
-
merged_iter_pqueue_add(&mi->pq, &e);
return 0;
}
-static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx)
-{
- if (iterator_is_null(&mi->stack[idx]))
- return 0;
- return merged_iter_advance_nonnull_subiter(mi, idx);
-}
-
static int merged_iter_next_entry(struct merged_iter *mi,
struct reftable_record *rec)
{
struct pq_entry entry = { 0 };
- int err = 0;
+ int err = 0, empty;
+
+ empty = merged_iter_pqueue_is_empty(mi->pq);
+
+ if (mi->advance_index >= 0) {
+ /*
+ * When there are no pqueue entries then we only have a single
+ * subiter left. There is no need to use the pqueue in that
+ * case anymore as we know that the subiter will return entries
+ * in the correct order already.
+ *
+ * While this may sound like a very specific edge case, it may
+ * happen more frequently than you think. Most repositories
+ * will end up having a single large base table that contains
+ * most of the refs. It's thus likely that we exhaust all
+ * subiters but the one from that base ref.
+ */
+ if (empty)
+ return iterator_next(&mi->subiters[mi->advance_index].iter,
+ rec);
+
+ err = merged_iter_advance_subiter(mi, mi->advance_index);
+ if (err < 0)
+ return err;
+ if (!err)
+ empty = 0;
+ mi->advance_index = -1;
+ }
- if (merged_iter_pqueue_is_empty(mi->pq))
+ if (empty)
return 1;
entry = merged_iter_pqueue_remove(&mi->pq);
- err = merged_iter_advance_subiter(mi, entry.index);
- if (err < 0)
- return err;
/*
One can also use reftable as datacenter-local storage, where the ref
such a deployment, the loop below must be changed to collect all
entries for the same key, and return new the newest one.
*/
- reftable_record_key(&entry.rec, &mi->entry_key);
while (!merged_iter_pqueue_is_empty(mi->pq)) {
struct pq_entry top = merged_iter_pqueue_top(mi->pq);
- int cmp = 0;
-
- reftable_record_key(&top.rec, &mi->key);
+ int cmp;
- cmp = strbuf_cmp(&mi->key, &mi->entry_key);
+ cmp = reftable_record_cmp(top.rec, entry.rec);
if (cmp > 0)
break;
merged_iter_pqueue_remove(&mi->pq);
err = merged_iter_advance_subiter(mi, top.index);
if (err < 0)
- goto done;
- reftable_record_release(&top.rec);
+ return err;
}
- reftable_record_release(rec);
- *rec = entry.rec;
-
-done:
- if (err)
- reftable_record_release(&entry.rec);
- return err;
+ mi->advance_index = entry.index;
+ SWAP(*rec, *entry.rec);
+ return 0;
}
-static int merged_iter_next(struct merged_iter *mi, struct reftable_record *rec)
+static int merged_iter_next_void(void *p, struct reftable_record *rec)
{
+ struct merged_iter *mi = p;
while (1) {
int err = merged_iter_next_entry(mi, rec);
- if (err == 0 && mi->suppress_deletions &&
- reftable_record_is_deletion(rec)) {
+ if (err)
+ return err;
+ if (mi->suppress_deletions && reftable_record_is_deletion(rec))
continue;
- }
-
- return err;
+ return 0;
}
}
-static int merged_iter_next_void(void *p, struct reftable_record *rec)
-{
- struct merged_iter *mi = p;
- if (merged_iter_pqueue_is_empty(mi->pq))
- return 1;
-
- return merged_iter_next(mi, rec);
-}
-
static struct reftable_iterator_vtable merged_iter_vtable = {
.next = &merged_iter_next_void,
.close = &merged_iter_close,
.typ = reftable_record_type(rec),
.hash_id = mt->hash_id,
.suppress_deletions = mt->suppress_deletions,
- .key = STRBUF_INIT,
- .entry_key = STRBUF_INIT,
+ .advance_index = -1,
};
struct merged_iter *p;
int err;
- REFTABLE_CALLOC_ARRAY(merged.stack, mt->stack_len);
+ REFTABLE_CALLOC_ARRAY(merged.subiters, mt->stack_len);
for (size_t i = 0; i < mt->stack_len; i++) {
err = reftable_table_seek_record(&mt->stack[i],
- &merged.stack[merged.stack_len], rec);
+ &merged.subiters[merged.stack_len].iter, rec);
if (err < 0)
goto out;
if (!err)
#ifndef MERGED_H
#define MERGED_H
-#include "pq.h"
+#include "system.h"
struct reftable_merged_table {
struct reftable_table *stack;
uint64_t max;
};
-struct merged_iter {
- struct reftable_iterator *stack;
- uint32_t hash_id;
- size_t stack_len;
- uint8_t typ;
- int suppress_deletions;
- struct merged_iter_pqueue pq;
- struct strbuf key;
- struct strbuf entry_key;
-};
-
void merged_table_release(struct reftable_merged_table *mt);
#endif
int pq_less(struct pq_entry *a, struct pq_entry *b)
{
- struct strbuf ak = STRBUF_INIT;
- struct strbuf bk = STRBUF_INIT;
- int cmp = 0;
- reftable_record_key(&a->rec, &ak);
- reftable_record_key(&b->rec, &bk);
-
- cmp = strbuf_cmp(&ak, &bk);
-
- strbuf_release(&ak);
- strbuf_release(&bk);
-
+ int cmp = reftable_record_cmp(a->rec, b->rec);
if (cmp == 0)
return a->index > b->index;
-
return cmp < 0;
}
-struct pq_entry merged_iter_pqueue_top(struct merged_iter_pqueue pq)
-{
- return pq.heap[0];
-}
-
-int merged_iter_pqueue_is_empty(struct merged_iter_pqueue pq)
-{
- return pq.len == 0;
-}
-
struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
{
int i = 0;
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq)
{
- int i = 0;
- for (i = 0; i < pq->len; i++) {
- reftable_record_release(&pq->heap[i].rec);
- }
FREE_AND_NULL(pq->heap);
- pq->len = pq->cap = 0;
+ memset(pq, 0, sizeof(*pq));
}
#include "record.h"
struct pq_entry {
- int index;
- struct reftable_record rec;
+ size_t index;
+ struct reftable_record *rec;
};
struct merged_iter_pqueue {
size_t cap;
};
-struct pq_entry merged_iter_pqueue_top(struct merged_iter_pqueue pq);
-int merged_iter_pqueue_is_empty(struct merged_iter_pqueue pq);
void merged_iter_pqueue_check(struct merged_iter_pqueue pq);
struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq);
void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e);
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq);
int pq_less(struct pq_entry *a, struct pq_entry *b);
+static inline struct pq_entry merged_iter_pqueue_top(struct merged_iter_pqueue pq)
+{
+ return pq.heap[0];
+}
+
+static inline int merged_iter_pqueue_is_empty(struct merged_iter_pqueue pq)
+{
+ return pq.len == 0;
+}
+
#endif
static void test_pq(void)
{
- char *names[54] = { NULL };
- int N = ARRAY_SIZE(names) - 1;
-
struct merged_iter_pqueue pq = { NULL };
+ struct reftable_record recs[54];
+ int N = ARRAY_SIZE(recs) - 1, i;
char *last = NULL;
- int i = 0;
for (i = 0; i < N; i++) {
- char name[100];
- snprintf(name, sizeof(name), "%02d", i);
- names[i] = xstrdup(name);
+ struct strbuf refname = STRBUF_INIT;
+ strbuf_addf(&refname, "%02d", i);
+
+ reftable_record_init(&recs[i], BLOCK_TYPE_REF);
+ recs[i].u.ref.refname = strbuf_detach(&refname, NULL);
}
i = 1;
do {
- struct pq_entry e = { .rec = { .type = BLOCK_TYPE_REF,
- .u.ref = {
- .refname = names[i],
- } } };
+ struct pq_entry e = {
+ .rec = &recs[i],
+ };
+
merged_iter_pqueue_add(&pq, &e);
merged_iter_pqueue_check(pq);
+
i = (i * 7) % N;
} while (i != 1);
while (!merged_iter_pqueue_is_empty(pq)) {
struct pq_entry e = merged_iter_pqueue_remove(&pq);
- struct reftable_record *rec = &e.rec;
merged_iter_pqueue_check(pq);
- EXPECT(reftable_record_type(rec) == BLOCK_TYPE_REF);
- if (last) {
- EXPECT(strcmp(last, rec->u.ref.refname) < 0);
- }
- /* this is names[i], so don't dealloc. */
- last = rec->u.ref.refname;
- rec->u.ref.refname = NULL;
- reftable_record_release(rec);
- }
- for (i = 0; i < N; i++) {
- reftable_free(names[i]);
+ EXPECT(reftable_record_type(e.rec) == BLOCK_TYPE_REF);
+ if (last)
+ EXPECT(strcmp(last, e.rec->u.ref.refname) < 0);
+ last = e.rec->u.ref.refname;
}
+ for (i = 0; i < N; i++)
+ reftable_record_release(&recs[i]);
merged_iter_pqueue_release(&pq);
}
while (1) {
struct table_iter next = TABLE_ITER_INIT;
- int err = 0;
- if (ti->is_finished) {
+ int err;
+
+ if (ti->is_finished)
return 1;
- }
+ /*
+ * Check whether the current block still has more records. If
+ * so, return it. If the iterator returns positive then the
+ * current block has been exhausted.
+ */
err = table_iter_next_in_block(ti, rec);
- if (err <= 0) {
+ if (err <= 0)
return err;
- }
+ /*
+ * Otherwise, we need to continue to the next block in the
+ * table and retry. If there are no more blocks then the
+ * iterator is drained.
+ */
err = table_iter_next_block(&next, ti);
- if (err != 0) {
- ti->is_finished = 1;
- }
table_iter_block_done(ti);
- if (err != 0) {
+ if (err) {
+ ti->is_finished = 1;
return err;
}
+
table_iter_copy_from(ti, &next);
block_iter_close(&next.bi);
}
return start.len - dest.len;
}
-int reftable_decode_key(struct strbuf *key, uint8_t *extra,
- struct strbuf last_key, struct string_view in)
+int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,
+ struct string_view in)
{
int start_len = in.len;
uint64_t prefix_len = 0;
uint64_t suffix_len = 0;
- int n = get_var_int(&prefix_len, &in);
+ int n;
+
+ n = get_var_int(&prefix_len, &in);
if (n < 0)
return -1;
string_view_consume(&in, n);
- if (prefix_len > last_key.len)
- return -1;
-
n = get_var_int(&suffix_len, &in);
if (n <= 0)
return -1;
*extra = (uint8_t)(suffix_len & 0x7);
suffix_len >>= 3;
- if (in.len < suffix_len)
+ if (in.len < suffix_len ||
+ prefix_len > last_key->len)
return -1;
- strbuf_reset(key);
- strbuf_add(key, last_key.buf, prefix_len);
- strbuf_add(key, in.buf, suffix_len);
+ strbuf_setlen(last_key, prefix_len);
+ strbuf_add(last_key, in.buf, suffix_len);
string_view_consume(&in, suffix_len);
return start_len - in.len;
{
struct reftable_ref_record *ref = rec;
const struct reftable_ref_record *src = src_rec;
+ char *refname = NULL;
+ size_t refname_cap = 0;
+
assert(hash_size > 0);
- /* This is simple and correct, but we could probably reuse the hash
- * fields. */
+ SWAP(refname, ref->refname);
+ SWAP(refname_cap, ref->refname_cap);
reftable_ref_record_release(ref);
+ SWAP(ref->refname, refname);
+ SWAP(ref->refname_cap, refname_cap);
+
if (src->refname) {
- ref->refname = xstrdup(src->refname);
+ size_t refname_len = strlen(src->refname);
+
+ REFTABLE_ALLOC_GROW(ref->refname, refname_len + 1,
+ ref->refname_cap);
+ memcpy(ref->refname, src->refname, refname_len);
+ ref->refname[refname_len] = 0;
}
+
ref->update_index = src->update_index;
ref->value_type = src->value_type;
switch (src->value_type) {
struct reftable_ref_record *r = rec;
struct string_view start = in;
uint64_t update_index = 0;
- int n = get_var_int(&update_index, &in);
+ const char *refname = NULL;
+ size_t refname_cap = 0;
+ int n;
+
+ assert(hash_size > 0);
+
+ n = get_var_int(&update_index, &in);
if (n < 0)
return n;
string_view_consume(&in, n);
+ SWAP(refname, r->refname);
+ SWAP(refname_cap, r->refname_cap);
reftable_ref_record_release(r);
+ SWAP(r->refname, refname);
+ SWAP(r->refname_cap, refname_cap);
- assert(hash_size > 0);
-
- r->refname = reftable_realloc(r->refname, key.len + 1);
+ REFTABLE_ALLOC_GROW(r->refname, key.len + 1, r->refname_cap);
memcpy(r->refname, key.buf, key.len);
- r->update_index = update_index;
r->refname[key.len] = 0;
+
+ r->update_index = update_index;
r->value_type = val_type;
switch (val_type) {
case REFTABLE_REF_VAL1:
(const struct reftable_ref_record *)p);
}
-
static int reftable_ref_record_equal_void(const void *a,
const void *b, int hash_size)
{
return reftable_ref_record_equal(ra, rb, hash_size);
}
+static int reftable_ref_record_cmp_void(const void *_a, const void *_b)
+{
+ const struct reftable_ref_record *a = _a;
+ const struct reftable_ref_record *b = _b;
+ return strcmp(a->refname, b->refname);
+}
+
static void reftable_ref_record_print_void(const void *rec,
int hash_size)
{
.release = &reftable_ref_record_release_void,
.is_deletion = &reftable_ref_record_is_deletion_void,
.equal = &reftable_ref_record_equal_void,
+ .cmp = &reftable_ref_record_cmp_void,
.print = &reftable_ref_record_print_void,
};
return 1;
}
+static int reftable_obj_record_cmp_void(const void *_a, const void *_b)
+{
+ const struct reftable_obj_record *a = _a;
+ const struct reftable_obj_record *b = _b;
+ int cmp;
+
+ cmp = memcmp(a->hash_prefix, b->hash_prefix,
+ a->hash_prefix_len > b->hash_prefix_len ?
+ a->hash_prefix_len : b->hash_prefix_len);
+ if (cmp)
+ return cmp;
+
+ /*
+ * When the prefix is the same then the object record that is longer is
+ * considered to be bigger.
+ */
+ return a->hash_prefix_len - b->hash_prefix_len;
+}
+
static struct reftable_record_vtable reftable_obj_record_vtable = {
.key = &reftable_obj_record_key,
.type = BLOCK_TYPE_OBJ,
.release = &reftable_obj_record_release,
.is_deletion = ¬_a_deletion,
.equal = &reftable_obj_record_equal_void,
+ .cmp = &reftable_obj_record_cmp_void,
.print = &reftable_obj_record_print,
};
hash_size);
}
+static int reftable_log_record_cmp_void(const void *_a, const void *_b)
+{
+ const struct reftable_log_record *a = _a;
+ const struct reftable_log_record *b = _b;
+ int cmp = strcmp(a->refname, b->refname);
+ if (cmp)
+ return cmp;
+
+ /*
+ * Note that the comparison here is reversed. This is because the
+ * update index is reversed when comparing keys. For reference, see how
+ * we handle this in reftable_log_record_key()`.
+ */
+ return b->update_index - a->update_index;
+}
+
int reftable_log_record_equal(const struct reftable_log_record *a,
const struct reftable_log_record *b, int hash_size)
{
.release = &reftable_log_record_release_void,
.is_deletion = &reftable_log_record_is_deletion_void,
.equal = &reftable_log_record_equal_void,
+ .cmp = &reftable_log_record_cmp_void,
.print = &reftable_log_record_print_void,
};
return ia->offset == ib->offset && !strbuf_cmp(&ia->last_key, &ib->last_key);
}
+static int reftable_index_record_cmp(const void *_a, const void *_b)
+{
+ const struct reftable_index_record *a = _a;
+ const struct reftable_index_record *b = _b;
+ return strbuf_cmp(&a->last_key, &b->last_key);
+}
+
static void reftable_index_record_print(const void *rec, int hash_size)
{
const struct reftable_index_record *idx = rec;
.release = &reftable_index_record_release,
.is_deletion = ¬_a_deletion,
.equal = &reftable_index_record_equal,
+ .cmp = &reftable_index_record_cmp,
.print = &reftable_index_record_print,
};
reftable_record_vtable(rec)->key(reftable_record_data(rec), dest);
}
-uint8_t reftable_record_type(struct reftable_record *rec)
-{
- return rec->type;
-}
-
int reftable_record_encode(struct reftable_record *rec, struct string_view dest,
int hash_size)
{
reftable_record_data(rec));
}
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b)
+{
+ if (a->type != b->type)
+ BUG("cannot compare reftable records of different type");
+ return reftable_record_vtable(a)->cmp(
+ reftable_record_data(a), reftable_record_data(b));
+}
+
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size)
{
if (a->type != b->type)
return (log->value_type == REFTABLE_LOG_DELETION);
}
-void string_view_consume(struct string_view *s, int n)
-{
- s->buf += n;
- s->len -= n;
-}
-
static void *reftable_record_data(struct reftable_record *rec)
{
switch (rec->type) {
};
/* Advance `s.buf` by `n`, and decrease length. */
-void string_view_consume(struct string_view *s, int n);
+static inline void string_view_consume(struct string_view *s, int n)
+{
+ s->buf += n;
+ s->len -= n;
+}
/* utilities for de/encoding varints */
/* Are two records equal? This assumes they have the same type. Returns 0 for non-equal. */
int (*equal)(const void *a, const void *b, int hash_size);
+ /*
+ * Compare keys of two records with each other. The records must have
+ * the same type.
+ */
+ int (*cmp)(const void *a, const void *b);
+
/* Print on stdout, for debugging. */
void (*print)(const void *rec, int hash_size);
};
struct strbuf prev_key, struct strbuf key,
uint8_t extra);
-/* Decode into `key` and `extra` from `in` */
-int reftable_decode_key(struct strbuf *key, uint8_t *extra,
- struct strbuf last_key, struct string_view in);
+/*
+ * Decode into `last_key` and `extra` from `in`. `last_key` is expected to
+ * contain the decoded key of the preceding record, if any.
+ */
+int reftable_decode_key(struct strbuf *last_key, uint8_t *extra,
+ struct string_view in);
/* reftable_index_record are used internally to speed up lookups. */
struct reftable_index_record {
void reftable_record_init(struct reftable_record *rec, uint8_t typ);
/* see struct record_vtable */
+int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);
void reftable_record_print(struct reftable_record *rec, int hash_size);
void reftable_record_key(struct reftable_record *rec, struct strbuf *dest);
-uint8_t reftable_record_type(struct reftable_record *rec);
void reftable_record_copy_from(struct reftable_record *rec,
struct reftable_record *src, int hash_size);
uint8_t reftable_record_val_type(struct reftable_record *rec);
int hash_size);
int reftable_record_is_deletion(struct reftable_record *rec);
+static inline uint8_t reftable_record_type(struct reftable_record *rec)
+{
+ return rec->type;
+}
+
/* frees and zeroes out the embedded record */
void reftable_record_release(struct reftable_record *rec);
EXPECT(!restart);
EXPECT(n > 0);
- m = reftable_decode_key(&roundtrip, &rt_extra, last_key, dest);
+ strbuf_addstr(&roundtrip, "refs/heads/master");
+ m = reftable_decode_key(&roundtrip, &rt_extra, dest);
EXPECT(n == m);
EXPECT(0 == strbuf_cmp(&key, &roundtrip));
EXPECT(rt_extra == extra);
/* reftable_ref_record holds a ref database entry target_value */
struct reftable_ref_record {
char *refname; /* Name of the ref, malloced. */
+ size_t refname_cap;
uint64_t update_index; /* Logical timestamp at which this value is
* written */
b = container_of(entry_or_key, const struct remote, ent);
if (key)
- return strncmp(a->name, key->str, key->len) || a->name[key->len];
+ return !!xstrncmpz(a->name, key->str, key->len);
else
return strcmp(a->name, b->name);
}
b = container_of(entry_or_key, const struct branch, ent);
if (key)
- return strncmp(a->name, key->str, key->len) ||
- a->name[key->len];
+ return !!xstrncmpz(a->name, key->str, key->len);
else
return strcmp(a->name, b->name);
}
if (MERGE_BASES_BATCH_SIZE < size)
size = MERGE_BASES_BATCH_SIZE;
- if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk)))
+ if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk, 0)))
break;
}
FETCH_NEGOTIATION_NOOP,
};
-#define REF_STORAGE_FORMAT_UNKNOWN 0
-#define REF_STORAGE_FORMAT_FILES 1
+#define REF_STORAGE_FORMAT_UNKNOWN 0
+#define REF_STORAGE_FORMAT_FILES 1
+#define REF_STORAGE_FORMAT_REFTABLE 2
struct repo_settings {
int initialized;
mmfile[i].ptr = repo_read_object_file(the_repository,
&ce->oid, &type,
&size);
+ if (!mmfile[i].ptr)
+ die(_("unable to read %s"),
+ oid_to_hex(&ce->oid));
mmfile[i].size = size;
}
}
}
tree = parse_tree_indirect(oid);
+ if (!tree) {
+ ret = error(_("unable to read tree (%s)"), oid_to_hex(oid));
+ goto leave_reset_head;
+ }
+
prime_cache_tree(r, r->index, tree);
if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0) {
object = parse_object_with_flags(revs->repo, oid,
revs->verify_objects ? 0 :
- PARSE_OBJECT_SKIP_HASH_CHECK);
+ PARSE_OBJECT_SKIP_HASH_CHECK |
+ PARSE_OBJECT_DISCARD_TREE);
if (!object) {
if (revs->ignore_missing)
- return object;
+ return NULL;
if (revs->exclude_promisor_objects && is_promisor_object(oid))
return NULL;
+ if (revs->do_not_die_on_missing_objects) {
+ oidset_insert(&revs->missing_commits, oid);
+ return NULL;
+ }
die("bad object %s", name);
}
object->flags |= flags;
*/
while (object->type == OBJ_TAG) {
struct tag *tag = (struct tag *) object;
+ struct object_id *oid;
if (revs->tag_objects && !(flags & UNINTERESTING))
add_pending_object(revs, object, tag->tag);
- object = parse_object(revs->repo, get_tagged_oid(tag));
+ oid = get_tagged_oid(tag);
+ object = parse_object(revs->repo, oid);
if (!object) {
if (revs->ignore_missing_links || (flags & UNINTERESTING))
return NULL;
if (revs->exclude_promisor_objects &&
is_promisor_object(&tag->tagged->oid))
return NULL;
+ if (revs->do_not_die_on_missing_objects && oid) {
+ oidset_insert(&revs->missing_commits, oid);
+ return NULL;
+ }
die("bad object %s", oid_to_hex(&tag->tagged->oid));
}
object->flags |= flags;
return 0;
}
-static int handle_one_reflog(const char *refname_in_wt,
- const struct object_id *oid UNUSED,
- int flag UNUSED, void *cb_data)
+static int handle_one_reflog(const char *refname_in_wt, void *cb_data)
{
struct all_refs_cb *cb = cb_data;
struct strbuf refname = STRBUF_INIT;
init_display_notes(&revs->notes_opt);
list_objects_filter_init(&revs->filter);
init_ref_exclusions(&revs->ref_excludes);
+ oidset_init(&revs->missing_commits, 0);
}
static void add_pending_commit_list(struct rev_info *revs,
}
}
+static const char *lookup_other_head(struct object_id *oid)
+{
+ int i;
+ static const char *const other_head[] = {
+ "MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "REBASE_HEAD"
+ };
+
+ for (i = 0; i < ARRAY_SIZE(other_head); i++)
+ if (!read_ref_full(other_head[i],
+ RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ oid, NULL)) {
+ if (is_null_oid(oid))
+ die(_("%s exists but is a symbolic ref"), other_head[i]);
+ return other_head[i];
+ }
+
+ die(_("--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD or REBASE_HEAD"));
+}
+
static void prepare_show_merge(struct rev_info *revs)
{
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
struct commit *head, *other;
struct object_id oid;
+ const char *other_name;
const char **prune = NULL;
int i, prune_num = 1; /* counting terminating NULL */
struct index_state *istate = revs->repo->index;
if (repo_get_oid(the_repository, "HEAD", &oid))
die("--merge without HEAD?");
head = lookup_commit_or_die(&oid, "HEAD");
- if (repo_get_oid(the_repository, "MERGE_HEAD", &oid))
- die("--merge without MERGE_HEAD?");
- other = lookup_commit_or_die(&oid, "MERGE_HEAD");
+ other_name = lookup_other_head(&oid);
+ other = lookup_commit_or_die(&oid, other_name);
add_pending_object(revs, &head->object, "HEAD");
- add_pending_object(revs, &other->object, "MERGE_HEAD");
- bases = repo_get_merge_bases(the_repository, head, other);
+ add_pending_object(revs, &other->object, other_name);
+ if (repo_get_merge_bases(the_repository, head, other, &bases) < 0)
+ exit(128);
add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
free_commit_list(bases);
} else {
/* A...B -- find merge bases between the two */
struct commit *a, *b;
- struct commit_list *exclude;
+ struct commit_list *exclude = NULL;
a = lookup_commit_reference(revs->repo, &a_obj->oid);
b = lookup_commit_reference(revs->repo, &b_obj->oid);
if (!a || !b)
return dotdot_missing(arg, dotdot, revs, symmetric);
- exclude = repo_get_merge_bases(the_repository, a, b);
+ if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0) {
+ free_commit_list(exclude);
+ return -1;
+ }
add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE,
flags_exclude);
add_pending_commit_list(revs, exclude, flags_exclude);
if (revarg_opt & REVARG_COMMITTISH)
get_sha1_flags |= GET_OID_COMMITTISH;
+ /*
+ * Even if revs->do_not_die_on_missing_objects is set, we
+ * should error out if we can't even get an oid, as
+ * `--missing=print` should be able to report missing oids.
+ */
if (get_oid_with_context(revs->repo, arg, get_sha1_flags, &oid, &oc))
return revs->ignore_missing ? 0 : -1;
if (!cant_be_filename)
verify_non_filename(revs->prefix, arg);
object = get_reference(revs, arg, &oid, flags ^ local_flags);
if (!object)
- return revs->ignore_missing ? 0 : -1;
+ return (revs->ignore_missing || revs->do_not_die_on_missing_objects) ? 0 : -1;
add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags);
add_pending_object_with_path(revs, object, arg, oc.mode, oc.path);
free(oc.path);
FOR_EACH_OBJECT_PROMISOR_ONLY);
}
- oidset_init(&revs->missing_commits, 0);
-
if (!revs->reflog_info)
prepare_to_use_bloom_filter(revs);
if (!revs->unsorted_input)
o.show_rename_progress = 1;
head_tree = parse_tree_indirect(head);
+ if (!head_tree)
+ return error(_("unable to read tree (%s)"), oid_to_hex(head));
next_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r);
base_tree = base ? repo_get_commit_tree(r, base) : empty_tree(r);
fprintf(stderr, _("Executing: %s\n"), command_line);
cmd.use_shell = 1;
strvec_push(&cmd.args, command_line);
+ strvec_push(&cmd.env, "GIT_CHERRY_PICK_HELP");
status = run_command(&cmd);
/* force re-reading of the cache */
}
tree = parse_tree_indirect(&oid);
+ if (!tree)
+ return error(_("unable to read tree (%s)"), oid_to_hex(&oid));
prime_cache_tree(r, r->index, tree);
if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0)
int run_commit_flags = 0;
struct strbuf ref_name = STRBUF_INIT;
struct commit *head_commit, *merge_commit, *i;
- struct commit_list *bases, *j;
+ struct commit_list *bases = NULL, *j;
struct commit_list *to_merge = NULL, **tail = &to_merge;
const char *strategy = !opts->xopts.nr &&
(!opts->strategy ||
}
merge_commit = to_merge->item;
- bases = repo_get_merge_bases(r, head_commit, merge_commit);
+ if (repo_get_merge_bases(r, head_commit, merge_commit, &bases) < 0) {
+ ret = -1;
+ goto leave_merge;
+ }
+
if (bases && oideq(&merge_commit->object.oid,
&bases->item->object.oid)) {
ret = 0;
#include "trace2.h"
static int advertise_sid = -1;
+static int advertise_object_info = -1;
static int client_hash_algo = GIT_HASH_SHA1;
static int always_advertise(struct repository *r UNUSED,
trace2_data_string("transfer", NULL, "client-sid", client_sid);
}
+static int object_info_advertise(struct repository *r, struct strbuf *value UNUSED)
+{
+ if (advertise_object_info == -1 &&
+ repo_config_get_bool(r, "transfer.advertiseobjectinfo",
+ &advertise_object_info)) {
+ /* disabled by default */
+ advertise_object_info = 0;
+ }
+ return advertise_object_info;
+}
+
struct protocol_capability {
/*
* The name of the capability. The server uses this name when
},
{
.name = "object-info",
- .advertise = always_advertise,
+ .advertise = object_info_advertise,
.command = cap_object_info,
},
{
char repo_version_string[10];
int repo_version = GIT_REPO_VERSION;
+ /*
+ * Note that we initialize the repository version to 1 when the ref
+ * storage format is unknown. This is on purpose so that we can add the
+ * correct object format to the config during git-clone(1). The format
+ * version will get adjusted by git-clone(1) once it has learned about
+ * the remote repository's format.
+ */
if (hash_algo != GIT_HASH_SHA1 ||
ref_storage_format != REF_STORAGE_FORMAT_FILES)
repo_version = GIT_REPO_VERSION_READ;
"%d", repo_version);
git_config_set("core.repositoryformatversion", repo_version_string);
- if (hash_algo != GIT_HASH_SHA1)
+ if (hash_algo != GIT_HASH_SHA1 && hash_algo != GIT_HASH_UNKNOWN)
git_config_set("extensions.objectformat",
hash_algos[hash_algo].name);
else if (reinit)
if (!*bitmap)
continue;
for (j = 0; j < bitmap_nr; j++)
- if (bitmap[0][j] &&
- /* Step 7, reachability test at commit level */
- !repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits)) {
- update_refstatus(ref_status, info->ref->nr, *bitmap);
- dst++;
- break;
+ if (bitmap[0][j]) {
+ /* Step 7, reachability test at commit level */
+ int ret = repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1);
+ if (ret < 0)
+ exit(128);
+ if (!ret) {
+ update_refstatus(ref_status, info->ref->nr, *bitmap);
+ dst++;
+ break;
+ }
}
}
info->nr_ours = dst;
si->reachable[c] = repo_in_merge_bases_many(the_repository,
commit,
si->nr_commits,
- si->commits);
+ si->commits,
+ 1);
+ if (si->reachable[c] < 0)
+ exit(128);
si->need_reachability_test[c] = 0;
}
return si->reachable[c];
(!is_null_oid(two) && !*right))
message = "(commits not present)";
- *merge_bases = repo_get_merge_bases(sub, *left, *right);
+ *merge_bases = NULL;
+ if (repo_get_merge_bases(sub, *left, *right, merge_bases) < 0) {
+ message = "(corrupt repository)";
+ goto output_header;
+ }
+
if (*merge_bases) {
if ((*merge_bases)->item == *left)
fast_forward = 1;
task = get_fetch_task_from_changed(spf, err);
if (task) {
- struct strbuf submodule_prefix = STRBUF_INIT;
-
child_process_init(cp);
cp->dir = task->repo->gitdir;
prepare_submodule_repo_env_in_gitdir(&cp->env);
strvec_pushv(&cp->args, task->git_args.v);
strvec_pushv(&cp->args, spf->args.v);
strvec_push(&cp->args, task->default_argv);
- strvec_push(&cp->args, "--submodule-prefix");
+ strvec_pushf(&cp->args, "--submodule-prefix=%s%s/",
+ spf->prefix, task->sub->path);
- strbuf_addf(&submodule_prefix, "%s%s/",
- spf->prefix,
- task->sub->path);
- strvec_push(&cp->args, submodule_prefix.buf);
*task_cb = task;
- strbuf_release(&submodule_prefix);
string_list_insert(&spf->seen_submodule_names, task->sub->name);
return 1;
}
if (spf->oid_fetch_tasks_nr) {
struct fetch_task *task =
spf->oid_fetch_tasks[spf->oid_fetch_tasks_nr - 1];
- struct strbuf submodule_prefix = STRBUF_INIT;
spf->oid_fetch_tasks_nr--;
- strbuf_addf(&submodule_prefix, "%s%s/",
- spf->prefix, task->sub->path);
-
child_process_init(cp);
prepare_submodule_repo_env_in_gitdir(&cp->env);
cp->git_cmd = 1;
strvec_init(&cp->args);
strvec_pushv(&cp->args, spf->args.v);
strvec_push(&cp->args, "on-demand");
- strvec_push(&cp->args, "--submodule-prefix");
- strvec_push(&cp->args, submodule_prefix.buf);
+ strvec_pushf(&cp->args, "--submodule-prefix=%s%s/",
+ spf->prefix, task->sub->path);
/* NEEDSWORK: have get_default_remote from submodule--helper */
strvec_push(&cp->args, "origin");
append_oid_to_argv, &cp->args);
*task_cb = task;
- strbuf_release(&submodule_prefix);
return 1;
}
repo_in_merge_bases(the_repository, A, B));
else if (!strcmp(av[1], "in_merge_bases_many"))
printf("%s(A,X):%d\n", av[1],
- repo_in_merge_bases_many(the_repository, A, X_nr, X_array));
+ repo_in_merge_bases_many(the_repository, A, X_nr, X_array, 0));
else if (!strcmp(av[1], "is_descendant_of"))
printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X));
else if (!strcmp(av[1], "get_merge_bases_many")) {
- struct commit_list *list = repo_get_merge_bases_many(the_repository,
- A, X_nr,
- X_array);
+ struct commit_list *list = NULL;
+ if (repo_get_merge_bases_many(the_repository,
+ A, X_nr,
+ X_array,
+ &list) < 0)
+ exit(128);
printf("%s(A,X):\n", av[1]);
print_sorted_commit_ids(list);
} else if (!strcmp(av[1], "reduce_heads")) {
return ret;
}
+static int each_reflog(const char *refname, void *cb_data UNUSED)
+{
+ printf("%s\n", refname);
+ return 0;
+}
+
static int cmd_for_each_reflog(struct ref_store *refs,
const char **argv UNUSED)
{
- return refs_for_each_reflog(refs, each_ref, NULL);
+ return refs_for_each_reflog(refs, each_reflog, NULL);
}
-static int each_reflog(struct object_id *old_oid, struct object_id *new_oid,
- const char *committer, timestamp_t timestamp,
- int tz, const char *msg, void *cb_data UNUSED)
+static int each_reflog_ent(struct object_id *old_oid, struct object_id *new_oid,
+ const char *committer, timestamp_t timestamp,
+ int tz, const char *msg, void *cb_data UNUSED)
{
printf("%s %s %s %" PRItime " %+05d%s%s", oid_to_hex(old_oid),
oid_to_hex(new_oid), committer, timestamp, tz,
{
const char *refname = notnull(*argv++, "refname");
- return refs_for_each_reflog_ent(refs, refname, each_reflog, refs);
+ return refs_for_each_reflog_ent(refs, refname, each_reflog_ent, refs);
}
static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv)
{
const char *refname = notnull(*argv++, "refname");
- return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs);
+ return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog_ent, refs);
}
static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
reject $1 https example.com user-overwrite
reject $1 https example.com user-erase1
reject $1 https example.com user-erase2
+ reject $1 https victim.example.com user
reject $1 http path.tld user
reject $1 https timeout.tld user
reject $1 https sso.tld
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh
+# If we're not given a specific external helper to run against,
+# there isn't much to test. But we can still run through our
+# battery of tests with a fake helper and check that the
+# test themselves are self-consistent and clean up after
+# themselves.
+#
+# We'll use the "store" helper, since we can easily inspect
+# its state by looking at the on-disk file. But since it doesn't
+# implement any caching or expiry logic, we'll cheat and override
+# the "check" function to just report all results as OK.
if test -z "$GIT_TEST_CREDENTIAL_HELPER"; then
- skip_all="used to test external credential helpers"
- test_done
+ GIT_TEST_CREDENTIAL_HELPER=store
+ GIT_TEST_CREDENTIAL_HELPER_TIMEOUT=store
+ check () {
+ test "$1" = "approve" || return 0
+ git -c credential.helper=store credential approve
+ }
+ check_cleanup=t
fi
test -z "$GIT_TEST_CREDENTIAL_HELPER_SETUP" ||
# might be long-term system storage
helper_test_clean "$GIT_TEST_CREDENTIAL_HELPER"
+if test "$check_cleanup" = "t"
+then
+ test_expect_success 'test cleanup removes everything' '
+ test_must_be_empty "$HOME/.git-credentials"
+ '
+fi
+
test_done
test_cmp_config -C client 1 core.repositoryformatversion
'
-test_expect_success SHA1,REFFILES 'convert to partial clone with noop extension' '
+test_expect_success DEFAULT_REPO_FORMAT 'convert to partial clone with noop extension' '
rm -fr server client &&
test_create_repo server &&
test_commit -C server my_commit 1 &&
git -C client fetch --unshallow --filter="blob:none"
'
-test_expect_success SHA1,REFFILES 'converting to partial clone fails with unrecognized extension' '
+test_expect_success DEFAULT_REPO_FORMAT 'converting to partial clone fails with unrecognized extension' '
rm -fr server client &&
test_create_repo server &&
test_commit -C server my_commit 1 &&
git -C partial.git rev-list --objects --missing=print HEAD >out &&
grep "[?]$FILE_HASH" out &&
+ # The no-lazy-fetch mechanism prevents Git from fetching
+ test_must_fail env GIT_NO_LAZY_FETCH=1 \
+ git -C partial.git cat-file -e "$FILE_HASH" &&
+
+ # The same with command line option to "git"
+ test_must_fail git --no-lazy-fetch -C partial.git cat-file -e "$FILE_HASH" &&
+
+ # The same, forcing a subprocess via an alias
+ test_must_fail git --no-lazy-fetch -C partial.git \
+ -c alias.foo="!git cat-file" foo -e "$FILE_HASH" &&
+
+ # Sanity check that the file is still missing
+ git -C partial.git rev-list --objects --missing=print HEAD >out &&
+ grep "[?]$FILE_HASH" out &&
+
git -C full cat-file -s "$FILE_HASH" >expect &&
test-tool partial-clone object-info partial.git "$FILE_HASH" >actual &&
test_cmp expect actual &&
# direct FS access for creating the reflogs. 3) PSEUDO-WT and refs/bisect/random
# do not create reflogs by default, so it is not testing a realistic scenario.
test_expect_success 'for_each_reflog()' '
- echo $ZERO_OID > .git/logs/PSEUDO-MAIN &&
+ echo $ZERO_OID >.git/logs/PSEUDO_MAIN_HEAD &&
mkdir -p .git/logs/refs/bisect &&
- echo $ZERO_OID > .git/logs/refs/bisect/random &&
+ echo $ZERO_OID >.git/logs/refs/bisect/random &&
- echo $ZERO_OID > .git/worktrees/wt/logs/PSEUDO-WT &&
+ echo $ZERO_OID >.git/worktrees/wt/logs/PSEUDO_WT_HEAD &&
mkdir -p .git/worktrees/wt/logs/refs/bisect &&
- echo $ZERO_OID > .git/worktrees/wt/logs/refs/bisect/wt-random &&
+ echo $ZERO_OID >.git/worktrees/wt/logs/refs/bisect/wt-random &&
- $RWT for-each-reflog | cut -d" " -f 2- | sort >actual &&
+ $RWT for-each-reflog >actual &&
cat >expected <<-\EOF &&
- HEAD 0x1
- PSEUDO-WT 0x0
- refs/bisect/wt-random 0x0
- refs/heads/main 0x0
- refs/heads/wt-main 0x0
+ HEAD
+ PSEUDO_WT_HEAD
+ refs/bisect/wt-random
+ refs/heads/main
+ refs/heads/wt-main
EOF
test_cmp expected actual &&
- $RMAIN for-each-reflog | cut -d" " -f 2- | sort >actual &&
+ $RMAIN for-each-reflog >actual &&
cat >expected <<-\EOF &&
- HEAD 0x1
- PSEUDO-MAIN 0x0
- refs/bisect/random 0x0
- refs/heads/main 0x0
- refs/heads/wt-main 0x0
+ HEAD
+ PSEUDO_MAIN_HEAD
+ refs/bisect/random
+ refs/heads/main
+ refs/heads/wt-main
EOF
test_cmp expected actual
'
test_grep broken stderr
'
+test_expect_success 'empty directory removal' '
+ git branch d1/d2/r1 HEAD &&
+ git branch d1/r2 HEAD &&
+ test_path_is_file .git/refs/heads/d1/d2/r1 &&
+ test_path_is_file .git/logs/refs/heads/d1/d2/r1 &&
+ git branch -d d1/d2/r1 &&
+ test_must_fail git show-ref --verify -q refs/heads/d1/d2 &&
+ test_must_fail git show-ref --verify -q logs/refs/heads/d1/d2 &&
+ test_path_is_file .git/refs/heads/d1/r2 &&
+ test_path_is_file .git/logs/refs/heads/d1/r2
+'
+
+test_expect_success 'symref empty directory removal' '
+ git branch e1/e2/r1 HEAD &&
+ git branch e1/r2 HEAD &&
+ git checkout e1/e2/r1 &&
+ test_when_finished "git checkout main" &&
+ test_path_is_file .git/refs/heads/e1/e2/r1 &&
+ test_path_is_file .git/logs/refs/heads/e1/e2/r1 &&
+ git update-ref -d HEAD &&
+ test_must_fail git show-ref --verify -q refs/heads/e1/e2 &&
+ test_must_fail git show-ref --verify -q logs/refs/heads/e1/e2 &&
+ test_path_is_file .git/refs/heads/e1/r2 &&
+ test_path_is_file .git/logs/refs/heads/e1/r2 &&
+ test_path_is_file .git/logs/HEAD
+'
+
+test_expect_success 'directory not created deleting packed ref' '
+ git branch d1/d2/r1 HEAD &&
+ git pack-refs --all &&
+ test_path_is_missing .git/refs/heads/d1/d2 &&
+ git update-ref -d refs/heads/d1/d2/r1 &&
+ test_path_is_missing .git/refs/heads/d1/d2 &&
+ test_path_is_missing .git/refs/heads/d1
+'
+
+test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for u is a symlink' '
+ git branch --create-reflog u &&
+ mv .git/logs/refs/heads/u real-u &&
+ ln -s real-u .git/logs/refs/heads/u &&
+ test_must_fail git branch -m u v
+'
+
+test_expect_success SYMLINKS 'git branch -m with symlinked .git/refs' '
+ test_when_finished "rm -rf subdir" &&
+ git init --bare subdir &&
+
+ rm -rfv subdir/refs subdir/objects subdir/packed-refs &&
+ ln -s ../.git/refs subdir/refs &&
+ ln -s ../.git/objects subdir/objects &&
+ ln -s ../.git/packed-refs subdir/packed-refs &&
+
+ git -C subdir rev-parse --absolute-git-dir >subdir.dir &&
+ git rev-parse --absolute-git-dir >our.dir &&
+ ! test_cmp subdir.dir our.dir &&
+
+ git -C subdir log &&
+ git -C subdir branch rename-src &&
+ git rev-parse rename-src >expect &&
+ git -C subdir branch -m rename-src rename-dest &&
+ git rev-parse rename-dest >actual &&
+ test_cmp expect actual &&
+ git branch -D rename-dest
+'
+
+test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' '
+ git checkout main &&
+ mv .git/logs actual_logs &&
+ cmd //c "mklink /D .git\logs ..\actual_logs" &&
+ git rebase -f HEAD^ &&
+ test -L .git/logs &&
+ rm .git/logs &&
+ mv actual_logs .git/logs
+'
+
+test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
+ umask 077 &&
+ git config core.sharedRepository group &&
+ git reflog expire --all &&
+ actual="$(ls -l .git/logs/refs/heads/main)" &&
+ case "$actual" in
+ -rw-rw-*)
+ : happy
+ ;;
+ *)
+ echo Ooops, .git/logs/refs/heads/main is not 066x [$actual]
+ false
+ ;;
+ esac
+'
+
test_done
--- /dev/null
+#!/bin/sh
+#
+# Copyright (c) 2020 Google LLC
+#
+
+test_description='reftable basics'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+if ! test_have_prereq REFTABLE
+then
+ skip_all='skipping reftable tests; set GIT_TEST_DEFAULT_REF_FORMAT=reftable'
+ test_done
+fi
+
+INVALID_OID=$(test_oid 001)
+
+test_expect_success 'init: creates basic reftable structures' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_path_is_dir repo/.git/reftable &&
+ test_path_is_file repo/.git/reftable/tables.list &&
+ echo reftable >expect &&
+ git -C repo rev-parse --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'init: sha256 object format via environment variable' '
+ test_when_finished "rm -rf repo" &&
+ GIT_DEFAULT_HASH=sha256 git init repo &&
+ cat >expect <<-EOF &&
+ sha256
+ reftable
+ EOF
+ git -C repo rev-parse --show-object-format --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'init: sha256 object format via option' '
+ test_when_finished "rm -rf repo" &&
+ git init --object-format=sha256 repo &&
+ cat >expect <<-EOF &&
+ sha256
+ reftable
+ EOF
+ git -C repo rev-parse --show-object-format --show-ref-format >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'init: reinitializing reftable backend succeeds' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo A &&
+
+ git -C repo for-each-ref >expect &&
+ git init --ref-format=reftable repo &&
+ git -C repo for-each-ref >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'init: reinitializing files with reftable backend fails' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=files repo &&
+ test_commit -C repo file &&
+
+ cp repo/.git/HEAD expect &&
+ test_must_fail git init --ref-format=reftable repo &&
+ test_cmp expect repo/.git/HEAD
+'
+
+test_expect_success 'init: reinitializing reftable with files backend fails' '
+ test_when_finished "rm -rf repo" &&
+ git init --ref-format=reftable repo &&
+ test_commit -C repo file &&
+
+ cp repo/.git/HEAD expect &&
+ test_must_fail git init --ref-format=files repo &&
+ test_cmp expect repo/.git/HEAD
+'
+
+test_expect_perms () {
+ local perms="$1"
+ local file="$2"
+ local actual=$(ls -l "$file") &&
+
+ case "$actual" in
+ $perms*)
+ : happy
+ ;;
+ *)
+ echo "$(basename $2) is not $perms but $actual"
+ false
+ ;;
+ esac
+}
+
+for umask in 002 022
+do
+ test_expect_success POSIXPERM 'init: honors core.sharedRepository' '
+ test_when_finished "rm -rf repo" &&
+ (
+ umask $umask &&
+ git init --shared=true repo &&
+ test 1 = "$(git -C repo config core.sharedrepository)"
+ ) &&
+ test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
+ for table in repo/.git/reftable/*.ref
+ do
+ test_expect_perms "-rw-rw-r--" "$table" ||
+ return 1
+ done
+ '
+done
+
+test_expect_success 'clone: can clone reftable repository' '
+ test_when_finished "rm -rf repo clone" &&
+ git init repo &&
+ test_commit -C repo message1 file1 &&
+
+ git clone repo cloned &&
+ echo reftable >expect &&
+ git -C cloned rev-parse --show-ref-format >actual &&
+ test_cmp expect actual &&
+ test_path_is_file cloned/file1
+'
+
+test_expect_success 'clone: can clone reffiles into reftable repository' '
+ test_when_finished "rm -rf reffiles reftable" &&
+ git init --ref-format=files reffiles &&
+ test_commit -C reffiles A &&
+ git clone --ref-format=reftable ./reffiles reftable &&
+
+ git -C reffiles rev-parse HEAD >expect &&
+ git -C reftable rev-parse HEAD >actual &&
+ test_cmp expect actual &&
+
+ git -C reftable rev-parse --show-ref-format >actual &&
+ echo reftable >expect &&
+ test_cmp expect actual &&
+
+ git -C reffiles rev-parse --show-ref-format >actual &&
+ echo files >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'clone: can clone reftable into reffiles repository' '
+ test_when_finished "rm -rf reffiles reftable" &&
+ git init --ref-format=reftable reftable &&
+ test_commit -C reftable A &&
+ git clone --ref-format=files ./reftable reffiles &&
+
+ git -C reftable rev-parse HEAD >expect &&
+ git -C reffiles rev-parse HEAD >actual &&
+ test_cmp expect actual &&
+
+ git -C reftable rev-parse --show-ref-format >actual &&
+ echo reftable >expect &&
+ test_cmp expect actual &&
+
+ git -C reffiles rev-parse --show-ref-format >actual &&
+ echo files >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'ref transaction: corrupted tables cause failure' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit file1 &&
+ for f in .git/reftable/*.ref
+ do
+ : >"$f" || return 1
+ done &&
+ test_must_fail git update-ref refs/heads/main HEAD
+ )
+'
+
+test_expect_success 'ref transaction: corrupted tables.list cause failure' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit file1 &&
+ echo garbage >.git/reftable/tables.list &&
+ test_must_fail git update-ref refs/heads/main HEAD
+ )
+'
+
+test_expect_success 'ref transaction: refuses to write ref causing F/D conflict' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo file &&
+ test_must_fail git -C repo update-ref refs/heads/main/forbidden
+'
+
+test_expect_success 'ref transaction: deleting ref with invalid name fails' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo file &&
+ test_must_fail git -C repo update-ref -d ../../my-private-file
+'
+
+test_expect_success 'ref transaction: can skip object ID verification' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_must_fail test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID 0 &&
+ test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION
+'
+
+test_expect_success 'ref transaction: updating same ref multiple times fails' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo A &&
+ cat >updates <<-EOF &&
+ update refs/heads/main $A
+ update refs/heads/main $A
+ EOF
+ cat >expect <<-EOF &&
+ fatal: multiple updates for ref ${SQ}refs/heads/main${SQ} not allowed
+ EOF
+ test_must_fail git -C repo update-ref --stdin <updates 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'ref transaction: can delete symbolic self-reference with git-symbolic-ref(1)' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ git -C repo symbolic-ref refs/heads/self refs/heads/self &&
+ git -C repo symbolic-ref -d refs/heads/self
+'
+
+test_expect_success 'ref transaction: deleting symbolic self-reference without --no-deref fails' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ git -C repo symbolic-ref refs/heads/self refs/heads/self &&
+ cat >expect <<-EOF &&
+ error: multiple updates for ${SQ}refs/heads/self${SQ} (including one via symref ${SQ}refs/heads/self${SQ}) are not allowed
+ EOF
+ test_must_fail git -C repo update-ref -d refs/heads/self 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'ref transaction: deleting symbolic self-reference with --no-deref succeeds' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ git -C repo symbolic-ref refs/heads/self refs/heads/self &&
+ git -C repo update-ref -d --no-deref refs/heads/self
+'
+
+test_expect_success 'ref transaction: creating symbolic ref fails with F/D conflict' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo A &&
+ cat >expect <<-EOF &&
+ error: unable to write symref for refs/heads: file/directory conflict
+ EOF
+ test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'ref transaction: ref deletion' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit file &&
+ HEAD_OID=$(git show-ref -s --verify HEAD) &&
+ cat >expect <<-EOF &&
+ $HEAD_OID refs/heads/main
+ $HEAD_OID refs/tags/file
+ EOF
+ git show-ref >actual &&
+ test_cmp expect actual &&
+
+ test_must_fail git update-ref -d refs/tags/file $INVALID_OID &&
+ git show-ref >actual &&
+ test_cmp expect actual &&
+
+ git update-ref -d refs/tags/file $HEAD_OID &&
+ echo "$HEAD_OID refs/heads/main" >expect &&
+ git show-ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'ref transaction: writes cause auto-compaction' '
+ test_when_finished "rm -rf repo" &&
+
+ git init repo &&
+ test_line_count = 1 repo/.git/reftable/tables.list &&
+
+ test_commit -C repo --no-tag A &&
+ test_line_count = 2 repo/.git/reftable/tables.list &&
+
+ test_commit -C repo --no-tag B &&
+ test_line_count = 1 repo/.git/reftable/tables.list
+'
+
+check_fsync_events () {
+ local trace="$1" &&
+ shift &&
+
+ cat >expect &&
+ sed -n \
+ -e '/^{"event":"counter",.*"category":"fsync",/ {
+ s/.*"category":"fsync",//;
+ s/}$//;
+ p;
+ }' \
+ <"$trace" >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'ref transaction: writes are synced' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo initial &&
+
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ GIT_TEST_FSYNC=true \
+ git -C repo -c core.fsync=reference \
+ -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD &&
+ check_fsync_events trace2.txt <<-EOF
+ "name":"hardware-flush","count":2
+ EOF
+'
+
+test_expect_success 'ref transaction: empty transaction in empty repo' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo --no-tag A &&
+ git -C repo update-ref -d refs/heads/main &&
+ test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD &&
+ git -C repo update-ref --stdin <<-EOF
+ prepare
+ commit
+ EOF
+'
+
+test_expect_success 'pack-refs: compacts tables' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+
+ test_commit -C repo A &&
+ ls -1 repo/.git/reftable >table-files &&
+ test_line_count = 4 table-files &&
+ test_line_count = 3 repo/.git/reftable/tables.list &&
+
+ git -C repo pack-refs &&
+ ls -1 repo/.git/reftable >table-files &&
+ test_line_count = 2 table-files &&
+ test_line_count = 1 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'pack-refs: prunes stale tables' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ touch repo/.git/reftable/stale-table.ref &&
+ git -C repo pack-refs &&
+ test_path_is_missing repo/.git/reftable/stable-ref.ref
+'
+
+test_expect_success 'pack-refs: does not prune non-table files' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ touch repo/.git/reftable/garbage &&
+ git -C repo pack-refs &&
+ test_path_is_file repo/.git/reftable/garbage
+'
+
+for umask in 002 022
+do
+ test_expect_success POSIXPERM 'pack-refs: honors core.sharedRepository' '
+ test_when_finished "rm -rf repo" &&
+ (
+ umask $umask &&
+ git init --shared=true repo &&
+ test_commit -C repo A &&
+ test_line_count = 3 repo/.git/reftable/tables.list
+ ) &&
+ git -C repo pack-refs &&
+ test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
+ for table in repo/.git/reftable/*.ref
+ do
+ test_expect_perms "-rw-rw-r--" "$table" ||
+ return 1
+ done
+ '
+done
+
+test_expect_success 'packed-refs: writes are synced' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo initial &&
+ test_line_count = 2 table-files &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ GIT_TEST_FSYNC=true \
+ git -C repo -c core.fsync=reference \
+ -c core.fsyncMethod=fsync pack-refs &&
+ check_fsync_events trace2.txt <<-EOF
+ "name":"hardware-flush","count":2
+ EOF
+'
+
+test_expect_success 'ref iterator: bogus names are flagged' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit --no-tag file &&
+ test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
+
+ cat >expect <<-EOF &&
+ $ZERO_OID refs/heads/bogus..name 0xc
+ $(git rev-parse HEAD) refs/heads/main 0x0
+ EOF
+ test-tool ref-store main for-each-ref "" >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'ref iterator: missing object IDs are not flagged' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION &&
+
+ cat >expect <<-EOF &&
+ $INVALID_OID refs/heads/broken-hash 0x0
+ EOF
+ test-tool ref-store main for-each-ref "" >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'basic: commit and list refs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo file &&
+ test_write_lines refs/heads/main refs/tags/file >expect &&
+ git -C repo for-each-ref --format="%(refname)" >actual &&
+ test_cmp actual expect
+'
+
+test_expect_success 'basic: can write large commit message' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ perl -e "
+ print \"this is a long commit message\" x 50000
+ " >commit-msg &&
+ git -C repo commit --allow-empty --file=../commit-msg
+'
+
+test_expect_success 'basic: show-ref fails with empty repository' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_must_fail git -C repo show-ref >actual &&
+ test_must_be_empty actual
+'
+
+test_expect_success 'basic: can check out unborn branch' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ git -C repo checkout -b main
+'
+
+test_expect_success 'basic: peeled tags are stored' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ test_commit -C repo file &&
+ git -C repo tag -m "annotated tag" test_tag HEAD &&
+ for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{}
+ do
+ echo "$(git -C repo rev-parse "$ref") $ref" || return 1
+ done >expect &&
+ git -C repo show-ref -d >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'basic: for-each-ref can print symrefs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit file &&
+ git branch &&
+ git symbolic-ref refs/heads/sym refs/heads/main &&
+ cat >expected <<-EOF &&
+ refs/heads/main
+ EOF
+ git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
+ test_cmp expected actual
+ )
+'
+
+test_expect_success 'basic: notes' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ write_script fake_editor <<-\EOF &&
+ echo "$MSG" >"$1"
+ echo "$MSG" >&2
+ EOF
+
+ test_commit 1st &&
+ test_commit 2nd &&
+ GIT_EDITOR=./fake_editor MSG=b4 git notes add &&
+ GIT_EDITOR=./fake_editor MSG=b3 git notes edit &&
+ echo b4 >expect &&
+ git notes --ref commits@{1} show >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'basic: stash' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit file &&
+ git stash list >expect &&
+ test_line_count = 0 expect &&
+
+ echo hoi >>file.t &&
+ git stash push -m stashed &&
+ git stash list >expect &&
+ test_line_count = 1 expect &&
+
+ git stash clear &&
+ git stash list >expect &&
+ test_line_count = 0 expect
+ )
+'
+
+test_expect_success 'basic: cherry-pick' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit message1 file1 &&
+ test_commit message2 file2 &&
+ git branch source &&
+ git checkout HEAD^ &&
+ test_commit message3 file3 &&
+ git cherry-pick source &&
+ test_path_is_file file2
+ )
+'
+
+test_expect_success 'basic: rebase' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit message1 file1 &&
+ test_commit message2 file2 &&
+ git branch source &&
+ git checkout HEAD^ &&
+ test_commit message3 file3 &&
+ git rebase source &&
+ test_path_is_file file2
+ )
+'
+
+test_expect_success 'reflog: can delete separate reflog entries' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit file &&
+ test_commit file2 &&
+ test_commit file3 &&
+ test_commit file4 &&
+ git reflog >actual &&
+ grep file3 actual &&
+
+ git reflog delete HEAD@{1} &&
+ git reflog >actual &&
+ ! grep file3 actual
+ )
+'
+
+test_expect_success 'reflog: can switch to previous branch' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit file1 &&
+ git checkout -b branch1 &&
+ test_commit file2 &&
+ git checkout -b branch2 &&
+ git switch - &&
+ git rev-parse --symbolic-full-name HEAD >actual &&
+ echo refs/heads/branch1 >expect &&
+ test_cmp actual expect
+ )
+'
+
+test_expect_success 'reflog: copying branch writes reflog entry' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit file1 &&
+ test_commit file2 &&
+ oid=$(git rev-parse --short HEAD) &&
+ git branch src &&
+ cat >expect <<-EOF &&
+ ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst
+ ${oid} dst@{1}: branch: Created from main
+ EOF
+ git branch -c src dst &&
+ git reflog dst >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'reflog: renaming branch writes reflog entry' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git symbolic-ref HEAD refs/heads/before &&
+ test_commit file &&
+ git show-ref >expected.refs &&
+ sed s/before/after/g <expected.refs >expected &&
+ git branch -M after &&
+ git show-ref >actual &&
+ test_cmp expected actual &&
+ echo refs/heads/after >expected &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expected actual
+ )
+'
+
+test_expect_success 'reflog: can store empty logs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_must_fail test-tool ref-store main reflog-exists refs/heads/branch &&
+ test-tool ref-store main create-reflog refs/heads/branch &&
+ test-tool ref-store main reflog-exists refs/heads/branch &&
+ test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual &&
+ test_must_be_empty actual
+ )
+'
+
+test_expect_success 'reflog: expiry empties reflog' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit initial &&
+ git checkout -b branch &&
+ test_commit fileA &&
+ test_commit fileB &&
+
+ cat >expect <<-EOF &&
+ commit: fileB
+ commit: fileA
+ branch: Created from HEAD
+ EOF
+ git reflog show --format="%gs" refs/heads/branch >actual &&
+ test_cmp expect actual &&
+
+ git reflog expire branch --expire=all &&
+ git reflog show --format="%gs" refs/heads/branch >actual &&
+ test_must_be_empty actual &&
+ test-tool ref-store main reflog-exists refs/heads/branch
+ )
+'
+
+test_expect_success 'reflog: can be deleted' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ test-tool ref-store main reflog-exists refs/heads/main &&
+ test-tool ref-store main delete-reflog refs/heads/main &&
+ test_must_fail test-tool ref-store main reflog-exists refs/heads/main
+ )
+'
+
+test_expect_success 'reflog: garbage collection deletes reflog entries' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ for count in $(test_seq 1 10)
+ do
+ test_commit "number $count" file.t $count number-$count ||
+ return 1
+ done &&
+ git reflog refs/heads/main >actual &&
+ test_line_count = 10 actual &&
+ grep "commit (initial): number 1" actual &&
+ grep "commit: number 10" actual &&
+
+ git gc &&
+ git reflog refs/heads/main >actual &&
+ test_line_count = 0 actual
+ )
+'
+
+test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit main-one &&
+ git checkout -b new-branch &&
+ test_commit new-one &&
+ test_commit new-two &&
+
+ echo new-one >expect &&
+ git log -1 --format=%s HEAD@{1} >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'worktree: adding worktree creates separate stack' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo A &&
+
+ git -C repo worktree add ../worktree &&
+ test_path_is_file repo/.git/worktrees/worktree/refs/heads &&
+ echo "ref: refs/heads/.invalid" >expect &&
+ test_cmp expect repo/.git/worktrees/worktree/HEAD &&
+ test_path_is_dir repo/.git/worktrees/worktree/reftable &&
+ test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list
+'
+
+test_expect_success 'worktree: pack-refs in main repo packs main refs' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo A &&
+ git -C repo worktree add ../worktree &&
+
+ test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 4 repo/.git/reftable/tables.list &&
+ git -C repo pack-refs &&
+ test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'worktree: pack-refs in worktree packs worktree refs' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo A &&
+ git -C repo worktree add ../worktree &&
+
+ test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 4 repo/.git/reftable/tables.list &&
+ git -C worktree pack-refs &&
+ test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 4 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'worktree: creating shared ref updates main stack' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo A &&
+
+ git -C repo worktree add ../worktree &&
+ git -C repo pack-refs &&
+ git -C worktree pack-refs &&
+ test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list &&
+
+ git -C worktree update-ref refs/heads/shared HEAD &&
+ test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 2 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'worktree: creating per-worktree ref updates worktree stack' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo A &&
+
+ git -C repo worktree add ../worktree &&
+ git -C repo pack-refs &&
+ git -C worktree pack-refs &&
+ test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list &&
+
+ git -C worktree update-ref refs/bisect/per-worktree HEAD &&
+ test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'worktree: creating per-worktree ref from main repo' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo A &&
+
+ git -C repo worktree add ../worktree &&
+ git -C repo pack-refs &&
+ git -C worktree pack-refs &&
+ test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list &&
+
+ git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD &&
+ test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'worktree: creating per-worktree ref from second worktree' '
+ test_when_finished "rm -rf repo wt1 wt2" &&
+ git init repo &&
+ test_commit -C repo A &&
+
+ git -C repo worktree add ../wt1 &&
+ git -C repo worktree add ../wt2 &&
+ git -C repo pack-refs &&
+ git -C wt1 pack-refs &&
+ git -C wt2 pack-refs &&
+ test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
+ test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list &&
+
+ git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD &&
+ test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
+ test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'worktree: can create shared and per-worktree ref in one transaction' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo A &&
+
+ git -C repo worktree add ../worktree &&
+ git -C repo pack-refs &&
+ git -C worktree pack-refs &&
+ test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 1 repo/.git/reftable/tables.list &&
+
+ cat >stdin <<-EOF &&
+ create worktrees/worktree/refs/bisect/per-worktree HEAD
+ create refs/branches/shared HEAD
+ EOF
+ git -C repo update-ref --stdin <stdin &&
+ test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
+ test_line_count = 2 repo/.git/reftable/tables.list
+'
+
+test_expect_success 'worktree: can access common refs' '
+ test_when_finished "rm -rf repo worktree" &&
+ git init repo &&
+ test_commit -C repo file1 &&
+ git -C repo branch branch1 &&
+ git -C repo worktree add ../worktree &&
+
+ echo refs/heads/worktree >expect &&
+ git -C worktree symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
+ git -C worktree checkout branch1
+'
+
+test_expect_success 'worktree: adds worktree with detached HEAD' '
+ test_when_finished "rm -rf repo worktree" &&
+
+ git init repo &&
+ test_commit -C repo A &&
+ git -C repo rev-parse main >expect &&
+
+ git -C repo worktree add --detach ../worktree main &&
+ git -C worktree rev-parse HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch: accessing FETCH_HEAD special ref works' '
+ test_when_finished "rm -rf repo sub" &&
+
+ git init sub &&
+ test_commit -C sub two &&
+ git -C sub rev-parse HEAD >expect &&
+
+ git init repo &&
+ test_commit -C repo one &&
+ git -C repo fetch ../sub &&
+ git -C repo rev-parse FETCH_HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_done
--- /dev/null
+#!/bin/sh
+
+test_description='reftable HTTPD tests'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-httpd.sh
+
+start_httpd
+
+REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo"
+
+test_expect_success 'serving ls-remote' '
+ git init --ref-format=reftable -b main "$REPO" &&
+ cd "$REPO" &&
+ test_commit m1 &&
+ >.git/git-daemon-export-ok &&
+ git ls-remote "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" | cut -f 2-2 -d " " >actual &&
+ cat >expect <<-EOF &&
+ HEAD
+ refs/heads/main
+ refs/tags/m1
+ EOF
+ test_cmp actual expect
+'
+
+test_done
test_cmp expect actual
'
-test_expect_success REFFILES,POSIXPERM 'git reflog expire honors core.sharedRepository' '
- umask 077 &&
- git config core.sharedRepository group &&
- git reflog expire --all &&
- actual="$(ls -l .git/logs/refs/heads/main)" &&
- case "$actual" in
- -rw-rw-*)
- : happy
- ;;
- *)
- echo Ooops, .git/logs/refs/heads/main is not 066x [$actual]
- false
- ;;
- esac
-'
-
test_expect_success POSIXPERM 'forced modes' '
test_when_finished "rm -rf new" &&
mkdir -p templates/hooks &&
test $A = $(git show-ref -s --verify $m)
'
-test_expect_success REFFILES 'empty directory removal' '
- git branch d1/d2/r1 HEAD &&
- git branch d1/r2 HEAD &&
- test_path_is_file .git/refs/heads/d1/d2/r1 &&
- test_path_is_file .git/logs/refs/heads/d1/d2/r1 &&
- git branch -d d1/d2/r1 &&
- test_must_fail git show-ref --verify -q refs/heads/d1/d2 &&
- test_must_fail git show-ref --verify -q logs/refs/heads/d1/d2 &&
- test_path_is_file .git/refs/heads/d1/r2 &&
- test_path_is_file .git/logs/refs/heads/d1/r2
-'
-
-test_expect_success REFFILES 'symref empty directory removal' '
- git branch e1/e2/r1 HEAD &&
- git branch e1/r2 HEAD &&
- git checkout e1/e2/r1 &&
- test_when_finished "git checkout main" &&
- test_path_is_file .git/refs/heads/e1/e2/r1 &&
- test_path_is_file .git/logs/refs/heads/e1/e2/r1 &&
- git update-ref -d HEAD &&
- test_must_fail git show-ref --verify -q refs/heads/e1/e2 &&
- test_must_fail git show-ref --verify -q logs/refs/heads/e1/e2 &&
- test_path_is_file .git/refs/heads/e1/r2 &&
- test_path_is_file .git/logs/refs/heads/e1/r2 &&
- test_path_is_file .git/logs/HEAD
-'
-
cat >expect <<EOF
$Z $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 Initial Creation
$A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150260 +0000 Switch
rm -f expect
git update-ref -d $m
-test_expect_success REFFILES 'query reflog with gap' '
+test_expect_success 'query reflog with gap' '
test_when_finished "git update-ref -d $m" &&
- git update-ref $m $F &&
- cat >.git/logs/$m <<-EOF &&
- $Z $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
- $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
- $D $F $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
- EOF
+ GIT_COMMITTER_DATE="1117150320 -0500" git update-ref $m $A &&
+ GIT_COMMITTER_DATE="1117150380 -0500" git update-ref $m $B &&
+ GIT_COMMITTER_DATE="1117150480 -0500" git update-ref $m $C &&
+ GIT_COMMITTER_DATE="1117150580 -0500" git update-ref $m $D &&
+ GIT_COMMITTER_DATE="1117150680 -0500" git update-ref $m $F &&
+ git reflog delete $m@{2} &&
git rev-parse --verify "main@{2005-05-26 23:33:01}" >actual 2>stderr &&
echo "$B" >expect &&
test_cmp expected actual
'
-test_expect_success REFFILES 'directory not created deleting packed ref' '
- git branch d1/d2/r1 HEAD &&
- git pack-refs --all &&
- test_path_is_missing .git/refs/heads/d1/d2 &&
- git update-ref -d refs/heads/d1/d2/r1 &&
- test_path_is_missing .git/refs/heads/d1/d2 &&
- test_path_is_missing .git/refs/heads/d1
-'
-
test_done
else
delname="$delref"
fi &&
- cat >expected-err <<-EOF &&
- fatal: cannot lock ref $SQ$addname$SQ: $SQ$delref$SQ exists; cannot create $SQ$addref$SQ
- EOF
$pack &&
if $add_del
then
printf "%s\n" "delete $delname" "create $addname $D"
fi >commands &&
test_must_fail git update-ref --stdin <commands 2>output.err &&
- test_cmp expected-err output.err &&
+ grep "fatal:\( cannot lock ref $SQ$addname$SQ:\)\? $SQ$delref$SQ exists; cannot create $SQ$addref$SQ" output.err &&
printf "%s\n" "$C $delref" >expected-refs &&
git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs &&
test_cmp expected-refs actual-refs
'
-test_expect_success REFFILES 'D/F conflict prevents add long + delete short' '
+test_expect_success 'D/F conflict prevents add long + delete short' '
df_test refs/df-al-ds --add-del foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents add short + delete long' '
+test_expect_success 'D/F conflict prevents add short + delete long' '
df_test refs/df-as-dl --add-del foo foo/bar
'
-test_expect_success REFFILES 'D/F conflict prevents delete long + add short' '
+test_expect_success 'D/F conflict prevents delete long + add short' '
df_test refs/df-dl-as --del-add foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents delete short + add long' '
+test_expect_success 'D/F conflict prevents delete short + add long' '
df_test refs/df-ds-al --del-add foo foo/bar
'
-test_expect_success REFFILES 'D/F conflict prevents add long + delete short packed' '
+test_expect_success 'D/F conflict prevents add long + delete short packed' '
df_test refs/df-al-dsp --pack --add-del foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents add short + delete long packed' '
+test_expect_success 'D/F conflict prevents add short + delete long packed' '
df_test refs/df-as-dlp --pack --add-del foo foo/bar
'
-test_expect_success REFFILES 'D/F conflict prevents delete long packed + add short' '
+test_expect_success 'D/F conflict prevents delete long packed + add short' '
df_test refs/df-dlp-as --pack --del-add foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents delete short packed + add long' '
+test_expect_success 'D/F conflict prevents delete short packed + add long' '
df_test refs/df-dsp-al --pack --del-add foo foo/bar
'
# Try some combinations involving symbolic refs...
-test_expect_success REFFILES 'D/F conflict prevents indirect add long + delete short' '
+test_expect_success 'D/F conflict prevents indirect add long + delete short' '
df_test refs/df-ial-ds --sym-add --add-del foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents indirect add long + indirect delete short' '
+test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' '
df_test refs/df-ial-ids --sym-add --sym-del --add-del foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents indirect add short + indirect delete long' '
+test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' '
df_test refs/df-ias-idl --sym-add --sym-del --add-del foo foo/bar
'
-test_expect_success REFFILES 'D/F conflict prevents indirect delete long + indirect add short' '
+test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' '
df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents indirect add long + delete short packed' '
+test_expect_success 'D/F conflict prevents indirect add long + delete short packed' '
df_test refs/df-ial-dsp --sym-add --pack --add-del foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents indirect add long + indirect delete short packed' '
+test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' '
df_test refs/df-ial-idsp --sym-add --sym-del --pack --add-del foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents add long + indirect delete short packed' '
+test_expect_success 'D/F conflict prevents add long + indirect delete short packed' '
df_test refs/df-al-idsp --sym-del --pack --add-del foo/bar foo
'
-test_expect_success REFFILES 'D/F conflict prevents indirect delete long packed + indirect add short' '
+test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' '
df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo
'
test_must_fail git rev-parse refs/tags/new-tag --
'
-# In reftable, we keep the reflogs around for deleted refs.
-test_expect_success !REFFILES 'delete-reflog(FOO, refs/tags/new-tag)' '
- $RUN delete-reflog FOO &&
- $RUN delete-reflog refs/tags/new-tag
-'
-
test_expect_success 'rename_refs(main, new-main)' '
git rev-parse main >expected &&
$RUN rename-ref refs/heads/main refs/heads/new-main &&
'
test_expect_success 'for_each_reflog()' '
- $RUN for-each-reflog | sort -k2 | cut -d" " -f 2- >actual &&
+ $RUN for-each-reflog >actual &&
cat >expected <<-\EOF &&
- HEAD 0x1
- refs/heads/main 0x0
- refs/heads/new-main 0x0
+ HEAD
+ refs/heads/main
+ refs/heads/new-main
EOF
test_cmp expected actual
'
'
test_expect_success 'for_each_reflog()' '
- $RUN for-each-reflog | sort | cut -d" " -f 2- >actual &&
+ $RUN for-each-reflog >actual &&
cat >expected <<-\EOF &&
- HEAD 0x1
- refs/heads/main 0x0
- refs/heads/new-main 0x0
+ HEAD
+ refs/heads/main
+ refs/heads/new-main
EOF
test_cmp expected actual
'
test_must_be_empty err
'
+test_expect_success 'list reflogs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ git reflog list >actual &&
+ test_must_be_empty actual &&
+
+ test_commit A &&
+ cat >expect <<-EOF &&
+ HEAD
+ refs/heads/main
+ EOF
+ git reflog list >actual &&
+ test_cmp expect actual &&
+
+ git branch b &&
+ cat >expect <<-EOF &&
+ HEAD
+ refs/heads/b
+ refs/heads/main
+ EOF
+ git reflog list >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'list reflogs with worktree' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit A &&
+ git worktree add wt &&
+ git -c core.logAllRefUpdates=always \
+ update-ref refs/worktree/main HEAD &&
+ git -c core.logAllRefUpdates=always \
+ update-ref refs/worktree/per-worktree HEAD &&
+ git -c core.logAllRefUpdates=always -C wt \
+ update-ref refs/worktree/per-worktree HEAD &&
+ git -c core.logAllRefUpdates=always -C wt \
+ update-ref refs/worktree/worktree HEAD &&
+
+ cat >expect <<-EOF &&
+ HEAD
+ refs/heads/main
+ refs/heads/wt
+ refs/worktree/main
+ refs/worktree/per-worktree
+ EOF
+ git reflog list >actual &&
+ test_cmp expect actual &&
+
+ cat >expect <<-EOF &&
+ HEAD
+ refs/heads/main
+ refs/heads/wt
+ refs/worktree/per-worktree
+ refs/worktree/worktree
+ EOF
+ git -C wt reflog list >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'reflog list returns error with additional args' '
+ cat >expect <<-EOF &&
+ error: list does not accept arguments: ${SQ}bogus${SQ}
+ EOF
+ test_must_fail git reflog list bogus 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'reflog for symref with unborn target can be listed' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ git symbolic-ref HEAD refs/heads/unborn &&
+ cat >expect <<-EOF &&
+ HEAD
+ refs/heads/main
+ EOF
+ git reflog list >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'reflog with invalid object ID can be listed' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ test-tool ref-store main update-ref msg refs/heads/missing \
+ $(test_oid deadbeef) "$ZERO_OID" REF_SKIP_OID_VERIFICATION &&
+ cat >expect <<-EOF &&
+ HEAD
+ refs/heads/main
+ refs/heads/missing
+ EOF
+ git reflog list >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
test_must_fail git checkout -b other
'
-test_expect_success REFFILES 'create ref directory/file conflict scenario' '
+test_expect_success 'create ref directory/file conflict scenario' '
git update-ref refs/heads/outer/inner main &&
-
- # do not rely on symbolic-ref to get a known state,
- # as it may use the same code we are testing
reset_to_df () {
- echo "ref: refs/heads/outer" >.git/HEAD
+ git symbolic-ref HEAD refs/heads/outer
}
'
-test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to branch)' '
+test_expect_success 'checkout away from d/f HEAD (unpacked, to branch)' '
reset_to_df &&
git checkout main
'
-test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to detached)' '
+test_expect_success 'checkout away from d/f HEAD (unpacked, to detached)' '
reset_to_df &&
git checkout --detach main
'
-test_expect_success REFFILES 'pack refs' '
+test_expect_success 'pack refs' '
git pack-refs --all --prune
'
-test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to branch)' '
+test_expect_success 'checkout away from d/f HEAD (packed, to branch)' '
reset_to_df &&
git checkout main
'
-test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to detached)' '
+test_expect_success 'checkout away from d/f HEAD (packed, to detached)' '
reset_to_df &&
git checkout --detach main
'
verify_state dir/foo index index
'
-test_expect_success 'git checkout -p HEAD with NO staged changes: abort' '
- set_and_save_state dir/foo work head &&
- test_write_lines n y n | git checkout -p HEAD &&
- verify_saved_state bar &&
- verify_saved_state dir/foo
-'
-
-test_expect_success 'git checkout -p HEAD with NO staged changes: apply' '
- test_write_lines n y y | git checkout -p HEAD &&
- verify_saved_state bar &&
- verify_state dir/foo head head
-'
-
-test_expect_success 'git checkout -p HEAD with change already staged' '
- set_state dir/foo index index &&
- # the third n is to get out in case it mistakenly does not apply
- test_write_lines n y n | git checkout -p HEAD &&
- verify_saved_state bar &&
- verify_state dir/foo head head
-'
+for opt in "HEAD" "@"
+do
+ test_expect_success "git checkout -p $opt with NO staged changes: abort" '
+ set_and_save_state dir/foo work head &&
+ test_write_lines n y n | git checkout -p $opt >output &&
+ verify_saved_state bar &&
+ verify_saved_state dir/foo &&
+ test_grep "Discard" output
+ '
+
+ test_expect_success "git checkout -p $opt with NO staged changes: apply" '
+ test_write_lines n y y | git checkout -p $opt >output &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head &&
+ test_grep "Discard" output
+ '
+
+ test_expect_success "git checkout -p $opt with change already staged" '
+ set_state dir/foo index index &&
+ # the third n is to get out in case it mistakenly does not apply
+ test_write_lines n y n | git checkout -p $opt >output &&
+ verify_saved_state bar &&
+ verify_state dir/foo head head &&
+ test_grep "Discard" output
+ '
+done
test_expect_success 'git checkout -p HEAD^...' '
# the third n is to get out in case it mistakenly does not apply
check_not_detached
'
+for opt in "HEAD" "@"
+do
+ test_expect_success "checkout $opt no-op/don't detach" '
+ reset &&
+ cat .git/HEAD >expect &&
+ git checkout $opt &&
+ cat .git/HEAD >actual &&
+ check_not_detached &&
+ test_cmp expect actual
+ '
+done
+
test_expect_success 'checkout tag detaches' '
reset &&
git checkout tag &&
test_grep ! "^hint: " stderr
'
-test_expect_success PERL 'checkout -p with multiple remotes does not print advice' '
+test_expect_success 'checkout -p with multiple remotes does not print advice' '
git checkout -B main &&
test_might_fail git branch -D foo &&
. ./lib-patch-mode.sh
-test_expect_success PERL 'setup' '
+test_expect_success 'setup' '
mkdir dir &&
echo parent >dir/foo &&
echo dummy >bar &&
save_head
'
-test_expect_success PERL 'restore -p without pathspec is fine' '
+test_expect_success 'restore -p without pathspec is fine' '
echo q >cmd &&
git restore -p <cmd
'
# note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar'
-test_expect_success PERL 'saying "n" does nothing' '
+test_expect_success 'saying "n" does nothing' '
set_and_save_state dir/foo work head &&
test_write_lines n n | git restore -p &&
verify_saved_state bar &&
verify_saved_state dir/foo
'
-test_expect_success PERL 'git restore -p' '
+test_expect_success 'git restore -p' '
set_and_save_state dir/foo work head &&
test_write_lines n y | git restore -p &&
verify_saved_state bar &&
verify_state dir/foo head head
'
-test_expect_success PERL 'git restore -p with staged changes' '
+test_expect_success 'git restore -p with staged changes' '
set_state dir/foo work index &&
test_write_lines n y | git restore -p &&
verify_saved_state bar &&
verify_state dir/foo index index
'
-test_expect_success PERL 'git restore -p --source=HEAD' '
- set_state dir/foo work index &&
- # the third n is to get out in case it mistakenly does not apply
- test_write_lines n y n | git restore -p --source=HEAD &&
- verify_saved_state bar &&
- verify_state dir/foo head index
-'
-
-test_expect_success PERL 'git restore -p --source=HEAD^' '
+for opt in "HEAD" "@"
+do
+ test_expect_success "git restore -p --source=$opt" '
+ set_state dir/foo work index &&
+ # the third n is to get out in case it mistakenly does not apply
+ test_write_lines n y n | git restore -p --source=$opt >output &&
+ verify_saved_state bar &&
+ verify_state dir/foo head index &&
+ test_grep "Discard" output
+ '
+done
+
+test_expect_success 'git restore -p --source=HEAD^' '
set_state dir/foo work index &&
# the third n is to get out in case it mistakenly does not apply
test_write_lines n y n | git restore -p --source=HEAD^ &&
verify_state dir/foo parent index
'
-test_expect_success PERL 'git restore -p --source=HEAD^...' '
+test_expect_success 'git restore -p --source=HEAD^...' '
set_state dir/foo work index &&
# the third n is to get out in case it mistakenly does not apply
test_write_lines n y n | git restore -p --source=HEAD^... &&
verify_state dir/foo parent index
'
-test_expect_success PERL 'git restore -p handles deletion' '
+test_expect_success 'git restore -p handles deletion' '
set_state dir/foo work index &&
rm dir/foo &&
test_write_lines n y | git restore -p &&
# dir/foo. There's always an extra 'n' to reject edits to dir/foo in
# the failure case (and thus get out of the loop).
-test_expect_success PERL 'path limiting works: dir' '
+test_expect_success 'path limiting works: dir' '
set_state dir/foo work head &&
test_write_lines y n | git restore -p dir &&
verify_saved_state bar &&
verify_state dir/foo head head
'
-test_expect_success PERL 'path limiting works: -- dir' '
+test_expect_success 'path limiting works: -- dir' '
set_state dir/foo work head &&
test_write_lines y n | git restore -p -- dir &&
verify_saved_state bar &&
verify_state dir/foo head head
'
-test_expect_success PERL 'path limiting works: HEAD^ -- dir' '
+test_expect_success 'path limiting works: HEAD^ -- dir' '
set_state dir/foo work head &&
# the third n is to get out in case it mistakenly does not apply
test_write_lines y n n | git restore -p --source=HEAD^ -- dir &&
verify_state dir/foo parent head
'
-test_expect_success PERL 'path limiting works: foo inside dir' '
+test_expect_success 'path limiting works: foo inside dir' '
set_state dir/foo work head &&
# the third n is to get out in case it mistakenly does not apply
test_write_lines y n n | (cd dir && git restore -p foo) &&
verify_state dir/foo head head
'
-test_expect_success PERL 'none of this moved HEAD' '
+test_expect_success 'none of this moved HEAD' '
verify_saved_head
'
test_ref_missing refs/heads/new-topic
'
-test_expect_success SYMLINKS,REFFILES 'git branch -m u v should fail when the reflog for u is a symlink' '
- git branch --create-reflog u &&
- mv .git/logs/refs/heads/u real-u &&
- ln -s real-u .git/logs/refs/heads/u &&
- test_must_fail git branch -m u v
-'
-
-test_expect_success SYMLINKS,REFFILES 'git branch -m with symlinked .git/refs' '
- test_when_finished "rm -rf subdir" &&
- git init --bare subdir &&
-
- rm -rfv subdir/refs subdir/objects subdir/packed-refs &&
- ln -s ../.git/refs subdir/refs &&
- ln -s ../.git/objects subdir/objects &&
- ln -s ../.git/packed-refs subdir/packed-refs &&
-
- git -C subdir rev-parse --absolute-git-dir >subdir.dir &&
- git rev-parse --absolute-git-dir >our.dir &&
- ! test_cmp subdir.dir our.dir &&
-
- git -C subdir log &&
- git -C subdir branch rename-src &&
- git rev-parse rename-src >expect &&
- git -C subdir branch -m rename-src rename-dest &&
- git rev-parse rename-dest >actual &&
- test_cmp expect actual &&
- git branch -D rename-dest
-'
-
test_expect_success 'test tracking setup via --track' '
git config remote.local.url . &&
git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
. ./test-lib.sh
-# arbitrary reference time: 2009-08-30 19:20:00
-GIT_TEST_DATE_NOW=1251660000; export GIT_TEST_DATE_NOW
-
test_expect_success 'error descriptions on empty repository' '
current=$(git branch --show-current) &&
cat >expect <<-EOF &&
test_cmp expect actual
'
-test_expect_success 'show branch --reflog=2' '
- sed "s/^> //" >expect <<-\EOF &&
- > ! [refs/heads/branch10@{0}] (4 years, 5 months ago) commit: branch10
- > ! [refs/heads/branch10@{1}] (4 years, 5 months ago) commit: branch10
- > --
- > + [refs/heads/branch10@{0}] branch10
- > ++ [refs/heads/branch10@{1}] initial
- EOF
- git show-branch --reflog=2 >actual &&
- test_cmp actual expect
-'
-
# incompatible options
while read combo
do
test_branch_op_in_wt -c new-branch
'
+test_expect_success 'setup reflogs' '
+ test_commit base &&
+ git checkout -b branch &&
+ test_commit one &&
+ git reset --hard HEAD^ &&
+ test_commit two &&
+ test_commit three
+'
+
+test_expect_success '--reflog shows reflog entries' '
+ cat >expect <<-\EOF &&
+ ! [branch@{0}] (0 seconds ago) commit: three
+ ! [branch@{1}] (60 seconds ago) commit: two
+ ! [branch@{2}] (2 minutes ago) reset: moving to HEAD^
+ ! [branch@{3}] (2 minutes ago) commit: one
+ ----
+ + [branch@{0}] three
+ ++ [branch@{1}] two
+ + [branch@{3}] one
+ ++++ [branch@{2}] base
+ EOF
+ # the output always contains relative timestamps; use
+ # a known time to get deterministic results
+ GIT_TEST_DATE_NOW=$test_tick \
+ git show-branch --reflog branch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--reflog handles missing reflog' '
+ git reflog expire --expire=now branch &&
+ git show-branch --reflog branch >actual &&
+ test_must_be_empty actual
+'
+
test_done
test_grep "already used by worktree at" err
'
-test_expect_success REFFILES,MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' '
- git checkout main &&
- mv .git/logs actual_logs &&
- cmd //c "mklink /D .git\logs ..\actual_logs" &&
- git rebase -f HEAD^ &&
- test -L .git/logs &&
- rm .git/logs &&
- mv actual_logs .git/logs
-'
-
test_expect_success 'rebase when inside worktree subdirectory' '
git init main-wt &&
(
git rebase --continue
'
+test_expect_success 'cherry-pick works with rebase --exec' '
+ test_when_finished "git cherry-pick --abort; \
+ git rebase --abort; \
+ git checkout primary" &&
+ echo "exec git cherry-pick G" >todo &&
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i D D
+ ) &&
+ test_cmp_rev G CHERRY_PICK_HEAD
+'
+
test_expect_success 'rebase -x with empty command fails' '
test_when_finished "git rebase --abort ||:" &&
test_must_fail env git rebase -x "" @ 2>actual &&
test_path_is_missing "$state_dir"
'
+ test_expect_success "pre rebase$type head is marked as reachable" '
+ # Clean up the state from the previous one
+ git checkout -f --detach pre-rebase &&
+ test_tick &&
+ git commit --amend --only -m "reworded" &&
+ orig_head=$(git rev-parse HEAD) &&
+ test_must_fail git rebase$type main &&
+ # Stop ORIG_HEAD marking $state_dir/orig-head as reachable
+ git update-ref -d ORIG_HEAD &&
+ git reflog expire --expire="$GIT_COMMITTER_DATE" --all &&
+ git prune --expire=now &&
+ git rebase --abort &&
+ test_cmp_rev $orig_head HEAD
+ '
+
test_expect_success "rebase$type --abort after --skip" '
# Clean up the state from the previous one
- git reset --hard pre-rebase &&
+ git checkout -B to-rebase pre-rebase &&
test_must_fail git rebase$type main &&
test_path_is_dir "$state_dir" &&
test_must_fail git rebase --skip &&
test_cmp_rev not-the-feature-branch unrelated-onto-branch
'
+test_expect_success 'autostash commit is marked as reachable' '
+ echo changed >file0 &&
+ git rebase --autostash --exec "git prune --expire=now" \
+ feature-branch^ feature-branch &&
+ # git rebase succeeds if the stash cannot be applied so we need to check
+ # the contents of file0
+ echo changed >expect &&
+ test_cmp expect file0
+'
+
test_done
test_description='stash -p'
. ./lib-patch-mode.sh
-if ! test_have_prereq PERL
-then
- skip_all='skipping stash -p tests, perl not available'
- test_done
-fi
-
test_expect_success 'setup' '
mkdir dir &&
echo parent > dir/foo &&
git log --no-walk -p refs/notes/textconv/magic HEAD
'
+test_expect_success 'caching is silently ignored outside repo' '
+ mkdir -p non-repo &&
+ echo one >non-repo/one &&
+ echo two >non-repo/two &&
+ echo "* diff=test" >attr &&
+ test_expect_code 1 \
+ nongit git -c core.attributesFile="$PWD/attr" \
+ -c diff.test.textconv="tr a-z A-Z <" \
+ -c diff.test.cachetextconv=true \
+ diff --no-index one two >actual &&
+ cat >expect <<-\EOF &&
+ diff --git a/one b/two
+ index 5626abf..f719efd 100644
+ --- a/one
+ +++ b/two
+ @@ -1 +1 @@
+ -ONE
+ +TWO
+ EOF
+ test_cmp expect actual
+'
+
test_done
)
'
+test_expect_success 'git apply respects core.fileMode' '
+ test_config core.fileMode false &&
+ echo true >script.sh &&
+ git add --chmod=+x script.sh &&
+ git ls-files -s script.sh >ls-files-output &&
+ test_grep "^100755" ls-files-output &&
+ test_tick && git commit -m "Add script" &&
+ git ls-tree -r HEAD script.sh >ls-tree-output &&
+ test_grep "^100755" ls-tree-output &&
+
+ echo true >>script.sh &&
+ test_tick && git commit -m "Modify script" script.sh &&
+ git format-patch -1 --stdout >patch &&
+ test_grep "^index.*100755$" patch &&
+
+ git switch -c branch HEAD^ &&
+ git apply --index patch 2>err &&
+ test_grep ! "has type 100644, expected 100755" err &&
+ git reset --hard &&
+
+ git apply patch 2>err &&
+ test_grep ! "has type 100644, expected 100755" err &&
+
+ git apply --cached patch 2>err &&
+ test_grep ! "has type 100644, expected 100755" err
+'
+
test_done
test_cmp expect actual
'
+test_expect_success '--merge-base with tree OIDs' '
+ git merge-tree --merge-base=side1^ side1 side3 >with-commits &&
+ git merge-tree --merge-base=side1^^{tree} side1^{tree} side3^{tree} >with-trees &&
+ test_cmp with-commits with-trees
+'
+
+test_expect_success 'error out on missing tree objects' '
+ git init --bare missing-tree.git &&
+ git rev-list side3 >list &&
+ git rev-parse side3^: >>list &&
+ git pack-objects missing-tree.git/objects/pack/side3-tree-is-missing <list &&
+ side3=$(git rev-parse side3) &&
+ test_must_fail git --git-dir=missing-tree.git merge-tree $side3^ $side3 >actual 2>err &&
+ test_grep "Could not read $(git rev-parse $side3:)" err &&
+ test_must_be_empty actual
+'
+
+test_expect_success 'error out on missing blob objects' '
+ echo 1 | git hash-object -w --stdin >blob1 &&
+ echo 2 | git hash-object -w --stdin >blob2 &&
+ echo 3 | git hash-object -w --stdin >blob3 &&
+ printf "100644 blob $(cat blob1)\tblob\n" | git mktree >tree1 &&
+ printf "100644 blob $(cat blob2)\tblob\n" | git mktree >tree2 &&
+ printf "100644 blob $(cat blob3)\tblob\n" | git mktree >tree3 &&
+ git init --bare missing-blob.git &&
+ cat blob1 blob3 tree1 tree2 tree3 |
+ git pack-objects missing-blob.git/objects/pack/side1-whatever-is-missing &&
+ test_must_fail git --git-dir=missing-blob.git >actual 2>err \
+ merge-tree --merge-base=$(cat tree1) $(cat tree2) $(cat tree3) &&
+ test_grep "unable to read blob object $(cat blob2)" err &&
+ test_must_be_empty actual
+'
+
+test_expect_success 'error out on missing commits as well' '
+ git init --bare missing-commit.git &&
+ git rev-list --objects side1 side3 >list-including-initial &&
+ grep -v ^$(git rev-parse side1^) <list-including-initial >list &&
+ git pack-objects missing-commit.git/objects/pack/missing-initial <list &&
+ side1=$(git rev-parse side1) &&
+ side3=$(git rev-parse side3) &&
+ test_must_fail git --git-dir=missing-commit.git \
+ merge-tree --allow-unrelated-histories $side1 $side3 >actual &&
+ test_must_be_empty actual
+'
+
test_done
fetch=shallow wait-for-done
server-option
object-format=$(test_oid algo)
- object-info
0000
EOF
fetch=shallow wait-for-done
server-option
object-format=$(test_oid algo)
- object-info
EOF
cat >expect.trailer <<-EOF &&
0000
# Test the basics of object-info
#
test_expect_success 'basics of object-info' '
+ test_config transfer.advertiseObjectInfo true &&
+
test-tool pkt-line pack >in <<-EOF &&
command=object-info
object-format=$(test_oid algo)
test_must_be_empty out
'
+test_expect_success 'object-info missing from capabilities when disabled' '
+ test_config transfer.advertiseObjectInfo false &&
+
+ GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \
+ --advertise-capabilities >out &&
+ test-tool pkt-line unpack <out >actual &&
+
+ ! grep object.info actual
+'
+
+test_expect_success 'object-info commands rejected when disabled' '
+ test_config transfer.advertiseObjectInfo false &&
+
+ test-tool pkt-line pack >in <<-EOF &&
+ command=object-info
+ EOF
+
+ test_must_fail test-tool serve-v2 --stateless-rpc <in 2>err &&
+ grep invalid.command err
+'
+
test_done
! grep ^GIT_PROTOCOL env.trace
'
+test_expect_success 'reject client packfile-uris if not advertised' '
+ {
+ packetize command=fetch &&
+ packetize object-format=$(test_oid algo) &&
+ printf 0001 &&
+ packetize packfile-uris https &&
+ packetize done &&
+ printf 0000
+ } >input &&
+ test_must_fail env GIT_PROTOCOL=version=2 \
+ git upload-pack client <input &&
+ test_must_fail env GIT_PROTOCOL=version=2 \
+ git -c uploadpack.blobpackfileuri \
+ upload-pack client <input &&
+ GIT_PROTOCOL=version=2 \
+ git -c uploadpack.blobpackfileuri=anything \
+ upload-pack client <input
+'
+
# Test protocol v2 with 'http://' transport
#
. "$TEST_DIRECTORY"/lib-httpd.sh
dir="$GIT_DIR/testgit/$alias"
+if ! git rev-parse --is-inside-git-dir
+then
+ exit 1
+fi
+
h_refspec="refs/heads/*:refs/testgit/$alias/heads/*"
t_refspec="refs/tags/*:refs/testgit/$alias/tags/*"
test_expect_success 'create repository and alternate directory' '
test_commit 1 &&
test_commit 2 &&
- test_commit 3
+ test_commit 3 &&
+ git tag -m "tag message" annot_tag HEAD~1 &&
+ git tag regul_tag HEAD~1 &&
+ git branch a_branch HEAD~1
'
# We manually corrupt the repository, which means that the commit-graph may
git rev-list --objects --no-object-names \
HEAD ^$obj >expect.raw &&
- # Blobs are shared by all commits, so evethough a commit/tree
+ # Blobs are shared by all commits, so even though a commit/tree
# might be skipped, its blob must be accounted for.
- if [ $obj != "HEAD:1.t" ]; then
+ if test $obj != "HEAD:1.t"
+ then
echo $(git rev-parse HEAD:1.t) >>expect.raw &&
echo $(git rev-parse HEAD:2.t) >>expect.raw
fi &&
done
done
+for missing_tip in "annot_tag" "regul_tag" "a_branch" "HEAD~1" "HEAD~1^{tree}" "HEAD:1.t"
+do
+ # We want to check that things work when both
+ # - all the tips passed are missing (case existing_tip = ""), and
+ # - there is one missing tip and one existing tip (case existing_tip = "HEAD")
+ for existing_tip in "" "HEAD"
+ do
+ for action in "allow-any" "print"
+ do
+ test_expect_success "--missing=$action with tip '$missing_tip' missing and tip '$existing_tip'" '
+ # Before the object is made missing, we use rev-list to
+ # get the expected oids.
+ if test "$existing_tip" = "HEAD"
+ then
+ git rev-list --objects --no-object-names \
+ HEAD ^$missing_tip >expect.raw
+ else
+ >expect.raw
+ fi &&
+
+ # Blobs are shared by all commits, so even though a commit/tree
+ # might be skipped, its blob must be accounted for.
+ if test "$existing_tip" = "HEAD" && test $missing_tip != "HEAD:1.t"
+ then
+ echo $(git rev-parse HEAD:1.t) >>expect.raw &&
+ echo $(git rev-parse HEAD:2.t) >>expect.raw
+ fi &&
+
+ missing_oid="$(git rev-parse $missing_tip)" &&
+
+ if test "$missing_tip" = "annot_tag"
+ then
+ oid="$(git rev-parse $missing_tip^{commit})" &&
+ echo "$missing_oid" >>expect.raw
+ else
+ oid="$missing_oid"
+ fi &&
+
+ path=".git/objects/$(test_oid_to_path $oid)" &&
+
+ mv "$path" "$path.hidden" &&
+ test_when_finished "mv $path.hidden $path" &&
+
+ git rev-list --missing=$action --objects --no-object-names \
+ $missing_oid $existing_tip >actual.raw &&
+
+ # When the action is to print, we should also add the missing
+ # oid to the expect list.
+ case $action in
+ allow-any)
+ ;;
+ print)
+ grep ?$oid actual.raw &&
+ echo ?$oid >>expect.raw
+ ;;
+ esac &&
+
+ sort actual.raw >actual &&
+ sort expect.raw >expect &&
+ test_cmp expect actual
+ '
+ done
+ done
+done
+
test_done
echo "" > expected.ok
cat > expected.missing-tree.default <<EOF
-fatal: unable to read tree $deleted
+fatal: unable to read tree ($deleted)
EOF
test_expect_success 'bisect fails if tree is broken on start commit' '
git update-ref refs/odd/spot main
'
+test_expect_success '--include-root-refs pattern prints pseudorefs' '
+ cat >expect <<-\EOF &&
+ HEAD
+ ORIG_HEAD
+ refs/heads/main
+ refs/heads/side
+ refs/odd/spot
+ refs/tags/annotated-tag
+ refs/tags/doubly-annotated-tag
+ refs/tags/doubly-signed-tag
+ refs/tags/four
+ refs/tags/one
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git update-ref ORIG_HEAD main &&
+ git for-each-ref --format="%(refname)" --include-root-refs >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--include-root-refs with other patterns' '
+ cat >expect <<-\EOF &&
+ HEAD
+ ORIG_HEAD
+ EOF
+ git update-ref ORIG_HEAD main &&
+ git for-each-ref --format="%(refname)" --include-root-refs "*HEAD" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'filtering with --points-at' '
cat >expect <<-\EOF &&
refs/heads/main
git checkout -b test-nonforward-a b &&
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
then
- test_must_fail git merge c >actual &&
+ test_must_fail git merge c 2>actual &&
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
grep "$sub_expect" actual
else
git rev-parse --short sub-d > ../expect) &&
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
then
- test_must_fail git merge c >actual &&
+ test_must_fail git merge c >actual 2>sub-actual &&
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
- grep "$sub_expect" actual
+ grep "$sub_expect" sub-actual
else
test_must_fail git merge c 2> actual
fi &&
) &&
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
then
- test_must_fail git merge c >actual &&
+ test_must_fail git merge c >actual 2>sub-actual &&
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
- grep "$sub_expect" actual
+ grep "$sub_expect" sub-actual
else
test_must_fail git merge c 2> actual
fi &&
git commit -a -m "f" &&
git checkout -b test-backward e &&
- test_must_fail git merge f >actual &&
+ test_must_fail git merge f 2>actual &&
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
then
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" &&
git checkout -b b init &&
git add sub &&
git commit -m "b" &&
- test_must_fail git merge a >actual &&
+ test_must_fail git merge a 2>actual &&
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
then
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" &&
git branch prune-entire B &&
git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t B.t" prune-entire &&
test_must_fail git rev-parse refs/heads/prune-entire &&
- if test_have_prereq REFFILES
- then
- test_must_fail git reflog exists refs/heads/prune-entire
- fi
+ test_must_fail git reflog exists refs/heads/prune-entire
'
test_expect_success '--remap-to-ancestor with filename filters' '
TEST_PASSES_SANITIZE_LEAK=true
. ./lib-patch-mode.sh
-test_expect_success PERL 'setup' '
+test_expect_success 'setup' '
mkdir dir &&
echo parent > dir/foo &&
echo dummy > bar &&
# note: bar sorts before foo, so the first 'n' is always to skip 'bar'
-test_expect_success PERL 'saying "n" does nothing' '
+test_expect_success 'saying "n" does nothing' '
set_and_save_state dir/foo work work &&
test_write_lines n n | git reset -p &&
verify_saved_state dir/foo &&
verify_saved_state bar
'
-test_expect_success PERL 'git reset -p' '
- test_write_lines n y | git reset -p >output &&
- verify_state dir/foo work head &&
- verify_saved_state bar &&
- test_grep "Unstage" output
-'
-
-test_expect_success PERL 'git reset -p HEAD^' '
+for opt in "HEAD" "@" ""
+do
+ test_expect_success "git reset -p $opt" '
+ set_and_save_state dir/foo work work &&
+ test_write_lines n y | git reset -p $opt >output &&
+ verify_state dir/foo work head &&
+ verify_saved_state bar &&
+ test_grep "Unstage" output
+ '
+done
+
+test_expect_success 'git reset -p HEAD^' '
test_write_lines n y | git reset -p HEAD^ >output &&
verify_state dir/foo work parent &&
verify_saved_state bar &&
test_grep "Apply" output
'
-test_expect_success PERL 'git reset -p HEAD^^{tree}' '
+test_expect_success 'git reset -p HEAD^^{tree}' '
test_write_lines n y | git reset -p HEAD^^{tree} >output &&
verify_state dir/foo work parent &&
verify_saved_state bar &&
test_grep "Apply" output
'
-test_expect_success PERL 'git reset -p HEAD^:dir/foo (blob fails)' '
+test_expect_success 'git reset -p HEAD^:dir/foo (blob fails)' '
set_and_save_state dir/foo work work &&
test_must_fail git reset -p HEAD^:dir/foo &&
verify_saved_state dir/foo &&
verify_saved_state bar
'
-test_expect_success PERL 'git reset -p aaaaaaaa (unknown fails)' '
+test_expect_success 'git reset -p aaaaaaaa (unknown fails)' '
set_and_save_state dir/foo work work &&
test_must_fail git reset -p aaaaaaaa &&
verify_saved_state dir/foo &&
# dir/foo. There's always an extra 'n' to reject edits to dir/foo in
# the failure case (and thus get out of the loop).
-test_expect_success PERL 'git reset -p dir' '
+test_expect_success 'git reset -p dir' '
set_state dir/foo work work &&
test_write_lines y n | git reset -p dir &&
verify_state dir/foo work head &&
verify_saved_state bar
'
-test_expect_success PERL 'git reset -p -- foo (inside dir)' '
+test_expect_success 'git reset -p -- foo (inside dir)' '
set_state dir/foo work work &&
test_write_lines y n | (cd dir && git reset -p -- foo) &&
verify_state dir/foo work head &&
verify_saved_state bar
'
-test_expect_success PERL 'git reset -p HEAD^ -- dir' '
+test_expect_success 'git reset -p HEAD^ -- dir' '
test_write_lines y n | git reset -p HEAD^ -- dir &&
verify_state dir/foo work parent &&
verify_saved_state bar
'
-test_expect_success PERL 'none of this moved HEAD' '
+test_expect_success 'none of this moved HEAD' '
verify_saved_head
'
test_cmp expect actual
'
-test_expect_success PERL 'reset -p' '
+test_expect_success 'reset -p' '
rm .git/index &&
git add a &&
echo y >yes &&
'
+test_expect_success 'clean.requireForce and --interactive' '
+ git clean --interactive </dev/null >output 2>error &&
+ test_grep ! "requireForce is true and" error &&
+ test_grep "\*\*\* Commands \*\*\*" output
+'
+
test_expect_success 'core.excludesfile' '
echo excludes >excludes &&
test_tick &&
git commit -m fourth &&
- test_must_fail git rebase --onto HEAD^^ HEAD^ HEAD^0 >actual_output &&
+ test_must_fail git rebase --onto HEAD^^ HEAD^ HEAD^0 2>actual_output &&
git ls-files -s submodule >actual &&
(
cd submodule &&
test_cmp expected actual
'
+test_expect_success 'commit --trailer with --verbose' '
+ cat >msg <<-\EOF &&
+ subject
+
+ body
+ EOF
+ GIT_EDITOR=: git commit --edit -F msg --allow-empty \
+ --trailer="my-trailer: value" --verbose &&
+ {
+ cat msg &&
+ echo &&
+ echo "my-trailer: value"
+ } >expected &&
+ git cat-file commit HEAD >commit.msg &&
+ sed -e "1,/^\$/d" commit.msg >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'multiple -m' '
>negative &&
.git/COMMIT_EDITMSG
'
+test_expect_success 'message does not have multiple scissors lines' '
+ git commit --cleanup=scissors -v --allow-empty -e -m foo &&
+ test $(grep -c -e "--- >8 ---" .git/COMMIT_EDITMSG) -eq 1
+'
+
test_expect_success AUTOIDENT 'message shows committer when it is automatic' '
echo >>negative &&
test_cmp expected actual
'
+test_expect_success 'suppressing --- does not disable cut-line handling' '
+ echo "real-trailer: before the cut" >expected &&
+
+ git interpret-trailers --parse --no-divider >actual <<-\EOF &&
+ subject
+
+ This input has a cut-line in it; we should stop parsing when we see it
+ and consider only trailers before that line.
+
+ real-trailer: before the cut
+
+ # ------------------------ >8 ------------------------
+ # Nothing below this line counts as part of the commit message.
+ not-a-trailer: too late
+ EOF
+
+ test_cmp expected actual
+'
+
test_done
test_description='hunk edit with "commit -p -m"'
. ./test-lib.sh
-if ! test_have_prereq PERL
-then
- skip_all="skipping '$test_description' tests, perl not available"
- test_done
-fi
-
test_expect_success 'setup (initial)' '
echo line1 >file &&
git add file &&
rm for-diff
'
-test_expect_success 'difftool ignores exit code' '
- test_config difftool.error.cmd false &&
- git difftool -y -t error branch
-'
+for opt in '' '--dir-diff'
+do
+ test_expect_success "difftool ${opt} ignores exit code" "
+ test_config difftool.error.cmd false &&
+ git difftool ${opt} -y -t error branch
+ "
-test_expect_success 'difftool forwards exit code with --trust-exit-code' '
- test_config difftool.error.cmd false &&
- test_must_fail git difftool -y --trust-exit-code -t error branch
-'
+ test_expect_success "difftool ${opt} forwards exit code with --trust-exit-code" "
+ test_config difftool.error.cmd false &&
+ test_must_fail git difftool ${opt} -y --trust-exit-code -t error branch
+ "
-test_expect_success 'difftool forwards exit code with --trust-exit-code for built-ins' '
- test_config difftool.vimdiff.path false &&
- test_must_fail git difftool -y --trust-exit-code -t vimdiff branch
-'
+ test_expect_success "difftool ${opt} forwards exit code with --trust-exit-code for built-ins" "
+ test_config difftool.vimdiff.path false &&
+ test_must_fail git difftool ${opt} -y --trust-exit-code -t vimdiff branch
+ "
-test_expect_success 'difftool honors difftool.trustExitCode = true' '
- test_config difftool.error.cmd false &&
- test_config difftool.trustExitCode true &&
- test_must_fail git difftool -y -t error branch
-'
+ test_expect_success "difftool ${opt} honors difftool.trustExitCode = true" "
+ test_config difftool.error.cmd false &&
+ test_config difftool.trustExitCode true &&
+ test_must_fail git difftool ${opt} -y -t error branch
+ "
-test_expect_success 'difftool honors difftool.trustExitCode = false' '
- test_config difftool.error.cmd false &&
- test_config difftool.trustExitCode false &&
- git difftool -y -t error branch
-'
+ test_expect_success "difftool ${opt} honors difftool.trustExitCode = false" "
+ test_config difftool.error.cmd false &&
+ test_config difftool.trustExitCode false &&
+ git difftool ${opt} -y -t error branch
+ "
-test_expect_success 'difftool ignores exit code with --no-trust-exit-code' '
- test_config difftool.error.cmd false &&
- test_config difftool.trustExitCode true &&
- git difftool -y --no-trust-exit-code -t error branch
-'
+ test_expect_success "difftool ${opt} ignores exit code with --no-trust-exit-code" "
+ test_config difftool.error.cmd false &&
+ test_config difftool.trustExitCode true &&
+ git difftool ${opt} -y --no-trust-exit-code -t error branch
+ "
-test_expect_success 'difftool stops on error with --trust-exit-code' '
- test_when_finished "rm -f for-diff .git/fail-right-file" &&
- test_when_finished "git reset -- for-diff" &&
- write_script .git/fail-right-file <<-\EOF &&
- echo failed
- exit 1
- EOF
- >for-diff &&
- git add for-diff &&
- test_must_fail git difftool -y --trust-exit-code \
- --extcmd .git/fail-right-file branch >actual &&
- test_line_count = 1 actual
-'
+ test_expect_success "difftool ${opt} stops on error with --trust-exit-code" "
+ test_when_finished 'rm -f for-diff .git/fail-right-file' &&
+ test_when_finished 'git reset -- for-diff' &&
+ write_script .git/fail-right-file <<-\EOF &&
+ echo failed
+ exit 1
+ EOF
+ >for-diff &&
+ git add for-diff &&
+ test_must_fail git difftool ${opt} -y --trust-exit-code \
+ --extcmd .git/fail-right-file branch >actual &&
+ test_line_count = 1 actual
+ "
-test_expect_success 'difftool honors exit status if command not found' '
- test_config difftool.nonexistent.cmd i-dont-exist &&
- test_config difftool.trustExitCode false &&
- test_must_fail git difftool -y -t nonexistent branch
-'
+ test_expect_success "difftool ${opt} honors exit status if command not found" "
+ test_config difftool.nonexistent.cmd i-dont-exist &&
+ test_config difftool.trustExitCode false &&
+ if test "${opt}" = '--dir-diff'
+ then
+ expected_code=127
+ else
+ expected_code=128
+ fi &&
+ test_expect_code \${expected_code} git difftool ${opt} -y -t nonexistent branch
+ "
+done
test_expect_success 'difftool honors --gui' '
difftool_test_setup &&
test_cmp expected actual
'
+test_expect_success 'padding must be non-negative' '
+ cat >input <<\EOF &&
+1 2 3 4 5 6
+EOF
+ cat >expected <<\EOF &&
+fatal: --padding must be non-negative
+EOF
+ test_must_fail git column --mode=column --padding=-1 <input >actual 2>&1 &&
+ test_cmp expected actual
+'
+
test_done
test_expect_success 'basic clone' '
test ! -d trunk &&
git svn clone "$svnrepo"/project/trunk &&
- test -d trunk/.git/svn &&
- test -e trunk/foo &&
+ test_path_is_dir trunk/.git/svn &&
+ test_path_exists trunk/foo &&
rm -rf trunk
'
test_expect_success 'clone to target directory' '
test ! -d target &&
git svn clone "$svnrepo"/project/trunk target &&
- test -d target/.git/svn &&
- test -e target/foo &&
+ test_path_is_dir target/.git/svn &&
+ test_path_exists target/foo &&
rm -rf target
'
test_expect_success 'clone with --stdlayout' '
test ! -d project &&
git svn clone -s "$svnrepo"/project &&
- test -d project/.git/svn &&
- test -e project/foo &&
+ test_path_is_dir project/.git/svn &&
+ test_path_exists project/foo &&
rm -rf project
'
test_expect_success 'clone to target directory with --stdlayout' '
test ! -d target &&
git svn clone -s "$svnrepo"/project target &&
- test -d target/.git/svn &&
- test -e target/foo &&
+ test_path_is_dir target/.git/svn &&
+ test_path_exists target/foo &&
rm -rf target
'
cd cloned &&
for i in a b c d d/e d/e/f "weird file name"
do
- if ! test -d "$i"
- then
- echo >&2 "$i does not exist" &&
- exit 1
- fi
+ test_path_is_dir "$i" || exit 1
done
)
'
git svn fetch &&
for i in a b c d d/e d/e/f "weird file name"
do
- if test -d "$i"
- then
- echo >&2 "$i exists" &&
- exit 1
- fi
+ test_path_is_missing "$i" || exit 1
done
)
'
test_expect_success 'git svn rebase creates empty directory' '
( cd cloned && git svn rebase ) &&
- test -d cloned/"! !"
+ test_path_is_dir cloned/"! !"
'
test_expect_success 'git svn mkdirs recreates empty directories' '
git svn mkdirs &&
for i in a b c d d/e d/e/f "weird file name" "! !"
do
- if ! test -d "$i"
- then
- echo >&2 "$i does not exist" &&
- exit 1
- fi
+ test_path_is_dir "$i" || exit 1
done
)
'
git svn mkdirs -r7 &&
for i in a b c d d/e d/e/f "weird file name"
do
- if ! test -d "$i"
- then
- echo >&2 "$i does not exist" &&
- exit 1
- fi
+ test_path_is_dir "$i" || exit 1
done &&
- if test -d "! !"
- then
- echo >&2 "$i should not exist" &&
- exit 1
- fi &&
+ test_path_is_missing "! !" || exit 1 &&
git svn mkdirs -r8 &&
- if ! test -d "! !"
- then
- echo >&2 "$i not exist" &&
- exit 1
- fi
+ test_path_is_dir "! !" || exit 1
)
'
cd trunk &&
for i in a "weird file name"
do
- if ! test -d "$i"
- then
- echo >&2 "$i does not exist" &&
- exit 1
- fi
+ test_path_is_dir "$i" || exit 1
done
)
'
test_expect_success 'removed top-level directory does not exist' '
git svn clone "$svnrepo" removed &&
- test ! -e removed/d
+ test_path_is_missing removed/d
'
unhandled=.git/svn/refs/remotes/git-svn/unhandled.log
svn_cmd mkdir -m gz "$svnrepo"/gz &&
git reset --hard $(git rev-list HEAD | tail -1) &&
git svn rebase &&
- test -f "$unhandled".gz &&
- test -f "$unhandled" &&
+ test_path_is_file "$unhandled".gz &&
+ test_path_is_file "$unhandled" &&
for i in a b c "weird file name" gz "! !"
do
- if ! test -d "$i"
- then
- echo >&2 "$i does not exist" &&
- exit 1
- fi
+ test_path_is_dir "$i" || exit 1
done
fi
)
test_cmp expect actual &&
test_path_is_missing 1/2 &&
- test_must_fail git rev-list --missing=print $second &&
+
+ # This relies on the fact that the presence of "--missing"
+ # on the command line forces lazy fetching off before
+ # "$second^{blob}" gets parsed. Without "^{blob}", a
+ # bare object name "$second" is taken into the queue and
+ # the command may not fail with a fixed "rev-list --missing".
+ test_must_fail git rev-list --missing=print "$second^{blob}" -- &&
+
git rev-list $second &&
git cat-file blob $second >actual &&
echo "second" >expect &&
EOF
'
+test_expect_success 'setup for git config submodule tests' '
+ test_create_repo sub &&
+ test_commit -C sub initial &&
+ git submodule add ./sub
+'
+
+test_expect_success 'git config - variable name - submodule and __git_compute_first_level_config_vars_for_section' '
+ test_completion "git config submodule." <<-\EOF
+ submodule.active Z
+ submodule.alternateErrorStrategy Z
+ submodule.alternateLocation Z
+ submodule.fetchJobs Z
+ submodule.propagateBranches Z
+ submodule.recurse Z
+ submodule.sub.Z
+ EOF
+'
+
+test_expect_success 'git config - variable name - __git_compute_second_level_config_vars_for_section' '
+ test_completion "git config submodule.sub." <<-\EOF
+ submodule.sub.url Z
+ submodule.sub.update Z
+ submodule.sub.branch Z
+ submodule.sub.fetchRecurseSubmodules Z
+ submodule.sub.ignore Z
+ submodule.sub.active Z
+ EOF
+'
+
test_expect_success 'git config - value' '
test_completion "git config color.pager " <<-\EOF
false Z
case "$GIT_DEFAULT_REF_FORMAT" in
files)
test_set_prereq REFFILES;;
+reftable)
+ test_set_prereq REFTABLE;;
*)
echo 2>&1 "error: unknown ref format $GIT_DEFAULT_REF_FORMAT"
exit 1
#include "test-lib.h"
-static int is_in(const char *s, int ch)
-{
- /*
- * We can't find NUL using strchr. Accept it as the first
- * character in the spec -- there are no empty classes.
- */
- if (ch == '\0')
- return ch == *s;
- if (*s == '\0')
- s++;
- return !!strchr(s, ch);
-}
-
-/* Macro to test a character type */
-#define TEST_CTYPE_FUNC(func, string) \
-static void test_ctype_##func(void) { \
- for (int i = 0; i < 256; i++) { \
- if (!check_int(func(i), ==, is_in(string, i))) \
- test_msg(" i: 0x%02x", i); \
+#define TEST_CHAR_CLASS(class, string) do { \
+ size_t len = ARRAY_SIZE(string) - 1 + \
+ BUILD_ASSERT_OR_ZERO(ARRAY_SIZE(string) > 0) + \
+ BUILD_ASSERT_OR_ZERO(sizeof(string[0]) == sizeof(char)); \
+ int skip = test__run_begin(); \
+ if (!skip) { \
+ for (int i = 0; i < 256; i++) { \
+ if (!check_int(class(i), ==, !!memchr(string, i, len)))\
+ test_msg(" i: 0x%02x", i); \
+ } \
+ check(!class(EOF)); \
} \
- if (!check(!func(EOF))) \
- test_msg(" i: 0x%02x (EOF)", EOF); \
-}
-
-#define TEST_CHAR_CLASS(class) TEST(test_ctype_##class(), #class " works")
+ test__run_end(!skip, TEST_LOCATION(), #class " works"); \
+} while (0)
#define DIGIT "0123456789"
#define LOWER "abcdefghijklmnopqrstuvwxyz"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
"\x7f"
-TEST_CTYPE_FUNC(isdigit, DIGIT)
-TEST_CTYPE_FUNC(isspace, " \n\r\t")
-TEST_CTYPE_FUNC(isalpha, LOWER UPPER)
-TEST_CTYPE_FUNC(isalnum, LOWER UPPER DIGIT)
-TEST_CTYPE_FUNC(is_glob_special, "*?[\\")
-TEST_CTYPE_FUNC(is_regex_special, "$()*+.?[\\^{|")
-TEST_CTYPE_FUNC(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~")
-TEST_CTYPE_FUNC(isascii, ASCII)
-TEST_CTYPE_FUNC(islower, LOWER)
-TEST_CTYPE_FUNC(isupper, UPPER)
-TEST_CTYPE_FUNC(iscntrl, CNTRL)
-TEST_CTYPE_FUNC(ispunct, PUNCT)
-TEST_CTYPE_FUNC(isxdigit, DIGIT "abcdefABCDEF")
-TEST_CTYPE_FUNC(isprint, LOWER UPPER DIGIT PUNCT " ")
-
int cmd_main(int argc, const char **argv) {
- /* Run all character type tests */
- TEST_CHAR_CLASS(isspace);
- TEST_CHAR_CLASS(isdigit);
- TEST_CHAR_CLASS(isalpha);
- TEST_CHAR_CLASS(isalnum);
- TEST_CHAR_CLASS(is_glob_special);
- TEST_CHAR_CLASS(is_regex_special);
- TEST_CHAR_CLASS(is_pathspec_magic);
- TEST_CHAR_CLASS(isascii);
- TEST_CHAR_CLASS(islower);
- TEST_CHAR_CLASS(isupper);
- TEST_CHAR_CLASS(iscntrl);
- TEST_CHAR_CLASS(ispunct);
- TEST_CHAR_CLASS(isxdigit);
- TEST_CHAR_CLASS(isprint);
+ TEST_CHAR_CLASS(isspace, " \n\r\t");
+ TEST_CHAR_CLASS(isdigit, DIGIT);
+ TEST_CHAR_CLASS(isalpha, LOWER UPPER);
+ TEST_CHAR_CLASS(isalnum, LOWER UPPER DIGIT);
+ TEST_CHAR_CLASS(is_glob_special, "*?[\\");
+ TEST_CHAR_CLASS(is_regex_special, "$()*+.?[\\^{|");
+ TEST_CHAR_CLASS(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~");
+ TEST_CHAR_CLASS(isascii, ASCII);
+ TEST_CHAR_CLASS(islower, LOWER);
+ TEST_CHAR_CLASS(isupper, UPPER);
+ TEST_CHAR_CLASS(iscntrl, CNTRL);
+ TEST_CHAR_CLASS(ispunct, PUNCT);
+ TEST_CHAR_CLASS(isxdigit, DIGIT "abcdefABCDEF");
+ TEST_CHAR_CLASS(isprint, LOWER UPPER DIGIT PUNCT " ");
return test_done();
}
/* Assume the naive end of the input is already what we want. */
end = strlen(input);
- if (no_divider)
- return end;
-
/* Optionally skip over any patch part ("---" line and below). */
- for (s = input; *s; s = next_line(s)) {
- const char *v;
+ if (!no_divider) {
+ for (s = input; *s; s = next_line(s)) {
+ const char *v;
- if (skip_prefix(s, "---", &v) && isspace(*v)) {
- end = s - input;
- break;
+ if (skip_prefix(s, "---", &v) && isspace(*v)) {
+ end = s - input;
+ break;
+ }
}
}
if (oid) {
buf = read_object_with_reference(r, oid, OBJ_TREE, &size, NULL);
if (!buf)
- die("unable to read tree %s", oid_to_hex(oid));
+ die(_("unable to read tree (%s)"), oid_to_hex(oid));
}
init_tree_desc(desc, buf, size);
return buf;
#include "shallow.h"
#include "write-or-die.h"
#include "json-writer.h"
+#include "strmap.h"
/* Remember to update object flag allocation in object.h */
#define THEY_HAVE (1u << 11)
struct string_list symref; /* v0 only */
struct object_array want_obj;
struct object_array have_obj;
- struct oid_array haves; /* v2 only */
- struct string_list wanted_refs; /* v2 only */
+ struct strmap wanted_refs; /* v2 only */
struct strvec hidden_refs;
struct object_array shallows;
- struct string_list deepen_not;
+ struct oidset deepen_not;
struct object_array extra_edge_obj;
int depth;
timestamp_t deepen_since;
unsigned done : 1; /* v2 only */
unsigned allow_ref_in_want : 1; /* v2 only */
unsigned allow_sideband_all : 1; /* v2 only */
+ unsigned seen_haves : 1; /* v2 only */
+ unsigned allow_packfile_uris : 1; /* v2 only */
unsigned advertise_sid : 1;
unsigned sent_capabilities : 1;
};
static void upload_pack_data_init(struct upload_pack_data *data)
{
struct string_list symref = STRING_LIST_INIT_DUP;
- struct string_list wanted_refs = STRING_LIST_INIT_DUP;
+ struct strmap wanted_refs = STRMAP_INIT;
struct strvec hidden_refs = STRVEC_INIT;
struct object_array want_obj = OBJECT_ARRAY_INIT;
struct object_array have_obj = OBJECT_ARRAY_INIT;
- struct oid_array haves = OID_ARRAY_INIT;
struct object_array shallows = OBJECT_ARRAY_INIT;
- struct string_list deepen_not = STRING_LIST_INIT_DUP;
+ struct oidset deepen_not = OID_ARRAY_INIT;
struct string_list uri_protocols = STRING_LIST_INIT_DUP;
struct object_array extra_edge_obj = OBJECT_ARRAY_INIT;
struct string_list allowed_filters = STRING_LIST_INIT_DUP;
data->hidden_refs = hidden_refs;
data->want_obj = want_obj;
data->have_obj = have_obj;
- data->haves = haves;
data->shallows = shallows;
data->deepen_not = deepen_not;
data->uri_protocols = uri_protocols;
static void upload_pack_data_clear(struct upload_pack_data *data)
{
string_list_clear(&data->symref, 1);
- string_list_clear(&data->wanted_refs, 1);
+ strmap_clear(&data->wanted_refs, 1);
strvec_clear(&data->hidden_refs);
object_array_clear(&data->want_obj);
object_array_clear(&data->have_obj);
- oid_array_clear(&data->haves);
object_array_clear(&data->shallows);
- string_list_clear(&data->deepen_not, 0);
+ oidset_clear(&data->deepen_not);
object_array_clear(&data->extra_edge_obj);
list_objects_filter_release(&data->filter_options);
string_list_clear(&data->allowed_filters, 0);
fail:
free(output_state);
- send_client_data(3, abort_msg, sizeof(abort_msg),
+ send_client_data(3, abort_msg, strlen(abort_msg),
pack_data->use_sideband);
die("git upload-pack: %s", abort_msg);
}
static int do_got_oid(struct upload_pack_data *data, const struct object_id *oid)
{
int we_knew_they_have = 0;
- struct object *o = parse_object(the_repository, oid);
+ struct object *o = parse_object_with_flags(the_repository, oid,
+ PARSE_OBJECT_SKIP_HASH_CHECK |
+ PARSE_OBJECT_DISCARD_TREE);
if (!o)
die("oops (%s)", oid_to_hex(oid));
int got_other = 0;
int sent_ready = 0;
- save_commit_buffer = 0;
-
for (;;) {
const char *arg;
strvec_push(&av, "rev-list");
if (data->deepen_since)
strvec_pushf(&av, "--max-age=%"PRItime, data->deepen_since);
- if (data->deepen_not.nr) {
+ if (oidset_size(&data->deepen_not)) {
+ const struct object_id *oid;
+ struct oidset_iter iter;
strvec_push(&av, "--not");
- for (i = 0; i < data->deepen_not.nr; i++) {
- struct string_list_item *s = data->deepen_not.items + i;
- strvec_push(&av, s->string);
- }
+ oidset_iter_init(&data->deepen_not, &iter);
+ while ((oid = oidset_iter_next(&iter)))
+ strvec_push(&av, oid_to_hex(oid));
strvec_push(&av, "--not");
}
for (i = 0; i < data->want_obj.nr; i++) {
return 0;
}
-static int process_deepen_not(const char *line, struct string_list *deepen_not, int *deepen_rev_list)
+static int process_deepen_not(const char *line, struct oidset *deepen_not, int *deepen_rev_list)
{
const char *arg;
if (skip_prefix(line, "deepen-not ", &arg)) {
struct object_id oid;
if (expand_ref(the_repository, arg, strlen(arg), &oid, &ref) != 1)
die("git upload-pack: ambiguous deepen-not: %s", line);
- string_list_append(deepen_not, ref);
+ oidset_insert(deepen_not, &oid);
free(ref);
*deepen_rev_list = 1;
return 1;
free(client_sid);
}
- o = parse_object(the_repository, &oid_buf);
+ o = parse_object_with_flags(the_repository, &oid_buf,
+ PARSE_OBJECT_SKIP_HASH_CHECK |
+ PARSE_OBJECT_DISCARD_TREE);
if (!o) {
packet_writer_error(&data->writer,
"upload-pack: not our ref %s",
data->allow_ref_in_want = git_config_bool(var, value);
} else if (!strcmp("uploadpack.allowsidebandall", var)) {
data->allow_sideband_all = git_config_bool(var, value);
+ } else if (!strcmp("uploadpack.blobpackfileuri", var)) {
+ if (value)
+ data->allow_packfile_uris = 1;
} else if (!strcmp("core.precomposeunicode", var)) {
precomposed_unicode = git_config_bool(var, value);
} else if (!strcmp("transfer.advertisesid", var)) {
return 0;
}
-static void get_upload_pack_config(struct upload_pack_data *data)
+static void get_upload_pack_config(struct repository *r,
+ struct upload_pack_data *data)
{
- git_config(upload_pack_config, data);
+ repo_config(r, upload_pack_config, data);
git_protected_config(upload_pack_protected_config, data);
+
+ data->allow_sideband_all |= git_env_bool("GIT_TEST_SIDEBAND_ALL", 0);
}
void upload_pack(const int advertise_refs, const int stateless_rpc,
struct upload_pack_data data;
upload_pack_data_init(&data);
- get_upload_pack_config(&data);
+ get_upload_pack_config(the_repository, &data);
data.stateless_rpc = stateless_rpc;
data.timeout = timeout;
"expected to get oid, not '%s'", line);
o = parse_object_with_flags(the_repository, &oid,
- PARSE_OBJECT_SKIP_HASH_CHECK);
+ PARSE_OBJECT_SKIP_HASH_CHECK |
+ PARSE_OBJECT_DISCARD_TREE);
if (!o) {
packet_writer_error(writer,
}
static int parse_want_ref(struct packet_writer *writer, const char *line,
- struct string_list *wanted_refs,
+ struct strmap *wanted_refs,
struct strvec *hidden_refs,
struct object_array *want_obj)
{
const char *refname_nons;
if (skip_prefix(line, "want-ref ", &refname_nons)) {
struct object_id oid;
- struct string_list_item *item;
struct object *o = NULL;
struct strbuf refname = STRBUF_INIT;
}
strbuf_release(&refname);
- item = string_list_append(wanted_refs, refname_nons);
- item->util = oiddup(&oid);
+ if (strmap_put(wanted_refs, refname_nons, oiddup(&oid))) {
+ packet_writer_error(writer, "duplicate want-ref %s",
+ refname_nons);
+ die("duplicate want-ref %s", refname_nons);
+ }
if (!starts_with(refname_nons, "refs/tags/")) {
struct commit *commit = lookup_commit_in_graph(the_repository, &oid);
return 0;
}
-static int parse_have(const char *line, struct oid_array *haves)
+static int parse_have(const char *line, struct upload_pack_data *data)
{
const char *arg;
if (skip_prefix(line, "have ", &arg)) {
struct object_id oid;
- if (get_oid_hex(arg, &oid))
- die("git upload-pack: expected SHA1 object, got '%s'", arg);
- oid_array_append(haves, &oid);
+ got_oid(data, arg, &oid);
+ data->seen_haves = 1;
return 1;
}
struct json_writer jw = JSON_WRITER_INIT;
jw_object_begin(&jw, 0);
- jw_object_intmax(&jw, "haves", data->haves.nr);
+ jw_object_intmax(&jw, "haves", data->have_obj.nr);
jw_object_intmax(&jw, "wants", data->want_obj.nr);
- jw_object_intmax(&jw, "want-refs", data->wanted_refs.nr);
+ jw_object_intmax(&jw, "want-refs", strmap_get_size(&data->wanted_refs));
jw_object_intmax(&jw, "depth", data->depth);
jw_object_intmax(&jw, "shallows", data->shallows.nr);
jw_object_bool(&jw, "deepen-since", data->deepen_since);
- jw_object_intmax(&jw, "deepen-not", data->deepen_not.nr);
+ jw_object_intmax(&jw, "deepen-not", oidset_size(&data->deepen_not));
jw_object_bool(&jw, "deepen-relative", data->deepen_relative);
if (data->filter_options.choice)
jw_object_string(&jw, "filter", list_object_filter_config_name(data->filter_options.choice));
&data->hidden_refs, &data->want_obj))
continue;
/* process have line */
- if (parse_have(arg, &data->haves))
+ if (parse_have(arg, data))
continue;
/* process args like thin-pack */
continue;
}
- if ((git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
- data->allow_sideband_all) &&
+ if (data->allow_sideband_all &&
!strcmp(arg, "sideband-all")) {
data->writer.use_sideband = 1;
continue;
}
- if (skip_prefix(arg, "packfile-uris ", &p)) {
+ if (data->allow_packfile_uris &&
+ skip_prefix(arg, "packfile-uris ", &p)) {
+ if (data->uri_protocols.nr)
+ send_err_and_die(data,
+ "multiple packfile-uris lines forbidden");
string_list_split(&data->uri_protocols, p, ',', -1);
continue;
}
trace2_fetch_info(data);
}
-static int process_haves(struct upload_pack_data *data, struct oid_array *common)
-{
- int i;
-
- /* Process haves */
- for (i = 0; i < data->haves.nr; i++) {
- const struct object_id *oid = &data->haves.oid[i];
-
- if (!repo_has_object_file_with_flags(the_repository, oid,
- OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT))
- continue;
-
- oid_array_append(common, oid);
-
- do_got_oid(data, oid);
- }
-
- return 0;
-}
-
-static int send_acks(struct upload_pack_data *data, struct oid_array *acks)
+static int send_acks(struct upload_pack_data *data, struct object_array *acks)
{
int i;
for (i = 0; i < acks->nr; i++) {
packet_writer_write(&data->writer, "ACK %s\n",
- oid_to_hex(&acks->oid[i]));
+ oid_to_hex(&acks->objects[i].item->oid));
}
if (!data->wait_for_done && ok_to_give_up(data)) {
static int process_haves_and_send_acks(struct upload_pack_data *data)
{
- struct oid_array common = OID_ARRAY_INIT;
int ret = 0;
- process_haves(data, &common);
if (data->done) {
ret = 1;
- } else if (send_acks(data, &common)) {
+ } else if (send_acks(data, &data->have_obj)) {
packet_writer_delim(&data->writer);
ret = 1;
} else {
ret = 0;
}
- oid_array_clear(&data->haves);
- oid_array_clear(&common);
return ret;
}
static void send_wanted_ref_info(struct upload_pack_data *data)
{
- const struct string_list_item *item;
+ struct hashmap_iter iter;
+ const struct strmap_entry *e;
- if (!data->wanted_refs.nr)
+ if (strmap_empty(&data->wanted_refs))
return;
packet_writer_write(&data->writer, "wanted-refs\n");
- for_each_string_list_item(item, &data->wanted_refs) {
+ strmap_for_each_entry(&data->wanted_refs, &iter, e) {
packet_writer_write(&data->writer, "%s %s\n",
- oid_to_hex(item->util),
- item->string);
+ oid_to_hex(e->value),
+ e->key);
}
packet_writer_delim(&data->writer);
FETCH_DONE,
};
-int upload_pack_v2(struct repository *r UNUSED, struct packet_reader *request)
+int upload_pack_v2(struct repository *r, struct packet_reader *request)
{
enum fetch_state state = FETCH_PROCESS_ARGS;
struct upload_pack_data data;
upload_pack_data_init(&data);
data.use_sideband = LARGE_PACKET_MAX;
- get_upload_pack_config(&data);
+ get_upload_pack_config(r, &data);
while (state != FETCH_DONE) {
switch (state) {
* they didn't want anything.
*/
state = FETCH_DONE;
- } else if (data.haves.nr) {
+ } else if (data.seen_haves) {
/*
* Request had 'have' lines, so lets ACK them.
*/
int upload_pack_advertise(struct repository *r,
struct strbuf *value)
{
- if (value) {
- int allow_filter_value;
- int allow_ref_in_want;
- int allow_sideband_all_value;
- char *str = NULL;
+ struct upload_pack_data data;
+ upload_pack_data_init(&data);
+ get_upload_pack_config(r, &data);
+
+ if (value) {
strbuf_addstr(value, "shallow wait-for-done");
- if (!repo_config_get_bool(r,
- "uploadpack.allowfilter",
- &allow_filter_value) &&
- allow_filter_value)
+ if (data.allow_filter)
strbuf_addstr(value, " filter");
- if (!repo_config_get_bool(r,
- "uploadpack.allowrefinwant",
- &allow_ref_in_want) &&
- allow_ref_in_want)
+ if (data.allow_ref_in_want)
strbuf_addstr(value, " ref-in-want");
- if (git_env_bool("GIT_TEST_SIDEBAND_ALL", 0) ||
- (!repo_config_get_bool(r,
- "uploadpack.allowsidebandall",
- &allow_sideband_all_value) &&
- allow_sideband_all_value))
+ if (data.allow_sideband_all)
strbuf_addstr(value, " sideband-all");
- if (!repo_config_get_string(r,
- "uploadpack.blobpackfileuri",
- &str) &&
- str) {
+ if (data.allow_packfile_uris)
strbuf_addstr(value, " packfile-uris");
- free(str);
- }
}
+ upload_pack_data_clear(&data);
+
return 1;
}
#include "userdiff.h"
#include "attr.h"
#include "strbuf.h"
+#include "environment.h"
static struct userdiff_driver *drivers;
static int ndrivers;
{
struct find_by_namelen_data *cb_data = priv;
- if (!strncmp(driver->name, cb_data->name, cb_data->len) &&
- !driver->name[cb_data->len]) {
+ if (!xstrncmpz(driver->name, cb_data->name, cb_data->len)) {
cb_data->driver = driver;
return 1; /* tell the caller to stop iterating */
}
if (!driver->textconv)
return NULL;
- if (driver->textconv_want_cache && !driver->textconv_cache) {
+ if (driver->textconv_want_cache && !driver->textconv_cache &&
+ have_git_dir()) {
struct notes_cache *c = xmalloc(sizeof(*c));
struct strbuf name = STRBUF_INIT;
strbuf_add_commented_lines(buf, explanation, strlen(explanation), comment_line_char);
}
-void wt_status_add_cut_line(FILE *fp)
+void wt_status_add_cut_line(struct wt_status *s)
{
struct strbuf buf = STRBUF_INIT;
+ if (s->added_cut_line)
+ return;
+ s->added_cut_line = 1;
wt_status_append_cut_line(&buf);
- fputs(buf.buf, fp);
+ fputs(buf.buf, s->fp);
strbuf_release(&buf);
}
* file (and even the "auto" setting won't work, since it
* will have checked isatty on stdout). But we then do want
* to insert the scissor line here to reliably remove the
- * diff before committing.
+ * diff before committing, if we didn't already include one
+ * before.
*/
if (s->fp != stdout) {
rev.diffopt.use_color = 0;
- wt_status_add_cut_line(s->fp);
+ wt_status_add_cut_line(s);
}
if (s->verbose > 1 && s->committable) {
/* print_updated() printed a header, so do we */
int rename_score;
int rename_limit;
enum wt_status_format status_format;
+ unsigned char added_cut_line; /* boolean */
struct wt_status_state state;
struct object_id oid_commit; /* when not Initial */
size_t wt_status_locate_end(const char *s, size_t len);
void wt_status_append_cut_line(struct strbuf *buf);
-void wt_status_add_cut_line(FILE *fp);
+void wt_status_add_cut_line(struct wt_status *s);
void wt_status_prepare(struct repository *r, struct wt_status *s);
void wt_status_print(struct wt_status *s);
void wt_status_collect(struct wt_status *s);