diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 4017ed82ca4341..c19530b086311a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,8 +1,10 @@ - - [ ] I was not able to find an [open](https://github.com/git-for-windows/git/issues?q=is%3Aopen) or [closed](https://github.com/git-for-windows/git/issues?q=is%3Aclosed) issue matching what I'm seeing + - [ ] I was not able to find an [open](https://github.com/microsoft/git/issues?q=is%3Aopen) + or [closed](https://github.com/microsoft/git/issues?q=is%3Aclosed) issue matching + what I'm seeing, including in [the `git-for-windows/git` tracker](https://github.com/git-for-windows/git/issues). ### Setup - - Which version of Git for Windows are you using? Is it 32-bit or 64-bit? + - Which version of `microsoft/git` are you using? Is it 32-bit or 64-bit? ``` $ git --version --build-options @@ -10,24 +12,22 @@ $ git --version --build-options ** insert your machine's response here ** ``` - - Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit? +Are you using Scalar or VFS for Git? + +** insert your answer here ** + +If VFS for Git, then what version? ``` -$ cmd.exe /c ver +$ gvfs version ** insert your machine's response here ** ``` - - What options did you set as part of the installation? Or did you choose the - defaults? + - Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit? ``` -# One of the following: -> type "C:\Program Files\Git\etc\install-options.txt" -> type "C:\Program Files (x86)\Git\etc\install-options.txt" -> type "%USERPROFILE%\AppData\Local\Programs\Git\etc\install-options.txt" -> type "$env:USERPROFILE\AppData\Local\Programs\Git\etc\install-options.txt" -$ cat /etc/install-options.txt +$ cmd.exe /c ver ** insert your machine's response here ** ``` @@ -58,7 +58,11 @@ $ cat /etc/install-options.txt ** insert here ** - - If the problem was occurring with a specific repository, can you provide the - URL to that repository to help us with testing? + - If the problem was occurring with a specific repository, can you specify + the repository? -** insert URL here ** + * [ ] Public repo: **insert URL here** + * [ ] Windows monorepo + * [ ] Office monorepo + * [ ] Other Microsoft-internal repo: **insert name here** + * [ ] Other internal repo. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7baf31f2c471ec..3cb48d8582f31c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,22 +1,10 @@ Thanks for taking the time to contribute to Git! -Those seeking to contribute to the Git for Windows fork should see -http://gitforwindows.org/#contribute on how to contribute Windows specific -enhancements. - -If your contribution is for the core Git functions and documentation -please be aware that the Git community does not use the github.com issues -or pull request mechanism for their contributions. - -Instead, we use the Git mailing list (git@vger.kernel.org) for code and -documentation submissions, code reviews, and bug reports. The -mailing list is plain text only (anything with HTML is sent directly -to the spam folder). - -Nevertheless, you can use GitGitGadget (https://gitgitgadget.github.io/) -to conveniently send your Pull Requests commits to our mailing list. - -For a single-commit pull request, please *leave the pull request description -empty*: your commit message itself should describe your changes. - -Please read the "guidelines for contributing" linked above! +This fork contains changes specific to monorepo scenarios. If you are an +external contributor, then please detail your reason for submitting to +this fork: + +* [ ] This is an early version of work already under review upstream. +* [ ] This change only applies to interactions with Azure DevOps and the + GVFS Protocol. +* [ ] This change only applies to the virtualization hook and VFS for Git. diff --git a/.github/actions/akv-secret/action.yml b/.github/actions/akv-secret/action.yml new file mode 100644 index 00000000000000..b9d88a7942ec6e --- /dev/null +++ b/.github/actions/akv-secret/action.yml @@ -0,0 +1,54 @@ +name: Get Azure Key Vault Secrets + +description: | + Get secrets from Azure Key Vault and store the results as masked step outputs, + environment variables, or files. + +inputs: + vault: + required: true + description: Name of the Azure Key Vault. + secrets: + required: true + description: | + Comma- or newline-separated list of secret names in Azure Key Vault. + The output and encoding of secrets can be specified using this syntax: + + SECRET ENCODING> $output:OUTPUT + SECRET ENCODING> $env:ENVAR + SECRET ENCODING> FILE + + SECRET Name of the secret in Azure Key Vault. + ENCODING (optional) Encoding of the secret: base64. + OUTPUT Name of a step output variable. + ENVAR Name of an environment variable. + FILE File path (relative or absolute). + + If no output format is specified the default is a step output variable + with the same name as the secret. I.e, SECRET > $output:SECRET. + + Examples: + + Assign output variable named `raw-var` to the raw value of the secret + `raw-secret`: + + raw-secret > $output:raw-var + + Assign output variable named `decoded-var` to the base64 decoded value + of the secret `encoded-secret`: + + encoded-secret base64> $output:decoded-var + + Download the secret named `tls-certificate` to the file path + `.certs/tls.cert`: + + tls-certificate > .certs/tls.cert + + Assign environment variable `ENV_SECRET` to the base64 decoded value of + the secret `encoded-secret`: + + encoded-secret base64> $env:ENV_SECRET + +runs: + using: node20 + main: index.js diff --git a/.github/actions/akv-secret/index.js b/.github/actions/akv-secret/index.js new file mode 100644 index 00000000000000..19a930db983b0c --- /dev/null +++ b/.github/actions/akv-secret/index.js @@ -0,0 +1,195 @@ +const { spawnSync } = require('child_process'); +const fs = require('fs'); +const os = require('os'); +const path = require('path'); +const { isUtf8 } = require("buffer"); + +// Note that we are not using the `@actions/core` package as it is not available +// without either committing node_modules/ to the repository, or using something +// like ncc to bundle the code. + +// See https://github.com/actions/toolkit/blob/%40actions/core%401.1.0/packages/core/src/command.ts#L81-L87 +const escapeData = (s) => { + return s + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') +} + +const stringify = (value) => { + if (typeof value === 'string') return value; + if (Buffer.isBuffer(value) && isUtf8(value)) return value.toString('utf-8'); + return undefined; +} + +const trimEOL = (buf) => { + let l = buf.length + if (l > 0 && buf[l - 1] === 0x0a) { + l -= l > 1 && buf[l - 2] === 0x0d ? 2 : 1 + } + return buf.slice(0, l) +} + +const writeBufToFile = (buf, file) => { + out = fs.createWriteStream(file) + out.write(buf) + out.end() +} + +const logInfo = (message) => { + process.stdout.write(`${message}${os.EOL}`); +} + +const setFailed = (error) => { + process.stdout.write(`::error::${escapeData(error.message)}${os.EOL}`); + process.exitCode = 1; +} + +const writeCommand = (file, name, value) => { + // Unique delimiter to avoid conflicts with actual values + let delim; + for (let count = 0; ; count++) { + delim = `XXXXXX${count}`; + if (!name.includes(delim) && !value.includes(delim)) { + break; + } + } + + fs.appendFileSync(file, `${name}<<${delim}${os.EOL}${value}${os.EOL}${delim}${os.EOL}`); +} + +const setSecret = (value) => { + value = stringify(value); + + // Masking a secret that is not a valid UTF-8 string or buffer is not useful + if (value === undefined) return; + + process.stdout.write( + value + .split(/\r?\n/g) + .filter(line => line.length > 0) // Cannot mask empty lines + .map( + value => `::add-mask::${escapeData(value)}${os.EOL}` + ) + .join('') + ); +} + +const setOutput = (name, value) => { + value = stringify(value); + if (value === undefined) { + throw new Error(`Output value '${name}' is not a valid UTF-8 string or buffer`); + } + + writeCommand(process.env.GITHUB_OUTPUT, name, value); +} + +const exportVariable = (name, value) => { + value = stringify(value); + if (value === undefined) { + throw new Error(`Environment variable '${name}' is not a valid UTF-8 string or buffer`); + } + + writeCommand(process.env.GITHUB_ENV, name, value); +} + +(async () => { + const vault = process.env.INPUT_VAULT; + const secrets = process.env.INPUT_SECRETS; + // Parse and normalize secret mappings + const secretMappings = secrets + .split(/[\n,]+/) + .map((entry) => entry.trim()) + .filter((entry) => entry) + .map((entry) => { + const [input, encoding, output] = entry.split(/(\S+)?>/).map((part) => part?.trim()); + return { input, encoding, output: output || `\$output:${input}` }; // Default output to $output:input if not specified + }); + + if (secretMappings.length === 0) { + throw new Error('No secrets provided.'); + } + + // Fetch secrets from Azure Key Vault + for (const { input: secretName, encoding, output } of secretMappings) { + let az = spawnSync('az', + [ + 'keyvault', + 'secret', + 'show', + '--vault-name', + vault, + '--name', + secretName, + '--query', + 'value', + '--output', + 'tsv' + ], + { + stdio: ['ignore', 'pipe', 'inherit'], + shell: true // az is a batch script on Windows + } + ); + + if (az.error) throw new Error(az.error, { cause: az.error }); + if (az.status !== 0) throw new Error(`az failed with status ${az.status}`); + + // az keyvault secret show --output tsv returns a buffer with trailing \n + // (or \r\n on Windows), so we need to trim it specifically. + let secretBuf = trimEOL(az.stdout); + + // Mask the raw secret value in logs + setSecret(secretBuf); + + // Handle encoded values if specified + // Sadly we cannot use the `--encoding` parameter of the `az keyvault + // secret (show|download)` command as the former does not support it, and + // the latter must be used with `--file` (we could use /dev/stdout on UNIX + // but not on Windows). + if (encoding) { + switch (encoding.toLowerCase()) { + case 'base64': + secretBuf = Buffer.from(secretBuf.toString('utf-8'), 'base64'); + break; + case 'ascii': + case 'utf8': + case 'utf-8': + // No need to decode the existing buffer from the az command + break; + default: + throw new Error(`Unsupported encoding: ${encoding}`); + } + + // Mask the decoded value + setSecret(secretBuf); + } + + const outputType = output.startsWith('$env:') + ? 'env' + : output.startsWith('$output:') + ? 'output' + : 'file'; + + switch (outputType) { + case 'env': + const varName = output.replace('$env:', '').trim(); + exportVariable(varName, secretBuf); + logInfo(`Secret set as environment variable: ${varName}`); + break; + + case 'output': + const outputName = output.replace('$output:', '').trim(); + setOutput(outputName, secretBuf); + logInfo(`Secret set as output variable: ${outputName}`); + break; + + case 'file': + const filePath = output.trim(); + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + writeBufToFile(secretBuf, filePath); + logInfo(`Secret written to file: ${filePath}`); + break; + } + } +})().catch(setFailed); diff --git a/.github/macos-installer/Makefile b/.github/macos-installer/Makefile new file mode 100644 index 00000000000000..6da1ec685d59ee --- /dev/null +++ b/.github/macos-installer/Makefile @@ -0,0 +1,158 @@ +SHELL := /bin/bash +SUDO := sudo +C_INCLUDE_PATH := /usr/include +CPLUS_INCLUDE_PATH := /usr/include +LD_LIBRARY_PATH := /usr/lib + +OSX_VERSION := $(shell sw_vers -productVersion) +TARGET_FLAGS := -mmacosx-version-min=$(OSX_VERSION) -DMACOSX_DEPLOYMENT_TARGET=$(OSX_VERSION) + +uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') + +ARCH_UNIV := universal +ARCH_FLAGS := -arch x86_64 -arch arm64 + +CFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS) +LDFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS) + +PREFIX := /usr/local +GIT_PREFIX := $(PREFIX)/git + +BUILD_DIR := $(GITHUB_WORKSPACE)/payload +DESTDIR := $(PWD)/stage/git-$(ARCH_UNIV)-$(VERSION) +ARTIFACTDIR := build-artifacts +SUBMAKE := $(MAKE) C_INCLUDE_PATH="$(C_INCLUDE_PATH)" CPLUS_INCLUDE_PATH="$(CPLUS_INCLUDE_PATH)" LD_LIBRARY_PATH="$(LD_LIBRARY_PATH)" TARGET_FLAGS="$(TARGET_FLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" NO_GETTEXT=1 NO_DARWIN_PORTS=1 prefix=$(GIT_PREFIX) GIT_BUILT_FROM_COMMIT="$(GIT_BUILT_FROM_COMMIT)" DESTDIR=$(DESTDIR) +CORES := $(shell bash -c "sysctl hw.ncpu | awk '{print \$$2}'") + +# Guard against environment variables +APPLE_APP_IDENTITY = +APPLE_INSTALLER_IDENTITY = +APPLE_KEYCHAIN_PROFILE = + +.PHONY: image pkg payload codesign notarize + +.SECONDARY: + +$(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV): + rm -f $(BUILD_DIR)/git-$(VERSION)/osx-installed* + mkdir -p $(DESTDIR)$(GIT_PREFIX) + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-built-keychain: + cd $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain; $(SUBMAKE) CFLAGS="$(CFLAGS) -g -O2 -Wall" + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-built: + [ -d $(DESTDIR)$(GIT_PREFIX) ] && $(SUDO) rm -rf $(DESTDIR) || echo ok + cd $(BUILD_DIR)/git-$(VERSION); $(SUBMAKE) -j $(CORES) all strip + echo "================" + echo "Dumping Linkage" + cd $(BUILD_DIR)/git-$(VERSION); ./git version + echo "====" + cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git + echo "====" + cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-http-fetch + echo "====" + cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-http-push + echo "====" + cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-remote-http + echo "====" + cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-gvfs-helper + echo "================" + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-installed-bin: $(BUILD_DIR)/git-$(VERSION)/osx-built $(BUILD_DIR)/git-$(VERSION)/osx-built-keychain + cd $(BUILD_DIR)/git-$(VERSION); $(SUBMAKE) install + cp $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain $(DESTDIR)$(GIT_PREFIX)/bin/git-credential-osxkeychain + mkdir -p $(DESTDIR)$(GIT_PREFIX)/contrib/completion + cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-completion.bash $(DESTDIR)$(GIT_PREFIX)/contrib/completion/ + cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-completion.zsh $(DESTDIR)$(GIT_PREFIX)/contrib/completion/ + cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-prompt.sh $(DESTDIR)$(GIT_PREFIX)/contrib/completion/ + # This is needed for Git-Gui, GitK + mkdir -p $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl + [ ! -f $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl/Error.pm ] && cp $(BUILD_DIR)/git-$(VERSION)/perl/private-Error.pm $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl/Error.pm || echo done + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-installed-man: $(BUILD_DIR)/git-$(VERSION)/osx-installed-bin + mkdir -p $(DESTDIR)$(GIT_PREFIX)/share/man + cp -R $(GITHUB_WORKSPACE)/manpages/ $(DESTDIR)$(GIT_PREFIX)/share/man + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-built-subtree: + $(SUBMAKE) -C $(BUILD_DIR)/git-$(VERSION)/Documentation asciidoc.conf + cd $(BUILD_DIR)/git-$(VERSION)/contrib/subtree; $(SUBMAKE) XML_CATALOG_FILES="$(XML_CATALOG_FILES)" all git-subtree.1 + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree: $(BUILD_DIR)/git-$(VERSION)/osx-built-subtree + mkdir -p $(DESTDIR) + cd $(BUILD_DIR)/git-$(VERSION)/contrib/subtree; $(SUBMAKE) XML_CATALOG_FILES="$(XML_CATALOG_FILES)" install install-man + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-installed-assets: $(BUILD_DIR)/git-$(VERSION)/osx-installed-bin + mkdir -p $(DESTDIR)$(GIT_PREFIX)/etc + cat assets/etc/gitconfig.osxkeychain >> $(DESTDIR)$(GIT_PREFIX)/etc/gitconfig + cp assets/uninstall.sh $(DESTDIR)$(GIT_PREFIX)/uninstall.sh + sh -c "echo .DS_Store >> $(DESTDIR)$(GIT_PREFIX)/share/git-core/templates/info/exclude" + +symlinks: + mkdir -p $(ARTIFACTDIR)$(PREFIX)/bin + cd $(ARTIFACTDIR)$(PREFIX)/bin; find ../git/bin -type f -exec ln -sf {} \; + for man in man1 man3 man5 man7; do mkdir -p $(ARTIFACTDIR)$(PREFIX)/share/man/$$man; (cd $(ARTIFACTDIR)$(PREFIX)/share/man/$$man; ln -sf ../../../git/share/man/$$man/* ./); done + ruby ../scripts/symlink-git-hardlinks.rb $(ARTIFACTDIR) + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-installed: $(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV) $(BUILD_DIR)/git-$(VERSION)/osx-installed-man $(BUILD_DIR)/git-$(VERSION)/osx-installed-assets $(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree + find $(DESTDIR)$(GIT_PREFIX) -type d -exec chmod ugo+rx {} \; + find $(DESTDIR)$(GIT_PREFIX) -type f -exec chmod ugo+r {} \; + touch $@ + +$(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV): $(BUILD_DIR)/git-$(VERSION)/osx-built + File $(BUILD_DIR)/git-$(VERSION)/git + File $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain + touch $@ + +disk-image/VERSION-$(VERSION)-$(ARCH_UNIV): + rm -f disk-image/*.pkg disk-image/VERSION-* disk-image/.DS_Store + mkdir disk-image + touch "$@" + +pkg_cmd := pkgbuild --identifier com.git.pkg --version $(VERSION) \ + --root $(ARTIFACTDIR)$(PREFIX) --scripts assets/scripts \ + --install-location $(PREFIX) --component-plist ./assets/git-components.plist + +ifdef APPLE_INSTALLER_IDENTITY + pkg_cmd += --sign "$(APPLE_INSTALLER_IDENTITY)" +endif + +pkg_cmd += disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg +disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg: disk-image/VERSION-$(VERSION)-$(ARCH_UNIV) symlinks + $(pkg_cmd) + +git-%-$(ARCH_UNIV).dmg: + hdiutil create git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) $(ARCH_UNIV)" -ov 2>&1 | tee err || { \ + grep "Resource busy" err && \ + sleep 5 && \ + hdiutil create git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(VERSION) $(ARCH_UNIV)" -ov; } + hdiutil convert -format UDZO -o $@ git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg + rm -f git-$(VERSION)-$(ARCH_UNIV).uncompressed.dmg + +payload: $(BUILD_DIR)/git-$(VERSION)/osx-installed $(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV) + +pkg: disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg + +image: git-$(VERSION)-$(ARCH_UNIV).dmg + +ifdef APPLE_APP_IDENTITY +codesign: + @$(CURDIR)/../scripts/codesign.sh --payload="build-artifacts/usr/local/git" \ + --identity="$(APPLE_APP_IDENTITY)" \ + --entitlements="$(CURDIR)/entitlements.xml" +endif + +# Notarization can only happen if the package is fully signed +ifdef APPLE_KEYCHAIN_PROFILE +notarize: + @$(CURDIR)/../scripts/notarize.sh \ + --package="disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg" \ + --keychain-profile="$(APPLE_KEYCHAIN_PROFILE)" +endif diff --git a/.github/macos-installer/assets/etc/gitconfig.osxkeychain b/.github/macos-installer/assets/etc/gitconfig.osxkeychain new file mode 100644 index 00000000000000..788266b3a40a9d --- /dev/null +++ b/.github/macos-installer/assets/etc/gitconfig.osxkeychain @@ -0,0 +1,2 @@ +[credential] + helper = osxkeychain diff --git a/.github/macos-installer/assets/git-components.plist b/.github/macos-installer/assets/git-components.plist new file mode 100644 index 00000000000000..78db36777df3ed --- /dev/null +++ b/.github/macos-installer/assets/git-components.plist @@ -0,0 +1,18 @@ + + + + + + BundleHasStrictIdentifier + + BundleIsRelocatable + + BundleIsVersionChecked + + BundleOverwriteAction + upgrade + RootRelativeBundlePath + git/share/git-gui/lib/Git Gui.app + + + diff --git a/.github/macos-installer/assets/scripts/postinstall b/.github/macos-installer/assets/scripts/postinstall new file mode 100755 index 00000000000000..94056db9b7b864 --- /dev/null +++ b/.github/macos-installer/assets/scripts/postinstall @@ -0,0 +1,62 @@ +#!/bin/bash +INSTALL_DST="$2" +SCALAR_C_CMD="$INSTALL_DST/git/bin/scalar" +SCALAR_DOTNET_CMD="/usr/local/scalar/scalar" +SCALAR_UNINSTALL_SCRIPT="/usr/local/scalar/uninstall_scalar.sh" + +function cleanupScalar() +{ + echo "checking whether Scalar was installed" + if [ ! -f "$SCALAR_C_CMD" ]; then + echo "Scalar not installed; exiting..." + return 0 + fi + echo "Scalar is installed!" + + echo "looking for Scalar.NET" + if [ ! -f "$SCALAR_DOTNET_CMD" ]; then + echo "Scalar.NET not found; exiting..." + return 0 + fi + echo "Scalar.NET found!" + + currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }') + + # Re-register Scalar.NET repositories with the newly-installed Scalar + for repo in $($SCALAR_DOTNET_CMD list); do + ( + PATH="$INSTALL_DST/git/bin:$PATH" + sudo -u "$currentUser" scalar register $repo || \ + echo "warning: skipping re-registration of $repo" + ) + done + + # Uninstall Scalar.NET + echo "removing Scalar.NET" + + # Add /usr/local/bin to path - default install location of Homebrew + PATH="/usr/local/bin:$PATH" + if (sudo -u "$currentUser" brew list --cask scalar); then + # Remove from Homebrew + sudo -u "$currentUser" brew remove --cask scalar || echo "warning: Scalar.NET uninstall via Homebrew completed with code $?" + echo "Scalar.NET uninstalled via Homebrew!" + elif (sudo -u "$currentUser" brew list --cask scalar-azrepos); then + sudo -u "$currentUser" brew remove --cask scalar-azrepos || echo "warning: Scalar.NET with GVFS uninstall via Homebrew completed with code $?" + echo "Scalar.NET with GVFS uninstalled via Homebrew!" + elif [ -f $SCALAR_UNINSTALL_SCRIPT ]; then + # If not installed with Homebrew, manually remove package + sudo -S sh $SCALAR_UNINSTALL_SCRIPT || echo "warning: Scalar.NET uninstall completed with code $?" + echo "Scalar.NET uninstalled!" + else + echo "warning: Scalar.NET uninstall script not found" + fi + + # Re-create the Scalar symlink, in case it was removed by the Scalar.NET uninstall operation + mkdir -p $INSTALL_DST/bin + /bin/ln -Fs "$SCALAR_C_CMD" "$INSTALL_DST/bin/scalar" +} + +# Run Scalar cleanup (will exit if not applicable) +cleanupScalar + +exit 0 \ No newline at end of file diff --git a/.github/macos-installer/assets/uninstall.sh b/.github/macos-installer/assets/uninstall.sh new file mode 100755 index 00000000000000..4fc79fbaa2e652 --- /dev/null +++ b/.github/macos-installer/assets/uninstall.sh @@ -0,0 +1,34 @@ +#!/bin/bash -e +if [ ! -r "/usr/local/git" ]; then + echo "Git doesn't appear to be installed via this installer. Aborting" + exit 1 +fi + +if [ "$1" != "--yes" ]; then + echo "This will uninstall git by removing /usr/local/git/, and symlinks" + printf "Type 'yes' if you are sure you wish to continue: " + read response +else + response="yes" +fi + +if [ "$response" == "yes" ]; then + # remove all of the symlinks we've created + pkgutil --files com.git.pkg | grep bin | while read f; do + if [ -L /usr/local/$f ]; then + sudo rm /usr/local/$f + fi + done + + # forget receipts. + pkgutil --packages | grep com.git.pkg | xargs -I {} sudo pkgutil --forget {} + echo "Uninstalled" + + # The guts all go here. + sudo rm -rf /usr/local/git/ +else + echo "Aborted" + exit 1 +fi + +exit 0 diff --git a/.github/macos-installer/entitlements.xml b/.github/macos-installer/entitlements.xml new file mode 100644 index 00000000000000..46f675661149b6 --- /dev/null +++ b/.github/macos-installer/entitlements.xml @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/.github/scripts/codesign.sh b/.github/scripts/codesign.sh new file mode 100755 index 00000000000000..076b29f93be45e --- /dev/null +++ b/.github/scripts/codesign.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +sign_directory () { + ( + cd "$1" + for f in * + do + macho=$(file --mime $f | grep mach) + # Runtime sign dylibs and Mach-O binaries + if [[ $f == *.dylib ]] || [ ! -z "$macho" ]; + then + echo "Runtime Signing $f" + codesign -s "$IDENTITY" $f --timestamp --force --options=runtime --entitlements $ENTITLEMENTS_FILE + elif [ -d "$f" ]; + then + echo "Signing files in subdirectory $f" + sign_directory "$f" + + else + echo "Signing $f" + codesign -s "$IDENTITY" $f --timestamp --force + fi + done + ) +} + +for i in "$@" +do +case "$i" in + --payload=*) + SIGN_DIR="${i#*=}" + shift # past argument=value + ;; + --identity=*) + IDENTITY="${i#*=}" + shift # past argument=value + ;; + --entitlements=*) + ENTITLEMENTS_FILE="${i#*=}" + shift # past argument=value + ;; + *) + die "unknown option '$i'" + ;; +esac +done + +if [ -z "$SIGN_DIR" ]; then + echo "error: missing directory argument" + exit 1 +elif [ -z "$IDENTITY" ]; then + echo "error: missing signing identity argument" + exit 1 +elif [ -z "$ENTITLEMENTS_FILE" ]; then + echo "error: missing entitlements file argument" + exit 1 +fi + +echo "======== INPUTS ========" +echo "Directory: $SIGN_DIR" +echo "Signing identity: $IDENTITY" +echo "Entitlements: $ENTITLEMENTS_FILE" +echo "======== END INPUTS ========" + +sign_directory "$SIGN_DIR" diff --git a/.github/scripts/notarize.sh b/.github/scripts/notarize.sh new file mode 100755 index 00000000000000..9315d688afbd49 --- /dev/null +++ b/.github/scripts/notarize.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +for i in "$@" +do +case "$i" in + --package=*) + PACKAGE="${i#*=}" + shift # past argument=value + ;; + --keychain-profile=*) + KEYCHAIN_PROFILE="${i#*=}" + shift # past argument=value + ;; + *) + die "unknown option '$i'" + ;; +esac +done + +if [ -z "$PACKAGE" ]; then + echo "error: missing package argument" + exit 1 +elif [ -z "$KEYCHAIN_PROFILE" ]; then + echo "error: missing keychain profile argument" + exit 1 +fi + +# Exit as soon as any line fails +set -e + +# Send the notarization request +xcrun notarytool submit -v "$PACKAGE" -p "$KEYCHAIN_PROFILE" --wait + +# Staple the notarization ticket (to allow offline installation) +xcrun stapler staple -v "$PACKAGE" diff --git a/.github/scripts/symlink-git-hardlinks.rb b/.github/scripts/symlink-git-hardlinks.rb new file mode 100644 index 00000000000000..174802ccc85d93 --- /dev/null +++ b/.github/scripts/symlink-git-hardlinks.rb @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby + +install_prefix = ARGV[0] +puts install_prefix +git_binary = File.join(install_prefix, '/usr/local/git/bin/git') + +[ + ['git' , File.join(install_prefix, '/usr/local/git/bin')], + ['../../bin/git', File.join(install_prefix, '/usr/local/git/libexec/git-core')] +].each do |link, path| + Dir.glob(File.join(path, '*')).each do |file| + next if file == git_binary + puts "#{file} #{File.size(file)} == #{File.size(git_binary)}" + next unless File.size(file) == File.size(git_binary) + puts "Symlinking #{file}" + puts `ln -sf #{link} #{file}` + exit $?.exitstatus if $?.exitstatus != 0 + end +end \ No newline at end of file diff --git a/.github/workflows/build-git-installers.yml b/.github/workflows/build-git-installers.yml new file mode 100644 index 00000000000000..b2ddb9ea61e97a --- /dev/null +++ b/.github/workflows/build-git-installers.yml @@ -0,0 +1,913 @@ +name: build-git-installers + +on: + push: + tags: + - 'v[0-9]*vfs*' # matches "vvfs" + +permissions: + id-token: write # required for Azure login via OIDC + +env: + DO_WIN_CODESIGN: ${{ secrets.WIN_CODESIGN_CERT_SECRET_NAME != '' && secrets.WIN_CODESIGN_PASS_SECRET_NAME != '' }} + DO_WIN_GPGSIGN: ${{ secrets.WIN_GPG_KEYGRIP_SECRET_NAME != '' && secrets.WIN_GPG_PRIVATE_SECRET_NAME != '' && secrets.WIN_GPG_PASSPHRASE_SECRET_NAME != '' }} + +jobs: + # Check prerequisites for the workflow + prereqs: + runs-on: ubuntu-latest + outputs: + tag_name: ${{ steps.tag.outputs.name }} # The full name of the tag, e.g. v2.32.0.vfs.0.0 + tag_version: ${{ steps.tag.outputs.version }} # The version number (without preceding "v"), e.g. 2.32.0.vfs.0.0 + steps: + - name: Validate tag + run: | + echo "$GITHUB_REF" | + grep -E '^refs/tags/v2\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.vfs\.0\.(0|[1-9][0-9]*)(\.rc[0-9])?$' || { + echo "::error::${GITHUB_REF#refs/tags/} is not of the form v2...vfs.0.[.rc]" >&2 + exit 1 + } + - name: Determine tag to build + run: | + echo "name=${GITHUB_REF#refs/tags/}" >>$GITHUB_OUTPUT + echo "version=${GITHUB_REF#refs/tags/v}" >>$GITHUB_OUTPUT + id: tag + - name: Clone git + uses: actions/checkout@v4 + - name: Validate the tag identified with trigger + run: | + die () { + echo "::error::$*" >&2 + exit 1 + } + + # `actions/checkout` only downloads the peeled tag (i.e. the commit) + git fetch origin +$GITHUB_REF:$GITHUB_REF + + # Verify that the tag is annotated + test $(git cat-file -t "$GITHUB_REF") == "tag" || die "Tag ${{ steps.tag.outputs.name }} is not annotated" + + # Verify tag follows rules in GIT-VERSION-GEN (i.e., matches the specified "DEF_VER" in + # GIT-VERSION-FILE) and matches tag determined from trigger + make GIT-VERSION-FILE + test "${{ steps.tag.outputs.version }}" == "$(sed -n 's/^GIT_VERSION *= *//p'< GIT-VERSION-FILE)" || die "GIT-VERSION-FILE tag ($(cat GIT-VERSION-FILE)) does not match ${{ steps.tag.outputs.name }}" + # End check prerequisites for the workflow + + # Build Windows installers (x86_64 & aarch64; installer & portable) + windows_pkg: + environment: release + needs: prereqs + strategy: + fail-fast: false + matrix: + arch: + - name: x86_64 + artifact: pkg-x86_64 + toolchain: x86_64 + mingwprefix: mingw64 + runner: windows-2019 + - name: aarch64 + artifact: pkg-aarch64 + toolchain: clang-aarch64 + mingwprefix: clangarm64 + runner: windows-11-arm + runs-on: ${{ matrix.arch.runner }} + env: + GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" + HOME: "${{github.workspace}}\\home" + USERPROFILE: "${{github.workspace}}\\home" + steps: + - name: Configure user + shell: bash + run: + USER_NAME="${{github.actor}}" && + USER_EMAIL="${{github.actor}}@users.noreply.github.com" && + mkdir -p "$HOME" && + git config --global user.name "$USER_NAME" && + git config --global user.email "$USER_EMAIL" && + echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV + - uses: git-for-windows/setup-git-for-windows-sdk@v1 + with: + flavor: build-installers + architecture: ${{ matrix.arch.name }} + - name: Clone build-extra + shell: bash + run: | + git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra + - name: Clone git + shell: bash + run: | + # Since we cannot directly clone a specified tag (as we would a branch with `git clone -b `), + # this clone has to be done manually (via init->fetch->reset). + + tag_name="${{ needs.prereqs.outputs.tag_name }}" && + git -c init.defaultBranch=main init && + git remote add -f origin https://github.com/git-for-windows/git && + git fetch "https://github.com/${{github.repository}}" refs/tags/${tag_name}:refs/tags/${tag_name} && + git reset --hard ${tag_name} + - name: Log in to Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - name: Download code signing secrets + id: codesign-secrets + if: env.DO_WIN_CODESIGN == 'true' + uses: ./.github/actions/akv-secret + with: + vault: ${{ secrets.AZURE_VAULT }} + secrets: | + ${{ secrets.WIN_CODESIGN_CERT_SECRET_NAME }} base64> home/.sig/codesign.p12 + ${{ secrets.WIN_CODESIGN_PASS_SECRET_NAME }} > home/.sig/codesign.pass + - name: Prepare home directory for code-signing + if: ${{ steps.codesign-secrets.outcome == 'success' }} + shell: bash + run: | + git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' + - name: Download GPG secrets + id: gpg-secrets + if: env.DO_WIN_GPGSIGN == 'true' + uses: ./.github/actions/akv-secret + with: + vault: ${{ secrets.AZURE_VAULT }} + secrets: | + ${{ secrets.WIN_GPG_KEYGRIP_SECRET_NAME }} > $output:keygrip + ${{ secrets.WIN_GPG_PRIVATE_SECRET_NAME }} base64> $output:private-key + ${{ secrets.WIN_GPG_PASSPHRASE_SECRET_NAME }} > $output:passphrase + - name: Prepare home directory for GPG signing + if: ${{ steps.gpg-secrets.outputs.keygrip != '' && steps.gpg-secrets.outputs.private-key != '' }} + shell: bash + run: | + # This section ensures that the identity for the GPG key matches the git user identity, otherwise + # signing will fail + + # Import the GPG private key + echo -n '${{ steps.gpg-secrets.outputs.private-key }}' | gpg $GPG_OPTIONS --import && + + info="$(gpg --list-keys --with-colons '${{ steps.gpg-secrets.outputs.keygrip }}' | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" && + git config --global user.name "${info% <*}" && + git config --global user.email "<${info#*<}" + - name: Build mingw-w64-${{matrix.arch.toolchain}}-git + shell: bash + run: | + set -x + + # Build the GPGKEY variable + export GPGKEY="${{ steps.gpg-secrets.outputs.keygrip }} --passphrase '${{ steps.gpg-secrets.outputs.passphrase }}' --yes --batch --no-tty --pinentry-mode loopback --digest-algo SHA256" && + + # Make sure that there is a `/usr/bin/git` that can be used by `makepkg-mingw` + printf '#!/bin/sh\n\nexec /${{matrix.arch.mingwprefix}}/bin/git.exe "$@"\n' >/usr/bin/git && + + sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-${{matrix.arch.name}} --build-src-pkg -o artifacts HEAD && + if test -n "${{ steps.gpg-secrets.outputs.keygrip }}" + then + for tar in artifacts/*.tar* + do + /usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor $tar + done + fi && + + b=$PWD/artifacts && + version=${{ needs.prereqs.outputs.tag_name }} && + (cd /usr/src/MINGW-packages/mingw-w64-git && + cp PKGBUILD.$version PKGBUILD && + git commit -s -m "mingw-w64-git: new version ($version)" PKGBUILD && + git bundle create "$b"/MINGW-packages.bundle origin/main..main) + - name: Publish mingw-w64-${{matrix.arch.toolchain}}-git + uses: actions/upload-artifact@v4 + with: + name: "${{ matrix.arch.artifact }}" + path: artifacts + windows_artifacts: + environment: release + needs: [prereqs, windows_pkg] + env: + HOME: "${{github.workspace}}\\home" + strategy: + fail-fast: false + matrix: + arch: + - name: x86_64 + artifact: pkg-x86_64 + toolchain: x86_64 + mingwprefix: mingw64 + runner: windows-2019 + - name: aarch64 + artifact: pkg-aarch64 + toolchain: clang-aarch64 + mingwprefix: clangarm64 + runner: windows-11-arm + type: + - name: installer + fileprefix: Git + - name: portable + fileprefix: PortableGit + runs-on: ${{ matrix.arch.runner }} + steps: + - name: Download ${{ matrix.arch.artifact }} + uses: actions/download-artifact@v4 + with: + name: ${{ matrix.arch.artifact }} + path: ${{ matrix.arch.artifact }} + - uses: git-for-windows/setup-git-for-windows-sdk@v1 + with: + flavor: build-installers + architecture: ${{ matrix.arch.name }} + - name: Clone build-extra + shell: bash + run: | + git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra + - name: Log in to Azure + uses: azure/login@v2 + if: env.DO_WIN_CODESIGN == 'true' + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - name: Check out repository (for akv-secret Action) + if: env.DO_WIN_CODESIGN == 'true' + uses: actions/checkout@v4 + with: + path: git + - name: Download code signing secrets + id: codesign-secrets + if: env.DO_WIN_CODESIGN == 'true' + uses: ./git/.github/actions/akv-secret + with: + vault: ${{ secrets.AZURE_VAULT }} + secrets: | + ${{ secrets.WIN_CODESIGN_CERT_SECRET_NAME }} base64> home/.sig/codesign.p12 + ${{ secrets.WIN_CODESIGN_PASS_SECRET_NAME }} > home/.sig/codesign.pass + - name: Prepare home directory for code-signing + if: ${{ steps.codesign-secrets.outcome == 'success' }} + shell: bash + run: | + git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' + - name: Retarget auto-update to microsoft/git + shell: bash + run: | + set -x + + b=/usr/src/build-extra && + + filename=$b/git-update-git-for-windows.config + tr % '\t' >$filename <<-\EOF && + [update] + %fromFork = microsoft/git + EOF + + sed -i -e '/^#include "file-list.iss"/a\ + Source: {#SourcePath}\\..\\git-update-git-for-windows.config; DestDir: {app}\\${{matrix.arch.mingwprefix}}\\bin; Flags: replacesameversion; AfterInstall: DeleteFromVirtualStore' \ + -e '/^Type: dirifempty; Name: {app}\\{#MINGW_BITNESS}$/i\ + Type: files; Name: {app}\\{#MINGW_BITNESS}\\bin\\git-update-git-for-windows.config\ + Type: dirifempty; Name: {app}\\{#MINGW_BITNESS}\\bin' \ + $b/installer/install.iss + - name: Set alerts to continue until upgrade is taken + shell: bash + run: | + set -x + + b=/${{matrix.arch.mingwprefix}}/bin && + + sed -i -e '6 a use_recently_seen=no' \ + $b/git-update-git-for-windows + - name: Set the installer Publisher to the Git Client team + shell: bash + run: | + b=/usr/src/build-extra && + sed -i -e 's/^\(AppPublisher=\).*/\1The Git Client Team at Microsoft/' $b/installer/install.iss + - name: Let the installer configure Visual Studio to use the installed Git + shell: bash + run: | + set -x + + b=/usr/src/build-extra && + + sed -i "# First, find the autoupdater parts in the install/uninstall steps + /if IsComponentInstalled('autoupdate')/{ + # slurp in the next two lines, where the call to InstallAutoUpdater()/UninstallAutoUpdater() happens + N + N + # insert the corresponding CustomPostInstall()/CustomPostUninstall() call before that block + s/^\\([ \t]*\\)\(.*\\)\\(Install\\|Uninstall\\)\\(AutoUpdater\\)/\\1CustomPost\\3();\\n\\1\\2\\3\\4/ + }" $b/installer/install.iss && + grep CustomPostInstall $b/installer/install.iss && + grep CustomPostUninstall $b/installer/install.iss && + + cat >>$b/installer/helpers.inc.iss <<\EOF + + procedure CustomPostInstall(); + begin + if not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\15.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\16.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\17.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\18.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\19.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or + not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\20.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) then + LogError('Could not register TeamFoundation\GitSourceControl'); + end; + + procedure CustomPostUninstall(); + begin + if not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\15.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\16.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\17.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\18.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\19.0\TeamFoundation\GitSourceControl','GitPath') or + not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\20.0\TeamFoundation\GitSourceControl','GitPath') then + LogError('Could not register TeamFoundation\GitSourceControl'); + end; + EOF + - name: Enable Scalar/C and the auto-updater in the installer by default + shell: bash + run: | + set -x + + b=/usr/src/build-extra && + + sed -i -e "/ChosenOptions:=''/a\\ + if (ExpandConstant('{param:components|/}')='/') then begin\n\ + WizardSelectComponents('autoupdate');\n\ + #ifdef WITH_SCALAR\n\ + WizardSelectComponents('scalar');\n\ + #endif\n\ + end;" $b/installer/install.iss + - name: Build ${{matrix.type.name}} (${{matrix.arch.name}}) + shell: bash + run: | + set -x + + # Copy the PDB archive to the directory where `--include-pdbs` expects it + b=/usr/src/build-extra && + mkdir -p $b/cached-source-packages && + cp ${{matrix.arch.artifact}}/*-pdb* $b/cached-source-packages/ && + + # Build the installer, embedding PDBs + eval $b/please.sh make_installers_from_mingw_w64_git --include-pdbs \ + --version=${{ needs.prereqs.outputs.tag_version }} \ + -o artifacts --${{matrix.type.name}} \ + --pkg=${{matrix.arch.artifact}}/mingw-w64-${{matrix.arch.toolchain}}-git-[0-9]*.tar.xz \ + --pkg=${{matrix.arch.artifact}}/mingw-w64-${{matrix.arch.toolchain}}-git-doc-html-[0-9]*.tar.xz && + + if test portable = '${{matrix.type.name}}' && test -n "$(git config alias.signtool)" + then + git signtool artifacts/PortableGit-*.exe + fi && + openssl dgst -sha256 artifacts/${{matrix.type.fileprefix}}-*.exe | sed "s/.* //" >artifacts/sha-256.txt + - name: Verify that .exe files are code-signed + if: env.DO_WIN_CODESIGN == 'true' + shell: pwsh + run: | + $ret = 0 + $files = Get-ChildItem -Path artifacts -Filter "${{matrix.type.fileprefix}}-*.exe" + foreach ($file in $files) { + $signature = Get-AuthenticodeSignature -FilePath $file.FullName + if ($signature.Status -eq 'Valid') { + Write-Host "[ VALID ] $($file.FullName)" + } else { + Write-Host "[INVALID] $($file.FullName)" + Write-Host " Message: $($signature.StatusMessage)" + $ret = 1 + } + } + exit $ret + - name: Publish ${{matrix.type.name}}-${{matrix.arch.name}} + uses: actions/upload-artifact@v4 + with: + name: win-${{matrix.type.name}}-${{matrix.arch.name}} + path: artifacts + # End build Windows installers + + # Build and sign Mac OSX installers & upload artifacts + create-macos-artifacts: + runs-on: macos-latest-xl-arm64 + needs: prereqs + env: + VERSION: "${{ needs.prereqs.outputs.tag_version }}" + environment: release + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + path: git + + - name: Install Git dependencies + run: | + set -ex + + # Install x86_64 packages + arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + arch -x86_64 /usr/local/bin/brew install gettext + + # Install arm64 packages + brew install automake asciidoc xmlto docbook + brew link --force gettext + + # Make universal gettext library + lipo -create -output libintl.a /usr/local/opt/gettext/lib/libintl.a /opt/homebrew/opt/gettext/lib/libintl.a + + - name: Log in to Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Download signing secrets + id: signing-secrets + uses: ./git/.github/actions/akv-secret + with: + vault: ${{ secrets.AZURE_VAULT }} + secrets: | + ${{ secrets.APPLE_APPSIGN_ID_SECRET_NAME }} > $output:appsign-id + ${{ secrets.APPLE_INSTSIGN_ID_SECRET_NAME }} > $output:instsign-id + ${{ secrets.APPLE_TEAM_ID_SECRET_NAME }} > $output:team-id + ${{ secrets.APPLE_DEVELOPER_ID_SECRET_NAME }} > $output:dev-id + ${{ secrets.APPLE_DEVELOPER_PASSWORD_SECRET_NAME }} > $output:dev-pass + ${{ secrets.APPLE_APPCERT_PASS_SECRET_NAME }} > $output:appcert-pass + ${{ secrets.APPLE_INSTCERT_PASS_SECRET_NAME }} > $output:instcert-pass + ${{ secrets.APPLE_APPCERT_SECRET_NAME }} base64> ${{ runner.temp }}/appcert.p12 + ${{ secrets.APPLE_INSTCERT_SECRET_NAME }} base64> ${{ runner.temp }}/instcert.p12 + + - name: Set up signing/notarization infrastructure + run: | + echo "Setting up signing certificates" + security create-keychain -p pwd $RUNNER_TEMP/buildagent.keychain + security default-keychain -s $RUNNER_TEMP/buildagent.keychain + security unlock-keychain -p pwd $RUNNER_TEMP/buildagent.keychain + # Prevent re-locking + security set-keychain-settings $RUNNER_TEMP/buildagent.keychain + + security import $RUNNER_TEMP/appcert.p12 \ + -k $RUNNER_TEMP/buildagent.keychain \ + -P '${{ steps.signing-secrets.outputs.appcert-pass }}' \ + -T /usr/bin/codesign + security set-key-partition-list \ + -S apple-tool:,apple:,codesign: \ + -s -k pwd \ + $RUNNER_TEMP/buildagent.keychain + + security import $RUNNER_TEMP/instcert.p12 \ + -k $RUNNER_TEMP/buildagent.keychain \ + -P '${{ steps.signing-secrets.outputs.instcert-pass }}' \ + -T /usr/bin/pkgbuild + security set-key-partition-list \ + -S apple-tool:,apple:,pkgbuild: \ + -s -k pwd \ + $RUNNER_TEMP/buildagent.keychain + + echo "Setting up notarytool" + xcrun notarytool store-credentials \ + --team-id '${{ steps.signing-secrets.outputs.team-id }}' \ + --apple-id '${{ steps.signing-secrets.outputs.dev-id }}' \ + --password '${{ steps.signing-secrets.outputs.dev-pass }}' \ + "msftgit" + + - name: Build, sign, and notarize artifacts + run: | + die () { + echo "$*" >&2 + exit 1 + } + + # Trace execution, stop on error + set -ex + + # Write to "version" file to force match with trigger payload version + echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version + + # Configure universal build + cat >git/config.mak <>git/config.mak <>git/config.mak <>git/config.mak + + # To make use of the catalogs... + export XML_CATALOG_FILES=$homebrew_prefix/etc/xml/catalog + + make -C git -j$(sysctl -n hw.physicalcpu) GIT-VERSION-FILE dist dist-doc + + export GIT_BUILT_FROM_COMMIT=$(gunzip -c git/git-$VERSION.tar.gz | git get-tar-commit-id) || + die "Could not determine commit for build" + + # Extract tarballs + mkdir payload manpages + tar -xvf git/git-$VERSION.tar.gz -C payload + tar -xvf git/git-manpages-$VERSION.tar.gz -C manpages + + # Lay out payload + cp git/config.mak payload/git-$VERSION/config.mak + make -C git/.github/macos-installer V=1 payload + + # Codesign payload + cp -R stage/git-universal-$VERSION/ \ + git/.github/macos-installer/build-artifacts + make -C git/.github/macos-installer V=1 codesign \ + APPLE_APP_IDENTITY='${{ steps.signing-secrets.outputs.appsign-id }}' || die "Creating signed payload failed" + + # Build and sign pkg + make -C git/.github/macos-installer V=1 pkg \ + APPLE_INSTALLER_IDENTITY='${{ steps.signing-secrets.outputs.instsign-id }}' \ + || die "Creating signed pkg failed" + + # Notarize pkg + make -C git/.github/macos-installer V=1 notarize \ + APPLE_INSTALLER_IDENTITY='${{ steps.signing-secrets.outputs.instsign-id }}' \ + APPLE_KEYCHAIN_PROFILE="msftgit" \ + || die "Creating signed and notarized pkg failed" + + # Create DMG + make -C git/.github/macos-installer V=1 image || die "Creating DMG failed" + + # Move all artifacts into top-level directory + mv git/.github/macos-installer/disk-image/*.pkg git/.github/macos-installer/ + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-artifacts + path: | + git/.github/macos-installer/*.dmg + git/.github/macos-installer/*.pkg + # End build and sign Mac OSX installers + + # Build and sign Debian package + create-linux-unsigned-artifacts: + runs-on: ubuntu-latest + container: + image: ubuntu:20.04 # security support until 04/02/2025, according to https://endoflife.date/ubuntu + volumes: + # override /__e/node20 because GitHub Actions uses a version that requires too-recent glibc, see "Install dependencies" below + - /tmp:/__e/node20 + needs: prereqs + steps: + - name: Install dependencies + run: | + set -ex + + # Prevent the dialog that asks interactively for the timezone + export DEBIAN_FRONTEND=noninteractive + export TZ=Etc/UTC + + apt-get update -q + apt-get install -y -q --no-install-recommends \ + build-essential \ + tcl tk gettext asciidoc xmlto \ + libcurl4-gnutls-dev libpcre2-dev zlib1g-dev libexpat-dev \ + curl ca-certificates + + # Install a Node.js version that works in older Ubuntu containers (read: does not require very recent glibc) + NODE_VERSION=v20.18.1 && + NODE_URL=https://unofficial-builds.nodejs.org/download/release/$NODE_VERSION/node-$NODE_VERSION-linux-x64-glibc-217.tar.gz && + curl -Lo /tmp/node.tar.gz $NODE_URL && + tar -C /__e/node20 -x --strip-components=1 -f /tmp/node.tar.gz + + - name: Clone git + uses: actions/checkout@v4 + with: + path: git + + - name: Build and create Debian package + run: | + set -ex + + die () { + echo "$*" >&2 + exit 1 + } + + echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version + make -C git GIT-VERSION-FILE + + VERSION="${{ needs.prereqs.outputs.tag_version }}" + + ARCH="$(dpkg-architecture -q DEB_HOST_ARCH)" + if test -z "$ARCH"; then + die "Could not determine host architecture!" + fi + + PKGNAME="microsoft-git_$VERSION" + PKGDIR="$(dirname $(pwd))/$PKGNAME" + + rm -rf "$PKGDIR" + mkdir -p "$PKGDIR" + + DESTDIR="$PKGDIR" make -C git -j5 V=1 DEVELOPER=1 \ + USE_LIBPCRE=1 \ + USE_CURL_FOR_IMAP_SEND=1 NO_OPENSSL=1 \ + NO_CROSS_DIRECTORY_HARDLINKS=1 \ + ASCIIDOC8=1 ASCIIDOC_NO_ROFF=1 \ + ASCIIDOC='TZ=UTC asciidoc' \ + prefix=/usr/local \ + gitexecdir=/usr/local/lib/git-core \ + libexecdir=/usr/local/lib/git-core \ + htmldir=/usr/local/share/doc/git/html \ + install install-doc install-html + + cd .. + mkdir "$PKGNAME/DEBIAN" + + # Based on https://packages.ubuntu.com/xenial/vcs/git + cat >"$PKGNAME/DEBIAN/control" < + Description: Git client built from the https://github.com/microsoft/git repository, + specialized in supporting monorepo scenarios. Includes the Scalar CLI. + EOF + + dpkg-deb -Zxz --build "$PKGNAME" + # Move Debian package for later artifact upload + mv "$PKGNAME.deb" "$GITHUB_WORKSPACE" + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: linux-unsigned-artifacts + path: | + *.deb + + create-linux-artifacts: + runs-on: ubuntu-latest + needs: [prereqs, create-linux-unsigned-artifacts] + environment: release + steps: + - name: Log into Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Check out repository (for akv-secret Action) + uses: actions/checkout@v4 + with: + path: git + + - name: Download GPG secrets + id: gpg-secrets + uses: ./git/.github/actions/akv-secret + with: + vault: ${{ secrets.AZURE_VAULT }} + secrets: | + ${{ secrets.LINUX_GPG_KEYGRIP_SECRET_NAME }} > $output:keygrip + ${{ secrets.LINUX_GPG_PRIVATE_SECRET_NAME }} base64> $output:private-key + ${{ secrets.LINUX_GPG_PASSPHRASE_SECRET_NAME }} > $output:passphrase + + - name: Prepare for GPG signing + run: | + # Install debsigs + sudo apt-get install -y debsigs + + # Import GPG key + echo -n '${{ steps.gpg-secrets.outputs.private-key }}' | gpg --import --no-tty --batch --yes + + # Configure GPG + echo "allow-preset-passphrase" > ~/.gnupg/gpg-agent.conf + gpg-connect-agent RELOADAGENT /bye + /usr/lib/gnupg2/gpg-preset-passphrase --preset '${{ steps.gpg-secrets.outputs.keygrip }}' <<<'${{ steps.gpg-secrets.outputs.passphrase }}' + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: linux-unsigned-artifacts + + - name: Sign Debian package + run: | + # Sign Debian package + version="${{ needs.prereqs.outputs.tag_version }}" + debsigs --sign=origin --verify --check microsoft-git_"$version".deb + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: linux-artifacts + path: | + *.deb + # End build and sign Debian package + + # Validate installers + validate-installers: + name: Validate installers + strategy: + matrix: + component: + - os: ubuntu-latest + artifact: linux-artifacts + command: git + - os: macos-latest-xl-arm64 + artifact: macos-artifacts + command: git + - os: macos-latest + artifact: macos-artifacts + command: git + - os: windows-latest + artifact: win-installer-x86_64 + command: $PROGRAMFILES\Git\cmd\git.exe + - os: windows-11-arm + artifact: win-installer-aarch64 + command: $PROGRAMFILES\Git\cmd\git.exe + runs-on: ${{ matrix.component.os }} + needs: [prereqs, windows_artifacts, create-macos-artifacts, create-linux-artifacts] + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ matrix.component.artifact }} + + - name: Install Windows + if: contains(matrix.component.artifact, 'win-installer') + shell: pwsh + run: | + $exePath = Get-ChildItem -Path ./*.exe | %{$_.FullName} + Start-Process -Wait -FilePath "$exePath" -ArgumentList "/SILENT /VERYSILENT /NORESTART /SUPPRESSMSGBOXES /ALLOWDOWNGRADE=1" + + - name: Install Linux + if: contains(matrix.component.artifact, 'linux') + run: | + debpath=$(find ./*.deb) + sudo apt install $debpath + + - name: Install macOS + if: contains(matrix.component.artifact, 'macos') + run: | + # avoid letting Homebrew's `git` in `/opt/homebrew/bin` override `/usr/local/bin/git` + arch="$(uname -m)" + test arm64 != "$arch" || + brew uninstall git + + pkgpath=$(find ./*universal*.pkg) + sudo installer -pkg $pkgpath -target / + + - name: Validate + shell: bash + run: | + "${{ matrix.component.command }}" --version | sed 's/git version //' >actual + echo ${{ needs.prereqs.outputs.tag_version }} >expect + cmp expect actual || exit 1 + + - name: Validate universal binary CPU architecture + if: contains(matrix.component.os, 'macos') + shell: bash + run: | + set -ex + git version --build-options >actual + cat actual + grep "cpu: $(uname -m)" actual + # End validate installers + + create-github-release: + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write # required for Azure login via OIDC + needs: + - validate-installers + - create-linux-artifacts + - create-macos-artifacts + - windows_artifacts + - prereqs + environment: release + if: | + success() || + (needs.create-linux-artifacts.result == 'skipped' && + needs.create-macos-artifacts.result == 'success' && + needs.windows_artifacts.result == 'success') + steps: + - name: Download Windows portable (x86_64) + uses: actions/download-artifact@v4 + with: + name: win-portable-x86_64 + path: win-portable-x86_64 + + - name: Download Windows portable (aarch64) + uses: actions/download-artifact@v4 + with: + name: win-portable-aarch64 + path: win-portable-aarch64 + + - name: Download Windows installer (x86_64) + uses: actions/download-artifact@v4 + with: + name: win-installer-x86_64 + path: win-installer-x86_64 + + - name: Download Windows installer (aarch64) + uses: actions/download-artifact@v4 + with: + name: win-installer-aarch64 + path: win-installer-aarch64 + + - name: Download macOS artifacts + uses: actions/download-artifact@v4 + with: + name: macos-artifacts + path: macos-artifacts + + - name: Download Debian package + uses: actions/download-artifact@v4 + with: + name: linux-artifacts + path: deb-package + + - name: Log into Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Check out repository (for akv-secret Action) + uses: actions/checkout@v4 + with: + path: git + + - name: Download Linux GPG public key signature file + uses: ./git/.github/actions/akv-secret + with: + vault: ${{ secrets.AZURE_VAULT }} + secrets: | + ${{ secrets.LINUX_GPG_PUBLIC_SECRET_NAME }} base64> deb-package/msft-git-public.asc + + - uses: actions/github-script@v6 + with: + script: | + const fs = require('fs'); + const path = require('path'); + + var releaseMetadata = { + owner: context.repo.owner, + repo: context.repo.repo + }; + + // Create the release + var tagName = "${{ needs.prereqs.outputs.tag_name }}"; + var createdRelease = await github.rest.repos.createRelease({ + ...releaseMetadata, + draft: true, + tag_name: tagName, + name: tagName + }); + releaseMetadata.release_id = createdRelease.data.id; + + // Uploads contents of directory to the release created above + async function uploadDirectoryToRelease(directory, includeExtensions=[]) { + return fs.promises.readdir(directory) + .then(async(files) => Promise.all( + files.filter(file => { + return includeExtensions.length==0 || includeExtensions.includes(path.extname(file).toLowerCase()); + }) + .map(async (file) => { + var filePath = path.join(directory, file); + github.rest.repos.uploadReleaseAsset({ + ...releaseMetadata, + name: file, + headers: { + "content-length": (await fs.promises.stat(filePath)).size + }, + data: fs.createReadStream(filePath) + }); + })) + ); + } + + await Promise.all([ + // Upload Windows x86_64 artifacts + uploadDirectoryToRelease('win-installer-x86_64', ['.exe']), + uploadDirectoryToRelease('win-portable-x86_64', ['.exe']), + + // Upload Windows aarch64 artifacts + uploadDirectoryToRelease('win-installer-aarch64', ['.exe']), + uploadDirectoryToRelease('win-portable-aarch64', ['.exe']), + + // Upload Mac artifacts + uploadDirectoryToRelease('macos-artifacts'), + + // Upload Ubuntu artifacts + uploadDirectoryToRelease('deb-package') + ]); diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 124301dbbe2fc1..01a0437b2f2634 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -147,9 +147,13 @@ jobs: key: cov-build-${{ env.COVERITY_LANGUAGE }}-${{ env.COVERITY_PLATFORM }}-${{ steps.lookup.outputs.hash }} - name: build with cov-build run: | - export PATH="$RUNNER_TEMP/cov-analysis/bin:$PATH" && + export PATH="$PATH:$RUNNER_TEMP/cov-analysis/bin" && cov-configure --gcc && - cov-build --dir cov-int make + if ! cov-build --dir cov-int make + then + cat cov-int/build-log.txt + exit 1 + fi - name: package the build run: tar -czvf cov-int.tgz cov-int - name: submit the build to Coverity Scan diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 14e598bac16818..f5bb5d9b9bc898 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -164,7 +164,7 @@ jobs: vs-build: name: win+VS build needs: ci-config - if: github.event.repository.owner.login == 'git-for-windows' && needs.ci-config.outputs.enabled == 'yes' + if: github.event.repository.owner.login == 'microsoft' && needs.ci-config.outputs.enabled == 'yes' env: NO_PERL: 1 GIT_CONFIG_PARAMETERS: "'user.name=CI' 'user.email=ci@git'" diff --git a/.github/workflows/monitor-components.yml b/.github/workflows/monitor-components.yml deleted file mode 100644 index 65d212ba194699..00000000000000 --- a/.github/workflows/monitor-components.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: Monitor component updates - -# Git for Windows is a slightly modified subset of MSYS2. Some of its -# components are maintained by Git for Windows, others by MSYS2. To help -# keeping the former up to date, this workflow monitors the Atom/RSS feeds -# and opens new tickets for each new component version. - -on: - schedule: - - cron: "23 8,11,14,17 * * *" - workflow_dispatch: - -env: - CHARACTER_LIMIT: 5000 - MAX_AGE: 7d - -jobs: - job: - # Only run this in Git for Windows' fork - if: github.event.repository.owner.login == 'git-for-windows' - runs-on: ubuntu-latest - permissions: - issues: write - strategy: - matrix: - component: - - label: git - feed: https://github.com/git/git/tags.atom - - label: git-lfs - feed: https://github.com/git-lfs/git-lfs/tags.atom - - label: git-credential-manager - feed: https://github.com/git-ecosystem/git-credential-manager/tags.atom - - label: tig - feed: https://github.com/jonas/tig/tags.atom - - label: cygwin - feed: https://github.com/cygwin/cygwin/releases.atom - title-pattern: ^(?!.*newlib) - - label: msys2-runtime-package - feed: https://github.com/msys2/MSYS2-packages/commits/master/msys2-runtime.atom - - label: msys2-runtime - feed: https://github.com/msys2/msys2-runtime/commits/HEAD.atom - aggregate: true - - label: openssh - feed: https://github.com/openssh/openssh-portable/tags.atom - - label: libfido2 - feed: https://github.com/Yubico/libfido2/tags.atom - - label: libcbor - feed: https://github.com/PJK/libcbor/tags.atom - - label: openssl - feed: https://github.com/openssl/openssl/tags.atom - title-pattern: ^(?!.*alpha) - - label: gnutls - feed: https://gnutls.org/news.atom - - label: heimdal - feed: https://github.com/heimdal/heimdal/tags.atom - - label: git-sizer - feed: https://github.com/github/git-sizer/tags.atom - - label: gitflow - feed: https://github.com/petervanderdoes/gitflow-avh/tags.atom - - label: curl - feed: https://github.com/curl/curl/tags.atom - title-pattern: ^(?!rc-) - - label: libgpg-error - feed: https://github.com/gpg/libgpg-error/releases.atom - title-pattern: ^libgpg-error-[0-9\.]*$ - - label: libgcrypt - feed: https://github.com/gpg/libgcrypt/releases.atom - title-pattern: ^libgcrypt-[0-9\.]*$ - - label: gpg - feed: https://github.com/gpg/gnupg/releases.atom - # As per https://gnupg.org/download/index.html#sec-1-1, the stable - # versions are the one with an even minor version number. - title-pattern: ^gnupg-\d+\.\d*[02468]\. - - label: mintty - feed: https://github.com/mintty/mintty/releases.atom - - label: 7-zip - feed: https://sourceforge.net/projects/sevenzip/rss?path=/7-Zip - aggregate: true - - label: bash - feed: https://git.savannah.gnu.org/cgit/bash.git/atom/?h=master - aggregate: true - - label: perl - feed: https://github.com/Perl/perl5/tags.atom - title-pattern: ^(?!.*(5\.[0-9]+[13579]|RC)) - - label: pcre2 - feed: https://github.com/PCRE2Project/pcre2/tags.atom - - label: mingw-w64-llvm - feed: https://github.com/msys2/MINGW-packages/commits/master/mingw-w64-llvm.atom - - label: innosetup - feed: https://github.com/jrsoftware/issrc/tags.atom - fail-fast: false - steps: - - uses: git-for-windows/rss-to-issues@v0 - with: - feed: ${{matrix.component.feed}} - prefix: "[New ${{matrix.component.label}} version]" - labels: component-update - github-token: ${{ secrets.GITHUB_TOKEN }} - character-limit: ${{ env.CHARACTER_LIMIT }} - max-age: ${{ env.MAX_AGE }} - aggregate: ${{matrix.component.aggregate}} - title-pattern: ${{matrix.component.title-pattern}} diff --git a/.github/workflows/release-homebrew.yml b/.github/workflows/release-homebrew.yml new file mode 100644 index 00000000000000..e00b90d8c07579 --- /dev/null +++ b/.github/workflows/release-homebrew.yml @@ -0,0 +1,51 @@ +name: Update Homebrew Tap +on: + release: + types: [released] + +permissions: + id-token: write # required for Azure login via OIDC + +jobs: + release: + runs-on: ubuntu-latest + environment: release + steps: + - id: version + name: Compute version number + run: | + echo "result=$(echo $GITHUB_REF | sed -e "s/^refs\/tags\/v//")" >>$GITHUB_OUTPUT + - id: hash + name: Compute release asset hash + uses: mjcheetham/asset-hash@v1.1 + with: + asset: /git-(.*)\.pkg/ + hash: sha256 + token: ${{ secrets.GITHUB_TOKEN }} + - name: Log into Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + - name: Retrieve token + id: token + run: | + az keyvault secret show \ + --name ${{ secrets.HOMEBREW_TOKEN_SECRET_NAME }} \ + --vault-name ${{ secrets.AZURE_VAULT }} \ + --query "value" -o tsv >token && + # avoid outputting the token under `set -x` by using `sed` instead of `echo` + sed s/^/::add-mask::/ >$GITHUB_OUTPUT && + rm token + - name: Update scalar Cask + uses: mjcheetham/update-homebrew@v1.4 + with: + token: ${{ steps.token.outputs.result }} + tap: microsoft/git + name: microsoft-git + type: cask + version: ${{ steps.version.outputs.result }} + sha256: ${{ steps.hash.outputs.result }} + alwaysUsePullRequest: false diff --git a/.github/workflows/release-winget.yml b/.github/workflows/release-winget.yml new file mode 100644 index 00000000000000..80d5cd828f4106 --- /dev/null +++ b/.github/workflows/release-winget.yml @@ -0,0 +1,82 @@ +name: "release-winget" +on: + release: + types: [released] + + workflow_dispatch: + inputs: + tag: + description: 'Tag name to release' + required: true + +permissions: + id-token: write # required for Azure login via OIDC + +env: + TAG_NAME: ${{ github.event.inputs.tag }} + +jobs: + release: + runs-on: windows-latest + environment: release + steps: + - name: Log into Azure + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Publish manifest with winget-create + run: | + # Enabling stop on error and tracing + Set-PSDebug -Trace 2 + $ErrorActionPreference = "Stop" + $PSNativeCommandErrorActionPreference = "Stop" + + if ($env:TAG_NAME -eq "") { + # Get latest release + $github = Get-Content '${{ github.event_path }}' | ConvertFrom-Json + + # Set the tag name environment variable + $env:TAG_NAME = $github.release.tag_name + + # Get download URLs + $asset_x64 = $github.release.assets | Where-Object -Property name -match '64-bit.exe$' + $asset_arm64 = $github.release.assets | Where-Object -Property name -match 'arm64.exe$' + $asset_x64_url = $asset_x64.browser_download_url + $asset_arm64_url = $asset_arm64.browser_download_url + } else { + # Get release object by its tag + $env:GH_TOKEN = ${{ toJson(secrets.GITHUB_TOKEN) }} + $github = (gh release view -R microsoft/git $env:TAG_NAME --json tagName,assets --jq '{tag_name: .tagName, assets: .assets}') | ConvertFrom-Json + + # Get download URLs + $asset_x64 = $github.assets | Where-Object -Property name -match '64-bit.exe$' + $asset_arm64 = $github.assets | Where-Object -Property name -match 'arm64.exe$' + $asset_x64_url = $asset_x64.url + $asset_arm64_url = $asset_arm64.url + } + + # Remove 'v' and 'vfs' from the version + $env:TAG_NAME -match 'v(.*?)vfs\.(.*)' + $version = $Matches[1] + $Matches[2] + + # Download wingetcreate and create manifests + Invoke-WebRequest https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe + .\wingetcreate.exe update Microsoft.Git ` + -v $version ` + -o . ` + -u "$($asset_x64_url)|x64|machine" ` + "$($asset_x64_url)|x64|user" ` + "$($asset_arm64_url)|arm64|machine" ` + "$($asset_arm64_url)|arm64|user" + + # Download the token from Azure Key Vault and mask it in the logs + az keyvault secret download --name ${{ secrets.WINGET_TOKEN_SECRET_NAME }} --vault-name ${{ secrets.AZURE_VAULT }} --file token.txt + Write-Host -NoNewLine "::add-mask::$(Get-Content token.txt)" + + # Submit the manifest to the winget-pkgs repository + $manifestDirectory = "$PWD\manifests\m\Microsoft\Git\$version" + .\wingetcreate.exe submit -t "$(Get-Content token.txt)" $manifestDirectory + shell: powershell diff --git a/.github/workflows/scalar-functional-tests.yml b/.github/workflows/scalar-functional-tests.yml new file mode 100644 index 00000000000000..2050d8ff7eb6aa --- /dev/null +++ b/.github/workflows/scalar-functional-tests.yml @@ -0,0 +1,218 @@ +name: Scalar Functional Tests + +env: + SCALAR_REPOSITORY: microsoft/scalar + SCALAR_REF: main + DEBUG_WITH_TMATE: false + SCALAR_TEST_SKIP_VSTS_INFO: true + +on: + push: + branches: [ vfs-*, tentative/vfs-* ] + pull_request: + branches: [ vfs-*, features/* ] + +jobs: + scalar: + name: "Scalar Functional Tests" + + strategy: + fail-fast: false + matrix: + # Order by runtime (in descending order) + os: [windows-2019, macos-13, ubuntu-22.04] + # Scalar.NET used to be tested using `features: [false, experimental]` + # But currently, Scalar/C ignores `feature.scalar` altogether, so let's + # save some electrons and run only one of them... + features: [ignored] + exclude: + # The built-in FSMonitor is not (yet) supported on Linux + - os: ubuntu-22.04 + features: experimental + runs-on: ${{ matrix.os }} + + env: + BUILD_FRAGMENT: bin/Release/netcoreapp3.1 + GIT_FORCE_UNTRACKED_CACHE: 1 + + steps: + - name: Check out Git's source code + uses: actions/checkout@v4 + + - name: Setup build tools on Windows + if: runner.os == 'Windows' + uses: git-for-windows/setup-git-for-windows-sdk@v1 + + - name: Provide a minimal `install` on Windows + if: runner.os == 'Windows' + shell: bash + run: | + test -x /usr/bin/install || + tr % '\t' >/usr/bin/install <<-\EOF + #!/bin/sh + + cmd=cp + while test $# != 0 + do + %case "$1" in + %-d) cmd="mkdir -p";; + %-m) shift;; # ignore mode + %*) break;; + %esac + %shift + done + + exec $cmd "$@" + EOF + + - name: Install build dependencies for Git (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get -q -y install libssl-dev libcurl4-openssl-dev gettext + + - name: Build and install Git + shell: bash + env: + NO_TCLTK: Yup + run: | + # We do require a VFS version + def_ver="$(sed -n 's/DEF_VER=\(.*vfs.*\)/\1/p' GIT-VERSION-GEN)" + test -n "$def_ver" + + # Ensure that `git version` reflects DEF_VER + case "$(git describe --match "v[0-9]*vfs*" HEAD)" in + ${def_ver%%.vfs.*}.vfs.*) ;; # okay, we can use this + *) git -c user.name=ci -c user.email=ci@github tag -m for-testing ${def_ver}.NNN.g$(git rev-parse --short HEAD);; + esac + + SUDO= + extra= + case "${{ runner.os }}" in + Windows) + extra=DESTDIR=/c/Progra~1/Git + cygpath -aw "/c/Program Files/Git/cmd" >>$GITHUB_PATH + ;; + Linux) + SUDO=sudo + extra=prefix=/usr + ;; + macOS) + SUDO=sudo + extra=prefix=/usr/local + ;; + esac + + $SUDO make -j5 $extra install + + - name: Ensure that we use the built Git and Scalar + shell: bash + run: | + type -p git + git version + case "$(git version)" in *.vfs.*) echo Good;; *) exit 1;; esac + type -p scalar + scalar version + case "$(scalar version 2>&1)" in *.vfs.*) echo Good;; *) exit 1;; esac + + - name: Check out Scalar's source code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Indicate full history so Nerdbank.GitVersioning works. + path: scalar + repository: ${{ env.SCALAR_REPOSITORY }} + ref: ${{ env.SCALAR_REF }} + + - name: Setup .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '3.1.426' + + - name: Install dependencies + run: dotnet restore + working-directory: scalar + env: + DOTNET_NOLOGO: 1 + + - name: Build + working-directory: scalar + run: dotnet build --configuration Release --no-restore -p:UseAppHost=true # Force generation of executable on macOS. + + - name: Setup platform (Linux) + if: runner.os == 'Linux' + run: | + echo "BUILD_PLATFORM=${{ runner.os }}" >>$GITHUB_ENV + echo "TRACE2_BASENAME=Trace2.${{ github.run_id }}__${{ github.run_number }}__${{ matrix.os }}__${{ matrix.features }}" >>$GITHUB_ENV + + - name: Setup platform (Mac) + if: runner.os == 'macOS' + run: | + echo 'BUILD_PLATFORM=Mac' >>$GITHUB_ENV + echo "TRACE2_BASENAME=Trace2.${{ github.run_id }}__${{ github.run_number }}__${{ matrix.os }}__${{ matrix.features }}" >>$GITHUB_ENV + + - name: Setup platform (Windows) + if: runner.os == 'Windows' + run: | + echo "BUILD_PLATFORM=${{ runner.os }}" >>$env:GITHUB_ENV + echo 'BUILD_FILE_EXT=.exe' >>$env:GITHUB_ENV + echo "TRACE2_BASENAME=Trace2.${{ github.run_id }}__${{ github.run_number }}__${{ matrix.os }}__${{ matrix.features }}" >>$env:GITHUB_ENV + + - name: Configure feature.scalar + run: git config --global feature.scalar ${{ matrix.features }} + + - id: functional_test + name: Functional test + timeout-minutes: 60 + working-directory: scalar + shell: bash + run: | + export GIT_TRACE2_EVENT="$PWD/$TRACE2_BASENAME/Event" + export GIT_TRACE2_PERF="$PWD/$TRACE2_BASENAME/Perf" + export GIT_TRACE2_EVENT_BRIEF=true + export GIT_TRACE2_PERF_BRIEF=true + mkdir -p "$TRACE2_BASENAME" + mkdir -p "$TRACE2_BASENAME/Event" + mkdir -p "$TRACE2_BASENAME/Perf" + git version --build-options + cd ../out + Scalar.FunctionalTests/$BUILD_FRAGMENT/Scalar.FunctionalTests$BUILD_FILE_EXT --test-scalar-on-path --test-git-on-path --timeout=300000 --full-suite + + - name: Force-stop FSMonitor daemons and Git processes (Windows) + if: runner.os == 'Windows' && (success() || failure()) + shell: bash + run: | + set -x + wmic process get CommandLine,ExecutablePath,HandleCount,Name,ParentProcessID,ProcessID + wmic process where "CommandLine Like '%fsmonitor--daemon %run'" delete + wmic process where "ExecutablePath Like '%git.exe'" delete + + - id: trace2_zip_unix + if: runner.os != 'Windows' && ( success() || failure() ) && ( steps.functional_test.conclusion == 'success' || steps.functional_test.conclusion == 'failure' ) + name: Zip Trace2 Logs (Unix) + shell: bash + working-directory: scalar + run: zip -q -r $TRACE2_BASENAME.zip $TRACE2_BASENAME/ + + - id: trace2_zip_windows + if: runner.os == 'Windows' && ( success() || failure() ) && ( steps.functional_test.conclusion == 'success' || steps.functional_test.conclusion == 'failure' ) + name: Zip Trace2 Logs (Windows) + working-directory: scalar + run: Compress-Archive -DestinationPath ${{ env.TRACE2_BASENAME }}.zip -Path ${{ env.TRACE2_BASENAME }} + + - name: Archive Trace2 Logs + if: ( success() || failure() ) && ( steps.trace2_zip_unix.conclusion == 'success' || steps.trace2_zip_windows.conclusion == 'success' ) + uses: actions/upload-artifact@v4 + with: + name: ${{ env.TRACE2_BASENAME }}.zip + path: scalar/${{ env.TRACE2_BASENAME }}.zip + retention-days: 3 + + # The GitHub Action `action-tmate` allows developers to connect to the running agent + # using SSH (it will be a `tmux` session; on Windows agents it will be inside the MSYS2 + # environment in `C:\msys64`, therefore it can be slightly tricky to interact with + # Git for Windows, which runs a slightly incompatible MSYS2 runtime). + - name: action-tmate + if: env.DEBUG_WITH_TMATE == 'true' && failure() + uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: true diff --git a/.gitignore b/.gitignore index a58ffc8d1a73d3..a0ac2ba0c6b3ca 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ /git-gc /git-get-tar-commit-id /git-grep +/git-gvfs-helper /git-hash-object /git-help /git-hook @@ -174,6 +175,7 @@ /git-unpack-file /git-unpack-objects /git-update-index +/git-update-microsoft-git /git-update-ref /git-update-server-info /git-upload-archive diff --git a/BRANCHES.md b/BRANCHES.md new file mode 100644 index 00000000000000..364158375e7d55 --- /dev/null +++ b/BRANCHES.md @@ -0,0 +1,59 @@ +Branches used in this repo +========================== + +The document explains the branching structure that we are using in the VFSForGit repository as well as the forking strategy that we have adopted for contributing. + +Repo Branches +------------- + +1. `vfs-#` + + These branches are used to track the specific version that match Git for Windows with the VFSForGit specific patches on top. When a new version of Git for Windows is released, the VFSForGit patches will be rebased on that windows version and a new gvfs-# branch created to create pull requests against. + + #### Examples + + ``` + vfs-2.27.0 + vfs-2.30.0 + ``` + + The versions of git for VFSForGit are based on the Git for Windows versions. v2.20.0.vfs.1 will correspond with the v2.20.0.windows.1 with the VFSForGit specific patches applied to the windows version. + +2. `vfs-#-exp` + + These branches are for releasing experimental features to early adopters. They + should contain everything within the corresponding `vfs-#` branch; if the base + branch updates, then merge into the `vfs-#-exp` branch as well. + +Tags +---- + +We are using annotated tags to build the version number for git. The build will look back through the commit history to find the first tag matching `v[0-9]*vfs*` and build the git version number using that tag. + +Full releases are of the form `v2.XX.Y.vfs.Z.W` where `v2.XX.Y` comes from the +upstream version and `Z.W` are custom updates within our fork. Specifically, +the `.Z` value represents the "compatibility level" with VFS for Git. Only +increase this version when making a breaking change with a released version +of VFS for Git. The `.W` version is used for minor updates between major +versions. + +Experimental releases are of the form `v2.XX.Y.vfs.Z.W.exp`. The `.exp` +suffix indicates that experimental features are available. The rest of the +version string comes from the full release tag. These versions will only +be made available as pre-releases on the releases page, never a full release. + +Forking +------- + +A personal fork of this repository and a branch in that repository should be used for development. + +These branches should be based on the latest vfs-# branch. If there are work in progress pull requests that you have based on a previous version branch when a new version branch is created, you will need to move your patches to the new branch to get them in that latest version. + +#### Example + +``` +git clone +git remote add ms https://github.com/Microsoft/git.git +git checkout -b my-changes ms/vfs-2.20.0 --no-track +git push -fu origin HEAD +``` diff --git a/Documentation/RelNotes/2.50.0.adoc b/Documentation/RelNotes/2.50.0.adoc index 95349ea50c001e..e85747335b2a4a 100644 --- a/Documentation/RelNotes/2.50.0.adoc +++ b/Documentation/RelNotes/2.50.0.adoc @@ -36,7 +36,7 @@ UI, Workflows & Features * Auth-related (and unrelated) error handling in send-email has been made more robust. - * Updating multiple references have only been possible in all-or-none + * Updating multiple references have only been possible in an all-or-nothing fashion with transactions, but it can be more efficient to batch multiple updates even when some of them are allowed to fail in a best-effort manner. A new "best effort batches of updates" mode @@ -53,7 +53,7 @@ UI, Workflows & Features * The build procedure installs bash (but not zsh) completion script. - * send-email has been updated to work better with Outlook's smtp server. + * send-email has been updated to work better with Outlook's SMTP server. * "git diff --minimal" used to give non-minimal output when its optimization kicked in, which has been disabled. @@ -62,7 +62,7 @@ UI, Workflows & Features delta chains from forming in a corner case even when there is no such cycle. - * Make repository clean-up tasks "gc" can do available to "git + * Make repository clean-up tasks that "gc" can do available to "git maintenance" front-end. * Bundle-URI feature did not use refs recorded in the bundle other @@ -188,7 +188,7 @@ Performance, Internal Implementation, Development Support etc. been dropped. * The code path to access the "packed-refs" file while "fsck" is - taught to mmap the file, instead of reading the whole file in the + taught to mmap the file, instead of reading the whole file into memory. * Assorted fixes for issues found with CodeQL. @@ -201,6 +201,17 @@ Performance, Internal Implementation, Development Support etc. we ended up checking for these non-existent files repeatedly, which has been optimized by memoizing the non-existence. + * Build settings have been improved for BSD based systems. + + * Newer version of libcURL detected curl_easy_setopt() calls we made + with platform-natural "int" when we should have used "long", which + all have been corrected. + + * Tests that compare $HOME and $(pwd), which should be the same + directory unless the tests chdir's around, would fail when the user + enters the test directory via symbolic links, which has been + corrected. + Fixes since v2.49 ----------------- @@ -316,8 +327,9 @@ Fixes since v2.49 * Fix for scheduled maintenance tasks on platforms using launchctl. (merge eb2d7beb0e jh/gc-launchctl-schedule-fix later to maint). - * Update to arm64 Windows port. - (merge 436a42215e js/windows-arm64 later to maint). + * Update to arm64 Windows port (part of which had been reverted as it + broke builds for existing platforms, which may need to be redone in + future releases). * hashmap API clean-up to ensure hashmap_clear() leaves a cleared map in a reusable state. @@ -380,14 +392,19 @@ Fixes since v2.49 reverse failed to give the mode bits of the path "removed" by the patch to the file it creates, which has been corrected. - * "git verify-refs" (and hence "git fsck --reference") started - erroring out in a repository in which secondary worktrees were - prepared with Git 2.43 or lower. + * "git verify-refs" errored out in a repository in which + linked worktrees were prepared with Git 2.43 or lower. (merge d5b3c38b8a sj/ref-contents-check-fix later to maint). - * Update total_ram() functrion on BSD variants. + * Update total_ram() function on BSD variants. + + * Update online_cpus() function on BSD variants. + + * Revert a botched bswap.h change that broke ntohll() functions on + big-endian systems with __builtin_bswap32/64(). - * Update online_cpus() functrion on BSD variants. + * Fixes for GitHub Actions Coverity job. + (merge 3cc4fc1ebd js/github-ci-win-coverity-fix later to maint). * Other code cleanup, docfix, build fix, etc. (merge 227c4f33a0 ja/doc-block-delimiter-markup-fix later to maint). diff --git a/Documentation/config.adoc b/Documentation/config.adoc index 32176de1f4d4e6..ad6a2f50677ca1 100644 --- a/Documentation/config.adoc +++ b/Documentation/config.adoc @@ -448,6 +448,8 @@ include::config/gui.adoc[] include::config/guitool.adoc[] +include::config/gvfs.adoc[] + include::config/help.adoc[] include::config/http.adoc[] @@ -488,6 +490,8 @@ include::config/pack.adoc[] include::config/pager.adoc[] +include::config/postcommand.adoc[] + include::config/pretty.adoc[] include::config/promisor.adoc[] diff --git a/Documentation/config/core.adoc b/Documentation/config/core.adoc index 1412cebd77a7f5..b3ec3bd3cde2a3 100644 --- a/Documentation/config/core.adoc +++ b/Documentation/config/core.adoc @@ -111,6 +111,14 @@ Version 2 uses an opaque string so that the monitor can return something that can be used to determine what files have changed without race conditions. +core.virtualFilesystem:: + If set, the value of this variable is used as a command which + will identify all files and directories that are present in + the working directory. Git will only track and update files + listed in the virtual file system. Using the virtual file system + will supersede the sparse-checkout settings which will be ignored. + See the "virtual file system" section of linkgit:githooks[5]. + core.trustctime:: If false, the ctime differences between the index and the working tree are ignored; useful when the inode change time @@ -742,6 +750,55 @@ core.multiPackIndex:: single index. See linkgit:git-multi-pack-index[1] for more information. Defaults to true. +core.gvfs:: + Enable the features needed for GVFS. This value can be set to true + to indicate all features should be turned on or the bit values listed + below can be used to turn on specific features. ++ +-- + GVFS_SKIP_SHA_ON_INDEX:: + Bit value 1 + Disables the calculation of the sha when writing the index + GVFS_MISSING_OK:: + Bit value 4 + Normally git write-tree ensures that the objects referenced by the + directory exist in the object database. This option disables this check. + GVFS_NO_DELETE_OUTSIDE_SPARSECHECKOUT:: + Bit value 8 + When marking entries to remove from the index and the working + directory this option will take into account what the + skip-worktree bit was set to so that if the entry has the + skip-worktree bit set it will not be removed from the working + directory. This will allow virtualized working directories to + detect the change to HEAD and use the new commit tree to show + the files that are in the working directory. + GVFS_FETCH_SKIP_REACHABILITY_AND_UPLOADPACK:: + Bit value 16 + While performing a fetch with a virtual file system we know + that there will be missing objects and we don't want to download + them just because of the reachability of the commits. We also + don't want to download a pack file with commits, trees, and blobs + since these will be downloaded on demand. This flag will skip the + checks on the reachability of objects during a fetch as well as + the upload pack so that extraneous objects don't get downloaded. + GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS:: + Bit value 64 + With a virtual file system we only know the file size before any + CRLF or smudge/clean filters processing is done on the client. + To prevent file corruption due to truncation or expansion with + garbage at the end, these filters must not run when the file + is first accessed and brought down to the client. Git.exe can't + currently tell the first access vs subsequent accesses so this + flag just blocks them from occurring at all. + GVFS_PREFETCH_DURING_FETCH:: + Bit value 128 + While performing a `git fetch` command, use the gvfs-helper to + perform a "prefetch" of commits and trees. +-- + +core.useGvfsHelper:: + TODO + core.sparseCheckout:: Enable "sparse checkout" feature. See linkgit:git-sparse-checkout[1] for more information. @@ -776,3 +833,12 @@ core.WSLCompat:: The default value is false. When set to true, Git will set the mode bits of the file in the way of wsl, so that the executable flag of files can be set or read correctly. + +core.configWriteLockTimeoutMS:: + When processes try to write to the config concurrently, it is likely + that one process "wins" and the other process(es) fail to lock the + config file. By configuring a timeout larger than zero, Git can be + told to try to lock the config again a couple times within the + specified timeout. If the timeout is configure to zero (which is the + default), Git will fail immediately when the config is already + locked. diff --git a/Documentation/config/gitcvs.adoc b/Documentation/config/gitcvs.adoc index 02da427fd9743f..31d7be3992b572 100644 --- a/Documentation/config/gitcvs.adoc +++ b/Documentation/config/gitcvs.adoc @@ -47,7 +47,8 @@ gitcvs.dbDriver:: May not contain double colons (`:`). Default: 'SQLite'. See linkgit:git-cvsserver[1]. -gitcvs.dbUser, gitcvs.dbPass:: +gitcvs.dbUser:: +gitcvs.dbPass:: Database user and password. Only useful if setting `gitcvs.dbDriver`, since SQLite has no concept of database users and/or passwords. 'gitcvs.dbUser' supports variable substitution (see diff --git a/Documentation/config/gvfs.adoc b/Documentation/config/gvfs.adoc new file mode 100644 index 00000000000000..7224939ac0b270 --- /dev/null +++ b/Documentation/config/gvfs.adoc @@ -0,0 +1,10 @@ +gvfs.cache-server:: + TODO + +gvfs.sharedcache:: + TODO + +gvfs.fallback:: + If set to `false`, then never fallback to the origin server when the cache + server fails to connect. This will alert users to failures with the cache + server, but avoid causing throttling on the origin server. diff --git a/Documentation/config/http.adoc b/Documentation/config/http.adoc index dedfe63322019d..7fd001206ded22 100644 --- a/Documentation/config/http.adoc +++ b/Documentation/config/http.adoc @@ -296,7 +296,8 @@ for most push problems, but can increase memory consumption significantly since the entire buffer is allocated even for small pushes. -http.lowSpeedLimit, http.lowSpeedTime:: +http.lowSpeedLimit:: +http.lowSpeedTime:: If the HTTP transfer speed, in bytes per second, is less than 'http.lowSpeedLimit' for longer than 'http.lowSpeedTime' seconds, the transfer is aborted. diff --git a/Documentation/config/index.adoc b/Documentation/config/index.adoc index 3eff42036033ea..0d6d05b70ce03d 100644 --- a/Documentation/config/index.adoc +++ b/Documentation/config/index.adoc @@ -1,3 +1,9 @@ +index.deleteSparseDirectories:: + When enabled, the cone mode sparse-checkout feature will delete + directories that are outside of the sparse-checkout cone, unless + such a directory contains an untracked, non-ignored file. Defaults + to true. + index.recordEndOfIndexEntries:: Specifies whether the index file should include an "End Of Index Entry" section. This reduces index load time on multiprocessor diff --git a/Documentation/config/postcommand.adoc b/Documentation/config/postcommand.adoc new file mode 100644 index 00000000000000..1ae7ce92f6ee22 --- /dev/null +++ b/Documentation/config/postcommand.adoc @@ -0,0 +1,13 @@ +postCommand.strategy:: + The `post-command` hook is run on every Git process by default. This + config option allows running the hook only conditionally, according + to these values: ++ +---- +`always`;; + run the `post-command` hook on every process (default). + +`worktree-change`;; + run the `post-command` hook only if the current process wrote to + the index and updated the worktree. +---- diff --git a/Documentation/config/protocol.adoc b/Documentation/config/protocol.adoc index a9bf187a933a24..01c399e99bb5d3 100644 --- a/Documentation/config/protocol.adoc +++ b/Documentation/config/protocol.adoc @@ -6,7 +6,7 @@ protocol.allow:: default policy of `never`, and all other protocols (including file) have a default policy of `user`. Supported policies: + --- +---- * `always` - protocol is always able to be used. @@ -18,7 +18,7 @@ protocol.allow:: execute clone/fetch/push commands without user input, e.g. recursive submodule initialization. --- +---- protocol..allow:: Set a policy to be used by protocol `` with clone/fetch/push @@ -26,7 +26,7 @@ protocol..allow:: + The protocol names currently used by git are: + --- +---- - `file`: any local file-based path (including `file://` URLs, or local paths) @@ -42,7 +42,7 @@ The protocol names currently used by git are: - any external helpers are named by their protocol (e.g., use `hg` to allow the `git-remote-hg` helper) --- +---- protocol.version:: If set, clients will attempt to communicate with a server @@ -51,7 +51,7 @@ protocol.version:: If unset, the default is `2`. Supported versions: + --- +---- * `0` - the original wire protocol. @@ -60,4 +60,4 @@ protocol.version:: * `2` - Wire protocol version 2, see linkgit:gitprotocol-v2[5]. --- +---- diff --git a/Documentation/config/push.adoc b/Documentation/config/push.adoc index 0acbbea18a320f..83282312262106 100644 --- a/Documentation/config/push.adoc +++ b/Documentation/config/push.adoc @@ -17,7 +17,7 @@ push.default:: (i.e. the fetch source is equal to the push destination), `upstream` is probably what you want. Possible values are: + --- +---- * `nothing` - do not push anything (error out) unless a refspec is given. This is primarily meant for people who want to @@ -64,7 +64,7 @@ branches outside your control. This used to be the default, but not since Git 2.0 (`simple` is the new default). --- +---- push.followTags:: If set to true, enable `--follow-tags` option by default. You diff --git a/Documentation/config/sendemail.adoc b/Documentation/config/sendemail.adoc index 5ffcfc9f2a76f7..f1a9fb7e9b3a5d 100644 --- a/Documentation/config/sendemail.adoc +++ b/Documentation/config/sendemail.adoc @@ -58,7 +58,7 @@ the documentation of the email program of the same name. The differences and limitations from the standard formats are described below: + --- +---- sendmail;; * Quoted aliases and quoted addresses are not supported: lines that contain a `"` symbol are ignored. @@ -68,7 +68,7 @@ sendmail;; * Warnings are printed on the standard error output for any explicitly unsupported constructs, and any other lines that are not recognized by the parser. --- +---- sendemail.annotate:: sendemail.bcc:: sendemail.cc:: diff --git a/Documentation/config/sideband.adoc b/Documentation/config/sideband.adoc index f347fd6b33004a..33cbe08bfab200 100644 --- a/Documentation/config/sideband.adoc +++ b/Documentation/config/sideband.adoc @@ -4,7 +4,7 @@ sideband.allowControlCharacters:: unwanted ANSI escape sequences from being sent to the terminal. Use this config setting to override this behavior: + --- +---- color:: Allow ANSI color sequences, line feeds and horizontal tabs, but mask all other control characters. This is the default. @@ -13,4 +13,4 @@ sideband.allowControlCharacters:: horizontal tabs. true:: Allow all control characters to be sent to the terminal. --- +---- diff --git a/Documentation/config/ssh.adoc b/Documentation/config/ssh.adoc index 2ca4bf93e1e30f..4f61c9351f3815 100644 --- a/Documentation/config/ssh.adoc +++ b/Documentation/config/ssh.adoc @@ -19,7 +19,7 @@ overridden via the environment variable `GIT_SSH_VARIANT`. The current command-line parameters used for each variant are as follows: + --- +---- * `ssh` - [-p port] [-4] [-6] [-o option] [username@]host command @@ -29,7 +29,7 @@ follows: * `tortoiseplink` - [-P port] [-4] [-6] -batch [username@]host command --- +---- + Except for the `simple` variant, command-line parameters are likely to change as git gains new features. diff --git a/Documentation/config/status.adoc b/Documentation/config/status.adoc index 8caf90f51c19a3..fa393e703eb01c 100644 --- a/Documentation/config/status.adoc +++ b/Documentation/config/status.adoc @@ -50,11 +50,11 @@ status.showUntrackedFiles:: systems. So, this variable controls how the commands display the untracked files. Possible values are: + --- +---- * `no` - Show no untracked files. * `normal` - Show untracked files and directories. * `all` - Show also individual files in untracked directories. --- +---- + If this variable is not specified, it defaults to 'normal'. All usual spellings for Boolean value `true` are taken as `normal` @@ -77,3 +77,25 @@ status.submoduleSummary:: the --ignore-submodules=dirty command-line option or the 'git submodule summary' command, which shows a similar output but does not honor these settings. + +status.deserializePath:: + EXPERIMENTAL, Pathname to a file containing cached status results + generated by `--serialize`. This will be overridden by + `--deserialize=` on the command line. If the cache file is + invalid or stale, git will fall-back and compute status normally. + +status.deserializeWait:: + EXPERIMENTAL, Specifies what `git status --deserialize` should do + if the serialization cache file is stale and whether it should + fall-back and compute status normally. This will be overridden by + `--deserialize-wait=` on the command line. ++ +---- +* `fail` - cause git to exit with an error when the status cache file +is stale; this is intended for testing and debugging. +* `block` - cause git to spin and periodically retry the cache file +every 100 ms; this is intended to help coordinate with another git +instance concurrently computing the cache file. +* `no` - to immediately fall-back if cache file is stale. This is the default. +* `` - time (in tenths of a second) to spin and retry. +---- diff --git a/Documentation/config/survey.adoc b/Documentation/config/survey.adoc index 9e594a2092f225..ae327075e2c6f9 100644 --- a/Documentation/config/survey.adoc +++ b/Documentation/config/survey.adoc @@ -3,7 +3,11 @@ survey.*:: command. The intention is that this command could be run in the background with these options. + --- +---- + survey.namerev:: + Boolean to show/hide `git name-rev` information for each + reported commit and the containing commit of each + reported tree and blob. verbose:: This boolean value implies the `--[no-]verbose` option. progress:: @@ -11,4 +15,33 @@ survey.*:: top:: This integer value implies `--top=`, specifying the number of entries in the detail tables. --- + showBlobSizes:: + A non-negative integer value. Requests details on the + largest file blobs by size in bytes. Provides a + default value for `--blob-sizes=` in + linkgit:git-survey[1]. + showCommitParents:: + A non-negative integer value. Requests details on the + commits with the most number of parents. Provides a + default value for `--commit-parents=` in + linkgit:git-survey[1]. + showCommitSizes:: + A non-negative integer value. Requests details on the + largest commits by size in bytes. Generally, these + are the commits with the largest commit messages. + Provides a default value for `--commit-sizes=` in + linkgit:git-survey[1]. + showTreeEntries:: + A non-negative integer value. Requests details on the + trees (directories) with the most number of entries + (files and subdirectories). Provides a default value + for `--tree-entries=` in linkgit:git-survey[1]. + showTreeSizes:: + A non-negative integer value. Requests details on the + largest trees (directories) by size in bytes. This + will set will usually be equal to the + `survey.showTreeEntries` set, but may be skewed by very + long file or subdirectory entry names. Provides a + default value for `--tree-sizes=` in + linkgit:git-survey[1]. +---- diff --git a/Documentation/config/trace2.adoc b/Documentation/config/trace2.adoc index 05639ce33f908a..f5d730934c8354 100644 --- a/Documentation/config/trace2.adoc +++ b/Documentation/config/trace2.adoc @@ -16,7 +16,7 @@ trace2.eventTarget:: This variable controls the event target destination. It may be overridden by the `GIT_TRACE2_EVENT` environment variable. The following table shows possible values. -+ + include::../trace2-target-values.adoc[] trace2.normalBrief:: diff --git a/Documentation/git-maintenance.adoc b/Documentation/git-maintenance.adoc index 931f3e02e85fe4..27ec1bdc1f89dc 100644 --- a/Documentation/git-maintenance.adoc +++ b/Documentation/git-maintenance.adoc @@ -69,6 +69,7 @@ task: * `prefetch`: hourly. * `loose-objects`: daily. * `incremental-repack`: daily. +* `cache-local-objects`: weekly. -- + `git maintenance register` will also disable foreground maintenance by @@ -172,7 +173,14 @@ rerere-gc:: worktree-prune:: The `worktree-prune` task deletes stale or broken worktrees. See - linkit:git-worktree[1] for more information. + linkgit:git-worktree[1] for more information. + +cache-local-objects:: + The `cache-local-objects` task only operates on Scalar or VFS for Git + repositories (cloned with either `scalar clone` or `gvfs clone`) that + have the `gvfs.sharedCache` configuration setting present. This task + migrates pack files and loose objects from the repository's object + directory in to the shared volume cache. OPTIONS ------- diff --git a/Documentation/git-status.adoc b/Documentation/git-status.adoc index 9a376886a5867a..62254617dd7fc1 100644 --- a/Documentation/git-status.adoc +++ b/Documentation/git-status.adoc @@ -151,6 +151,21 @@ ignored, then the directory is not shown, but all contents are shown. threshold. See also linkgit:git-diff[1] `--find-renames`. +--serialize[=]:: + (EXPERIMENTAL) Serialize raw status results to a file or stdout + in a format suitable for use by `--deserialize`. If a path is + given, serialize data will be written to that path *and* normal + status output will be written to stdout. If path is omitted, + only binary serialization data will be written to stdout. + +--deserialize[=]:: + (EXPERIMENTAL) Deserialize raw status results from a file or + stdin rather than scanning the worktree. If `` is omitted + and `status.deserializePath` is unset, input is read from stdin. +--no-deserialize:: + (EXPERIMENTAL) Disable implicit deserialization of status results + from the value of `status.deserializePath`. + ...:: See the 'pathspec' entry in linkgit:gitglossary[7]. @@ -424,6 +439,26 @@ quoted as explained for the configuration variable `core.quotePath` (see linkgit:git-config[1]). +SERIALIZATION and DESERIALIZATION (EXPERIMENTAL) +------------------------------------------------ + +The `--serialize` option allows git to cache the result of a +possibly time-consuming status scan to a binary file. A local +service/daemon watching file system events could use this to +periodically pre-compute a fresh status result. + +Interactive users could then use `--deserialize` to simply +(and immediately) print the last-known-good result without +waiting for the status scan. + +The binary serialization file format includes some worktree state +information allowing `--deserialize` to reject the cached data +and force a normal status scan if, for example, the commit, branch, +or status modes/options change. The format cannot, however, indicate +when the cached data is otherwise stale -- that coordination belongs +to the task driving the serializations. + + CONFIGURATION ------------- diff --git a/Documentation/git-survey.adoc b/Documentation/git-survey.adoc index 44f3a0568b7697..c57b9920905ca2 100644 --- a/Documentation/git-survey.adoc +++ b/Documentation/git-survey.adoc @@ -32,6 +32,10 @@ OPTIONS --progress:: Show progress. This is automatically enabled when interactive. +--[no-]name-rev:: + Print `git name-rev` output for each commit, tree, and blob. + Defaults to true. + Ref Selection ~~~~~~~~~~~~~ @@ -59,6 +63,32 @@ only refs for the given options are added. --other:: Add notes (`refs/notes/`) and stashes (`refs/stash/`) to the set. +Large Item Selection +~~~~~~~~~~~~~~~~~~~~ + +The following options control the optional display of large items under +various dimensions of scale. The OID of the largest `n` objects will be +displayed in reverse sorted order. For each, `n` defaults to 10. + +--commit-parents:: + Shows the OIDs of the commits with the most parent commits. + +--commit-sizes:: + Shows the OIDs of the largest commits by size in bytes. This is + usually the ones with the largest commit messages. + +--tree-entries:: + Shows the OIDs of the trees with the most number of entries. These + are the directories with the most number of files or subdirectories. + +--tree-sizes:: + Shows the OIDs of the largest trees by size in bytes. This set + will usually be the same as the vector of number of entries unless + skewed by very long entry names. + +--blob-sizes:: + Shows the OIDs of the largest blobs by size in bytes. + OUTPUT ------ @@ -78,6 +108,11 @@ Reachable Object Summary The reachable object summary shows the total number of each kind of Git object, including tags, commits, trees, and blobs. +CONFIGURATION +------------- + +include::config/survey.adoc[] + GIT --- Part of the linkgit:git[1] suite diff --git a/Documentation/git-update-microsoft-git.adoc b/Documentation/git-update-microsoft-git.adoc new file mode 100644 index 00000000000000..724bfc172f8ab7 --- /dev/null +++ b/Documentation/git-update-microsoft-git.adoc @@ -0,0 +1,24 @@ +git-update-microsoft-git(1) +=========================== + +NAME +---- +git-update-microsoft-git - Update the installed version of Git + + +SYNOPSIS +-------- +[verse] +'git update-microsoft-git' + +DESCRIPTION +----------- +This version of Git is based on the Microsoft fork of Git, which +has custom capabilities focused on supporting monorepos. This +command checks for the latest release of that fork and installs +it on your machine. + + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/githooks.adoc b/Documentation/githooks.adoc index 0397dec64d7315..86c78b3b4825e2 100644 --- a/Documentation/githooks.adoc +++ b/Documentation/githooks.adoc @@ -758,6 +758,26 @@ and "0" meaning they were not. Only one parameter should be set to "1" when the hook runs. The hook running passing "1", "1" should not be possible. +virtualFilesystem +~~~~~~~~~~~~~~~~~~ + +"Virtual File System" allows populating the working directory sparsely. +The projection data is typically automatically generated by an external +process. Git will limit what files it checks for changes as well as which +directories are checked for untracked files based on the path names given. +Git will also only update those files listed in the projection. + +The hook is invoked when the configuration option core.virtualFilesystem +is set. It takes one argument, a version (currently 1). + +The hook should output to stdout the list of all files in the working +directory that git should track. The paths are relative to the root +of the working directory and are separated by a single NUL. Full paths +('dir1/a.txt') as well as directories are supported (ie 'dir1/'). + +The exit status determines whether git will use the data from the +hook. On error, git will abort the command with an error message. + SEE ALSO -------- linkgit:git-hook[1] diff --git a/Documentation/lint-manpages.sh b/Documentation/lint-manpages.sh index a0ea572382d8d9..53c7ed9f12ec66 100755 --- a/Documentation/lint-manpages.sh +++ b/Documentation/lint-manpages.sh @@ -27,6 +27,8 @@ check_missing_docs () ( git-init-db) continue;; git-remote-*) continue;; git-stage) continue;; + git-gvfs-helper) continue;; + git-update-microsoft-git) continue;; git-legacy-*) continue;; git-?*--?* ) continue ;; esac diff --git a/Documentation/meson.build b/Documentation/meson.build index 42541b15c033a1..1aad1ac75ef558 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -149,6 +149,7 @@ manpages = { 'git-unpack-file.adoc' : 1, 'git-unpack-objects.adoc' : 1, 'git-update-index.adoc' : 1, + 'git-update-microsoft-git.adoc' : 1, 'git-update-ref.adoc' : 1, 'git-update-server-info.adoc' : 1, 'git-upload-archive.adoc' : 1, diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index 4bd5b150e8e1d4..7e6c1211be6873 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -9,7 +9,9 @@ SYNOPSIS -------- [verse] scalar clone [--single-branch] [--branch ] [--full-clone] - [--[no-]src] [--[no-]tags] [--[no-]maintenance] [] + [--[no-]src] [--[no-]tags] [--[no-]maintenance] + [--[no-]src] [--local-cache-path ] [--cache-server-url ] + [] scalar list scalar register [--[no-]maintenance] [] scalar unregister [] @@ -17,6 +19,7 @@ scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) scalar reconfigure [--maintenance=(enable|disable|keep)] [ --all | ] scalar diagnose [] scalar delete +scalar cache-server ( --get | --set | --list [] ) [] DESCRIPTION ----------- @@ -102,6 +105,37 @@ cloning. If the HEAD at the remote did not point at any branch when background maintenance feature. Use the `--no-maintenance` to skip this configuration. +--local-cache-path :: + Override the path to the local cache root directory; Pre-fetched objects + are stored into a repository-dependent subdirectory of that path. ++ +The default is `:\.scalarCache` on Windows (on the same drive as the +clone), and `~/.scalarCache` on macOS. + +--cache-server-url :: + Retrieve missing objects from the specified remote, which is expected to + understand the GVFS protocol. + +--[no-]gvfs-protocol:: + When cloning from a `` with either `dev.azure.com` or + `visualstudio.com` in the name, `scalar clone` will attempt to use the GVFS + Protocol to access Git objects, specifically from a cache server when + available, and will fail to clone if there is an error over that protocol. + + To enable the GVFS Protocol regardless of the origin ``, use + `--gvfs-protocol`. This will cause `scalar clone` to fail when the origin + server fails to provide a valid response to the `gvfs/config` endpoint. + + To disable the GVFS Protocol, use `--no-gvfs-protocol` and `scalar clone` + will only use the Git protocol, starting with a partial clone. This can be + helpful if your `` points to Azure Repos but the repository does not + have GVFS cache servers enabled. It is likely more efficient to use its + partial clone functionality through the Git protocol. + + Previous versions of `scalar clone` could fall back to a partial clone over + the Git protocol if there is any issue gathering GVFS configuration + information from the origin server. + List ~~~~ @@ -191,6 +225,27 @@ delete :: This subcommand lets you delete an existing Scalar enlistment from your local file system, unregistering the repository. +Cache-server +~~~~~~~~~~~~ + +cache-server ( --get | --set | --list [] ) []:: + This command lets you query or set the GVFS-enabled cache server used + to fetch missing objects. + +--get:: + This is the default command mode: query the currently-configured cache + server URL, if any. + +--list:: + Access the `gvfs/info` endpoint of the specified remote (default: + `origin`) to figure out which cache servers are available, if any. ++ +In contrast to the `--get` command mode (which only accesses the local +repository), this command mode triggers a request via the network that +potentially requires authentication. If authentication is required, the +configured credential helper is employed (see linkgit:git-credential[1] +for details). + SEE ALSO -------- linkgit:git-clone[1], linkgit:git-maintenance[1]. diff --git a/Documentation/technical/api-path-walk.adoc b/Documentation/technical/api-path-walk.adoc index 6cc4cb491d3804..5b7e6038de5653 100644 --- a/Documentation/technical/api-path-walk.adoc +++ b/Documentation/technical/api-path-walk.adoc @@ -56,6 +56,14 @@ better off using the revision walk API instead. the revision walk so that the walk emits commits marked with the `UNINTERESTING` flag. +`edge_aggressive`:: + For performance reasons, usually only the boundary commits are + explored to find UNINTERESTING objects. However, in the case of + shallow clones it can be helpful to mark all trees and blobs + reachable from UNINTERESTING tip commits as UNINTERESTING. This + matches the behavior of `--objects-edge-aggressive` in the + revision API. + `pl`:: This pattern list pointer allows focusing the path-walk search to a set of patterns, only emitting paths that match the given diff --git a/Documentation/technical/read-object-protocol.txt b/Documentation/technical/read-object-protocol.txt new file mode 100644 index 00000000000000..a893b46e7c28a9 --- /dev/null +++ b/Documentation/technical/read-object-protocol.txt @@ -0,0 +1,102 @@ +Read Object Process +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The read-object process enables Git to read all missing blobs with a +single process invocation for the entire life of a single Git command. +This is achieved by using a packet format (pkt-line, see technical/ +protocol-common.txt) based protocol over standard input and standard +output as follows. All packets, except for the "*CONTENT" packets and +the "0000" flush packet, are considered text and therefore are +terminated by a LF. + +Git starts the process when it encounters the first missing object that +needs to be retrieved. After the process is started, Git sends a welcome +message ("git-read-object-client"), a list of supported protocol version +numbers, and a flush packet. Git expects to read a welcome response +message ("git-read-object-server"), exactly one protocol version number +from the previously sent list, and a flush packet. All further +communication will be based on the selected version. + +The remaining protocol description below documents "version=1". Please +note that "version=42" in the example below does not exist and is only +there to illustrate how the protocol would look with more than one +version. + +After the version negotiation Git sends a list of all capabilities that +it supports and a flush packet. Git expects to read a list of desired +capabilities, which must be a subset of the supported capabilities list, +and a flush packet as response: +------------------------ +packet: git> git-read-object-client +packet: git> version=1 +packet: git> version=42 +packet: git> 0000 +packet: git< git-read-object-server +packet: git< version=1 +packet: git< 0000 +packet: git> capability=get +packet: git> capability=have +packet: git> capability=put +packet: git> capability=not-yet-invented +packet: git> 0000 +packet: git< capability=get +packet: git< 0000 +------------------------ +The only supported capability in version 1 is "get". + +Afterwards Git sends a list of "key=value" pairs terminated with a flush +packet. The list will contain at least the command (based on the +supported capabilities) and the sha1 of the object to retrieve. Please +note, that the process must not send any response before it received the +final flush packet. + +When the process receives the "get" command, it should make the requested +object available in the git object store and then return success. Git will +then check the object store again and this time find it and proceed. +------------------------ +packet: git> command=get +packet: git> sha1=0a214a649e1b3d5011e14a3dc227753f2bd2be05 +packet: git> 0000 +------------------------ + +The process is expected to respond with a list of "key=value" pairs +terminated with a flush packet. If the process does not experience +problems then the list must contain a "success" status. +------------------------ +packet: git< status=success +packet: git< 0000 +------------------------ + +In case the process cannot or does not want to process the content, it +is expected to respond with an "error" status. +------------------------ +packet: git< status=error +packet: git< 0000 +------------------------ + +In case the process cannot or does not want to process the content as +well as any future content for the lifetime of the Git process, then it +is expected to respond with an "abort" status at any point in the +protocol. +------------------------ +packet: git< status=abort +packet: git< 0000 +------------------------ + +Git neither stops nor restarts the process in case the "error"/"abort" +status is set. + +If the process dies during the communication or does not adhere to the +protocol then Git will stop the process and restart it with the next +object that needs to be processed. + +After the read-object process has processed an object it is expected to +wait for the next "key=value" list containing a command. Git will close +the command pipe on exit. The process is expected to detect EOF and exit +gracefully on its own. Git will wait until the process has stopped. + +A long running read-object process demo implementation can be found in +`contrib/long-running-read-object/example.pl` located in the Git core +repository. If you develop your own long running process then the +`GIT_TRACE_PACKET` environment variables can be very helpful for +debugging (see linkgit:git[1]). diff --git a/Documentation/technical/sparse-index.adoc b/Documentation/technical/sparse-index.adoc index 3b24c1a219f811..c466dbddc930a9 100644 --- a/Documentation/technical/sparse-index.adoc +++ b/Documentation/technical/sparse-index.adoc @@ -206,3 +206,10 @@ Here are some commands that might be useful to update: * `git am` * `git clean` * `git stash` + +In order to help identify the cases where remaining index expansion is +occurring in user machines, calls to `ensure_full_index()` have been +replaced with `ensure_full_index_with_reason()` or with +`ensure_full_index_unaudited()`. These versions add tracing that should +help identify the reason for the index expansion without needing full +access to someone's repository. diff --git a/Documentation/technical/status-serialization-format.txt b/Documentation/technical/status-serialization-format.txt new file mode 100644 index 00000000000000..475ae814495581 --- /dev/null +++ b/Documentation/technical/status-serialization-format.txt @@ -0,0 +1,107 @@ +Git status serialization format +=============================== + +Git status serialization enables git to dump the results of a status scan +to a binary file. This file can then be loaded by later status invocations +to print the cached status results. + +The file contains the essential fields from: +() the index +() the "struct wt_status" for the overall results +() the contents of "struct wt_status_change_data" for tracked changed files +() the list of untracked and ignored files + +Version 1 Format: +================= + +The V1 file begins with a required header section followed by optional +sections for each type of item (changed, untracked, ignored). Individual +item sections are only present if necessary. Each item section begins +with an item-type header with the number of items in the section. + +Each "line" in the format is encoded using pkt-line with a final LF. +Flush packets are used to terminate sections. + +----------------- +PKT-LINE("version" SP "1") + +[] +[] +[] +----------------- + + +V1 Header +--------- + +The v1-header-section fields are taken directly from "struct wt_status". +Each field is printed on a separate pkt-line. Lines for NULL string +values are omitted. All integers are printed with "%d". OIDs are +printed in hex. + +v1-header-section = + + PKT-LINE() + +v1-index-headers = PKT-LINE("index_mtime" SP SP LF) + +v1-wt-status-headers = PKT-LINE("is_initial" SP LF) + [ PKT-LINE("branch" SP LF) ] + [ PKT-LINE("reference" SP LF) ] + PKT-LINE("show_ignored_files" SP LF) + PKT-LINE("show_untracked_files" SP LF) + PKT-LINE("show_ignored_directory" SP LF) + [ PKT-LINE("ignore_submodule_arg" SP LF) ] + PKT-LINE("detect_rename" SP LF) + PKT-LINE("rename_score" SP LF) + PKT-LINE("rename_limit" SP LF) + PKT-LINE("detect_break" SP LF) + PKT-LINE("sha1_commit" SP LF) + PKT-LINE("committable" SP LF) + PKT-LINE("workdir_dirty" SP LF) + + +V1 Changed Items +---------------- + +The v1-changed-item-section lists all of the changed items with one +item per pkt-line. Each pkt-line contains: a binary block of data +from "struct wt_status_serialize_data_fixed" in a fixed header where +integers are in network byte order and OIDs are in raw (non-hex) form. +This is followed by one or two raw pathnames (not c-quoted) with NUL +terminators (both NULs are always present even if there is no rename). + +v1-changed-item-section = PKT-LINE("changed" SP LF) + [ PKT-LINE( LF) ]+ + PKT-LINE() + +changed_item = + + + + + + + + + + + + NUL + [ ] + NUL + + +V1 Untracked and Ignored Items +------------------------------ + +These sections are simple lists of pathnames. They ARE NOT +c-quoted. + +v1-untracked-item-section = PKT-LINE("untracked" SP LF) + [ PKT-LINE( LF) ]+ + PKT-LINE() + +v1-ignored-item-section = PKT-LINE("ignored" SP LF) + [ PKT-LINE( LF) ]+ + PKT-LINE() diff --git a/Documentation/trace2-target-values.adoc b/Documentation/trace2-target-values.adoc index 06f19533134f9d..503d9f13864c27 100644 --- a/Documentation/trace2-target-values.adoc +++ b/Documentation/trace2-target-values.adoc @@ -1,12 +1,12 @@ --- +---- * `0` or `false` - Disables the target. * `1` or `true` - Writes to `STDERR`. * `[2-9]` - Writes to the already opened file descriptor. * `` - Writes to the file in append mode. If the target -already exists and is a directory, the traces will be written to files (one -per process) underneath the given directory. + already exists and is a directory, the traces will be written to files (one + per process) underneath the given directory. * `af_unix:[:]` - Write to a -Unix DomainSocket (on platforms that support them). Socket -type can be either `stream` or `dgram`; if omitted Git will -try both. --- + Unix DomainSocket (on platforms that support them). Socket + type can be either `stream` or `dgram`; if omitted Git will + try both. +---- \ No newline at end of file diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 1047b8d11de767..77da75e986e63a 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,6 +1,9 @@ #!/bin/sh -DEF_VER=v2.50.0-rc1 +DEF_VER=v2.50.0 + +# Identify microsoft/git via a distinct version suffix +DEF_VER=$DEF_VER.vfs.0.0 LF=' ' @@ -47,9 +50,15 @@ then test -d "${GIT_DIR:-.git}" || test -f "$SOURCE_DIR"/.git; } && - VN=$(git -C "$SOURCE_DIR" describe --dirty --match="v[0-9]*" 2>/dev/null) && + VN=$(git -C "$SOURCE_DIR" describe --dirty --match="v[0-9]*vfs*" 2>/dev/null) && case "$VN" in *$LF*) (exit 1) ;; + v[0-9]*) + if test "${VN%%.vfs.*}" != "${DEF_VER%%.vfs.*}" + then + echo "Found version $VN, which is not based on $DEF_VER" >&2 + exit 1 + fi ;; esac then VN=$(echo "$VN" | sed -e 's/-/./g'); @@ -82,7 +91,7 @@ read GIT_MAJOR_VERSION GIT_MINOR_VERSION GIT_MICRO_VERSION GIT_PATCH_LEVEL trail $(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ') EOF -REPLACED=$(printf "%s" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ +REPLACED=$(printf "%s\n" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \ -e "s|@GIT_MAJOR_VERSION@|$GIT_MAJOR_VERSION|" \ -e "s|@GIT_MINOR_VERSION@|$GIT_MINOR_VERSION|" \ -e "s|@GIT_MICRO_VERSION@|$GIT_MICRO_VERSION|" \ diff --git a/Makefile b/Makefile index 89275cbf6c2a66..17bbed2a070cd4 100644 --- a/Makefile +++ b/Makefile @@ -1048,6 +1048,8 @@ LIB_OBJS += git-zlib.o LIB_OBJS += gpg-interface.o LIB_OBJS += graph.o LIB_OBJS += grep.o +LIB_OBJS += gvfs.o +LIB_OBJS += gvfs-helper-client.o LIB_OBJS += hash-lookup.o LIB_OBJS += hash.o LIB_OBJS += hashmap.o @@ -1207,6 +1209,7 @@ LIB_OBJS += utf8.o LIB_OBJS += varint.o LIB_OBJS += version.o LIB_OBJS += versioncmp.o +LIB_OBJS += virtualfilesystem.o LIB_OBJS += walker.o LIB_OBJS += wildmatch.o LIB_OBJS += worktree.o @@ -1214,6 +1217,8 @@ LIB_OBJS += wrapper.o LIB_OBJS += write-or-die.o LIB_OBJS += ws.o LIB_OBJS += wt-status.o +LIB_OBJS += wt-status-deserialize.o +LIB_OBJS += wt-status-serialize.o LIB_OBJS += xdiff-interface.o BUILTIN_OBJS += builtin/add.o @@ -1335,6 +1340,7 @@ BUILTIN_OBJS += builtin/tag.o BUILTIN_OBJS += builtin/unpack-file.o BUILTIN_OBJS += builtin/unpack-objects.o BUILTIN_OBJS += builtin/update-index.o +BUILTIN_OBJS += builtin/update-microsoft-git.o BUILTIN_OBJS += builtin/update-ref.o BUILTIN_OBJS += builtin/update-server-info.o BUILTIN_OBJS += builtin/upload-archive.o @@ -1697,6 +1703,9 @@ endif endif BASIC_CFLAGS += $(CURL_CFLAGS) + PROGRAM_OBJS += gvfs-helper.o + TEST_PROGRAMS_NEED_X += test-gvfs-protocol + REMOTE_CURL_PRIMARY = git-remote-http$X REMOTE_CURL_ALIASES = git-remote-https$X git-remote-ftp$X git-remote-ftps$X REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES) @@ -2822,6 +2831,7 @@ GIT_OBJS += git.o .PHONY: git-objs git-objs: $(GIT_OBJS) +SCALAR_OBJS := json-parser.o SCALAR_OBJS += scalar.o .PHONY: scalar-objs scalar-objs: $(SCALAR_OBJS) @@ -2926,7 +2936,7 @@ gettext.sp gettext.s gettext.o: GIT-PREFIX gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \ -DGIT_LOCALE_PATH='"$(localedir_relative_SQ)"' -http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp: SP_EXTRA_FLAGS += \ +http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp gvfs-helper.sp: SP_EXTRA_FLAGS += \ -DCURL_DISABLE_TYPECHECK pack-revindex.sp: SP_EXTRA_FLAGS += -Wno-memcpy-max-count @@ -2977,10 +2987,14 @@ $(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(LAZYLOAD_LIBCURL_OB $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS) -scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS) +scalar$X: $(SCALAR_OBJS) GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ $(filter %.o,$^) $(LIBS) +git-gvfs-helper$X: gvfs-helper.o http.o GIT-LDFLAGS $(GITLIBS) $(LAZYLOAD_LIBCURL_OBJ) + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ + $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS) + $(LIB_FILE): $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^ @@ -3749,7 +3763,7 @@ dist: git-archive$(X) configure @$(MAKE) -C git-gui TARDIR=../.dist-tmp-dir/git-gui dist-version ./git-archive --format=tar \ $(GIT_ARCHIVE_EXTRA_FILES) \ - --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar + --prefix=$(GIT_TARNAME)/ HEAD > $(GIT_TARNAME).tar @$(RM) -r .dist-tmp-dir gzip -f -9 $(GIT_TARNAME).tar diff --git a/README.md b/README.md index 026d5d85caef09..ce4a0e199310dc 100644 --- a/README.md +++ b/README.md @@ -1,148 +1,225 @@ -Git for Windows -=============== - -[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) -[![Open in Visual Studio Code](https://img.shields.io/static/v1?logo=visualstudiocode&label=&message=Open%20in%20Visual%20Studio%20Code&labelColor=2c2c32&color=007acc&logoColor=007acc)](https://open.vscode.dev/git-for-windows/git) -[![Build status](https://github.com/git-for-windows/git/workflows/CI/badge.svg)](https://github.com/git-for-windows/git/actions?query=branch%3Amain+event%3Apush) -[![Join the chat at https://gitter.im/git-for-windows/git](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/git-for-windows/git?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -This is [Git for Windows](http://git-for-windows.github.io/), the Windows port -of [Git](http://git-scm.com/). - -The Git for Windows project is run using a [governance -model](http://git-for-windows.github.io/governance-model.html). If you -encounter problems, you can report them as [GitHub -issues](https://github.com/git-for-windows/git/issues), discuss them in Git -for Windows' [Discussions](https://github.com/git-for-windows/git/discussions) -or on the [Git mailing list](mailto:git@vger.kernel.org), and [contribute bug -fixes](https://gitforwindows.org/how-to-participate). - -To build Git for Windows, please either install [Git for Windows' -SDK](https://gitforwindows.org/#download-sdk), start its `git-bash.exe`, `cd` -to your Git worktree and run `make`, or open the Git worktree as a folder in -Visual Studio. - -To verify that your build works, use one of the following methods: - -- If you want to test the built executables within Git for Windows' SDK, - prepend `/bin-wrappers` to the `PATH`. -- Alternatively, run `make install` in the Git worktree. -- If you need to test this in a full installer, run `sdk build - git-and-installer`. -- You can also "install" Git into an existing portable Git via `make install - DESTDIR=` where `` refers to the top-level directory of the - portable Git. In this instance, you will want to prepend that portable Git's - `/cmd` directory to the `PATH`, or test by running that portable Git's - `git-bash.exe` or `git-cmd.exe`. -- If you built using a recent Visual Studio, you can use the menu item - `Build>Install git` (you will want to click on `Project>CMake Settings for - Git` first, then click on `Edit JSON` and then point `installRoot` to the - `mingw64` directory of an already-unpacked portable Git). - - As in the previous bullet point, you will then prepend `/cmd` to the `PATH` - or run using the portable Git's `git-bash.exe` or `git-cmd.exe`. -- If you want to run the built executables in-place, but in a CMD instead of - inside a Bash, you can run a snippet like this in the `git-bash.exe` window - where Git was built (ensure that the `EOF` line has no leading spaces), and - then paste into the CMD window what was put in the clipboard: - - ```sh - clip.exe < -including full documentation and Git related tools. - -See [Documentation/gittutorial.adoc][] to get started, then see -[Documentation/giteveryday.adoc][] for a useful minimum set of commands, and -`Documentation/git-.adoc` for documentation of each command. -If git has been correctly installed, then the tutorial can also be -read with `man gittutorial` or `git help tutorial`, and the -documentation of each command with `man git-` or `git help -`. - -CVS users may also want to read [Documentation/gitcvs-migration.adoc][] -(`man gitcvs-migration` or `git help cvs-migration` if git is -installed). - -The user discussion and development of core Git take place on the Git -mailing list -- everyone is welcome to post bug reports, feature -requests, comments and patches to git@vger.kernel.org (read -[Documentation/SubmittingPatches][] for instructions on patch submission -and [Documentation/CodingGuidelines][]). - -Those wishing to help with error message, usage and informational message -string translations (localization l10) should see [po/README.md][] -(a `po` file is a Portable Object file that holds the translations). - -To subscribe to the list, send an email to -(see https://subspace.kernel.org/subscribing.html for details). The mailing -list archives are available at , - and other archival sites. -The core git mailing list is plain text (no HTML!). - -Issues which are security relevant should be disclosed privately to -the Git Security mailing list . - -The maintainer frequently sends the "What's cooking" reports that -list the current status of various development topics to the mailing -list. The discussion following them give a good reference for -project status, development direction and remaining tasks. - -The name "git" was given by Linus Torvalds when he wrote the very -first version. He described the tool as "the stupid content tracker" -and the name as (depending on your mood): - - - random three-letter combination that is pronounceable, and not - actually used by any common UNIX command. The fact that it is a - mispronunciation of "get" may or may not be relevant. - - stupid. contemptible and despicable. simple. Take your pick from the - dictionary of slang. - - "global information tracker": you're in a good mood, and it actually - works for you. Angels sing, and a light suddenly fills the room. - - "goddamn idiotic truckload of sh*t": when it breaks - -[INSTALL]: INSTALL -[Documentation/gittutorial.adoc]: Documentation/gittutorial.adoc -[Documentation/giteveryday.adoc]: Documentation/giteveryday.adoc -[Documentation/gitcvs-migration.adoc]: Documentation/gitcvs-migration.adoc -[Documentation/SubmittingPatches]: Documentation/SubmittingPatches -[Documentation/CodingGuidelines]: Documentation/CodingGuidelines -[po/README.md]: po/README.md +If you're working in a monorepo and want to take advantage of the performance boosts in +`microsoft/git`, then you can download the latest version installer for your OS from the +[Releases page](https://github.com/microsoft/git/releases). Alternatively, you can opt to install +via the command line, using the below instructions for supported OSes: + +## Windows + +__Note:__ Winget is still in public preview, meaning you currently +[need to take special installation steps](https://docs.microsoft.com/en-us/windows/package-manager/winget/#install-winget): +Either manually install the `.appxbundle` available at the +[preview version of App Installer](https://www.microsoft.com/p/app-installer/9nblggh4nns1?ocid=9nblggh4nns1_ORSEARCH_Bing&rtc=1&activetab=pivot:overviewtab), +or participate in the +[Windows Insider flight ring](https://insider.windows.com/https://insider.windows.com/) +since `winget` is available by default on preview versions of Windows. + +To install with Winget, run + +```shell +winget install --id microsoft.git +``` + +Double-check that you have the right version by running these commands, +which should have the same output: + +```shell +git version +scalar version +``` + +To upgrade `microsoft/git`, use the following Git command, which will download and install the latest +release. + +```shell +git update-microsoft-git +``` + +You may also be alerted with a notification to upgrade, which presents a single-click process for +running `git update-microsoft-git`. + +## macOS + +To install `microsoft/git` on macOS, first [be sure that Homebrew is installed](https://brew.sh/) then +install the `microsoft-git` cask with these steps: + +```shell +brew tap microsoft/git +brew install --cask microsoft-git +``` + +Double-check that you have the right version by running these commands, +which should have the same output: + +```shell +git version +scalar version +``` + +To upgrade microsoft/git, you can run the necessary `brew` commands: + +```shell +brew update +brew upgrade --cask microsoft-git +``` + +Or you can run the `git update-microsoft-git` command, which will run those brew commands for you. + +## Linux +### Ubuntu/Debian distributions + +On newer distributions*, you can install using the most recent Debian package. +To download and validate the signature of this package, run the following: + +```shell +# Install needed packages +sudo apt-get install -y curl debsig-verify + +# Download public key signature file +curl -s https://api.github.com/repos/microsoft/git/releases/latest \ +| grep -E 'browser_download_url.*msft-git-public.asc' \ +| cut -d : -f 2,3 \ +| tr -d \" \ +| xargs -I 'url' curl -L -o msft-git-public.asc 'url' + +# De-armor public key signature file +gpg --output msft-git-public.gpg --dearmor msft-git-public.asc + +# Note that the fingerprint of this key is "B8F12E25441124E1", which you can +# determine by running: +gpg --show-keys msft-git-public.asc | head -n 2 | tail -n 1 | tail -c 17 + +# Copy de-armored public key to debsig keyring folder +sudo mkdir /usr/share/debsig/keyrings/B8F12E25441124E1 +sudo mv msft-git-public.gpg /usr/share/debsig/keyrings/B8F12E25441124E1/ + +# Create an appropriate policy file +sudo mkdir /etc/debsig/policies/B8F12E25441124E1 +cat > generic.pol << EOL + + + + + + + + + + + +EOL + +sudo mv generic.pol /etc/debsig/policies/B8F12E25441124E1/generic.pol + +# Download Debian package +curl -s https://api.github.com/repos/microsoft/git/releases/latest \ +| grep "browser_download_url.*deb" \ +| cut -d : -f 2,3 \ +| tr -d \" \ +| xargs -I 'url' curl -L -o msft-git.deb 'url' + +# Verify +debsig-verify msft-git.deb + +# Install +sudo dpkg -i msft-git.deb +``` + +Double-check that you have the right version by running these commands, +which should have the same output: + +```shell +git version +scalar version +``` + +To upgrade, you will need to repeat these steps to reinstall. + +*Older distributions are missing some required dependencies. Even +though the package may appear to install successfully, `microsoft/ +git` will not function as expected. If you are running `Ubuntu 20.04` or +older, please follow the install from source instructions below +instead of installing the debian package. + +### Installing From Source + +On older or other distros you will need to compile and install `microsoft/git` from source: + +```shell +git clone https://github.com/microsoft/git microsoft-git +cd microsoft-git +make -j12 prefix=/usr/local +sudo make -j12 prefix=/usr/local install +``` + +For more assistance building Git from source, see +[the INSTALL file in the core Git project](https://github.com/git/git/blob/master/INSTALL). + +#### Common Debian based dependencies +While the INSTALL file covers dependencies in detail, here is a shortlist of common required dependencies on older Debian/Ubuntu distros: + +```shell +sudo apt-get update +sudo apt-get install libz-dev libssl-dev libcurl4-gnutls-dev libexpat1-dev gettext cmake gcc +``` + +Contributing +========================================================= + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit . + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/abspath.c b/abspath.c index 0c17e98654e4b0..e899f46d02097a 100644 --- a/abspath.c +++ b/abspath.c @@ -14,7 +14,7 @@ int is_directory(const char *path) } /* removes the last path component from 'path' except if 'path' is root */ -static void strip_last_component(struct strbuf *path) +void strip_last_path_component(struct strbuf *path) { size_t offset = offset_1st_component(path->buf); size_t len = path->len; @@ -119,7 +119,7 @@ static char *strbuf_realpath_1(struct strbuf *resolved, const char *path, continue; /* '.' component */ } else if (next.len == 2 && !strcmp(next.buf, "..")) { /* '..' component; strip the last path component */ - strip_last_component(resolved); + strip_last_path_component(resolved); continue; } @@ -171,7 +171,7 @@ static char *strbuf_realpath_1(struct strbuf *resolved, const char *path, * strip off the last component since it will * be replaced with the contents of the symlink */ - strip_last_component(resolved); + strip_last_path_component(resolved); } /* diff --git a/abspath.h b/abspath.h index 4653080d5e4b7a..06241ba13cf646 100644 --- a/abspath.h +++ b/abspath.h @@ -10,6 +10,11 @@ char *real_pathdup(const char *path, int die_on_error); const char *absolute_path(const char *path); char *absolute_pathdup(const char *path); +/** + * Remove the last path component from 'path' except if 'path' is root. + */ +void strip_last_path_component(struct strbuf *path); + /* * Concatenate "prefix" (if len is non-zero) and "path", with no * connecting characters (so "prefix" should end with a "/"). diff --git a/apply.c b/apply.c index 8f6704beecd1cc..0644430e9f2e52 100644 --- a/apply.c +++ b/apply.c @@ -20,6 +20,7 @@ #include "dir.h" #include "environment.h" #include "gettext.h" +#include "gvfs.h" #include "hex.h" #include "xdiff-interface.h" #include "merge-ll.h" @@ -3373,6 +3374,25 @@ static int checkout_target(struct index_state *istate, { struct checkout costate = CHECKOUT_INIT; + /* + * Do not checkout the entry if the skipworktree bit is set + * + * Both callers of this method (check_preimage and load_current) + * check for the existance of the file before calling this + * method so we know that the file doesn't exist at this point + * and we don't need to perform that check again here. + * We just need to check the skip-worktree and return. + * + * This is to prevent git from creating a file in the + * working directory that has the skip-worktree bit on, + * then updating the index from the patch and not keeping + * the working directory version up to date with what it + * changed the index version to be. + */ + if (gvfs_config_is_set(GVFS_USE_VIRTUAL_FILESYSTEM) && + ce_skip_worktree(ce)) + return 0; + costate.refresh_cache = 1; costate.istate = istate; if (checkout_entry(ce, &costate, NULL, NULL) || diff --git a/bin-wrappers/.gitignore b/bin-wrappers/.gitignore index 1c6c90458b7586..e481f5a45a7a0d 100644 --- a/bin-wrappers/.gitignore +++ b/bin-wrappers/.gitignore @@ -6,4 +6,5 @@ /git-upload-pack /scalar /test-fake-ssh +/test-gvfs-protocol /test-tool diff --git a/builtin.h b/builtin.h index 36e14fc1d2855e..ec07e249b50d6e 100644 --- a/builtin.h +++ b/builtin.h @@ -240,6 +240,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix, struct repository * int cmd_unpack_file(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_unpack_objects(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_update_index(int argc, const char **argv, const char *prefix, struct repository *repo); +int cmd_update_microsoft_git(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_update_ref(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_update_server_info(int argc, const char **argv, const char *prefix, struct repository *repo); int cmd_upload_archive(int argc, const char **argv, const char *prefix, struct repository *repo); diff --git a/builtin/add.c b/builtin/add.c index 9a4b5f712d8389..7d95c94096e525 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + /* * "git add" builtin command * @@ -5,6 +7,7 @@ */ #include "builtin.h" +#include "environment.h" #include "advice.h" #include "config.h" #include "lockfile.h" @@ -47,6 +50,7 @@ static int chmod_pathspec(struct repository *repo, int err; if (!include_sparse && + !core_virtualfilesystem && (ce_skip_worktree(ce) || !path_in_sparse_checkout(ce->name, repo->index))) continue; @@ -132,8 +136,9 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec * if (!seen[i]) { const char *path = pathspec->items[i].original; - if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) || - !path_in_sparse_checkout(path, repo->index)) { + if (!core_virtualfilesystem && + (matches_skip_worktree(pathspec, i, &skip_worktree_seen) || + !path_in_sparse_checkout(path, repo->index))) { string_list_append(&only_match_skip_worktree, pathspec->items[i].original); } else { @@ -143,7 +148,11 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec * } } - if (only_match_skip_worktree.nr) { + /* + * When using a virtual filesystem, we might re-add a path + * that is currently virtual and we want that to succeed. + */ + if (!core_virtualfilesystem && only_match_skip_worktree.nr) { advise_on_updating_sparse_paths(&only_match_skip_worktree); ret = 1; } @@ -529,7 +538,11 @@ int cmd_add(int argc, if (seen[i]) continue; - if (!include_sparse && + /* + * When using a virtual filesystem, we might re-add a path + * that is currently virtual and we want that to succeed. + */ + if (!include_sparse && !core_virtualfilesystem && matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) { string_list_append(&only_match_skip_worktree, pathspec.items[i].original); @@ -553,7 +566,6 @@ int cmd_add(int argc, } } - if (only_match_skip_worktree.nr) { advise_on_updating_sparse_paths(&only_match_skip_worktree); exit_status = 1; diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index 7f74bc702fa739..0aca3f89cc6cfc 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -155,7 +155,7 @@ static int checkout_all(struct index_state *index, const char *prefix, int prefi * first entry inside the expanded sparse directory). */ if (ignore_skip_worktree) { - ensure_full_index(index); + ensure_full_index_with_reason(index, "checkout-index"); ce = index->cache[i]; } } diff --git a/builtin/checkout.c b/builtin/checkout.c index 4d328563efcf54..c4b4f36a03a022 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -21,6 +21,7 @@ #include "object-file.h" #include "object-name.h" #include "object-store.h" +#include "packfile.h" #include "parse-options.h" #include "path.h" #include "preload-index.h" @@ -1050,8 +1051,16 @@ static void update_refs_for_switch(const struct checkout_opts *opts, strbuf_release(&msg); if (!opts->quiet && !opts->force_detach && - (new_branch_info->path || !strcmp(new_branch_info->name, "HEAD"))) + (new_branch_info->path || !strcmp(new_branch_info->name, "HEAD"))) { + unsigned long nr_unpack_entry_at_start; + + trace2_region_enter("tracking", "report_tracking", the_repository); + nr_unpack_entry_at_start = get_nr_unpack_entry(); report_tracking(new_branch_info); + trace2_data_intmax("tracking", NULL, "report_tracking/nr_unpack_entries", + (intmax_t)(get_nr_unpack_entry() - nr_unpack_entry_at_start)); + trace2_region_leave("tracking", "report_tracking", the_repository); + } } static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED, diff --git a/builtin/commit.c b/builtin/commit.c index 8ab0861ab0b59f..320491c03cb5f6 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -42,6 +42,7 @@ #include "commit-graph.h" #include "pretty.h" #include "trailer.h" +#include "trace2.h" static const char * const builtin_commit_usage[] = { N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u[]] [--amend]\n" @@ -164,6 +165,122 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un return 0; } +static int do_serialize = 0; +static char *serialize_path = NULL; + +static int reject_implicit = 0; +static int do_implicit_deserialize = 0; +static int do_explicit_deserialize = 0; +static char *deserialize_path = NULL; + +static enum wt_status_deserialize_wait implicit_deserialize_wait = DESERIALIZE_WAIT__UNSET; +static enum wt_status_deserialize_wait explicit_deserialize_wait = DESERIALIZE_WAIT__UNSET; + +/* + * --serialize | --serialize= + * + * Request that we serialize status output rather than or in addition to + * printing in any of the established formats. + * + * Without a path, we write binary serialization data to stdout (and omit + * the normal status output). + * + * With a path, we write binary serialization data to the and then + * write normal status output. + */ +static int opt_parse_serialize(const struct option *opt, const char *arg, int unset) +{ + enum wt_status_format *value = (enum wt_status_format *)opt->value; + if (unset || !arg) + *value = STATUS_FORMAT_SERIALIZE_V1; + + if (arg) { + free(serialize_path); + serialize_path = xstrdup(arg); + } + + if (do_explicit_deserialize) + die("cannot mix --serialize and --deserialize"); + do_implicit_deserialize = 0; + + do_serialize = 1; + return 0; +} + +/* + * --deserialize | --deserialize= | + * --no-deserialize + * + * Request that we deserialize status data from some existing resource + * rather than performing a status scan. + * + * The input source can come from stdin or a path given here -- or be + * inherited from the config settings. + */ +static int opt_parse_deserialize(const struct option *opt UNUSED, const char *arg, int unset) +{ + if (unset) { + do_implicit_deserialize = 0; + do_explicit_deserialize = 0; + } else { + if (do_serialize) + die("cannot mix --serialize and --deserialize"); + if (arg) { + /* override config or stdin */ + free(deserialize_path); + deserialize_path = xstrdup(arg); + } + if (!deserialize_path || !*deserialize_path) + do_explicit_deserialize = 1; /* read stdin */ + else if (wt_status_deserialize_access(deserialize_path, R_OK) == 0) + do_explicit_deserialize = 1; /* can read from this file */ + else { + /* + * otherwise, silently fallback to the normal + * collection scan + */ + do_implicit_deserialize = 0; + do_explicit_deserialize = 0; + } + } + + return 0; +} + +static enum wt_status_deserialize_wait parse_dw(const char *arg) +{ + int tenths; + + if (!strcmp(arg, "fail")) + return DESERIALIZE_WAIT__FAIL; + else if (!strcmp(arg, "block")) + return DESERIALIZE_WAIT__BLOCK; + else if (!strcmp(arg, "no")) + return DESERIALIZE_WAIT__NO; + + /* + * Otherwise, assume it is a timeout in tenths of a second. + * If it contains a bogus value, atol() will return zero + * which is OK. + */ + tenths = atol(arg); + if (tenths < 0) + tenths = DESERIALIZE_WAIT__NO; + return tenths; +} + +static int opt_parse_deserialize_wait(const struct option *opt UNUSED, + const char *arg, + int unset) +{ + if (unset) + explicit_deserialize_wait = DESERIALIZE_WAIT__UNSET; + else + explicit_deserialize_wait = parse_dw(arg); + + return 0; +} + static int opt_parse_m(const struct option *opt, const char *arg, int unset) { struct strbuf *buf = opt->value; @@ -268,7 +385,7 @@ static int list_paths(struct string_list *list, const char *with_tree, } /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(the_repository->index); + ensure_full_index_unaudited(the_repository->index); for (i = 0; i < the_repository->index->cache_nr; i++) { const struct cache_entry *ce = the_repository->index->cache[i]; struct string_list_item *item; @@ -1018,7 +1135,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, int i, ita_nr = 0; /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(the_repository->index); + ensure_full_index_unaudited(the_repository->index); for (i = 0; i < the_repository->index->cache_nr; i++) if (ce_intent_to_add(the_repository->index->cache[i])) ita_nr++; @@ -1188,6 +1305,8 @@ static enum untracked_status_type parse_untracked_setting_name(const char *u) return SHOW_NORMAL_UNTRACKED_FILES; else if (!strcmp(u, "all")) return SHOW_ALL_UNTRACKED_FILES; + else if (!strcmp(u,"complete")) + return SHOW_COMPLETE_UNTRACKED_FILES; else return SHOW_UNTRACKED_FILES_ERROR; } @@ -1483,6 +1602,28 @@ static int git_status_config(const char *k, const char *v, s->relative_paths = git_config_bool(k, v); return 0; } + if (!strcmp(k, "status.deserializepath")) { + /* + * Automatically assume deserialization if this is + * set in the config and the file exists. Do not + * complain if the file does not exist, because we + * silently fall back to normal mode. + */ + if (v && *v && access(v, R_OK) == 0) { + do_implicit_deserialize = 1; + deserialize_path = xstrdup(v); + } else { + reject_implicit = 1; + } + return 0; + } + if (!strcmp(k, "status.deserializewait")) { + if (!v || !*v) + implicit_deserialize_wait = DESERIALIZE_WAIT__UNSET; + else + implicit_deserialize_wait = parse_dw(v); + return 0; + } if (!strcmp(k, "status.showuntrackedfiles")) { enum untracked_status_type u; @@ -1522,7 +1663,8 @@ struct repository *repo UNUSED) static const char *rename_score_arg = (const char *)-1; static struct wt_status s; unsigned int progress_flag = 0; - int fd; + int try_deserialize; + int fd = -1; struct object_id oid; static struct option builtin_status_options[] = { OPT__VERBOSE(&verbose, N_("be verbose")), @@ -1537,6 +1679,15 @@ struct repository *repo UNUSED) OPT_CALLBACK_F(0, "porcelain", &status_format, N_("version"), N_("machine-readable output"), PARSE_OPT_OPTARG, opt_parse_porcelain), + OPT_CALLBACK_F(0, "serialize", &status_format, + N_("path"), N_("serialize raw status data to path or stdout"), + PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_serialize), + OPT_CALLBACK_F(0, "deserialize", NULL, + N_("path"), N_("deserialize raw status data from file"), + PARSE_OPT_OPTARG, opt_parse_deserialize), + OPT_CALLBACK_F(0, "deserialize-wait", NULL, + N_("fail|block|no"), N_("how to wait if status cache file is invalid"), + PARSE_OPT_OPTARG, opt_parse_deserialize_wait), OPT_SET_INT(0, "long", &status_format, N_("show status in long format (default)"), STATUS_FORMAT_LONG), @@ -1598,10 +1749,53 @@ struct repository *repo UNUSED) s.show_untracked_files == SHOW_NO_UNTRACKED_FILES) die(_("Unsupported combination of ignored and untracked-files arguments")); + if (s.show_untracked_files == SHOW_COMPLETE_UNTRACKED_FILES && + s.show_ignored_mode == SHOW_NO_IGNORED) + die(_("Complete Untracked only supported with ignored files")); + parse_pathspec(&s.pathspec, 0, PATHSPEC_PREFER_FULL, prefix, argv); + /* + * If we want to try to deserialize status data from a cache file, + * we need to re-order the initialization code. The problem is that + * this makes for a very nasty diff and causes merge conflicts as we + * carry it forward. And it easy to mess up the merge, so we + * duplicate some code here to hopefully reduce conflicts. + */ + try_deserialize = (!do_serialize && + (do_implicit_deserialize || do_explicit_deserialize)); + + /* + * Disable deserialize when verbose is set because it causes us to + * print diffs for each modified file, but that requires us to have + * the index loaded and we don't want to do that (at least not now for + * this seldom used feature). My fear is that would further tangle + * the merge conflict with upstream. + * + * TODO Reconsider this in the future. + */ + if (try_deserialize && verbose) { + trace2_data_string("status", the_repository, "deserialize/reject", + "args/verbose"); + try_deserialize = 0; + } + + if (try_deserialize) + goto skip_init; + /* + * If we implicitly received a status cache pathname from the config + * and the file does not exist, we silently reject it and do the normal + * status "collect". Fake up some trace2 messages to reflect this and + * assist post-processors know this case is different. + */ + if (!do_serialize && reject_implicit) { + trace2_cmd_mode("implicit-deserialize"); + trace2_data_string("status", the_repository, "deserialize/reject", + "status-cache/access"); + } + enable_fscache(0); if (status_format != STATUS_FORMAT_PORCELAIN && status_format != STATUS_FORMAT_PORCELAIN_V2) @@ -1616,6 +1810,7 @@ struct repository *repo UNUSED) else fd = -1; +skip_init: s.is_initial = repo_get_oid(the_repository, s.reference, &oid) ? 1 : 0; if (!s.is_initial) oidcpy(&s.oid_commit, &oid); @@ -1632,6 +1827,36 @@ struct repository *repo UNUSED) s.rename_score = parse_rename_score(&rename_score_arg); } + if (try_deserialize) { + int result; + enum wt_status_deserialize_wait dw = implicit_deserialize_wait; + if (explicit_deserialize_wait != DESERIALIZE_WAIT__UNSET) + dw = explicit_deserialize_wait; + if (dw == DESERIALIZE_WAIT__UNSET) + dw = DESERIALIZE_WAIT__NO; + + if (s.relative_paths) + s.prefix = prefix; + + trace2_cmd_mode("deserialize"); + result = wt_status_deserialize(&s, deserialize_path, dw); + if (result == DESERIALIZE_OK) + return 0; + if (dw == DESERIALIZE_WAIT__FAIL) + die(_("Rejected status serialization cache")); + + /* deserialize failed, so force the initialization we skipped above. */ + enable_fscache(1); + repo_read_index_preload(the_repository, &s.pathspec, 0); + refresh_index(the_repository->index, REFRESH_QUIET|REFRESH_UNMERGED, &s.pathspec, NULL, NULL); + + if (use_optional_locks()) + fd = repo_hold_locked_index(the_repository, &index_lock, 0); + else + fd = -1; + } + + trace2_cmd_mode("collect"); wt_status_collect(&s); if (0 <= fd) @@ -1640,6 +1865,17 @@ struct repository *repo UNUSED) if (s.relative_paths) s.prefix = prefix; + if (serialize_path) { + int fd_serialize = xopen(serialize_path, + O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd_serialize < 0) + die_errno(_("could not serialize to '%s'"), + serialize_path); + trace2_cmd_mode("serialize"); + wt_status_serialize_v1(fd_serialize, &s); + close(fd_serialize); + } + wt_status_print(&s); wt_status_collect_free_buffers(&s); diff --git a/builtin/difftool.c b/builtin/difftool.c index e0dc7a1a9179bd..445c5a7c810b19 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -607,7 +607,7 @@ static int run_dir_diff(struct repository *repo, ret = run_command(&cmd); /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(&wtindex); + ensure_full_index_unaudited(&wtindex); /* * If the diff includes working copy files and those diff --git a/builtin/fetch.c b/builtin/fetch.c index 40a0e8d24434f2..bd81ef1cfba62f 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -21,6 +21,9 @@ #include "string-list.h" #include "remote.h" #include "transport.h" +#include "gvfs.h" +#include "gvfs-helper-client.h" +#include "packfile.h" #include "run-command.h" #include "parse-options.h" #include "sigchain.h" @@ -1160,6 +1163,13 @@ static int store_updated_refs(struct display_state *display_state, opt.exclude_hidden_refs_section = "fetch"; rm = ref_map; + + /* + * Before checking connectivity, be really sure we have the + * latest pack-files loaded into memory. + */ + reprepare_packed_git(the_repository); + if (check_connected(iterate_ref_map, &rm, &opt)) { rc = error(_("%s did not send all necessary objects"), display_state->url); @@ -2540,6 +2550,9 @@ int cmd_fetch(int argc, } string_list_remove_duplicates(&list, 0); + if (core_gvfs & GVFS_PREFETCH_DURING_FETCH) + gh_client__prefetch(0, NULL); + if (negotiate_only) { struct oidset acked_commits = OIDSET_INIT; struct oidset_iter iter; diff --git a/builtin/fsck.c b/builtin/fsck.c index e7d96a9c8ea586..af4ed3c57d7e60 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -815,7 +815,7 @@ static void fsck_index(struct index_state *istate, const char *index_path, unsigned int i; /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(istate); + ensure_full_index_unaudited(istate); for (i = 0; i < istate->cache_nr; i++) { unsigned int mode; struct blob *blob; diff --git a/builtin/gc.c b/builtin/gc.c index 7dc94f243d7dc6..0a2d9622b15bfb 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -13,12 +13,15 @@ #define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS +#include "git-compat-util.h" #include "builtin.h" #include "abspath.h" +#include "copy.h" #include "date.h" #include "dir.h" #include "environment.h" #include "hex.h" +#include "gvfs.h" #include "config.h" #include "tempfile.h" #include "lockfile.h" @@ -896,6 +899,9 @@ int cmd_gc(int argc, if (quiet) strvec_push(&repack, "-q"); + if ((!opts.auto_flag || (opts.auto_flag && cfg.gc_auto_threshold > 0)) && gvfs_config_is_set(GVFS_BLOCK_COMMANDS)) + die(_("'git gc' is not supported on a GVFS repo")); + if (opts.auto_flag) { if (cfg.detach_auto && opts.detach < 0) opts.detach = 1; @@ -1297,18 +1303,25 @@ static int write_loose_object_to_stdin(const struct object_id *oid, return ++(d->count) > d->batch_size; } +static const char *shared_object_dir = NULL; + static int pack_loose(struct maintenance_run_opts *opts) { struct repository *r = the_repository; int result = 0; struct write_loose_object_data data; struct child_process pack_proc = CHILD_PROCESS_INIT; + const char *object_dir = r->objects->odb->path; + + /* If set, use the shared object directory. */ + if (shared_object_dir) + object_dir = shared_object_dir; /* * Do not start pack-objects process * if there are no loose objects. */ - if (!for_each_loose_file_in_objdir(r->objects->odb->path, + if (!for_each_loose_file_in_objdir(object_dir, bail_on_loose, NULL, NULL, NULL)) return 0; @@ -1320,7 +1333,7 @@ static int pack_loose(struct maintenance_run_opts *opts) strvec_push(&pack_proc.args, "--quiet"); else strvec_push(&pack_proc.args, "--no-quiet"); - strvec_pushf(&pack_proc.args, "%s/pack/loose", r->objects->odb->path); + strvec_pushf(&pack_proc.args, "%s/pack/loose", object_dir); pack_proc.in = -1; @@ -1348,7 +1361,7 @@ static int pack_loose(struct maintenance_run_opts *opts) else if (data.batch_size > 0) data.batch_size--; /* Decrease for equality on limit. */ - for_each_loose_file_in_objdir(r->objects->odb->path, + for_each_loose_file_in_objdir(object_dir, write_loose_object_to_stdin, NULL, NULL, @@ -1513,6 +1526,186 @@ static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts return 0; } +static void link_or_copy_or_die(const char *src, const char *dst) +{ + if (!link(src, dst)) + return; + + /* Use copy operation if src and dst are on different file systems. */ + if (errno != EXDEV) + warning_errno(_("failed to link '%s' to '%s'"), src, dst); + + if (copy_file(dst, src, 0444)) + die_errno(_("failed to copy '%s' to '%s'"), src, dst); +} + +static void rename_or_copy_or_die(const char *src, const char *dst) +{ + if (!rename(src, dst)) + return; + + /* Use copy and delete if src and dst are on different file systems. */ + if (errno != EXDEV) + warning_errno(_("failed to move '%s' to '%s'"), src, dst); + + if (copy_file(dst, src, 0444)) + die_errno(_("failed to copy '%s' to '%s'"), src, dst); + + if (unlink(src)) + die_errno(_("failed to delete '%s'"), src); +} + +static void migrate_pack(const char *srcdir, const char *dstdir, + const char *pack_filename) +{ + size_t basenamelen, srclen, dstlen; + struct strbuf src = STRBUF_INIT, dst = STRBUF_INIT; + struct { + const char *ext; + unsigned move:1; + } files[] = { + {".pack", 0}, + {".keep", 0}, + {".rev", 0}, + {".idx", 1}, /* The index file must be atomically moved last. */ + }; + + trace2_region_enter("maintenance", "migrate_pack", the_repository); + + basenamelen = strlen(pack_filename) - 5; /* .pack */ + strbuf_addstr(&src, srcdir); + strbuf_addch(&src, '/'); + strbuf_add(&src, pack_filename, basenamelen); + strbuf_addstr(&src, ".idx"); + + /* A pack without an index file is not yet ready to be migrated. */ + if (!file_exists(src.buf)) + goto cleanup; + + strbuf_setlen(&src, src.len - 4 /* .idx */); + strbuf_addstr(&dst, dstdir); + strbuf_addch(&dst, '/'); + strbuf_add(&dst, pack_filename, basenamelen); + + srclen = src.len; + dstlen = dst.len; + + /* Move or copy files from the source directory to the destination. */ + for (size_t i = 0; i < ARRAY_SIZE(files); i++) { + strbuf_setlen(&src, srclen); + strbuf_addstr(&src, files[i].ext); + + if (!file_exists(src.buf)) + continue; + + strbuf_setlen(&dst, dstlen); + strbuf_addstr(&dst, files[i].ext); + + if (files[i].move) + rename_or_copy_or_die(src.buf, dst.buf); + else + link_or_copy_or_die(src.buf, dst.buf); + } + + /* + * Now the pack and all associated files exist at the destination we can + * now clean up the files in the source directory. + */ + for (size_t i = 0; i < ARRAY_SIZE(files); i++) { + /* Files that were moved rather than copied have no clean up. */ + if (files[i].move) + continue; + + strbuf_setlen(&src, srclen); + strbuf_addstr(&src, files[i].ext); + + /* Files that never existed in originally have no clean up.*/ + if (!file_exists(src.buf)) + continue; + + if (unlink(src.buf)) + warning_errno(_("failed to delete '%s'"), src.buf); + } + +cleanup: + strbuf_release(&src); + strbuf_release(&dst); + + trace2_region_leave("maintenance", "migrate_pack", the_repository); +} + +static void move_pack_to_shared_cache(const char *full_path, size_t full_path_len, + const char *file_name, void *data) +{ + char *srcdir; + const char *dstdir = (const char *)data; + + /* We only care about the actual pack files here. + * The associated .idx, .keep, .rev files will be copied in tandem + * with the pack file, with the index file being moved last. + * The original locations of the non-index files will only deleted + * once all other files have been copied/moved. + */ + if (!ends_with(file_name, ".pack")) + return; + + srcdir = xstrndup(full_path, full_path_len - strlen(file_name) - 1); + + migrate_pack(srcdir, dstdir, file_name); + + free(srcdir); +} + +static int move_loose_object_to_shared_cache(const struct object_id *oid, + const char *path, + UNUSED void *data) +{ + struct stat st; + struct strbuf dst = STRBUF_INIT; + char *hex = oid_to_hex(oid); + + strbuf_addf(&dst, "%s/%.2s/", shared_object_dir, hex); + + if (stat(dst.buf, &st)) { + if (mkdir(dst.buf, 0777)) + die_errno(_("failed to create directory '%s'"), dst.buf); + } else if (!S_ISDIR(st.st_mode)) + die(_("expected '%s' to be a directory"), dst.buf); + + strbuf_addstr(&dst, hex+2); + rename_or_copy_or_die(path, dst.buf); + + strbuf_release(&dst); + return 0; +} + +static int maintenance_task_cache_local_objs(UNUSED struct maintenance_run_opts *opts, + UNUSED struct gc_config *cfg) +{ + struct strbuf dstdir = STRBUF_INIT; + struct repository *r = the_repository; + + /* This task is only applicable with a VFS/Scalar shared cache. */ + if (!shared_object_dir) + return 0; + + /* If the dest is the same as the local odb path then we do nothing. */ + if (!fspathcmp(r->objects->odb->path, shared_object_dir)) + goto cleanup; + + strbuf_addf(&dstdir, "%s/pack", shared_object_dir); + + for_each_file_in_pack_dir(r->objects->odb->path, move_pack_to_shared_cache, + dstdir.buf); + + for_each_loose_object(move_loose_object_to_shared_cache, NULL, + FOR_EACH_OBJECT_LOCAL_ONLY); + +cleanup: + strbuf_release(&dstdir); + return 0; +} + typedef int maintenance_task_fn(struct maintenance_run_opts *opts, struct gc_config *cfg); @@ -1545,6 +1738,7 @@ enum maintenance_task_label { TASK_REFLOG_EXPIRE, TASK_WORKTREE_PRUNE, TASK_RERERE_GC, + TASK_CACHE_LOCAL_OBJS, /* Leave as final value */ TASK__COUNT @@ -1596,6 +1790,10 @@ static struct maintenance_task tasks[] = { maintenance_task_rerere_gc, rerere_gc_condition, }, + [TASK_CACHE_LOCAL_OBJS] = { + "cache-local-objects", + maintenance_task_cache_local_objs, + }, }; static int compare_tasks_by_selection(const void *a_, const void *b_) @@ -1690,6 +1888,8 @@ static void initialize_maintenance_strategy(void) tasks[TASK_LOOSE_OBJECTS].schedule = SCHEDULE_DAILY; tasks[TASK_PACK_REFS].enabled = 1; tasks[TASK_PACK_REFS].schedule = SCHEDULE_WEEKLY; + tasks[TASK_CACHE_LOCAL_OBJS].enabled = 1; + tasks[TASK_CACHE_LOCAL_OBJS].schedule = SCHEDULE_WEEKLY; } } @@ -1762,6 +1962,7 @@ static int maintenance_run(int argc, const char **argv, const char *prefix, int i; struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT; struct gc_config cfg = GC_CONFIG_INIT; + const char *tmp_obj_dir = NULL; struct option builtin_maintenance_run_options[] = { OPT_BOOL(0, "auto", &opts.auto_flag, N_("run tasks based on the state of the repository")), @@ -1799,6 +2000,17 @@ static int maintenance_run(int argc, const char **argv, const char *prefix, usage_with_options(builtin_maintenance_run_usage, builtin_maintenance_run_options); + /* + * To enable the VFS for Git/Scalar shared object cache, use + * the gvfs.sharedcache config option to redirect the + * maintenance to that location. + */ + if (!git_config_get_value("gvfs.sharedcache", &tmp_obj_dir) && + tmp_obj_dir) { + shared_object_dir = xstrdup(tmp_obj_dir); + setenv(DB_ENVIRONMENT, shared_object_dir, 1); + } + ret = maintenance_run_tasks(&opts, &cfg); gc_config_release(&cfg); return ret; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index bb7925bd29f0aa..55e5116cade5cc 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -893,7 +893,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, if (startup_info->have_repository) { read_lock(); collision_test_needed = has_object(the_repository, oid, - HAS_OBJECT_FETCH_PROMISOR); + OBJECT_INFO_FOR_PREFETCH); read_unlock(); } @@ -1900,6 +1900,7 @@ int cmd_index_pack(int argc, unsigned foreign_nr = 1; /* zero is a "good" value, assume bad */ int report_end_of_input = 0; int hash_algo = 0; + int dash_o = 0; /* * index-pack never needs to fetch missing objects except when @@ -1984,6 +1985,7 @@ int cmd_index_pack(int argc, if (index_name || (i+1) >= argc) usage(index_pack_usage); index_name = argv[++i]; + dash_o = 1; } else if (starts_with(arg, "--index-version=")) { char *c; opts.version = strtoul(arg + 16, &c, 10); @@ -2037,6 +2039,8 @@ int cmd_index_pack(int argc, repo_set_hash_algo(the_repository, GIT_HASH_SHA1); opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY); + if (rev_index && dash_o && !ends_with(index_name, ".idx")) + rev_index = 0; if (rev_index) { opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV; if (index_name) diff --git a/builtin/ls-files.c b/builtin/ls-files.c index be74f0a03b20f3..cf73cd888859f8 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -414,7 +414,7 @@ static void show_files(struct repository *repo, struct dir_struct *dir) return; if (!show_sparse_dirs) - ensure_full_index(repo->index); + ensure_full_index_with_reason(repo->index, "ls-files"); for (i = 0; i < repo->index->cache_nr; i++) { const struct cache_entry *ce = repo->index->cache[i]; diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 3314fb13361d64..b0bc54d2e473c3 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -66,7 +66,7 @@ static void merge_all(void) { int i; /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(the_repository->index); + ensure_full_index_unaudited(the_repository->index); for (i = 0; i < the_repository->index->cache_nr; i++) { const struct cache_entry *ce = the_repository->index->cache[i]; if (!ce_stage(ce)) @@ -98,7 +98,7 @@ int cmd_merge_index(int argc, repo_read_index(the_repository); /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(the_repository->index); + ensure_full_index_unaudited(the_repository->index); i = 1; if (!strcmp(argv[i], "-o")) { diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index b16e1a1ef219b0..ea67312119d0b3 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -203,6 +203,7 @@ static int keep_unreachable, unpack_unreachable, include_tag; static timestamp_t unpack_unreachable_expiration; static int pack_loose_unreachable; static int cruft; +static int shallow = 0; static timestamp_t cruft_expiration; static int local; static int have_non_local_packs; @@ -4566,6 +4567,7 @@ static void get_object_list_path_walk(struct rev_info *revs) * base objects. */ info.prune_all_uninteresting = sparse; + info.edge_aggressive = shallow; if (walk_objects_by_path(&info)) die(_("failed to pack objects via path-walk")); @@ -4767,7 +4769,6 @@ int cmd_pack_objects(int argc, struct repository *repo UNUSED) { int use_internal_rev_list = 0; - int shallow = 0; int all_progress_implied = 0; struct strvec rp = STRVEC_INIT; int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0; @@ -4955,10 +4956,6 @@ int cmd_pack_objects(int argc, warning(_("cannot use delta islands with --path-walk")); path_walk = 0; } - if (path_walk && shallow) { - warning(_("cannot use --shallow with --path-walk")); - path_walk = 0; - } if (path_walk) { strvec_push(&rp, "--boundary"); /* diff --git a/builtin/push.c b/builtin/push.c index 92d530e5c4dff0..b1581a9c091502 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -619,6 +619,10 @@ int cmd_push(int argc, else if (recurse_submodules == RECURSE_SUBMODULES_ONLY) flags |= TRANSPORT_RECURSE_SUBMODULES_ONLY; + prepare_repo_settings(the_repository); + if (the_repository->settings.pack_use_path_walk) + flags |= TRANSPORT_PUSH_NO_REUSE_DELTA; + if (tags) refspec_append(&rs, "refs/tags/*"); diff --git a/builtin/read-tree.c b/builtin/read-tree.c index a8f352f7cd9b10..3be3ac29f77a04 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -231,7 +231,8 @@ int cmd_read_tree(int argc, setup_work_tree(); if (opts.skip_sparse_checkout) - ensure_full_index(the_repository->index); + ensure_full_index_with_reason(the_repository->index, + "read-tree"); if (opts.merge) { switch (stage - 1) { diff --git a/builtin/repack.c b/builtin/repack.c index 228a107e3f9fda..6dfad58415befa 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -24,6 +24,7 @@ #include "pack-bitmap.h" #include "refs.h" #include "list-objects-filter-options.h" +#include "gvfs.h" #define ALL_INTO_ONE 1 #define LOOSEN_UNREACHABLE 2 @@ -1145,6 +1146,7 @@ int cmd_repack(int argc, struct tempfile *refs_snapshot = NULL; int i, ext, ret; int show_progress; + const char *tmp_obj_dir = NULL; /* variables to be filled by option parsing */ int delete_redundant = 0; @@ -1273,6 +1275,10 @@ int cmd_repack(int argc, write_bitmaps = 0; } + if (gvfs_config_is_set(GVFS_ANY_MASK) && + !git_config_get_value("gvfs.sharedcache", &tmp_obj_dir)) + warning(_("shared object cache is configured but will not be repacked")); + if (write_midx && write_bitmaps) { struct strbuf path = STRBUF_INIT; diff --git a/builtin/reset.c b/builtin/reset.c index 46df000e7b15c4..3051a92385127a 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -40,6 +40,8 @@ #include "add-interactive.h" #include "strbuf.h" #include "quote.h" +#include "dir.h" +#include "entry.h" #define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000) @@ -160,9 +162,48 @@ static void update_index_from_diff(struct diff_queue_struct *q, for (i = 0; i < q->nr; i++) { int pos; + int respect_skip_worktree = 1; struct diff_filespec *one = q->queue[i]->one; + struct diff_filespec *two = q->queue[i]->two; int is_in_reset_tree = one->mode && !is_null_oid(&one->oid); + int is_missing = !(one->mode && !is_null_oid(&one->oid)); + int was_missing = !two->mode && is_null_oid(&two->oid); struct cache_entry *ce; + struct cache_entry *ceBefore; + struct checkout state = CHECKOUT_INIT; + + /* + * When using the virtual filesystem feature, the cache entries that are + * added here will not have the skip-worktree bit set. + * + * Without this code there is data that is lost because the files that + * would normally be in the working directory are not there and show as + * deleted for the next status or in the case of added files just disappear. + * We need to create the previous version of the files in the working + * directory so that they will have the right content and the next + * status call will show modified or untracked files correctly. + */ + if (core_virtualfilesystem && !file_exists(two->path)) + { + respect_skip_worktree = 0; + pos = index_name_pos(the_repository->index, two->path, strlen(two->path)); + + if ((pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) && + (is_missing || !was_missing)) + { + state.force = 1; + state.refresh_cache = 1; + state.istate = the_repository->index; + ceBefore = make_cache_entry(the_repository->index, two->mode, + &two->oid, two->path, + 0, 0); + if (!ceBefore) + die(_("make_cache_entry failed for path '%s'"), + two->path); + + checkout_entry(ceBefore, &state, NULL, NULL); + } + } if (!is_in_reset_tree && !intent_to_add) { remove_file_from_index(the_repository->index, one->path); @@ -181,8 +222,14 @@ static void update_index_from_diff(struct diff_queue_struct *q, * to properly construct the reset sparse directory. */ pos = index_name_pos(the_repository->index, one->path, strlen(one->path)); - if ((pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) || - (pos < 0 && !path_in_sparse_checkout(one->path, the_repository->index))) + + /* + * Do not add the SKIP_WORKTREE bit back if we populated the + * file on purpose in a virtual filesystem scenario. + */ + if (respect_skip_worktree && + ((pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) || + (pos < 0 && !path_in_sparse_checkout(one->path, the_repository->index)))) ce->ce_flags |= CE_SKIP_WORKTREE; if (!ce) @@ -215,7 +262,8 @@ static int read_from_tree(const struct pathspec *pathspec, opt.add_remove = diff_addremove; if (pathspec->nr && pathspec_needs_expanded_index(the_repository->index, pathspec)) - ensure_full_index(the_repository->index); + ensure_full_index_with_reason(the_repository->index, + "reset pathspec"); if (do_diff_cache(tree_oid, &opt)) return 1; diff --git a/builtin/rm.c b/builtin/rm.c index a6565a69cfca87..df9c6e77af1655 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -7,6 +7,7 @@ #define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" +#include "environment.h" #include "advice.h" #include "config.h" #include "lockfile.h" @@ -309,12 +310,13 @@ int cmd_rm(int argc, seen = xcalloc(pathspec.nr, 1); if (pathspec_needs_expanded_index(the_repository->index, &pathspec)) - ensure_full_index(the_repository->index); + ensure_full_index_with_reason(the_repository->index, + "rm pathspec"); for (unsigned int i = 0; i < the_repository->index->cache_nr; i++) { const struct cache_entry *ce = the_repository->index->cache[i]; - if (!include_sparse && + if (!include_sparse && !core_virtualfilesystem && (ce_skip_worktree(ce) || !path_in_sparse_checkout(ce->name, the_repository->index))) continue; @@ -351,7 +353,11 @@ int cmd_rm(int argc, *original ? original : "."); } - if (only_match_skip_worktree.nr) { + /* + * When using a virtual filesystem, we might re-add a path + * that is currently virtual and we want that to succeed. + */ + if (!core_virtualfilesystem && only_match_skip_worktree.nr) { advise_on_updating_sparse_paths(&only_match_skip_worktree); ret = 1; } diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 1bf01591b27523..8425c1a69644f5 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -112,7 +112,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix, static void clean_tracked_sparse_directories(struct repository *r) { - int i, was_full = 0; + int i, value, was_full = 0; struct strbuf path = STRBUF_INIT; size_t pathlen; struct string_list_item *item; @@ -128,6 +128,13 @@ static void clean_tracked_sparse_directories(struct repository *r) !r->index->sparse_checkout_patterns->use_cone_patterns) return; + /* + * Users can disable this behavior. + */ + if (!repo_config_get_bool(r, "index.deletesparsedirectories", &value) && + !value) + return; + /* * Use the sparse index as a data structure to assist finding * directories that are safe to delete. This conversion to a @@ -201,7 +208,8 @@ static void clean_tracked_sparse_directories(struct repository *r) strbuf_release(&path); if (was_full) - ensure_full_index(r->index); + ensure_full_index_with_reason(r->index, + "sparse-checkout:was full"); } static int update_working_directory(struct pattern_list *pl) @@ -431,7 +439,8 @@ static int update_modes(int *cone_mode, int *sparse_index) the_repository->index->updated_workdir = 1; if (!*sparse_index) - ensure_full_index(the_repository->index); + ensure_full_index_with_reason(the_repository->index, + "sparse-checkout:disabling sparse index"); } return 0; diff --git a/builtin/stash.c b/builtin/stash.c index cfbd92852a6557..29acc8baa8e272 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -402,7 +402,7 @@ static int restore_untracked(struct object_id *u_tree) child_process_init(&cp); cp.git_cmd = 1; - strvec_pushl(&cp.args, "checkout-index", "--all", NULL); + strvec_pushl(&cp.args, "checkout-index", "--all", "-f", NULL); strvec_pushf(&cp.env, "GIT_INDEX_FILE=%s", stash_index_path.buf); @@ -1559,7 +1559,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q char *ps_matched = xcalloc(ps->nr, 1); /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(the_repository->index); + ensure_full_index_unaudited(the_repository->index); for (size_t i = 0; i < the_repository->index->cache_nr; i++) ce_path_match(the_repository->index, the_repository->index->cache[i], ps, ps_matched); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 53da2116ddf576..fac542a5136e22 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -3400,7 +3400,7 @@ static void die_on_index_match(const char *path, int force) char *ps_matched = xcalloc(ps.nr, 1); /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(the_repository->index); + ensure_full_index_unaudited(the_repository->index); /* * Since there is only one pathspec, we just need to diff --git a/builtin/survey.c b/builtin/survey.c index 096a1bb92e597f..ffcba893b16825 100644 --- a/builtin/survey.c +++ b/builtin/survey.c @@ -13,11 +13,12 @@ #include "ref-filter.h" #include "refs.h" #include "revision.h" +#include "run-command.h" #include "strbuf.h" #include "strvec.h" -#include "tag.h" #include "trace2.h" -#include "color.h" +#include "tree.h" +#include "tree-walk.h" static const char * const survey_usage[] = { N_("(EXPERIMENTAL!) git survey "), @@ -41,6 +42,16 @@ static struct survey_refs_wanted default_ref_options = { struct survey_opts { int verbose; int show_progress; + int show_name_rev; + + int show_largest_commits_by_nr_parents; + int show_largest_commits_by_size_bytes; + + int show_largest_trees_by_nr_entries; + int show_largest_trees_by_size_bytes; + + int show_largest_blobs_by_size_bytes; + int top_nr; struct survey_refs_wanted refs; }; @@ -53,6 +64,312 @@ struct survey_report_ref_summary { size_t tags_annotated_nr; size_t others_nr; size_t unknown_nr; + + size_t cnt_symref; + + size_t cnt_packed; + size_t cnt_loose; + + /* + * Measure the length of the refnames. We can look for + * potential platform limits. The partial sums may help us + * estimate the size of a haves/wants conversation, since each + * refname and a SHA must be transmitted. + */ + size_t len_max_local_refname; + size_t len_sum_local_refnames; + size_t len_max_remote_refname; + size_t len_sum_remote_refnames; +}; + +/* + * HBIN -- hex binning (histogram bucketing). + * + * We create histograms for various counts and sums. Since we have a + * wide range of values (objects range in size from 1 to 4G bytes), a + * linear bucketing is not interesting. Instead, lets use a + * log16()-based bucketing. This gives us a better spread on the low + * and middle range and a coarse bucketing on the high end. + * + * The idea here is that it doesn't matter if you have n 1GB blobs or + * n/2 1GB blobs and n/2 1.5GB blobs -- either way you have a scaling + * problem that we want to report on. + */ +#define HBIN_LEN (sizeof(unsigned long) * 2) +#define HBIN_MASK (0xF) +#define HBIN_SHIFT (4) + +static int hbin(unsigned long value) +{ + for (size_t k = 0; k < HBIN_LEN; k++) { + if ((value & ~(HBIN_MASK)) == 0) + return k; + value >>= HBIN_SHIFT; + } + + return 0; /* should not happen */ +} + +/* + * QBIN -- base4 binning (histogram bucketing). + * + * This is the same idea as the above, but we want better granularity + * in the low end and don't expect as many large values. + */ +#define QBIN_LEN (sizeof(unsigned long) * 4) +#define QBIN_MASK (0x3) +#define QBIN_SHIFT (2) + +static int qbin(unsigned long value) +{ + for (size_t k = 0; k < QBIN_LEN; k++) { + if ((value & ~(QBIN_MASK)) == 0) + return k; + value >>= (QBIN_SHIFT); + } + + return 0; /* should not happen */ +} + +/* + * histogram bin for objects. + */ +struct obj_hist_bin { + uint64_t sum_size; /* sum(object_size) for all objects in this bin */ + uint64_t sum_disk_size; /* sum(on_disk_size) for all objects in this bin */ + uint32_t cnt_seen; /* number seen in this bin */ +}; + +static void incr_obj_hist_bin(struct obj_hist_bin *pbin, + unsigned long object_length, + off_t disk_sizep) +{ + pbin->sum_size += object_length; + pbin->sum_disk_size += disk_sizep; + pbin->cnt_seen++; +} + +/* + * Remember the largest n objects for some scaling dimension. This + * could be the observed object size or number of entries in a tree. + * We'll use this to generate a sorted vector in the output for that + * dimension. + */ +struct large_item { + uint64_t size; + struct object_id oid; + + /* + * For blobs and trees the name field is the pathname of the + * file or directory. Root trees will have a zero-length + * name. The name field is not currenly used for commits. + */ + struct strbuf name; + + /* + * For blobs and trees remember the transient commit from + * the treewalk so that we can say that this large item + * first appeared in this commit (relative to the treewalk + * order). + */ + struct object_id containing_commit_oid; + + /* + * Lookup `containing_commit_oid` using `git name-rev`. + * Lazy allocate this post-treewalk. + */ + struct strbuf name_rev; +}; + +struct large_item_vec { + char *dimension_label; + char *item_label; + uint64_t nr_items; + struct large_item items[FLEX_ARRAY]; /* nr_items */ +}; + +static struct large_item_vec *alloc_large_item_vec(const char *dimension_label, + const char *item_label, + uint64_t nr_items) +{ + struct large_item_vec *vec; + size_t flex_len = nr_items * sizeof(struct large_item); + size_t k; + + if (!nr_items) + return NULL; + + vec = xcalloc(1, (sizeof(struct large_item_vec) + flex_len)); + vec->dimension_label = strdup(dimension_label); + vec->item_label = strdup(item_label); + vec->nr_items = nr_items; + + for (k = 0; k < nr_items; k++) + strbuf_init(&vec->items[k].name, 0); + + return vec; +} + +static void free_large_item_vec(struct large_item_vec *vec) +{ + if (!vec) + return; + + for (size_t k = 0; k < vec->nr_items; k++) { + strbuf_release(&vec->items[k].name); + strbuf_release(&vec->items[k].name_rev); + } + + free(vec->dimension_label); + free(vec->item_label); + free(vec); +} + +static void maybe_insert_large_item(struct large_item_vec *vec, + uint64_t size, + struct object_id *oid, + const char *name, + const struct object_id *containing_commit_oid) +{ + size_t rest_len; + size_t k; + + if (!vec || !vec->nr_items) + return; + + /* + * Since the odds an object being among the largest n + * is small, shortcut and see if it is smaller than + * the smallest one in our set and quickly reject it. + */ + if (size < vec->items[vec->nr_items - 1].size) + return; + + for (k = 0; k < vec->nr_items; k++) { + if (size < vec->items[k].size) + continue; + + /* + * The last large_item in the vector is about to be + * overwritten by the previous one during the shift. + * Steal its allocated strbuf and reuse it. + * + * We can ignore .name_rev because it will not be + * allocated until after the treewalk. + */ + strbuf_release(&vec->items[vec->nr_items - 1].name); + + /* push items[k..] down one and insert data for this item here */ + + rest_len = (vec->nr_items - k - 1) * sizeof(struct large_item); + if (rest_len) + memmove(&vec->items[k + 1], &vec->items[k], rest_len); + + memset(&vec->items[k], 0, sizeof(struct large_item)); + vec->items[k].size = size; + oidcpy(&vec->items[k].oid, oid); + oidcpy(&vec->items[k].containing_commit_oid, containing_commit_oid ? containing_commit_oid : null_oid(the_hash_algo)); + strbuf_init(&vec->items[k].name, 0); + if (name && *name) + strbuf_addstr(&vec->items[k].name, name); + + return; + } +} + +/* + * Common fields for any type of object. + */ +struct survey_stats_base_object { + uint32_t cnt_seen; + + uint32_t cnt_missing; /* we may have a partial clone. */ + + /* + * Number of objects grouped by where they are stored on disk. + * This is a function of how the ODB is packed. + */ + uint32_t cnt_cached; /* see oi.whence */ + uint32_t cnt_loose; /* see oi.whence */ + uint32_t cnt_packed; /* see oi.whence */ + uint32_t cnt_dbcached; /* see oi.whence */ + + uint64_t sum_size; /* sum(object_size) */ + uint64_t sum_disk_size; /* sum(disk_size) */ + + /* + * A histogram of the count of objects, the observed size, and + * the on-disk size grouped by the observed size. + */ + struct obj_hist_bin size_hbin[HBIN_LEN]; +}; + +/* + * PBIN -- parent vector binning (histogram bucketing). + * + * We create a histogram based upon the number of parents + * in a commit. This is a simple linear vector. It starts + * at zero for "initial" commits. + * + * If a commit has more parents, just put it in the last bin. + */ +#define PBIN_VEC_LEN (32) + +struct survey_stats_commits { + struct survey_stats_base_object base; + + /* + * Count of commits with k parents. + */ + uint32_t parent_cnt_pbin[PBIN_VEC_LEN]; + + struct large_item_vec *vec_largest_by_nr_parents; + struct large_item_vec *vec_largest_by_size_bytes; +}; + +/* + * Stats for reachable trees. + */ +struct survey_stats_trees { + struct survey_stats_base_object base; + + /* + * Keep a vector of the trees with the most number of entries. + * This gives us a feel for the width of a tree when there are + * gigantic directories. + */ + struct large_item_vec *vec_largest_by_nr_entries; + + /* + * Keep a vector of the trees with the largest size in bytes. + * The contents of this may or may not match items in the other + * vector, since entryname length can alter the results. + */ + struct large_item_vec *vec_largest_by_size_bytes; + + /* + * Computing the sum of the number of entries across all trees + * is probably not that interesting. + */ + uint64_t sum_entries; /* sum(nr_entries) -- sum across all trees */ + + /* + * A histogram of the count of trees, the observed size, and + * the on-disk size grouped by the number of entries in the tree. + */ + struct obj_hist_bin entry_qbin[QBIN_LEN]; +}; + +/* + * Stats for reachable blobs. + */ +struct survey_stats_blobs { + struct survey_stats_base_object base; + + /* + * Remember the OIDs of the largest n blobs. + */ + struct large_item_vec *vec_largest_by_size_bytes; }; struct survey_report_object_summary { @@ -60,6 +377,10 @@ struct survey_report_object_summary { size_t tags_nr; size_t trees_nr; size_t blobs_nr; + + struct survey_stats_commits commits; + struct survey_stats_trees trees; + struct survey_stats_blobs blobs; }; /** @@ -229,6 +550,12 @@ struct survey_context { static void clear_survey_context(struct survey_context *ctx) { + free_large_item_vec(ctx->report.reachable_objects.commits.vec_largest_by_nr_parents); + free_large_item_vec(ctx->report.reachable_objects.commits.vec_largest_by_size_bytes); + free_large_item_vec(ctx->report.reachable_objects.trees.vec_largest_by_nr_entries); + free_large_item_vec(ctx->report.reachable_objects.trees.vec_largest_by_size_bytes); + free_large_item_vec(ctx->report.reachable_objects.blobs.vec_largest_by_size_bytes); + ref_array_clear(&ctx->ref_array); strvec_clear(&ctx->refs); } @@ -349,6 +676,128 @@ static void print_table_plaintext(struct survey_table *table) free(column_widths); } +static void pretty_print_bin_table(const char *title_caption, + const char *bucket_header, + struct obj_hist_bin *bin, + uint64_t bin_len, int bin_shift, uint64_t bin_mask) +{ + struct survey_table table = SURVEY_TABLE_INIT; + struct strbuf bucket = STRBUF_INIT, cnt_seen = STRBUF_INIT; + struct strbuf sum_size = STRBUF_INIT, sum_disk_size = STRBUF_INIT; + uint64_t lower = 0; + uint64_t upper = bin_mask; + + table.table_name = title_caption; + strvec_pushl(&table.header, bucket_header, "Count", "Size", "Disk Size", NULL); + + for (size_t k = 0; k < bin_len; k++) { + struct obj_hist_bin *p = bin + k; + uintmax_t lower_k = lower; + uintmax_t upper_k = upper; + + lower = upper+1; + upper = (upper << bin_shift) + bin_mask; + + if (!p->cnt_seen) + continue; + + strbuf_reset(&bucket); + strbuf_addf(&bucket, "%"PRIuMAX"..%"PRIuMAX, lower_k, upper_k); + + strbuf_reset(&cnt_seen); + strbuf_addf(&cnt_seen, "%"PRIuMAX, (uintmax_t)p->cnt_seen); + + strbuf_reset(&sum_size); + strbuf_addf(&sum_size, "%"PRIuMAX, (uintmax_t)p->sum_size); + + strbuf_reset(&sum_disk_size); + strbuf_addf(&sum_disk_size, "%"PRIuMAX, (uintmax_t)p->sum_disk_size); + + insert_table_rowv(&table, bucket.buf, + cnt_seen.buf, sum_size.buf, sum_disk_size.buf, NULL); + } + strbuf_release(&bucket); + strbuf_release(&cnt_seen); + strbuf_release(&sum_size); + strbuf_release(&sum_disk_size); + + print_table_plaintext(&table); + clear_table(&table); +} + +static void survey_report_hbin(const char *title_caption, + struct obj_hist_bin *bin) +{ + pretty_print_bin_table(title_caption, + "Byte Range", + bin, + HBIN_LEN, HBIN_SHIFT, HBIN_MASK); +} + +static void survey_report_tree_lengths(struct survey_context *ctx) +{ + pretty_print_bin_table(_("TREE HISTOGRAM BY NUMBER OF ENTRIES"), + "Entry Range", + ctx->report.reachable_objects.trees.entry_qbin, + QBIN_LEN, QBIN_SHIFT, QBIN_MASK); +} + +static void survey_report_commit_parents(struct survey_context *ctx) +{ + struct survey_stats_commits *psc = &ctx->report.reachable_objects.commits; + struct survey_table table = SURVEY_TABLE_INIT; + struct strbuf parents = STRBUF_INIT, counts = STRBUF_INIT; + + table.table_name = _("HISTOGRAM BY NUMBER OF COMMIT PARENTS"); + strvec_pushl(&table.header, "Parents", "Counts", NULL); + + for (int k = 0; k < PBIN_VEC_LEN; k++) + if (psc->parent_cnt_pbin[k]) { + strbuf_reset(&parents); + strbuf_addf(&parents, "%02d", k); + + strbuf_reset(&counts); + strbuf_addf(&counts, "%14"PRIuMAX, (uintmax_t)psc->parent_cnt_pbin[k]); + + insert_table_rowv(&table, parents.buf, counts.buf, NULL); + } + strbuf_release(&parents); + strbuf_release(&counts); + + print_table_plaintext(&table); + clear_table(&table); +} + +static void survey_report_largest_vec(struct survey_context *ctx, struct large_item_vec *vec) +{ + struct survey_table table = SURVEY_TABLE_INIT; + struct strbuf size = STRBUF_INIT; + + if (!vec || !vec->nr_items) + return; + + table.table_name = vec->dimension_label; + strvec_pushl(&table.header, "Size", "OID", "Name", "Commit", ctx->opts.show_name_rev ? "Name-Rev" : NULL, NULL); + + for (size_t k = 0; k < vec->nr_items; k++) { + struct large_item *pk = &vec->items[k]; + if (!is_null_oid(&pk->oid)) { + strbuf_reset(&size); + strbuf_addf(&size, "%"PRIuMAX, (uintmax_t)pk->size); + + insert_table_rowv(&table, size.buf, oid_to_hex(&pk->oid), pk->name.buf, + is_null_oid(&pk->containing_commit_oid) ? + "" : oid_to_hex(&pk->containing_commit_oid), + !ctx->opts.show_name_rev ? NULL : pk->name_rev.len ? pk->name_rev.buf : "", + NULL); + } + } + strbuf_release(&size); + + print_table_plaintext(&table); + clear_table(&table); +} + static void survey_report_plaintext_refs(struct survey_context *ctx) { struct survey_report_ref_summary *refs = &ctx->report.refs; @@ -380,6 +829,42 @@ static void survey_report_plaintext_refs(struct survey_context *ctx) free(fmt); } + /* + * SymRefs are somewhat orthogonal to the above classification (e.g. + * "HEAD" --> detached and "refs/remotes/origin/HEAD" --> remote) so the + * above classified counts will already include them, but it is less + * confusing to display them here than to create a whole new section. + */ + if (ctx->report.refs.cnt_symref) { + char *fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)refs->cnt_symref); + insert_table_rowv(&table, _("Symbolic refs"), fmt, NULL); + free(fmt); + } + + if (ctx->report.refs.cnt_loose || ctx->report.refs.cnt_packed) { + char *fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)refs->cnt_loose); + insert_table_rowv(&table, _("Loose refs"), fmt, NULL); + free(fmt); + fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)refs->cnt_packed); + insert_table_rowv(&table, _("Packed refs"), fmt, NULL); + free(fmt); + } + + if (ctx->report.refs.len_max_local_refname || ctx->report.refs.len_max_remote_refname) { + char *fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)refs->len_max_local_refname); + insert_table_rowv(&table, _("Max local refname length"), fmt, NULL); + free(fmt); + fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)refs->len_sum_local_refnames); + insert_table_rowv(&table, _("Sum local refnames length"), fmt, NULL); + free(fmt); + fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)refs->len_max_remote_refname); + insert_table_rowv(&table, _("Max remote refname length"), fmt, NULL); + free(fmt); + fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)refs->len_sum_remote_refnames); + insert_table_rowv(&table, _("Sum remote refnames length"), fmt, NULL); + free(fmt); + } + print_table_plaintext(&table); clear_table(&table); } @@ -465,6 +950,19 @@ static void survey_report_plaintext(struct survey_context *ctx) ctx->report.by_type, REPORT_TYPE_COUNT); + survey_report_commit_parents(ctx); + + survey_report_hbin(_("COMMITS HISTOGRAM BY SIZE IN BYTES"), + ctx->report.reachable_objects.commits.base.size_hbin); + + survey_report_tree_lengths(ctx); + + survey_report_hbin(_("TREES HISTOGRAM BY SIZE IN BYTES"), + ctx->report.reachable_objects.trees.base.size_hbin); + + survey_report_hbin(_("BLOBS HISTOGRAM BY SIZE IN BYTES"), + ctx->report.reachable_objects.blobs.base.size_hbin); + survey_report_plaintext_sorted_size( &ctx->report.top_paths_by_count[REPORT_TYPE_TREE]); survey_report_plaintext_sorted_size( @@ -479,6 +977,12 @@ static void survey_report_plaintext(struct survey_context *ctx) &ctx->report.top_paths_by_inflate[REPORT_TYPE_TREE]); survey_report_plaintext_sorted_size( &ctx->report.top_paths_by_inflate[REPORT_TYPE_BLOB]); + + survey_report_largest_vec(ctx, ctx->report.reachable_objects.commits.vec_largest_by_nr_parents); + survey_report_largest_vec(ctx, ctx->report.reachable_objects.commits.vec_largest_by_size_bytes); + survey_report_largest_vec(ctx, ctx->report.reachable_objects.trees.vec_largest_by_nr_entries); + survey_report_largest_vec(ctx, ctx->report.reachable_objects.trees.vec_largest_by_size_bytes); + survey_report_largest_vec(ctx, ctx->report.reachable_objects.blobs.vec_largest_by_size_bytes); } /* @@ -550,6 +1054,31 @@ static int survey_load_config_cb(const char *var, const char *value, ctx->opts.show_progress = git_config_bool(var, value); return 0; } + if (!strcmp(var, "survey.namerev")) { + ctx->opts.show_name_rev = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "survey.showcommitparents")) { + ctx->opts.show_largest_commits_by_nr_parents = git_config_ulong(var, value, cctx->kvi); + return 0; + } + if (!strcmp(var, "survey.showcommitsizes")) { + ctx->opts.show_largest_commits_by_size_bytes = git_config_ulong(var, value, cctx->kvi); + return 0; + } + + if (!strcmp(var, "survey.showtreeentries")) { + ctx->opts.show_largest_trees_by_nr_entries = git_config_ulong(var, value, cctx->kvi); + return 0; + } + if (!strcmp(var, "survey.showtreesizes")) { + ctx->opts.show_largest_trees_by_size_bytes = git_config_ulong(var, value, cctx->kvi); + return 0; + } + if (!strcmp(var, "survey.showblobsizes")) { + ctx->opts.show_largest_blobs_by_size_bytes = git_config_ulong(var, value, cctx->kvi); + return 0; + } if (!strcmp(var, "survey.top")) { ctx->opts.top_nr = git_config_bool(var, value); return 0; @@ -615,6 +1144,80 @@ static void do_load_refs(struct survey_context *ctx, ref_sorting_release(sorting); } +/* + * Try to run `git name-rev` on each of the containing-commit-oid's + * in this large-item-vec to get a pretty name for each OID. Silently + * ignore errors if it fails because this info is nice to have but not + * essential. + */ +static void large_item_vec_lookup_name_rev(struct survey_context *ctx, + struct large_item_vec *vec) +{ + struct child_process cp = CHILD_PROCESS_INIT; + struct strbuf in = STRBUF_INIT; + struct strbuf out = STRBUF_INIT; + const char *line; + size_t k; + + if (!vec || !vec->nr_items) + return; + + ctx->progress_total += vec->nr_items; + display_progress(ctx->progress, ctx->progress_total); + + for (k = 0; k < vec->nr_items; k++) + strbuf_addf(&in, "%s\n", oid_to_hex(&vec->items[k].containing_commit_oid)); + + cp.git_cmd = 1; + strvec_pushl(&cp.args, "name-rev", "--name-only", "--annotate-stdin", NULL); + if (pipe_command(&cp, in.buf, in.len, &out, 0, NULL, 0)) { + strbuf_release(&in); + strbuf_release(&out); + return; + } + + line = out.buf; + k = 0; + while (*line) { + const char *eol = strchrnul(line, '\n'); + + strbuf_init(&vec->items[k].name_rev, 0); + strbuf_add(&vec->items[k].name_rev, line, (eol - line)); + + line = eol + 1; + k++; + } + + strbuf_release(&in); + strbuf_release(&out); +} + +static void do_lookup_name_rev(struct survey_context *ctx) +{ + /* + * `git name-rev` can be very expensive when there are lots of + * refs, so make it optional. + */ + if (!ctx->opts.show_name_rev) + return; + + if (ctx->opts.show_progress) { + ctx->progress_total = 0; + ctx->progress = start_progress(ctx->repo, _("Resolving name-revs..."), 0); + } + + large_item_vec_lookup_name_rev(ctx, ctx->report.reachable_objects.commits.vec_largest_by_nr_parents); + large_item_vec_lookup_name_rev(ctx, ctx->report.reachable_objects.commits.vec_largest_by_size_bytes); + + large_item_vec_lookup_name_rev(ctx, ctx->report.reachable_objects.trees.vec_largest_by_nr_entries); + large_item_vec_lookup_name_rev(ctx, ctx->report.reachable_objects.trees.vec_largest_by_size_bytes); + + large_item_vec_lookup_name_rev(ctx, ctx->report.reachable_objects.blobs.vec_largest_by_size_bytes); + + if (ctx->opts.show_progress) + stop_progress(&ctx->progress); +} + /* * The REFS phase: * @@ -638,6 +1241,7 @@ static void survey_phase_refs(struct survey_context *ctx) for (int i = 0; i < ctx->ref_array.nr; i++) { unsigned long size; struct ref_array_item *item = ctx->ref_array.items[i]; + size_t len = strlen(item->refname); switch (item->kind) { case FILTER_REFS_TAGS: @@ -664,6 +1268,33 @@ static void survey_phase_refs(struct survey_context *ctx) ctx->report.refs.unknown_nr++; break; } + + /* + * SymRefs are somewhat orthogonal to the above + * classification (e.g. "HEAD" --> detached + * and "refs/remotes/origin/HEAD" --> remote) so + * our totals will already include them. + */ + if (item->flag & REF_ISSYMREF) + ctx->report.refs.cnt_symref++; + + /* + * Where/how is the ref stored in GITDIR. + */ + if (item->flag & REF_ISPACKED) + ctx->report.refs.cnt_packed++; + else + ctx->report.refs.cnt_loose++; + + if (item->kind == FILTER_REFS_REMOTES) { + ctx->report.refs.len_sum_remote_refnames += len; + if (len > ctx->report.refs.len_max_remote_refname) + ctx->report.refs.len_max_remote_refname = len; + } else { + ctx->report.refs.len_sum_local_refnames += len; + if (len > ctx->report.refs.len_max_local_refname) + ctx->report.refs.len_max_local_refname = len; + } } trace2_region_leave("survey", "phase/refs", ctx->repo); @@ -698,7 +1329,8 @@ static void increment_object_counts( static void increment_totals(struct survey_context *ctx, struct oid_array *oids, - struct survey_report_object_size_summary *summary) + struct survey_report_object_size_summary *summary, + const char *path) { for (size_t i = 0; i < oids->nr; i++) { struct object_info oi = OBJECT_INFO_INIT; @@ -706,6 +1338,8 @@ static void increment_totals(struct survey_context *ctx, unsigned long object_length = 0; off_t disk_sizep = 0; enum object_type type; + struct survey_stats_base_object *base; + int hb; oi.typep = &type; oi.sizep = &object_length; @@ -714,11 +1348,86 @@ static void increment_totals(struct survey_context *ctx, if (oid_object_info_extended(ctx->repo, &oids->oid[i], &oi, oi_flags) < 0) { summary->num_missing++; - } else { - summary->nr++; - summary->disk_size += disk_sizep; - summary->inflated_size += object_length; + continue; + } + + summary->nr++; + summary->disk_size += disk_sizep; + summary->inflated_size += object_length; + + switch (type) { + case OBJ_COMMIT: { + struct commit *commit = lookup_commit(ctx->repo, &oids->oid[i]); + unsigned k = commit_list_count(commit->parents); + + if (k >= PBIN_VEC_LEN) + k = PBIN_VEC_LEN - 1; + + ctx->report.reachable_objects.commits.parent_cnt_pbin[k]++; + base = &ctx->report.reachable_objects.commits.base; + + maybe_insert_large_item(ctx->report.reachable_objects.commits.vec_largest_by_nr_parents, k, &commit->object.oid, NULL, &commit->object.oid); + maybe_insert_large_item(ctx->report.reachable_objects.commits.vec_largest_by_size_bytes, object_length, &commit->object.oid, NULL, &commit->object.oid); + break; + } + case OBJ_TREE: { + struct tree *tree = lookup_tree(ctx->repo, &oids->oid[i]); + if (tree) { + struct survey_stats_trees *pst = &ctx->report.reachable_objects.trees; + struct tree_desc desc; + struct name_entry entry; + uint64_t nr_entries; + int qb; + + parse_tree(tree); + init_tree_desc(&desc, &oids->oid[i], tree->buffer, tree->size); + nr_entries = 0; + while (tree_entry(&desc, &entry)) + nr_entries++; + + pst->sum_entries += nr_entries; + + maybe_insert_large_item(pst->vec_largest_by_nr_entries, nr_entries, &tree->object.oid, path, NULL); + maybe_insert_large_item(pst->vec_largest_by_size_bytes, object_length, &tree->object.oid, path, NULL); + + qb = qbin(nr_entries); + incr_obj_hist_bin(&pst->entry_qbin[qb], object_length, disk_sizep); + } + base = &ctx->report.reachable_objects.trees.base; + break; + } + case OBJ_BLOB: + base = &ctx->report.reachable_objects.blobs.base; + + maybe_insert_large_item(ctx->report.reachable_objects.blobs.vec_largest_by_size_bytes, object_length, &oids->oid[i], path, NULL); + break; + default: + continue; + } + + switch (oi.whence) { + case OI_CACHED: + base->cnt_cached++; + break; + case OI_LOOSE: + base->cnt_loose++; + break; + case OI_PACKED: + base->cnt_packed++; + break; + case OI_DBCACHED: + base->cnt_dbcached++; + break; + default: + break; } + + base->sum_size += object_length; + base->sum_disk_size += disk_sizep; + + hb = hbin(object_length); + incr_obj_hist_bin(&base->size_hbin[hb], object_length, disk_sizep); + } } @@ -730,7 +1439,7 @@ static void increment_object_totals(struct survey_context *ctx, struct survey_report_object_size_summary *total; struct survey_report_object_size_summary summary = { 0 }; - increment_totals(ctx, oids, &summary); + increment_totals(ctx, oids, &summary, path); switch (type) { case OBJ_COMMIT: @@ -864,6 +1573,12 @@ static void survey_phase_objects(struct survey_context *ctx) release_revisions(&revs); trace2_region_leave("survey", "phase/objects", ctx->repo); + + if (ctx->opts.show_name_rev) { + trace2_region_enter("survey", "phase/namerev", the_repository); + do_lookup_name_rev(ctx); + trace2_region_enter("survey", "phase/namerev", the_repository); + } } int cmd_survey(int argc, const char **argv, const char *prefix, struct repository *repo) @@ -888,6 +1603,7 @@ int cmd_survey(int argc, const char **argv, const char *prefix, struct repositor static struct option survey_options[] = { OPT__VERBOSE(&ctx.opts.verbose, N_("verbose output")), OPT_BOOL(0, "progress", &ctx.opts.show_progress, N_("show progress")), + OPT_BOOL(0, "name-rev", &ctx.opts.show_name_rev, N_("run name-rev on each reported commit")), OPT_INTEGER('n', "top", &ctx.opts.top_nr, N_("number of entries to include in detail tables")), @@ -899,6 +1615,14 @@ int cmd_survey(int argc, const char **argv, const char *prefix, struct repositor OPT_BOOL_F(0, "detached", &ctx.opts.refs.want_detached, N_("include detached HEAD"), PARSE_OPT_NONEG), OPT_BOOL_F(0, "other", &ctx.opts.refs.want_other, N_("include notes and stashes"), PARSE_OPT_NONEG), + OPT_INTEGER_F(0, "commit-parents", &ctx.opts.show_largest_commits_by_nr_parents, N_("show N largest commits by parent count"), PARSE_OPT_NONEG), + OPT_INTEGER_F(0, "commit-sizes", &ctx.opts.show_largest_commits_by_size_bytes, N_("show N largest commits by size in bytes"), PARSE_OPT_NONEG), + + OPT_INTEGER_F(0, "tree-entries", &ctx.opts.show_largest_trees_by_nr_entries, N_("show N largest trees by entry count"), PARSE_OPT_NONEG), + OPT_INTEGER_F(0, "tree-sizes", &ctx.opts.show_largest_trees_by_size_bytes, N_("show N largest trees by size in bytes"), PARSE_OPT_NONEG), + + OPT_INTEGER_F(0, "blob-sizes", &ctx.opts.show_largest_blobs_by_size_bytes, N_("show N largest blobs by size in bytes"), PARSE_OPT_NONEG), + OPT_END(), }; @@ -922,6 +1646,39 @@ int cmd_survey(int argc, const char **argv, const char *prefix, struct repositor fixup_refs_wanted(&ctx); + if (ctx.opts.show_largest_commits_by_nr_parents) + ctx.report.reachable_objects.commits.vec_largest_by_nr_parents = + alloc_large_item_vec( + "largest_commits_by_nr_parents", + "nr_parents", + ctx.opts.show_largest_commits_by_nr_parents); + if (ctx.opts.show_largest_commits_by_size_bytes) + ctx.report.reachable_objects.commits.vec_largest_by_size_bytes = + alloc_large_item_vec( + "largest_commits_by_size_bytes", + "size", + ctx.opts.show_largest_commits_by_size_bytes); + + if (ctx.opts.show_largest_trees_by_nr_entries) + ctx.report.reachable_objects.trees.vec_largest_by_nr_entries = + alloc_large_item_vec( + "largest_trees_by_nr_entries", + "nr_entries", + ctx.opts.show_largest_trees_by_nr_entries); + if (ctx.opts.show_largest_trees_by_size_bytes) + ctx.report.reachable_objects.trees.vec_largest_by_size_bytes = + alloc_large_item_vec( + "largest_trees_by_size_bytes", + "size", + ctx.opts.show_largest_trees_by_size_bytes); + + if (ctx.opts.show_largest_blobs_by_size_bytes) + ctx.report.reachable_objects.blobs.vec_largest_by_size_bytes = + alloc_large_item_vec( + "largest_blobs_by_size_bytes", + "size", + ctx.opts.show_largest_blobs_by_size_bytes); + survey_phase_refs(&ctx); survey_phase_objects(&ctx); @@ -931,3 +1688,143 @@ int cmd_survey(int argc, const char **argv, const char *prefix, struct repositor clear_survey_context(&ctx); return 0; } + +/* + * NEEDSWORK: So far, I only have iteration on the requested set of + * refs and treewalk/reachable objects on that set of refs. The + * following is a bit of a laundry list of things that I'd like to + * add. + * + * [] Dump stats on all of the packfiles. The number and size of each. + * Whether each is in the .git directory or in an alternate. The + * state of the IDX or MIDX files and etc. Delta chain stats. All + * of this data is relative to the "lived-in" state of the + * repository. Stuff that may change after a GC or repack. + * + * [] Clone and Index stats. partial, shallow, sparse-checkout, + * sparse-index, etc. Hydration stats. + * + * [] Dump stats on each remote. When we fetch from a remote the size + * of the response is related to the set of haves on the server. + * You can see this in `GIT_TRACE_CURL=1 git fetch`. We get a + * `ls-refs` payload that lists all of the branches and tags on the + * server, so at a minimum the RefName and SHA for each. But for + * annotated tags we also get the peeled SHA. The size of this + * overhead on every fetch is proporational to the size of the `git + * ls-remote` response (roughly, although the latter repeats the + * RefName of the peeled tag). If, for example, you have 500K refs + * on a remote, you're going to have a long "haves" message, so + * every fetch will be slow just because of that overhead (not + * counting new objects to be downloaded). + * + * Note that the local set of tags in "refs/tags/" is a union over + * all remotes. However, since most people only have one remote, + * we can probaly estimate the overhead value directly from the + * size of the set of "refs/tags/" that we visited while building + * the `ref_info` and `ref_array` and not need to ask the remote. + * + * [] Should the "string length of refnames / remote refs", for + * example, be sub-divided by remote so we can project the + * cost of the haves/wants overhead a fetch. + * + * [] Can we examine the merge commits and classify them as clean or + * dirty? (ie. ones with merge conflicts that needed to be + * addressed during the merge itself.) + * + * [] Do dirty merges affect performance of later operations? + * + * [] Dump info on the complexity of the DAG. Criss-cross merges. + * The number of edges that must be touched to compute merge bases. + * Edge length. The number of parallel lanes in the history that + * must be navigated to get to the merge base. What affects the + * cost of the Ahead/Behind computation? How often do + * criss-crosses occur and do they cause various operations to slow + * down? + * + * [] If there are primary branches (like "main" or "master") are they + * always on the left side of merges? Does the graph have a clean + * left edge? Or are there normal and "backwards" merges? Do + * these cause problems at scale? + * + * [] If we have a hierarchy of FI/RI branches like "L1", "L2, ..., + * can we learn anything about the shape of the repo around these + * FI and RI integrations? + * + * [] Do we need a no-PII flag to omit pathnames or branch/tag names + * in the various histograms? (This would turn off --name-rev + * too.) + * + * [] I have so far avoided adding opinions about individual fields + * (such as the way `git-sizer` prints a row of stars or bangs in + * the last column). + * + * I'm wondering if that is a job of this executable or if it + * should be done in a post-processing step using the JSON output. + * + * My problem with the `git-sizer` approach is that it doesn't give + * the (casual) user any information on why it has stars or bangs. + * And there isn't a good way to print detailed information in the + * ASCII-art tables that would be easy to understand. + * + * [] For example, a large number of refs does not define a cliff. + * Performance will drop off (linearly, quadratically, ... ??). + * The tool should refer them to article(s) talking about the + * different problems that it could cause. So should `git + * survey` just print the number and (implicitly) refer them to + * the man page (chapter/verse) or to a tool that will interpret + * the number and explain it? + * + * [] Alternatively, should `git survey` do that analysis too and + * just print footnotes for each large number? + * + * [] The computation of the raw survey JSON data can take HOURS on + * a very large repo (like Windows), so I'm wondering if we + * want to keep the opinion portion separate. + * + * [] In addition to opinions based on the static data, I would like + * to dump the JSON results (or the Trace2 telemetry) into a DB and + * aggregate it with other users. + * + * Granted, they should all see the same DAG and the same set of + * reachable objects, but we could average across all datasets + * generated on a particular date and detect outlier users. + * + * [] Maybe someone cloned from the `_full` endpoint rather than + * the limited refs endpoint. + * + * [] Maybe that user is having problems with repacking / GC / + * maintenance without knowing it. + * + * [] I'd also like to dump use the DB to compare survey datasets over + * a time. How fast is their repository growing and in what ways? + * + * [] I'd rather have the delta analysis NOT be inside `git + * survey`, so it makes sense to consider having all of it in a + * post-process step. + * + * [] Another reason to put the opinion analysis in a post-process + * is that it would be easier to generate plots on the data tables. + * Granted, we can get plots from telemetry, but a stand-alone user + * could run the JSON thru python or jq or something and generate + * something nicer than ASCII-art and it could handle cross-referencing + * and hyperlinking to helpful information on each issue. + * + * [] I think there are several classes of data that we can report on: + * + * [] The "inherit repo properties", such as the shape and size of + * the DAG -- these should be universal in each enlistment. + * + * [] The "ODB lived in properties", such as the efficiency + * of the repack and things like partial and shallow clone. + * These will vary, but indicate health of the ODB. + * + * [] The "index related properties", such as sparse-checkout, + * sparse-index, cache-tree, untracked-cache, fsmonitor, and + * etc. These will also vary, but are more like knobs for + * the user to adjust. + * + * [] I want to compare these with Matt's "dimensions of scale" + * notes and see if there are other pieces of data that we + * could compute/consider. + * + */ diff --git a/builtin/update-index.c b/builtin/update-index.c index 538b619ba4f3bb..a5d7c0ed50b55b 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -8,6 +8,7 @@ #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" +#include "gvfs.h" #include "bulk-checkin.h" #include "config.h" #include "environment.h" @@ -713,7 +714,9 @@ static int do_reupdate(const char **paths, * to process each path individually */ if (S_ISSPARSEDIR(ce->ce_mode)) { - ensure_full_index(the_repository->index); + const char *fmt = "update-index:modified sparse dir '%s'"; + ensure_full_index_with_reason(the_repository->index, + fmt, ce->name); goto redo; } @@ -1164,7 +1167,13 @@ int cmd_update_index(int argc, argc = parse_options_end(&ctx); getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf; + if (mark_skip_worktree_only && gvfs_config_is_set(GVFS_BLOCK_COMMANDS)) + die(_("modifying the skip worktree bit is not supported on a GVFS repo")); + if (preferred_index_format) { + if (preferred_index_format != 4 && gvfs_config_is_set(GVFS_BLOCK_COMMANDS)) + die(_("changing the index version is not supported on a GVFS repo")); + if (preferred_index_format < 0) { printf(_("%d\n"), the_repository->index->version); } else if (preferred_index_format < INDEX_FORMAT_LB || @@ -1210,6 +1219,9 @@ int cmd_update_index(int argc, end_odb_transaction(); if (split_index > 0) { + if (gvfs_config_is_set(GVFS_BLOCK_COMMANDS)) + die(_("split index is not supported on a GVFS repo")); + if (repo_config_get_split_index(the_repository) == 0) warning(_("core.splitIndex is set to false; " "remove or change it, if you really want to " diff --git a/builtin/update-microsoft-git.c b/builtin/update-microsoft-git.c new file mode 100644 index 00000000000000..357cd598962046 --- /dev/null +++ b/builtin/update-microsoft-git.c @@ -0,0 +1,76 @@ +#include "builtin.h" +#include "repository.h" +#include "parse-options.h" +#include "run-command.h" +#include "strvec.h" + +#if defined(GIT_WINDOWS_NATIVE) +/* + * On Windows, run 'git update-git-for-windows' which + * is installed by the installer, based on the script + * in git-for-windows/build-extra. + */ +static int platform_specific_upgrade(void) +{ + struct child_process cp = CHILD_PROCESS_INIT; + + strvec_push(&cp.args, "git-update-git-for-windows"); + return run_command(&cp); +} +#elif defined(__APPLE__) +/* + * On macOS, we expect the user to have the microsoft-git + * cask installed via Homebrew. We check using these + * commands: + * + * 1. 'brew update' to get latest versions. + * 2. 'brew upgrade --cask microsoft-git' to get the + * latest version. + */ +static int platform_specific_upgrade(void) +{ + int res; + struct child_process update = CHILD_PROCESS_INIT; + struct child_process upgrade = CHILD_PROCESS_INIT; + + printf("Updating Homebrew with 'brew update'\n"); + + strvec_pushl(&update.args, "brew", "update", NULL); + res = run_command(&update); + + if (res) { + error(_("'brew update' failed; is brew installed?")); + return 1; + } + + printf("Upgrading microsoft-git with 'brew upgrade --cask microsoft-git'\n"); + strvec_pushl(&upgrade.args, "brew", "upgrade", "--cask", "microsoft-git", NULL); + res = run_command(&upgrade); + + return res; +} +#else +static int platform_specific_upgrade(void) +{ + error(_("update-microsoft-git is not supported on this platform")); + return 1; +} +#endif + +static const char * const update_microsoft_git_usage[] = { + N_("git update-microsoft-git"), + NULL, +}; + + +int cmd_update_microsoft_git(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) +{ + static struct option microsoft_git_options[] = { + OPT_END(), + }; + show_usage_with_options_if_asked(argc, argv, + update_microsoft_git_usage, + microsoft_git_options); + + return platform_specific_upgrade(); +} diff --git a/builtin/worktree.c b/builtin/worktree.c index 88a36ea9f8674e..c5893ab6d08a51 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -4,6 +4,7 @@ #include "builtin.h" #include "abspath.h" #include "advice.h" +#include "gvfs.h" #include "checkout.h" #include "config.h" #include "copy.h" diff --git a/cache-tree.c b/cache-tree.c index fa3858e2829aa8..06ecb1ce44250f 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -4,6 +4,7 @@ #include "git-compat-util.h" #include "gettext.h" #include "hex.h" +#include "gvfs.h" #include "lockfile.h" #include "tree.h" #include "tree-walk.h" @@ -233,7 +234,7 @@ static void discard_unused_subtrees(struct cache_tree *it) } } -int cache_tree_fully_valid(struct cache_tree *it) +static int cache_tree_fully_valid_1(struct cache_tree *it) { int i; if (!it) @@ -243,7 +244,7 @@ int cache_tree_fully_valid(struct cache_tree *it) HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) return 0; for (i = 0; i < it->subtree_nr; i++) { - if (!cache_tree_fully_valid(it->down[i]->cache_tree)) + if (!cache_tree_fully_valid_1(it->down[i]->cache_tree)) return 0; } return 1; @@ -254,6 +255,17 @@ static int must_check_existence(const struct cache_entry *ce) return !(repo_has_promisor_remote(the_repository) && ce_skip_worktree(ce)); } +int cache_tree_fully_valid(struct cache_tree *it) +{ + int result; + + trace2_region_enter("cache_tree", "fully_valid", NULL); + result = cache_tree_fully_valid_1(it); + trace2_region_leave("cache_tree", "fully_valid", NULL); + + return result; +} + static int update_one(struct cache_tree *it, struct cache_entry **cache, int entries, @@ -263,7 +275,8 @@ static int update_one(struct cache_tree *it, int flags) { struct strbuf buffer; - int missing_ok = flags & WRITE_TREE_MISSING_OK; + int missing_ok = gvfs_config_is_set(GVFS_MISSING_OK) ? + WRITE_TREE_MISSING_OK : (flags & WRITE_TREE_MISSING_OK); int dryrun = flags & WRITE_TREE_DRY_RUN; int repair = flags & WRITE_TREE_REPAIR; int to_invalidate = 0; @@ -435,7 +448,29 @@ static int update_one(struct cache_tree *it, continue; strbuf_grow(&buffer, entlen + 100); - strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0'); + + switch (mode) { + case 0100644: + strbuf_add(&buffer, "100644 ", 7); + break; + case 0100664: + strbuf_add(&buffer, "100664 ", 7); + break; + case 0100755: + strbuf_add(&buffer, "100755 ", 7); + break; + case 0120000: + strbuf_add(&buffer, "120000 ", 7); + break; + case 0160000: + strbuf_add(&buffer, "160000 ", 7); + break; + default: + strbuf_addf(&buffer, "%o ", mode); + break; + } + strbuf_add(&buffer, path + baselen, entlen); + strbuf_addch(&buffer, '\0'); strbuf_add(&buffer, oid->hash, the_hash_algo->rawsz); #if DEBUG_CACHE_TREE diff --git a/commit.c b/commit.c index e915b2b9a1295c..64d0268838207c 100644 --- a/commit.c +++ b/commit.c @@ -1,6 +1,7 @@ #define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" +#include "gvfs.h" #include "tag.h" #include "commit.h" #include "commit-graph.h" @@ -557,13 +558,17 @@ int repo_parse_commit_internal(struct repository *r, .sizep = &size, .contentp = &buffer, }; + int ret; /* * Git does not support partial clones that exclude commits, so set * OBJECT_INFO_SKIP_FETCH_OBJECT to fail fast when an object is missing. */ int flags = OBJECT_INFO_LOOKUP_REPLACE | OBJECT_INFO_SKIP_FETCH_OBJECT | - OBJECT_INFO_DIE_IF_CORRUPT; - int ret; + OBJECT_INFO_DIE_IF_CORRUPT; + + /* But the GVFS Protocol _does_ support missing commits! */ + if (gvfs_config_is_set(GVFS_MISSING_OK)) + flags ^= OBJECT_INFO_SKIP_FETCH_OBJECT; if (!item) return -1; diff --git a/compat/mingw.c b/compat/mingw.c index 540ae4b06cd0a4..b7078cf3e5c18e 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -719,8 +719,10 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) DWORD create = (oflags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING; /* only these flags are supported */ - if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND)) - return errno = ENOSYS, -1; + if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND)) { + errno = ENOSYS; + return -1; + } /* * FILE_SHARE_WRITE is required to permit child processes @@ -3096,12 +3098,14 @@ static int start_timer_thread(void) timer_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (timer_event) { timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL); - if (!timer_thread ) - return errno = ENOMEM, - error("cannot start timer thread"); - } else - return errno = ENOMEM, - error("cannot allocate resources for timer"); + if (!timer_thread ) { + errno = ENOMEM; + return error("cannot start timer thread"); + } + } else { + errno = ENOMEM; + return error("cannot allocate resources for timer"); + } return 0; } @@ -3134,13 +3138,15 @@ int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out) static const struct timeval zero; static int atexit_done; - if (out) - return errno = EINVAL, - error("setitimer param 3 != NULL not implemented"); + if (out) { + errno = EINVAL; + return error("setitimer param 3 != NULL not implemented"); + } if (!is_timeval_eq(&in->it_interval, &zero) && - !is_timeval_eq(&in->it_interval, &in->it_value)) - return errno = EINVAL, - error("setitimer: it_interval must be zero or eq it_value"); + !is_timeval_eq(&in->it_interval, &in->it_value)) { + errno = EINVAL; + return error("setitimer: it_interval must be zero or eq it_value"); + } if (timer_thread) stop_timer_thread(); @@ -3160,12 +3166,14 @@ int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out) int sigaction(int sig, struct sigaction *in, struct sigaction *out) { - if (sig != SIGALRM) - return errno = EINVAL, - error("sigaction only implemented for SIGALRM"); - if (out) - return errno = EINVAL, - error("sigaction: param 3 != NULL not implemented"); + if (sig != SIGALRM) { + errno = EINVAL; + return error("sigaction only implemented for SIGALRM"); + } + if (out) { + errno = EINVAL; + return error("sigaction: param 3 != NULL not implemented"); + } timer_fn = in->sa_handler; return 0; @@ -4318,6 +4326,8 @@ int wmain(int argc, const wchar_t **wargv) SetConsoleCtrlHandler(handle_ctrl_c, TRUE); + trace2_initialize_clock(); + maybe_redirect_std_handles(); adjust_symlink_flags(); fsync_object_files = 1; diff --git a/compat/posix.h b/compat/posix.h index 6c1af589e71dec..704529dc61d6d1 100644 --- a/compat/posix.h +++ b/compat/posix.h @@ -60,11 +60,11 @@ # else # define _XOPEN_SOURCE 500 # endif -#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \ - !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \ - !defined(__TANDEM) && !defined(__QNX__) && !defined(__MirBSD__) && \ - !defined(__CYGWIN__) -#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */ +#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ + !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__MirBSD__) && \ + !defined(__USLC__) && !defined(_M_UNIX) && !defined(__sgi) && \ + !defined(__TANDEM) && !defined(__QNX__) && !defined(__CYGWIN__) +#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500 */ #define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */ #endif #define _ALL_SOURCE 1 diff --git a/config.c b/config.c index fee2c33c8c2d7e..a8c2533cb3383f 100644 --- a/config.c +++ b/config.c @@ -13,6 +13,7 @@ #include "abspath.h" #include "advice.h" #include "date.h" +#include "gvfs.h" #include "branch.h" #include "config.h" #include "parse.h" @@ -43,6 +44,7 @@ #include "wildmatch.h" #include "ws.h" #include "write-or-die.h" +#include "transport.h" struct config_source { struct config_source *prev; @@ -1612,8 +1614,22 @@ int git_default_core_config(const char *var, const char *value, return 0; } + if (!strcmp(var, "core.gvfs")) { + gvfs_load_config_value(value); + return 0; + } + + if (!strcmp(var, "core.usegvfshelper")) { + core_use_gvfs_helper = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.sparsecheckout")) { - core_apply_sparse_checkout = git_config_bool(var, value); + /* virtual file system relies on the sparse checkout logic so force it on */ + if (core_virtualfilesystem) + core_apply_sparse_checkout = 1; + else + core_apply_sparse_checkout = git_config_bool(var, value); return 0; } @@ -1642,6 +1658,11 @@ int git_default_core_config(const char *var, const char *value, return 0; } + if (!strcmp(var, "core.virtualizeobjects")) { + core_virtualize_objects = git_config_bool(var, value); + return 0; + } + /* Add other config variables here and to Documentation/config.adoc. */ return platform_core_config(var, value, ctx, cb); } @@ -1754,6 +1775,37 @@ static int git_default_mailmap_config(const char *var, const char *value) return 0; } +static int git_default_gvfs_config(const char *var, const char *value) +{ + if (!strcmp(var, "gvfs.cache-server")) { + char *v2 = NULL; + + if (!git_config_string(&v2, var, value) && v2 && *v2) { + free(gvfs_cache_server_url); + gvfs_cache_server_url = transport_anonymize_url(v2); + } + free(v2); + return 0; + } + + if (!strcmp(var, "gvfs.sharedcache") && value && *value) { + strbuf_setlen(&gvfs_shared_cache_pathname, 0); + strbuf_addstr(&gvfs_shared_cache_pathname, value); + if (strbuf_normalize_path(&gvfs_shared_cache_pathname) < 0) { + /* + * Pretend it wasn't set. This will cause us to + * fallback to ".git/objects" effectively. + */ + strbuf_release(&gvfs_shared_cache_pathname); + return 0; + } + strbuf_trim_trailing_dir_sep(&gvfs_shared_cache_pathname); + return 0; + } + + return 0; +} + static int git_default_attr_config(const char *var, const char *value) { if (!strcmp(var, "attr.tree")) { @@ -1821,6 +1873,9 @@ int git_default_config(const char *var, const char *value, if (starts_with(var, "sparse.")) return git_default_sparse_config(var, value); + if (starts_with(var, "gvfs.")) + return git_default_gvfs_config(var, value); + /* Add other config variables here and to Documentation/config.adoc. */ return 0; } @@ -2703,6 +2758,44 @@ int repo_config_get_max_percent_split_change(struct repository *r) return -1; /* default value */ } +int repo_config_get_virtualfilesystem(struct repository *r) +{ + /* Run only once. */ + static int virtual_filesystem_result = -1; + if (virtual_filesystem_result >= 0) + return virtual_filesystem_result; + + if (repo_config_get_pathname(r, "core.virtualfilesystem", &core_virtualfilesystem)) + core_virtualfilesystem = xstrdup_or_null(getenv("GIT_VIRTUALFILESYSTEM_TEST")); + + if (core_virtualfilesystem && !*core_virtualfilesystem) + FREE_AND_NULL(core_virtualfilesystem); + + if (core_virtualfilesystem) { + /* + * Some git commands spawn helpers and redirect the index to a different + * location. These include "difftool -d" and the sequencer + * (i.e. `git rebase -i`, `git cherry-pick` and `git revert`) and others. + * In those instances we don't want to update their temporary index with + * our virtualization data. + */ + char *default_index_file = xstrfmt("%s/%s", the_repository->gitdir, "index"); + int should_run_hook = !strcmp(default_index_file, the_repository->index_file); + + free(default_index_file); + if (should_run_hook) { + /* virtual file system relies on the sparse checkout logic so force it on */ + core_apply_sparse_checkout = 1; + virtual_filesystem_result = 1; + return 1; + } + FREE_AND_NULL(core_virtualfilesystem); + } + + virtual_filesystem_result = 0; + return 0; +} + int repo_config_get_index_threads(struct repository *r, int *dest) { int is_bool, val; @@ -3177,6 +3270,7 @@ int repo_config_set_multivar_in_file_gently(struct repository *r, const char *comment, unsigned flags) { + static unsigned long timeout_ms = ULONG_MAX; int fd = -1, in_fd = -1; int ret; struct lock_file lock = LOCK_INIT; @@ -3197,11 +3291,16 @@ int repo_config_set_multivar_in_file_gently(struct repository *r, if (!config_filename) config_filename = filename_buf = repo_git_path(r, "config"); + if ((long)timeout_ms < 0 && + git_config_get_ulong("core.configWriteLockTimeoutMS", &timeout_ms)) + timeout_ms = 0; + /* * The lock serves a purpose in addition to locking: the new * contents of .git/config will be written into it. */ - fd = hold_lock_file_for_update(&lock, config_filename, 0); + fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0, + timeout_ms); if (fd < 0) { error_errno(_("could not lock config file %s"), config_filename); ret = CONFIG_NO_LOCK; diff --git a/config.h b/config.h index 36ab27a4ace709..c3ca5466aa5cae 100644 --- a/config.h +++ b/config.h @@ -693,6 +693,8 @@ int repo_config_get_index_threads(struct repository *r, int *dest); int repo_config_get_split_index(struct repository *r); int repo_config_get_max_percent_split_change(struct repository *r); +int repo_config_get_virtualfilesystem(struct repository *r); + /* This dies if the configured or default date is in the future */ int repo_config_get_expiry(struct repository *r, const char *key, char **output); diff --git a/config.mak.uname b/config.mak.uname index bc9855d2391abd..ab5b5e2e763850 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -301,17 +301,14 @@ ifeq ($(uname_S),FreeBSD) FILENO_IS_A_MACRO = UnfortunatelyYes endif ifeq ($(uname_S),OpenBSD) - NO_STRCASESTR = YesPlease - NO_MEMMEM = YesPlease + DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease USE_ST_TIMESPEC = YesPlease NEEDS_LIBICONV = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib HAVE_PATHS_H = YesPlease HAVE_BSD_SYSCTL = YesPlease - HAVE_BSD_KERN_PROC_SYSCTL = YesPlease CSPRNG_METHOD = arc4random - PROCFS_EXECUTABLE_PATH = /proc/curproc/file FREAD_READS_DIRECTORIES = UnfortunatelyYes FILENO_IS_A_MACRO = UnfortunatelyYes endif diff --git a/connected.c b/connected.c index 4415388bebacdf..7380b7dd278459 100644 --- a/connected.c +++ b/connected.c @@ -1,8 +1,10 @@ #define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" +#include "environment.h" #include "gettext.h" #include "hex.h" +#include "gvfs.h" #include "object-store.h" #include "run-command.h" #include "sigchain.h" @@ -34,6 +36,26 @@ int check_connected(oid_iterate_fn fn, void *cb_data, struct transport *transport; size_t base_len; + /* + * Running a virtual file system there will be objects that are + * missing locally and we don't want to download a bunch of + * commits, trees, and blobs just to make sure everything is + * reachable locally so this option will skip reachablility + * checks below that use rev-list. This will stop the check + * before uploadpack runs to determine if there is anything to + * fetch. Returning zero for the first check will also prevent the + * uploadpack from happening. It will also skip the check after + * the fetch is finished to make sure all the objects where + * downloaded in the pack file. This will allow the fetch to + * run and get all the latest tip commit ids for all the branches + * in the fetch but not pull down commits, trees, or blobs via + * upload pack. + */ + if (gvfs_config_is_set(GVFS_FETCH_SKIP_REACHABILITY_AND_UPLOADPACK)) + return 0; + if (core_virtualize_objects) + return 0; + if (!opt) opt = &defaults; transport = opt->transport; diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 3fbbbec61c1688..1083d0298b3a3f 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -635,7 +635,7 @@ if(NOT CURL_FOUND) add_compile_definitions(NO_CURL) message(WARNING "git-http-push and git-http-fetch will not be built") else() - list(APPEND PROGRAMS_BUILT git-http-fetch git-http-push git-imap-send git-remote-http) + list(APPEND PROGRAMS_BUILT git-http-fetch git-http-push git-imap-send git-remote-http git-gvfs-helper) if(CURL_VERSION_STRING VERSION_GREATER_EQUAL 7.34.0) add_compile_definitions(USE_CURL_FOR_IMAP_SEND) endif() @@ -804,7 +804,7 @@ target_link_libraries(git-sh-i18n--envsubst common-main) add_executable(git-shell ${CMAKE_SOURCE_DIR}/shell.c) target_link_libraries(git-shell common-main) -add_executable(scalar ${CMAKE_SOURCE_DIR}/scalar.c) +add_executable(scalar ${CMAKE_SOURCE_DIR}/scalar.c ${CMAKE_SOURCE_DIR}/json-parser.c) target_link_libraries(scalar common-main) if(CURL_FOUND) @@ -823,6 +823,9 @@ if(CURL_FOUND) add_executable(git-http-push ${CMAKE_SOURCE_DIR}/http-push.c) target_link_libraries(git-http-push http_obj common-main ${CURL_LIBRARIES} ${EXPAT_LIBRARIES}) endif() + + add_executable(git-gvfs-helper ${CMAKE_SOURCE_DIR}/gvfs-helper.c) + target_link_libraries(git-gvfs-helper http_obj common-main ${CURL_LIBRARIES} ) endif() parse_makefile_for_executables(git_builtin_extra "BUILT_INS") @@ -1120,6 +1123,20 @@ set(wrapper_scripts set(wrapper_test_scripts test-fake-ssh test-tool) +if(CURL_FOUND) + list(APPEND wrapper_test_scripts test-gvfs-protocol) + + add_executable(test-gvfs-protocol ${CMAKE_SOURCE_DIR}/t/helper/test-gvfs-protocol.c) + target_link_libraries(test-gvfs-protocol common-main) + + if(MSVC) + set_target_properties(test-gvfs-protocol + PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/t/helper) + set_target_properties(test-gvfs-protocol + PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/t/helper) + endif() +endif() + foreach(script ${wrapper_scripts}) file(STRINGS ${CMAKE_SOURCE_DIR}/bin-wrappers/wrap-for-bin.sh content NEWLINE_CONSUME) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index e3d88b06721b39..a5666585396653 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1837,7 +1837,7 @@ _git_clone () esac } -__git_untracked_file_modes="all no normal" +__git_untracked_file_modes="all no normal complete" __git_trailer_tokens () { diff --git a/contrib/long-running-read-object/example.pl b/contrib/long-running-read-object/example.pl new file mode 100644 index 00000000000000..b8f37f836a813c --- /dev/null +++ b/contrib/long-running-read-object/example.pl @@ -0,0 +1,114 @@ +#!/usr/bin/perl +# +# Example implementation for the Git read-object protocol version 1 +# See Documentation/technical/read-object-protocol.txt +# +# Allows you to test the ability for blobs to be pulled from a host git repo +# "on demand." Called when git needs a blob it couldn't find locally due to +# a lazy clone that only cloned the commits and trees. +# +# A lazy clone can be simulated via the following commands from the host repo +# you wish to create a lazy clone of: +# +# cd /host_repo +# git rev-parse HEAD +# git init /guest_repo +# git cat-file --batch-check --batch-all-objects | grep -v 'blob' | +# cut -d' ' -f1 | git pack-objects /guest_repo/.git/objects/pack/noblobs +# cd /guest_repo +# git config core.virtualizeobjects true +# git reset --hard +# +# Please note, this sample is a minimal skeleton. No proper error handling +# was implemented. +# + +use strict; +use warnings; + +# +# Point $DIR to the folder where your host git repo is located so we can pull +# missing objects from it +# +my $DIR = "/host_repo/.git/"; + +sub packet_bin_read { + my $buffer; + my $bytes_read = read STDIN, $buffer, 4; + if ( $bytes_read == 0 ) { + + # EOF - Git stopped talking to us! + exit(); + } + elsif ( $bytes_read != 4 ) { + die "invalid packet: '$buffer'"; + } + my $pkt_size = hex($buffer); + if ( $pkt_size == 0 ) { + return ( 1, "" ); + } + elsif ( $pkt_size > 4 ) { + my $content_size = $pkt_size - 4; + $bytes_read = read STDIN, $buffer, $content_size; + if ( $bytes_read != $content_size ) { + die "invalid packet ($content_size bytes expected; $bytes_read bytes read)"; + } + return ( 0, $buffer ); + } + else { + die "invalid packet size: $pkt_size"; + } +} + +sub packet_txt_read { + my ( $res, $buf ) = packet_bin_read(); + unless ( $buf =~ s/\n$// ) { + die "A non-binary line MUST be terminated by an LF."; + } + return ( $res, $buf ); +} + +sub packet_bin_write { + my $buf = shift; + print STDOUT sprintf( "%04x", length($buf) + 4 ); + print STDOUT $buf; + STDOUT->flush(); +} + +sub packet_txt_write { + packet_bin_write( $_[0] . "\n" ); +} + +sub packet_flush { + print STDOUT sprintf( "%04x", 0 ); + STDOUT->flush(); +} + +( packet_txt_read() eq ( 0, "git-read-object-client" ) ) || die "bad initialize"; +( packet_txt_read() eq ( 0, "version=1" ) ) || die "bad version"; +( packet_bin_read() eq ( 1, "" ) ) || die "bad version end"; + +packet_txt_write("git-read-object-server"); +packet_txt_write("version=1"); +packet_flush(); + +( packet_txt_read() eq ( 0, "capability=get" ) ) || die "bad capability"; +( packet_bin_read() eq ( 1, "" ) ) || die "bad capability end"; + +packet_txt_write("capability=get"); +packet_flush(); + +while (1) { + my ($command) = packet_txt_read() =~ /^command=([^=]+)$/; + + if ( $command eq "get" ) { + my ($sha1) = packet_txt_read() =~ /^sha1=([0-9a-f]{40})$/; + packet_bin_read(); + + system ('git --git-dir="' . $DIR . '" cat-file blob ' . $sha1 . ' | git -c core.virtualizeobjects=false hash-object -w --stdin >/dev/null 2>&1'); + packet_txt_write(($?) ? "status=error" : "status=success"); + packet_flush(); + } else { + die "bad command '$command'"; + } +} diff --git a/contrib/scalar/docs/faq.md b/contrib/scalar/docs/faq.md new file mode 100644 index 00000000000000..a14f78a996d5d5 --- /dev/null +++ b/contrib/scalar/docs/faq.md @@ -0,0 +1,51 @@ +Frequently Asked Questions +========================== + +Using Scalar +------------ + +### I don't want a sparse clone, I want every file after I clone! + +Run `scalar clone --full-clone ` to initialize your repo to include +every file. You can switch to a sparse-checkout later by running +`git sparse-checkout init --cone`. + +### I already cloned without `--full-clone`. How do I get everything? + +Run `git sparse-checkout disable`. + +Scalar Design Decisions +----------------------- + +There may be many design decisions within Scalar that are confusing at first +glance. Some of them may cause friction when you use Scalar with your existing +repos and existing habits. + +> Scalar has the most benefit when users design repositories +> with efficient patterns. + +For example: Scalar uses the sparse-checkout feature to limit the size of the +working directory within a large monorepo. It is designed to work efficiently +with monorepos that are highly componentized, allowing most developers to +need many fewer files in their daily work. + +### Why does `scalar clone` create a `/src` folder? + +Scalar uses a file system watcher to keep track of changes under this `src` folder. +Any activity in this folder is assumed to be important to Git operations. By +creating the `src` folder, we are making it easy for your build system to +create output folders outside the `src` directory. We commonly see systems +create folders for build outputs and package downloads. Scalar itself creates +these folders during its builds. + +Your build system may create build artifacts such as `.obj` or `.lib` files +next to your source code. These are commonly "hidden" from Git using +`.gitignore` files. Having such artifacts in your source tree creates +additional work for Git because it needs to look at these files and match them +against the `.gitignore` patterns. + +By following the `src` pattern Scalar tries to establish and placing your build +intermediates and outputs parallel with the `src` folder and not inside it, +you can help optimize Git command performance for developers in the repository +by limiting the number of files Git needs to consider for many common +operations. diff --git a/contrib/scalar/docs/getting-started.md b/contrib/scalar/docs/getting-started.md new file mode 100644 index 00000000000000..d5125330320d2c --- /dev/null +++ b/contrib/scalar/docs/getting-started.md @@ -0,0 +1,109 @@ +Getting Started +=============== + +Registering existing Git repos +------------------------------ + +To add a repository to the list of registered repos, run `scalar register []`. +If `` is not provided, then the "current repository" is discovered from +the working directory by scanning the parent paths for a path containing a `.git` +folder, possibly inside a `src` folder. + +To see which repositories are currently tracked by the service, run +`scalar list`. + +Run `scalar unregister []` to remove the repo from this list. + +Creating a new Scalar clone +--------------------------------------------------- + +The `clone` verb creates a local enlistment of a remote repository using the +partial clone feature available e.g. on GitHub, or using the +[GVFS protocol](https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md), +such as Azure Repos. + +``` +scalar clone [options] [] +``` + +Create a local copy of the repository at ``. If specified, create the `` +directory and place the repository there. Otherwise, the last section of the `` +will be used for ``. + +At the end, the repo is located at `/src`. By default, the sparse-checkout +feature is enabled and the only files present are those in the root of your +Git repository. Use `git sparse-checkout set` to expand the set of directories +you want to see, or `git sparse-checkout disable` to expand to all files. You +can explore the subdirectories outside your sparse-checkout specification using +`git ls-tree HEAD`. + +### Sparse Repo Mode + +By default, Scalar reduces your working directory to only the files at the +root of the repository. You need to add the folders you care about to build up +to your working set. + +* `scalar clone ` + * Please choose the **Clone with HTTPS** option in the `Clone Repository` dialog in Azure Repos, not **Clone with SSH**. +* `cd \src` +* At this point, your `src` directory only contains files that appear in your root + tree. No folders are populated. +* Set the directory list for your sparse-checkout using: + 1. `git sparse-checkout set ...` + 2. `git sparse-checkout set --stdin < dir-list.txt` +* Run git commands as you normally would. +* To fully populate your working directory, run `git sparse-checkout disable`. + +If instead you want to start with all files on-disk, you can clone with the +`--full-clone` option. To enable sparse-checkout after the fact, run +`git sparse-checkout init --cone`. This will initialize your sparse-checkout +patterns to only match the files at root. + +If you are unfamiliar with what directories are available in the repository, +then you can run `git ls-tree -d --name-only HEAD` to discover the directories +at root, or `git ls-tree -d --name-only HEAD ` to discover the directories +in ``. + +### Options + +These options allow a user to customize their initial enlistment. + +* `--full-clone`: If specified, do not initialize the sparse-checkout feature. + All files will be present in your `src` directory. This behaves very similar + to a Git partial clone in that blobs are downloaded on demand. However, it + will use the GVFS protocol to download all Git objects. + +* `--cache-server-url=`: If specified, set the intended cache server to + the specified ``. All object queries will use the GVFS protocol to this + `` instead of the origin remote. If the remote supplies a list of + cache servers via the `/gvfs/config` endpoint, then the `clone` command + will select a nearby cache server from that list. + +* `--branch=`: Specify the branch to checkout after clone. + +* `--local-cache-path=`: Use this option to override the path for the + local Scalar cache. If not specified, then Scalar will select a default + path to share objects with your other enlistments. On Windows, this path + is a subdirectory of `:\.scalarCache\`. On Mac, this path is a + subdirectory of `~/.scalarCache/`. The default cache path is recommended so + multiple enlistments of the same remote repository share objects on the + same device. + +### Advanced Options + +The options below are not intended for use by a typical user. These are +usually used by build machines to create a temporary enlistment that +operates on a single commit. + +* `--single-branch`: Use this option to only download metadata for the branch + that will be checked out. This is helpful for build machines that target + a remote with many branches. Any `git fetch` commands after the clone will + still ask for all branches. + +Removing a Scalar Clone +----------------------- + +Since the `scalar clone` command sets up a file-system watcher (when available), +that watcher could prevent deleting the enlistment. Run `scalar delete ` +from outside of your enlistment to unregister the enlistment from the filesystem +watcher and delete the enlistment at ``. diff --git a/contrib/scalar/docs/index.md b/contrib/scalar/docs/index.md new file mode 100644 index 00000000000000..4f56e2b0ebbac6 --- /dev/null +++ b/contrib/scalar/docs/index.md @@ -0,0 +1,54 @@ +Scalar: Enabling Git at Scale +============================= + +Scalar is a tool that helps Git scale to some of the largest Git repositories. +It achieves this by enabling some advanced Git features, such as: + +* *Partial clone:* reduces time to get a working repository by not + downloading all Git objects right away. + +* *Background prefetch:* downloads Git object data from all remotes every + hour, reducing the amount of time for foreground `git fetch` calls. + +* *Sparse-checkout:* limits the size of your working directory. + +* *File system monitor:* tracks the recently modified files and eliminates + the need for Git to scan the entire worktree. + +* *Commit-graph:* accelerates commit walks and reachability calculations, + speeding up commands like `git log`. + +* *Multi-pack-index:* enables fast object lookups across many pack-files. + +* *Incremental repack:* Repacks the packed Git data into fewer pack-file + without disrupting concurrent commands by using the multi-pack-index. + +By running `scalar register` in any Git repo, Scalar will automatically enable +these features for that repo (except partial clone) and start running suggested +maintenance in the background using +[the `git maintenance` feature](https://git-scm.com/docs/git-maintenance). + +Repos cloned with the `scalar clone` command use partial clone or the +[GVFS protocol](https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md) +to significantly reduce the amount of data required to get started +using a repository. By delaying all blob downloads until they are required, +Scalar allows you to work with very large repositories quickly. The GVFS +protocol allows a network of _cache servers_ to serve objects with lower +latency and higher throughput. The cache servers also reduce load on the +central server. + +Documentation +------------- + +* [Getting Started](getting-started.md): Get started with Scalar. + Includes `scalar register`, `scalar unregister`, `scalar clone`, and + `scalar delete`. + +* [Troubleshooting](troubleshooting.md): + Collect diagnostic information or update custom settings. Includes + `scalar diagnose` and `scalar cache-server`. + +* [The Philosophy of Scalar](philosophy.md): Why does Scalar work the way + it does, and how do we make decisions about its future? + +* [Frequently Asked Questions](faq.md) diff --git a/contrib/scalar/docs/philosophy.md b/contrib/scalar/docs/philosophy.md new file mode 100644 index 00000000000000..e3dfa025a2504c --- /dev/null +++ b/contrib/scalar/docs/philosophy.md @@ -0,0 +1,71 @@ +The Philosophy of Scalar +======================== + +The team building Scalar has **opinions** about Git performance. Scalar +takes out the guesswork by automatically configuring your Git repositories +to take advantage of the latest and greatest features. It is difficult to +say that these are the absolute best settings for every repository, but +these settings do work for some of the largest repositories in the world. + +Scalar intends to do very little more than the standard Git client. We +actively implement new features into Git instead of Scalar, then update +Scalar only to configure those new settings. In particular, we ported +features like background maintenance to Git to make Scalar simpler and +make Git more powerful. + +Scalar ships inside [a custom version of Git][microsoft-git], but we are +working to make it available in other forks of Git. The only feature +that is not intended to ever reach the standard Git client is Scalar's use +of [the GVFS Protocol][gvfs-protocol], which is essentially an older +version of [Git's partial clone feature](https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/) +that was available first in Azure Repos. Services such as GitHub support +only partial clone instead of the GVFS protocol because that is the +standard adopted by the Git project. If your hosting service supports +partial clone, then we absolutely recommend it as a way to greatly speed +up your clone and fetch times and to reduce how much disk space your Git +repository requires. Scalar will help with this! + +If you don't use the GVFS Protocol, then most of the value of Scalar can +be found in the core Git client. However, most of the advanced features +that really optimize Git's performance are off by default for compatibility +reasons. To really take advantage of Git's latest and greatest features, +you either need to study the [`git config` documentation](https://git-scm.com/docs/git-config) +and regularly read [the Git release notes](https://github.com/git/git/tree/master/Documentation/RelNotes). +Even if you do all that work and customize your Git settings on your machines, +you likely will want to share those settings with other team members. +Or, you can just use Scalar! + +Using `scalar register` on an existing Git repository will give you these +benefits: + +* Additional compression of your `.git/index` file. +* Hourly background `git fetch` operations, keeping you in-sync with your + remotes. +* Advanced data structures, such as the `commit-graph` and `multi-pack-index` + are updated automatically in the background. +* If using macOS or Windows, then Scalar configures Git's builtin File System + Monitor, providing faster commands such as `git status` or `git add`. + +Additionally, if you use `scalar clone` to create a new repository, then +you will automatically get these benefits: + +* Use Git's partial clone feature to only download the files you need for + your current checkout. +* Use Git's [sparse-checkout feature][sparse-checkout] to minimize the + number of files required in your working directory. + [Read more about sparse-checkout here.][sparse-checkout-blog] +* Create the Git repository inside `/src` to make it easy to + place build artifacts outside of the Git repository, such as in + `/bin` or `/packages`. + +We also admit that these **opinions** can always be improved! If you have +an idea of how to improve our setup, consider +[creating an issue](https://github.com/microsoft/scalar/issues/new) or +contributing a pull request! Some [existing](https://github.com/microsoft/scalar/issues/382) +[issues](https://github.com/microsoft/scalar/issues/388) have already +improved our configuration settings and roadmap! + +[gvfs-protocol]: https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md +[microsoft-git]: https://github.com/microsoft/git +[sparse-checkout]: https://git-scm.com/docs/git-sparse-checkout +[sparse-checkout-blog]: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/ diff --git a/contrib/scalar/docs/troubleshooting.md b/contrib/scalar/docs/troubleshooting.md new file mode 100644 index 00000000000000..c54d2438f22523 --- /dev/null +++ b/contrib/scalar/docs/troubleshooting.md @@ -0,0 +1,40 @@ +Troubleshooting +=============== + +Diagnosing Issues +----------------- + +The `scalar diagnose` command collects logs and config details for the current +repository. The resulting zip file helps root-cause issues. + +When run inside your repository, creates a zip file containing several important +files for that repository. This includes: + +* Configuration files from your `.git` folder, such as the `config` file, + `index`, `hooks`, and `refs`. + +* A summary of your Git object database, including the number of loose objects + and the names and sizes of pack-files. + +As the `diagnose` command completes, it provides the path of the resulting +zip file. This zip can be attached to bug reports to make the analysis easier. + +Modifying Configuration Values +------------------------------ + +The Scalar-specific configuration is only available for repos using the +GVFS protocol. + +### Cache Server URL + +When using an enlistment cloned with `scalar clone` and the GVFS protocol, +you will have a value called the cache server URL. Cache servers are a feature +of the GVFS protocol to provide low-latency access to the on-demand object +requests. This modifies the `gvfs.cache-server` setting in your local Git config +file. + +Run `scalar cache-server --get` to see the current cache server. + +Run `scalar cache-server --list` to see the available cache server URLs. + +Run `scalar cache-server --set=` to set your cache server to ``. diff --git a/convert.c b/convert.c index b5f7cf6306c3c3..cfef6d16b7754c 100644 --- a/convert.c +++ b/convert.c @@ -3,6 +3,7 @@ #include "git-compat-util.h" #include "advice.h" +#include "gvfs.h" #include "config.h" #include "convert.h" #include "copy.h" @@ -563,6 +564,9 @@ static int crlf_to_git(struct index_state *istate, if (!buf) return 1; + if (gvfs_config_is_set(GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS)) + die("CRLF conversions not supported when running under GVFS"); + /* only grow if not in place */ if (strbuf_avail(buf) + buf->len < len) strbuf_grow(buf, len - buf->len); @@ -602,6 +606,9 @@ static int crlf_to_worktree(const char *src, size_t len, struct strbuf *buf, if (!will_convert_lf_to_crlf(&stats, crlf_action)) return 0; + if (gvfs_config_is_set(GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS)) + die("CRLF conversions not supported when running under GVFS"); + /* are we "faking" in place editing ? */ if (src == buf->buf) to_free = strbuf_detach(buf, NULL); @@ -711,6 +718,9 @@ static int apply_single_file_filter(const char *path, const char *src, size_t le struct async async; struct filter_params params; + if (gvfs_config_is_set(GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS)) + die("Filter \"%s\" not supported when running under GVFS", cmd); + memset(&async, 0, sizeof(async)); async.proc = filter_buffer_or_fd; async.data = ¶ms; @@ -1130,6 +1140,9 @@ static int ident_to_git(const char *src, size_t len, if (!buf) return 1; + if (gvfs_config_is_set(GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS)) + die("ident conversions not supported when running under GVFS"); + /* only grow if not in place */ if (strbuf_avail(buf) + buf->len < len) strbuf_grow(buf, len - buf->len); @@ -1177,6 +1190,9 @@ static int ident_to_worktree(const char *src, size_t len, if (!cnt) return 0; + if (gvfs_config_is_set(GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS)) + die("ident conversions not supported when running under GVFS"); + /* are we "faking" in place editing ? */ if (src == buf->buf) to_free = strbuf_detach(buf, NULL); @@ -1629,6 +1645,9 @@ static int lf_to_crlf_filter_fn(struct stream_filter *filter, size_t count, o = 0; struct lf_to_crlf_filter *lf_to_crlf = (struct lf_to_crlf_filter *)filter; + if (gvfs_config_is_set(GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS)) + die("CRLF conversions not supported when running under GVFS"); + /* * We may be holding onto the CR to see if it is followed by a * LF, in which case we would need to go to the main loop. @@ -1873,6 +1892,9 @@ static int ident_filter_fn(struct stream_filter *filter, struct ident_filter *ident = (struct ident_filter *)filter; static const char head[] = "$Id"; + if (gvfs_config_is_set(GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS)) + die("ident conversions not supported when running under GVFS"); + if (!input) { /* drain upon eof */ switch (ident->state) { diff --git a/credential.c b/credential.c index 2594c0c4229ba0..d1f31126bb5ff6 100644 --- a/credential.c +++ b/credential.c @@ -456,6 +456,8 @@ static int run_credential_helper(struct credential *c, else helper.no_stdout = 1; + helper.trace2_child_class = "cred"; + if (start_command(&helper) < 0) return -1; diff --git a/diagnose.c b/diagnose.c index b1be74be9831f8..0e329b21787a4f 100644 --- a/diagnose.c +++ b/diagnose.c @@ -12,6 +12,7 @@ #include "parse-options.h" #include "repository.h" #include "write-or-die.h" +#include "config.h" struct archive_dir { const char *path; @@ -71,6 +72,39 @@ static int dir_file_stats(struct object_directory *object_dir, void *data) return 0; } +static void dir_stats(struct strbuf *buf, const char *path) +{ + DIR *dir = opendir(path); + struct dirent *e; + struct stat e_stat; + struct strbuf file_path = STRBUF_INIT; + size_t base_path_len; + + if (!dir) + return; + + strbuf_addstr(buf, "Contents of "); + strbuf_add_absolute_path(buf, path); + strbuf_addstr(buf, ":\n"); + + strbuf_add_absolute_path(&file_path, path); + strbuf_addch(&file_path, '/'); + base_path_len = file_path.len; + + while ((e = readdir(dir)) != NULL) + if (!is_dot_or_dotdot(e->d_name) && e->d_type == DT_REG) { + strbuf_setlen(&file_path, base_path_len); + strbuf_addstr(&file_path, e->d_name); + if (!stat(file_path.buf, &e_stat)) + strbuf_addf(buf, "%-70s %16"PRIuMAX"\n", + e->d_name, + (uintmax_t)e_stat.st_size); + } + + strbuf_release(&file_path); + closedir(dir); +} + static int count_files(struct strbuf *path) { DIR *dir = opendir(path->buf); @@ -185,7 +219,8 @@ int create_diagnostics_archive(struct repository *r, struct strvec archiver_args = STRVEC_INIT; char **argv_copy = NULL; int stdout_fd = -1, archiver_fd = -1; - struct strbuf buf = STRBUF_INIT; + char *cache_server_url = NULL, *shared_cache = NULL; + struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT; int res; struct archive_dir archive_dirs[] = { { ".git", 0 }, @@ -220,6 +255,13 @@ int create_diagnostics_archive(struct repository *r, get_version_info(&buf, 1); strbuf_addf(&buf, "Repository root: %s\n", r->worktree); + + repo_config_get_string(r, "gvfs.cache-server", &cache_server_url); + repo_config_get_string(r, "gvfs.sharedCache", &shared_cache); + strbuf_addf(&buf, "Cache Server: %s\nLocal Cache: %s\n\n", + cache_server_url ? cache_server_url : "None", + shared_cache ? shared_cache : "None"); + get_disk_info(&buf); write_or_die(stdout_fd, buf.buf, buf.len); strvec_pushf(&archiver_args, @@ -250,6 +292,52 @@ int create_diagnostics_archive(struct repository *r, } } + if (shared_cache) { + size_t path_len; + + strbuf_reset(&buf); + strbuf_addf(&path, "%s/pack", shared_cache); + strbuf_reset(&buf); + strbuf_addstr(&buf, "--add-virtual-file=packs-cached.txt:"); + dir_stats(&buf, path.buf); + strvec_push(&archiver_args, buf.buf); + + strbuf_reset(&buf); + strbuf_addstr(&buf, "--add-virtual-file=objects-cached.txt:"); + loose_objs_stats(&buf, shared_cache); + strvec_push(&archiver_args, buf.buf); + + strbuf_reset(&path); + strbuf_addf(&path, "%s/info", shared_cache); + path_len = path.len; + + if (is_directory(path.buf)) { + DIR *dir = opendir(path.buf); + struct dirent *e; + + while ((e = readdir(dir))) { + if (!strcmp(".", e->d_name) || !strcmp("..", e->d_name)) + continue; + if (e->d_type == DT_DIR) + continue; + + strbuf_reset(&buf); + strbuf_addf(&buf, "--add-virtual-file=info/%s:", e->d_name); + + strbuf_setlen(&path, path_len); + strbuf_addch(&path, '/'); + strbuf_addstr(&path, e->d_name); + + if (strbuf_read_file(&buf, path.buf, 0) < 0) { + res = error_errno(_("could not read '%s'"), path.buf); + goto diagnose_cleanup; + } + strvec_push(&archiver_args, buf.buf); + } + closedir(dir); + } + } + strvec_pushl(&archiver_args, "--prefix=", oid_to_hex(r->hash_algo->empty_tree), "--", NULL); @@ -263,10 +351,13 @@ int create_diagnostics_archive(struct repository *r, goto diagnose_cleanup; } - fprintf(stderr, "\n" - "Diagnostics complete.\n" - "All of the gathered info is captured in '%s'\n", - zip_path->buf); + strbuf_reset(&buf); + strbuf_addf(&buf, "\n" + "Diagnostics complete.\n" + "All of the gathered info is captured in '%s'\n", + zip_path->buf); + write_or_die(stdout_fd, buf.buf, buf.len); + write_or_die(2, buf.buf, buf.len); diagnose_cleanup: if (archiver_fd >= 0) { @@ -277,6 +368,8 @@ int create_diagnostics_archive(struct repository *r, free(argv_copy); strvec_clear(&archiver_args); strbuf_release(&buf); + free(cache_server_url); + free(shared_cache); return res; } diff --git a/diff.c b/diff.c index 90e8003dd11e4d..627ff5cfabc5a2 100644 --- a/diff.c +++ b/diff.c @@ -4046,6 +4046,13 @@ static int reuse_worktree_file(struct index_state *istate, has_object_pack(istate->repo, oid)) return 0; + /* + * If this path does not match our sparse-checkout definition, + * then the file will not be in the working directory. + */ + if (!path_in_sparse_checkout(name, istate)) + return 0; + /* * Similarly, if we'd have to convert the file contents anyway, that * makes the optimization not worthwhile. diff --git a/dir.c b/dir.c index 6a0e11de6802ea..1185be724f6d10 100644 --- a/dir.c +++ b/dir.c @@ -11,6 +11,7 @@ #include "git-compat-util.h" #include "abspath.h" +#include "virtualfilesystem.h" #include "config.h" #include "convert.h" #include "dir.h" @@ -1485,6 +1486,19 @@ enum pattern_match_result path_matches_pattern_list( int result = NOT_MATCHED; size_t slash_pos; + if (core_virtualfilesystem) { + /* + * The virtual file system data is used to prevent git from traversing + * any part of the tree that is not in the virtual file system. Return + * 1 to exclude the entry if it is not found in the virtual file system, + * else fall through to the regular excludes logic as it may further exclude. + */ + if (*dtype == DT_UNKNOWN) + *dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen); + if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0) + return 1; + } + if (!pl->use_cone_patterns) { pattern = last_matching_pattern_from_list(pathname, pathlen, basename, dtype, pl, istate); @@ -1574,6 +1588,13 @@ static int path_in_sparse_checkout_1(const char *path, enum pattern_match_result match = UNDECIDED; const char *end, *slash; + /* + * When using a virtual filesystem, there aren't really patterns + * to follow, but be extra careful to skip this check. + */ + if (core_virtualfilesystem) + return 1; + /* * We default to accepting a path if the path is empty, there are no * patterns, or the patterns are of the wrong type. @@ -1829,8 +1850,22 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir, int is_excluded(struct dir_struct *dir, struct index_state *istate, const char *pathname, int *dtype_p) { - struct path_pattern *pattern = - last_matching_pattern(dir, istate, pathname, dtype_p); + struct path_pattern *pattern; + + if (core_virtualfilesystem) { + /* + * The virtual file system data is used to prevent git from traversing + * any part of the tree that is not in the virtual file system. Return + * 1 to exclude the entry if it is not found in the virtual file system, + * else fall through to the regular excludes logic as it may further exclude. + */ + if (*dtype_p == DT_UNKNOWN) + *dtype_p = resolve_dtype(DT_UNKNOWN, istate, pathname, strlen(pathname)); + if (is_excluded_from_virtualfilesystem(pathname, strlen(pathname), *dtype_p) > 0) + return 1; + } + + pattern = last_matching_pattern(dir, istate, pathname, dtype_p); if (pattern) return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1; return 0; @@ -2448,6 +2483,8 @@ static enum path_treatment treat_path(struct dir_struct *dir, ignore_case); if (dtype != DT_DIR && has_path_in_index) return path_none; + if (is_excluded_from_virtualfilesystem(path->buf, path->len, dtype) > 0) + return path_excluded; /* * When we are looking at a directory P in the working tree, @@ -2652,6 +2689,8 @@ static void add_path_to_appropriate_result_list(struct dir_struct *dir, /* add the path to the appropriate result list */ switch (state) { case path_excluded: + if (is_excluded_from_virtualfilesystem(path->buf, path->len, DT_DIR) > 0) + break; if (dir->flags & DIR_SHOW_IGNORED) dir_add_name(dir, istate, path->buf, path->len); else if ((dir->flags & DIR_SHOW_IGNORED_TOO) || @@ -3199,6 +3238,8 @@ static int cmp_icase(char a, char b) { if (a == b) return 0; + if (is_dir_sep(a)) + return is_dir_sep(b) ? 0 : -1; if (ignore_case) return toupper(a) - toupper(b); return a - b; diff --git a/entry.c b/entry.c index 6a19769b7ae308..24dba7a51fe6bd 100644 --- a/entry.c +++ b/entry.c @@ -455,7 +455,7 @@ static void mark_colliding_entries(const struct checkout *state, ce->ce_flags |= CE_MATCHED; /* TODO: audit for interaction with sparse-index. */ - ensure_full_index(state->istate); + ensure_full_index_unaudited(state->istate); for (size_t i = 0; i < state->istate->cache_nr; i++) { struct cache_entry *dup = state->istate->cache[i]; diff --git a/environment.c b/environment.c index bea386da217ce3..1223bfe9516407 100644 --- a/environment.c +++ b/environment.c @@ -67,9 +67,12 @@ int grafts_keep_true_parents; int core_apply_sparse_checkout; int core_sparse_checkout_cone; int sparse_expect_files_outside_of_patterns; +int core_gvfs; +char *core_virtualfilesystem; int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ unsigned long pack_size_limit_cfg; +int core_virtualize_objects; int max_allowed_tree_depth = #ifdef _MSC_VER /* @@ -116,6 +119,9 @@ int protect_hfs = PROTECT_HFS_DEFAULT; #define PROTECT_NTFS_DEFAULT 1 #endif int protect_ntfs = PROTECT_NTFS_DEFAULT; +int core_use_gvfs_helper; +char *gvfs_cache_server_url; +struct strbuf gvfs_shared_cache_pathname = STRBUF_INIT; /* * The character that begins a commented line in user-editable file diff --git a/environment.h b/environment.h index 3d98461a06f702..f890659730ef19 100644 --- a/environment.h +++ b/environment.h @@ -156,9 +156,14 @@ extern unsigned long pack_size_limit_cfg; extern int max_allowed_tree_depth; extern int core_preload_index; +extern char *core_virtualfilesystem; +extern int core_gvfs; extern int precomposed_unicode; extern int protect_hfs; extern int protect_ntfs; +extern int core_use_gvfs_helper; +extern char *gvfs_cache_server_url; +extern struct strbuf gvfs_shared_cache_pathname; extern int core_apply_sparse_checkout; extern int core_sparse_checkout_cone; @@ -210,5 +215,6 @@ extern const char *comment_line_str; extern char *comment_line_str_to_free; extern int auto_comment_line_char; +extern int core_virtualize_objects; # endif /* USE_THE_REPOSITORY_VARIABLE */ #endif /* ENVIRONMENT_H */ diff --git a/generate-configlist.sh b/generate-configlist.sh index b06da53c891819..75c39ade20939d 100755 --- a/generate-configlist.sh +++ b/generate-configlist.sh @@ -13,17 +13,16 @@ print_config_list () { cat <&2 " * $TCL_PATH failed; using unoptimized loading" - rm -f $@ + rm -f lib/tclIndex echo '# Autogenerated by git-gui Makefile' >lib/tclIndex echo >>lib/tclIndex echo "class.tcl" >>lib/tclIndex diff --git a/git.c b/git.c index 8b468567377993..d2abaa4e68d2a9 100644 --- a/git.c +++ b/git.c @@ -1,6 +1,7 @@ #define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" +#include "gvfs.h" #include "config.h" #include "environment.h" #include "exec-cmd.h" @@ -17,6 +18,8 @@ #include "shallow.h" #include "trace.h" #include "trace2.h" +#include "dir.h" +#include "hook.h" #define RUN_SETUP (1<<0) #define RUN_SETUP_GENTLY (1<<1) @@ -28,6 +31,8 @@ #define NEED_WORK_TREE (1<<3) #define DELAY_PAGER_CONFIG (1<<4) #define NO_PARSEOPT (1<<5) /* parse-options is not used */ +#define BLOCK_ON_GVFS_REPO (1<<6) /* command not allowed in GVFS repos */ +#define BLOCK_ON_VFS_ENABLED (1<<7) /* command not allowed when virtual file system is used */ struct cmd_struct { const char *cmd; @@ -437,6 +442,69 @@ static int handle_alias(struct strvec *args) return ret; } +/* Runs pre/post-command hook */ +static struct strvec sargv = STRVEC_INIT; +static int run_post_hook = 0; +static int exit_code = -1; + +static int run_pre_command_hook(struct repository *r, const char **argv) +{ + char *lock; + int ret = 0; + struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; + + /* + * Ensure the global pre/post command hook is only called for + * the outer command and not when git is called recursively + * or spawns multiple commands (like with the alias command) + */ + lock = getenv("COMMAND_HOOK_LOCK"); + if (lock && !strcmp(lock, "true")) + return 0; + setenv("COMMAND_HOOK_LOCK", "true", 1); + + /* call the hook proc */ + strvec_pushv(&sargv, argv); + strvec_pushf(&sargv, "--git-pid=%"PRIuMAX, (uintmax_t)getpid()); + strvec_pushv(&opt.args, sargv.v); + ret = run_hooks_opt(r, "pre-command", &opt); + + if (!ret) + run_post_hook = 1; + return ret; +} + +static int run_post_command_hook(struct repository *r) +{ + char *lock; + int ret = 0; + struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; + + /* + * Only run post_command if pre_command succeeded in this process + */ + if (!run_post_hook) + return 0; + lock = getenv("COMMAND_HOOK_LOCK"); + if (!lock || strcmp(lock, "true")) + return 0; + + strvec_pushv(&opt.args, sargv.v); + strvec_pushf(&opt.args, "--exit_code=%u", exit_code); + ret = run_hooks_opt(r, "post-command", &opt); + + run_post_hook = 0; + strvec_clear(&sargv); + strvec_clear(&opt.args); + setenv("COMMAND_HOOK_LOCK", "false", 1); + return ret; +} + +static void post_command_hook_atexit(void) +{ + run_post_command_hook(the_repository); +} + static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct repository *repo) { int status, help; @@ -473,16 +541,27 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv, struct if (!help && p->option & NEED_WORK_TREE) setup_work_tree(); + if (!help && p->option & BLOCK_ON_GVFS_REPO && gvfs_config_is_set(GVFS_BLOCK_COMMANDS)) + die("'git %s' is not supported on a GVFS repo", p->cmd); + + if (!help && p->option & BLOCK_ON_VFS_ENABLED && gvfs_config_is_set(GVFS_USE_VIRTUAL_FILESYSTEM)) + die("'git %s' is not supported when using the virtual file system", p->cmd); + + if (run_pre_command_hook(the_repository, argv)) + die("pre-command hook aborted command"); + trace_argv_printf(argv, "trace: built-in: git"); trace2_cmd_name(p->cmd); validate_cache_entries(repo->index); - status = p->fn(argc, argv, prefix, no_repo ? NULL : repo); + exit_code = status = p->fn(argc, argv, prefix, no_repo ? NULL : repo); validate_cache_entries(repo->index); if (status) return status; + run_post_command_hook(the_repository); + /* Somebody closed stdout? */ if (fstat(fileno(stdout), &st)) return 0; @@ -552,7 +631,7 @@ static struct cmd_struct commands[] = { { "for-each-ref", cmd_for_each_ref, RUN_SETUP }, { "for-each-repo", cmd_for_each_repo, RUN_SETUP_GENTLY }, { "format-patch", cmd_format_patch, RUN_SETUP }, - { "fsck", cmd_fsck, RUN_SETUP }, + { "fsck", cmd_fsck, RUN_SETUP | BLOCK_ON_VFS_ENABLED }, { "fsck-objects", cmd_fsck, RUN_SETUP }, { "fsmonitor--daemon", cmd_fsmonitor__daemon, RUN_SETUP }, { "gc", cmd_gc, RUN_SETUP }, @@ -595,7 +674,7 @@ static struct cmd_struct commands[] = { { "pack-refs", cmd_pack_refs, RUN_SETUP }, { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT }, { "pickaxe", cmd_blame, RUN_SETUP }, - { "prune", cmd_prune, RUN_SETUP }, + { "prune", cmd_prune, RUN_SETUP | BLOCK_ON_VFS_ENABLED }, { "prune-packed", cmd_prune_packed, RUN_SETUP }, { "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE }, { "push", cmd_push, RUN_SETUP }, @@ -608,7 +687,7 @@ static struct cmd_struct commands[] = { { "remote", cmd_remote, RUN_SETUP }, { "remote-ext", cmd_remote_ext, NO_PARSEOPT }, { "remote-fd", cmd_remote_fd, NO_PARSEOPT }, - { "repack", cmd_repack, RUN_SETUP }, + { "repack", cmd_repack, RUN_SETUP | BLOCK_ON_VFS_ENABLED }, { "replace", cmd_replace, RUN_SETUP }, { "replay", cmd_replay, RUN_SETUP }, { "rerere", cmd_rerere, RUN_SETUP }, @@ -629,7 +708,7 @@ static struct cmd_struct commands[] = { { "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE }, { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE }, { "stripspace", cmd_stripspace }, - { "submodule--helper", cmd_submodule__helper, RUN_SETUP }, + { "submodule--helper", cmd_submodule__helper, RUN_SETUP | BLOCK_ON_GVFS_REPO }, { "survey", cmd_survey, RUN_SETUP }, { "switch", cmd_switch, RUN_SETUP | NEED_WORK_TREE }, { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP }, @@ -637,6 +716,7 @@ static struct cmd_struct commands[] = { { "unpack-file", cmd_unpack_file, RUN_SETUP | NO_PARSEOPT }, { "unpack-objects", cmd_unpack_objects, RUN_SETUP | NO_PARSEOPT }, { "update-index", cmd_update_index, RUN_SETUP }, + { "update-microsoft-git", cmd_update_microsoft_git }, { "update-ref", cmd_update_ref, RUN_SETUP }, { "update-server-info", cmd_update_server_info, RUN_SETUP }, { "upload-archive", cmd_upload_archive, NO_PARSEOPT }, @@ -648,7 +728,7 @@ static struct cmd_struct commands[] = { { "verify-tag", cmd_verify_tag, RUN_SETUP }, { "version", cmd_version }, { "whatchanged", cmd_whatchanged, RUN_SETUP }, - { "worktree", cmd_worktree, RUN_SETUP }, + { "worktree", cmd_worktree, RUN_SETUP | BLOCK_ON_VFS_ENABLED }, { "write-tree", cmd_write_tree, RUN_SETUP }, }; @@ -773,13 +853,16 @@ static void execv_dashed_external(const char **argv) */ trace_argv_printf(cmd.args.v, "trace: exec:"); + if (run_pre_command_hook(the_repository, cmd.args.v)) + die("pre-command hook aborted command"); + /* * If we fail because the command is not found, it is * OK to return. Otherwise, we just pass along the status code, * or our usual generic code if we were not even able to exec * the program. */ - status = run_command(&cmd); + exit_code = status = run_command(&cmd); /* * If the child process ran and we are now going to exit, emit a @@ -790,6 +873,8 @@ static void execv_dashed_external(const char **argv) exit(status); else if (errno != ENOENT) exit(128); + + run_post_command_hook(the_repository); } static int run_argv(struct strvec *args) @@ -897,6 +982,7 @@ int cmd_main(int argc, const char **argv) } trace_command_performance(argv); + atexit(post_command_hook_atexit); /* * "git-xxxx" is the same as "git xxxx", but we obviously: @@ -924,10 +1010,14 @@ int cmd_main(int argc, const char **argv) if (!argc) { /* The user didn't specify a command; give them help */ commit_pager_choice(); + if (run_pre_command_hook(the_repository, argv)) + die("pre-command hook aborted command"); printf(_("usage: %s\n\n"), git_usage_string); list_common_cmds_help(); printf("\n%s\n", _(git_more_info_string)); - exit(1); + exit_code = 1; + run_post_command_hook(the_repository); + exit(exit_code); } if (!strcmp("--version", argv[0]) || !strcmp("-v", argv[0])) diff --git a/gvfs-helper-client.c b/gvfs-helper-client.c new file mode 100644 index 00000000000000..a47af1b51fc328 --- /dev/null +++ b/gvfs-helper-client.c @@ -0,0 +1,615 @@ +#define USE_THE_REPOSITORY_VARIABLE +#include "git-compat-util.h" +#include "config.h" +#include "dir.h" +#include "environment.h" +#include "gvfs-helper-client.h" +#include "hex.h" +#include "object-file.h" +#include "object.h" +#include "oidset.h" +#include "packfile.h" +#include "pkt-line.h" +#include "quote.h" +#include "sigchain.h" +#include "strvec.h" +#include "sub-process.h" +#include "trace2.h" + +static struct oidset gh_client__oidset_queued = OIDSET_INIT; +static unsigned long gh_client__oidset_count; + +struct gh_server__process { + struct subprocess_entry subprocess; /* must be first */ + unsigned int supported_capabilities; +}; + +static int gh_server__subprocess_map_initialized; +static struct hashmap gh_server__subprocess_map; +static struct object_directory *gh_client__chosen_odb; + +/* + * The "objects" capability has verbs: "get" and "post" and "prefetch". + */ +#define CAP_OBJECTS (1u<<1) +#define CAP_OBJECTS_NAME "objects" + +#define CAP_OBJECTS__VERB_GET1_NAME "get" +#define CAP_OBJECTS__VERB_POST_NAME "post" +#define CAP_OBJECTS__VERB_PREFETCH_NAME "prefetch" + +static int gh_client__start_fn(struct subprocess_entry *subprocess) +{ + static int versions[] = {1, 0}; + static struct subprocess_capability capabilities[] = { + { CAP_OBJECTS_NAME, CAP_OBJECTS }, + { NULL, 0 } + }; + + struct gh_server__process *entry = (struct gh_server__process *)subprocess; + + return subprocess_handshake(subprocess, "gvfs-helper", versions, + NULL, capabilities, + &entry->supported_capabilities); +} + +/* + * Send the queued OIDs in the OIDSET to gvfs-helper for it to + * fetch from the cache-server or main Git server using "/gvfs/objects" + * POST semantics. + * + * objects.post LF + * ( LF)* + * + * + */ +static int gh_client__send__objects_post(struct child_process *process) +{ + struct oidset_iter iter; + struct object_id *oid; + int err; + + /* + * We assume that all of the packet_ routines call error() + * so that we don't have to. + */ + + err = packet_write_fmt_gently( + process->in, + (CAP_OBJECTS_NAME "." CAP_OBJECTS__VERB_POST_NAME "\n")); + if (err) + return err; + + oidset_iter_init(&gh_client__oidset_queued, &iter); + while ((oid = oidset_iter_next(&iter))) { + err = packet_write_fmt_gently(process->in, "%s\n", + oid_to_hex(oid)); + if (err) + return err; + } + + err = packet_flush_gently(process->in); + if (err) + return err; + + return 0; +} + +/* + * Send the given OID to gvfs-helper for it to fetch from the + * cache-server or main Git server using "/gvfs/objects" GET + * semantics. + * + * This ignores any queued OIDs. + * + * objects.get LF + * LF + * + * + */ +static int gh_client__send__objects_get(struct child_process *process, + const struct object_id *oid) +{ + int err; + + /* + * We assume that all of the packet_ routines call error() + * so that we don't have to. + */ + + err = packet_write_fmt_gently( + process->in, + (CAP_OBJECTS_NAME "." CAP_OBJECTS__VERB_GET1_NAME "\n")); + if (err) + return err; + + err = packet_write_fmt_gently(process->in, "%s\n", + oid_to_hex(oid)); + if (err) + return err; + + err = packet_flush_gently(process->in); + if (err) + return err; + + return 0; +} + +/* + * Send a request to gvfs-helper to prefetch packfiles from either the + * cache-server or the main Git server using "/gvfs/prefetch". + * + * objects.prefetch LF + * [ LF] + * + */ +static int gh_client__send__objects_prefetch(struct child_process *process, + timestamp_t seconds_since_epoch) +{ + int err; + + /* + * We assume that all of the packet_ routines call error() + * so that we don't have to. + */ + + err = packet_write_fmt_gently( + process->in, + (CAP_OBJECTS_NAME "." CAP_OBJECTS__VERB_PREFETCH_NAME "\n")); + if (err) + return err; + + if (seconds_since_epoch) { + err = packet_write_fmt_gently(process->in, "%" PRItime "\n", + seconds_since_epoch); + if (err) + return err; + } + + err = packet_flush_gently(process->in); + if (err) + return err; + + return 0; +} + +/* + * Update the loose object cache to include the newly created + * object. + */ +static void gh_client__update_loose_cache(const char *line) +{ + const char *v1_oid; + struct object_id oid; + + if (!skip_prefix(line, "loose ", &v1_oid)) + BUG("update_loose_cache: invalid line '%s'", line); + + if (get_oid_hex(v1_oid, &oid)) + BUG("update_loose_cache: invalid line '%s'", line); + + odb_loose_cache_add_new_oid(gh_client__chosen_odb, &oid); +} + +/* + * Update the packed-git list to include the newly created packfile. + */ +static void gh_client__update_packed_git(const char *line) +{ + struct strbuf path = STRBUF_INIT; + const char *v1_filename; + struct packed_git *p; + int is_local; + + if (!skip_prefix(line, "packfile ", &v1_filename)) + BUG("update_packed_git: invalid line '%s'", line); + + /* + * ODB[0] is the local .git/objects. All others are alternates. + */ + is_local = (gh_client__chosen_odb == the_repository->objects->odb); + + strbuf_addf(&path, "%s/pack/%s", + gh_client__chosen_odb->path, v1_filename); + strbuf_strip_suffix(&path, ".pack"); + strbuf_addstr(&path, ".idx"); + + p = add_packed_git(the_repository, path.buf, path.len, is_local); + if (p) + install_packed_git_and_mru(the_repository, p); + strbuf_release(&path); +} + +/* + * CAP_OBJECTS verbs return the same format response: + * + * + * * + * + * + * + * Where: + * + * ::= odb SP LF + * + * ::= / + * + * ::= packfile SP LF + * + * ::= loose SP LF + * + * ::= ok LF + * / partial LF + * / error SP LF + * + * Note that `gvfs-helper` controls how/if it chunks the request when + * it talks to the cache-server and/or main Git server. So it is + * possible for us to receive many packfiles and/or loose objects *AND + * THEN* get a hard network error or a 404 on an individual object. + * + * If we get a partial result, we can let the caller try to continue + * -- for example, maybe an immediate request for a tree object was + * grouped with a queued request for a blob. The tree-walk *might* be + * able to continue and let the 404 blob be handled later. + */ +static int gh_client__objects__receive_response( + struct child_process *process, + enum gh_client__created *p_ghc, + int *p_nr_loose, int *p_nr_packfile) +{ + enum gh_client__created ghc = GHC__CREATED__NOTHING; + const char *v1; + char *line; + int len; + int nr_loose = 0; + int nr_packfile = 0; + int err = 0; + + while (1) { + /* + * Warning: packet_read_line_gently() calls die() + * despite the _gently moniker. + */ + len = packet_read_line_gently(process->out, NULL, &line); + if ((len < 0) || !line) + break; + + if (starts_with(line, "odb")) { + /* trust that this matches what we expect */ + } + + else if (starts_with(line, "packfile")) { + gh_client__update_packed_git(line); + ghc |= GHC__CREATED__PACKFILE; + nr_packfile++; + } + + else if (starts_with(line, "loose")) { + gh_client__update_loose_cache(line); + ghc |= GHC__CREATED__LOOSE; + nr_loose++; + } + + else if (starts_with(line, "ok")) + ; + else if (starts_with(line, "partial")) + ; + else if (skip_prefix(line, "error ", &v1)) { + error("gvfs-helper error: '%s'", v1); + err = -1; + } + } + + *p_ghc = ghc; + *p_nr_loose = nr_loose; + *p_nr_packfile = nr_packfile; + + return err; +} + +/* + * Select the preferred ODB for fetching missing objects. + * This should be the alternate with the same directory + * name as set in `gvfs.sharedCache`. + * + * Fallback to .git/objects if necessary. + */ +static void gh_client__choose_odb(void) +{ + struct object_directory *odb; + + if (gh_client__chosen_odb) + return; + + prepare_alt_odb(the_repository); + gh_client__chosen_odb = the_repository->objects->odb; + + if (!gvfs_shared_cache_pathname.len) + return; + + for (odb = the_repository->objects->odb->next; odb; odb = odb->next) { + if (!fspathcmp(odb->path, gvfs_shared_cache_pathname.buf)) { + gh_client__chosen_odb = odb; + return; + } + } +} + +/* + * Custom exit handler for the `gvfs-helper` subprocesses. + * + * These helper subprocesses will keep waiting for input until they are + * stopped. The default `subprocess_exit_handler()` will instead wait for + * the subprocess to exit, which is not what we want: In case of a fatal + * error, the Git process will exit and the `gvfs-helper` subprocesses will + * need to be stopped explicitly. + * + * The default behavior of `cleanup_children()` does, however, terminate + * the process after calling the `clean_on_exit_handler`. So that's exactly + * what we do here: reproduce the exact same code as + * `subprocess_exit_handler()` modulo waiting for the process that won't + * ever terminate on its own. + */ +static void gh_client__subprocess_exit_handler(struct child_process *process) +{ + sigchain_push(SIGPIPE, SIG_IGN); + /* Closing the pipe signals the subprocess to initiate a shutdown. */ + close(process->in); + close(process->out); + sigchain_pop(SIGPIPE); + /* + * In contrast to subprocess_exit_handler(), do _not_ wait for the + * process to finish on its own accord: It needs to be terminated via + * a signal, which is what `cleanup_children()` will do after this + * function returns. + */ +} + +static struct gh_server__process *gh_client__find_long_running_process( + unsigned int cap_needed) +{ + struct gh_server__process *entry; + struct strvec argv = STRVEC_INIT; + struct strbuf quoted = STRBUF_INIT; + int fallback; + + gh_client__choose_odb(); + + /* + * TODO decide what defaults we want. + */ + strvec_push(&argv, "gvfs-helper"); + strvec_push(&argv, "--cache-server=trust"); + strvec_pushf(&argv, "--shared-cache=%s", + gh_client__chosen_odb->path); + + /* If gvfs.fallback=false, then don't add --fallback. */ + if (!git_config_get_bool("gvfs.fallback", &fallback) && + !fallback) + strvec_push(&argv, "--no-fallback"); + else + strvec_push(&argv, "--fallback"); + + strvec_push(&argv, "server"); + + sq_quote_argv_pretty("ed, argv.v); + + /* + * Find an existing long-running process with the above command + * line -or- create a new long-running process for this and + * subsequent requests. + */ + if (!gh_server__subprocess_map_initialized) { + gh_server__subprocess_map_initialized = 1; + hashmap_init(&gh_server__subprocess_map, + (hashmap_cmp_fn)cmd2process_cmp, NULL, 0); + entry = NULL; + } else + entry = (struct gh_server__process *)subprocess_find_entry( + &gh_server__subprocess_map, quoted.buf); + + if (!entry) { + entry = xmalloc(sizeof(*entry)); + entry->supported_capabilities = 0; + + if (subprocess_start_strvec(&gh_server__subprocess_map, + &entry->subprocess, 1, + &argv, gh_client__start_fn)) + FREE_AND_NULL(entry); + else + entry->subprocess.process.clean_on_exit_handler = + gh_client__subprocess_exit_handler; + } + + if (entry && + (entry->supported_capabilities & cap_needed) != cap_needed) { + error("gvfs-helper: does not support needed capabilities"); + subprocess_stop(&gh_server__subprocess_map, + (struct subprocess_entry *)entry); + FREE_AND_NULL(entry); + } + + strvec_clear(&argv); + strbuf_release("ed); + + return entry; +} + +void gh_client__queue_oid(const struct object_id *oid) +{ + /* + * Keep this trace as a printf only, so that it goes to the + * perf log, but not the event log. It is useful for interactive + * debugging, but generates way too much (unuseful) noise for the + * database. + */ + if (trace2_is_enabled()) + trace2_printf("gh_client__queue_oid: %s", oid_to_hex(oid)); + + if (!oidset_insert(&gh_client__oidset_queued, oid)) + gh_client__oidset_count++; +} + +/* + * This routine should actually take a "const struct oid_array *" + * rather than the component parts, but fetch_objects() uses + * this model (because of the call in sha1-file.c). + */ +void gh_client__queue_oid_array(const struct object_id *oids, int oid_nr) +{ + int k; + + for (k = 0; k < oid_nr; k++) + gh_client__queue_oid(&oids[k]); +} + +/* + * Bulk fetch all of the queued OIDs in the OIDSET. + */ +int gh_client__drain_queue(enum gh_client__created *p_ghc) +{ + struct gh_server__process *entry; + struct child_process *process; + int nr_loose = 0; + int nr_packfile = 0; + int err = 0; + + *p_ghc = GHC__CREATED__NOTHING; + + if (!gh_client__oidset_count) + return 0; + + entry = gh_client__find_long_running_process(CAP_OBJECTS); + if (!entry) + return -1; + + trace2_region_enter("gh-client", "objects/post", the_repository); + + process = &entry->subprocess.process; + + sigchain_push(SIGPIPE, SIG_IGN); + + err = gh_client__send__objects_post(process); + if (!err) + err = gh_client__objects__receive_response( + process, p_ghc, &nr_loose, &nr_packfile); + + sigchain_pop(SIGPIPE); + + if (err) { + subprocess_stop(&gh_server__subprocess_map, + (struct subprocess_entry *)entry); + FREE_AND_NULL(entry); + } + + trace2_data_intmax("gh-client", the_repository, + "objects/post/nr_objects", gh_client__oidset_count); + trace2_region_leave("gh-client", "objects/post", the_repository); + + oidset_clear(&gh_client__oidset_queued); + gh_client__oidset_count = 0; + + return err; +} + +/* + * Get exactly 1 object immediately. + * Ignore any queued objects. + */ +int gh_client__get_immediate(const struct object_id *oid, + enum gh_client__created *p_ghc) +{ + struct gh_server__process *entry; + struct child_process *process; + int nr_loose = 0; + int nr_packfile = 0; + int err = 0; + + /* + * Keep this trace as a printf only, so that it goes to the + * perf log, but not the event log. It is useful for interactive + * debugging, but generates way too much (unuseful) noise for the + * database. + */ + if (trace2_is_enabled()) + trace2_printf("gh_client__get_immediate: %s", oid_to_hex(oid)); + + entry = gh_client__find_long_running_process(CAP_OBJECTS); + if (!entry) + return -1; + + trace2_region_enter("gh-client", "objects/get", the_repository); + + process = &entry->subprocess.process; + + sigchain_push(SIGPIPE, SIG_IGN); + + err = gh_client__send__objects_get(process, oid); + if (!err) + err = gh_client__objects__receive_response( + process, p_ghc, &nr_loose, &nr_packfile); + + sigchain_pop(SIGPIPE); + + if (err) { + subprocess_stop(&gh_server__subprocess_map, + (struct subprocess_entry *)entry); + FREE_AND_NULL(entry); + } + + trace2_region_leave("gh-client", "objects/get", the_repository); + + return err; +} + +/* + * Ask gvfs-helper to prefetch commits-and-trees packfiles since a + * given timestamp. + * + * If seconds_since_epoch is zero, gvfs-helper will scan the ODB for + * the last received prefetch and ask for ones newer than that. + */ +int gh_client__prefetch(timestamp_t seconds_since_epoch, + int *nr_packfiles_received) +{ + struct gh_server__process *entry; + struct child_process *process; + enum gh_client__created ghc; + int nr_loose = 0; + int nr_packfile = 0; + int err = 0; + + entry = gh_client__find_long_running_process(CAP_OBJECTS); + if (!entry) + return -1; + + trace2_region_enter("gh-client", "objects/prefetch", the_repository); + trace2_data_intmax("gh-client", the_repository, "prefetch/since", + seconds_since_epoch); + + process = &entry->subprocess.process; + + sigchain_push(SIGPIPE, SIG_IGN); + + err = gh_client__send__objects_prefetch(process, seconds_since_epoch); + if (!err) + err = gh_client__objects__receive_response( + process, &ghc, &nr_loose, &nr_packfile); + + sigchain_pop(SIGPIPE); + + if (err) { + subprocess_stop(&gh_server__subprocess_map, + (struct subprocess_entry *)entry); + FREE_AND_NULL(entry); + } + + trace2_data_intmax("gh-client", the_repository, + "prefetch/packfile_count", nr_packfile); + trace2_region_leave("gh-client", "objects/prefetch", the_repository); + + if (nr_packfiles_received) + *nr_packfiles_received = nr_packfile; + + return err; +} diff --git a/gvfs-helper-client.h b/gvfs-helper-client.h new file mode 100644 index 00000000000000..7692534ecda54c --- /dev/null +++ b/gvfs-helper-client.h @@ -0,0 +1,87 @@ +#ifndef GVFS_HELPER_CLIENT_H +#define GVFS_HELPER_CLIENT_H + +struct repository; +struct commit; +struct object_id; + +enum gh_client__created { + /* + * The _get_ operation did not create anything. If doesn't + * matter if `gvfs-helper` had errors or not -- just that + * nothing was created. + */ + GHC__CREATED__NOTHING = 0, + + /* + * The _get_ operation created one or more packfiles. + */ + GHC__CREATED__PACKFILE = 1<<1, + + /* + * The _get_ operation created one or more loose objects. + * (Not necessarily the for the individual OID you requested.) + */ + GHC__CREATED__LOOSE = 1<<2, + + /* + * The _get_ operation created one or more packfilea *and* + * one or more loose objects. + */ + GHC__CREATED__PACKFILE_AND_LOOSE = (GHC__CREATED__PACKFILE | + GHC__CREATED__LOOSE), +}; + +/* + * Ask `gvfs-helper server` to immediately fetch a single object + * using "/gvfs/objects" GET semantics. + * + * A long-running background process is used to make subsequent + * requests more efficient. + * + * A loose object will be created in the shared-cache ODB and + * in-memory cache updated. + */ +int gh_client__get_immediate(const struct object_id *oid, + enum gh_client__created *p_ghc); + +/* + * Queue this OID for a future fetch using `gvfs-helper service`. + * It does not wait. + * + * Callers should not rely on the queued object being on disk until + * the queue has been drained. + */ +void gh_client__queue_oid(const struct object_id *oid); +void gh_client__queue_oid_array(const struct object_id *oids, int oid_nr); + +/* + * Ask `gvfs-helper server` to fetch the set of queued OIDs using + * "/gvfs/objects" POST semantics. + * + * A long-running background process is used to subsequent requests + * more efficient. + * + * One or more packfiles will be created in the shared-cache ODB. + */ +int gh_client__drain_queue(enum gh_client__created *p_ghc); + +/* + * Ask `gvfs-helper server` to fetch any "prefetch packs" + * available on the server more recent than the requested time. + * + * If seconds_since_epoch is zero, gvfs-helper will scan the ODB for + * the last received prefetch and ask for ones newer than that. + * + * A long-running background process is used to subsequent requests + * (either prefetch or regular immediate/queued requests) more efficient. + * + * One or more packfiles will be created in the shared-cache ODB. + * + * Returns 0 on success, -1 on error. Optionally also returns the + * number of prefetch packs received. + */ +int gh_client__prefetch(timestamp_t seconds_since_epoch, + int *nr_packfiles_received); + +#endif /* GVFS_HELPER_CLIENT_H */ diff --git a/gvfs-helper.c b/gvfs-helper.c new file mode 100644 index 00000000000000..26db841a03eeaf --- /dev/null +++ b/gvfs-helper.c @@ -0,0 +1,4245 @@ +// TODO Write a man page. Here are some notes for dogfooding. +// TODO +// +// Usage: git gvfs-helper [] [] +// +// : +// +// --remote= // defaults to "origin" +// +// --fallback // boolean. defaults to off +// +// When a fetch from the cache-server fails, automatically +// fallback to the main Git server. This option has no effect +// if no cache-server is defined. +// +// --cache-server= // defaults to "verify" +// +// verify := lookup the set of defined cache-servers using +// "gvfs/config" and confirm that the selected +// cache-server is well-known. Silently disable the +// cache-server if not. (See security notes later.) +// +// error := verify cache-server and abort if not well-known. +// +// trust := do not verify cache-server. just use it, if set. +// +// disable := disable the cache-server and always use the main +// Git server. +// +// --shared-cache= +// +// A relative or absolute pathname to the ODB directory to store +// fetched objects. +// +// If this option is not specified, we default to the value +// in the "gvfs.sharedcache" config setting and then to the +// local ".git/objects" directory. +// +// : +// +// config +// +// Fetch the "gvfs/config" string from the main Git server. +// (The cache-server setting is ignored because cache-servers +// do not support this REST API.) +// +// get +// +// Fetch 1 or more objects one at a time using a "/gvfs/objects" +// GET request. +// +// If a cache-server is configured, +// try it first. Optionally fallback to the main Git server. +// +// The set of objects is given on stdin and is assumed to be +// a list of , one per line. +// +// : +// +// --max-retries= // defaults to "6" +// +// Number of retries after transient network errors. +// Set to zero to disable such retries. +// +// post +// +// Fetch 1 or more objects in bulk using a "/gvfs/objects" POST +// request. +// +// If a cache-server is configured, +// try it first. Optionally fallback to the main Git server. +// +// The set of objects is given on stdin and is assumed to be +// a list of , one per line. +// +// : +// +// --block-size= // defaults to "4000" +// +// Request objects from server in batches of at +// most n objects (not bytes). +// +// --depth= // defaults to "1" +// +// --max-retries= // defaults to "6" +// +// Number of retries after transient network errors. +// Set to zero to disable such retries. +// +// prefetch +// +// Use "/gvfs/prefetch" REST API to fetch 1 or more commits-and-trees +// prefetch packs from the server. +// +// : +// +// --since= // defaults to "0" +// +// Time in seconds since the epoch. If omitted or +// zero, the timestamp from the newest prefetch +// packfile found in the shared-cache ODB is used. +// (This is based upon the packfile name, not the +// mtime.) +// +// The GVFS Protocol defines this value as a way to +// request cached packfiles NEWER THAN this timestamp. +// +// --max-retries= // defaults to "6" +// +// Number of retries after transient network errors. +// Set to zero to disable such retries. +// +// server +// +// Interactive/sub-process mode. Listen for a series of commands +// and data on stdin and return results on stdout. This command +// uses pkt-line format [1] and implements the long-running process +// protocol [2] to communicate with the foreground/parent process. +// +// : +// +// --block-size= // defaults to "4000" +// +// Request objects from server in batches of at +// most n objects (not bytes) when using POST +// requests. +// +// --depth= // defaults to "1" +// +// --max-retries= // defaults to "6" +// +// Number of retries after transient network errors. +// Set to zero to disable such retries. +// +// Interactive verb: objects.get +// +// Fetch 1 or more objects, one at a time, using a +// "/gvfs/objects" GET requests. +// +// Each object will be created as a loose object in the ODB. +// +// Create 1 or more loose objects in the shared-cache ODB. +// (The pathname of the selected ODB is reported at the +// beginning of the response; this should match the pathname +// given on the command line). +// +// git> objects.get +// git> +// git> +// git> ... +// git> +// git> 0000 +// +// git< odb +// git< loose +// git< loose +// git< ... +// git< loose +// git< ok | partial | error +// git< 0000 +// +// Interactive verb: objects.post +// +// Fetch 1 or more objects, in bulk, using one or more +// "/gvfs/objects" POST requests. +// +// Create 1 or more loose objects and/or packfiles in the +// shared-cache ODB. A POST is allowed to respond with +// either loose or packed objects. +// +// git> objects.post +// git> +// git> +// git> ... +// git> +// git> 0000 +// +// git< odb +// git< loose | packfile +// git< loose | packfile +// git< ... +// git< loose | packfile +// git< ok | partial | error +// git< 0000 +// +// Interactive verb: object.prefetch +// +// Fetch 1 or more prefetch packs using a "/gvfs/prefetch" +// request. +// +// git> objects.prefetch +// git> // optional +// git> 0000 +// +// git< odb +// git< packfile +// git< packfile +// git< ... +// git< packfile +// git< ok | error +// git< 0000 +// +// If a cache-server is configured, try it first. +// Optionally fallback to the main Git server. +// +// [1] Documentation/technical/protocol-common.txt +// [2] Documentation/technical/long-running-process-protocol.txt +// [3] See GIT_TRACE_PACKET +// +// endpoint +// +// Fetch the given endpoint from the main Git server (specifying +// `gvfs/config` as endpoint is idempotent to the `config` +// command mentioned above). +// +////////////////////////////////////////////////////////////////// + +#define USE_THE_REPOSITORY_VARIABLE +#include "git-compat-util.h" +#include "git-curl-compat.h" +#include "environment.h" +#include "hex.h" +#include "setup.h" +#include "config.h" +#include "remote.h" +#include "connect.h" +#include "strbuf.h" +#include "walker.h" +#include "http.h" +#include "exec-cmd.h" +#include "run-command.h" +#include "pkt-line.h" +#include "string-list.h" +#include "sideband.h" +#include "strvec.h" +#include "credential.h" +#include "oid-array.h" +#include "send-pack.h" +#include "path.h" +#include "protocol.h" +#include "quote.h" +#include "transport.h" +#include "parse-options.h" +#include "object-file.h" +#include "object-store.h" +#include "json-writer.h" +#include "tempfile.h" +#include "oidset.h" +#include "dir.h" +#include "url.h" +#include "abspath.h" +#include "progress.h" +#include "trace2.h" +#include "wrapper.h" +#include "packfile.h" +#include "date.h" + +#define TR2_CAT "gvfs-helper" + +static const char * const main_usage[] = { + N_("git gvfs-helper [] config []"), + N_("git gvfs-helper [] get []"), + N_("git gvfs-helper [] post []"), + N_("git gvfs-helper [] prefetch []"), + N_("git gvfs-helper [] server []"), + NULL +}; + +static const char *const objects_get_usage[] = { + N_("git gvfs-helper [] get []"), + NULL +}; + +static const char *const objects_post_usage[] = { + N_("git gvfs-helper [] post []"), + NULL +}; + +static const char *const prefetch_usage[] = { + N_("git gvfs-helper [] prefetch []"), + NULL +}; + +static const char *const server_usage[] = { + N_("git gvfs-helper [] server []"), + NULL +}; + +/* + * "commitDepth" field in gvfs protocol + */ +#define GH__DEFAULT__OBJECTS_POST__COMMIT_DEPTH 1 + +/* + * Chunk/block size in number of objects we request in each packfile + */ +#define GH__DEFAULT__OBJECTS_POST__BLOCK_SIZE 4000 + +/* + * Retry attempts (after the initial request) for transient errors and 429s. + */ +#define GH__DEFAULT_MAX_RETRIES 6 + +/* + * Maximum delay in seconds for transient (network) error retries. + */ +#define GH__DEFAULT_MAX_TRANSIENT_BACKOFF_SEC 300 + +/* + * Our exit-codes. + */ +enum gh__error_code { + GH__ERROR_CODE__USAGE = -1, /* will be mapped to usage() */ + GH__ERROR_CODE__OK = 0, + GH__ERROR_CODE__ERROR = 1, /* unspecified */ + GH__ERROR_CODE__CURL_ERROR = 2, + GH__ERROR_CODE__HTTP_401 = 3, + GH__ERROR_CODE__HTTP_404 = 4, + GH__ERROR_CODE__HTTP_429 = 5, + GH__ERROR_CODE__HTTP_503 = 6, + GH__ERROR_CODE__HTTP_OTHER = 7, + GH__ERROR_CODE__UNEXPECTED_CONTENT_TYPE = 8, + GH__ERROR_CODE__COULD_NOT_CREATE_TEMPFILE = 8, + GH__ERROR_CODE__COULD_NOT_INSTALL_LOOSE = 10, + GH__ERROR_CODE__COULD_NOT_INSTALL_PACKFILE = 11, + GH__ERROR_CODE__SUBPROCESS_SYNTAX = 12, + GH__ERROR_CODE__INDEX_PACK_FAILED = 13, + GH__ERROR_CODE__COULD_NOT_INSTALL_PREFETCH = 14, +}; + +enum gh__cache_server_mode { + /* verify URL. disable if unknown. */ + GH__CACHE_SERVER_MODE__VERIFY_DISABLE = 0, + /* verify URL. error if unknown. */ + GH__CACHE_SERVER_MODE__VERIFY_ERROR, + /* disable the cache-server, if defined */ + GH__CACHE_SERVER_MODE__DISABLE, + /* trust any cache-server */ + GH__CACHE_SERVER_MODE__TRUST_WITHOUT_VERIFY, +}; + +/* + * The set of command line, config, and environment variables + * that we use as input to decide how we should operate. + */ +static struct gh__cmd_opts { + const char *remote_name; + + int try_fallback; /* to git server if cache-server fails */ + int show_progress; + + int depth; + unsigned int block_size; + int max_retries; + int max_transient_backoff_sec; + + enum gh__cache_server_mode cache_server_mode; +} gh__cmd_opts; + +/* + * The chosen global state derrived from the inputs in gh__cmd_opts. + */ +static struct gh__global { + struct remote *remote; + + struct credential main_creds; + struct credential cache_creds; + + const char *main_url; + const char *cache_server_url; + + struct strbuf buf_odb_path; + + int http_is_initialized; + int cache_server_is_initialized; /* did sub-command look for one */ + int main_creds_need_approval; /* try to only approve them once */ + +} gh__global; + +enum gh__server_type { + GH__SERVER_TYPE__MAIN = 0, + GH__SERVER_TYPE__CACHE = 1, + + GH__SERVER_TYPE__NR, +}; + +static const char *gh__server_type_label[GH__SERVER_TYPE__NR] = { + "(main)", + "(cs)" +}; + +enum gh__objects_mode { + GH__OBJECTS_MODE__NONE = 0, + + /* + * Bulk fetch objects. + * + * But also, force the use of HTTP POST regardless of how many + * objects we are requesting. + * + * The GVFS Protocol treats requests for commit objects + * differently in GET and POST requests WRT whether it + * automatically also fetches the referenced trees. + */ + GH__OBJECTS_MODE__POST, + + /* + * Fetch objects one at a time using HTTP GET. + * + * Force the use of GET (primarily because of the commit + * object treatment). + */ + GH__OBJECTS_MODE__GET, + + /* + * Fetch one or more pre-computed "prefetch packs" containing + * commits and trees. + */ + GH__OBJECTS_MODE__PREFETCH, +}; + +struct gh__azure_throttle +{ + unsigned long tstu_limit; + unsigned long tstu_remaining; + + unsigned long reset_sec; + unsigned long retry_after_sec; +}; + +static void gh__azure_throttle__zero(struct gh__azure_throttle *azure) +{ + azure->tstu_limit = 0; + azure->tstu_remaining = 0; + azure->reset_sec = 0; + azure->retry_after_sec = 0; +} + +#define GH__AZURE_THROTTLE_INIT { \ + .tstu_limit = 0, \ + .tstu_remaining = 0, \ + .reset_sec = 0, \ + .retry_after_sec = 0, \ + } + +static struct gh__azure_throttle gh__global_throttle[GH__SERVER_TYPE__NR] = { + GH__AZURE_THROTTLE_INIT, + GH__AZURE_THROTTLE_INIT, +}; + +/* + * Stolen from http.c + */ +static CURLcode gh__curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf) +{ + char *ptr; + CURLcode ret; + + strbuf_reset(buf); + ret = curl_easy_getinfo(curl, info, &ptr); + if (!ret && ptr) + strbuf_addstr(buf, ptr); + return ret; +} + +enum gh__progress_state { + GH__PROGRESS_STATE__START = 0, + GH__PROGRESS_STATE__PHASE1, + GH__PROGRESS_STATE__PHASE2, + GH__PROGRESS_STATE__PHASE3, +}; + +/* + * Parameters to drive an HTTP request (with any necessary retries). + */ +struct gh__request_params { + /* + * b_is_post indicates if the current HTTP request is a POST=1 or + * a GET=0. This is a lower level field used to setup CURL and + * the tempfile used to receive the content. + * + * It is related to, but different from the GH__OBJECTS_MODE__ + * field that we present to the gvfs-helper client or in the CLI + * (which only concerns the semantics of the /gvfs/objects protocol + * on the set of requested OIDs). + * + * For example, we use an HTTP GET to get the /gvfs/config data + * into a buffer. + */ + int b_is_post; + int b_write_to_file; /* write to file=1 or strbuf=0 */ + int b_permit_cache_server_if_defined; + + enum gh__objects_mode objects_mode; + enum gh__server_type server_type; + + int k_attempt; /* robust retry attempt */ + int k_transient_delay_sec; /* delay before transient error retries */ + + unsigned long object_count; /* number of objects being fetched */ + + const struct strbuf *post_payload; /* POST body to send */ + + struct curl_slist *headers; /* additional http headers to send */ + struct tempfile *tempfile; /* for response content when file */ + struct strbuf *buffer; /* for response content when strbuf */ + struct strbuf tr2_label; /* for trace2 regions */ + + struct object_id loose_oid; + + /* + * Note that I am putting all of the progress-related instance data + * inside the request-params in the hope that we can eventually + * do multi-threaded/concurrent HTTP requests when chunking + * large requests. However, the underlying "struct progress" API + * is not thread safe (that is, it doesn't allow concurrent progress + * reports (since that might require multiple lines on the screen + * or something)). + */ + enum gh__progress_state progress_state; + struct strbuf progress_base_phase2_msg; + struct strbuf progress_base_phase3_msg; + + /* + * The buffer for the formatted progress message is shared by the + * "struct progress" API and must remain valid for the duration of + * the start_progress..stop_progress lifespan. + */ + struct strbuf progress_msg; + struct progress *progress; + + struct strbuf e2eid; + + struct string_list *result_list; /* we do not own this */ +}; + +#define GH__REQUEST_PARAMS_INIT { \ + .b_is_post = 0, \ + .b_write_to_file = 0, \ + .b_permit_cache_server_if_defined = 1, \ + .server_type = GH__SERVER_TYPE__MAIN, \ + .k_attempt = 0, \ + .k_transient_delay_sec = 0, \ + .object_count = 0, \ + .post_payload = NULL, \ + .headers = NULL, \ + .tempfile = NULL, \ + .buffer = NULL, \ + .tr2_label = STRBUF_INIT, \ + .loose_oid = {{0}}, \ + .progress_state = GH__PROGRESS_STATE__START, \ + .progress_base_phase2_msg = STRBUF_INIT, \ + .progress_base_phase3_msg = STRBUF_INIT, \ + .progress_msg = STRBUF_INIT, \ + .progress = NULL, \ + .e2eid = STRBUF_INIT, \ + .result_list = NULL, \ + } + +static void gh__request_params__release(struct gh__request_params *params) +{ + if (!params) + return; + + params->post_payload = NULL; /* we do not own this */ + + curl_slist_free_all(params->headers); + params->headers = NULL; + + delete_tempfile(¶ms->tempfile); + + params->buffer = NULL; /* we do not own this */ + + strbuf_release(¶ms->tr2_label); + + strbuf_release(¶ms->progress_base_phase2_msg); + strbuf_release(¶ms->progress_base_phase3_msg); + strbuf_release(¶ms->progress_msg); + + stop_progress(¶ms->progress); + params->progress = NULL; + + strbuf_release(¶ms->e2eid); + + params->result_list = NULL; /* we do not own this */ +} + +/* + * How we handle retries for various unexpected network errors. + */ +enum gh__retry_mode { + /* + * The operation was successful, so no retry is needed. + * Use this for HTTP 200, for example. + */ + GH__RETRY_MODE__SUCCESS = 0, + + /* + * Retry using the normal 401 Auth mechanism. + */ + GH__RETRY_MODE__HTTP_401, + + /* + * Fail because at least one of the requested OIDs does not exist. + */ + GH__RETRY_MODE__FAIL_404, + + /* + * A transient network error, such as dropped connection + * or network IO error. Our belief is that a retry MAY + * succeed. (See Gremlins and Cosmic Rays....) + */ + GH__RETRY_MODE__TRANSIENT, + + /* + * Request was blocked completely because of a 429. + */ + GH__RETRY_MODE__HTTP_429, + + /* + * Request failed because the server was (temporarily?) offline. + */ + GH__RETRY_MODE__HTTP_503, + + /* + * The operation had a hard failure and we have no + * expectation that a second attempt will give a different + * answer, such as a bad hostname or a mal-formed URL. + */ + GH__RETRY_MODE__HARD_FAIL, +}; + +/* + * Bucket to describe the results of an HTTP requests (may be + * overwritten during retries so that it describes the final attempt). + */ +struct gh__response_status { + struct strbuf error_message; + struct strbuf content_type; + enum gh__error_code ec; + enum gh__retry_mode retry; + intmax_t bytes_received; + struct gh__azure_throttle *azure; +}; + +#define GH__RESPONSE_STATUS_INIT { \ + .error_message = STRBUF_INIT, \ + .content_type = STRBUF_INIT, \ + .ec = GH__ERROR_CODE__OK, \ + .retry = GH__RETRY_MODE__SUCCESS, \ + .bytes_received = 0, \ + .azure = NULL, \ + } + +static void gh__response_status__zero(struct gh__response_status *s) +{ + strbuf_setlen(&s->error_message, 0); + strbuf_setlen(&s->content_type, 0); + s->ec = GH__ERROR_CODE__OK; + s->retry = GH__RETRY_MODE__SUCCESS; + s->bytes_received = 0; + s->azure = NULL; +} + +static void install_result(struct gh__request_params *params, + struct gh__response_status *status); + +/* + * Log the E2EID for the current request. + * + * Since every HTTP request to the cache-server and to the main Git server + * will send back a unique E2EID (probably a GUID), we don't want to overload + * telemetry with each ID -- rather, only the ones for which there was a + * problem and that may be helpful in a post mortem. + */ +static void log_e2eid(struct gh__request_params *params, + struct gh__response_status *status) +{ + if (!params->e2eid.len) + return; + + switch (status->retry) { + default: + case GH__RETRY_MODE__SUCCESS: + case GH__RETRY_MODE__HTTP_401: + case GH__RETRY_MODE__FAIL_404: + return; + + case GH__RETRY_MODE__HARD_FAIL: + case GH__RETRY_MODE__TRANSIENT: + case GH__RETRY_MODE__HTTP_429: + case GH__RETRY_MODE__HTTP_503: + break; + } + + if (trace2_is_enabled()) { + struct strbuf key = STRBUF_INIT; + + strbuf_addstr(&key, "e2eid"); + strbuf_addstr(&key, gh__server_type_label[params->server_type]); + + trace2_data_string(TR2_CAT, NULL, key.buf, + params->e2eid.buf); + + strbuf_release(&key); + } +} + +/* + * Normalize a few HTTP response codes before we try to decide + * how to dispatch on them. + */ +static long gh__normalize_odd_codes(struct gh__request_params *params, + long http_response_code) +{ + if (params->server_type == GH__SERVER_TYPE__CACHE && + http_response_code == 400) { + /* + * The cache-server sends a somewhat bogus 400 instead of + * the normal 401 when AUTH is required. Fixup the status + * to hide that. + * + * TODO Technically, the cache-server could send a 400 + * TODO for many reasons, not just for their bogus + * TODO pseudo-401, but we're going to assume it is a + * TODO 401 for now. We should confirm the expected + * TODO error message in the response-body. + */ + return 401; + } + + if (http_response_code == 203) { + /* + * A proxy server transformed a 200 from the origin server + * into a 203. We don't care about the subtle distinction. + */ + return 200; + } + + return http_response_code; +} + +/* + * Map HTTP response codes into a retry strategy. + * See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + * + * https://docs.microsoft.com/en-us/azure/devops/integrate/concepts/rate-limits?view=azure-devops + */ +static void compute_retry_mode_from_http_response( + struct gh__response_status *status, + long http_response_code) +{ + switch (http_response_code) { + + case 200: + status->retry = GH__RETRY_MODE__SUCCESS; + status->ec = GH__ERROR_CODE__OK; + return; + + case 301: /* all the various flavors of HTTP Redirect */ + case 302: + case 303: + case 304: + case 305: + case 306: + case 307: + case 308: + /* + * TODO Consider a redirected-retry (with or without + * TODO a Retry-After header). + */ + goto hard_fail; + + case 401: + strbuf_addstr(&status->error_message, + "(http:401) Not Authorized"); + status->retry = GH__RETRY_MODE__HTTP_401; + status->ec = GH__ERROR_CODE__HTTP_401; + return; + + case 404: + /* + * TODO if params->object_count > 1, consider + * TODO splitting the request into 2 halves + * TODO and retrying each half in series. + */ + strbuf_addstr(&status->error_message, + "(http:404) Not Found"); + status->retry = GH__RETRY_MODE__FAIL_404; + status->ec = GH__ERROR_CODE__HTTP_404; + return; + + case 429: + /* + * This is a hard block because we've been bad. + */ + strbuf_addstr(&status->error_message, + "(http:429) Too Many Requests [throttled]"); + status->retry = GH__RETRY_MODE__HTTP_429; + status->ec = GH__ERROR_CODE__HTTP_429; + + trace2_data_string(TR2_CAT, NULL, "error/http", + status->error_message.buf); + return; + + case 503: + /* + * We assume that this comes with a "Retry-After" header like 429s. + */ + strbuf_addstr(&status->error_message, + "(http:503) Server Unavailable [throttled]"); + status->retry = GH__RETRY_MODE__HTTP_503; + status->ec = GH__ERROR_CODE__HTTP_503; + + trace2_data_string(TR2_CAT, NULL, "error/http", + status->error_message.buf); + return; + + default: + goto hard_fail; + } + +hard_fail: + strbuf_addf(&status->error_message, "(http:%d) Other [hard_fail]", + (int)http_response_code); + status->retry = GH__RETRY_MODE__HARD_FAIL; + status->ec = GH__ERROR_CODE__HTTP_OTHER; + + trace2_data_string(TR2_CAT, NULL, "error/http", + status->error_message.buf); + return; +} + +/* + * Map CURLE errors code to a retry strategy. + * See and + * https://curl.haxx.se/libcurl/c/libcurl-errors.html + * + * This could be a static table rather than a switch, but + * that is harder to debug and we may want to selectively + * log errors. + * + * I've commented out all of the hard-fail cases for now + * and let the default handle them. This is to indicate + * that I considered them and found them to be not actionable. + * Also, the spelling of some of the CURLE_ symbols seem + * to change between curl releases on different platforms, + * so I'm not going to fight that. + */ +static void compute_retry_mode_from_curl_error( + struct gh__response_status *status, + CURLcode curl_code) +{ + switch (curl_code) { + case CURLE_OK: + status->retry = GH__RETRY_MODE__SUCCESS; + status->ec = GH__ERROR_CODE__OK; + return; + + //se CURLE_UNSUPPORTED_PROTOCOL: goto hard_fail; + //se CURLE_FAILED_INIT: goto hard_fail; + //se CURLE_URL_MALFORMAT: goto hard_fail; + //se CURLE_NOT_BUILT_IN: goto hard_fail; + //se CURLE_COULDNT_RESOLVE_PROXY: goto hard_fail; + //se CURLE_COULDNT_RESOLVE_HOST: goto hard_fail; + case CURLE_COULDNT_CONNECT: goto transient; + //se CURLE_WEIRD_SERVER_REPLY: goto hard_fail; + //se CURLE_REMOTE_ACCESS_DENIED: goto hard_fail; + //se CURLE_FTP_ACCEPT_FAILED: goto hard_fail; + //se CURLE_FTP_WEIRD_PASS_REPLY: goto hard_fail; + //se CURLE_FTP_ACCEPT_TIMEOUT: goto hard_fail; + //se CURLE_FTP_WEIRD_PASV_REPLY: goto hard_fail; + //se CURLE_FTP_WEIRD_227_FORMAT: goto hard_fail; + //se CURLE_FTP_CANT_GET_HOST: goto hard_fail; + case CURLE_HTTP2: goto transient; + //se CURLE_FTP_COULDNT_SET_TYPE: goto hard_fail; + case CURLE_PARTIAL_FILE: goto transient; + //se CURLE_FTP_COULDNT_RETR_FILE: goto hard_fail; + //se CURLE_OBSOLETE20: goto hard_fail; + //se CURLE_QUOTE_ERROR: goto hard_fail; + //se CURLE_HTTP_RETURNED_ERROR: goto hard_fail; + case CURLE_WRITE_ERROR: goto transient; + //se CURLE_OBSOLETE24: goto hard_fail; + case CURLE_UPLOAD_FAILED: goto transient; + //se CURLE_READ_ERROR: goto hard_fail; + //se CURLE_OUT_OF_MEMORY: goto hard_fail; + case CURLE_OPERATION_TIMEDOUT: goto transient; + //se CURLE_OBSOLETE29: goto hard_fail; + //se CURLE_FTP_PORT_FAILED: goto hard_fail; + //se CURLE_FTP_COULDNT_USE_REST: goto hard_fail; + //se CURLE_OBSOLETE32: goto hard_fail; + //se CURLE_RANGE_ERROR: goto hard_fail; + case CURLE_HTTP_POST_ERROR: goto transient; + //se CURLE_SSL_CONNECT_ERROR: goto hard_fail; + //se CURLE_BAD_DOWNLOAD_RESUME: goto hard_fail; + //se CURLE_FILE_COULDNT_READ_FILE: goto hard_fail; + //se CURLE_LDAP_CANNOT_BIND: goto hard_fail; + //se CURLE_LDAP_SEARCH_FAILED: goto hard_fail; + //se CURLE_OBSOLETE40: goto hard_fail; + //se CURLE_FUNCTION_NOT_FOUND: goto hard_fail; + //se CURLE_ABORTED_BY_CALLBACK: goto hard_fail; + //se CURLE_BAD_FUNCTION_ARGUMENT: goto hard_fail; + //se CURLE_OBSOLETE44: goto hard_fail; + //se CURLE_INTERFACE_FAILED: goto hard_fail; + //se CURLE_OBSOLETE46: goto hard_fail; + //se CURLE_TOO_MANY_REDIRECTS: goto hard_fail; + //se CURLE_UNKNOWN_OPTION: goto hard_fail; + //se CURLE_TELNET_OPTION_SYNTAX: goto hard_fail; + //se CURLE_OBSOLETE50: goto hard_fail; + //se CURLE_PEER_FAILED_VERIFICATION: goto hard_fail; + //se CURLE_GOT_NOTHING: goto hard_fail; + //se CURLE_SSL_ENGINE_NOTFOUND: goto hard_fail; + //se CURLE_SSL_ENGINE_SETFAILED: goto hard_fail; + case CURLE_SEND_ERROR: goto transient; + case CURLE_RECV_ERROR: goto transient; + //se CURLE_OBSOLETE57: goto hard_fail; + //se CURLE_SSL_CERTPROBLEM: goto hard_fail; + //se CURLE_SSL_CIPHER: goto hard_fail; + //se CURLE_SSL_CACERT: goto hard_fail; + //se CURLE_BAD_CONTENT_ENCODING: goto hard_fail; + //se CURLE_LDAP_INVALID_URL: goto hard_fail; + //se CURLE_FILESIZE_EXCEEDED: goto hard_fail; + //se CURLE_USE_SSL_FAILED: goto hard_fail; + //se CURLE_SEND_FAIL_REWIND: goto hard_fail; + //se CURLE_SSL_ENGINE_INITFAILED: goto hard_fail; + //se CURLE_LOGIN_DENIED: goto hard_fail; + //se CURLE_TFTP_NOTFOUND: goto hard_fail; + //se CURLE_TFTP_PERM: goto hard_fail; + //se CURLE_REMOTE_DISK_FULL: goto hard_fail; + //se CURLE_TFTP_ILLEGAL: goto hard_fail; + //se CURLE_TFTP_UNKNOWNID: goto hard_fail; + //se CURLE_REMOTE_FILE_EXISTS: goto hard_fail; + //se CURLE_TFTP_NOSUCHUSER: goto hard_fail; + //se CURLE_CONV_FAILED: goto hard_fail; + //se CURLE_CONV_REQD: goto hard_fail; + //se CURLE_SSL_CACERT_BADFILE: goto hard_fail; + //se CURLE_REMOTE_FILE_NOT_FOUND: goto hard_fail; + //se CURLE_SSH: goto hard_fail; + //se CURLE_SSL_SHUTDOWN_FAILED: goto hard_fail; + case CURLE_AGAIN: goto transient; + //se CURLE_SSL_CRL_BADFILE: goto hard_fail; + //se CURLE_SSL_ISSUER_ERROR: goto hard_fail; + //se CURLE_FTP_PRET_FAILED: goto hard_fail; + //se CURLE_RTSP_CSEQ_ERROR: goto hard_fail; + //se CURLE_RTSP_SESSION_ERROR: goto hard_fail; + //se CURLE_FTP_BAD_FILE_LIST: goto hard_fail; + //se CURLE_CHUNK_FAILED: goto hard_fail; + //se CURLE_NO_CONNECTION_AVAILABLE: goto hard_fail; + //se CURLE_SSL_PINNEDPUBKEYNOTMATCH: goto hard_fail; + //se CURLE_SSL_INVALIDCERTSTATUS: goto hard_fail; +#ifdef CURLE_HTTP2_STREAM + case CURLE_HTTP2_STREAM: goto transient; +#endif + default: goto hard_fail; + } + +hard_fail: + strbuf_addf(&status->error_message, "(curl:%d) %s [hard_fail]", + curl_code, curl_easy_strerror(curl_code)); + status->retry = GH__RETRY_MODE__HARD_FAIL; + status->ec = GH__ERROR_CODE__CURL_ERROR; + + trace2_data_string(TR2_CAT, NULL, "error/curl", + status->error_message.buf); + return; + +transient: + strbuf_addf(&status->error_message, "(curl:%d) %s [transient]", + curl_code, curl_easy_strerror(curl_code)); + status->retry = GH__RETRY_MODE__TRANSIENT; + status->ec = GH__ERROR_CODE__CURL_ERROR; + + trace2_data_string(TR2_CAT, NULL, "error/curl", + status->error_message.buf); + return; +} + +/* + * Create a single normalized 'ec' error-code from the status we + * received from the HTTP request. Map a few of the expected HTTP + * status code to 'ec', but don't get too crazy here. + */ +static void gh__response_status__set_from_slot( + struct gh__request_params *params, + struct gh__response_status *status, + const struct active_request_slot *slot) +{ + long http_response_code; + CURLcode curl_code; + + curl_code = slot->results->curl_result; + gh__curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE, + &status->content_type); + curl_easy_getinfo(slot->curl, CURLINFO_RESPONSE_CODE, + &http_response_code); + + strbuf_setlen(&status->error_message, 0); + + http_response_code = gh__normalize_odd_codes(params, + http_response_code); + + /* + * Use normalized response/status codes form curl/http to decide + * how to set the error-code we propagate *AND* to decide if we + * we should retry because of transient network problems. + */ + if (curl_code == CURLE_OK || + curl_code == CURLE_HTTP_RETURNED_ERROR) + compute_retry_mode_from_http_response(status, + http_response_code); + else + compute_retry_mode_from_curl_error(status, curl_code); + + if (status->ec != GH__ERROR_CODE__OK) + status->bytes_received = 0; + else if (params->b_write_to_file) + status->bytes_received = (intmax_t)ftell(params->tempfile->fp); + else + status->bytes_received = (intmax_t)params->buffer->len; +} + +static void gh__response_status__release(struct gh__response_status *status) +{ + if (!status) + return; + strbuf_release(&status->error_message); + strbuf_release(&status->content_type); +} + +static int gh__curl_progress_cb(void *clientp, + curl_off_t dltotal, curl_off_t dlnow, + curl_off_t ultotal, curl_off_t ulnow) +{ + struct gh__request_params *params = clientp; + + /* + * From what I can tell, CURL progress arrives in 3 phases. + * + * [1] An initial connection setup phase where we get [0,0] [0,0]. + * [2] An upload phase where we start sending the request headers + * and body. ulnow will be > 0. ultotal may or may not be 0. + * [3] A download phase where we start receiving the response + * headers and payload body. dlnow will be > 0. dltotal may + * or may not be 0. + * + * If we pass zero for the total to the "struct progress" API, we + * get simple numbers rather than percentages. So our progress + * output format may vary depending. + * + * It is unclear if CURL will give us a final callback after + * everything is finished, so we leave the progress handle open + * and let the caller issue the final stop_progress(). + * + * There is a bit of a mismatch between the CURL API and the + * "struct progress" API. The latter requires us to set the + * progress message when we call one of the start_progress + * methods. We cannot change the progress message while we are + * showing progress state. And we cannot change the denominator + * (total) after we start. CURL may or may not give us the total + * sizes for each phase. + * + * Also be advised that the "struct progress" API eats messages + * so that the screen is only updated every second or so. And + * may not print anything if the start..stop happen in less then + * 2 seconds. Whereas CURL calls this callback very frequently. + * The net-net is that we may not actually see this progress + * message for small/fast HTTP requests. + */ + + switch (params->progress_state) { + case GH__PROGRESS_STATE__START: /* first callback */ + if (dlnow == 0 && ulnow == 0) + goto enter_phase_1; + + if (ulnow) + goto enter_phase_2; + else + goto enter_phase_3; + + case GH__PROGRESS_STATE__PHASE1: + if (dlnow == 0 && ulnow == 0) + return 0; + + if (ulnow) + goto enter_phase_2; + else + goto enter_phase_3; + + case GH__PROGRESS_STATE__PHASE2: + display_progress(params->progress, ulnow); + if (dlnow == 0) + return 0; + + stop_progress(¶ms->progress); + goto enter_phase_3; + + case GH__PROGRESS_STATE__PHASE3: + display_progress(params->progress, dlnow); + return 0; + + default: + return 0; + } + +enter_phase_1: + /* + * Don't bother to create a progress handle during phase [1]. + * Because we get [0,0,0,0], we don't have any data to report + * and would just have to synthesize some type of progress. + * From my testing, phase [1] is fairly quick (probably just + * the SSL handshake), so the "struct progress" API will most + * likely completely eat any messages that we did produce. + */ + params->progress_state = GH__PROGRESS_STATE__PHASE1; + return 0; + +enter_phase_2: + strbuf_setlen(¶ms->progress_msg, 0); + if (params->progress_base_phase2_msg.len) { + if (params->k_attempt > 0) + strbuf_addf(¶ms->progress_msg, "%s [retry %d/%d] (bytes sent)", + params->progress_base_phase2_msg.buf, + params->k_attempt, gh__cmd_opts.max_retries); + else + strbuf_addf(¶ms->progress_msg, "%s (bytes sent)", + params->progress_base_phase2_msg.buf); + params->progress = start_progress(the_repository, params->progress_msg.buf, ultotal); + display_progress(params->progress, ulnow); + } + params->progress_state = GH__PROGRESS_STATE__PHASE2; + return 0; + +enter_phase_3: + strbuf_setlen(¶ms->progress_msg, 0); + if (params->progress_base_phase3_msg.len) { + if (params->k_attempt > 0) + strbuf_addf(¶ms->progress_msg, "%s [retry %d/%d] (bytes received)", + params->progress_base_phase3_msg.buf, + params->k_attempt, gh__cmd_opts.max_retries); + else + strbuf_addf(¶ms->progress_msg, "%s (bytes received)", + params->progress_base_phase3_msg.buf); + params->progress = start_progress(the_repository, params->progress_msg.buf, dltotal); + display_progress(params->progress, dlnow); + } + params->progress_state = GH__PROGRESS_STATE__PHASE3; + return 0; +} + +/* + * Run the request without using "run_one_slot()" because we + * don't want the post-request normalization, error handling, + * and auto-reauth handling in http.c. + */ +static void gh__run_one_slot(struct active_request_slot *slot, + struct gh__request_params *params, + struct gh__response_status *status) +{ + struct strbuf key = STRBUF_INIT; + + strbuf_addbuf(&key, ¶ms->tr2_label); + strbuf_addstr(&key, gh__server_type_label[params->server_type]); + + params->progress_state = GH__PROGRESS_STATE__START; + strbuf_setlen(¶ms->e2eid, 0); + + trace2_region_enter(TR2_CAT, key.buf, NULL); + + if (!start_active_slot(slot)) { + compute_retry_mode_from_curl_error(status, + CURLE_FAILED_INIT); + } else { + run_active_slot(slot); + if (params->b_write_to_file) + fflush(params->tempfile->fp); + + gh__response_status__set_from_slot(params, status, slot); + + log_e2eid(params, status); + + if (status->ec == GH__ERROR_CODE__OK) { + int old_len = key.len; + + /* + * We only log the number of bytes received. + * We do not log the number of objects requested + * because the server may give us more than that + * (such as when we request a commit). + */ + strbuf_addstr(&key, "/nr_bytes"); + trace2_data_intmax(TR2_CAT, NULL, + key.buf, + status->bytes_received); + strbuf_setlen(&key, old_len); + } + } + + if (params->progress) + stop_progress(¶ms->progress); + + if (status->ec == GH__ERROR_CODE__OK && params->b_write_to_file) + install_result(params, status); + + trace2_region_leave(TR2_CAT, key.buf, NULL); + + strbuf_release(&key); +} + +static int option_parse_cache_server_mode(const struct option *opt, + const char *arg, int unset) +{ + if (unset) /* should not happen */ + return error(_("missing value for switch '%s'"), + opt->long_name); + + else if (!strcmp(arg, "verify")) + gh__cmd_opts.cache_server_mode = + GH__CACHE_SERVER_MODE__VERIFY_DISABLE; + + else if (!strcmp(arg, "error")) + gh__cmd_opts.cache_server_mode = + GH__CACHE_SERVER_MODE__VERIFY_ERROR; + + else if (!strcmp(arg, "disable")) + gh__cmd_opts.cache_server_mode = + GH__CACHE_SERVER_MODE__DISABLE; + + else if (!strcmp(arg, "trust")) + gh__cmd_opts.cache_server_mode = + GH__CACHE_SERVER_MODE__TRUST_WITHOUT_VERIFY; + + else + return error(_("invalid value for switch '%s'"), + opt->long_name); + + return 0; +} + +/* + * Let command line args override "gvfs.sharedcache" config setting + * and override the value set by git_default_config(). + * + * The command line is parsed *AFTER* the config is loaded, so + * prepared_alt_odb() has already been called any default or inherited + * shared-cache has already been set. + * + * We have a chance to override it here. + */ +static int option_parse_shared_cache_directory(const struct option *opt, + const char *arg, int unset) +{ + struct strbuf buf_arg = STRBUF_INIT; + + if (unset) /* should not happen */ + return error(_("missing value for switch '%s'"), + opt->long_name); + + strbuf_addstr(&buf_arg, arg); + if (strbuf_normalize_path(&buf_arg) < 0) { + /* + * Pretend command line wasn't given. Use whatever + * settings we already have from the config. + */ + strbuf_release(&buf_arg); + return 0; + } + strbuf_trim_trailing_dir_sep(&buf_arg); + + if (!strbuf_cmp(&buf_arg, &gvfs_shared_cache_pathname)) { + /* + * The command line argument matches what we got from + * the config, so we're already setup correctly. (And + * we have already verified that the directory exists + * on disk.) + */ + strbuf_release(&buf_arg); + return 0; + } + + else if (!gvfs_shared_cache_pathname.len) { + /* + * A shared-cache was requested and we did not inherit one. + * Try it, but let alt_odb_usable() secretly disable it if + * it cannot create the directory on disk. + */ + strbuf_addbuf(&gvfs_shared_cache_pathname, &buf_arg); + + add_to_alternates_memory(buf_arg.buf); + + strbuf_release(&buf_arg); + return 0; + } + + else { + /* + * The requested shared-cache is different from the one + * we inherited. Replace the inherited value with this + * one, but smartly fallback if necessary. + */ + struct strbuf buf_prev = STRBUF_INIT; + + strbuf_addbuf(&buf_prev, &gvfs_shared_cache_pathname); + + strbuf_setlen(&gvfs_shared_cache_pathname, 0); + strbuf_addbuf(&gvfs_shared_cache_pathname, &buf_arg); + + add_to_alternates_memory(buf_arg.buf); + + /* + * alt_odb_usable() releases gvfs_shared_cache_pathname + * if it cannot create the directory on disk, so fallback + * to the previous choice when it fails. + */ + if (!gvfs_shared_cache_pathname.len) + strbuf_addbuf(&gvfs_shared_cache_pathname, + &buf_prev); + + strbuf_release(&buf_arg); + strbuf_release(&buf_prev); + return 0; + } +} + +/* + * Lookup the URL for this remote (defaults to 'origin'). + */ +static void lookup_main_url(void) +{ + /* + * Both VFS and Scalar only work with 'origin', so we expect this. + * The command line arg is mainly for debugging. + */ + if (!gh__cmd_opts.remote_name || !*gh__cmd_opts.remote_name) + gh__cmd_opts.remote_name = "origin"; + + gh__global.remote = remote_get(gh__cmd_opts.remote_name); + if (!gh__global.remote->url.v[0] || !*gh__global.remote->url.v[0]) + die("unknown remote '%s'", gh__cmd_opts.remote_name); + + /* + * Strip out any in-line auth in the origin server URL so that + * we can control which creds we fetch. + * + * Azure DevOps has been known to suggest https URLS of the + * form "https://@dev.azure.com//". + * + * Break that so that we can force the use of a PAT. + */ + gh__global.main_url = transport_anonymize_url(gh__global.remote->url.v[0]); + + trace2_data_string(TR2_CAT, NULL, "remote/url", gh__global.main_url); +} + +static void do__http_get__gvfs_config(struct gh__response_status *status, + struct strbuf *config_data); + +/* + * Find the URL of the cache-server, if we have one. + * + * This routine is called by the initialization code and is allowed + * to call die() rather than returning an 'ec'. + */ +static void select_cache_server(void) +{ + struct gh__response_status status = GH__RESPONSE_STATUS_INIT; + struct strbuf config_data = STRBUF_INIT; + const char *match = NULL; + + /* + * This only indicates that the sub-command actually called + * this routine. We rely on gh__global.cache_server_url to tell + * us if we actually have a cache-server configured. + */ + gh__global.cache_server_is_initialized = 1; + gh__global.cache_server_url = NULL; + + if (gh__cmd_opts.cache_server_mode == GH__CACHE_SERVER_MODE__DISABLE) { + trace2_data_string(TR2_CAT, NULL, "cache/url", "disabled"); + return; + } + + if (!gvfs_cache_server_url || !*gvfs_cache_server_url) { + switch (gh__cmd_opts.cache_server_mode) { + default: + case GH__CACHE_SERVER_MODE__TRUST_WITHOUT_VERIFY: + case GH__CACHE_SERVER_MODE__VERIFY_DISABLE: + trace2_data_string(TR2_CAT, NULL, "cache/url", "unset"); + return; + + case GH__CACHE_SERVER_MODE__VERIFY_ERROR: + die("cache-server not set"); + } + } + + /* + * If the cache-server and main Git server have the same URL, we + * can silently disable the cache-server (by NOT setting the field + * in gh__global and explicitly disable the fallback logic.) + */ + if (!strcmp(gvfs_cache_server_url, gh__global.main_url)) { + gh__cmd_opts.try_fallback = 0; + trace2_data_string(TR2_CAT, NULL, "cache/url", "same"); + return; + } + + if (gh__cmd_opts.cache_server_mode == + GH__CACHE_SERVER_MODE__TRUST_WITHOUT_VERIFY) { + gh__global.cache_server_url = gvfs_cache_server_url; + trace2_data_string(TR2_CAT, NULL, "cache/url", + gvfs_cache_server_url); + return; + } + + /* + * GVFS cache-servers use the main Git server's creds rather + * than having their own creds. This feels like a security + * hole. For example, if the cache-server URL is pointed to a + * bad site, we'll happily send them our creds to the main Git + * server with each request to the cache-server. This would + * allow an attacker to later use our creds to impersonate us + * on the main Git server. + * + * So we optionally verify that the URL to the cache-server is + * well-known by the main Git server. + */ + + do__http_get__gvfs_config(&status, &config_data); + + if (status.ec == GH__ERROR_CODE__OK) { + /* + * The gvfs/config response is in JSON, but I don't think + * we need to parse it and all that. Lets just do a simple + * strstr() and assume it is sufficient. + * + * We do add some context to the pattern to guard against + * some attacks. + */ + struct strbuf pattern = STRBUF_INIT; + + strbuf_addf(&pattern, "\"Url\":\"%s\"", gvfs_cache_server_url); + match = strstr(config_data.buf, pattern.buf); + + strbuf_release(&pattern); + } + + strbuf_release(&config_data); + + if (match) { + gh__global.cache_server_url = gvfs_cache_server_url; + trace2_data_string(TR2_CAT, NULL, "cache/url", + gvfs_cache_server_url); + } + + else if (gh__cmd_opts.cache_server_mode == + GH__CACHE_SERVER_MODE__VERIFY_ERROR) { + if (status.ec != GH__ERROR_CODE__OK) + die("could not verify cache-server '%s': %s", + gvfs_cache_server_url, + status.error_message.buf); + else + die("could not verify cache-server '%s'", + gvfs_cache_server_url); + } + + else if (gh__cmd_opts.cache_server_mode == + GH__CACHE_SERVER_MODE__VERIFY_DISABLE) { + if (status.ec != GH__ERROR_CODE__OK) + warning("could not verify cache-server '%s': %s", + gvfs_cache_server_url, + status.error_message.buf); + else + warning("could not verify cache-server '%s'", + gvfs_cache_server_url); + trace2_data_string(TR2_CAT, NULL, "cache/url", + "disabled"); + } + + gh__response_status__release(&status); +} + +/* + * Read stdin until EOF (or a blank line) and add the desired OIDs + * to the oidset. + * + * Stdin should contain a list of OIDs. Lines may have additional + * text following the OID that we ignore. + */ +static unsigned long read_stdin_for_oids(struct oidset *oids) +{ + struct object_id oid; + struct strbuf buf_stdin = STRBUF_INIT; + unsigned long count = 0; + + do { + if (strbuf_getline(&buf_stdin, stdin) == EOF || !buf_stdin.len) + break; + + if (get_oid_hex(buf_stdin.buf, &oid)) + continue; /* just silently eat it */ + + if (!oidset_insert(oids, &oid)) + count++; + } while (1); + + strbuf_release(&buf_stdin); + return count; +} + +/* + * Build a complete JSON payload for a gvfs/objects POST request + * containing the first `nr_in_block` OIDs found in the OIDSET + * indexed by the given iterator. + * + * https://github.com/microsoft/VFSForGit/blob/master/Protocol.md + * + * Return the number of OIDs we actually put into the payload. + * If only 1 OID was found, also return it. + */ +static unsigned long build_json_payload__gvfs_objects( + struct json_writer *jw_req, + struct oidset_iter *iter, + unsigned long nr_in_block, + struct object_id *oid_out) +{ + unsigned long k; + const struct object_id *oid; + const struct object_id *oid_prev = NULL; + + k = 0; + + jw_init(jw_req); + jw_object_begin(jw_req, 0); + jw_object_intmax(jw_req, "commitDepth", gh__cmd_opts.depth); + jw_object_inline_begin_array(jw_req, "objectIds"); + while (k < nr_in_block && (oid = oidset_iter_next(iter))) { + jw_array_string(jw_req, oid_to_hex(oid)); + k++; + oid_prev = oid; + } + jw_end(jw_req); + jw_end(jw_req); + + if (oid_out) { + if (k == 1) + oidcpy(oid_out, oid_prev); + else + oidclr(oid_out, the_repository->hash_algo); + } + + return k; +} + +/* + * Lookup the creds for the main/origin Git server. + */ +static void lookup_main_creds(void) +{ + if (gh__global.main_creds.username && *gh__global.main_creds.username) + return; + + credential_from_url(&gh__global.main_creds, gh__global.main_url); + credential_fill(the_repository, &gh__global.main_creds, 0); + gh__global.main_creds_need_approval = 1; +} + +/* + * If we have a set of creds for the main Git server, tell the credential + * manager to throw them away and ask it to reacquire them. + */ +static void refresh_main_creds(void) +{ + if (gh__global.main_creds.username && *gh__global.main_creds.username) + credential_reject(the_repository, &gh__global.main_creds); + + lookup_main_creds(); + + // TODO should we compare before and after values of u/p and + // TODO shortcut reauth if we already know it will fail? + // TODO if so, return a bool if same/different. +} + +static void approve_main_creds(void) +{ + if (!gh__global.main_creds_need_approval) + return; + + credential_approve(the_repository, &gh__global.main_creds); + gh__global.main_creds_need_approval = 0; +} + +/* + * Build a set of creds for the cache-server based upon the main Git + * server (assuming we have a cache-server configured). + * + * That is, we NEVER fill them directly for the cache-server -- we + * only synthesize them from the filled main creds. + */ +static void synthesize_cache_server_creds(void) +{ + if (!gh__global.cache_server_is_initialized) + BUG("sub-command did not initialize cache-server vars"); + + if (!gh__global.cache_server_url) + return; + + if (gh__global.cache_creds.username && *gh__global.cache_creds.username) + return; + + /* + * Get the main Git server creds so we can borrow the username + * and password when we talk to the cache-server. + */ + lookup_main_creds(); + free(gh__global.cache_creds.username); + gh__global.cache_creds.username = xstrdup(gh__global.main_creds.username); + free(gh__global.cache_creds.password); + gh__global.cache_creds.password = xstrdup(gh__global.main_creds.password); +} + +/* + * Flush and refresh the cache-server creds. Because the cache-server + * does not do 401s (or manage creds), we have to reload the main Git + * server creds first. + * + * That is, we NEVER reject them directly because we never filled them. + */ +static void refresh_cache_server_creds(void) +{ + credential_clear(&gh__global.cache_creds); + + refresh_main_creds(); + synthesize_cache_server_creds(); +} + +/* + * We NEVER approve cache-server creds directly because we never directly + * filled them. However, we should be able to infer that the main ones + * are valid and can approve them if necessary. + */ +static void approve_cache_server_creds(void) +{ + approve_main_creds(); +} + +/* + * Get the pathname to the ODB where we write objects that we download. + */ +static void select_odb(void) +{ + prepare_alt_odb(the_repository); + + strbuf_init(&gh__global.buf_odb_path, 0); + + if (gvfs_shared_cache_pathname.len) + strbuf_addbuf(&gh__global.buf_odb_path, + &gvfs_shared_cache_pathname); + else + strbuf_addstr(&gh__global.buf_odb_path, + the_repository->objects->odb->path); +} + +/* + * Create a unique tempfile or tempfile-pair inside the + * tempPacks directory. + */ +static void my_create_tempfile( + struct gh__response_status *status, + int b_fdopen, + const char *suffix1, struct tempfile **t1, + const char *suffix2, struct tempfile **t2) +{ + static unsigned int nth = 0; + static struct timeval tv = {0}; + static struct tm tm = {0}; + static time_t secs = 0; + static char date[32] = {0}; + + struct strbuf basename = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; + int len_tp; + enum scld_error scld; + int retries; + + gh__response_status__zero(status); + + if (!nth) { + /* + * Create a unique string to use in the name of all + * tempfiles created by this process. + */ + gettimeofday(&tv, NULL); + secs = tv.tv_sec; + gmtime_r(&secs, &tm); + + xsnprintf(date, sizeof(date), "%4d%02d%02d-%02d%02d%02d-%06ld", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + (long)tv.tv_usec); + } + + /* + * Create a for this instance/pair using a series + * number . + */ + strbuf_addf(&basename, "t-%s-%04d", date, nth++); + + if (!suffix1 || !*suffix1) + suffix1 = "temp"; + + /* + * Create full pathname as: + * + * "/pack/tempPacks/." + */ + strbuf_setlen(&buf, 0); + strbuf_addbuf(&buf, &gh__global.buf_odb_path); + strbuf_complete(&buf, '/'); + strbuf_addstr(&buf, "pack/tempPacks/"); + len_tp = buf.len; + strbuf_addf( &buf, "%s.%s", basename.buf, suffix1); + + scld = safe_create_leading_directories(the_repository, buf.buf); + if (scld != SCLD_OK && scld != SCLD_EXISTS) { + strbuf_addf(&status->error_message, + "could not create directory for tempfile: '%s'", + buf.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_CREATE_TEMPFILE; + goto cleanup; + } + + retries = 0; + *t1 = create_tempfile(buf.buf); + while (!*t1 && retries < 5) { + retries++; + strbuf_setlen(&buf, len_tp); + strbuf_addf(&buf, "%s-%d.%s", basename.buf, retries, suffix1); + *t1 = create_tempfile(buf.buf); + } + + if (!*t1) { + strbuf_addf(&status->error_message, + "could not create tempfile: '%s'", + buf.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_CREATE_TEMPFILE; + goto cleanup; + } + if (b_fdopen) + fdopen_tempfile(*t1, "w"); + + /* + * Optionally create a peer tempfile with the same basename. + * (This is useful for prefetching .pack and .idx pairs.) + * + * "/pack/tempPacks/." + */ + if (suffix2 && *suffix2 && t2) { + strbuf_setlen(&buf, len_tp); + strbuf_addf( &buf, "%s.%s", basename.buf, suffix2); + + *t2 = create_tempfile(buf.buf); + while (!*t2 && retries < 5) { + retries++; + strbuf_setlen(&buf, len_tp); + strbuf_addf(&buf, "%s-%d.%s", basename.buf, retries, suffix2); + *t2 = create_tempfile(buf.buf); + } + + if (!*t2) { + strbuf_addf(&status->error_message, + "could not create tempfile: '%s'", + buf.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_CREATE_TEMPFILE; + goto cleanup; + } + if (b_fdopen) + fdopen_tempfile(*t2, "w"); + } + +cleanup: + strbuf_release(&buf); + strbuf_release(&basename); +} + +/* + * Create pathnames to the final location of the .pack and .idx + * files in the ODB. These are of the form: + * + * "/pack/-[-]." + * + * For example, for prefetch packs, will be the epoch + * timestamp and will be the packfile hash. + */ +static void create_final_packfile_pathnames( + const char *term_1, const char *term_2, const char *term_3, + struct strbuf *pack_path, struct strbuf *idx_path, + struct strbuf *pack_filename) +{ + struct strbuf base = STRBUF_INIT; + struct strbuf path = STRBUF_INIT; + + if (term_3 && *term_3) + strbuf_addf(&base, "%s-%s-%s", term_1, term_2, term_3); + else + strbuf_addf(&base, "%s-%s", term_1, term_2); + + strbuf_setlen(pack_filename, 0); + strbuf_addf( pack_filename, "%s.pack", base.buf); + + strbuf_addbuf(&path, &gh__global.buf_odb_path); + strbuf_complete(&path, '/'); + strbuf_addstr(&path, "pack/"); + + strbuf_setlen(pack_path, 0); + strbuf_addbuf(pack_path, &path); + strbuf_addf( pack_path, "%s.pack", base.buf); + + strbuf_setlen(idx_path, 0); + strbuf_addbuf(idx_path, &path); + strbuf_addf( idx_path, "%s.idx", base.buf); + + strbuf_release(&base); + strbuf_release(&path); +} + +/* + * Create a pathname to the loose object in the shared-cache ODB + * with the given OID. Try to "mkdir -p" to ensure the parent + * directories exist. + */ +static int create_loose_pathname_in_odb(struct strbuf *buf_path, + const struct object_id *oid) +{ + enum scld_error scld; + const char *hex; + + hex = oid_to_hex(oid); + + strbuf_setlen(buf_path, 0); + strbuf_addbuf(buf_path, &gh__global.buf_odb_path); + strbuf_complete(buf_path, '/'); + strbuf_add(buf_path, hex, 2); + strbuf_addch(buf_path, '/'); + strbuf_addstr(buf_path, hex+2); + + scld = safe_create_leading_directories(the_repository, buf_path->buf); + if (scld != SCLD_OK && scld != SCLD_EXISTS) + return -1; + + return 0; +} + +static void my_run_index_pack(struct gh__request_params *params UNUSED, + struct gh__response_status *status, + const struct strbuf *temp_path_pack, + const struct strbuf *temp_path_idx, + struct strbuf *packfile_checksum) +{ + struct child_process ip = CHILD_PROCESS_INIT; + struct strbuf ip_stdout = STRBUF_INIT; + + strvec_push(&ip.args, "git"); + strvec_push(&ip.args, "index-pack"); + + ip.err = -1; + ip.no_stderr = 1; + + /* Skip generating the rev index, we don't need it. */ + strvec_push(&ip.args, "--no-rev-index"); + + strvec_pushl(&ip.args, "-o", temp_path_idx->buf, NULL); + strvec_push(&ip.args, temp_path_pack->buf); + ip.no_stdin = 1; + ip.out = -1; + + if (pipe_command(&ip, NULL, 0, &ip_stdout, 0, NULL, 0)) { + unlink(temp_path_pack->buf); + unlink(temp_path_idx->buf); + strbuf_addf(&status->error_message, + "index-pack failed on '%s'", + temp_path_pack->buf); + /* + * Lets assume that index-pack failed because the + * downloaded file is corrupt (truncated). + * + * Retry it as if the network had dropped. + */ + status->retry = GH__RETRY_MODE__TRANSIENT; + status->ec = GH__ERROR_CODE__INDEX_PACK_FAILED; + goto cleanup; + } + + if (packfile_checksum) { + /* + * stdout from index-pack should have the packfile hash. + * Extract it and use it in the final packfile name. + * + * TODO What kind of validation should we do on the + * TODO string and is there ever any other output besides + * TODO just the checksum ? + */ + strbuf_trim_trailing_newline(&ip_stdout); + + strbuf_addbuf(packfile_checksum, &ip_stdout); + } + +cleanup: + strbuf_release(&ip_stdout); + child_process_clear(&ip); +} + +static void my_finalize_packfile(struct gh__request_params *params, + struct gh__response_status *status, + int b_keep, + const struct strbuf *temp_path_pack, + const struct strbuf *temp_path_idx, + struct strbuf *final_path_pack, + struct strbuf *final_path_idx, + struct strbuf *final_filename) +{ + /* + * Install the .pack and .idx into the ODB pack directory. + * + * We might be racing with other instances of gvfs-helper if + * we, in parallel, both downloaded the exact same packfile + * (with the same checksum SHA) and try to install it at the + * same time. This might happen on Windows where the loser + * can get an EBUSY or EPERM trying to move/rename the + * tempfile into the pack dir, for example. + * + * So, we always install the .pack before the .idx for + * consistency. And only if *WE* created the .pack and .idx + * files, do we create the matching .keep (when requested). + * + * If we get an error and the target files already exist, we + * silently eat the error. Note that finalize_object_file() + * has already munged errno (and it has various creation + * strategies), so we don't bother looking at it. + */ + if (finalize_object_file(temp_path_pack->buf, final_path_pack->buf) || + finalize_object_file(temp_path_idx->buf, final_path_idx->buf)) { + unlink(temp_path_pack->buf); + unlink(temp_path_idx->buf); + + if (file_exists(final_path_pack->buf) && + file_exists(final_path_idx->buf)) { + trace2_printf("%s: assuming ok for %s", TR2_CAT, final_path_pack->buf); + goto assume_ok; + } + + strbuf_addf(&status->error_message, + "could not install packfile '%s'", + final_path_pack->buf); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PACKFILE; + return; + } + + if (b_keep) { + struct strbuf keep = STRBUF_INIT; + int fd_keep; + + strbuf_addbuf(&keep, final_path_pack); + strbuf_strip_suffix(&keep, ".pack"); + strbuf_addstr(&keep, ".keep"); + + fd_keep = xopen(keep.buf, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd_keep >= 0) + close(fd_keep); + + strbuf_release(&keep); + } + +assume_ok: + if (params->result_list) { + struct strbuf result_msg = STRBUF_INIT; + + strbuf_addf(&result_msg, "packfile %s", final_filename->buf); + string_list_append(params->result_list, result_msg.buf); + strbuf_release(&result_msg); + } +} + +/* + * Convert the tempfile into a temporary .pack, index it into a temporary .idx + * file, and then install the pair into ODB. + */ +static void install_packfile(struct gh__request_params *params, + struct gh__response_status *status) +{ + struct strbuf temp_path_pack = STRBUF_INIT; + struct strbuf temp_path_idx = STRBUF_INIT; + struct strbuf packfile_checksum = STRBUF_INIT; + struct strbuf final_path_pack = STRBUF_INIT; + struct strbuf final_path_idx = STRBUF_INIT; + struct strbuf final_filename = STRBUF_INIT; + + gh__response_status__zero(status); + + /* + * After the download is complete, we will need to steal the file + * from the tempfile() class (so that it doesn't magically delete + * it when we close the file handle) and then index it. + */ + strbuf_addf(&temp_path_pack, "%s.pack", + get_tempfile_path(params->tempfile)); + strbuf_addf(&temp_path_idx, "%s.idx", + get_tempfile_path(params->tempfile)); + + if (rename_tempfile(¶ms->tempfile, + temp_path_pack.buf) == -1) { + strbuf_addf(&status->error_message, + "could not rename packfile to '%s'", + temp_path_pack.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PACKFILE; + goto cleanup; + } + + my_run_index_pack(params, status, &temp_path_pack, &temp_path_idx, + &packfile_checksum); + if (status->ec != GH__ERROR_CODE__OK) + goto cleanup; + + create_final_packfile_pathnames("vfs", packfile_checksum.buf, NULL, + &final_path_pack, &final_path_idx, + &final_filename); + my_finalize_packfile(params, status, 0, + &temp_path_pack, &temp_path_idx, + &final_path_pack, &final_path_idx, + &final_filename); + +cleanup: + strbuf_release(&temp_path_pack); + strbuf_release(&temp_path_idx); + strbuf_release(&packfile_checksum); + strbuf_release(&final_path_pack); + strbuf_release(&final_path_idx); + strbuf_release(&final_filename); +} + +/* + * bswap.h only defines big endian functions. + * The GVFS Protocol defines fields in little endian. + */ +static inline uint64_t my_get_le64(uint64_t le_val) +{ +#if GIT_BYTE_ORDER == GIT_LITTLE_ENDIAN + return le_val; +#else + return default_bswap64(le_val); +#endif +} + +#define MY_MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MY_MAX(x,y) (((x) > (y)) ? (x) : (y)) + +/* + * Copy the `nr_bytes_total` from `fd_in` to `fd_out`. + * + * This could be used to extract a single packfile from + * a multipart file, for example. + */ +static int my_copy_fd_len(int fd_in, int fd_out, ssize_t nr_bytes_total) +{ + char buffer[8192]; + + while (nr_bytes_total > 0) { + ssize_t len_to_read = MY_MIN(nr_bytes_total, (ssize_t)sizeof(buffer)); + ssize_t nr_read = xread(fd_in, buffer, len_to_read); + + if (!nr_read) + break; + if (nr_read < 0) + return -1; + + if (write_in_full(fd_out, buffer, nr_read) < 0) + return -1; + + nr_bytes_total -= nr_read; + } + + return 0; +} + +/* + * Copy the `nr_bytes_total` from `fd_in` to `fd_out` AND save the + * final `tail_len` bytes in the given buffer. + * + * This could be used to extract a single packfile from + * a multipart file and read the final SHA into the buffer. + */ +static int my_copy_fd_len_tail(int fd_in, int fd_out, ssize_t nr_bytes_total, + unsigned char *buf_tail, ssize_t tail_len) +{ + memset(buf_tail, 0, tail_len); + + if (my_copy_fd_len(fd_in, fd_out, nr_bytes_total) < 0) + return -1; + + if (nr_bytes_total < tail_len) + return 0; + + /* Reset the position to read the tail */ + lseek(fd_in, -tail_len, SEEK_CUR); + + if (xread(fd_in, (char *)buf_tail, tail_len) != tail_len) + return -1; + + return 0; +} + +/* + * See the protocol document for the per-packfile header. + */ +struct ph { + uint64_t timestamp; + uint64_t pack_len; + uint64_t idx_len; +}; + +/* + * Extract the next packfile from the multipack. + * Install {.pack, .idx, .keep} set. + * + * Mark each successfully installed prefetch pack as .keep it as installed + * in case we have errors decoding/indexing later packs within the received + * multipart file. (A later pass can delete the unnecessary .keep files + * from this and any previous invocations.) + */ +static void extract_packfile_from_multipack( + struct gh__request_params *params, + struct gh__response_status *status, + int fd_multipack, + unsigned short k) +{ + struct ph ph; + struct tempfile *tempfile_pack = NULL; + int result = -1; + int b_no_idx_in_multipack; + struct object_id packfile_checksum; + char hex_checksum[GIT_MAX_HEXSZ + 1]; + struct strbuf buf_timestamp = STRBUF_INIT; + struct strbuf temp_path_pack = STRBUF_INIT; + struct strbuf temp_path_idx = STRBUF_INIT; + struct strbuf final_path_pack = STRBUF_INIT; + struct strbuf final_path_idx = STRBUF_INIT; + struct strbuf final_filename = STRBUF_INIT; + + if (xread(fd_multipack, &ph, sizeof(ph)) != sizeof(ph)) { + strbuf_addf(&status->error_message, + "could not read header for packfile[%d] in multipack", + k); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PREFETCH; + goto done; + } + + ph.timestamp = my_get_le64(ph.timestamp); + ph.pack_len = my_get_le64(ph.pack_len); + ph.idx_len = my_get_le64(ph.idx_len); + + if (!ph.pack_len) { + strbuf_addf(&status->error_message, + "packfile[%d]: zero length packfile?", k); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PREFETCH; + goto done; + } + + b_no_idx_in_multipack = (ph.idx_len == maximum_unsigned_value_of_type(uint64_t) || + ph.idx_len == 0); + + /* + * We are going to harden `gvfs-helper` here and ignore the .idx file + * if it is provided and always compute it locally so that we get the + * added verification that `git index-pack` provides. + */ + my_create_tempfile(status, 0, "pack", &tempfile_pack, NULL, NULL); + if (!tempfile_pack) + goto done; + + /* + * Copy the current packfile from the open stream and capture + * the checksum. + * + * TODO This assumes that the checksum is SHA1. Fix this if/when + * TODO Git converts to SHA256. + */ + result = my_copy_fd_len_tail(fd_multipack, + get_tempfile_fd(tempfile_pack), + ph.pack_len, + packfile_checksum.hash, + GIT_SHA1_RAWSZ); + packfile_checksum.algo = GIT_HASH_SHA1; + + if (result < 0){ + strbuf_addf(&status->error_message, + "could not extract packfile[%d] from multipack", + k); + goto done; + } + strbuf_addstr(&temp_path_pack, get_tempfile_path(tempfile_pack)); + close_tempfile_gently(tempfile_pack); + + oid_to_hex_r(hex_checksum, &packfile_checksum); + + /* + * Always compute the .idx file from the .pack file. + */ + strbuf_addbuf(&temp_path_idx, &temp_path_pack); + strbuf_strip_suffix(&temp_path_idx, ".pack"); + strbuf_addstr(&temp_path_idx, ".idx"); + + my_run_index_pack(params, status, + &temp_path_pack, &temp_path_idx, + NULL); + if (status->ec != GH__ERROR_CODE__OK) + goto done; + + if (!b_no_idx_in_multipack) { + /* + * Server sent the .idx immediately after the .pack in the + * data stream. Skip over it. + */ + if (lseek(fd_multipack, ph.idx_len, SEEK_CUR) < 0) { + strbuf_addf(&status->error_message, + "could not skip index[%d] in multipack", + k); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PREFETCH; + goto done; + } + } + + strbuf_addf(&buf_timestamp, "%u", (unsigned int)ph.timestamp); + create_final_packfile_pathnames("prefetch", buf_timestamp.buf, hex_checksum, + &final_path_pack, &final_path_idx, + &final_filename); + strbuf_release(&buf_timestamp); + + my_finalize_packfile(params, status, 1, + &temp_path_pack, &temp_path_idx, + &final_path_pack, &final_path_idx, + &final_filename); + +done: + delete_tempfile(&tempfile_pack); + strbuf_release(&temp_path_pack); + strbuf_release(&temp_path_idx); + strbuf_release(&final_path_pack); + strbuf_release(&final_path_idx); + strbuf_release(&final_filename); +} + +struct keep_files_data { + timestamp_t max_timestamp; + int pos_of_max; + struct string_list *keep_files; +}; + +static void cb_keep_files(const char *full_path, size_t full_path_len UNUSED, + const char *file_path, void *void_data) +{ + struct keep_files_data *data = void_data; + const char *val; + timestamp_t t; + + /* + * We expect prefetch packfiles named like: + * + * prefetch--.keep + */ + if (!skip_prefix(file_path, "prefetch-", &val)) + return; + if (!ends_with(val, ".keep")) + return; + + t = strtol(val, NULL, 10); + if (t > data->max_timestamp) { + data->pos_of_max = data->keep_files->nr; + data->max_timestamp = t; + } + + string_list_append(data->keep_files, full_path); +} + +static void delete_stale_keep_files( + struct gh__request_params *params UNUSED, + struct gh__response_status *status UNUSED) +{ + struct string_list keep_files = STRING_LIST_INIT_DUP; + struct keep_files_data data = { 0, 0, &keep_files }; + size_t k; + + for_each_file_in_pack_dir(gh__global.buf_odb_path.buf, + cb_keep_files, &data); + for (k = 0; k < keep_files.nr; k++) { + if ((ssize_t)k != data.pos_of_max) + unlink(keep_files.items[k].string); + } + + string_list_clear(&keep_files, 0); +} + +/* + * Cut apart the received multipart response into individual packfiles + * and install each one. + */ +static void install_prefetch(struct gh__request_params *params, + struct gh__response_status *status) +{ + static unsigned char v1_h[6] = { 'G', 'P', 'R', 'E', ' ', 0x01 }; + + struct mh { + unsigned char h[6]; + unsigned char np[2]; + }; + + struct mh mh; + unsigned short np; + unsigned short k; + int fd = -1; + int nr_installed = 0; + + struct strbuf temp_path_mp = STRBUF_INIT; + + /* + * Steal the multi-part file from the tempfile class. + */ + strbuf_addf(&temp_path_mp, "%s.mp", get_tempfile_path(params->tempfile)); + if (rename_tempfile(¶ms->tempfile, temp_path_mp.buf) == -1) { + strbuf_addf(&status->error_message, + "could not rename prefetch tempfile to '%s'", + temp_path_mp.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PREFETCH; + goto cleanup; + } + + fd = git_open_cloexec(temp_path_mp.buf, O_RDONLY); + if (fd == -1) { + strbuf_addf(&status->error_message, + "could not reopen prefetch tempfile '%s'", + temp_path_mp.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_PREFETCH; + goto cleanup; + } + + if ((xread(fd, &mh, sizeof(mh)) != sizeof(mh)) || + (memcmp(mh.h, &v1_h, sizeof(mh.h)))) { + strbuf_addstr(&status->error_message, + "invalid prefetch multipart header"); + goto cleanup; + } + + np = (unsigned short)mh.np[0] + ((unsigned short)mh.np[1] << 8); + if (np) + trace2_data_intmax(TR2_CAT, NULL, + "prefetch/packfile_count", np); + + if (gh__cmd_opts.show_progress) + params->progress = start_progress(the_repository, "Installing prefetch packfiles", np); + + for (k = 0; k < np; k++) { + extract_packfile_from_multipack(params, status, fd, k); + display_progress(params->progress, k + 1); + if (status->ec != GH__ERROR_CODE__OK) + break; + nr_installed++; + } + stop_progress(¶ms->progress); + + if (nr_installed) + delete_stale_keep_files(params, status); + +cleanup: + if (fd != -1) + close(fd); + + unlink(temp_path_mp.buf); + strbuf_release(&temp_path_mp); +} + +/* + * Wrapper for read_loose_object() to read and verify the hash of a + * loose object, and discard the contents buffer. + * + * Returns 0 on success, negative on error (details may be written to stderr). + */ +static int verify_loose_object(const char *path, + const struct object_id *expected_oid) +{ + enum object_type type; + void *contents = NULL; + unsigned long size; + int ret; + struct object_info oi = OBJECT_INFO_INIT; + struct object_id real_oid = *null_oid(the_hash_algo); + oi.typep = &type; + oi.sizep = &size; + + ret = read_loose_object(path, expected_oid, &real_oid, &contents, &oi); + free(contents); + + return ret; +} + +/* + * Convert the tempfile into a permanent loose object in the ODB. + */ +static void install_loose(struct gh__request_params *params, + struct gh__response_status *status) +{ + struct strbuf tmp_path = STRBUF_INIT; + struct strbuf loose_path = STRBUF_INIT; + + gh__response_status__zero(status); + + /* + * close tempfile to steal ownership away from tempfile class. + */ + strbuf_addstr(&tmp_path, get_tempfile_path(params->tempfile)); + close_tempfile_gently(params->tempfile); + + /* + * Compute the hash of the received content (while it is still + * in a temp file) and verify that it matches the OID that we + * requested and was not corrupted. + */ + if (verify_loose_object(tmp_path.buf, ¶ms->loose_oid)) { + strbuf_addf(&status->error_message, + "hash failed for received loose object '%s'", + oid_to_hex(¶ms->loose_oid)); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_LOOSE; + goto cleanup; + } + + /* + * Try to install the tempfile as the actual loose object. + * + * If the loose object already exists, finalize_object_file() + * will NOT overwrite/replace it. It will silently eat the + * EEXIST error and unlink the tempfile as it if was + * successful. We just let it lie to us. + * + * Since our job is to back-fill missing objects needed by a + * foreground git process -- git should have called + * oid_object_info_extended() and loose_object_info() BEFORE + * asking us to download the missing object. So if we get a + * collision we have to assume something else is happening in + * parallel and we lost the race. And that's OK. + */ + if (create_loose_pathname_in_odb(&loose_path, ¶ms->loose_oid)) { + strbuf_addf(&status->error_message, + "cannot create directory for loose object '%s'", + loose_path.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_LOOSE; + goto cleanup; + } + + if (finalize_object_file(tmp_path.buf, loose_path.buf)) { + unlink(tmp_path.buf); + strbuf_addf(&status->error_message, + "could not install loose object '%s'", + loose_path.buf); + status->ec = GH__ERROR_CODE__COULD_NOT_INSTALL_LOOSE; + goto cleanup; + } + + if (params->result_list) { + struct strbuf result_msg = STRBUF_INIT; + + strbuf_addf(&result_msg, "loose %s", + oid_to_hex(¶ms->loose_oid)); + string_list_append(params->result_list, result_msg.buf); + strbuf_release(&result_msg); + } + +cleanup: + strbuf_release(&tmp_path); + strbuf_release(&loose_path); +} + +static void install_result(struct gh__request_params *params, + struct gh__response_status *status) +{ + if (params->objects_mode == GH__OBJECTS_MODE__PREFETCH) { + /* + * The "gvfs/prefetch" API is the only thing that sends + * these multi-part packfiles. According to the protocol + * documentation, they will have this x- content type. + * + * However, it appears that there is a BUG in the origin + * server causing it to sometimes send "text/html" instead. + * So, we silently handle both. + */ + if (!strcmp(status->content_type.buf, + "application/x-gvfs-timestamped-packfiles-indexes")) { + install_prefetch(params, status); + return; + } + + if (!strcmp(status->content_type.buf, "text/html")) { + install_prefetch(params, status); + return; + } + } else { + if (!strcmp(status->content_type.buf, "application/x-git-packfile")) { + assert(params->b_is_post); + assert(params->objects_mode == GH__OBJECTS_MODE__POST); + + install_packfile(params, status); + return; + } + + if (!strcmp(status->content_type.buf, + "application/x-git-loose-object")) { + /* + * We get these for "gvfs/objects" GET and POST requests. + * + * Note that this content type is singular, not plural. + */ + install_loose(params, status); + return; + } + } + + strbuf_addf(&status->error_message, + "install_result: received unknown content-type '%s'", + status->content_type.buf); + status->ec = GH__ERROR_CODE__UNEXPECTED_CONTENT_TYPE; +} + +/* + * Our wrapper to initialize the HTTP layer. + * + * We always use the real origin server, not the cache-server, when + * initializing the http/curl layer. + */ +static void gh_http_init(void) +{ + if (gh__global.http_is_initialized) + return; + + http_init(gh__global.remote, gh__global.main_url, 0); + gh__global.http_is_initialized = 1; +} + +static void gh_http_cleanup(void) +{ + if (!gh__global.http_is_initialized) + return; + + http_cleanup(); + gh__global.http_is_initialized = 0; +} + +/* + * buffer has ": [\r]\n" + */ +static void parse_resp_hdr_1(const char *buffer, size_t size, size_t nitems, + struct strbuf *key, struct strbuf *value) +{ + const char *end = buffer + (size * nitems); + const char *p; + + p = strchr(buffer, ':'); + + strbuf_setlen(key, 0); + strbuf_add(key, buffer, (p - buffer)); + + p++; /* skip ':' */ + p++; /* skip ' ' */ + + strbuf_setlen(value, 0); + strbuf_add(value, p, (end - p)); + strbuf_trim_trailing_newline(value); +} + +static size_t parse_resp_hdr(char *buffer, size_t size, size_t nitems, + void *void_params) +{ + struct gh__request_params *params = void_params; + struct gh__azure_throttle *azure = &gh__global_throttle[params->server_type]; + + if (starts_with(buffer, "X-RateLimit-")) { + struct strbuf key = STRBUF_INIT; + struct strbuf val = STRBUF_INIT; + + parse_resp_hdr_1(buffer, size, nitems, &key, &val); + + /* + * The following X- headers are specific to AzureDevOps. + * Other servers have similar sets of values, but I haven't + * compared them in depth. + */ + // trace2_printf("%s: Throttle: %s %s", TR2_CAT, key.buf, val.buf); + + if (!strcmp(key.buf, "X-RateLimit-Resource")) { + /* + * The name of the resource that is complaining. + * Just log it because we can't do anything with it. + */ + strbuf_setlen(&key, 0); + strbuf_addstr(&key, "ratelimit/resource"); + strbuf_addstr(&key, gh__server_type_label[params->server_type]); + + trace2_data_string(TR2_CAT, NULL, key.buf, val.buf); + } + + else if (!strcmp(key.buf, "X-RateLimit-Delay")) { + /* + * The amount of delay added to our response. + * Just log it because we can't do anything with it. + */ + unsigned long tarpit_delay_ms; + + strbuf_setlen(&key, 0); + strbuf_addstr(&key, "ratelimit/delay_ms"); + strbuf_addstr(&key, gh__server_type_label[params->server_type]); + + git_parse_ulong(val.buf, &tarpit_delay_ms); + + trace2_data_intmax(TR2_CAT, NULL, key.buf, tarpit_delay_ms); + } + + else if (!strcmp(key.buf, "X-RateLimit-Limit")) { + /* + * The resource limit/quota before we get a 429. + */ + git_parse_ulong(val.buf, &azure->tstu_limit); + } + + else if (!strcmp(key.buf, "X-RateLimit-Remaining")) { + /* + * The amount of our quota remaining. When zero, we + * should get 429s on futher requests until the reset + * time. + */ + git_parse_ulong(val.buf, &azure->tstu_remaining); + } + + else if (!strcmp(key.buf, "X-RateLimit-Reset")) { + /* + * The server gave us a time-in-seconds-since-the-epoch + * for when our quota will be reset (if we stop all + * activity right now). + * + * Checkpoint the local system clock so we can do some + * sanity checks on any clock skew. Also, since we get + * the headers before we get the content, we can adjust + * our delay to compensate for the full download time. + */ + unsigned long now = time(NULL); + unsigned long reset_time; + + git_parse_ulong(val.buf, &reset_time); + if (reset_time > now) + azure->reset_sec = reset_time - now; + } + + strbuf_release(&key); + strbuf_release(&val); + } + + else if (starts_with(buffer, "Retry-After")) { + struct strbuf key = STRBUF_INIT; + struct strbuf val = STRBUF_INIT; + + parse_resp_hdr_1(buffer, size, nitems, &key, &val); + + /* + * We get this header with a 429 and 503 and possibly a 30x. + * + * Curl does have CURLINFO_RETRY_AFTER that nicely parses and + * normalizes the value (and supports HTTP/1.1 usage), but it + * is not present yet in the version shipped with the Mac, so + * we do it directly here. + */ + git_parse_ulong(val.buf, &azure->retry_after_sec); + + strbuf_release(&key); + strbuf_release(&val); + } + + else if (starts_with(buffer, "X-VSS-E2EID")) { + struct strbuf key = STRBUF_INIT; + + /* + * Capture the E2EID as it goes by, but don't log it until we + * know the request result. + */ + parse_resp_hdr_1(buffer, size, nitems, &key, ¶ms->e2eid); + + strbuf_release(&key); + } + + return nitems * size; +} + +/* + * Wait "duration" seconds and drive the progress mechanism. + * + * We spin slightly faster than we need to to keep the progress bar + * drawn (especially if the user presses return while waiting) and to + * compensate for delay factors built into the progress class (which + * might wait for 2 seconds before drawing the first message). + */ +static void do_throttle_spin(struct gh__request_params *params, + const char *tr2_label, + const char *progress_msg, + int duration) +{ + struct strbuf region = STRBUF_INIT; + struct progress *progress = NULL; + unsigned long begin = time(NULL); + unsigned long now = begin; + unsigned long end = begin + duration; + + strbuf_addstr(®ion, tr2_label); + strbuf_addstr(®ion, gh__server_type_label[params->server_type]); + trace2_region_enter(TR2_CAT, region.buf, NULL); + + if (gh__cmd_opts.show_progress) + progress = start_progress(the_repository, progress_msg, duration); + + while (now < end) { + display_progress(progress, (now - begin)); + + sleep_millisec(100); + + now = time(NULL); + } + + display_progress(progress, duration); + stop_progress(&progress); + + trace2_region_leave(TR2_CAT, region.buf, NULL); + strbuf_release(®ion); +} + +/* + * Delay the outbound request if necessary in response to previous throttle + * blockages or hints. Throttle data is somewhat orthogonal to the status + * results from any previous request and/or the request params of the next + * request. + * + * Note that the throttle info also is cross-process information, such as + * 2 concurrent fetches in 2 different terminal windows to the same server + * will be sharing the same server quota. These could be coordinated too, + * so that a blockage received in one process would prevent the other + * process from starting another request (and also blocked or extending + * the delay interval). We're NOT going to do that level of integration. + * We will let both processes independently attempt the next request. + * This may cause us to miss the end-of-quota boundary if the server + * extends it because of the second request. + * + * TODO Should we have a max-wait option and then return a hard-error + * TODO of some type? + */ +static void do_throttle_wait(struct gh__request_params *params, + struct gh__response_status *status UNUSED) +{ + struct gh__azure_throttle *azure = + &gh__global_throttle[params->server_type]; + + if (azure->retry_after_sec) { + /* + * We were given a hard delay (such as after a 429). + * Spin until the requested time. + */ + do_throttle_spin(params, "throttle/hard", + "Waiting on hard throttle (sec)", + azure->retry_after_sec); + return; + } + + if (azure->reset_sec > 0) { + /* + * We were given a hint that we are overloading + * the server. Voluntarily backoff (before we + * get tarpitted or blocked). + */ + do_throttle_spin(params, "throttle/soft", + "Waiting on soft throttle (sec)", + azure->reset_sec); + return; + } + + if (params->k_transient_delay_sec) { + /* + * Insert an arbitrary delay before retrying after a + * transient (network) failure. + */ + do_throttle_spin(params, "throttle/transient", + "Waiting to retry after network error (sec)", + params->k_transient_delay_sec); + return; + } +} + +static void set_main_creds_on_slot(struct active_request_slot *slot, + const struct credential *creds) +{ + assert(creds == &gh__global.main_creds); + + /* + * When talking to the main/origin server, we have 3 modes + * of operation: + * + * [1] The initial request is sent without loading creds + * and with ANY-AUTH set. (And the `":"` is a magic + * value.) + * + * This allows libcurl to negotiate for us if it can. + * For example, this allows NTLM to work by magic and + * we get 200s without ever seeing a 401. If libcurl + * cannot negotiate for us, it gives us a 401 (and all + * of the 401 code in this file responds to that). + * + * [2] A 401 retry will load the main creds and try again. + * This causes `creds->username`to be non-NULL (even + * if refers to a zero-length string). And we assume + * BASIC Authentication. (And a zero-length username + * is a convention for PATs, but then sometimes users + * put the PAT in their `username` field and leave the + * `password` field blank. And that works too.) + * + * [3] Subsequent requests on the same connection use + * whatever worked before. + */ + if (creds && creds->username) { + curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(slot->curl, CURLOPT_USERNAME, creds->username); + curl_easy_setopt(slot->curl, CURLOPT_PASSWORD, creds->password); + } else { + curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + curl_easy_setopt(slot->curl, CURLOPT_USERPWD, ":"); + } +} + +static void set_cache_server_creds_on_slot(struct active_request_slot *slot, + const struct credential *creds) +{ + assert(creds == &gh__global.cache_creds); + assert(creds->username); + + /* + * Things are weird when talking to a cache-server: + * + * [1] They don't send 401s on an auth error, rather they send + * a 400 (with a nice human-readable string in the html body). + * This prevents libcurl from doing any negotiation for us. + * + * [2] Cache-servers don't manage their own passwords, but + * rather require us to send the Basic Authentication + * username & password that we would send to the main + * server. (So yes, we have to get creds validated + * against the main server creds and substitute them when + * talking to the cache-server.) + * + * This means that: + * + * [a] We cannot support cache-servers that want to use NTLM. + * + * [b] If we want to talk to a cache-server, we have get the + * Basic Auth creds for the main server. And this may be + * problematic if the libcurl and/or the credential manager + * insists on using NTLM and prevents us from getting them. + * + * So we never try AUTH-ANY and force Basic Auth (if possible). + */ + if (creds && creds->username) { + curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(slot->curl, CURLOPT_USERNAME, creds->username); + curl_easy_setopt(slot->curl, CURLOPT_PASSWORD, creds->password); + } +} + +/* + * Do a single HTTP request WITHOUT robust-retry, auth-retry or fallback. + */ +static void do_req(const char *url_base, + const char *url_component, + const struct credential *creds, + struct gh__request_params *params, + struct gh__response_status *status) +{ + struct active_request_slot *slot; + struct slot_results results; + struct strbuf rest_url = STRBUF_INIT; + + gh__response_status__zero(status); + + if (params->b_write_to_file) { + /* Delete dirty tempfile from a previous attempt. */ + if (params->tempfile) + delete_tempfile(¶ms->tempfile); + + my_create_tempfile(status, 1, NULL, ¶ms->tempfile, NULL, NULL); + if (!params->tempfile || status->ec != GH__ERROR_CODE__OK) + return; + } else { + /* Guard against caller using dirty buffer */ + strbuf_setlen(params->buffer, 0); + } + + end_url_with_slash(&rest_url, url_base); + strbuf_addstr(&rest_url, url_component); + + do_throttle_wait(params, status); + gh__azure_throttle__zero(&gh__global_throttle[params->server_type]); + + slot = get_active_slot(); + slot->results = &results; + + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0L); /* not a HEAD request */ + curl_easy_setopt(slot->curl, CURLOPT_URL, rest_url.buf); + curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, params->headers); + if (curl_version_info(CURLVERSION_NOW)->version_num < 0x074b00) + /* + * cURL 7.75.0 allows headers to be parsed even when + * `CURLOPT_FAILONERROR` is enabled and the HTTP result code + * indicates an error. This is the behavior expected by + * `gvfs-helper`. + * + * On older cURL versions, `gvfs-helper` still needs to parse + * the HTTP headers and therefore needs to _not_ fail upon + * HTTP result codes indicating errors; For newer cURL + * versions, we still prefer to enable `FAILONERROR`. + */ + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, (long)0); + + if (params->b_is_post) { + curl_easy_setopt(slot->curl, CURLOPT_POST, 1L); + curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL); + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, + params->post_payload->buf); + curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, + (long)params->post_payload->len); + } else { + curl_easy_setopt(slot->curl, CURLOPT_POST, 0L); + } + + if (params->b_write_to_file) { + curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite); + curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, + (void*)params->tempfile->fp); + } else { + curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, + fwrite_buffer); + curl_easy_setopt(slot->curl, CURLOPT_FILE, params->buffer); + } + + curl_easy_setopt(slot->curl, CURLOPT_HEADERFUNCTION, parse_resp_hdr); + curl_easy_setopt(slot->curl, CURLOPT_HEADERDATA, params); + + if (params->server_type == GH__SERVER_TYPE__MAIN) + set_main_creds_on_slot(slot, creds); + else + set_cache_server_creds_on_slot(slot, creds); + + if (params->progress_base_phase2_msg.len || + params->progress_base_phase3_msg.len) { + curl_easy_setopt(slot->curl, CURLOPT_XFERINFOFUNCTION, + gh__curl_progress_cb); + curl_easy_setopt(slot->curl, CURLOPT_XFERINFODATA, params); + curl_easy_setopt(slot->curl, CURLOPT_NOPROGRESS, 0L); + } else { + curl_easy_setopt(slot->curl, CURLOPT_NOPROGRESS, 1L); + } + + gh__run_one_slot(slot, params, status); + strbuf_release(&rest_url); +} + +/* + * Compute the delay for the nth attempt. + * + * No delay for the first attempt. Then use a normal exponential backoff + * starting from 8. + */ +static int compute_transient_delay(int attempt) +{ + int v; + + if (attempt < 1) + return 0; + + /* + * Let 8K be our hard limit (for integer overflow protection). + * That's over 2 hours. This is 8<<10. + */ + if (attempt > 10) + attempt = 10; + + v = 8 << (attempt - 1); + + if (v > gh__cmd_opts.max_transient_backoff_sec) + v = gh__cmd_opts.max_transient_backoff_sec; + + return v; +} + +/* + * Robustly make an HTTP request. Retry if necessary to hide common + * transient network errors and/or 429 blockages. + * + * For a transient (network) failure (where we do not have a throttle + * delay factor), we should insert a small delay to let the network + * recover. The outage might be because the VPN dropped, or the + * machine went to sleep or something and we want to give the network + * time to come back up. Insert AI here :-) + */ +static void do_req__with_robust_retry(const char *url_base, + const char *url_component, + const struct credential *creds, + struct gh__request_params *params, + struct gh__response_status *status) +{ + for (params->k_attempt = 0; + params->k_attempt < gh__cmd_opts.max_retries + 1; + params->k_attempt++) { + + do_req(url_base, url_component, creds, params, status); + + switch (status->retry) { + default: + case GH__RETRY_MODE__SUCCESS: + case GH__RETRY_MODE__HTTP_401: /* caller does auth-retry */ + case GH__RETRY_MODE__HARD_FAIL: + case GH__RETRY_MODE__FAIL_404: + return; + + case GH__RETRY_MODE__HTTP_429: + case GH__RETRY_MODE__HTTP_503: + /* + * We should have gotten a "Retry-After" header with + * these and that gives us the wait time. If not, + * fallthru and use the backoff delay. + */ + if (gh__global_throttle[params->server_type].retry_after_sec) + continue; + /*fallthru*/ + + case GH__RETRY_MODE__TRANSIENT: + params->k_transient_delay_sec = + compute_transient_delay(params->k_attempt); + continue; + } + } +} + +static void do_req__to_main(const char *url_component, + struct gh__request_params *params, + struct gh__response_status *status) +{ + params->server_type = GH__SERVER_TYPE__MAIN; + + /* + * When talking to the main Git server, we DO NOT preload the + * creds before the first request. + */ + + do_req__with_robust_retry(gh__global.main_url, url_component, + &gh__global.main_creds, + params, status); + + if (status->retry == GH__RETRY_MODE__HTTP_401) { + refresh_main_creds(); + + do_req__with_robust_retry(gh__global.main_url, url_component, + &gh__global.main_creds, + params, status); + } + + if (status->retry == GH__RETRY_MODE__SUCCESS) + approve_main_creds(); +} + +static void do_req__to_cache_server(const char *url_component, + struct gh__request_params *params, + struct gh__response_status *status) +{ + params->server_type = GH__SERVER_TYPE__CACHE; + + /* + * When talking to a cache-server, DO force load the creds. + * This implicitly preloads the creds to the main server. + */ + synthesize_cache_server_creds(); + + do_req__with_robust_retry(gh__global.cache_server_url, url_component, + &gh__global.cache_creds, + params, status); + + if (status->retry == GH__RETRY_MODE__HTTP_401) { + refresh_cache_server_creds(); + + do_req__with_robust_retry(gh__global.cache_server_url, + url_component, + &gh__global.cache_creds, + params, status); + } + + if (status->retry == GH__RETRY_MODE__SUCCESS) + approve_cache_server_creds(); +} + +/* + * Try the cache-server (if configured) then fall-back to the main Git server. + */ +static void do_req__with_fallback(const char *url_component, + struct gh__request_params *params, + struct gh__response_status *status) +{ + if (gh__global.cache_server_url && + params->b_permit_cache_server_if_defined) { + do_req__to_cache_server(url_component, params, status); + + if (status->retry == GH__RETRY_MODE__SUCCESS) + return; + + if (!gh__cmd_opts.try_fallback) + return; + + /* + * The cache-server shares creds with the main Git server, + * so if our creds failed against the cache-server, they + * will also fail against the main Git server. We just let + * this fail. + * + * Falling-back would likely just cause the 3rd (or maybe + * 4th) cred prompt. + */ + if (status->retry == GH__RETRY_MODE__HTTP_401) + return; + } + + do_req__to_main(url_component, params, status); +} + +/* + * Call "gvfs/config" REST API. + * + * Return server's response buffer. This is probably a raw JSON string. + */ +static void do__http_get__simple_endpoint(struct gh__response_status *status, + struct strbuf *response, + const char *endpoint, + const char *tr2_label) +{ + struct gh__request_params params = GH__REQUEST_PARAMS_INIT; + + strbuf_addstr(¶ms.tr2_label, tr2_label); + + params.b_is_post = 0; + params.b_write_to_file = 0; + /* cache-servers do not handle gvfs/config REST calls */ + params.b_permit_cache_server_if_defined = 0; + params.buffer = response; + params.objects_mode = GH__OBJECTS_MODE__NONE; + + params.object_count = 1; /* a bit of a lie */ + + /* + * "X-TFS-FedAuthRedirect: Suppress" disables the 302 + 203 redirect + * sequence to a login page and forces the main Git server to send a + * normal 401. + */ + params.headers = http_copy_default_headers(); + params.headers = curl_slist_append(params.headers, + "X-TFS-FedAuthRedirect: Suppress"); + params.headers = curl_slist_append(params.headers, + "Pragma: no-cache"); + + if (gh__cmd_opts.show_progress) { + /* + * gvfs/config has a very small reqest payload, so I don't + * see any need to report progress on the upload side of + * the GET. So just report progress on the download side. + */ + strbuf_addf(¶ms.progress_base_phase3_msg, + "Receiving %s", endpoint); + } + + do_req__with_fallback(endpoint, ¶ms, status); + + gh__request_params__release(¶ms); +} + +static void do__http_get__gvfs_config(struct gh__response_status *status, + struct strbuf *config_data) +{ + do__http_get__simple_endpoint(status, config_data, "gvfs/config", + "GET/config"); +} + +static void setup_gvfs_objects_progress(struct gh__request_params *params, + unsigned long num, unsigned long den) +{ + if (!gh__cmd_opts.show_progress) + return; + + if (params->b_is_post) { + strbuf_addf(¶ms->progress_base_phase3_msg, + "Receiving packfile %ld/%ld with %ld objects", + num, den, params->object_count); + } + /* If requesting only one object, then do not show progress */ +} + +/* + * Call "gvfs/objects/" REST API to fetch a loose object + * and write it to the ODB. + */ +static void do__http_get__gvfs_object(struct gh__response_status *status, + const struct object_id *oid, + unsigned long l_num, unsigned long l_den, + struct string_list *result_list) +{ + struct gh__request_params params = GH__REQUEST_PARAMS_INIT; + struct strbuf component_url = STRBUF_INIT; + + gh__response_status__zero(status); + + strbuf_addf(&component_url, "gvfs/objects/%s", oid_to_hex(oid)); + + strbuf_addstr(¶ms.tr2_label, "GET/objects"); + + params.b_is_post = 0; + params.b_write_to_file = 1; + params.b_permit_cache_server_if_defined = 1; + params.objects_mode = GH__OBJECTS_MODE__GET; + + params.object_count = 1; + + params.result_list = result_list; + + params.headers = http_copy_default_headers(); + params.headers = curl_slist_append(params.headers, + "X-TFS-FedAuthRedirect: Suppress"); + params.headers = curl_slist_append(params.headers, + "Pragma: no-cache"); + + oidcpy(¶ms.loose_oid, oid); + + setup_gvfs_objects_progress(¶ms, l_num, l_den); + + do_req__with_fallback(component_url.buf, ¶ms, status); + + gh__request_params__release(¶ms); + strbuf_release(&component_url); +} + +/* + * Call "gvfs/objects" POST REST API to fetch a batch of objects + * from the OIDSET. Normal, this is results in a packfile containing + * `nr_wanted_in_block` objects. And we return the number actually + * consumed (along with the filename of the resulting packfile). + * + * However, if we only have 1 oid (remaining) in the OIDSET, the + * server *MAY* respond to our POST with a loose object rather than + * a packfile with 1 object. + * + * Append a message to the result_list describing the result. + * + * Return the number of OIDs consumed from the OIDSET. + */ +static void do__http_post__gvfs_objects(struct gh__response_status *status, + struct oidset_iter *iter, + unsigned long nr_wanted_in_block, + int j_pack_num, int j_pack_den, + struct string_list *result_list, + unsigned long *nr_oid_taken) +{ + struct json_writer jw_req = JSON_WRITER_INIT; + struct gh__request_params params = GH__REQUEST_PARAMS_INIT; + + gh__response_status__zero(status); + + params.object_count = build_json_payload__gvfs_objects( + &jw_req, iter, nr_wanted_in_block, ¶ms.loose_oid); + *nr_oid_taken = params.object_count; + + strbuf_addstr(¶ms.tr2_label, "POST/objects"); + + params.b_is_post = 1; + params.b_write_to_file = 1; + params.b_permit_cache_server_if_defined = 1; + params.objects_mode = GH__OBJECTS_MODE__POST; + + params.post_payload = &jw_req.json; + + params.result_list = result_list; + + params.headers = http_copy_default_headers(); + params.headers = curl_slist_append(params.headers, + "X-TFS-FedAuthRedirect: Suppress"); + params.headers = curl_slist_append(params.headers, + "Pragma: no-cache"); + params.headers = curl_slist_append(params.headers, + "Content-Type: application/json"); + /* + * If our POST contains more than one object, we want the + * server to send us a packfile. We DO NOT want the non-standard + * concatenated loose object format, so we DO NOT send: + * "Accept: application/x-git-loose-objects" (plural) + * + * However, if the payload only requests 1 OID, the server + * will send us a single loose object instead of a packfile, + * so we ACK that and send: + * "Accept: application/x-git-loose-object" (singular) + */ + params.headers = curl_slist_append(params.headers, + "Accept: application/x-git-packfile"); + params.headers = curl_slist_append(params.headers, + "Accept: application/x-git-loose-object"); + + setup_gvfs_objects_progress(¶ms, j_pack_num, j_pack_den); + + do_req__with_fallback("gvfs/objects", ¶ms, status); + + gh__request_params__release(¶ms); + jw_release(&jw_req); +} + +struct find_last_data { + timestamp_t timestamp; + int nr_files; +}; + +static void cb_find_last(const char *full_path UNUSED, size_t full_path_len UNUSED, + const char *file_path, void *void_data) +{ + struct find_last_data *data = void_data; + const char *val; + timestamp_t t; + + if (!skip_prefix(file_path, "prefetch-", &val)) + return; + if (!ends_with(val, ".pack")) + return; + + data->nr_files++; + + /* + * We expect prefetch packfiles named like: + * + * prefetch--.pack + */ + t = strtol(val, NULL, 10); + + data->timestamp = MY_MAX(t, data->timestamp); +} + +/* + * Find the server timestamp on the last prefetch packfile that + * we have in the ODB. + * + * TODO I'm going to assume that all prefetch packs are created + * TODO equal and take the one with the largest t value. + * TODO + * TODO Or should we look for one marked with .keep ? + * + * TODO Alternatively, should we maybe get the 2nd largest? + * TODO (Or maybe subtract an hour delta from the largest?) + * TODO + * TODO Since each cache-server maintains its own set of prefetch + * TODO packs (such that 2 requests may hit 2 different + * TODO load-balanced servers and get different answers (with or + * TODO without clock-skew issues)), is it possible for us to miss + * TODO the absolute fringe of new commits and trees? + * TODO + * TODO That is, since the cache-server generates hourly prefetch + * TODO packs, we could do a prefetch and be up-to-date, but then + * TODO do the main fetch and hit a different cache/main server + * TODO and be behind by as much as an hour and have to demand- + * TODO load the commits/trees. + * + * TODO Alternatively, should we compare the last timestamp found + * TODO with "now" and silently do nothing if within an epsilon? + */ +static void find_last_prefetch_timestamp(timestamp_t *last) +{ + struct find_last_data data; + + memset(&data, 0, sizeof(data)); + + for_each_file_in_pack_dir(gh__global.buf_odb_path.buf, cb_find_last, &data); + + *last = data.timestamp; +} + +/* + * Call "gvfs/prefetch[?lastPackTimestamp=]" REST API to + * fetch a series of packfiles and write them to the ODB. + * + * Return a list of packfile names. + */ +static void do__http_get__gvfs_prefetch(struct gh__response_status *status, + timestamp_t seconds_since_epoch, + struct string_list *result_list) +{ + struct gh__request_params params = GH__REQUEST_PARAMS_INIT; + struct strbuf component_url = STRBUF_INIT; + + gh__response_status__zero(status); + + strbuf_addstr(&component_url, "gvfs/prefetch"); + + if (!seconds_since_epoch) + find_last_prefetch_timestamp(&seconds_since_epoch); + if (seconds_since_epoch) + strbuf_addf(&component_url, "?lastPackTimestamp=%"PRItime, + seconds_since_epoch); + + params.b_is_post = 0; + params.b_write_to_file = 1; + params.b_permit_cache_server_if_defined = 1; + params.objects_mode = GH__OBJECTS_MODE__PREFETCH; + + params.object_count = -1; + + params.result_list = result_list; + + params.headers = http_copy_default_headers(); + params.headers = curl_slist_append(params.headers, + "X-TFS-FedAuthRedirect: Suppress"); + params.headers = curl_slist_append(params.headers, + "Pragma: no-cache"); + params.headers = curl_slist_append(params.headers, + "Accept: application/x-gvfs-timestamped-packfiles-indexes"); + + if (gh__cmd_opts.show_progress) + strbuf_addf(¶ms.progress_base_phase3_msg, + "Prefetch %"PRItime" (%s)", + seconds_since_epoch, + show_date(seconds_since_epoch, 0, + DATE_MODE(ISO8601))); + + do_req__with_fallback(component_url.buf, ¶ms, status); + + gh__request_params__release(¶ms); + strbuf_release(&component_url); +} + +/* + * Drive one or more HTTP GET requests to fetch the objects + * in the given OIDSET. These are received into loose objects. + * + * Accumulate results for each request in `result_list` until we get a + * hard error and have to stop. + */ +static void do__http_get__fetch_oidset(struct gh__response_status *status, + struct oidset *oids, + unsigned long nr_oid_total, + struct string_list *result_list) +{ + struct oidset_iter iter; + struct strbuf err404 = STRBUF_INIT; + const struct object_id *oid; + unsigned long k; + int had_404 = 0; + + gh__response_status__zero(status); + if (!nr_oid_total) + return; + + oidset_iter_init(oids, &iter); + + for (k = 0; k < nr_oid_total; k++) { + oid = oidset_iter_next(&iter); + + do__http_get__gvfs_object(status, oid, k+1, nr_oid_total, + result_list); + + /* + * If we get a 404 for an individual object, ignore + * it and get the rest. We'll fixup the 'ec' later. + */ + if (status->ec == GH__ERROR_CODE__HTTP_404) { + if (!err404.len) + strbuf_addf(&err404, "%s: from GET %s", + status->error_message.buf, + oid_to_hex(oid)); + /* + * Mark the fetch as "incomplete", but don't + * stop trying to get other chunks. + */ + had_404 = 1; + continue; + } + + if (status->ec != GH__ERROR_CODE__OK) { + /* Stop at the first hard error. */ + strbuf_addf(&status->error_message, ": from GET %s", + oid_to_hex(oid)); + goto cleanup; + } + } + +cleanup: + if (had_404 && status->ec == GH__ERROR_CODE__OK) { + strbuf_setlen(&status->error_message, 0); + strbuf_addbuf(&status->error_message, &err404); + status->ec = GH__ERROR_CODE__HTTP_404; + } + + strbuf_release(&err404); +} + +/* + * Drive one or more HTTP POST requests to bulk fetch the objects in + * the given OIDSET. Create one or more packfiles and/or loose objects. + * + * Accumulate results for each request in `result_list` until we get a + * hard error and have to stop. + */ +static void do__http_post__fetch_oidset(struct gh__response_status *status, + struct oidset *oids, + unsigned long nr_oid_total, + struct string_list *result_list) +{ + struct oidset_iter iter; + struct strbuf err404 = STRBUF_INIT; + unsigned long k; + unsigned long nr_oid_taken; + int j_pack_den = 0; + int j_pack_num = 0; + int had_404 = 0; + + gh__response_status__zero(status); + if (!nr_oid_total) + return; + + oidset_iter_init(oids, &iter); + + j_pack_den = ((nr_oid_total + gh__cmd_opts.block_size - 1) + / gh__cmd_opts.block_size); + + for (k = 0; k < nr_oid_total; k += nr_oid_taken) { + j_pack_num++; + + do__http_post__gvfs_objects(status, &iter, + gh__cmd_opts.block_size, + j_pack_num, j_pack_den, + result_list, + &nr_oid_taken); + + /* + * Because the oidset iterator has random + * order, it does no good to say the k-th or + * n-th chunk was incomplete; the client + * cannot use that index for anything. + * + * We get a 404 when at least one object in + * the chunk was not found. + * + * For now, ignore the 404 and go on to the + * next chunk and then fixup the 'ec' later. + */ + if (status->ec == GH__ERROR_CODE__HTTP_404) { + if (!err404.len) + strbuf_addf(&err404, + "%s: from POST", + status->error_message.buf); + /* + * Mark the fetch as "incomplete", but don't + * stop trying to get other chunks. + */ + had_404 = 1; + continue; + } + + if (status->ec != GH__ERROR_CODE__OK) { + /* Stop at the first hard error. */ + strbuf_addstr(&status->error_message, + ": from POST"); + goto cleanup; + } + } + +cleanup: + if (had_404 && status->ec == GH__ERROR_CODE__OK) { + strbuf_setlen(&status->error_message, 0); + strbuf_addbuf(&status->error_message, &err404); + status->ec = GH__ERROR_CODE__HTTP_404; + } + + strbuf_release(&err404); +} + +/* + * Finish with initialization. This happens after the main option + * parsing, dispatch to sub-command, and sub-command option parsing + * and before actually doing anything. + * + * Optionally configure the cache-server if the sub-command will + * use it. + */ +static void finish_init(int setup_cache_server) +{ + select_odb(); + + lookup_main_url(); + gh_http_init(); + + if (setup_cache_server) + select_cache_server(); +} + +/* + * Request gvfs/config from main Git server. (Config data is not + * available from a GVFS cache-server.) + * + * Print the received server configuration (as the raw JSON string). + */ +static enum gh__error_code do_sub_cmd__config(int argc UNUSED, const char **argv UNUSED) +{ + struct gh__response_status status = GH__RESPONSE_STATUS_INIT; + struct strbuf config_data = STRBUF_INIT; + enum gh__error_code ec = GH__ERROR_CODE__OK; + + trace2_cmd_mode("config"); + + finish_init(0); + + do__http_get__gvfs_config(&status, &config_data); + ec = status.ec; + + if (ec == GH__ERROR_CODE__OK) + printf("%s\n", config_data.buf); + else + error("config: %s", status.error_message.buf); + + gh__response_status__release(&status); + strbuf_release(&config_data); + + return ec; +} + +static enum gh__error_code do_sub_cmd__endpoint(int argc, const char **argv) +{ + struct gh__response_status status = GH__RESPONSE_STATUS_INIT; + struct strbuf data = STRBUF_INIT; + enum gh__error_code ec = GH__ERROR_CODE__OK; + const char *endpoint; + + if (argc != 2) + return GH__ERROR_CODE__ERROR; + endpoint = argv[1]; + + trace2_cmd_mode(endpoint); + + finish_init(0); + + do__http_get__simple_endpoint(&status, &data, endpoint, endpoint); + ec = status.ec; + + if (ec == GH__ERROR_CODE__OK) + printf("%s\n", data.buf); + else + error("config: %s", status.error_message.buf); + + gh__response_status__release(&status); + strbuf_release(&data); + + return ec; +} + +/* + * Read a list of objects from stdin and fetch them as a series of + * single object HTTP GET requests. + */ +static enum gh__error_code do_sub_cmd__get(int argc, const char **argv) +{ + static struct option get_options[] = { + OPT_INTEGER('r', "max-retries", &gh__cmd_opts.max_retries, + N_("retries for transient network errors")), + OPT_END(), + }; + + struct gh__response_status status = GH__RESPONSE_STATUS_INIT; + struct oidset oids = OIDSET_INIT; + struct string_list result_list = STRING_LIST_INIT_DUP; + enum gh__error_code ec = GH__ERROR_CODE__OK; + unsigned long nr_oid_total; + size_t k; + + trace2_cmd_mode("get"); + + if (argc > 1 && !strcmp(argv[1], "-h")) + usage_with_options(objects_get_usage, get_options); + + argc = parse_options(argc, argv, NULL, get_options, objects_get_usage, 0); + if (gh__cmd_opts.max_retries < 0) + gh__cmd_opts.max_retries = 0; + + finish_init(1); + + nr_oid_total = read_stdin_for_oids(&oids); + + do__http_get__fetch_oidset(&status, &oids, nr_oid_total, &result_list); + + ec = status.ec; + + for (k = 0; k < result_list.nr; k++) + printf("%s\n", result_list.items[k].string); + + if (ec != GH__ERROR_CODE__OK) + error("get: %s", status.error_message.buf); + + gh__response_status__release(&status); + oidset_clear(&oids); + string_list_clear(&result_list, 0); + + return ec; +} + +/* + * Read a list of objects from stdin and fetch them in a single request (or + * multiple block-size requests) using one or more HTTP POST requests. + */ +static enum gh__error_code do_sub_cmd__post(int argc, const char **argv) +{ + static struct option post_options[] = { + OPT_UNSIGNED('b', "block-size", &gh__cmd_opts.block_size, + N_("number of objects to request at a time")), + OPT_INTEGER('d', "depth", &gh__cmd_opts.depth, + N_("Commit depth")), + OPT_INTEGER('r', "max-retries", &gh__cmd_opts.max_retries, + N_("retries for transient network errors")), + OPT_END(), + }; + + struct gh__response_status status = GH__RESPONSE_STATUS_INIT; + struct oidset oids = OIDSET_INIT; + struct string_list result_list = STRING_LIST_INIT_DUP; + enum gh__error_code ec = GH__ERROR_CODE__OK; + unsigned long nr_oid_total; + size_t k; + + trace2_cmd_mode("post"); + + if (argc > 1 && !strcmp(argv[1], "-h")) + usage_with_options(objects_post_usage, post_options); + + argc = parse_options(argc, argv, NULL, post_options, objects_post_usage, 0); + if (gh__cmd_opts.depth < 1) + gh__cmd_opts.depth = 1; + if (gh__cmd_opts.max_retries < 0) + gh__cmd_opts.max_retries = 0; + + finish_init(1); + + nr_oid_total = read_stdin_for_oids(&oids); + + do__http_post__fetch_oidset(&status, &oids, nr_oid_total, &result_list); + + ec = status.ec; + + for (k = 0; k < result_list.nr; k++) + printf("%s\n", result_list.items[k].string); + + if (ec != GH__ERROR_CODE__OK) + error("post: %s", status.error_message.buf); + + gh__response_status__release(&status); + oidset_clear(&oids); + string_list_clear(&result_list, 0); + + return ec; +} + +/* + * Interpret the given string as a timestamp and compute an absolute + * UTC-seconds-since-epoch value (and without TZ). + * + * Note that the gvfs/prefetch API only accepts seconds since epoch, + * so that is all we really need here. But there is a tradition of + * various Git commands allowing a variety of formats for args like + * this. For example, see the `--date` arg in `git commit`. We allow + * these other forms mainly for testing purposes. + */ +static int my_parse_since(const char *since, timestamp_t *p_timestamp) +{ + int offset = 0; + int errors = 0; + unsigned long t; + + if (!parse_date_basic(since, p_timestamp, &offset)) + return 0; + + t = approxidate_careful(since, &errors); + if (!errors) { + *p_timestamp = t; + return 0; + } + + return -1; +} + +/* + * Ask the server for all available packfiles -or- all available since + * the given timestamp. + */ +static enum gh__error_code do_sub_cmd__prefetch(int argc, const char **argv) +{ + static const char *since_str; + static struct option prefetch_options[] = { + OPT_STRING(0, "since", &since_str, N_("since"), N_("seconds since epoch")), + OPT_INTEGER('r', "max-retries", &gh__cmd_opts.max_retries, + N_("retries for transient network errors")), + OPT_END(), + }; + + struct gh__response_status status = GH__RESPONSE_STATUS_INIT; + struct string_list result_list = STRING_LIST_INIT_DUP; + enum gh__error_code ec = GH__ERROR_CODE__OK; + timestamp_t seconds_since_epoch = 0; + size_t k; + + trace2_cmd_mode("prefetch"); + + if (argc > 1 && !strcmp(argv[1], "-h")) + usage_with_options(prefetch_usage, prefetch_options); + + argc = parse_options(argc, argv, NULL, prefetch_options, prefetch_usage, 0); + if (since_str && *since_str) { + if (my_parse_since(since_str, &seconds_since_epoch)) + die("could not parse 'since' field"); + } + if (gh__cmd_opts.max_retries < 0) + gh__cmd_opts.max_retries = 0; + + finish_init(1); + + do__http_get__gvfs_prefetch(&status, seconds_since_epoch, &result_list); + + ec = status.ec; + + for (k = 0; k < result_list.nr; k++) + printf("%s\n", result_list.items[k].string); + + if (ec != GH__ERROR_CODE__OK) + error("prefetch: %s", status.error_message.buf); + + gh__response_status__release(&status); + string_list_clear(&result_list, 0); + + return ec; +} + +/* + * Handle the 'objects.get' and 'objects.post' and 'objects.prefetch' + * verbs in "server mode". + * + * Only call error() and set ec for hard errors where we cannot + * communicate correctly with the foreground client process. Pass any + * actual data errors (such as 404's or 401's from the fetch) back to + * the client process. + */ +static enum gh__error_code do_server_subprocess__objects(const char *verb_line) +{ + struct gh__response_status status = GH__RESPONSE_STATUS_INIT; + struct oidset oids = OIDSET_INIT; + struct object_id oid; + struct string_list result_list = STRING_LIST_INIT_DUP; + enum gh__error_code ec = GH__ERROR_CODE__OK; + char *line; + int len; + int err; + size_t k; + enum gh__objects_mode objects_mode; + unsigned long nr_oid_total = 0; + timestamp_t seconds_since_epoch = 0; + + if (!strcmp(verb_line, "objects.get")) + objects_mode = GH__OBJECTS_MODE__GET; + else if (!strcmp(verb_line, "objects.post")) + objects_mode = GH__OBJECTS_MODE__POST; + else if (!strcmp(verb_line, "objects.prefetch")) + objects_mode = GH__OBJECTS_MODE__PREFETCH; + else { + error("server: unexpected objects-mode verb '%s'", verb_line); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + + switch (objects_mode) { + case GH__OBJECTS_MODE__GET: + case GH__OBJECTS_MODE__POST: + while (1) { + len = packet_read_line_gently(0, NULL, &line); + if (len < 0 || !line) + break; + + if (get_oid_hex(line, &oid)) { + error("server: invalid oid syntax '%s'", line); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + + if (!oidset_insert(&oids, &oid)) + nr_oid_total++; + } + + if (!nr_oid_total) { + /* if zero objects requested, trivial OK. */ + if (packet_write_fmt_gently(1, "ok\n")) { + error("server: cannot write 'get' result to client"); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + } else + ec = GH__ERROR_CODE__OK; + goto cleanup; + } + + if (objects_mode == GH__OBJECTS_MODE__GET) + do__http_get__fetch_oidset(&status, &oids, + nr_oid_total, &result_list); + else + do__http_post__fetch_oidset(&status, &oids, + nr_oid_total, &result_list); + break; + + case GH__OBJECTS_MODE__PREFETCH: + /* get optional timestamp line */ + while (1) { + len = packet_read_line_gently(0, NULL, &line); + if (len < 0 || !line) + break; + + seconds_since_epoch = strtoul(line, NULL, 10); + } + + do__http_get__gvfs_prefetch(&status, seconds_since_epoch, + &result_list); + break; + + default: + BUG("unexpected object_mode in switch '%d'", objects_mode); + } + + /* + * Write pathname of the ODB where we wrote all of the objects + * we fetched. + */ + if (packet_write_fmt_gently(1, "odb %s\n", + gh__global.buf_odb_path.buf)) { + error("server: cannot write 'odb' to client"); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + + for (k = 0; k < result_list.nr; k++) + if (packet_write_fmt_gently(1, "%s\n", + result_list.items[k].string)) + { + error("server: cannot write result to client: '%s'", + result_list.items[k].string); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + + /* + * We only use status.ec to tell the client whether the request + * was complete, incomplete, or had IO errors. We DO NOT return + * this value to our caller. + */ + err = 0; + if (status.ec == GH__ERROR_CODE__OK) + err = packet_write_fmt_gently(1, "ok\n"); + else if (status.ec == GH__ERROR_CODE__HTTP_404) + err = packet_write_fmt_gently(1, "partial\n"); + else + err = packet_write_fmt_gently(1, "error %s\n", + status.error_message.buf); + if (err) { + error("server: cannot write result to client"); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + + if (packet_flush_gently(1)) { + error("server: cannot flush result to client"); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + +cleanup: + oidset_clear(&oids); + string_list_clear(&result_list, 0); + gh__response_status__release(&status); + + return ec; +} + +typedef enum gh__error_code (fn_subprocess_cmd)(const char *verb_line); + +struct subprocess_capability { + const char *name; + int client_has; + fn_subprocess_cmd *pfn; +}; + +static struct subprocess_capability caps[] = { + { "objects", 0, do_server_subprocess__objects }, + { NULL, 0, NULL }, +}; + +/* + * Handle the subprocess protocol handshake as described in: + * [] Documentation/technical/protocol-common.txt + * [] Documentation/technical/long-running-process-protocol.txt + */ +static int do_protocol_handshake(void) +{ +#define OUR_SUBPROCESS_VERSION "1" + + char *line; + int len; + int k; + int b_support_our_version = 0; + + len = packet_read_line_gently(0, NULL, &line); + if (len < 0 || !line || strcmp(line, "gvfs-helper-client")) { + error("server: subprocess welcome handshake failed: %s", line); + return -1; + } + + while (1) { + const char *v; + len = packet_read_line_gently(0, NULL, &line); + if (len < 0 || !line) + break; + if (!skip_prefix(line, "version=", &v)) { + error("server: subprocess version handshake failed: %s", + line); + return -1; + } + b_support_our_version |= (!strcmp(v, OUR_SUBPROCESS_VERSION)); + } + if (!b_support_our_version) { + error("server: client does not support our version: %s", + OUR_SUBPROCESS_VERSION); + return -1; + } + + if (packet_write_fmt_gently(1, "gvfs-helper-server\n") || + packet_write_fmt_gently(1, "version=%s\n", + OUR_SUBPROCESS_VERSION) || + packet_flush_gently(1)) { + error("server: cannot write version handshake"); + return -1; + } + + while (1) { + const char *v; + int k; + + len = packet_read_line_gently(0, NULL, &line); + if (len < 0 || !line) + break; + if (!skip_prefix(line, "capability=", &v)) { + error("server: subprocess capability handshake failed: %s", + line); + return -1; + } + for (k = 0; caps[k].name; k++) + if (!strcmp(v, caps[k].name)) + caps[k].client_has = 1; + } + + for (k = 0; caps[k].name; k++) + if (caps[k].client_has) + if (packet_write_fmt_gently(1, "capability=%s\n", + caps[k].name)) { + error("server: cannot write capabilities handshake: %s", + caps[k].name); + return -1; + } + if (packet_flush_gently(1)) { + error("server: cannot write capabilities handshake"); + return -1; + } + + return 0; +} + +/* + * Interactively listen to stdin for a series of commands and execute them. + */ +static enum gh__error_code do_sub_cmd__server(int argc, const char **argv) +{ + static struct option server_options[] = { + OPT_UNSIGNED('b', "block-size", &gh__cmd_opts.block_size, + N_("number of objects to request at a time")), + OPT_INTEGER('d', "depth", &gh__cmd_opts.depth, + N_("Commit depth")), + OPT_INTEGER('r', "max-retries", &gh__cmd_opts.max_retries, + N_("retries for transient network errors")), + OPT_END(), + }; + + enum gh__error_code ec = GH__ERROR_CODE__OK; + char *line; + int len; + int k; + + trace2_cmd_mode("server"); + + if (argc > 1 && !strcmp(argv[1], "-h")) + usage_with_options(server_usage, server_options); + + argc = parse_options(argc, argv, NULL, server_options, server_usage, 0); + if (gh__cmd_opts.depth < 1) + gh__cmd_opts.depth = 1; + if (gh__cmd_opts.max_retries < 0) + gh__cmd_opts.max_retries = 0; + + finish_init(1); + + if (do_protocol_handshake()) { + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + +top_of_loop: + while (1) { + len = packet_read_line_gently(0, NULL, &line); + if (len < 0 || !line) { + /* use extra FLUSH as a QUIT */ + ec = GH__ERROR_CODE__OK; + goto cleanup; + } + + for (k = 0; caps[k].name; k++) { + if (caps[k].client_has && + starts_with(line, caps[k].name)) { + ec = (caps[k].pfn)(line); + if (ec != GH__ERROR_CODE__OK) + goto cleanup; + goto top_of_loop; + } + } + + error("server: unknown command '%s'", line); + ec = GH__ERROR_CODE__SUBPROCESS_SYNTAX; + goto cleanup; + } + +cleanup: + return ec; +} + +static enum gh__error_code do_sub_cmd(int argc, const char **argv) +{ + if (!strcmp(argv[0], "get")) + return do_sub_cmd__get(argc, argv); + + if (!strcmp(argv[0], "post")) + return do_sub_cmd__post(argc, argv); + + if (!strcmp(argv[0], "config")) + return do_sub_cmd__config(argc, argv); + + if (!strcmp(argv[0], "endpoint")) + return do_sub_cmd__endpoint(argc, argv); + + if (!strcmp(argv[0], "prefetch")) + return do_sub_cmd__prefetch(argc, argv); + + /* + * server mode is for talking with git.exe via the "gh_client_" API + * using packet-line format. + */ + if (!strcmp(argv[0], "server")) + return do_sub_cmd__server(argc, argv); + + return GH__ERROR_CODE__USAGE; +} + +/* + * Communicate with the primary Git server or a GVFS cache-server using the + * GVFS Protocol. + * + * https://github.com/microsoft/VFSForGit/blob/master/Protocol.md + */ +int cmd_main(int argc, const char **argv) +{ + static struct option main_options[] = { + OPT_STRING('r', "remote", &gh__cmd_opts.remote_name, + N_("remote"), + N_("Remote name")), + OPT_BOOL('f', "fallback", &gh__cmd_opts.try_fallback, + N_("Fallback to Git server if cache-server fails")), + OPT_CALLBACK(0, "cache-server", NULL, + N_("cache-server"), + N_("cache-server=disable|trust|verify|error"), + option_parse_cache_server_mode), + OPT_CALLBACK(0, "shared-cache", NULL, + N_("pathname"), + N_("Pathname to shared objects directory"), + option_parse_shared_cache_directory), + OPT_BOOL('p', "progress", &gh__cmd_opts.show_progress, + N_("Show progress")), + OPT_END(), + }; + + enum gh__error_code ec = GH__ERROR_CODE__OK; + + if (argc > 1 && !strcmp(argv[1], "-h")) + usage_with_options(main_usage, main_options); + + trace2_cmd_name("gvfs-helper"); + packet_trace_identity("gvfs-helper"); + + setup_git_directory_gently(NULL); + + /* Set any non-zero initial values in gh__cmd_opts. */ + gh__cmd_opts.depth = GH__DEFAULT__OBJECTS_POST__COMMIT_DEPTH; + gh__cmd_opts.block_size = GH__DEFAULT__OBJECTS_POST__BLOCK_SIZE; + gh__cmd_opts.max_retries = GH__DEFAULT_MAX_RETRIES; + gh__cmd_opts.max_transient_backoff_sec = + GH__DEFAULT_MAX_TRANSIENT_BACKOFF_SEC; + + gh__cmd_opts.show_progress = !!isatty(2); + + // TODO use existing gvfs config settings to override our GH__DEFAULT_ + // TODO values in gh__cmd_opts. (And maybe add/remove our command line + // TODO options for them.) + // TODO + // TODO See "scalar.max-retries" (and maybe "gvfs.max-retries") + + git_config(git_default_config, NULL); + + argc = parse_options(argc, argv, NULL, main_options, main_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + if (argc == 0) + usage_with_options(main_usage, main_options); + + ec = do_sub_cmd(argc, argv); + + gh_http_cleanup(); + + if (ec == GH__ERROR_CODE__USAGE) + usage_with_options(main_usage, main_options); + + return ec; +} diff --git a/gvfs.c b/gvfs.c new file mode 100644 index 00000000000000..11635237893968 --- /dev/null +++ b/gvfs.c @@ -0,0 +1,43 @@ +#define USE_THE_REPOSITORY_VARIABLE +#include "git-compat-util.h" +#include "environment.h" +#include "gvfs.h" +#include "setup.h" +#include "config.h" + +static int gvfs_config_loaded; +static int core_gvfs_is_bool; + +static int early_core_gvfs_config(const char *var, const char *value, + const struct config_context *ctx, void *cb UNUSED) +{ + if (!strcmp(var, "core.gvfs")) + core_gvfs = git_config_bool_or_int("core.gvfs", value, ctx->kvi, + &core_gvfs_is_bool); + return 0; +} + +void gvfs_load_config_value(const char *value) +{ + if (value) { + struct key_value_info default_kvi = KVI_INIT; + core_gvfs = git_config_bool_or_int("core.gvfs", value, &default_kvi, &core_gvfs_is_bool); + } else if (startup_info->have_repository == 0) + read_early_config(the_repository, early_core_gvfs_config, NULL); + else + repo_config_get_bool_or_int(the_repository, "core.gvfs", + &core_gvfs_is_bool, &core_gvfs); + + /* Turn on all bits if a bool was set in the settings */ + if (core_gvfs_is_bool && core_gvfs) + core_gvfs = -1; +} + +int gvfs_config_is_set(int mask) +{ + if (!gvfs_config_loaded) + gvfs_load_config_value(NULL); + + gvfs_config_loaded = 1; + return (core_gvfs & mask) == mask; +} diff --git a/gvfs.h b/gvfs.h new file mode 100644 index 00000000000000..07cb0722e44a03 --- /dev/null +++ b/gvfs.h @@ -0,0 +1,38 @@ +#ifndef GVFS_H +#define GVFS_H + + +/* + * This file is for the specific settings and methods + * used for GVFS functionality + */ + + +/* + * The list of bits in the core_gvfs setting + */ +#define GVFS_SKIP_SHA_ON_INDEX (1 << 0) +#define GVFS_BLOCK_COMMANDS (1 << 1) +#define GVFS_MISSING_OK (1 << 2) + +/* + * This behavior of not deleting outside of the sparse-checkout + * is specific to the virtual filesystem support. It is only + * enabled by VFS for Git, and so can be used as an indicator + * that we are in a virtualized filesystem environment and not + * in a Scalar environment. This bit has two names to reflect + * that. + */ +#define GVFS_NO_DELETE_OUTSIDE_SPARSECHECKOUT (1 << 3) +#define GVFS_USE_VIRTUAL_FILESYSTEM (1 << 3) + +#define GVFS_FETCH_SKIP_REACHABILITY_AND_UPLOADPACK (1 << 4) +#define GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS (1 << 6) +#define GVFS_PREFETCH_DURING_FETCH (1 << 7) + +#define GVFS_ANY_MASK 0xFFFFFFFF + +void gvfs_load_config_value(const char *value); +int gvfs_config_is_set(int mask); + +#endif /* GVFS_H */ diff --git a/help.c b/help.c index 21b778707a6a65..d6a2e78eb92eab 100644 --- a/help.c +++ b/help.c @@ -769,6 +769,22 @@ char *help_unknown_cmd(const char *cmd) exit(1); } +#if defined(__APPLE__) +static const char *git_host_cpu(void) { + if (!strcmp(GIT_HOST_CPU, "universal")) { +#if defined(__x86_64__) + return "x86_64"; +#elif defined(__aarch64__) + return "arm64"; +#endif + } + + return GIT_HOST_CPU; +} +#undef GIT_HOST_CPU +#define GIT_HOST_CPU git_host_cpu() +#endif + void get_version_info(struct strbuf *buf, int show_build_options) { /* diff --git a/hook.c b/hook.c index b3de1048bf44b9..be69f6a4527662 100644 --- a/hook.c +++ b/hook.c @@ -1,5 +1,9 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" +#include "trace2/tr2_sid.h" #include "abspath.h" +#include "environment.h" #include "advice.h" #include "gettext.h" #include "hook.h" @@ -10,13 +14,66 @@ #include "environment.h" #include "setup.h" +static int early_hooks_path_config(const char *var, const char *value, + const struct config_context *ctx UNUSED, void *cb) +{ + if (!strcmp(var, "core.hookspath")) + return git_config_pathname((char **)cb, var, value); + + return 0; +} + +/* Discover the hook before setup_git_directory() was called */ +static const char *hook_path_early(const char *name, struct strbuf *result) +{ + static struct strbuf hooks_dir = STRBUF_INIT; + static int initialized; + + if (initialized < 0) + return NULL; + + if (!initialized) { + struct strbuf gitdir = STRBUF_INIT, commondir = STRBUF_INIT; + char *early_hooks_dir = NULL; + + if (discover_git_directory(&commondir, &gitdir) < 0) { + strbuf_release(&gitdir); + strbuf_release(&commondir); + initialized = -1; + return NULL; + } + + read_early_config(the_repository, early_hooks_path_config, &early_hooks_dir); + if (!early_hooks_dir) + strbuf_addf(&hooks_dir, "%s/hooks/", commondir.buf); + else { + strbuf_add_absolute_path(&hooks_dir, early_hooks_dir); + free(early_hooks_dir); + strbuf_addch(&hooks_dir, '/'); + } + + strbuf_release(&gitdir); + strbuf_release(&commondir); + + initialized = 1; + } + + strbuf_addf(result, "%s%s", hooks_dir.buf, name); + return result->buf; +} + const char *find_hook(struct repository *r, const char *name) { static struct strbuf path = STRBUF_INIT; int found_hook; - repo_git_path_replace(r, &path, "hooks/%s", name); + strbuf_reset(&path); + if (have_git_dir()) + repo_git_path_replace(r, &path, "hooks/%s", name); + else if (!hook_path_early(name, &path)) + return NULL; + found_hook = access(path.buf, X_OK) >= 0; #ifdef STRIP_EXTENSION if (!found_hook) { @@ -120,6 +177,93 @@ static void run_hooks_opt_clear(struct run_hooks_opt *options) strvec_clear(&options->args); } +static char *get_post_index_change_sentinel_name(struct repository *r) +{ + struct strbuf path = STRBUF_INIT; + const char *sid = tr2_sid_get(); + char *slash = strchr(sid, '/'); + + /* + * Name is based on top-level SID, so children can indicate that + * the top-level process should run the post-command hook. + */ + if (slash) + *slash = 0; + + /* + * Do not write to hooks directory, as it could be redirected + * somewhere like the source tree. + */ + repo_git_path_replace(r, &path, "info/index-change-%s.snt", sid); + + return strbuf_detach(&path, NULL); +} + +static int write_post_index_change_sentinel(struct repository *r) +{ + char *path = get_post_index_change_sentinel_name(r); + FILE *fp = xfopen(path, "w"); + + if (fp) { + fprintf(fp, "run post-command hook"); + fclose(fp); + } + + free(path); + return fp ? 0 : -1; +} + +/** + * Try to delete the sentinel file for this repository. If that succeeds, then + * return 1. + */ +static int post_index_change_sentinel_exists(struct repository *r) +{ + char *path = get_post_index_change_sentinel_name(r); + int res = 1; + + if (unlink(path)) { + if (is_missing_file_error(errno)) + res = 0; + else + warning_errno("failed to remove index-change sentinel file '%s'", path); + } + + free(path); + return res; +} + +/** + * See if we can replace the requested hook with an internal behavior. + * Returns 0 if the real hook should run. Returns nonzero if we instead + * executed custom internal behavior and the real hook should not run. + */ +static int handle_hook_replacement(struct repository *r, + const char *hook_name, + struct strvec *args) +{ + const char *strval; + if (repo_config_get_string_tmp(r, "postcommand.strategy", &strval) || + strcasecmp(strval, "worktree-change")) + return 0; + + if (!strcmp(hook_name, "post-index-change")) { + /* Create a sentinel file only if the worktree changed. */ + if (!strcmp(args->v[0], "1")) + write_post_index_change_sentinel(r); + + /* We don't skip post-index-change hooks that exist. */ + return 0; + } + if (!strcmp(hook_name, "post-command") && + !post_index_change_sentinel_exists(r)) { + /* We skip the post-command hook in this case. */ + return 1; + } + + return 0; +} + int run_hooks_opt(struct repository *r, const char *hook_name, struct run_hooks_opt *options) { @@ -129,7 +273,7 @@ int run_hooks_opt(struct repository *r, const char *hook_name, .hook_name = hook_name, .options = options, }; - const char *const hook_path = find_hook(r, hook_name); + const char *hook_path; int ret = 0; const struct run_process_parallel_opts opts = { .tr2_category = "hook", @@ -145,6 +289,25 @@ int run_hooks_opt(struct repository *r, const char *hook_name, .data = &cb_data, }; + /* Interject hook behavior depending on strategy. */ + if (r && r->gitdir && + handle_hook_replacement(r, hook_name, &options->args)) + return 0; + + hook_path = find_hook(r, hook_name); + + /* + * Backwards compatibility hack in VFS for Git: when originally + * introduced (and used!), it was called `post-indexchanged`, but this + * name was changed during the review on the Git mailing list. + * + * Therefore, when the `post-index-change` hook is not found, let's + * look for a hook with the old name (which would be found in case of + * already-existing checkouts). + */ + if (!hook_path && !strcmp(hook_name, "post-index-change")) + hook_path = find_hook(r, "post-indexchanged"); + if (!options) BUG("a struct run_hooks_opt must be provided to run_hooks"); @@ -184,6 +347,7 @@ int run_hooks_l(struct repository *r, const char *hook_name, ...) { struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; va_list ap; + int result; const char *arg; va_start(ap, hook_name); @@ -191,5 +355,7 @@ int run_hooks_l(struct repository *r, const char *hook_name, ...) strvec_push(&opt.args, arg); va_end(ap); - return run_hooks_opt(r, hook_name, &opt); + result = run_hooks_opt(r, hook_name, &opt); + strvec_clear(&opt.args); + return result; } diff --git a/http-push.c b/http-push.c index 56db9ce8edff77..f5a92529a8406b 100644 --- a/http-push.c +++ b/http-push.c @@ -195,7 +195,7 @@ static char *xml_entities(const char *s) static void curl_setup_http_get(CURL *curl, const char *url, const char *custom_req) { - curl_easy_setopt(curl, CURLOPT_HTTPGET, 1l); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_null); @@ -205,7 +205,7 @@ static void curl_setup_http(CURL *curl, const char *url, const char *custom_req, struct buffer *buffer, curl_write_callback write_fn) { - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1l); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_INFILE, buffer); curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len); @@ -213,9 +213,9 @@ static void curl_setup_http(CURL *curl, const char *url, curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer); curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn); - curl_easy_setopt(curl, CURLOPT_NOBODY, 0l); + curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1l); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); } static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options) diff --git a/http.c b/http.c index 37cf43e746c01b..6d06c6c463f9f8 100644 --- a/http.c +++ b/http.c @@ -147,7 +147,7 @@ static char *cached_accept_language; static char *http_ssl_backend; -static int http_schannel_check_revoke_mode = +static long http_schannel_check_revoke_mode = #ifdef CURLSSLOPT_REVOKE_BEST_EFFORT CURLSSLOPT_REVOKE_BEST_EFFORT; #else @@ -1044,13 +1044,13 @@ static CURL *get_curl_handle(void) die("curl_easy_init failed"); if (!curl_ssl_verify) { - curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0l); - curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0l); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0L); } else { /* Verify authenticity of the peer's certificate */ - curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1l); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1L); /* The name in the cert must match whom we tried to connect */ - curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2l); + curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2L); } if (curl_http_version) { @@ -1153,7 +1153,7 @@ static CURL *get_curl_handle(void) curl_low_speed_time); } - curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20l); + curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20L); curl_easy_setopt(result, CURLOPT_POSTREDIR, (long)CURL_REDIR_POST_ALL); #ifdef GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR @@ -1187,7 +1187,7 @@ static CURL *get_curl_handle(void) user_agent ? user_agent : git_user_agent()); if (curl_ftp_no_epsv) - curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0l); + curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0L); if (curl_ssl_try) curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY); @@ -1290,7 +1290,7 @@ static CURL *get_curl_handle(void) } init_curl_proxy_auth(result); - curl_easy_setopt(result, CURLOPT_TCP_KEEPALIVE, 1l); + curl_easy_setopt(result, CURLOPT_TCP_KEEPALIVE, 1L); if (curl_tcp_keepidle > -1) curl_easy_setopt(result, CURLOPT_TCP_KEEPIDLE, @@ -1576,9 +1576,9 @@ struct active_request_slot *get_active_slot(void) curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, NULL); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL); curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, -1L); - curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0l); - curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1l); - curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1l); + curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0L); + curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1L); curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL); /* @@ -1587,9 +1587,9 @@ struct active_request_slot *get_active_slot(void) * HTTP_FOLLOW_* cases themselves. */ if (http_follow_config == HTTP_FOLLOW_ALWAYS) - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1l); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L); else - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0l); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 0L); curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve); curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods); @@ -2156,12 +2156,12 @@ static int http_request(const char *url, int ret; slot = get_active_slot(); - curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1l); + curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1L); if (!result) { - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1l); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1L); } else { - curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0l); + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, result); if (target == HTTP_REQUEST_FILE) { @@ -2187,7 +2187,7 @@ static int http_request(const char *url, strbuf_addstr(&buf, " no-cache"); if (options && options->initial_request && http_follow_config == HTTP_FOLLOW_INITIAL) - curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1l); + curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1L); headers = curl_slist_append(headers, buf.buf); @@ -2206,7 +2206,7 @@ static int http_request(const char *url, curl_easy_setopt(slot->curl, CURLOPT_URL, url); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(slot->curl, CURLOPT_ENCODING, ""); - curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0l); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0L); ret = run_one_slot(slot, &results); @@ -2786,7 +2786,7 @@ struct http_object_request *new_http_object_request(const char *base_url, freq->headers = object_request_headers(); curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEDATA, freq); - curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0l); + curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0L); curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file); curl_easy_setopt(freq->slot->curl, CURLOPT_ERRORBUFFER, freq->errorstr); curl_easy_setopt(freq->slot->curl, CURLOPT_URL, freq->url); diff --git a/json-parser.c b/json-parser.c new file mode 100644 index 00000000000000..5d8cd182fb4747 --- /dev/null +++ b/json-parser.c @@ -0,0 +1,191 @@ +#include "git-compat-util.h" +#include "hex.h" +#include "json-parser.h" + +int reset_iterator(struct json_iterator *it) +{ + it->p = it->begin = it->json; + strbuf_release(&it->key); + strbuf_release(&it->string_value); + it->type = JSON_NULL; + return -1; +} + +static int parse_json_string(struct json_iterator *it, struct strbuf *out) +{ + const char *begin = it->p; + + if (*(it->p)++ != '"') { + error("expected double quote: '%.*s'", 5, begin); + return reset_iterator(it); + } + + strbuf_reset(&it->string_value); +#define APPEND(c) strbuf_addch(out, c) + while (*it->p != '"') { + switch (*it->p) { + case '\0': + error("incomplete string: '%s'", begin); + return reset_iterator(it); + case '\\': + it->p++; + if (*it->p == '\\' || *it->p == '"') + APPEND(*it->p); + else if (*it->p == 'b') + APPEND(8); + else if (*it->p == 't') + APPEND(9); + else if (*it->p == 'n') + APPEND(10); + else if (*it->p == 'f') + APPEND(12); + else if (*it->p == 'r') + APPEND(13); + else if (*it->p == 'u') { + unsigned char binary[2]; + int i; + + if (hex_to_bytes(binary, it->p + 1, 2) < 0) { + error("invalid: '%.*s'", 6, it->p - 1); + return reset_iterator(it); + } + it->p += 4; + + i = (binary[0] << 8) | binary[1]; + if (i < 0x80) + APPEND(i); + else if (i < 0x0800) { + APPEND(0xc0 | ((i >> 6) & 0x1f)); + APPEND(0x80 | (i & 0x3f)); + } else if (i < 0x10000) { + APPEND(0xe0 | ((i >> 12) & 0x0f)); + APPEND(0x80 | ((i >> 6) & 0x3f)); + APPEND(0x80 | (i & 0x3f)); + } else { + APPEND(0xf0 | ((i >> 18) & 0x07)); + APPEND(0x80 | ((i >> 12) & 0x3f)); + APPEND(0x80 | ((i >> 6) & 0x3f)); + APPEND(0x80 | (i & 0x3f)); + } + } + break; + default: + APPEND(*it->p); + } + it->p++; + } + + it->end = it->p++; + return 0; +} + +static void skip_whitespace(struct json_iterator *it) +{ + while (isspace(*it->p)) + it->p++; +} + +int iterate_json(struct json_iterator *it) +{ + skip_whitespace(it); + it->begin = it->p; + + switch (*it->p) { + case '\0': + reset_iterator(it); + return 0; + case 'n': + if (!starts_with(it->p, "null")) { + error("unexpected value: %.*s", 4, it->p); + return reset_iterator(it); + } + it->type = JSON_NULL; + it->end = it->p = it->begin + 4; + break; + case 't': + if (!starts_with(it->p, "true")) { + error("unexpected value: %.*s", 4, it->p); + return reset_iterator(it); + } + it->type = JSON_TRUE; + it->end = it->p = it->begin + 4; + break; + case 'f': + if (!starts_with(it->p, "false")) { + error("unexpected value: %.*s", 5, it->p); + return reset_iterator(it); + } + it->type = JSON_FALSE; + it->end = it->p = it->begin + 5; + break; + case '-': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + it->type = JSON_NUMBER; + it->end = it->p = it->begin + strspn(it->p, "-.0123456789"); + break; + case '"': + it->type = JSON_STRING; + if (parse_json_string(it, &it->string_value) < 0) + return -1; + break; + case '[': { + const char *save = it->begin; + size_t key_offset = it->key.len; + int i = 0, res; + + for (it->p++, skip_whitespace(it); *it->p != ']'; i++) { + strbuf_addf(&it->key, "[%d]", i); + + if ((res = iterate_json(it))) { + reset_iterator(it); + return res; + } + strbuf_setlen(&it->key, key_offset); + + skip_whitespace(it); + if (*it->p == ',') + it->p++; + } + + it->type = JSON_ARRAY; + it->begin = save; + it->end = it->p; + it->p++; + break; + } + case '{': { + const char *save = it->begin; + size_t key_offset = it->key.len; + int res; + + strbuf_addch(&it->key, '.'); + for (it->p++, skip_whitespace(it); *it->p != '}'; ) { + strbuf_setlen(&it->key, key_offset + 1); + if (parse_json_string(it, &it->key) < 0) + return -1; + skip_whitespace(it); + if (*(it->p)++ != ':') { + error("expected colon: %.*s", 5, it->p); + return reset_iterator(it); + } + + if ((res = iterate_json(it))) + return res; + + skip_whitespace(it); + if (*it->p == ',') + it->p++; + } + strbuf_setlen(&it->key, key_offset); + + it->type = JSON_OBJECT; + it->begin = save; + it->end = it->p; + it->p++; + break; + } + } + + return it->fn(it); +} diff --git a/json-parser.h b/json-parser.h new file mode 100644 index 00000000000000..cb1f4832273e57 --- /dev/null +++ b/json-parser.h @@ -0,0 +1,31 @@ +#ifndef JSON_PARSER_H +#define JSON_PARSER_H + +#include "strbuf.h" + +struct json_iterator { + const char *json, *p, *begin, *end; + struct strbuf key, string_value; + enum { + JSON_NULL = 0, + JSON_FALSE, + JSON_TRUE, + JSON_NUMBER, + JSON_STRING, + JSON_ARRAY, + JSON_OBJECT + } type; + int (*fn)(struct json_iterator *it); + void *fn_data; +}; +#define JSON_ITERATOR_INIT(json_, fn_, fn_data_) { \ + .json = json_, .p = json_, \ + .key = STRBUF_INIT, .string_value = STRBUF_INIT, \ + .fn = fn_, .fn_data = fn_data_ \ +} + +int iterate_json(struct json_iterator *it); +/* Releases the iterator, always returns -1 */ +int reset_iterator(struct json_iterator *it); + +#endif diff --git a/merge-ort.c b/merge-ort.c index 47b3d1730ece36..f9e96d73809f98 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4568,7 +4568,8 @@ static int record_conflicted_index_entries(struct merge_options *opt) */ strmap_for_each_entry(&opt->priv->conflicted, &iter, e) { if (!path_in_sparse_checkout(e->key, index)) { - ensure_full_index(index); + const char *fmt = "merge-ort: path outside sparse checkout (%s)"; + ensure_full_index_with_reason(index, fmt, e->key); break; } } diff --git a/meson.build b/meson.build index 96ac729a122ce7..4e7a027734254c 100644 --- a/meson.build +++ b/meson.build @@ -353,6 +353,8 @@ libgit_sources = [ 'gpg-interface.c', 'graph.c', 'grep.c', + 'gvfs.c', + 'gvfs-helper-client.c', 'hash-lookup.c', 'hash.c', 'hashmap.c', @@ -525,6 +527,7 @@ libgit_sources = [ 'varint.c', 'version.c', 'versioncmp.c', + 'virtualfilesystem.c', 'walker.c', 'wildmatch.c', 'worktree.c', @@ -532,6 +535,8 @@ libgit_sources = [ 'write-or-die.c', 'ws.c', 'wt-status.c', + 'wt-status-deserialize.c', + 'wt-status-serialize.c', 'xdiff-interface.c', 'xdiff/xdiffi.c', 'xdiff/xemit.c', @@ -666,6 +671,7 @@ builtin_sources = [ 'builtin/unpack-file.c', 'builtin/unpack-objects.c', 'builtin/update-index.c', + 'builtin/update-microsoft-git.c', 'builtin/update-ref.c', 'builtin/update-server-info.c', 'builtin/upload-archive.c', @@ -1780,7 +1786,7 @@ test_dependencies += executable('git-http-backend', ) bin_wrappers += executable('scalar', - sources: 'scalar.c', + sources: ['scalar.c', 'json-parser.c'], dependencies: [libgit_commonmain], install: true, install_dir: get_option('libexecdir') / 'git-core', @@ -1818,6 +1824,13 @@ if curl.found() ) endif + test_dependencies += executable('git-gvfs-helper', + sources: 'gvfs-helper.c', + dependencies: [libgit_curl], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + foreach alias : [ 'git-remote-https', 'git-remote-ftp', 'git-remote-ftps' ] test_dependencies += executable(alias, sources: 'remote-curl.c', @@ -1852,6 +1865,7 @@ endforeach foreach symlink : [ 'git', + 'git-gvfs-helper', 'git-receive-pack', 'git-shell', 'git-upload-archive', diff --git a/name-hash.c b/name-hash.c index b91e276267891e..95d1b2ef371a18 100644 --- a/name-hash.c +++ b/name-hash.c @@ -749,6 +749,26 @@ struct cache_entry *index_file_exists(struct index_state *istate, const char *na return NULL; } +struct cache_entry *index_file_next_match(struct index_state *istate, struct cache_entry *ce, int igncase) +{ + struct cache_entry *next; + + if (!igncase || !ce) { + return NULL; + } + + next = hashmap_get_next_entry(&istate->name_hash, ce, ent); + if (!next) + return NULL; + + hashmap_for_each_entry_from(&istate->name_hash, next, ent) { + if (same_name(next, ce->name, ce_namelen(ce), igncase)) + return next; + } + + return NULL; +} + void free_name_hash(struct index_state *istate) { if (!istate->name_hash_initialized) diff --git a/name-hash.h b/name-hash.h index 0cbfc4286316b2..d808eba3e3b672 100644 --- a/name-hash.h +++ b/name-hash.h @@ -12,6 +12,7 @@ int index_dir_find(struct index_state *istate, const char *name, int namelen, void adjust_dirname_case(struct index_state *istate, char *name); struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase); +struct cache_entry *index_file_next_match(struct index_state *istate, struct cache_entry *ce, int igncase); int test_lazy_init_name_hash(struct index_state *istate, int try_threaded); void add_name_hash(struct index_state *istate, struct cache_entry *ce); diff --git a/object-file.c b/object-file.c index 1644a0d98533da..07bc2cd8bf8050 100644 --- a/object-file.c +++ b/object-file.c @@ -114,10 +114,23 @@ static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen) return 0; } -static int check_and_freshen(const struct object_id *oid, int freshen) +static int check_and_freshen(const struct object_id *oid, int freshen, + int skip_virtualized_objects) { - return check_and_freshen_local(oid, freshen) || + int ret; + int tried_hook = 0; + +retry: + ret = check_and_freshen_local(oid, freshen) || check_and_freshen_nonlocal(oid, freshen); + if (!ret && core_virtualize_objects && !skip_virtualized_objects && + !tried_hook) { + tried_hook = 1; + if (!read_object_process(oid)) + goto retry; + } + + return ret; } int has_loose_object_nonlocal(const struct object_id *oid) @@ -127,7 +140,7 @@ int has_loose_object_nonlocal(const struct object_id *oid) int has_loose_object(const struct object_id *oid) { - return check_and_freshen(oid, 0); + return check_and_freshen(oid, 0, 0); } int format_object_header(char *str, size_t size, enum object_type type, @@ -920,9 +933,10 @@ static int write_loose_object(const struct object_id *oid, char *hdr, FOF_SKIP_COLLISION_CHECK); } -static int freshen_loose_object(const struct object_id *oid) +static int freshen_loose_object(const struct object_id *oid, + int skip_virtualized_objects) { - return check_and_freshen(oid, 1); + return check_and_freshen(oid, 1, skip_virtualized_objects); } static int freshen_packed_object(const struct object_id *oid) @@ -1018,7 +1032,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len, die(_("deflateEnd on stream object failed (%d)"), ret); close_loose_object(fd, tmp_file.buf); - if (freshen_packed_object(oid) || freshen_loose_object(oid)) { + if (freshen_packed_object(oid) || freshen_loose_object(oid, 1)) { unlink_or_warn(tmp_file.buf); goto cleanup; } @@ -1081,7 +1095,7 @@ int write_object_file_flags(const void *buf, size_t len, * it out into .git/objects/??/?{38} file. */ write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); - if (freshen_packed_object(oid) || freshen_loose_object(oid)) + if (freshen_packed_object(oid) || freshen_loose_object(oid, 1)) return 0; if (write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags)) return -1; @@ -1492,6 +1506,13 @@ struct oidtree *odb_loose_cache(struct object_directory *odb, return odb->loose_objects_cache; } +void odb_loose_cache_add_new_oid(struct object_directory *odb, + const struct object_id *oid) +{ + struct oidtree *cache = odb_loose_cache(odb, oid); + append_loose_object(oid, NULL, cache); +} + void odb_clear_loose_cache(struct object_directory *odb) { oidtree_clear(odb->loose_objects_cache); diff --git a/object-file.h b/object-file.h index 185a3a3381ee38..81df036930e5a1 100644 --- a/object-file.h +++ b/object-file.h @@ -33,6 +33,14 @@ struct object_directory; struct oidtree *odb_loose_cache(struct object_directory *odb, const struct object_id *oid); +/* + * Add a new object to the loose object cache (possibly after the + * cache was populated). This might be used after dynamically + * fetching a missing object. + */ +void odb_loose_cache_add_new_oid(struct object_directory *odb, + const struct object_id *oid); + /* Empty the loose object cache for the specified object directory. */ void odb_clear_loose_cache(struct object_directory *odb); diff --git a/object-store.c b/object-store.c index 58cde0313a5533..188768864c06b4 100644 --- a/object-store.c +++ b/object-store.c @@ -7,7 +7,9 @@ #include "dir.h" #include "environment.h" #include "gettext.h" +#include "gvfs-helper-client.h" #include "hex.h" +#include "hook.h" #include "khash.h" #include "lockfile.h" #include "loose.h" @@ -16,14 +18,19 @@ #include "object-store.h" #include "packfile.h" #include "path.h" +#include "pkt-line.h" #include "promisor-remote.h" #include "quote.h" #include "replace-object.h" #include "run-command.h" #include "setup.h" +#include "sigchain.h" #include "strbuf.h" #include "strvec.h" +#include "sub-process.h" #include "submodule.h" +#include "trace.h" +#include "trace2.h" #include "write-or-die.h" KHASH_INIT(odb_path_map, const char * /* key: odb_path */, @@ -83,6 +90,8 @@ int odb_mkstemp(struct strbuf *temp_filename, const char *pattern) return xmkstemp_mode(temp_filename->buf, mode); } +static int gvfs_matched_shared_cache_to_alternate; + /* * Return non-zero iff the path is usable as an alternate object database. */ @@ -92,6 +101,52 @@ static int alt_odb_usable(struct raw_object_store *o, { int r; + if (!strbuf_cmp(path, &gvfs_shared_cache_pathname)) { + /* + * `gvfs.sharedCache` is the preferred alternate that we + * will use with `gvfs-helper.exe` to dynamically fetch + * missing objects. It is set during git_default_config(). + * + * Make sure the directory exists on disk before we let the + * stock code discredit it. + */ + struct strbuf buf_pack_foo = STRBUF_INIT; + enum scld_error scld; + + /* + * Force create the "" and "/pack" directories, if + * not present on disk. Append an extra bogus directory to + * get safe_create_leading_directories() to see "/pack" + * as a leading directory of something deeper (which it + * won't create). + */ + strbuf_addf(&buf_pack_foo, "%s/pack/foo", path->buf); + + scld = safe_create_leading_directories(the_repository, buf_pack_foo.buf); + if (scld != SCLD_OK && scld != SCLD_EXISTS) { + error_errno(_("could not create shared-cache ODB '%s'"), + gvfs_shared_cache_pathname.buf); + + strbuf_release(&buf_pack_foo); + + /* + * Pretend no shared-cache was requested and + * effectively fallback to ".git/objects" for + * fetching missing objects. + */ + strbuf_release(&gvfs_shared_cache_pathname); + return 0; + } + + /* + * We know that there is an alternate (either from + * .git/objects/info/alternates or from a memory-only + * entry) associated with the shared-cache directory. + */ + gvfs_matched_shared_cache_to_alternate++; + strbuf_release(&buf_pack_foo); + } + /* Detect cases where alternate disappeared */ if (!is_directory(path->buf)) { error(_("object directory %s does not exist; " @@ -583,6 +638,33 @@ void prepare_alt_odb(struct repository *r) link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0); read_info_alternates(r, r->objects->odb->path, 0); + + if (gvfs_shared_cache_pathname.len && + !gvfs_matched_shared_cache_to_alternate) { + /* + * There is no entry in .git/objects/info/alternates for + * the requested shared-cache directory. Therefore, the + * odb-list does not contain this directory. + * + * Force this directory into the odb-list as an in-memory + * alternate. Implicitly create the directory on disk, if + * necessary. + * + * See GIT_ALTERNATE_OBJECT_DIRECTORIES for another example + * of this kind of usage. + * + * Note: This has the net-effect of allowing Git to treat + * `gvfs.sharedCache` as an unofficial alternate. This + * usage should be discouraged for compatbility reasons + * with other tools in the overall Git ecosystem (that + * won't know about this trick). It would be much better + * for us to update .git/objects/info/alternates instead. + * The code here is considered a backstop. + */ + link_alt_odb_entries(r, gvfs_shared_cache_pathname.buf, + '\n', NULL, 0); + } + r->objects->loaded_alternates = 1; } @@ -592,6 +674,125 @@ int has_alt_odb(struct repository *r) return !!r->objects->odb->next; } +#define CAP_GET (1u<<0) + +static int subprocess_map_initialized; +static struct hashmap subprocess_map; + +struct read_object_process { + struct subprocess_entry subprocess; + unsigned int supported_capabilities; +}; + +static int start_read_object_fn(struct subprocess_entry *subprocess) +{ + struct read_object_process *entry = (struct read_object_process *)subprocess; + static int versions[] = {1, 0}; + static struct subprocess_capability capabilities[] = { + { "get", CAP_GET }, + { NULL, 0 } + }; + + return subprocess_handshake(subprocess, "git-read-object", versions, + NULL, capabilities, + &entry->supported_capabilities); +} + +int read_object_process(const struct object_id *oid) +{ + int err; + struct read_object_process *entry; + struct child_process *process; + struct strbuf status = STRBUF_INIT; + const char *cmd = find_hook(the_repository, "read-object"); + uint64_t start; + + start = getnanotime(); + + trace2_region_enter("subprocess", "read_object", the_repository); + + if (!subprocess_map_initialized) { + subprocess_map_initialized = 1; + hashmap_init(&subprocess_map, (hashmap_cmp_fn)cmd2process_cmp, + NULL, 0); + entry = NULL; + } else { + entry = (struct read_object_process *) subprocess_find_entry(&subprocess_map, cmd); + } + + if (!entry) { + entry = xmalloc(sizeof(*entry)); + entry->supported_capabilities = 0; + + if (subprocess_start(&subprocess_map, &entry->subprocess, cmd, + start_read_object_fn)) { + free(entry); + err = -1; + goto leave_region; + } + } + process = &entry->subprocess.process; + + if (!(CAP_GET & entry->supported_capabilities)) { + err = -1; + goto leave_region; + } + + sigchain_push(SIGPIPE, SIG_IGN); + + err = packet_write_fmt_gently(process->in, "command=get\n"); + if (err) + goto done; + + err = packet_write_fmt_gently(process->in, "sha1=%s\n", oid_to_hex(oid)); + if (err) + goto done; + + err = packet_flush_gently(process->in); + if (err) + goto done; + + err = subprocess_read_status(process->out, &status); + err = err ? err : strcmp(status.buf, "success"); + +done: + sigchain_pop(SIGPIPE); + + if (err || errno == EPIPE) { + err = err ? err : errno; + if (!strcmp(status.buf, "error")) { + /* The process signaled a problem with the file. */ + } + else if (!strcmp(status.buf, "abort")) { + /* + * The process signaled a permanent problem. Don't try to read + * objects with the same command for the lifetime of the current + * Git process. + */ + entry->supported_capabilities &= ~CAP_GET; + } + else { + /* + * Something went wrong with the read-object process. + * Force shutdown and restart if needed. + */ + error("external process '%s' failed", cmd); + subprocess_stop(&subprocess_map, + (struct subprocess_entry *)entry); + free(entry); + } + } + + trace_performance_since(start, "read_object_process"); + +leave_region: + trace2_region_leave_printf("subprocess", "read_object", the_repository, + "result %d", err); + + strbuf_release(&status); + return err; +} + int obj_read_use_lock = 0; pthread_mutex_t obj_read_mutex; @@ -625,7 +826,8 @@ static int do_oid_object_info_extended(struct repository *r, int rtype; const struct object_id *real = oid; int already_retried = 0; - + int tried_hook = 0; + int tried_gvfs_helper = 0; if (flags & OBJECT_INFO_LOOKUP_REPLACE) real = lookup_replace_object(r, oid); @@ -636,6 +838,7 @@ static int do_oid_object_info_extended(struct repository *r, if (!oi) oi = &blank_oi; +retry: co = find_cached_object(r->objects, real); if (co) { if (oi->typep) @@ -660,11 +863,44 @@ static int do_oid_object_info_extended(struct repository *r, if (!loose_object_info(r, real, oi, flags)) return 0; + if (core_use_gvfs_helper && !tried_gvfs_helper) { + enum gh_client__created ghc; + + if (flags & OBJECT_INFO_SKIP_FETCH_OBJECT) + return -1; + + gh_client__get_immediate(real, &ghc); + tried_gvfs_helper = 1; + + /* + * Retry the lookup IIF `gvfs-helper` created one + * or more new packfiles or loose objects. + */ + if (ghc != GHC__CREATED__NOTHING) + continue; + + /* + * If `gvfs-helper` fails, we just want to return -1. + * But allow the other providers to have a shot at it. + * (At least until we have a chance to consolidate + * them.) + */ + } + /* Not a loose object; someone else may have just packed it. */ if (!(flags & OBJECT_INFO_QUICK)) { reprepare_packed_git(r); if (find_pack_entry(r, real, &e)) break; + if (core_virtualize_objects && !tried_hook) { + // TODO Assert or at least trace2 if gvfs-helper + // TODO was tried and failed and then read-object-hook + // TODO is successful at getting this object. + tried_hook = 1; + // TODO BUG? Should 'oid' be 'real' ? + if (!read_object_process(oid)) + goto retry; + } } /* diff --git a/object-store.h b/object-store.h index c5890085352329..efe0ea6114da3c 100644 --- a/object-store.h +++ b/object-store.h @@ -335,4 +335,6 @@ void *read_object_with_reference(struct repository *r, unsigned long *size, struct object_id *oid_ret); +int read_object_process(const struct object_id *oid); + #endif /* OBJECT_STORE_H */ diff --git a/packfile.c b/packfile.c index 70c7208f027b52..c15a10021cbce4 100644 --- a/packfile.c +++ b/packfile.c @@ -794,6 +794,12 @@ void install_packed_git(struct repository *r, struct packed_git *pack) hashmap_add(&r->objects->pack_map, &pack->packmap_ent); } +void install_packed_git_and_mru(struct repository *r, struct packed_git *pack) +{ + install_packed_git(r, pack); + list_add(&pack->mru, &r->objects->packed_git_mru); +} + void (*report_garbage)(unsigned seen_bits, const char *path); static void report_helper(const struct string_list *list, @@ -1702,6 +1708,13 @@ struct unpack_entry_stack_ent { unsigned long size; }; +static unsigned long g_nr_unpack_entry; + +unsigned long get_nr_unpack_entry(void) +{ + return g_nr_unpack_entry; +} + void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset, enum object_type *final_type, unsigned long *final_size) { @@ -1715,6 +1728,8 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset, int delta_stack_nr = 0, delta_stack_alloc = UNPACK_ENTRY_STACK_PREALLOC; int base_from_cache = 0; + g_nr_unpack_entry++; + prepare_repo_settings(p->repo); write_pack_access_log(p, obj_offset); diff --git a/packfile.h b/packfile.h index 3a3c77cf05a63d..98bad8b2fa3430 100644 --- a/packfile.h +++ b/packfile.h @@ -144,6 +144,7 @@ extern void (*report_garbage)(unsigned seen_bits, const char *path); void reprepare_packed_git(struct repository *r); void install_packed_git(struct repository *r, struct packed_git *pack); +void install_packed_git_and_mru(struct repository *r, struct packed_git *pack); struct packed_git *get_packed_git(struct repository *r); struct list_head *get_packed_git_mru(struct repository *r); @@ -300,4 +301,9 @@ int load_idx(const char *path, const unsigned int hashsz, void *idx_map, */ int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len); +/* + * Return the number of objects fetched from a packfile. + */ +unsigned long get_nr_unpack_entry(void); + #endif diff --git a/path-walk.c b/path-walk.c index 341bdd2ba4ef46..2d4ddbadd50f78 100644 --- a/path-walk.c +++ b/path-walk.c @@ -503,7 +503,11 @@ int walk_objects_by_path(struct path_walk_info *info) if (prepare_revision_walk(info->revs)) die(_("failed to setup revision walk")); - /* Walk trees to mark them as UNINTERESTING. */ + /* + * Walk trees to mark them as UNINTERESTING. + * This is particularly important when 'edge_aggressive' is set. + */ + info->revs->edge_hint_aggressive = info->edge_aggressive; edge_repo = info->revs->repo; edge_tree_list = root_tree_list; mark_edges_uninteresting(info->revs, show_edge, diff --git a/path-walk.h b/path-walk.h index 473ee9d361c864..5ef5a8440e6b5e 100644 --- a/path-walk.h +++ b/path-walk.h @@ -50,6 +50,13 @@ struct path_walk_info { */ int prune_all_uninteresting; + /** + * When 'edge_aggressive' is set, then the revision walk will use + * the '--object-edge-aggressive' option to mark even more objects + * as uninteresting. + */ + int edge_aggressive; + /** * Specify a sparse-checkout definition to match our paths to. Do not * walk outside of this sparse definition. If the patterns are in diff --git a/pkt-line.c b/pkt-line.c index a5bcbc96fb340f..ae54a960a6320e 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -230,7 +230,7 @@ static int do_packet_write(const int fd_out, const char *buf, size_t size, return 0; } -static int packet_write_gently(const int fd_out, const char *buf, size_t size) +int packet_write_gently(const int fd_out, const char *buf, size_t size) { struct strbuf err = STRBUF_INIT; if (do_packet_write(fd_out, buf, size, &err)) { diff --git a/pkt-line.h b/pkt-line.h index 3b33cc64f34dcc..10fd9a812e1935 100644 --- a/pkt-line.h +++ b/pkt-line.h @@ -29,6 +29,7 @@ void packet_write(int fd_out, const char *buf, size_t size); void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3))); int packet_flush_gently(int fd); int packet_write_fmt_gently(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +int packet_write_gently(const int fd_out, const char *buf, size_t size); int write_packetized_from_fd_no_flush(int fd_in, int fd_out); int write_packetized_from_buf_no_flush_count(const char *src_in, size_t len, int fd_out, int *packet_counter); diff --git a/po/TEAMS b/po/TEAMS index 9a6a15cd9a1661..647a107a7a3f68 100644 --- a/po/TEAMS +++ b/po/TEAMS @@ -29,6 +29,10 @@ Repository: https://github.com/jnavila/git Leader: Jean-Noël Avila Members: Sébastien Helleu +Language: ga (Irish) +Repository: https://github.com/aindriu80/git-po +Members: Aindriú Mac Giolla Eoin + Language: id (Indonesian) Repository: https://github.com/bagasme/git-po Leader: Bagas Sanjaya diff --git a/po/bg.po b/po/bg.po index 37d127faac7169..a6410662c39baf 100644 --- a/po/bg.po +++ b/po/bg.po @@ -234,6 +234,10 @@ # acquire lock придобивам ключалка # detached отделѐн, несвързан # revision walk обхождане на версиите +# exit code изходен код +# score оценка за съвпадение +# raw необработен +# # # ------------------------ # „$var“ - може да не сработва за shell има gettext и eval_gettext - проверка - намират се лесно по „$ @@ -262,8 +266,8 @@ msgid "" msgstr "" "Project-Id-Version: git 2.48\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2025-03-05 22:57+0000\n" -"PO-Revision-Date: 2025-03-06 09:15+0100\n" +"POT-Creation-Date: 2025-05-29 13:50+0200\n" +"PO-Revision-Date: 2025-05-29 20:25+0200\n" "Last-Translator: Alexander Shopov \n" "Language-Team: Bulgarian \n" "Language: bg\n" @@ -1807,7 +1811,7 @@ msgstr "„stat“ не може да се изпълни върху „%s“" #, c-format msgid "unable to read %s" -msgstr "обектът „%s“ не може да бъде прочетен" +msgstr "обектът „%s“ не може да се прочете" #, c-format msgid "Badly quoted content in file '%s': %s" @@ -2163,7 +2167,7 @@ msgid "update tracked files" msgstr "обновяване на следените файлове" msgid "renormalize EOL of tracked files (implies -u)" -msgstr "уеднаквяване на знаците за край на файл (включва опцията „-u“)" +msgstr "уеднаквяване на знаците за край на ред (включва опцията „-u“)" msgid "record only the fact that the path will be added later" msgstr "отбелязване само на факта, че пътят ще се добави по-късно" @@ -2739,11 +2743,11 @@ msgstr "Неправилен аргумент на функцията „bisect_ #, c-format msgid "couldn't get the oid of the rev '%s'" -msgstr "идентификаторът на обект на версия „%s“ не може да бъде получен" +msgstr "идентификаторът на обект на версия „%s“ не може да се получи" #, c-format msgid "couldn't open the file '%s'" -msgstr "файлът „%s“ не може да бъде отворен" +msgstr "файлът „%s“ не може да се отвори" #, c-format msgid "Invalid command: you're currently in a %s/%s bisect" @@ -2879,8 +2883,7 @@ msgstr "" #, c-format msgid "cannot read file '%s' for replaying" msgstr "" -"файлът „%s“ не може да бъде прочетен, за да се изпълнят командите от него " -"наново" +"файлът „%s“ не може да се прочете, за да се изпълнят командите от него наново" #, c-format msgid "running %s\n" @@ -2905,7 +2908,7 @@ msgstr "" #, c-format msgid "cannot open file '%s' for writing" -msgstr "файлът „%s“ не може да бъде отворен за запис" +msgstr "файлът „%s“ не може да се отвори за запис" msgid "bisect run cannot continue any more" msgstr "двоичното търсене не може да продължи" @@ -2964,7 +2967,7 @@ msgstr "трябва да завършва с цвят" #, c-format msgid "cannot find revision %s to ignore" -msgstr "версията за прескачане „%s“ не може да бъде открита" +msgstr "версията за прескачане „%s“ липсва" msgid "show blame entries as we find them, incrementally" msgstr "извеждане на авторството с намирането му, последователно" @@ -2986,7 +2989,7 @@ msgid "force progress reporting" msgstr "извеждане на напредъка" msgid "show output score for blame entries" -msgstr "извеждане на допълнителна информация за определянето на авторството" +msgstr "извеждане на оценка за съвпадение при определяне на авторството" msgid "show original filename (Default: auto)" msgstr "" @@ -3054,7 +3057,7 @@ msgid "use 's contents as the final image" msgstr "използване на съдържанието на ФАЙЛа като крайно положение" msgid "score" -msgstr "напасване на редовете" +msgstr "оценка за съвпадение" msgid "find line copies within and across files" msgstr "" @@ -3175,7 +3178,7 @@ msgid "" "branch '%s' not found.\n" "Did you forget --remote?" msgstr "" -"клонът „%s“ не може да бъде открит.\n" +"клонът „%s“ липсва.\n" "Пробвахте ли опцията „--remote“?" #, c-format @@ -3191,7 +3194,7 @@ msgid "Deleted branch %s (was %s).\n" msgstr "Изтрит клон „%s“ (той сочеше към „%s“).\n" msgid "unable to parse format string" -msgstr "форматиращият низ не може да бъде анализиран: %s" +msgstr "форматиращият низ не може да се анализира: %s" msgid "could not resolve HEAD" msgstr "подаването, сочено от указателя „HEAD“, не може да се установи" @@ -3596,7 +3599,7 @@ msgstr "Разпакетиране на пратки от обекти" #, c-format msgid "cannot read object %s '%s'" -msgstr "обектът „%s“ (%s) не може да бъде прочетен" +msgstr "обектът „%s“ (%s) не може да се прочете" msgid "flush is only for --buffer mode" msgstr "изчистването на буферите (flush) се ползва само за „--buffer“" @@ -3622,11 +3625,8 @@ msgstr "може да укажете само една пакетна опция msgid "git cat-file " msgstr "git cat-file ВИД ОБЕКТ" -msgid "git cat-file (-e | -p) " -msgstr "git cat-file (-e|-p) ОБЕКТ" - -msgid "git cat-file (-t | -s) [--allow-unknown-type] " -msgstr "git cat-file (-t|-s) [--allow-unknown-type] ОБЕКТ" +msgid "git cat-file (-e | -p | -t | -s) " +msgstr "git cat-file (-e|-p|-t|-s) ОБЕКТ" msgid "" "git cat-file (--textconv | --filters)\n" @@ -3665,9 +3665,6 @@ msgstr "" msgid "show object size" msgstr "извеждане на размера на обект" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "позволяване на опциите „-s“ и „-t“ да работят с повредени обекти" - msgid "use mail map file" msgstr "" "използване на файл за съответствията на имената и адресите на е-поща " @@ -3730,6 +3727,13 @@ msgid "use a for (--textconv | --filters); Not with 'batch'" msgstr "" "опциите „--textconv“/„--filters“ изискват ПЪТ, а пакетният режим (batch) не" +msgid "objects filter only supported in batch mode" +msgstr "филтрирането на обекти е възможно само в пакетен режим" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "филтрирането на обекти не се поддържа: „%s“" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "„%s=<%s>“ изисква „%s“ или „%s“" @@ -3911,11 +3915,11 @@ msgstr "някоя от необходимите версии липсва в п #, c-format msgid "path '%s': cannot merge" -msgstr "пътят „%s“ не може да бъде слян" +msgstr "пътят „%s“ не може да се слее" #, c-format msgid "Unable to add merge result for '%s'" -msgstr "Резултатът за „%s“ не може да бъде слян" +msgstr "Резултатът за „%s“ не може да се слее" #, c-format msgid "Recreated %d merge conflict" @@ -3966,7 +3970,7 @@ msgstr "пътят „%s“ не е слят" #, c-format msgid "unable to read tree (%s)" -msgstr "дървото не може да бъде прочетено (%s)" +msgstr "дървото не може да се прочете (%s)" msgid "you need to resolve your current index first" msgstr "първо трябва да коригирате индекса си" @@ -3988,7 +3992,7 @@ msgid "HEAD is now at" msgstr "Указателят „HEAD“ в момента сочи към" msgid "unable to update HEAD" -msgstr "Указателят „HEAD“ не може да бъде обновен" +msgstr "Указателят „HEAD“ не може да се обнови" #, c-format msgid "Reset branch '%s'\n" @@ -4262,7 +4266,7 @@ msgstr "липсва име на клон, използвайте опцията #, c-format msgid "could not resolve %s" -msgstr "„%s“ не може да бъде проследен" +msgstr "„%s“ не може да се проследи" msgid "invalid path specification" msgstr "указан е неправилен път" @@ -4345,7 +4349,7 @@ msgstr "Изтриване на „%s“\n" #, c-format msgid "Would remove %s\n" -msgstr "Файлът „%s“ ще бъде изтрит\n" +msgstr "Файлът „%s“ ще се изтрие\n" #, c-format msgid "Skipping repository %s\n" @@ -4353,21 +4357,21 @@ msgstr "Прескачане на хранилището „%s“\n" #, c-format msgid "Would skip repository %s\n" -msgstr "Хранилището „%s“ ще бъде прескочено\n" +msgstr "Хранилището „%s“ ще се прескочи\n" #, c-format msgid "failed to remove %s" -msgstr "файлът „%s“ не може да бъде изтрит" +msgstr "файлът „%s“ не може да се изтрие" #, c-format msgid "could not lstat %s\n" msgstr "не може да се получи информация чрез „lstat“ за „%s“\n" msgid "Refusing to remove current working directory\n" -msgstr "Текущата работна директория няма да бъде изтрита\n" +msgstr "Текущата работна директория няма да се изтрие\n" msgid "Would refuse to remove current working directory\n" -msgstr "Текущата работна директория няма да бъде изтрита\n" +msgstr "Текущата работна директория няма да се изтрие\n" #, c-format msgid "" @@ -4440,8 +4444,8 @@ msgstr "" msgid "Would remove the following item:" msgid_plural "Would remove the following items:" -msgstr[0] "Следният обект ще бъде изтрит:" -msgstr[1] "Следните обекти ще бъдат изтрити:" +msgstr[0] "Следният обект ще се изтрие:" +msgstr[1] "Следните обекти ще се изтрият:" msgid "No more files to clean, exiting." msgstr "Файловете за изчистване свършиха. Изход от програмата." @@ -4482,7 +4486,7 @@ msgstr "" #, c-format msgid "failed to stat '%s'" -msgstr "не може да бъде получена информация чрез „stat“ за „%s“" +msgstr "не може да се получи информация чрез „stat“ за „%s“" #, c-format msgid "%s exists and is not a directory" @@ -4515,11 +4519,11 @@ msgstr "твърдата връзка е различна от източник #, c-format msgid "failed to create link '%s'" -msgstr "връзката „%s“ не може да бъде създадена" +msgstr "връзката „%s“ не може да се създаде" #, c-format msgid "failed to copy file to '%s'" -msgstr "файлът не може да бъде копиран като „%s“" +msgstr "файлът не може да се копира като „%s“" #, c-format msgid "failed to iterate over '%s'" @@ -4546,7 +4550,7 @@ msgstr "отдалеченото хранилище не изпрати всич #, c-format msgid "unable to update %s" -msgstr "обектът „%s“ не може да бъде обновен" +msgstr "обектът „%s“ не може да се обнови" msgid "failed to initialize sparse-checkout" msgstr "частичното изтегляне не може да се инициализира" @@ -4557,7 +4561,7 @@ msgstr "" "съществува. Изтегляне не може да се извърши" msgid "unable to checkout working tree" -msgstr "работното дърво не може да бъде подготвено" +msgstr "работното дърво не може да се подготви" msgid "unable to write parameters to config file" msgstr "настройките не може да бъдат записани в конфигурационния файл" @@ -4566,7 +4570,7 @@ msgid "cannot repack to clean up" msgstr "не може да се извърши пакетиране за изчистване на файловете" msgid "cannot unlink temporary alternates file" -msgstr "временният файл за алтернативни обекти не може да бъде изтрит" +msgstr "временният файл за алтернативни обекти не може да се изтрие" msgid "don't clone shallow repository" msgstr "без клониране на плитко хранилище" @@ -4730,7 +4734,7 @@ msgstr "родителските директории на „%s“ не мож #, c-format msgid "could not create work tree dir '%s'" -msgstr "работното дърво в „%s“ не може да бъде създадено." +msgstr "работното дърво в „%s“ не може да се създаде." #, c-format msgid "Cloning into bare repository '%s'...\n" @@ -5070,22 +5074,22 @@ msgid "updating files failed" msgstr "неуспешно обновяване на файловете" msgid "failed to unpack HEAD tree object" -msgstr "върховото дърво (HEAD tree object) не може да бъде извадено от пакет" +msgstr "върховото дърво (HEAD tree object) не може да се извади от пакет" msgid "No paths with --include/--only does not make sense." msgstr "опциите „--include“ и „--only“ изискват аргументи." msgid "unable to create temporary index" -msgstr "временният индекс не може да бъде създаден" +msgstr "временният индекс не може да се създаде" msgid "interactive add failed" msgstr "неуспешно интерактивно добавяне" msgid "unable to update temporary index" -msgstr "временният индекс не може да бъде обновен" +msgstr "временният индекс не може да се обнови" msgid "Failed to update main cache tree" -msgstr "Кешът за обектите-дървета не може да бъде обновен" +msgstr "Кешът за обектите-дървета не може да се обнови" msgid "cannot do a partial commit during a merge." msgstr "по време на сливане не може да се извърши частично подаване." @@ -5097,10 +5101,10 @@ msgid "cannot do a partial commit during a rebase." msgstr "по време на пребазиране не може да се извърши частично подаване." msgid "cannot read the index" -msgstr "индексът не може да бъде прочетен" +msgstr "индексът не може да се прочете" msgid "unable to write temporary index file" -msgstr "временният индекс не може да бъде записан" +msgstr "временният индекс не може да се запише" #, c-format msgid "commit '%s' lacks author header" @@ -5126,7 +5130,7 @@ msgstr "" #, c-format msgid "could not lookup commit '%s'" -msgstr "следното подаване не може да бъде открито: %s" +msgstr "следното подаване липсва: %s" #, c-format msgid "(reading log message from standard input)\n" @@ -5137,24 +5141,24 @@ msgstr "съобщението за подаване не бе прочетен #, c-format msgid "could not read log file '%s'" -msgstr "файлът със съобщението за подаване „%s“ не може да бъде прочетен" +msgstr "файлът със съобщението за подаване „%s“ не може да се прочете" #, c-format msgid "options '%s' and '%s:%s' cannot be used together" msgstr "опциите „--%s“ и „--%s:%s“ са несъвместими" msgid "could not read SQUASH_MSG" -msgstr "съобщението за вкарване SQUASH_MSG не може да бъде прочетено" +msgstr "съобщението за вкарване SQUASH_MSG не може да се прочете" msgid "could not read MERGE_MSG" -msgstr "съобщението за сливане MERGE_MSG не може да бъде прочетено" +msgstr "съобщението за сливане MERGE_MSG не може да се прочете" #, c-format msgid "could not open '%s'" msgstr "„%s“ не може да се отвори" msgid "could not write commit template" -msgstr "шаблонът за подаване не може да бъде запазен" +msgstr "шаблонът за подаване не може да се запази" #, c-format msgid "" @@ -5231,7 +5235,7 @@ msgid "%sCommitter: %.*s <%.*s>" msgstr "%sПодаващ: %.*s <%.*s>" msgid "Cannot read index" -msgstr "Индексът не може да бъде прочетен" +msgstr "Индексът не може да се прочете" msgid "unable to pass trailers to --trailers" msgstr "епилогът не може да се подаде на „--trailers“" @@ -5275,7 +5279,7 @@ msgid "reword option of '%s' and '%s' cannot be used together" msgstr "опциите „%s“ и „%s“ са несъвместими" msgid "You have nothing to amend." -msgstr "Няма какво да бъде поправено." +msgstr "Няма какво да се поправи." msgid "You are in the middle of a merge -- cannot amend." msgstr "В момента се извършва сливане, не може да поправяте." @@ -5471,18 +5475,18 @@ msgid "ok to record a change with an empty message" msgstr "позволяване на подавания с празни съобщения" msgid "could not parse HEAD commit" -msgstr "върховото подаване „HEAD“ не може да бъде прочетено" +msgstr "върховото подаване „HEAD“ не може да се прочете" #, c-format msgid "Corrupt MERGE_HEAD file (%s)" msgstr "Повреден файл за върха за сливането „MERGE_HEAD“ (%s)" msgid "could not read MERGE_MODE" -msgstr "режимът на сливане „MERGE_MODE“ не може да бъде прочетен" +msgstr "режимът на сливане „MERGE_MODE“ не може да се прочете" #, c-format msgid "could not read commit message: %s" -msgstr "съобщението за подаване не може да бъде прочетено: %s" +msgstr "съобщението за подаване не може да се прочете: %s" #, c-format msgid "Aborting commit due to empty commit message.\n" @@ -5723,7 +5727,7 @@ msgstr "при търсене да се уважат и директивите #, c-format msgid "unable to read config file '%s'" -msgstr "конфигурационният файл „%s“ не може да бъде прочетен" +msgstr "конфигурационният файл „%s“ не може да се прочете" msgid "error processing config file(s)" msgstr "грешка при обработката на конфигурационен файл" @@ -5804,7 +5808,7 @@ msgstr "не се поддържа редактиране на обекти-BLOB #, c-format msgid "cannot create configuration file %s" -msgstr "конфигурационният файл „%s“ не може да бъде създаден" +msgstr "конфигурационният файл „%s“ не може да се създаде" msgid "Action" msgstr "Действие" @@ -6042,7 +6046,7 @@ msgstr "" "добавяне на такъв МАРКЕР на счупеното работно дърво (стандартно е „-broken“)" msgid "No names found, cannot describe anything." -msgstr "Не са открити имена — нищо не може да бъде описано." +msgstr "Не са открити имена — нищо не може да се опише." #, c-format msgid "option '%s' and commit-ishes cannot be used together" @@ -6064,6 +6068,51 @@ msgstr "укажете суфикса на файла във формат за msgid "specify the content of the diagnostic archive" msgstr "указване на съдържанието на диагностичния архив" +#, c-format +msgid "unable to parse mode: %s" +msgstr "режимът не може да се анализира: %s" + +#, c-format +msgid "unable to parse object id: %s" +msgstr "идентификаторът на обекта не може да се анализира: %s" + +msgid "git diff-pairs -z []" +msgstr "git diff-pairs -z [ОПЦИЯ_ЗА_РАЗЛИКИ…]" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "непознат аргумент: %s" + +msgid "working without -z is not supported" +msgstr "опцията „-z“ е задължителна" + +msgid "pathspec arguments not supported" +msgstr "не се поддържат опции за пътища" + +msgid "revision arguments not allowed" +msgstr "не се поддържат опции за версии" + +msgid "invalid raw diff input" +msgstr "неправилен необработен вход за разлики" + +msgid "tree objects not supported" +msgstr "не се поддържат обекти-дървета" + +msgid "got EOF while reading path" +msgstr "край на файл (EOF) при изчитане на път" + +msgid "got EOF while reading destination path" +msgstr "край на файл (EOF) при изчитане на целевия път" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "" +"оценката за съвпадение при преименуване/копиране не може да се анализира: %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "непознато състояние на разлика: %c" + msgid "--merge-base only works with two commits" msgstr "опцията „--merge-base“ изисква точно две подавания" @@ -6106,15 +6155,15 @@ msgstr "git difftool [ОПЦИЯ…] [ПОДАВАНЕ [ПОДАВАНЕ]] [[--] #, c-format msgid "could not read symlink %s" -msgstr "символната връзка „%s“ не може да бъде прочетена" +msgstr "символната връзка „%s“ не може да се прочете" #, c-format msgid "could not read symlink file %s" -msgstr "файлът, сочен от символната връзка „%s“, не може да бъде прочетен" +msgstr "файлът, сочен от символната връзка „%s“, не може да се прочете" #, c-format msgid "could not read object %s for symlink %s" -msgstr "обектът „%s“ за символната връзка „%s“ не може да бъде прочетен" +msgstr "обектът „%s“ за символната връзка „%s“ не може да се прочете" msgid "" "combined diff formats ('-c' and '--cc') are not supported in\n" @@ -6206,8 +6255,11 @@ msgstr "Съобщение за напредъка на всеки такъв Б msgid "select handling of signed tags" msgstr "Как да се обработват подписаните етикети" +msgid "select handling of signed commits" +msgstr "как да се обработват подписаните подавания" + msgid "select handling of tags that tag filtered objects" -msgstr "Как да се обработват етикетите на филтрираните обекти" +msgstr "как да се обработват етикетите на филтрираните обекти" msgid "select handling of commit messages in an alternate encoding" msgstr "" @@ -6304,7 +6356,7 @@ msgid "fetch.parallel cannot be negative" msgstr "опцията „fetch.parallel“ трябва да е неотрицателна" msgid "couldn't find remote ref HEAD" -msgstr "указателят „HEAD“ в отдалеченото хранилище не може да бъде открит" +msgstr "указателят „HEAD“ в отдалеченото хранилище липсва" #, c-format msgid "From %.*s\n" @@ -6327,10 +6379,10 @@ msgid "[tag update]" msgstr "[обновяване на етикетите]" msgid "unable to update local ref" -msgstr "локален указател не може да бъде обновен" +msgstr "локален указател не може да се обнови" msgid "would clobber existing tag" -msgstr "съществуващ етикет ще бъде презаписан" +msgstr "ще се презапише съществуващ етикет" msgid "[new tag]" msgstr "[нов етикет]" @@ -6349,7 +6401,7 @@ msgstr "същинско сливане" #, c-format msgid "cannot open '%s'" -msgstr "„%s“ не може да бъде отворен" +msgstr "„%s“ не може да се отвори" msgid "" "fetch normally indicates which branches had a forced update,\n" @@ -6531,7 +6583,7 @@ msgstr "брой подмодули доставени паралелно" msgid "modify the refspec to place all refs within refs/prefetch/" msgstr "" -"промяна на указателя, така че и той, както останалите, да бъде в „refs/" +"промяна на указателя, така че и той, както останалите, да е в „refs/" "prefetch/“" msgid "prune remote-tracking branches no longer on remote" @@ -6865,10 +6917,6 @@ msgstr "%s: разлика в контролната сума при: %s" msgid "%s: object corrupt or missing: %s" msgstr "%s: развален или липсващ обект: %s" -#, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: обектът е непознат вид „%s“: %s" - #, c-format msgid "%s: object could not be parsed: %s" msgstr "„%s“: не може да се анализира: „%s“" @@ -6920,22 +6968,25 @@ msgstr "„%s“: неправилен указател за отмяна на #, c-format msgid "unable to load rev-index for pack '%s'" -msgstr "обратният индекс на пакета „%s“ не може да бъде зареден" +msgstr "обратният индекс на пакета „%s“ не може да се зареди" #, c-format msgid "invalid rev-index for pack '%s'" msgstr "неправилен обратен индекс за пакета „%s“" +msgid "Checking ref database" +msgstr "Проверка на базата от данни с указателите" + msgid "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" -" [--[no-]name-objects] [...]" +" [--[no-]name-objects] [--[no-]references] [...]" msgstr "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" -" [--[no-]name-objects] [ОБЕКТ…]" +" [--[no-]name-objects] [--[no-]references] [ОБЕКТ…]" msgid "show unreachable objects" msgstr "показване на недостижимите обекти" @@ -6973,6 +7024,9 @@ msgstr "показване на напредъка" msgid "show verbose names for reachable objects" msgstr "показване на подробни имена на достижимите обекти" +msgid "check reference database consistency" +msgstr "проверка на валидността на базата от данни с указатели" + msgid "Checking objects" msgstr "Проверка на обектите" @@ -7008,7 +7062,7 @@ msgstr "fsmonitor-daemon не наблюдава „%s“\n" #, c-format msgid "could not create fsmonitor cookie '%s'" -msgstr "бисквитката за fsmonitor „%s“ не може да бъде създадена" +msgstr "бисквитката за fsmonitor „%s“ не може да се създаде" #, c-format msgid "fsmonitor: cookie_result '%d' != SEEN" @@ -7187,19 +7241,19 @@ msgid "unrecognized --schedule argument '%s'" msgstr "непознат аргумент към „--schedule“: %s" msgid "failed to write commit-graph" -msgstr "графът с подаванията не може да бъде записан" +msgstr "графът с подаванията не може да се запише" msgid "failed to prefetch remotes" msgstr "неуспешно предварително доставяне на отдалечените клони" msgid "failed to start 'git pack-objects' process" -msgstr "процесът за командата „git pack-objects“ не може да бъде стартиран" +msgstr "процесът за командата „git pack-objects“ не може да се стартира" msgid "failed to finish 'git pack-objects' process" msgstr "процесът за командата „git pack-objects“ не може да завърши" msgid "failed to write multi-pack-index" -msgstr "индексът за множество пакети не може да бъде записан" +msgstr "индексът за множество пакети не може да се запише" msgid "'git multi-pack-index expire' failed" msgstr "неуспешно изпълнение на „git multi-pack-index expire“" @@ -7258,7 +7312,7 @@ msgid "unable to add '%s' value of '%s'" msgstr "неуспешно добавяне на стойност на „%s“ за „%s“" msgid "return success even if repository was not registered" -msgstr "успешно завършване, дори ако хранилището не бъде регистрирано" +msgstr "успешно завършване, дори ако хранилището не се регистрира" #, c-format msgid "unable to unset '%s' value of '%s'" @@ -7341,7 +7395,7 @@ msgid "" "then try again. If it still fails, a git-maintenance(1) process may have\n" "crashed in this repository earlier: remove the file manually to continue." msgstr "" -"Файлът-ключалка „%s.lock“ не може да бъде създаден: %s\n" +"Файлът-ключалка „%s.lock“ не може да се създаде: %s\n" "\n" "Изглежда, че и друг процес на git-maintenance(1) е пуснат в това\n" "хранилище. Уверете се, че всички подобни процеси са спрени и опитайте\n" @@ -7392,7 +7446,7 @@ msgstr "липсва поддръжка за нишки. „%s“ ще се п #, c-format msgid "unable to read tree %s" -msgstr "дървото не може да бъде прочетено: %s" +msgstr "дървото не може да се прочете: %s" #, c-format msgid "unable to grep from object of type %s" @@ -7562,7 +7616,7 @@ msgstr "опциите „--no-index“ и „--untracked“ са несъвме #, c-format msgid "unable to resolve revision: %s" -msgstr "версията „%s“ не може бъде открита" +msgstr "версията „%s“ не може се открие" msgid "--untracked not supported with --recurse-submodules" msgstr "опциите „--untracked“ и „--recurse-submodules“ са несъвместими" @@ -7758,7 +7812,7 @@ msgstr[0] "не може да се запълни %d байт" msgstr[1] "не може да се запълнят %d байта" msgid "early EOF" -msgstr "неочакван край на файл" +msgstr "неочакван край на файл (EOF)" msgid "read error on input" msgstr "грешка при четене на входните данни" @@ -7799,7 +7853,7 @@ msgid "unknown object type %d" msgstr "непознат вид обект %d" msgid "cannot pread pack file" -msgstr "пакетният файл не може да бъде прочетен" +msgstr "пакетният файл не може да се прочете" #, c-format msgid "premature end of pack file, % byte missing" @@ -7817,11 +7871,11 @@ msgstr "" #, c-format msgid "cannot read existing object info %s" -msgstr "съществуващият обект в „%s“ не може да бъде прочетен" +msgstr "съществуващият обект в „%s“ не може да се прочете" #, c-format msgid "cannot read existing object %s" -msgstr "съществуващият обект „%s“ не може да бъде прочетен" +msgstr "съществуващият обект „%s“ не може да се прочете" #, c-format msgid "invalid blob object %s" @@ -7835,7 +7889,7 @@ msgid "Not all child objects of %s are reachable" msgstr "Някои обекти, наследници на „%s“, не може да бъдат достигнати" msgid "failed to apply delta" -msgstr "разликата не може да бъде приложена" +msgstr "разликата не може да се приложи" msgid "Receiving objects" msgstr "Получаване на обекти" @@ -7916,11 +7970,11 @@ msgstr "неправилна стойност: „pack.indexVersion=%“ #, c-format msgid "Cannot open existing pack file '%s'" -msgstr "Съществуващият пакетен файл „%s“ не може да бъде отворен" +msgstr "Съществуващият пакетен файл „%s“ не може да се отвори" #, c-format msgid "Cannot open existing pack idx file for '%s'" -msgstr "Съществуващият индекс за пакетния файл „%s“ не може да бъде отворен" +msgstr "Съществуващият индекс за пакетния файл „%s“ не може да се отвори" #, c-format msgid "non delta: %d object" @@ -7996,8 +8050,7 @@ msgstr "права̀" msgid "specify that the git repository is to be shared amongst several users" msgstr "" -"указване, че хранилището на Git ще бъде споделено от повече от един " -"потребител" +"указване, че хранилището на Git ще се споделя от повече от един потребител" msgid "override the name of the initial branch" msgstr "задаване на името на първоначалния клон" @@ -8010,7 +8063,7 @@ msgstr "указване на алгоритъм за контролна сум #, c-format msgid "cannot mkdir %s" -msgstr "директорията „%s“ не може да бъде създадена" +msgstr "директорията „%s“ не може да се създаде" #, c-format msgid "cannot chdir to %s" @@ -8057,7 +8110,7 @@ msgstr "временният файл не може да се отвори" #, c-format msgid "could not read input file '%s'" -msgstr "входният файл „%s“ не може да бъде прочетен" +msgstr "входният файл „%s“ не може да се прочете" msgid "could not read from stdin" msgstr "от стандартния вход не може да се чете" @@ -8145,10 +8198,6 @@ msgstr "" "проследяване на еволюцията на диапазона от редове НАЧАЛО,КРАЙ или :ФУНКЦИЯта " "във ФАЙЛа" -#, c-format -msgid "unrecognized argument: %s" -msgstr "непознат аргумент: %s" - msgid "-L: cannot be used with pathspec" msgstr "опцията „-LДИАПАЗОН:ФАЙЛ“ не може да се ползва с път" @@ -8162,7 +8211,7 @@ msgstr "git show %s: повреден файл" #, c-format msgid "could not read object %s" -msgstr "обектът не може да бъде прочетен: %s" +msgstr "обектът не може да се прочете: %s" #, c-format msgid "unknown type: %d" @@ -8177,7 +8226,7 @@ msgstr "не е зададена стойност на „format.headers“" #, c-format msgid "cannot open patch file %s" -msgstr "файлът-кръпка „%s“ не може да бъде отворен" +msgstr "файлът-кръпка „%s“ не може да се отвори" msgid "need exactly one range" msgstr "трябва да зададете точно един диапазон" @@ -8187,7 +8236,7 @@ msgstr "не е диапазон" #, c-format msgid "unable to read branch description file '%s'" -msgstr "файлът с описанието на клона „%s“ не може да бъде прочетен" +msgstr "файлът с описанието на клона „%s“ не може да се прочете" msgid "cover letter needs email format" msgstr "придружаващото писмо трябва да е форматирано като е-писмо" @@ -8214,20 +8263,20 @@ msgid "failed to resolve '%s' as a valid ref" msgstr "„%s“ не е указател или не сочи към нищо" msgid "could not find exact merge base" -msgstr "точната база за сливане не може да бъде открита" +msgstr "точната база за сливане не може да се открие" msgid "" "failed to get upstream, if you want to record base commit automatically,\n" "please use git branch --set-upstream-to to track a remote branch.\n" "Or you could specify base commit by --base= manually" msgstr "" -"следеният клон не може да бъде установен. Ако искате ръчно да го\n" +"следеният клон не може да се установи. Ако искате ръчно да го\n" "зададете, използвайте „git branch --set-upstream-to“.\n" "Може ръчно да зададете базово подаване чрез „--" "base=<ИДЕНТИФИКАТОР_НА_БАЗОВО_ПОДАВАНЕ>“." msgid "failed to find exact merge base" -msgstr "точната база при сливане не може да бъде открита" +msgstr "точната база при сливане не може да се определи" msgid "base commit should be the ancestor of revision list" msgstr "базовото подаване трябва да е предшественикът на списъка с версиите" @@ -8236,7 +8285,7 @@ msgid "base commit shouldn't be in revision list" msgstr "базовото подаване не може да е в списъка с версиите" msgid "cannot get patch id" -msgstr "идентификаторът на кръпката не може да бъде получен" +msgstr "идентификаторът на кръпката не може да се получи" msgid "failed to infer range-diff origin of current series" msgstr "" @@ -8424,7 +8473,7 @@ msgstr "опцията „--remerge-diff“ е несъвместима с ге #, c-format msgid "could not create directory '%s'" -msgstr "Директорията „%s“ не може да бъде създадена" +msgstr "Директорията „%s“ не може да се създаде" msgid "--interdiff requires --cover-letter or single patch" msgstr "" @@ -8450,7 +8499,7 @@ msgstr "Диапазонна разлика спрямо v%d:" #, c-format msgid "unable to read signature file '%s'" -msgstr "файлът „%s“ с подпис не може да бъде прочетен" +msgstr "файлът „%s“ с подпис не може да се прочете" msgid "Generating patches" msgstr "Създаване на кръпки" @@ -8787,7 +8836,7 @@ msgstr "поддържа се само сливане на точно две и #, c-format msgid "could not resolve ref '%s'" -msgstr "указателят „%s“ не може да бъде проследен" +msgstr "указателят „%s“ не може да се проследи" #, c-format msgid "Merging %s with %s\n" @@ -8821,6 +8870,9 @@ msgstr "само тривиално сливане" msgid "also show informational/conflict messages" msgstr "показване и информационните съобщения, и тези при конфликт" +msgid "suppress all output; only exit status wanted" +msgstr "без извеждане на информация, получаване само на изходен код" + msgid "list filenames without modes/oids/stages" msgstr "" "извеждане на имената на файлове без режими/идентификатори на обекти/етапи" @@ -8952,12 +9004,11 @@ msgstr "Вече е обновено." #, c-format msgid "Squash commit -- not updating HEAD\n" -msgstr "Вкарано подаване — указателят „HEAD“ няма да бъде обновен\n" +msgstr "Вкарано подаване — указателят „HEAD“ няма да се обнови\n" #, c-format msgid "No merge message -- not updating HEAD\n" -msgstr "" -"Липсва съобщение при подаване — указателят „HEAD“ няма да бъде обновен\n" +msgstr "Липсва съобщение при подаване — указателят „HEAD“ няма да се обнови\n" #, c-format msgid "'%s' does not point to a commit" @@ -8968,14 +9019,14 @@ msgid "Bad branch.%s.mergeoptions string: %s" msgstr "Неправилен низ за настройката „branch.%s.mergeoptions“: „%s“" msgid "Unable to write index." -msgstr "Индексът не може да бъде прочетен" +msgstr "Индексът не може да се прочете" msgid "Not handling anything other than two heads merge." msgstr "Поддържа се само сливане на точно две истории." #, c-format msgid "unable to write %s" -msgstr "„%s“ не може да бъде записан" +msgstr "„%s“ не може да се запише" #, c-format msgid "Could not read from '%s'" @@ -8984,8 +9035,8 @@ msgstr "От „%s“ не може да се чете" #, c-format msgid "Not committing merge; use 'git commit' to complete the merge.\n" msgstr "" -"Сливането няма да бъде подадено. За завършването му и подаването му " -"използвайте командата „git commit“.\n" +"Сливането няма да се подаде. За завършването му и подаването му използвайте " +"командата „git commit“.\n" msgid "" "Please enter a commit message to explain why this merge is necessary,\n" @@ -9163,7 +9214,7 @@ msgstr "%d (FSCK_IGNORE?) никога не трябва да задейства #, c-format msgid "could not read tagged object '%s'" -msgstr "обектът с етикет не може да бъде прочетен: %s" +msgstr "обектът с етикет не може да се прочете: %s" #, c-format msgid "object '%s' tagged as '%s', but is a '%s' type" @@ -9176,7 +9227,7 @@ msgid "tag on stdin did not refer to a valid object" msgstr "етикетът на стандартния вход не сочи към правилен обект" msgid "unable to write tag file" -msgstr "файлът за етикета не може да бъде запазен" +msgstr "файлът за етикета не може да се запази" msgid "input is NUL terminated" msgstr "входните записи са разделени с нулевия знак „NUL“" @@ -9239,8 +9290,11 @@ msgstr "" "при препакетиране пакетните файлове, които са с по-малък от този размер, да " "се обединяват в пакети с по-голям от този размер" -msgid "git mv [] ... " -msgstr "git mv [ОПЦИЯ…] ОБЕКТ… ЦЕЛ" +msgid "git mv [-v] [-f] [-n] [-k] " +msgstr "git mv [-v] [-f] [-n] [-k] ОБЕКТ… ЦЕЛ" + +msgid "git mv [-v] [-f] [-n] [-k] ... " +msgstr "git mv [-v] [-f] [-n] [-k] ОБЕКТ… ЦЕЛЕВА_ДИРЕКТОРИЯ" #, c-format msgid "Directory %s is in index and no submodule?" @@ -9310,6 +9364,12 @@ msgstr "целта съществува в индекса" msgid "%s, source=%s, destination=%s" msgstr "%s, обект: „%s“, цел: „%s“" +#, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "" +"невъзможно е да се преместят едновременно и „%s“, и родителската директория " +"„%s“" + #, c-format msgid "Renaming %s to %s\n" msgstr "Преименуване на „%s“ на „%s“\n" @@ -9455,7 +9515,7 @@ msgid "please supply the note contents using either -m or -F option" msgstr "задайте съдържанието на бележката с някоя от опциите „-m“ или „-F“" msgid "unable to write note object" -msgstr "обектът-бележка не може да бъде записан" +msgstr "обектът-бележка не може да се запише" #, c-format msgid "the note contents have been left in %s" @@ -9463,7 +9523,7 @@ msgstr "съдържанието на бележката е във файла #, c-format msgid "could not open or read '%s'" -msgstr "файлът „%s“ не може да бъде отворен или прочетен" +msgstr "файлът „%s“ не може да се отвори или прочете" #, c-format msgid "failed to resolve '%s' as a valid ref." @@ -9471,7 +9531,7 @@ msgstr "не може да се открие към какво сочи „%s“ #, c-format msgid "failed to read object '%s'." -msgstr "обектът „%s“ не може да бъде прочетен." +msgstr "обектът „%s“ не може да се прочете." #, c-format msgid "cannot read note data from non-blob object '%s'." @@ -9575,16 +9635,16 @@ msgstr "" "C“.\n" msgid "failed to delete ref NOTES_MERGE_PARTIAL" -msgstr "указателят „NOTES_MERGE_PARTIAL“ не може да бъде изтрит" +msgstr "указателят „NOTES_MERGE_PARTIAL“ не може да се изтрие" msgid "failed to delete ref NOTES_MERGE_REF" -msgstr "указателят „NOTES_MERGE_REF“ не може да бъде изтрит" +msgstr "указателят „NOTES_MERGE_REF“ не може да се изтрие" msgid "failed to remove 'git notes merge' worktree" -msgstr "работната директория на „git notes merge“ не може да бъде изтрита" +msgstr "работната директория на „git notes merge“ не може да се изтрие" msgid "failed to read ref NOTES_MERGE_PARTIAL" -msgstr "указателят „NOTES_MERGE_PARTIAL“ не може да бъде прочетен" +msgstr "указателят „NOTES_MERGE_PARTIAL“ не може да се прочете" msgid "could not find commit from NOTES_MERGE_PARTIAL." msgstr "подаването от „NOTES_MERGE_PARTIAL“ не може да се открие." @@ -9741,7 +9801,7 @@ msgstr "Записване на обектите" #, c-format msgid "failed to stat %s" -msgstr "не може да бъде получена информация чрез „stat“ за „%s“" +msgstr "не може да се получи информация чрез „stat“ за „%s“" #, c-format msgid "failed utime() on %s" @@ -9772,11 +9832,11 @@ msgstr "Преброяване на обектите" #, c-format msgid "unable to get size of %s" -msgstr "размерът на „%s“ не може да бъде получен" +msgstr "размерът на „%s“ не може да се получи" #, c-format msgid "unable to parse object header of %s" -msgstr "заглавната част на „%s“ не може да бъде анализирана" +msgstr "заглавната част на „%s“ не може да се анализира" #, c-format msgid "object %s cannot be read" @@ -9801,7 +9861,7 @@ msgstr "" #, c-format msgid "unable to get type of object %s" -msgstr "видът на обекта „%s“ не може да бъде определен" +msgstr "видът на обекта „%s“ не може да се определи" msgid "Compressing objects" msgstr "Компресиране на обектите" @@ -9831,7 +9891,7 @@ msgstr "" #, c-format msgid "could not get type of object %s in pack %s" -msgstr "видът на обекта „%s“ в пакет „%s“ не може да бъде определен" +msgstr "видът на обекта „%s“ в пакет „%s“ не може да се определи" #, c-format msgid "could not find pack '%s'" @@ -9839,7 +9899,7 @@ msgstr "пакетът „%s“ не може да се открие" #, c-format msgid "packfile %s cannot be accessed" -msgstr "пакетният файл „%s“ не може да бъде достъпен" +msgstr "пакетният файл „%s“ не може да се достъпи" msgid "Enumerating cruft objects" msgstr "Изброяване на ненужните обекти" @@ -9872,14 +9932,14 @@ msgstr "" "заредят" msgid "cannot open pack index" -msgstr "индексът на пакетния файл не може да бъде отворен" +msgstr "индексът на пакетния файл не може да се отвори" #, c-format msgid "loose object at %s could not be examined" -msgstr "непакетираният обект в „%s“ не може да бъде анализиран" +msgstr "непакетираният обект в „%s“ не може да се анализира" msgid "unable to force loose object" -msgstr "оставането на обекта непакетиран не може да бъде наложено" +msgstr "оставането на обекта непакетиран не може да се наложи" #, c-format msgid "not a rev '%s'" @@ -10272,6 +10332,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "недостъпно подаване: %s" +#, c-format +msgid "invalid refspec '%s'" +msgstr "неправилен указател: „%s“" + msgid "ignoring --verify-signatures for rebase" msgstr "без „--verify-signatures“ при пребазиране" @@ -10330,7 +10394,7 @@ msgid "" "$ git reset --hard\n" "to recover." msgstr "" -"Работното ви копие не може да бъде превъртяно.\n" +"Работното ви копие не може да се превърти.\n" "След като запазите всичко необходимо посочено от командата:\n" " git diff %s\n" "изпълнете:\n" @@ -10806,7 +10870,7 @@ msgstr "неправилната стойност на „allow_rerere_autoupdat #, c-format msgid "could not remove '%s'" -msgstr "„%s“ не може да бъде изтрит" +msgstr "„%s“ не може да се изтрие" #, c-format msgid "" @@ -11047,7 +11111,7 @@ msgstr "" "Опцията „--edit-todo“ е достъпна само по време на интерактивно пребазиране." msgid "Cannot read HEAD" -msgstr "Указателят „HEAD“ не може да бъде прочетен" +msgstr "Указателят „HEAD“ не може да се прочете" msgid "" "You must edit all merge conflicts and then\n" @@ -11125,7 +11189,7 @@ msgid "No such ref: %s" msgstr "Такъв указател няма: %s" msgid "Could not resolve HEAD to a commit" -msgstr "Подаването, сочено от указателя „HEAD“, не може да бъде открито" +msgstr "Липсва подаването, сочено от указателя „HEAD“" #, c-format msgid "'%s': need exactly one merge base with branch" @@ -11265,6 +11329,9 @@ msgstr "" msgid "git reflog exists " msgstr "git reflog exists УКАЗАТЕЛ" +msgid "git reflog drop [--all [--single-worktree] | ...]" +msgstr "git reflog drop [--all [--single-worktree]|УКАЗАТЕЛ…]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "неправилно времево клеймо „%s“ подадено към „--%s“" @@ -11318,8 +11385,8 @@ msgid "Marking reachable objects..." msgstr "Отбелязване на достижимите обекти…" #, c-format -msgid "%s points nowhere!" -msgstr "„%s“ не сочи наникъде!" +msgid "reflog could not be found: '%s'" +msgstr "журналът с указатели липсва: „%s“" msgid "no reflog specified to delete" msgstr "не е указан журнал с подавания за изтриване" @@ -11328,6 +11395,15 @@ msgstr "не е указан журнал с подавания за изтри msgid "invalid ref format: %s" msgstr "неправилен формат на указател: %s" +msgid "drop the reflogs of all references" +msgstr "изтриване на всички журнали с указатели" + +msgid "drop reflogs from the current worktree only" +msgstr "изтриване на журнала с указатели само в текущото работно дърво" + +msgid "references specified along with --all" +msgstr "указателите се задават с опцията „--all“" + msgid "git refs migrate --ref-format= [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format=ФОРМАТ [--no-reflog] [--dry-run]" @@ -11470,7 +11546,7 @@ msgstr "вече съществува отдалечено хранилище с #, c-format msgid "Could not setup master '%s'" -msgstr "Основният клон „%s“ не може да бъде настроен" +msgstr "Основният клон „%s“ не може да се настрои" #, c-format msgid "more than one %s" @@ -11514,7 +11590,7 @@ msgstr "Няма отдалечено хранилище на име „%s“" #, c-format msgid "Could not rename config section '%s' to '%s'" -msgstr "Разделът „%s“ в настройките не може да бъде преименуван на „%s“" +msgstr "Разделът „%s“ в настройките не може да се преименува на „%s“" #, c-format msgid "" @@ -11552,7 +11628,7 @@ msgstr[1] "" #, c-format msgid "Could not remove config section '%s'" -msgstr "Разделът „%s“ в настройките не може да бъде изтрит" +msgstr "Разделът „%s“ в настройките не може да се изтрие" #, c-format msgid " new (next fetch will store in remotes/%s)" @@ -11734,7 +11810,7 @@ msgstr "" #, c-format msgid "Could not delete %s" -msgstr "„%s“ не може да бъде изтрит" +msgstr "„%s“ не може да се изтрие" #, c-format msgid "Not a valid ref: %s" @@ -11762,7 +11838,7 @@ msgstr "адрес: %s" #, c-format msgid " * [would prune] %s" -msgstr " ● [ще бъде окастрено] %s" +msgstr " ● [ще се окастри] %s" #, c-format msgid " * [pruned] %s" @@ -11863,7 +11939,7 @@ msgstr "пакет „%s“ е твърде голям за свиване" #, c-format msgid "could not open tempfile %s for writing" -msgstr "временният файл „%s“ не може да бъде отворен за запис" +msgstr "временният файл „%s“ не може да се отвори за запис" msgid "could not close refs snapshot tempfile" msgstr "временният файл със снимка на указателите не може да се затвори" @@ -11896,6 +11972,11 @@ msgid "with --cruft, expire objects older than this" msgstr "" "с опцията „--cruft“: обявяване на обектите по-стари от това ВРЕМЕ за остарели" +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "" +"с опцията „--cruft“: препакетиране само на пакетите за ненужни обекти, които " +"са с размер под този" + msgid "remove redundant packs, and run git-prune-packed" msgstr "" "премахване на ненужните пакетирани файлове и изпълнение на командата „git-" @@ -12015,7 +12096,7 @@ msgstr "" #, c-format msgid "replace ref '%s' not found" -msgstr "указателят за замяна „%s“ не може да бъде открит" +msgstr "указателят за замяна „%s“ липсва" #, c-format msgid "Deleted replace ref '%s'" @@ -12041,14 +12122,14 @@ msgstr "" #, c-format msgid "unable to open %s for writing" -msgstr "„%s“ не може да бъде отворен за запис" +msgstr "„%s“ не може да се отвори за запис" msgid "cat-file reported failure" msgstr "изпълнението на „cat-file“ завърши с грешка" #, c-format msgid "unable to open %s for reading" -msgstr "„%s“ не може да бъде отворен за четене" +msgstr "„%s“ не може да се отвори за четене" msgid "unable to spawn mktree" msgstr "не може да се създаде процес за „mktree“" @@ -12067,7 +12148,7 @@ msgid "unable to fstat %s" msgstr "„fstat“ не може да се изпълни върху „%s“" msgid "unable to write object to database" -msgstr "обектът не може да бъде записан в базата от данни" +msgstr "обектът не може да се запише в базата от данни" #, c-format msgid "unable to get object type for %s" @@ -12105,11 +12186,11 @@ msgid "the original commit '%s' has a gpg signature" msgstr "първоначалното подаване „%s“ е с подпис на GPG" msgid "the signature will be removed in the replacement commit!" -msgstr "Подписът ще бъде премахнат в заменящото подаване!" +msgstr "Подписът ще се премахне в заменящото подаване!" #, c-format msgid "could not write replacement commit for: '%s'" -msgstr "заменящото подаване за „%s“ не може да бъде записано" +msgstr "заменящото подаване за „%s“ не може да се запише" #, c-format msgid "graft for '%s' unnecessary" @@ -12294,11 +12375,11 @@ msgid "You do not have a valid HEAD." msgstr "Указателят „HEAD“ е повреден." msgid "Failed to find tree of HEAD." -msgstr "Дървото, сочено от указателя „HEAD“, не може да бъде открито." +msgstr "Дървото, сочено от указателя „HEAD“, не може да се открие." #, c-format msgid "Failed to find tree of %s." -msgstr "Дървото, сочено от „%s“, не може да бъде открито." +msgstr "Дървото, сочено от „%s“, не може да се открие." #, c-format msgid "HEAD is now at %s" @@ -12364,19 +12445,22 @@ msgstr "" #, c-format msgid "Could not reset index file to revision '%s'." -msgstr "Индексът не може да бъде занулен към версия „%s“." +msgstr "Индексът не може да се занули към версия „%s“." msgid "Could not write new index file." -msgstr "Новият индекс не може да бъде записан." +msgstr "Новият индекс не може да се запише." #, c-format msgid "unable to get disk usage of %s" -msgstr "използваното място за „%s“ не може да бъде получено" +msgstr "използваното място за „%s“ не може да се получи" #, c-format msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "неправилна стойност за „%s“: „%s“, единственият позволен формат е „%s“" +msgid "-z option used with unsupported option" +msgstr "неподдържана комбинация с опцията „-z“" + msgid "rev-list does not support display of notes" msgstr "командата „rev-list“ не поддържа извеждането на бележки" @@ -12463,7 +12547,7 @@ msgid "this operation must be run in a work tree" msgstr "тази команда трябва да се изпълни в работно дърво" msgid "Could not read the index" -msgstr "Индексът не може да бъде прочетен" +msgstr "Индексът не може да се прочете" #, c-format msgid "unknown mode for --show-object-format: %s" @@ -12787,8 +12871,8 @@ msgstr "опцията „--reflog“ изисква точно едно име #, c-format msgid "only %d entry can be shown at one time." msgid_plural "only %d entries can be shown at one time." -msgstr[0] "само %d запис може да бъде показан наведнъж." -msgstr[1] "само %d записа може да бъде показани наведнъж." +msgstr[0] "само %d запис може да се покаже наведнъж." +msgstr[1] "само %d записа може да се покажат наведнъж." #, c-format msgid "no such ref %s" @@ -12898,14 +12982,14 @@ msgstr "" #, c-format msgid "failed to remove directory '%s'" -msgstr "директорията „%s“ не може да бъде изтрита" +msgstr "директорията „%s“ не може да се изтрие" msgid "failed to create directory for sparse-checkout file" -msgstr "директорията за частично изтегляне „%s“ не може да бъде създадена" +msgstr "директорията за частично изтегляне „%s“ не може да се създаде" #, c-format msgid "unable to fdopen %s" -msgstr "обектът „%s“ не може да бъде отворен с „fdopen“" +msgstr "обектът „%s“ не може да се отвори с „fdopen“" msgid "failed to initialize worktree config" msgstr "настройките на работното дърво не може да се инициализират" @@ -12933,7 +13017,7 @@ msgstr "пътят „%s“ не може да се нормализира" #, c-format msgid "unable to unquote C-style string '%s'" -msgstr "цитирането на низ, форматиран за C — „%s“ не може да бъде изчистено" +msgstr "цитирането на низ, форматиран за C — „%s“ не може да се изчисти" msgid "unable to load existing sparse-checkout patterns" msgstr "шаблоните за частично изтегляне не може да се заредят" @@ -13119,7 +13203,7 @@ msgstr "" "index“." msgid "could not save index tree" -msgstr "дървото сочено от индекса не може да бъде запазено" +msgstr "дървото сочено от индекса не може да се запази" #, c-format msgid "Merging %s with %s" @@ -13140,7 +13224,7 @@ msgstr "Изтрито: „%s“ (%s)" #, c-format msgid "%s: Could not drop stash entry" -msgstr "Скатаното „%s“ не може да бъде изтрито" +msgstr "Скатаното „%s“ не може да се изтрие" #, c-format msgid "'%s' is not a stash reference" @@ -13153,10 +13237,10 @@ msgid "No branch name specified" msgstr "Не е указано име на клон" msgid "failed to parse tree" -msgstr "дървото не може да бъде анализирано" +msgstr "дървото не може да се анализира" msgid "failed to unpack trees" -msgstr "дървото не може да бъде разпакетирано" +msgstr "дървото не може да се разпакетира" msgid "include untracked files in the stash" msgstr "скатаване и на неследените файлове" @@ -13166,7 +13250,7 @@ msgstr "извеждане само на неследените файлове #, c-format msgid "Cannot update %s with %s" -msgstr "Указателят „%s“ не може да бъде обновен да сочи към „%s“" +msgstr "Указателят „%s“ не може да се обнови да сочи към „%s“" msgid "stash message" msgstr "съобщение при скатаване" @@ -13184,19 +13268,19 @@ msgid "You do not have the initial commit yet" msgstr "Все още липсва първоначално подаване" msgid "Cannot save the current index state" -msgstr "Състоянието на текущия индекс не може да бъде запазено" +msgstr "Състоянието на текущия индекс не може да се запази" msgid "Cannot save the untracked files" msgstr "Неследените файлове не може да се запазят" msgid "Cannot save the current worktree state" -msgstr "Състоянието на работното дърво не може да бъде запазено" +msgstr "Състоянието на работното дърво не може да се запази" msgid "Cannot save the current staged state" -msgstr "Състоянието на текущия индекс не може да бъде запазено" +msgstr "Състоянието на текущия индекс не може да се запази" msgid "Cannot record working tree state" -msgstr "Състоянието на работното дърво не може да бъде запазено" +msgstr "Състоянието на работното дърво не може да се запази" msgid "Can't use --patch and --include-untracked or --all at the same time" msgstr "опцията „--patch“ е несъвместима с „--include-untracked“ и „--all“" @@ -13216,7 +13300,7 @@ msgid "Cannot initialize stash" msgstr "Скатаването не може да стартира" msgid "Cannot save the current status" -msgstr "Текущото състояние не може да бъде запазено" +msgstr "Текущото състояние не може да се запази" #, c-format msgid "Saved working directory and index state %s" @@ -13329,7 +13413,7 @@ msgstr "Във файла „.gitmodules“ липсва информация з #, c-format msgid "could not resolve HEAD ref inside the submodule '%s'" -msgstr "указателят сочен от „HEAD“ в подмодула „%s“ не може да бъде открит" +msgstr "указателят сочен от „HEAD“ в подмодула „%s“ липсва" #, c-format msgid "failed to recurse into submodule '%s'" @@ -13400,7 +13484,7 @@ msgstr "неуспешно регистриране на адрес за път #, c-format msgid "failed to update remote for submodule '%s'" -msgstr "отдалеченият адрес на подмодула „%s“ не може да бъде променен" +msgstr "отдалеченият адрес на подмодула „%s“ не може да се промени" msgid "suppress output of synchronizing submodule url" msgstr "без извеждане на информация при синхронизирането на подмодул" @@ -13432,11 +13516,11 @@ msgstr "Директорията „%s“ е изчистена\n" #, c-format msgid "Could not remove submodule work tree '%s'\n" msgstr "" -"Директорията към работното дърво на подмодула „%s“ не може да бъде изтрита\n" +"Директорията към работното дърво на подмодула „%s“ не може да се изтрие\n" #, c-format msgid "could not create empty submodule directory %s" -msgstr "празната директория за подмодула „%s“ не може да бъде създадена" +msgstr "празната директория за подмодула „%s“ не може да се създаде" #, c-format msgid "Submodule '%s' (%s) unregistered for path '%s'\n" @@ -13501,7 +13585,7 @@ msgstr "Неуспешно клониране на адреса „%s“ в пъ #, c-format msgid "could not get submodule directory for '%s'" -msgstr "директорията на подмодула „%s“ не може да бъде получена" +msgstr "директорията на подмодула „%s“ не може да се получи" msgid "alternative anchor for relative paths" msgstr "директория за определянето на относителните пътища" @@ -13726,7 +13810,7 @@ msgid "force creation" msgstr "принудително създаване" msgid "show whether the branch would be created" -msgstr "извеждане дали клонът ще бъде създаден" +msgstr "извеждане дали клонът ще се създаде" msgid "" "git submodule--helper create-branch [-f|--force] [--create-reflog] [-q|--" @@ -13775,7 +13859,7 @@ msgstr "Активиране на локалното хранилище за п #, c-format msgid "unable to checkout submodule '%s'" -msgstr "Подмодулът „%s“ не може да бъде изтеглен" +msgstr "Подмодулът „%s“ не може да се изтегли" msgid "please make sure that the .gitmodules file is in the working tree" msgstr "файлът „.gitmodules“ трябва да е в работното дърво" @@ -13924,7 +14008,7 @@ msgstr "" "изтриете вие.\n" msgid "unable to sign the tag" -msgstr "етикетът не може да бъде подписан" +msgstr "етикетът не може да се подпише" #, c-format msgid "" @@ -14047,15 +14131,15 @@ msgstr "Разпакетиране на обектите" #, c-format msgid "failed to create directory %s" -msgstr "директорията „%s“ не може да бъде създадена" +msgstr "директорията „%s“ не може да се създаде" #, c-format msgid "failed to delete file %s" -msgstr "файлът „%s“ не може да бъде изтрит" +msgstr "файлът „%s“ не може да се изтрие" #, c-format msgid "failed to delete directory %s" -msgstr "директорията „%s“ не може да бъде изтрита" +msgstr "директорията „%s“ не може да се изтрие" #, c-format msgid "Testing mtime in '%s' " @@ -14098,8 +14182,7 @@ msgid "git update-index [] [--] [...]" msgstr "git update-index [ОПЦИЯ…] [--] [ФАЙЛ…]" msgid "continue refresh even when index needs update" -msgstr "" -"продължаване с обновяването, дори когато индексът трябва да бъде обновен" +msgstr "продължаване с обновяването, дори когато индексът трябва да се обнови" msgid "refresh: ignore submodules" msgstr "подмодулите да се игнорират при обновяването" @@ -14283,8 +14366,8 @@ msgstr "" "git update-ref [ОПЦИЯ…] ИМЕ_НА_УКАЗАТЕЛ НОВ_ИДЕНТИФИКАТОР_НА_ОБЕКТ " "[СТАР_ИДЕНТИФИКАТОР_НА_ОБЕКТ]" -msgid "git update-ref [] --stdin [-z]" -msgstr "git update-ref [ОПЦИЯ…] --stdin [-z]" +msgid "git update-ref [] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [ОПЦИЯ…] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "изтриване на указателя" @@ -14300,6 +14383,9 @@ msgstr "" msgid "read updates from stdin" msgstr "изчитане на указателите от стандартния вход" +msgid "batch reference updates" +msgstr "пакетно обновяване на указатели" + msgid "update the info files from scratch" msgstr "обновяване на информационните файлове от нулата" @@ -14458,7 +14544,7 @@ msgstr "„%s“ не може да се изчисти в „%s“" #, c-format msgid "could not create directory of '%s'" -msgstr "директорията „%s“ не може да бъде създадена" +msgstr "директорията „%s“ не може да се създаде" msgid "initializing" msgstr "инициализация" @@ -14616,8 +14702,7 @@ msgstr "" #, c-format msgid "validation failed, cannot move working tree: %s" -msgstr "" -"проверките са неуспешни, работното дърво не може да бъде преместено: %s" +msgstr "проверките са неуспешни, работното дърво не може да се премести: %s" #, c-format msgid "failed to move '%s' to '%s'" @@ -14659,7 +14744,7 @@ msgstr "" #, c-format msgid "validation failed, cannot remove working tree: %s" -msgstr "проверките са неуспешни, работното дърво не може да бъде изтрито: %s" +msgstr "проверките са неуспешни, работното дърво не може да се изтрие: %s" #, c-format msgid "repair: %s: %s" @@ -14792,7 +14877,7 @@ msgid "unable to dup bundle descriptor" msgstr "неуспешно дублиране на дескриптора на пратката с „dup“" msgid "Could not spawn pack-objects" -msgstr "Командата „git pack-objects“ не може да бъде стартирана" +msgstr "Командата „git pack-objects“ не може да се стартира" msgid "pack-objects died" msgstr "Командата „git pack-objects“ не завърши успешно" @@ -14815,7 +14900,7 @@ msgstr "Създаването на празна пратка е невъзмо #, c-format msgid "cannot create '%s'" -msgstr "файлът „%s“ не може да бъде създаден" +msgstr "файлът „%s“ не може да се създаде" msgid "index-pack died" msgstr "командата „git index-pack“ не завърши успешно" @@ -15001,6 +15086,9 @@ msgstr "Сравняване на файлове от работното дър msgid "Compare a tree to the working tree or index" msgstr "Сравняване на обекти-дърво с работното дърво и индекса" +msgid "Compare the content and mode of provided blob pairs" +msgstr "Сравняване на съдържанието и режимите на двойките обекти-BLOB" + msgid "Compares the content and mode of blobs found via two tree objects" msgstr "" "Сравняване на съдържанието и права̀та за достъп на обектите-BLOB чрез два " @@ -15543,7 +15631,7 @@ msgstr "" #, c-format msgid "could not find commit %s" -msgstr "подаването „%s“ не може да бъде открито" +msgstr "подаването „%s“ липсва" msgid "commit-graph requires overflow generation data but has none" msgstr "" @@ -15603,7 +15691,7 @@ msgstr "" "правилният брой на идентификаторите в основния граф не може да се запише" msgid "unable to create temporary graph layer" -msgstr "не може да бъде създаден временен слой за гра̀фа с подаванията" +msgstr "не може да се създаде временен слой за гра̀фа с подаванията" #, c-format msgid "unable to adjust shared permissions for '%s'" @@ -15619,10 +15707,10 @@ msgid "unable to open commit-graph chain file" msgstr "файлът с веригата на гра̀фа с подаванията не може да се отвори" msgid "failed to rename base commit-graph file" -msgstr "основният файл на гра̀фа с подаванията не може да бъде преименуван" +msgstr "основният файл на гра̀фа с подаванията не може да се преименува" msgid "failed to rename temporary commit-graph file" -msgstr "временният файл на гра̀фа с подаванията не може да бъде преименуван" +msgstr "временният файл на гра̀фа с подаванията не може да се преименува" #, c-format msgid "cannot merge graphs with %, % commits" @@ -15723,7 +15811,7 @@ msgstr "Проверка на подаванията в гра̀фа" #, c-format msgid "could not parse commit %s" -msgstr "подаването „%s“ не може да бъде анализирано" +msgstr "подаването „%s“ не може да се анализира" #, c-format msgid "%s %s is not a commit!" @@ -15892,7 +15980,7 @@ msgstr "неуспешно изпълнение на closedir(„%s“)" #, c-format msgid "[GLE %ld] unable to open for read '%ls'" msgstr "" -"файлът „%2$ls“ не може да бъде отворен за четене [последна грешка в нишката: " +"файлът „%2$ls“ не може да се отвори за четене [последна грешка в нишката: " "GLE=%1$ld]" #, c-format @@ -15903,11 +15991,11 @@ msgstr "" #, c-format msgid "failed to copy SID (%ld)" -msgstr "идентификаторът за сигурност (SID=%ld) не може да бъде копиран" +msgstr "идентификаторът за сигурност (SID=%ld) не може да се копира" #, c-format msgid "failed to get owner for '%s' (%ld)" -msgstr "притежателят на „%s“ (%ld) не може да бъде получен" +msgstr "притежателят на „%s“ (%ld) не може да се получи" msgid "memory exhausted" msgstr "паметта е изчерпана" @@ -15967,10 +16055,10 @@ msgid "No previous regular expression" msgstr "Няма предхождащ регулярен израз" msgid "could not send IPC command" -msgstr "командата за комуникация между процеси не може да бъде пратена" +msgstr "командата за комуникация между процеси не може да се прати" msgid "could not read IPC response" -msgstr "отговорът за комуникацията между процеси не може да бъде прочетен" +msgstr "отговорът за комуникацията между процеси не може да се прочете" #, c-format msgid "could not start accept_thread '%s'" @@ -16021,7 +16109,7 @@ msgstr "" #, c-format msgid "could not expand include path '%s'" -msgstr "пътят за вмъкване „%s“не може да бъде разширен" +msgstr "пътят за вмъкване „%s“ не може да се разшири" msgid "relative config includes must come from files" msgstr "относителните вмъквания на конфигурации трябва да идват от файлове" @@ -16163,7 +16251,7 @@ msgstr "неправилна булева стойност „%s“ за „%s #, c-format msgid "failed to expand user dir in: '%s'" -msgstr "домашната папка на потребителя не може да бъде открита: „%s“" +msgstr "домашната папка на потребителя липсва: „%s“" #, c-format msgid "'%s' for '%s' is not a valid timestamp" @@ -16222,7 +16310,7 @@ msgstr "указателят „%s“ не сочи към обект-BLOB" #, c-format msgid "unable to resolve config blob '%s'" -msgstr "обектът-BLOB „%s“ с конфигурации не може да бъде открит" +msgstr "обектът-BLOB „%s“ с конфигурации липсва" msgid "unable to parse command-line config" msgstr "неправилни настройки от командния ред" @@ -16258,7 +16346,7 @@ msgstr "зададени са няколко стойности за „%s“" #, c-format msgid "failed to write new configuration file %s" -msgstr "новият конфигурационен файл „%s“ не може да бъде запазен" +msgstr "новият конфигурационен файл „%s“ не може да се запази" #, c-format msgid "no multi-line comment allowed: '%s'" @@ -16266,7 +16354,7 @@ msgstr "коментари на повече от един ред не са по #, c-format msgid "could not lock config file %s" -msgstr "конфигурационният файл „%s“ не може да бъде заключен" +msgstr "конфигурационният файл „%s“ не може да се заключи" #, c-format msgid "opening %s" @@ -16290,7 +16378,7 @@ msgstr "неуспешна смяна на права̀ с „chmod“ върх #, c-format msgid "could not write config file %s" -msgstr "конфигурационният файл „%s“ не може да бъде записан" +msgstr "конфигурационният файл „%s“ не може да се запише" #, c-format msgid "could not set '%s' to '%s'" @@ -16462,13 +16550,13 @@ msgid "unable to fork" msgstr "неуспешно създаване на процес" msgid "Could not run 'git rev-list'" -msgstr "Командата „git rev-list“ не може да бъде изпълнена." +msgstr "Командата „git rev-list“ не може да се изпълни." msgid "failed write to rev-list" msgstr "неуспешен запис на списъка с версиите" msgid "failed to close rev-list's stdin" -msgstr "стандартният вход на списъка с версиите не може да бъде затворен" +msgstr "стандартният вход на списъка с версиите не може да се затвори" #, c-format msgid "illegal crlf_action %d" @@ -16542,7 +16630,7 @@ msgstr "неуспешно създаване на процес за външе #, c-format msgid "cannot feed the input to external filter '%s'" -msgstr "входът не може да бъде подаден на външния филтър „%s“" +msgstr "входът не може да се подаде на външния филтър „%s“" #, c-format msgid "external filter '%s' failed %d" @@ -16689,7 +16777,7 @@ msgstr "неправилен обект-дърво: %s" #, c-format msgid "failed to load island regex for '%s': %s" -msgstr "регулярният израз на групата за „%s“, не може да бъде зареден: „%s“" +msgstr "регулярният израз на групата за „%s“, не може да се зареди: „%s“" #, c-format msgid "island regex from config has too many capture groups (max=%d)" @@ -16711,7 +16799,7 @@ msgstr "директорията „%s“ липсва и не може да с #, c-format msgid "could not open directory '%s'" -msgstr "директорията „%s“ не може да бъде отворена" +msgstr "директорията „%s“ не може да се отвори" #, c-format msgid "skipping '%s', which is neither file nor directory" @@ -16722,7 +16810,7 @@ msgstr "стандартният изход не може да се дублир #, c-format msgid "could not add directory '%s' to archiver" -msgstr "директорията „%s“ не може да бъде добавена към архива" +msgstr "директорията „%s“ не може да се добави към архива" msgid "failed to write archive" msgstr "неуспешен запис на архива" @@ -16731,7 +16819,7 @@ msgid "--merge-base does not work with ranges" msgstr "опцията „--merge-base“ не работи с диапазони" msgid "unable to get HEAD" -msgstr "Указателят „HEAD“ не може да бъде получен" +msgstr "Указателят „HEAD“ не може да се получи" msgid "no merge base found" msgstr "липсва база за сливане" @@ -16914,7 +17002,7 @@ msgid "generate diffs with lines context" msgstr "файловете с разлики да са с контекст с такъв БРОЙ редове" msgid "generate the diff in raw format" -msgstr "файловете с разлики да са в суров формат" +msgstr "файловете с разлики да са в необработен формат" msgid "synonym for '-p --raw'" msgstr "псевдоним на „-p --raw“" @@ -17266,7 +17354,7 @@ msgstr "задайте променливата „%s“ да е поне %d и #, c-format msgid "failed to read orderfile '%s'" -msgstr "файлът с подредбата на съответствията „%s“ не може да бъде прочетен" +msgstr "файлът с подредбата на съответствията „%s“ не може да се прочете" msgid "Performing inexact rename detection" msgstr "Търсене на преименувания на обекти съчетани с промѐни" @@ -17311,7 +17399,7 @@ msgid "" "No directory name could be guessed.\n" "Please specify a directory on the command line" msgstr "" -"Името на директорията не може да бъде отгатнато.\n" +"Името на директорията не може да се отгатне.\n" "Задайте директорията изрично на командния ред" #, c-format @@ -17523,7 +17611,7 @@ msgstr "грешка при обработка на потвържденията #. #, c-format msgid "expected packfile to be sent after '%s'" -msgstr "очаква се пакетният файл да бъде изпратен след „%s“" +msgstr "очаква се пакетният файл да се изпрати след „%s“" #. TRANSLATORS: The parameter will be 'ready', a protocol #. keyword. @@ -17552,7 +17640,7 @@ msgid "git fetch-pack: expected response end packet" msgstr "git fetch-pack: очаква се пакет за край на отговора" msgid "no matching remote head" -msgstr "не може да бъде открит подходящ връх от отдалеченото хранилище" +msgstr "липсва подходящ връх от отдалеченото хранилище" msgid "unexpected 'ready' from remote" msgstr "неочаквано състояние за готовност от отдалечено хранилище" @@ -17754,7 +17842,7 @@ msgstr "лош/несъвместим подпис „%s“" #, c-format msgid "failed to get the ssh fingerprint for key '%s'" -msgstr "отпечатъкът по ssh на ключа „%s“ не може да бъде получен" +msgstr "отпечатъкът по ssh на ключа „%s“ не може да се получи" msgid "" "either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured" @@ -17818,7 +17906,7 @@ msgstr "" #, c-format msgid "'%s': unable to read %s" -msgstr "„%s“: файлът сочен от „%s“ не може да бъде прочетен" +msgstr "„%s“: файлът сочен от „%s“ не може да се прочете" #, c-format msgid "'%s': short read" @@ -17903,7 +17991,7 @@ msgid "" "able to execute it. Maybe git-%s is broken?" msgstr "" "Изглежда, че „%s“ е команда на git, но тя не може да\n" -"бъде изпълнена. Вероятно пакетът „git-%s“ е повреден." +"се изпълни. Вероятно пакетът „git-%s“ е повреден." #, c-format msgid "git: '%s' is not a git command. See 'git --help'." @@ -17994,6 +18082,10 @@ msgstr "Управлението на делегирането не се под msgid "Unknown value for http.proactiveauth" msgstr "Непозната стойност за „http.proactiveauth“" +#, c-format +msgid "failed to parse %s" +msgstr "„%s“ не може да се анализира" + #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Неподдържана реализация на SSL „%s“. Поддържат се:" @@ -18064,15 +18156,14 @@ msgstr "липсва адрес за е-поща, а автоматичното #, c-format msgid "unable to auto-detect email address (got '%s')" msgstr "" -"адресът за е-поща не може да бъде отгатнат (най-доброто предположение бе " -"„%s“)" +"адресът за е-поща не може да се отгатне (най-доброто предположение бе „%s“)" msgid "no name was given and auto-detection is disabled" msgstr "липсва име, а автоматичното отгатване е изключено" #, c-format msgid "unable to auto-detect name (got '%s')" -msgstr "името не може да бъде отгатнато (най-доброто предположение бе „%s“)" +msgstr "името не може да се отгатне (най-доброто предположение бе „%s“)" #, c-format msgid "empty ident name (for <%s>) not allowed" @@ -18148,7 +18239,7 @@ msgid "" "may have crashed in this repository earlier:\n" "remove the file manually to continue." msgstr "" -"Файлът-ключалка „%s.lock“ не може да бъде създаден: %s\n" +"Файлът-ключалка „%s.lock“ не може да се създаде: %s\n" "\n" "Изглежда, че и друг процес на git е пуснат в това хранилище, напр.\n" "редактор, стартиран с „git commit“. Уверете се, че всички подобни\n" @@ -18158,10 +18249,10 @@ msgstr "" #, c-format msgid "Unable to create '%s.lock': %s" -msgstr "Файлът-ключалка „%s.lock“ не може да бъде създаден: %s" +msgstr "Файлът-ключалка „%s.lock“ не може да се създаде: %s" msgid "unable to create temporary object directory" -msgstr "не може да бъде създадена директория за временни обекти" +msgstr "не може да се създаде директория за временни обекти" #, c-format msgid "could not write loose object index %s" @@ -18189,6 +18280,10 @@ msgstr "съобщението не може да се форматира: %s" msgid "invalid marker-size '%s', expecting an integer" msgstr "неправилен размер на маркер: „%s“, изисква се цяло число" +#, c-format +msgid "Could not parse object '%s'" +msgstr "Неуспешен анализ на обекта „%s“" + #, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Неуспешно сливане на подмодула „%s“ (не е изтеглен)" @@ -18208,7 +18303,7 @@ msgstr "ГРЕШКА: неуспешно сливане на подмодула #, c-format msgid "Failed to merge submodule %s (commits don't follow merge-base)" msgstr "" -"Подмодулът „%s“ не може да бъде слят (базата за сливане не предшества " +"Подмодулът „%s“ не може да се слее (базата за сливане не предшества " "подаванията)" #, c-format @@ -18433,292 +18528,23 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "неуспешно събиране на информацията за сливането на „%s“, „%s“ и „%s“" -msgid "(bad commit)\n" -msgstr "(лошо подаване)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "" -"неуспешно изпълнение на „add_cacheinfo“ за пътя „%s“. Сливането е " -"преустановено." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "" -"неуспешно изпълнение на „add_cacheinfo“ за обновяването на пътя „%s“. " -"Сливането е преустановено." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "грешка при създаването на пътя „%s“%s" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Изтриване на „%s“, за да се освободи място за поддиректория\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": възможно е да има конфликт директория/файл." - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "" -"преустановяване на действието, за да не се изтрие неследеният файл „%s“" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "обектът „%s“ (%s) се очакваше да е BLOB, а не е" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "„%s“ не може да се отвори: %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "неуспешно създаване на символната връзка „%s“: %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "" -"не е ясно какво да се прави с обекта „%2$s“ (%3$s) с права̀ за достъп „%1$06o“" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Неуспешно сливане на подмодула „%s“ (хранилището е с грешки)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "Превъртане на подмодула „%s“ до следното подаване:" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "Превъртане на подмодула „%s“" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"Неуспешно сливане на подмодула „%s“ (липсва сливането, което се предшества " -"от подаванията)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Неуспешно сливане на подмодула „%s“ (не е превъртане)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "" -"Открито е сливане, което може да решава проблема със сливането на " -"подмодула:\n" - -#, c-format -msgid "" -"If this is correct simply add it to the index for example\n" -"by using:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"which will accept this suggestion.\n" -msgstr "" -"Ако това е така, добавете го към индекса с команда като следната:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"Това приема предложеното.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "Неуспешно сливане на подмодула „%s“ (открити са множество сливания)" - -msgid "failed to execute internal merge" -msgstr "неуспешно вътрешно сливане" - -#, c-format -msgid "unable to add %s to database" -msgstr "„%s“ не може да се добави в базата от данни" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "Грешка: за да не се изтрие неследеният файл „%s“, се записва в „%s“." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"КОНФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ в %s. Версия %s на „%s“ " -"е оставена в дървото." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"КОНФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ е преименуван на „%s“ в " -"%s. Версия %s на „%s“ е оставена в дървото." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"КОНФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ в %s. Версия %s на „%s“ " -"е оставена в дървото: %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"КОНФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ е преименуван на „%s“ в " -"%s. Версия %s на „%s“ е оставена в дървото: %s." - -msgid "rename" -msgstr "преименуване" - -msgid "renamed" -msgstr "преименуван" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "Преустановяване на действието, за да не се изгуби промененият „%s“" - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "" -"Отказ да се загуби неследеният файл „%s“, защото е на място, където пречи." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"КОНФЛИКТ (преименуване/добавяне): „%s“ е преименуван на „%s“ в клон „%s“, а " -"„%s“ е добавен в „%s“" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "„%s“ е директория в „%s“, затова се добавя като „%s“" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "" -"Преустановяване на действието, за да не се изгуби неследеният файл „%s“. " -"Вместо него се добавя „%s“" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"КОНФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " -"„%s“, а „%s“ е преименуван на „%s“ в „%s“/%s." - -msgid " (left unresolved)" -msgstr " (некоригиран конфликт)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"КОНФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " -"„%s“, а „%s“ е преименуван на „%s“ в „%s“" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"КОНФЛИКТ (раздвояване при преименуване на директория): Не е ясно къде да се " -"постави „%s“, защото няколко нови директории поделят съдържанието на " -"директория „%s“, като никоя не съдържа мнозинство от файловете ѝ." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"КОНФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " -"„%s“, а „%s“ е преименуван на „%s“ в „%s“" - -#, c-format -msgid "cannot read object %s" -msgstr "обектът „%s“ не може да се прочете" - -#, c-format -msgid "object %s is not a blob" -msgstr "обектът „%s“ не е BLOB" - -msgid "modify" -msgstr "промяна" - -msgid "modified" -msgstr "променен" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "Прескачане на „%s“ (слетият резултат е идентичен със сегашния)" - -#, c-format -msgid "Adding as %s instead" -msgstr "Добавяне като „%s“" - -#, c-format -msgid "Removing %s" -msgstr "Изтриване на „%s“" - -msgid "file/directory" -msgstr "файл/директория" - -msgid "directory/file" -msgstr "директория/файл" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"КОНФЛИКТ (%s): Съществува директория на име „%s“ в „%s“. Добавяне на „%s“ " -"като „%s“" - -#, c-format -msgid "Adding %s" -msgstr "Добавяне на „%s“" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "КОНФЛИКТ (добавяне/добавяне): Конфликт при сливане на „%s“" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "неуспешно сливане на дърветата „%s“ и „%s“" - -msgid "Merging:" -msgstr "Сливане:" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "открит е %u общ предшественик:" -msgstr[1] "открити са %u общи предшественици:" - -msgid "merge returned no commit" -msgstr "сливането не върна подаване" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "Неуспешен анализ на обекта „%s“" - msgid "failed to read the cache" -msgstr "кешът не може да бъде прочетен" +msgstr "кешът не може да се прочете" #, c-format msgid "failed to add packfile '%s'" -msgstr "пакетният файл „%s“ не може да бъде добавен" +msgstr "пакетният файл „%s“ не може да се добави" #, c-format msgid "failed to open pack-index '%s'" -msgstr "индексът за пакети „%s“ не може да бъде отворен" +msgstr "индексът за пакети „%s“ не може да се отвори" #, c-format msgid "failed to locate object %d in packfile" msgstr "обект %d в пакетния файл липсва" msgid "cannot store reverse index file" -msgstr "файлът за индекса не може да бъде съхранен" +msgstr "файлът за индекса не може да се съхрани" #, c-format msgid "could not parse line: %s" @@ -18741,17 +18567,17 @@ msgstr "не може да се създаде връзка „%s“, която #, c-format msgid "failed to clear multi-pack-index at %s" -msgstr "индексът за множество пакети не може да бъде изчистен при „%s“" - -msgid "cannot write incremental MIDX with bitmap" -msgstr "" -"нарастващият индекс за множество пакети с битова маска не може да се запише" +msgstr "индексът за множество пакети не може да се изчисти при „%s“" msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "" "индексът за множество пакети се прескача, защото сумата за проверка не " "съвпада" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "файлът с обратния индекс за множество пакети „%s“ не може да се зареди" + msgid "Adding packfiles to multi-pack-index" msgstr "Добавяне на пакетни файлове към индекс за множество пакети" @@ -18776,14 +18602,13 @@ msgid "no pack files to index." msgstr "няма пакетни файлове за индексиране" msgid "refusing to write multi-pack .bitmap without any objects" -msgstr "" -"многопакетната битова маска без никакви обекти не може да бъде запазена" +msgstr "многопакетната битова маска без никакви обекти не може да се запази" msgid "unable to create temporary MIDX layer" msgstr "не може да се създаде временен слой за индекса за множество пакети" msgid "could not write multi-pack bitmap" -msgstr "многопакетната битова маска не може да бъде запазена" +msgstr "многопакетната битова маска не може да се запази" msgid "unable to open multi-pack-index chain file" msgstr "файлът с веригата на гра̀фа с подаванията не може да се отвори" @@ -18809,10 +18634,10 @@ msgid "cannot repack an incremental multi-pack-index" msgstr "нарастващият индекс за множество пакети не може да се препакетира" msgid "could not start pack-objects" -msgstr "командата „pack-objects“ не може да бъде стартирана" +msgstr "командата „pack-objects“ не може да се стартира" msgid "could not finish pack-objects" -msgstr "командата „pack-objects“ не може да бъде завършена" +msgstr "командата „pack-objects“ не може да завърши" msgid "multi-pack-index OID fanout is of the wrong size" msgstr "" @@ -18929,8 +18754,7 @@ msgstr "" msgid "multi-pack-index file exists, but failed to parse" msgstr "" -"файлът с индекса за множество пакети съществува, но не може да бъде " -"анализиран" +"файлът с индекса за множество пакети съществува, но не може да се анализира" msgid "incorrect checksum" msgstr "неправилна сума за проверка" @@ -18959,11 +18783,11 @@ msgstr "Проверка на отместването на обекти" #, c-format msgid "failed to load pack entry for oid[%d] = %s" -msgstr "записът в пакета за обекта oid[%d] = %s не може да бъде зареден" +msgstr "записът в пакета за обекта oid[%d] = %s не може да се зареди" #, c-format msgid "failed to load pack-index for packfile %s" -msgstr "индексът на пакета „%s“ не може да бъде зареден" +msgstr "индексът на пакета „%s“ не може да се зареди" #, c-format msgid "incorrect object offset for oid[%d] = %s: % != %" @@ -19004,7 +18828,7 @@ msgstr "" msgid "Cannot commit uninitialized/unreferenced notes tree" msgstr "" -"Неинициализирано или нереферирано дърво за бележки не може да бъде подадено" +"Неинициализирано или нереферирано дърво за бележки не може да се подаде" #, c-format msgid "Bad notes.rewriteMode value: '%s'" @@ -19042,68 +18866,6 @@ msgstr "не може да се открие съответствието на msgid "Failed to convert object from %s to %s" msgstr "Неуспешно преобразуване на „%s“ към „%s“" -#, c-format -msgid "object directory %s does not exist; check .git/objects/info/alternates" -msgstr "" -"директорията за обекти „%s“ не съществува, проверете „.git/objects/info/" -"alternates“" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "алтернативният път към обекти не може да бъде нормализиран: „%s“" - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "" -"%s: алтернативните хранилища за обекти се пренебрегват поради прекалено " -"дълбоко влагане" - -msgid "unable to fdopen alternates lockfile" -msgstr "заключващият файл за алтернативите не може да се отвори с „fdopen“" - -msgid "unable to read alternates file" -msgstr "файлът с алтернативите не може да бъде прочетен" - -msgid "unable to move new alternates file into place" -msgstr "новият файл с алтернативите не може да бъде преместен на мястото му" - -#, c-format -msgid "path '%s' does not exist" -msgstr "пътят „%s“ не съществува." - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "все още не се поддържа еталонно хранилище „%s“ като свързано." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "еталонното хранилище „%s“ не е локално" - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "еталонното хранилище „%s“ е плитко" - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "еталонното хранилище „%s“ е с присаждане" - -#, c-format -msgid "could not find object directory matching %s" -msgstr "директорията с обекти, която отговаря на „%s“, не може да бъде открита" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "неправилен ред при анализа на алтернативните указатели: „%s“" - -#, c-format -msgid "attempting to mmap % over limit %" -msgstr "" -"неуспешен опит за „mmap“ %, което е над позволеното %" - -#, c-format -msgid "mmap failed%s" -msgstr "неуспешно изпълнение на „mmap“%s" - #, c-format msgid "object file %s is empty" msgstr "файлът с обектите „%s“ е празен" @@ -19122,14 +18884,14 @@ msgstr "непакетираният обект „%s“ не може да се #, c-format msgid "unable to parse %s header" -msgstr "заглавната част на „%s“ не може да бъде анализирана" +msgstr "заглавната част на „%s“ не може да се анализира" msgid "invalid object type" msgstr "неправилен вид обект" #, c-format msgid "unable to unpack %s header" -msgstr "заглавната част на „%s“ не може да бъде разпакетирана" +msgstr "заглавната част на „%s“ не може да се разпакетира" #, c-format msgid "header for %s too long, exceeds %d bytes" @@ -19139,21 +18901,9 @@ msgstr "заглавната част на „%s“ е прекалено дъл msgid "loose object %s (stored in %s) is corrupt" msgstr "непакетираният обект „%s“ (в „%s“) е повреден" -#, c-format -msgid "replacement %s not found for %s" -msgstr "заместителят „%s“ на „%s“ не може да бъде открит" - -#, c-format -msgid "packed object %s (stored in %s) is corrupt" -msgstr "пакетираният обект „%s“ (в „%s“) е повреден" - -#, c-format -msgid "missing mapping of %s to %s" -msgstr "липсва съответствие на „%s“ към „%s“" - #, c-format msgid "unable to open %s" -msgstr "обектът „%s“ не може да бъде отворен" +msgstr "обектът „%s“ не може да се отвори" #, c-format msgid "files '%s' and '%s' differ in contents" @@ -19161,11 +18911,11 @@ msgstr "съдържанието на файловете „%s“ и „%s“ е #, c-format msgid "unable to write file %s" -msgstr "файлът „%s“ не може да бъде записан" +msgstr "файлът „%s“ не може да се запише" #, c-format msgid "unable to write repeatedly vanishing file %s" -msgstr "смаляващият се файл „%s“ не може да бъде записван" +msgstr "смаляващият се файл „%s“ не може да се запише" #, c-format msgid "unable to set permission to '%s'" @@ -19180,7 +18930,7 @@ msgstr "" "няма права̀ за добавяне на обект към базата от данни на хранилището „%s“" msgid "unable to create temporary file" -msgstr "не може да бъде създаден временен файл" +msgstr "не може да се създаде временен файл" msgid "unable to write loose object file" msgstr "грешка при записа на файла с непакетиран обект" @@ -19211,7 +18961,7 @@ msgstr "неуспешно изпълнение на „deflateEnd“ върху #, c-format msgid "unable to create directory %s" -msgstr "директорията „%s“ не може да бъде създадена" +msgstr "директорията „%s“ не може да се създаде" #, c-format msgid "cannot read object for %s" @@ -19244,10 +18994,6 @@ msgstr "„%s“ не може да се вмъкне в базата от да msgid "%s: unsupported file type" msgstr "неподдържан вид файл: „%s“" -#, c-format -msgid "%s is not a valid '%s' object" -msgstr "„%s“ е неправилен обект от вид „%s“" - #, c-format msgid "hash mismatch for %s (expected %s)" msgstr "неправилна контролна сума за „%s“ (трябва да е %s)" @@ -19258,15 +19004,20 @@ msgstr "неуспешно изпълнение на „mmap“ върху „%s #, c-format msgid "unable to unpack header of %s" -msgstr "заглавната част на „%s“ не може да бъде разпакетирана" +msgstr "заглавната част на „%s“ не може да се разпакетира" #, c-format msgid "unable to parse header of %s" -msgstr "заглавната част на „%s“ не може да бъде анализирана" +msgstr "заглавната част на „%s“ не може да се анализира" + +#, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "" +"заглавната част „%s“ на %s не може да се анализира, за да се определи видът" #, c-format msgid "unable to unpack contents of %s" -msgstr "съдържанието на „%s“ не може да бъде разпакетирано" +msgstr "съдържанието не може да се разпакетира: „%s“" #. TRANSLATORS: This is a line of ambiguous object #. output shown when we cannot look up or parse the @@ -19422,6 +19173,75 @@ msgstr "необходими са и двете — ОБЕКТ:ПЪТ, а е д msgid "invalid object name '%.*s'." msgstr "неправилно име на обект: „%.*s“" +#, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "" +"директорията за обекти „%s“ не съществува, проверете „.git/objects/info/" +"alternates“" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "алтернативният път към обекти не може да се нормализира: „%s“" + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "" +"%s: алтернативните хранилища за обекти се пренебрегват поради прекалено " +"дълбоко влагане" + +msgid "unable to fdopen alternates lockfile" +msgstr "заключващият файл за алтернативите не може да се отвори с „fdopen“" + +msgid "unable to read alternates file" +msgstr "файлът с алтернативите не може да се прочете" + +msgid "unable to move new alternates file into place" +msgstr "новият файл с алтернативите не може да се премести на мястото си" + +#, c-format +msgid "path '%s' does not exist" +msgstr "пътят „%s“ не съществува." + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "все още не се поддържа еталонно хранилище „%s“ като свързано." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "еталонното хранилище „%s“ не е локално" + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "еталонното хранилище „%s“ е плитко" + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "еталонното хранилище „%s“ е с присаждане" + +#, c-format +msgid "could not find object directory matching %s" +msgstr "директорията с обекти, която отговаря на „%s“, не може да се открие" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "неправилен ред при анализа на алтернативните указатели: „%s“" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "заместителят „%s“ на „%s“ липсва" + +#, c-format +msgid "packed object %s (stored in %s) is corrupt" +msgstr "пакетираният обект „%s“ (в „%s“) е повреден" + +#, c-format +msgid "missing mapping of %s to %s" +msgstr "липсва съответствие на „%s“ към „%s“" + +#, c-format +msgid "%s is not a valid '%s' object" +msgstr "„%s“ е неправилен обект от вид „%s“" + #, c-format msgid "invalid object type \"%s\"" msgstr "неправилен вид обект: „%s“" @@ -19436,7 +19256,7 @@ msgstr "обектът „%s“ е непознат вид: %d" #, c-format msgid "unable to parse object: %s" -msgstr "обектът „%s“ не може да бъде анализиран" +msgstr "обектът „%s“ не може да се анализира" #, c-format msgid "hash mismatch %s" @@ -19603,7 +19423,7 @@ msgstr "„%s“ липсва в пакет „%s“ при отместване #, c-format msgid "unable to get disk usage of '%s'" -msgstr "използваното място за съхранение на „%s“ не може да бъде получено" +msgstr "използваното място за съхранение на „%s“ не може да се получи" #, c-format msgid "bitmap file '%s' has invalid checksum" @@ -19735,6 +19555,14 @@ msgstr "опцията „%s“ не приема аргументи" msgid "%s isn't available" msgstr "опцията „%s“ не е налична" +#, c-format +msgid "value %s for %s not in range [%,%]" +msgstr "стойността %s за „%s“ е извън диапазона [%,%]" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "„%s“ очаква цяло число, евентуално със суфикс „k“/„m“/„g“" + #, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "" @@ -19895,10 +19723,6 @@ msgstr "" msgid "bad boolean environment value '%s' for '%s'" msgstr "неправилна булева стойност „%s“ за „%s“" -#, c-format -msgid "failed to parse %s" -msgstr "„%s“ не може да бъде анализиран" - #, c-format msgid "failed to walk children of tree %s: not found" msgstr "неуспешно обхождане на дъщерните елементи на дървото „%s“: то липсва" @@ -20064,8 +19888,12 @@ msgid "could not fetch %s from promisor remote" msgstr "„%s“ не може да се достави от гарантиращото хранилище" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "има хранилище с име „%s“, но адресът му сочи към „%s“, а не към „%s“" +msgid "no or empty URL advertised for remote '%s'" +msgstr "липсващ или празен адрес за отдалечено хранилище „%s“" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "има хранилище с име „%s“, но адресът му е „%s“, а не „%s“" #, c-format msgid "unknown '%s' value for '%s' config option" @@ -20088,7 +19916,7 @@ msgstr "Изтриване на повтарящите се обекти" #, c-format msgid "failed to load pseudo-merge regex for %s: '%s'" msgstr "" -"регулярният израз за псевдо сливания за „%s“, не може да бъде зареден: „%s“" +"регулярният израз за псевдо сливания за „%s“, не може да се зареди: „%s“" #, c-format msgid "%s must be non-negative, using default" @@ -20154,7 +19982,7 @@ msgstr "" #, c-format msgid "could not parse commit '%s'" -msgstr "подаването „%s“ не може да бъде анализирано" +msgstr "подаването „%s“ не може да се анализира" #, c-format msgid "" @@ -20173,7 +20001,7 @@ msgstr "неуспешно търсене на разлика" #, c-format msgid "could not parse log for '%s'" -msgstr "журналът с подаванията на „%s“ не може да бъде анализиран" +msgstr "журналът с подаванията на „%s“ не може да се анализира" #, c-format msgid "invalid extra cruft tip: '%s'" @@ -20185,7 +20013,7 @@ msgstr "допълнителните скорошни обекти не може #, c-format msgid "will not add file alias '%s' ('%s' already exists in index)" msgstr "" -"няма да бъде добавен псевдоним за файл „%s“ („%s“ вече съществува в индекса)" +"няма да се добави псевдоним за файл „%s“ („%s“ вече съществува в индекса)" msgid "cannot create an empty blob in the object database" msgstr "в базата от данни за обектите не може да се създаде празен обект-BLOB" @@ -20198,7 +20026,7 @@ msgstr "" #, c-format msgid "unable to index file '%s'" -msgstr "файлът „%s“ не може да бъде индексиран" +msgstr "файлът „%s“ не може да се индексира" #, c-format msgid "unable to add '%s' to index" @@ -20319,7 +20147,7 @@ msgid "cannot write split index for a sparse index" msgstr "не може да се запише разделѐн, частичен индекс" msgid "failed to convert to a sparse-index" -msgstr "индексът не може да бъде превърнат в частичен" +msgstr "индексът не може да се превърне в частичен" #, c-format msgid "unable to open git dir: %s" @@ -20438,7 +20266,7 @@ msgid "" "If you remove a line here THAT COMMIT WILL BE LOST.\n" msgstr "" "\n" -"Ако изтриете ред, съответстващото му подаване ще бъде ИЗТРИТО.\n" +"Ако изтриете ред, съответстващото му подаване ще се ИЗТРИЕ.\n" msgid "" "\n" @@ -20460,7 +20288,7 @@ msgid "" "\n" msgstr "" "\n" -"Ако изтриете всичко, пребазирането ще бъде преустановено.\n" +"Ако изтриете всичко, пребазирането ще се преустанови.\n" "\n" #, c-format @@ -20745,7 +20573,7 @@ msgstr "" #, c-format msgid "could not retrieve `%s`" -msgstr "„%s“ не може да бъде получен" +msgstr "„%s“ не може да се получи" #, c-format msgid "invalid branch name: %s = %s" @@ -20812,7 +20640,7 @@ msgstr "невъзможно е едновременно да се обрабо #, c-format msgid "could not delete reference %s: %s" -msgstr "Указателят „%s“ не може да бъде изтрит: %s" +msgstr "Указателят „%s“ не може да се изтрие: %s" #, c-format msgid "could not delete references: %s" @@ -20843,11 +20671,15 @@ msgstr "файлът с указател „%s“ не може да се про #, c-format msgid "cannot open directory %s" -msgstr "директорията „%s“ не може да бъде отворена" +msgstr "директорията „%s“ не може да се отвори" msgid "Checking references consistency" msgstr "Проверка на валидността на указателите" +#, c-format +msgid "unable to open '%s'" +msgstr "„%s“ не може да се отвори" + #, c-format msgid "refname is dangerous: %s" msgstr "опасно име на указател: %s" @@ -20914,16 +20746,12 @@ msgstr "стекът не може да се свие: %s" #, c-format msgid "refname %s not found" -msgstr "името на указателя „%s“ не може да бъде открито" +msgstr "името на указателя „%s“ не може да се открие" #, c-format msgid "refname %s is a symbolic ref, copying it is not supported" msgstr "името на указател „%s“ е символен указател, не може да се копира" -#, c-format -msgid "invalid refspec '%s'" -msgstr "неправилен указател: „%s“" - #, c-format msgid "pattern '%s' has no '*'" msgstr "шаблонът „%s“ не съдържа „*“" @@ -21003,13 +20831,12 @@ msgstr "толкова големи изтласквания не може да #, c-format msgid "cannot deflate request; zlib deflate error %d" msgstr "" -"заявката не може да бъде декомпресирана, грешка от „zlib“ при " -"декомпресиране: %d" +"заявката не може да се декомпресира, грешка от „zlib“ при декомпресиране: %d" #, c-format msgid "cannot deflate request; zlib end error %d" msgstr "" -"заявката не може да бъде декомпресирана; грешка от „zlib“ при завършване: %d<" +"заявката не може да се декомпресира; грешка от „zlib“ при завършване: %d" #, c-format msgid "%d bytes of length header were received" @@ -21071,8 +20898,7 @@ msgid "" "If you cannot, please let us know why you still need to use it by\n" "sending an e-mail to ." msgstr "" -"изчитането на отдалеченото хранилище от „%s/%s“ предстои да бъде " -"премахнато.\n" +"изчитането на отдалеченото хранилище от „%s/%s“ предстои да се премахне.\n" "Ако все още ползвате директорията „remotes/“, препоръчваме да я мигрирате\n" "към следящи директории на база настройки чрез командата:\n" "\n" @@ -21244,7 +21070,7 @@ msgstr "простото (simple) изтласкване не съответст #, c-format msgid "couldn't find remote ref %s" -msgstr "отдалеченият указател „%s“ не може да бъде открит" +msgstr "отдалеченият указател „%s“ липсва" #, c-format msgid "* Ignoring funny ref '%s' locally" @@ -21282,8 +21108,8 @@ msgstr " (публикувайте локалните промѐни чрез msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n" msgid_plural "" "Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n" -msgstr[0] "Клонът ви е с %2$d подаване зад „%1$s“ и може да бъде превъртян.\n" -msgstr[1] "Клонът ви е с %2$d подавания зад „%1$s“ и може да бъде превъртян.\n" +msgstr[0] "Клонът ви е с %2$d подаване зад „%1$s“ и може да се превърти.\n" +msgstr[1] "Клонът ви е с %2$d подавания зад „%1$s“ и може да се превърти.\n" msgid " (use \"git pull\" to update your local branch)\n" msgstr " (обновете локалния си клон чрез „git pull“)\n" @@ -21308,7 +21134,7 @@ msgstr " (слейте отдалечения клон в локалния чр #, c-format msgid "cannot parse expected object name '%s'" -msgstr "очакваното име на обект „%s“ не може да бъде анализирано" +msgstr "очакваното име на обект „%s“ не може да се анализира" #, c-format msgid "cannot strip one component off url '%s'" @@ -21330,7 +21156,7 @@ msgid "corrupt MERGE_RR" msgstr "повреден „MERGE_RR“ (запис за коригиране на конфликт)" msgid "unable to write rerere record" -msgstr "приложеното коригиране на конфликт не може да бъде записано" +msgstr "приложеното коригиране на конфликт не може да се запише" #, c-format msgid "there were errors while writing '%s' (%s)" @@ -21400,7 +21226,7 @@ msgstr "не може да се определи към какво да сочи #, c-format msgid "failed to find tree of %s" -msgstr "дървото, сочено от „%s“, не може да бъде открито" +msgstr "дървото, сочено от „%s“, не може да се открие" #, c-format msgid "unsupported section for hidden refs: %s" @@ -21428,7 +21254,7 @@ msgstr "" #, c-format msgid "could not get commit for --ancestry-path argument %s" -msgstr "подаването „%s“ към опцията „--ancestry-path“ не може да бъде получено" +msgstr "подаването „%s“ към опцията „--ancestry-path“ не може да се получи" msgid "--unpacked= no longer supported" msgstr "опцията „--unpacked=ПАКЕТЕН_ФАЙЛ“ вече не се поддържа" @@ -21483,11 +21309,11 @@ msgstr "директория не може да се зачисли" msgid "could not set recommended config" msgstr "препоръчаните настройки не може да се зададат" -msgid "could not turn on maintenance" -msgstr "задачите по поддръжка не може да се включат" +msgid "could not toggle maintenance" +msgstr "режимът на задачите по поддръжка не може да се превключи" msgid "could not start the FSMonitor daemon" -msgstr "фоновият процес на FSMonitor не може да бъде спрян" +msgstr "фоновият процес на FSMonitor не може да се спре" msgid "could not turn off maintenance" msgstr "задачите по поддръжка не може да се изключат" @@ -21508,13 +21334,13 @@ msgid "failed to get default branch name" msgstr "неуспешно получаване на името на стандартния клон" msgid "failed to unregister repository" -msgstr "хранилището не може да бъде отчислено" +msgstr "хранилището не може да се отчисли" msgid "failed to stop the FSMonitor daemon" -msgstr "фоновият процес FSMonitor не може да бъде спрян" +msgstr "фоновият процес FSMonitor не може да се спре" msgid "failed to delete enlistment directory" -msgstr "зачислената директория не може да бъде изтрита" +msgstr "зачислената директория не може да се изтрие" msgid "branch to checkout after clone" msgstr "към кой клон да се премине след клониране" @@ -21531,12 +21357,16 @@ msgstr "създаване на хранилище в директория „sr msgid "specify if tags should be fetched during clone" msgstr "указва дали етикетите да се доставят при клониране" +msgid "specify if background maintenance should be enabled" +msgstr "дали на заден фон да се изпълняват задачи за поддръжката" + msgid "" "scalar clone [--single-branch] [--branch ] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] []" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] []" msgstr "" "scalar clone [--single-branch] [--branch ОСНОВЕН_КЛОН] [--full-clone]\n" -" [--[no-]src] [--[no-]tags] АДРЕС [ЗАЧИСЛЕНА_ДИРЕКТОРИЯ]" +" [--[no-]src] [--[no-]tags] [--[no-]maintenance] АДРЕС " +"[ЗАЧИСЛЕНА_ДИРЕКТОРИЯ]" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -21548,7 +21378,7 @@ msgstr "директорията „%s“ вече съществува" #, c-format msgid "failed to get default branch for '%s'" -msgstr "основният клон на „%s“ не може да бъде получен" +msgstr "основният клон на „%s“ не може да се получи" #, c-format msgid "could not configure remote in '%s'" @@ -21574,18 +21404,32 @@ msgstr "scalar diagnose [ЗАЧИСЛЕНА_ДИРЕКТОРИЯ]" msgid "`scalar list` does not take arguments" msgstr "„scalar list“ не приема аргументи" -msgid "scalar register []" -msgstr "scalar register [ЗАЧИСЛЕНА_ДИРЕКТОРИЯ]" +msgid "scalar register [--[no-]maintenance] []" +msgstr "scalar register [--[no-]maintenance] [ЗАЧИСЛЕНА_ДИРЕКТОРИЯ]" msgid "reconfigure all registered enlistments" msgstr "пренастройване на всички зачислени директории" -msgid "scalar reconfigure [--all | ]" -msgstr "scalar reconfigure [--all|ЗАЧИСЛЕНА_ДИРЕКТОРИЯ]" +msgid "(enable|disable|keep)" +msgstr "(enable=включване|disable=изключване|keep=запазване)" + +msgid "signal how to adjust background maintenance" +msgstr "как да се промени поддръжката на заден фон" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all|" +"ЗАЧИСЛЕНА_ДИРЕКТОРИЯ]" msgid "--all or , but not both" msgstr "опцията „--all“ и указването на зачислена директория не са съвместими" +#, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "непознат режим за „--maintenance“: „%s“" + #, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "остарялото скаларно хранилище (scalar.repo) „%s“ не може да се изтрие" @@ -21633,7 +21477,7 @@ msgid "scalar delete " msgstr "scalar delete ЗАЧИСЛЕНА_ДИРЕКТОРИЯ" msgid "refusing to delete current working directory" -msgstr "текущата работна директория няма да бъде изтрита" +msgstr "текущата работна директория няма да се изтрие" msgid "include Git version" msgstr "включване и на версията на git" @@ -21670,15 +21514,14 @@ msgstr "" #, c-format msgid "unable to parse remote unpack status: %s" -msgstr "" -"състоянието от отдалеченото разпакетиране не може да бъде анализирано: %s" +msgstr "състоянието от отдалеченото разпакетиране не може да се анализира: %s" #, c-format msgid "remote unpack failed: %s" msgstr "неуспешно отдалечено разпакетиране: %s" msgid "failed to sign the push certificate" -msgstr "сертификатът за изтласкване не може да бъде подписан" +msgstr "сертификатът за изтласкване не може да се подпише" msgid "send-pack: unable to fork off fetch subprocess" msgstr "send-pack: неуспешно създаване на процес" @@ -21712,7 +21555,7 @@ msgstr "несъществуващ режим на изчистване „%s“ #, c-format msgid "could not delete '%s'" -msgstr "„%s“ не може да бъде изтрит" +msgstr "„%s“ не може да се изтрие" msgid "revert" msgstr "отмяна" @@ -21826,13 +21669,13 @@ msgstr "подайте или скатайте промѐните, за да #. #, c-format msgid "%s: Unable to write new index file" -msgstr "%s: новият индекс не може да бъде запазен" +msgstr "%s: новият индекс не може да се запази" msgid "unable to update cache tree" -msgstr "кешът на обектите-дървета не може да бъде обновен" +msgstr "кешът на обектите-дървета не може да се обнови" msgid "could not resolve HEAD commit" -msgstr "подаването, сочено от указателя „HEAD“, не може да бъде открито" +msgstr "подаването, сочено от указателя „HEAD“, липсва" #, c-format msgid "no key present in '%.*s'" @@ -21840,7 +21683,7 @@ msgstr "в „%.*s“ няма ключове" #, c-format msgid "unable to dequote value of '%s'" -msgstr "цитирането на стойността на „%s“ не може да бъде изчистено" +msgstr "цитирането на стойността на „%s“ не може да се изчисти" msgid "'GIT_AUTHOR_NAME' already given" msgstr "настройката за автор „GIT_AUTHOR_NAME“ вече е зададена" @@ -21949,15 +21792,13 @@ msgstr "" " git commit --amend --reset-author\n" msgid "couldn't look up newly created commit" -msgstr "току що създаденото подаване не може да бъде открито" +msgstr "току що създаденото подаване липсва" msgid "could not parse newly created commit" -msgstr "току що създаденото подаване не може да бъде анализирано" +msgstr "току що създаденото подаване не може да се анализира" msgid "unable to resolve HEAD after creating commit" -msgstr "" -"състоянието сочено от указателя „HEAD“ не може да бъде открито след " -"подаването" +msgstr "състоянието сочено от указателя „HEAD“ липсва след подаването" msgid "detached HEAD" msgstr "несвързан връх „HEAD“" @@ -21966,18 +21807,18 @@ msgid " (root-commit)" msgstr " (начално подаване)" msgid "could not parse HEAD" -msgstr "указателят „HEAD“ не може да бъде анализиран" +msgstr "указателят „HEAD“ не може да се анализира" #, c-format msgid "HEAD %s is not a commit!" msgstr "указателят „HEAD“ „%s“ сочи към нещо, което не е подаване!" msgid "unable to parse commit author" -msgstr "авторът на подаването не може да бъде анализиран" +msgstr "авторът на подаването не може да се анализира" #, c-format msgid "unable to read commit message from '%s'" -msgstr "съобщението за подаване не може да бъде прочетено от „%s“" +msgstr "съобщението за подаване не може да се прочете от „%s“" #, c-format msgid "invalid author identity '%s'" @@ -21992,7 +21833,7 @@ msgstr "„%s“ не може да се обнови" #, c-format msgid "could not parse parent commit %s" -msgstr "родителското подаване „%s“ не може да бъде анализирано" +msgstr "родителското подаване „%s“ не може да се анализира" #, c-format msgid "unknown command: %d" @@ -22006,11 +21847,11 @@ msgid "This is the commit message #%d:" msgstr "Това е съобщение при подаване №%d:" msgid "The 1st commit message will be skipped:" -msgstr "Съобщението при подаване №1 ще бъде прескочено:" +msgstr "Съобщението при подаване №1 ще се прескочи:" #, c-format msgid "The commit message #%d will be skipped:" -msgstr "Съобщението при подаване №%d ще бъде прескочено:" +msgstr "Съобщението при подаване №%d ще се прескочи:" #, c-format msgid "This is a combination of %d commits." @@ -22027,12 +21868,11 @@ msgid "could not read HEAD" msgstr "указателят „HEAD“ не може да се прочете" msgid "could not read HEAD's commit message" -msgstr "" -"съобщението за подаване към указателя „HEAD“ не може да бъде прочетено: %s" +msgstr "съобщението за подаване към указателя „HEAD“ не може да се прочете: %s" #, c-format msgid "could not read commit message of %s" -msgstr "съобщението за подаване към „%s“ не може да бъде прочетено" +msgstr "съобщението за подаване към „%s“ не може да се прочете" msgid "your index file is unmerged." msgstr "индексът не е слят." @@ -22060,11 +21900,11 @@ msgstr "%s: неразпозната стойност за родителско #, c-format msgid "could not revert %s... %s" -msgstr "подаването „%s“… не може да бъде отменено: „%s“" +msgstr "подаването „%s“… не може да се отменени: „%s“" #, c-format msgid "could not apply %s... %s" -msgstr "подаването „%s“… не може да бъде приложено: „%s“" +msgstr "подаването „%s“… не може да се приложи: „%s“" #, c-format msgid "dropping %s %s -- patch contents already upstream\n" @@ -22211,24 +22051,23 @@ msgstr "използвайте „git cherry-pick (--continue|%s--abort|--quit) #, c-format msgid "could not create sequencer directory '%s'" msgstr "" -"директорията за определянето на последователността „%s“ не може да бъде " -"създадена" +"директорията за определянето на последователността „%s“ не може да се създаде" msgid "no cherry-pick or revert in progress" msgstr "" "в момента не се извършва отбиране на подавания или пребазиране на клона" msgid "cannot resolve HEAD" -msgstr "Подаването сочено от указателя „HEAD“ не може да бъде открито" +msgstr "Подаването сочено от указателя „HEAD“ липсва" msgid "cannot abort from a branch yet to be born" msgstr "" -"действието не може да бъде преустановено, когато сте на клон, който тепърва " -"предстои да бъде създаден" +"действието не може да се преустанови, когато сте на клон, който тепърва " +"предстои да се създаде" #, c-format msgid "cannot read '%s': %s" -msgstr "„%s“ не може да бъде прочетен: %s" +msgstr "„%s“ не може да се прочете: %s" msgid "unexpected end of file" msgstr "неочакван край на файл" @@ -22266,10 +22105,10 @@ msgstr "" " git %s --continue" msgid "cannot read HEAD" -msgstr "указателят „HEAD“ не може да бъде прочетен" +msgstr "указателят „HEAD“ не може да се прочете" msgid "could not write commit message file" -msgstr "файлът със съобщението за подаване не може да бъде записан" +msgstr "файлът със съобщението за подаване не може да се запише" #, c-format msgid "" @@ -22291,7 +22130,7 @@ msgstr "" #, c-format msgid "Could not apply %s... %.*s" -msgstr "Подаването „%s“… не може да бъде приложено: „%.*s“" +msgstr "Подаването „%s“… не може да се приложи: „%.*s“" #, c-format msgid "Could not merge %.*s" @@ -22340,7 +22179,7 @@ msgstr "неправилно име на етикет: „%.*s“" #, c-format msgid "could not resolve '%s'" -msgstr "„%s“ не може да бъде открит" +msgstr "„%s“ липсва" msgid "writing fake root commit" msgstr "запазване на фалшиво начално подаване" @@ -22364,14 +22203,14 @@ msgstr "върху начално подаване не може да се из #, c-format msgid "could not get commit message of '%s'" -msgstr "съобщението за подаване към „%s“ не може да бъде получено" +msgstr "съобщението за подаване към „%s“ не може да се получи" #, c-format msgid "could not even attempt to merge '%.*s'" msgstr "сливането на „%.*s“ не може даже да започне" msgid "merge: Unable to write new index file" -msgstr "сливане: новият индекс не може да бъде запазен" +msgstr "сливане: новият индекс не може да се запази" #, c-format msgid "" @@ -22405,7 +22244,7 @@ msgstr "Неочакван резултат при скатаване: „%s“" #, c-format msgid "Could not create directory for '%s'" -msgstr "Директорията за „%s“ не може да бъде създадена" +msgstr "Директорията за „%s“ не може да се създаде" #, c-format msgid "Created autostash: %s\n" @@ -22420,7 +22259,7 @@ msgstr "Автоматично скатаното е приложено.\n" #, c-format msgid "cannot store %s" -msgstr "„%s“ не може да бъде запазен" +msgstr "„%s“ не може да се запази" #, c-format msgid "" @@ -22464,7 +22303,7 @@ msgid "" " git rebase --edit-todo\n" " git rebase --continue\n" msgstr "" -"Следната запланувана команда не може да бъде изпълнена:\n" +"Следната запланувана команда не може да се изпълни:\n" "\n" " %.*s\n" "\n" @@ -22495,7 +22334,7 @@ msgstr "указателят за „onto“ не може да се проче #, c-format msgid "could not update HEAD to %s" -msgstr "„HEAD“ не може да бъде обновен до „%s“" +msgstr "„HEAD“ не може да се обнови до „%s“" #, c-format msgid "Successfully rebased and updated %s.\n" @@ -22526,10 +22365,10 @@ msgstr "" #, c-format msgid "could not write file: '%s'" -msgstr "файлът „%s“ не може да бъде записан" +msgstr "файлът „%s“ не може да се запише" msgid "could not remove CHERRY_PICK_HEAD" -msgstr "указателят „CHERRY_PICK_HEAD“ не може да бъде изтрит" +msgstr "указателят „CHERRY_PICK_HEAD“ не може да се изтрие" msgid "could not commit staged changes." msgstr "промѐните в индекса не може да бъдат подадени." @@ -22543,7 +22382,7 @@ msgid "%s: bad revision" msgstr "%s: неправилна версия" msgid "can't revert as initial commit" -msgstr "първоначалното подаване не може да бъде отменено" +msgstr "първоначалното подаване не може да се отмени" #, c-format msgid "skipped previously applied commit %s" @@ -22676,7 +22515,7 @@ msgstr "процесът не може да се върне към предиш #, c-format msgid "failed to stat '%*s%s%s'" -msgstr "не може да бъде получена информация чрез „stat“ за „%*s%s%s“" +msgstr "не може да се получи информация чрез „stat“ за „%*s%s%s“" #, c-format msgid "safe.directory '%s' not absolute" @@ -22695,7 +22534,7 @@ msgstr "" " git config --global --add safe.directory %s" msgid "Unable to read current working directory" -msgstr "Текущата работна директория не може да бъде прочетена" +msgstr "Текущата работна директория не може да се прочете" #, c-format msgid "cannot change to '%s'" @@ -22743,11 +22582,11 @@ msgstr "не може да се получи информация чрез „st #, c-format msgid "cannot opendir '%s'" -msgstr "директорията „%s“ не може да бъде отворена" +msgstr "директорията „%s“ не може да се отвори" #, c-format msgid "cannot readlink '%s'" -msgstr "връзката „%s“ не може да бъде прочетена" +msgstr "връзката „%s“ не може да се прочете" #, c-format msgid "cannot symlink '%s' '%s'" @@ -22897,7 +22736,7 @@ msgstr "" #, c-format msgid "Could not update .gitmodules entry %s" -msgstr "Записът „%s“ във файла „.gitmodules“ не може да бъде променен" +msgstr "Записът „%s“ във файла „.gitmodules“ не може да се промени" msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" msgstr "" @@ -22910,7 +22749,7 @@ msgstr "Във файла „.gitmodules“ липсва раздел за ди #, c-format msgid "Could not remove .gitmodules entry for %s" -msgstr "Записът „%s“ във файла „.gitmodules“ не може да бъде изтрит" +msgstr "Записът „%s“ във файла „.gitmodules“ не може да се изтрие" msgid "staging updated .gitmodules failed" msgstr "неуспешно добавяне на променения файл „.gitmodules“ в индекса" @@ -22957,7 +22796,7 @@ msgstr "Изтласкване на подмодула „%s“\n" #, c-format msgid "Unable to push submodule '%s'\n" -msgstr "Подмодулът „%s“ не може да бъде изтласкан\n" +msgstr "Подмодулът „%s“ не може да се изтласка\n" #, c-format msgid "Fetching submodule %s%s\n" @@ -22965,11 +22804,11 @@ msgstr "Доставяне на подмодула „%s%s“\n" #, c-format msgid "Could not access submodule '%s'\n" -msgstr "Подмодулът „%s“ не може да бъде достъпен\n" +msgstr "Подмодулът „%s“ не може да се достъпи\n" #, c-format msgid "Could not access submodule '%s' at commit %s\n" -msgstr "Подмодулът „%s“ не може да бъде достъпен при подаване %s\n" +msgstr "Подмодулът „%s“ не може да се достъпи при подаване %s\n" #, c-format msgid "Fetching submodule %s%s at commit %s\n" @@ -23045,7 +22884,7 @@ msgstr "" #, c-format msgid "could not lookup name for submodule '%s'" -msgstr "името на подмодула „%s“ не може да бъде намерено" +msgstr "името на подмодула „%s“ не може да се намери" #, c-format msgid "refusing to move '%s' into an existing git dir" @@ -23070,7 +22909,7 @@ msgstr "„ls-tree“ завърши с неочакван изходен код #, c-format msgid "failed to lstat '%s'" -msgstr "не може да бъде получена информация чрез „lstat“ за „%s“" +msgstr "не може да се получи информация чрез „lstat“ за „%s“" msgid "no remote configured to get bundle URIs from" msgstr "не е настроено отдалечено хранилище за списъците с адреси на пратки" @@ -23089,6 +22928,9 @@ msgstr "" "какъв брой записи в кеша на обектите-дървета да се отбележат като невалидни " "(стандартно е 0)" +msgid "the number of objects to write" +msgstr "брой записани обекти" + msgid "test-tool path-walk -- " msgstr "test-tool path-walk ОПЦИЯ… -- ОПЦИЯ_ЗА_ВЕРСИИ…" @@ -23219,7 +23061,7 @@ msgstr "неуспешен пълен запис към насрещната п #, c-format msgid "unable to find remote helper for '%s'" -msgstr "насрещната помощна програма за „%s“ не може да бъде открита" +msgstr "насрещната помощна програма за „%s“ липсва" msgid "can't dup helper output fd" msgstr "" @@ -23332,7 +23174,7 @@ msgid "" "Perhaps you should specify a branch.\n" msgstr "" "Няма общи указатели, не са указани никакви указатели —\n" -"нищо няма да бъде направено. Пробвайте да укажете клон.\n" +"нищо няма да се направи. Пробвайте да укажете клон.\n" #, c-format msgid "unsupported object format '%s'" @@ -23379,7 +23221,7 @@ msgstr "Клонът „%s“ ще следи „%s“ от „%s“\n" #, c-format msgid "could not read bundle '%s'" -msgstr "пратката на git „%s“ не може да бъде прочетена" +msgstr "пратката на git „%s“ не може да се прочете" #, c-format msgid "transport: invalid depth option '%s'" @@ -23530,7 +23372,7 @@ msgid "" "Refusing to remove the current working directory:\n" "%s" msgstr "" -"Текущата работна директория няма да бъде изтрита:\n" +"Текущата работна директория няма да се изтрие:\n" "%s" #, c-format @@ -23640,7 +23482,7 @@ msgid "" "Cannot update submodule:\n" "%s" msgstr "" -"Подмодулът не може да бъде обновен:\n" +"Подмодулът не може да се обнови:\n" "„%s“" #, c-format @@ -23815,7 +23657,7 @@ msgstr "файлът „gitdir“ не съществува" #, c-format msgid "unable to read gitdir file (%s)" -msgstr "файлът „gitdir“ не може да бъде прочетен (%s)" +msgstr "файлът „gitdir“ не може да се прочете (%s)" #, c-format msgid "short read (expected % bytes, read %)" @@ -23854,11 +23696,11 @@ msgstr "променливата на средата „%s“ не може да #, c-format msgid "unable to create '%s'" -msgstr "пакетният файл „%s“ не може да бъде създаден" +msgstr "пакетният файл „%s“ не може да се създаде" #, c-format msgid "could not open '%s' for reading and writing" -msgstr "„%s“ не може да бъде отворен и за четене, и за запис" +msgstr "„%s“ не може да се отвори и за четене, и за запис" #, c-format msgid "unable to access '%s'" @@ -23870,6 +23712,15 @@ msgstr "текущата работна директория е недостъп msgid "unable to get random bytes" msgstr "не може да се получат случайни байтове" +#, c-format +msgid "attempting to mmap % over limit %" +msgstr "" +"неуспешен опит за „mmap“ %, което е над позволеното %" + +#, c-format +msgid "mmap failed%s" +msgstr "неуспешно изпълнение на „mmap“%s" + msgid "Unmerged paths:" msgstr "Неслети пътища:" @@ -24001,7 +23852,7 @@ msgid "" "Everything below it will be ignored." msgstr "" "Не променяйте и не изтривайте горния ред.\n" -"Всичко отдолу ще бъде изтрито." +"Всичко отдолу ще се изтрие." #, c-format msgid "" @@ -24638,9 +24489,16 @@ msgstr "" "Подсистемата за SMTP не може да се инициализира. Проверете настройките и " "използвайте опцията: „--smtp-debug“." +#, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook промени „Message-ID“ да е: %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "ПРЕДУПРЕЖДЕНИЕ: в отговора на сървъра липсва „Message-ID“.\n" + #, perl-format msgid "Failed to send %s\n" -msgstr "„%s“ не може да бъде изпратен\n" +msgstr "„%s“ не може да се изпрати\n" #, perl-format msgid "Dry-Sent %s" @@ -24664,7 +24522,7 @@ msgstr "Резултат: успех" #, perl-format msgid "can't open file %s" -msgstr "файлът „%s“ не може да бъде отворен" +msgstr "файлът „%s“ не може да се отвори" #, perl-format msgid "(mbox) Adding cc: %s from line '%s'\n" @@ -24684,7 +24542,7 @@ msgstr "(тяло) Добавяне на „як: %s“ от ред „%s“\n" #, perl-format msgid "(%s) Could not execute '%s'" -msgstr "(%s) Не може да бъде се изпълни „%s“" +msgstr "(%s) Не може да се изпълни „%s“" #, perl-format msgid "(%s) Malformed output from '%s'" diff --git a/po/de.po b/po/de.po index 4d9c46fb19de01..6b65bb618076f8 100644 --- a/po/de.po +++ b/po/de.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: Git\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2025-03-06 18:29+0100\n" -"PO-Revision-Date: 2025-03-07 17:28+0100\n" +"POT-Creation-Date: 2025-05-27 22:57+0000\n" +"PO-Revision-Date: 2025-05-31 18:38+0200\n" "Last-Translator: Ralf Thielow \n" "Language-Team: German\n" "Language: de\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -"X-Generator: Poedit 3.4.4\n" +"X-Generator: Poedit 3.6\n" #, c-format msgid "Huh (%s)?" @@ -379,8 +379,8 @@ msgstr "Ergänzung im Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d%s,?]? " #, c-format msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " msgstr "" -"Diesen Patch-Block im Index und Arbeitsverzeichnis verwerfen [y,n,q,a," -"d%s,?]? " +"Diesen Patch-Block im Index und Arbeitsverzeichnis verwerfen " +"[y,n,q,a,d%s,?]? " msgid "" "y - discard this hunk from index and worktree\n" @@ -411,8 +411,8 @@ msgstr "Ergänzung auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d%s,?]? " #, c-format msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " msgstr "" -"Diesen Patch-Block auf Index und Arbeitsverzeichnis anwenden [y,n,q,a," -"d%s,?]? " +"Diesen Patch-Block auf Index und Arbeitsverzeichnis anwenden " +"[y,n,q,a,d%s,?]? " msgid "" "y - apply this hunk to index and worktree\n" @@ -1746,10 +1746,12 @@ msgstr "" msgid "not tracking: ambiguous information for ref '%s'" msgstr "kein Tracking: mehrdeutige Informationen für Referenz '%s'" +#. #-#-#-#-# branch.c.po #-#-#-#-# #. TRANSLATORS: This is a line listing a remote with duplicate #. refspecs in the advice message below. For RTL languages you'll #. probably want to swap the "%s" and leading " " space around. #. +#. #-#-#-#-# object-name.c.po #-#-#-#-# #. TRANSLATORS: This is line item of ambiguous object output #. from describe_ambiguous_object() above. For RTL languages #. you'll probably want to swap the "%s" and leading " " space @@ -3096,11 +3098,11 @@ msgid "HEAD not found below refs/heads!" msgstr "HEAD wurde nicht unter \"refs/heads\" gefunden!" msgid "" -"branch with --recurse-submodules can only be used if submodule." -"propagateBranches is enabled" +"branch with --recurse-submodules can only be used if " +"submodule.propagateBranches is enabled" msgstr "" -"Branch mit --recurse-submodules kann nur genutzt werden, wenn submodule." -"propagateBranches aktiviert ist" +"Branch mit --recurse-submodules kann nur genutzt werden, wenn " +"submodule.propagateBranches aktiviert ist" msgid "--recurse-submodules can only be used to create branches" msgstr "--recurse-submodules kann nur genutzt werden, um Branches zu erstellen" @@ -3355,11 +3357,8 @@ msgstr "Nur eine Batch-Option erlaubt." msgid "git cat-file " msgstr "git cat-file " -msgid "git cat-file (-e | -p) " -msgstr "git cat-file (-e | -p) " - -msgid "git cat-file (-t | -s) [--allow-unknown-type] " -msgstr "git cat-file (-t | -s) [--allow-unknown-type] " +msgid "git cat-file (-e | -p | -t | -s) " +msgstr "git cat-file (-e | -p | -t | -s) " msgid "" "git cat-file (--textconv | --filters)\n" @@ -3398,9 +3397,6 @@ msgstr "zeige Objekt-Typ (eines von 'blob', 'tree', 'commit', 'tag', ...)" msgid "show object size" msgstr "Objektgröße anzeigen" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "-s und -t mit beschädigten Objekten erlauben" - msgid "use mail map file" msgstr "\"mailmap\"-Datei verwenden" @@ -3460,6 +3456,13 @@ msgid "use a for (--textconv | --filters); Not with 'batch'" msgstr "" "nutzen Sie einen für (--textconv | --filters); Nicht mit 'batch'" +msgid "objects filter only supported in batch mode" +msgstr "Objektfilter werden nur im Batch-Modus unterstützt" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "Objektfilter nicht unterstützt: '%s'" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "'%s=<%s>' benötigt '%s' oder '%s'" @@ -5785,6 +5788,50 @@ msgstr "Dateiendung im strftime-Format für den Dateinamen angeben" msgid "specify the content of the diagnostic archive" msgstr "den Inhalt des Diagnosearchivs angeben" +#, c-format +msgid "unable to parse mode: %s" +msgstr "Konnte Modus '%s' nicht parsen." + +#, c-format +msgid "unable to parse object id: %s" +msgstr "Konnte Objekt-ID '%s' nicht parsen." + +msgid "git diff-pairs -z []" +msgstr "git diff-pairs -z []" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "nicht erkanntes Argument: %s" + +msgid "working without -z is not supported" +msgstr "Arbeiten ohne -z wird nicht unterstützt" + +msgid "pathspec arguments not supported" +msgstr "Pfadspezifikationen als Argumente werden nicht unterstützt" + +msgid "revision arguments not allowed" +msgstr "Commits als Argumente werden nicht unterstützt" + +msgid "invalid raw diff input" +msgstr "ungültige Raw-Diff-Eingabe" + +msgid "tree objects not supported" +msgstr "Tree-Objekte werden nicht unterstützt" + +msgid "got EOF while reading path" +msgstr "EOF beim Lesen des Pfads" + +msgid "got EOF while reading destination path" +msgstr "EOF beim Lesen des Zielpfads" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "Konnte Umbenennen/Kopieren-Punktzahl nicht parsen: %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "unbekannter Diff-Status: %c" + msgid "--merge-base only works with two commits" msgstr "--merge-base funktioniert nur mit zwei Commits" @@ -5927,6 +5974,9 @@ msgstr "Fortschritt nach Objekten anzeigen" msgid "select handling of signed tags" msgstr "Behandlung von signierten Tags wählen" +msgid "select handling of signed commits" +msgstr "Behandlung von signierten Commits wählen" + msgid "select handling of tags that tag filtered objects" msgstr "Behandlung von Tags wählen, die gefilterte Objekte markieren" @@ -6367,8 +6417,8 @@ msgid "protocol does not support --negotiate-only, exiting" msgstr "Protokoll unterstützt --negotiate-only nicht, beende" msgid "" -"--filter can only be used with the remote configured in extensions." -"partialclone" +"--filter can only be used with the remote configured in " +"extensions.partialclone" msgstr "" "--filter kann nur mit den Remote-Repositories verwendet werden,\n" "die in extensions.partialclone konfiguriert sind" @@ -6588,10 +6638,6 @@ msgstr "%s: Hash-Pfad stimmt nicht überein, gefunden bei: %s" msgid "%s: object corrupt or missing: %s" msgstr "%s: Objekt fehlerhaft oder nicht vorhanden: %s" -#, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s: Objekt hat einen unbekannten Typ '%s': %s" - #, c-format msgid "%s: object could not be parsed: %s" msgstr "%s: Objekt konnte nicht geparst werden: %s" @@ -6649,16 +6695,19 @@ msgstr "rev-Index für Pack-Datei '%s' kann nicht geladen werden" msgid "invalid rev-index for pack '%s'" msgstr "ungültiger Rev-Index für Pack-Datei '%s'" +msgid "Checking ref database" +msgstr "Referenzdatenbank überprüfen" + msgid "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" -" [--[no-]name-objects] [...]" +" [--[no-]name-objects] [--[no-]references] [...]" msgstr "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" -" [--[no-]name-objects] [...]" +" [--[no-]name-objects] [--[no-]references] [...]" msgid "show unreachable objects" msgstr "unerreichbare Objekte anzeigen" @@ -6696,6 +6745,9 @@ msgstr "Fortschrittsanzeige anzeigen" msgid "show verbose names for reachable objects" msgstr "ausführliche Namen für erreichbare Objekte anzeigen" +msgid "check reference database consistency" +msgstr "Konsistenz der Referenzdatenbank überprüfen" + msgid "Checking objects" msgstr "Prüfe Objekte" @@ -7104,6 +7156,7 @@ msgstr "grep: Fehler beim Erzeugen eines Thread: %s" msgid "invalid number of threads specified (%d) for %s" msgstr "ungültige Anzahl von Threads (%d) für %s angegeben" +#. #-#-#-#-# grep.c.po #-#-#-#-# #. TRANSLATORS: %s is the configuration #. variable for tweaking threads, currently #. grep.threads @@ -7861,10 +7914,6 @@ msgstr "" "Entwicklung der Zeilen vom Bereich , oder Funktion :" " in verfolgen" -#, c-format -msgid "unrecognized argument: %s" -msgstr "nicht erkanntes Argument: %s" - msgid "-L: cannot be used with pathspec" msgstr "-L: kann nicht mit Pfadspezifikation verwendet werden" @@ -8527,6 +8576,9 @@ msgstr "nur einen trivialen Merge durchführen" msgid "also show informational/conflict messages" msgstr "auch Informations-/Konfliktmeldungen anzeigen" +msgid "suppress all output; only exit status wanted" +msgstr "alle Ausgaben unterdrücken; nur Exit-Status verwenden" + msgid "list filenames without modes/oids/stages" msgstr "Dateinamen ohne Modi/Oids/Stufen auflisten" @@ -8941,8 +8993,11 @@ msgstr "" "während des Umpackens, sammle Paket-Dateien von geringerer Größe in einen " "Stapel, welcher größer ist als diese Größe" -msgid "git mv [] ... " -msgstr "git mv [] ... " +msgid "git mv [-v] [-f] [-n] [-k] " +msgstr "git mv [-v] [-f] [-n] [-k] " + +msgid "git mv [-v] [-f] [-n] [-k] ... " +msgstr "git mv [-v] [-f] [-n] [-k] ... " #, c-format msgid "Directory %s is in index and no submodule?" @@ -9013,6 +9068,12 @@ msgstr "Ziel existiert im Index" msgid "%s, source=%s, destination=%s" msgstr "%s, Quelle=%s, Ziel=%s" +#, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "" +"kann nicht sowohl '%s' als auch das übergeordnete Verzeichnis '%s' " +"verschieben" + #, c-format msgid "Renaming %s to %s\n" msgstr "Benenne %s nach %s um\n" @@ -9971,6 +10032,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "Konnte nicht auf Commit '%s' zugreifen." +#, c-format +msgid "invalid refspec '%s'" +msgstr "ungültige Refspec '%s'" + msgid "ignoring --verify-signatures for rebase" msgstr "Ignoriere --verify-signatures für Rebase" @@ -10971,6 +11036,9 @@ msgstr "" msgid "git reflog exists " msgstr "git reflog exists " +msgid "git reflog drop [--all [--single-worktree] | ...]" +msgstr "git reflog drop [--all [--single-worktree] | ...]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "ungültiger Zeitstempel '%s' für '--%s'" @@ -11022,8 +11090,8 @@ msgid "Marking reachable objects..." msgstr "Markiere nicht erreichbare Objekte..." #, c-format -msgid "%s points nowhere!" -msgstr "%s zeigt auf nichts!" +msgid "reflog could not be found: '%s'" +msgstr "Reflog konnte nicht gefunden werden: '%s'" msgid "no reflog specified to delete" msgstr "Kein Reflog zum Löschen angegeben." @@ -11032,6 +11100,15 @@ msgstr "Kein Reflog zum Löschen angegeben." msgid "invalid ref format: %s" msgstr "Ungültiges Format für Referenzen: %s" +msgid "drop the reflogs of all references" +msgstr "die Reflogs aller Referenzen löschen" + +msgid "drop reflogs from the current worktree only" +msgstr "nur Reflogs aus dem aktuellen Arbeitsverzeichnis löschen" + +msgid "references specified along with --all" +msgstr "Referenzen, die zusammen mit --all angegeben werden" + msgid "git refs migrate --ref-format= [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format= [--no-reflog] [--dry-run]" @@ -11594,6 +11671,10 @@ msgstr "Datumsangabe" msgid "with --cruft, expire objects older than this" msgstr "mit --cruft, Objekte verfallen lassen, die älter sind als das" +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "" +"mit --cruft, nur Cruft-Pakete umpacken, die kleiner als dieser Wert sind" + msgid "remove redundant packs, and run git-prune-packed" msgstr "redundante Pakete entfernen und \"git-prune-packed\" ausführen" @@ -12077,6 +12158,9 @@ msgstr "konnte Festplattennutzung von %s nicht bekommen" msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "ungültiger Wert für '%s': '%s', das einzig zulässige Format ist '%s'" +msgid "-z option used with unsupported option" +msgstr "Die Option -z wird mit nicht unterstützter Option verwendet." + msgid "rev-list does not support display of notes" msgstr "rev-list unterstützt keine Anzeige von Notizen" @@ -13995,8 +14079,8 @@ msgstr "git update-ref [] -d []" msgid "git update-ref [] []" msgstr "git update-ref [] []" -msgid "git update-ref [] --stdin [-z]" -msgstr "git update-ref [] --stdin [-z]" +msgid "git update-ref [] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "diese Referenz löschen" @@ -14010,6 +14094,9 @@ msgstr "Standard-Eingabe hat durch NUL-Zeichen abgeschlossene Argumente" msgid "read updates from stdin" msgstr "Aktualisierungen von der Standard-Eingabe lesen" +msgid "batch reference updates" +msgstr "Batch-Referenz-Updates" + msgid "update the info files from scratch" msgstr "die Informationsdateien von Grund auf aktualisieren" @@ -14724,6 +14811,9 @@ msgstr "Dateien von dem Arbeitsverzeichnis und dem Index vergleichen" msgid "Compare a tree to the working tree or index" msgstr "ein Verzeichnis von dem Arbeitsverzeichnis und dem Index vergleichen" +msgid "Compare the content and mode of provided blob pairs" +msgstr "Inhalt und Modus der bereitgestellten Blobpaare vergleichen" + msgid "Compares the content and mode of blobs found via two tree objects" msgstr "" "den Inhalt und Modus von Blobs aus zwei Verzeichnisobjekten vergleichen" @@ -15380,8 +15470,8 @@ msgid "" "attempting to write a commit-graph, but 'commitGraph.changedPathsVersion' " "(%d) is not supported" msgstr "" -"versuche, einen Commit-Graphen zu schreiben, aber 'commitGraph." -"changedPathsVersion' (%d) wird nicht unterstützt" +"versuche, einen Commit-Graphen zu schreiben, aber " +"'commitGraph.changedPathsVersion' (%d) wird nicht unterstützt" msgid "too many commits to write graph" msgstr "zu viele Commits zum Schreiben des Graphen" @@ -17681,6 +17771,10 @@ msgstr "Kontrolle über Delegation wird mit cURL < 7.22.0 nicht unterstützt" msgid "Unknown value for http.proactiveauth" msgstr "Unbekannter Wert für http.proactiveauth" +#, c-format +msgid "failed to parse %s" +msgstr "Fehler beim Parsen von %s." + #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Nicht unterstütztes SSL-Backend '%s'. Unterstützte SSL-Backends:" @@ -17871,6 +17965,10 @@ msgstr "Meldung kann nicht formatiert werden: %s" msgid "invalid marker-size '%s', expecting an integer" msgstr "ungültige marker-size '%s', ganze Zahl erwartet" +#, c-format +msgid "Could not parse object '%s'" +msgstr "Konnte Objekt '%s' nicht parsen." + #, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Fehler beim Merge von Submodul %s (nicht ausgecheckt)." @@ -18124,276 +18222,6 @@ msgid "collecting merge info failed for trees %s, %s, %s" msgstr "" "Sammeln von Merge-Informationen für die Referenzen %s, %s, %s fehlgeschlagen" -msgid "(bad commit)\n" -msgstr "(ungültiger Commit)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "add_cacheinfo für Pfad '%s' fehlgeschlagen; Merge wird abgebrochen." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "" -"add_cacheinfo zur Aktualisierung für Pfad '%s' fehlgeschlagen;\n" -"Merge wird abgebrochen." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "Fehler beim Erstellen des Pfades '%s'%s" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Entferne %s, um Platz für Unterverzeichnis zu schaffen\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": vielleicht ein Verzeichnis/Datei-Konflikt?" - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "verweigere, da unversionierte Dateien in '%s' verloren gehen würden" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "Blob erwartet für %s '%s'" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "Fehler beim Öffnen von '%s': %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "Fehler beim Erstellen einer symbolischen Verknüpfung für '%s': %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "weiß nicht was mit %06o %s '%s' zu machen ist" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "" -"Submodul %s konnte nicht zusammengeführt werden (Repository beschädigt)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "Spule Submodul %s zu dem folgenden Commit vor:" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "Spule Submodul %s vor" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"Fehler beim Merge von Submodule %s (dem Merge nachfolgende Commits nicht " -"gefunden)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Fehler beim Merge von Submodul %s (kein Vorspulen)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Mögliche Auflösung des Merges für Submodul gefunden:\n" - -#, c-format -msgid "" -"If this is correct simply add it to the index for example\n" -"by using:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"which will accept this suggestion.\n" -msgstr "" -"Falls das korrekt ist, fügen Sie es einfach der Staging-Area, zum Beispiel " -"mit:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"hinzu, um diesen Vorschlag zu akzeptieren.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "Fehler beim Merge von Submodul %s (mehrere Merges gefunden)" - -msgid "failed to execute internal merge" -msgstr "Fehler bei Ausführung des internen Merges" - -#, c-format -msgid "unable to add %s to database" -msgstr "konnte %s nicht zur Datenbank hinzufügen" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "" -"Fehler: Verweigere unversionierte Datei bei %s zu verlieren;\n" -"schreibe stattdessen nach %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde " -"im Arbeitsbereich gelassen." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s nach %s in %s. Stand %s von " -"%s wurde im Arbeitsbereich gelassen." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde " -"im Arbeitsbereich bei %s gelassen." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"KONFLIKT (%s/löschen): %s gelöscht in %s und %s nach %s in %s. Stand %s von " -"%s wurde im Arbeitsbereich bei %s gelassen." - -msgid "rename" -msgstr "umbenennen" - -msgid "renamed" -msgstr "umbenannt" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "Verweigere geänderte Datei bei %s zu verlieren." - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "" -"Verweigere unversionierte Datei bei %s zu verlieren, auch wenn diese im Weg " -"ist." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"KONFLIKT (umbenennen/hinzufügen): Benenne um %s->%s in %s. %s hinzugefügt in " -"%s" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s ist ein Verzeichnis in %s, füge es stattdessen als %s hinzu" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "" -"Verweigere unversionierte Datei bei %s zu verlieren; füge stattdessen %s " -"hinzu" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"KONFLIKT (umbenennen/umbenennen): Benenne um \"%s\"->\"%s\" in Branch \"%s\" " -"und \"%s\"->\"%s\" in Branch \"%s\"%s" - -msgid " (left unresolved)" -msgstr " (bleibt unaufgelöst)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"KONFLIKT (umbenennen/umbenennen): Benenne um %s->%s in %s. Benenne um %s->%s " -"in %s" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"KONFLIKT (Aufteilung Verzeichnisumbenennung): Unklar, wo %s zu platzieren " -"ist,\n" -"weil Verzeichnis %s zu mehreren anderen Verzeichnissen umbenannt wurde, " -"wobei\n" -"keines dieser Ziele die Mehrheit der Dateien erhielt." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"KONFLIKT (umbenennen/umbenennen): Benenne Verzeichnis um %s->%s in %s.\n" -"Benenne Verzeichnis um %s->%s in %s" - -#, c-format -msgid "cannot read object %s" -msgstr "kann Objekt %s nicht lesen" - -#, c-format -msgid "object %s is not a blob" -msgstr "Objekt %s ist kein Blob" - -msgid "modify" -msgstr "ändern" - -msgid "modified" -msgstr "geändert" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "%s ausgelassen (Ergebnis des Merges existiert bereits)" - -#, c-format -msgid "Adding as %s instead" -msgstr "Füge stattdessen als %s hinzu" - -#, c-format -msgid "Removing %s" -msgstr "Entferne %s" - -msgid "file/directory" -msgstr "Datei/Verzeichnis" - -msgid "directory/file" -msgstr "Verzeichnis/Datei" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"KONFLIKT (%s): Es existiert bereits ein Verzeichnis %s in %s. Füge %s als %s " -"hinzu." - -#, c-format -msgid "Adding %s" -msgstr "Füge %s hinzu" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "KONFLIKT (hinzufügen/hinzufügen): Merge-Konflikt in %s" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "Zusammenführen der \"Tree\"-Objekte %s und %s fehlgeschlagen" - -msgid "Merging:" -msgstr "Merge:" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "%u gemeinsamen Vorgänger-Commit gefunden" -msgstr[1] "%u gemeinsame Vorgänger-Commits gefunden" - -msgid "merge returned no commit" -msgstr "Merge hat keinen Commit zurückgegeben" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "Konnte Objekt '%s' nicht parsen." - msgid "failed to read the cache" msgstr "Lesen des Zwischenspeichers fehlgeschlagen" @@ -18435,13 +18263,14 @@ msgstr "kann '%s' nicht mit '%s' verknüpfen" msgid "failed to clear multi-pack-index at %s" msgstr "Fehler beim Löschen des Multi-Pack-Index bei %s" -msgid "cannot write incremental MIDX with bitmap" -msgstr "kann kein inkrementelles MIDX mit Bitmap schreiben" - msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "" "ignoriere existierenden Multi-Pack-Index; Prüfsumme stimmt nicht überein" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "konnte den umgekehrten Index für MIDX %s nicht laden" + msgid "Adding packfiles to multi-pack-index" msgstr "Packdateien zum Multi-Pack-Index hinzufügen" @@ -18703,69 +18532,6 @@ msgstr "kann %s %s in Commit-Objekt nicht zuordnen" msgid "Failed to convert object from %s to %s" msgstr "Objekt konnte nicht von %s nach %s konvertiert werden" -#, c-format -msgid "object directory %s does not exist; check .git/objects/info/alternates" -msgstr "" -"Objektverzeichnis %s existiert nicht; prüfe .git/objects/info/alternates" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "Konnte alternativen Objektpfad '%s' nicht normalisieren." - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s: ignoriere alternative Objektspeicher - Verschachtelung zu tief" - -msgid "unable to fdopen alternates lockfile" -msgstr "Konnte fdopen nicht auf Lock-Datei für \"alternates\" aufrufen." - -msgid "unable to read alternates file" -msgstr "Konnte \"alternates\"-Datei nicht lesen." - -msgid "unable to move new alternates file into place" -msgstr "Konnte neue \"alternates\"-Datei nicht übernehmen." - -#, c-format -msgid "path '%s' does not exist" -msgstr "Pfad '%s' existiert nicht" - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "" -"Referenziertes Repository '%s' wird noch nicht als verknüpftes\n" -"Arbeitsverzeichnis unterstützt." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "Referenziertes Repository '%s' ist kein lokales Repository." - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "" -"Referenziertes Repository '%s' hat eine unvollständige Historie (shallow)." - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "" -"Referenziertes Repository '%s' ist mit künstlichen Vorgängern (\"grafts\") " -"eingehängt." - -#, c-format -msgid "could not find object directory matching %s" -msgstr "konnte Objekt-Verzeichnis nicht finden, dass '%s' entsprechen soll" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "Ungültige Zeile beim Parsen alternativer Referenzen: %s" - -#, c-format -msgid "attempting to mmap % over limit %" -msgstr "Versuche mmap % über Limit %." - -#, c-format -msgid "mmap failed%s" -msgstr "mmap fehlgeschlagen%s" - #, c-format msgid "object file %s is empty" msgstr "Objektdatei %s ist leer." @@ -18801,18 +18567,6 @@ msgstr "Header für %s zu lang, überschreitet %d Bytes" msgid "loose object %s (stored in %s) is corrupt" msgstr "Loses Objekt %s (gespeichert in %s) ist beschädigt." -#, c-format -msgid "replacement %s not found for %s" -msgstr "Ersetzung %s für %s nicht gefunden." - -#, c-format -msgid "packed object %s (stored in %s) is corrupt" -msgstr "Gepacktes Objekt %s (gespeichert in %s) ist beschädigt." - -#, c-format -msgid "missing mapping of %s to %s" -msgstr "fehlende Abbildung von %s auf %s" - #, c-format msgid "unable to open %s" msgstr "kann %s nicht öffnen" @@ -18907,10 +18661,6 @@ msgstr "%s: Fehler beim Einfügen in die Datenbank" msgid "%s: unsupported file type" msgstr "%s: nicht unterstützte Dateiart" -#, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s ist kein gültiges '%s' Objekt" - #, c-format msgid "hash mismatch for %s (expected %s)" msgstr "Hash für %s stimmt nicht überein (%s erwartet)." @@ -18927,6 +18677,10 @@ msgstr "Konnte Kopfbereich von %s nicht entpacken." msgid "unable to parse header of %s" msgstr "Konnte Kopfbereich von %s nicht parsen." +#, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "Konnte den Typ aus der Kopfzeile '%s' von %s nicht parsen." + #, c-format msgid "unable to unpack contents of %s" msgstr "Konnte Inhalt von %s nicht entpacken." @@ -19087,6 +18841,77 @@ msgstr ": benötigt, nur '%s' angegeben" msgid "invalid object name '%.*s'." msgstr "ungültiger Objektname '%.*s'." +#, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "" +"Objektverzeichnis %s existiert nicht; prüfe .git/objects/info/alternates" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "Konnte alternativen Objektpfad '%s' nicht normalisieren." + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s: ignoriere alternative Objektspeicher - Verschachtelung zu tief" + +msgid "unable to fdopen alternates lockfile" +msgstr "Konnte fdopen nicht auf Lock-Datei für \"alternates\" aufrufen." + +msgid "unable to read alternates file" +msgstr "Konnte \"alternates\"-Datei nicht lesen." + +msgid "unable to move new alternates file into place" +msgstr "Konnte neue \"alternates\"-Datei nicht übernehmen." + +#, c-format +msgid "path '%s' does not exist" +msgstr "Pfad '%s' existiert nicht" + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "" +"Referenziertes Repository '%s' wird noch nicht als verknüpftes\n" +"Arbeitsverzeichnis unterstützt." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "Referenziertes Repository '%s' ist kein lokales Repository." + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "" +"Referenziertes Repository '%s' hat eine unvollständige Historie (shallow)." + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "" +"Referenziertes Repository '%s' ist mit künstlichen Vorgängern (\"grafts\") " +"eingehängt." + +#, c-format +msgid "could not find object directory matching %s" +msgstr "konnte Objekt-Verzeichnis nicht finden, dass '%s' entsprechen soll" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "Ungültige Zeile beim Parsen alternativer Referenzen: %s" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "Ersetzung %s für %s nicht gefunden." + +#, c-format +msgid "packed object %s (stored in %s) is corrupt" +msgstr "Gepacktes Objekt %s (gespeichert in %s) ist beschädigt." + +#, c-format +msgid "missing mapping of %s to %s" +msgstr "fehlende Abbildung von %s auf %s" + +#, c-format +msgid "%s is not a valid '%s' object" +msgstr "%s ist kein gültiges '%s' Objekt" + #, c-format msgid "invalid object type \"%s\"" msgstr "Ungültiger Objekttyp \"%s\"" @@ -19370,6 +19195,14 @@ msgstr "%s erwartet keinen Wert" msgid "%s isn't available" msgstr "%s ist nicht verfügbar." +#, c-format +msgid "value %s for %s not in range [%,%]" +msgstr "Wert %s für %s nicht im Bereich [%,%]" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s erwartet einen ganzzahligen Wert mit einem optionalen k/m/g-Suffix" + #, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" msgstr "" @@ -19531,10 +19364,6 @@ msgstr "" msgid "bad boolean environment value '%s' for '%s'" msgstr "falscher boolescher Wert von Umgebungsvariable '%s' für '%s'" -#, c-format -msgid "failed to parse %s" -msgstr "Fehler beim Parsen von %s." - #, c-format msgid "failed to walk children of tree %s: not found" msgstr "Fehlen beim Durchlaufen der Kinder von Baum %s: nicht gefunden" @@ -19701,7 +19530,11 @@ msgid "could not fetch %s from promisor remote" msgstr "konnte %s nicht von Promisor-Remote abrufen" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" +msgid "no or empty URL advertised for remote '%s'" +msgstr "keine oder leere URL für Remote-Repository '%s' angegeben" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" msgstr "" "bekanntes Remote-Repository mit dem Namen '%s', aber mit der URL '%s' statt " "'%s'" @@ -20481,6 +20314,10 @@ msgstr "Verzeichnis %s kann nicht geöffnet werden" msgid "Checking references consistency" msgstr "Überprüfung der Konsistenz der Referenzen" +#, c-format +msgid "unable to open '%s'" +msgstr "konnte '%s' nicht öffnen" + #, c-format msgid "refname is dangerous: %s" msgstr "Referenzname ist gefährlich: %s" @@ -20551,10 +20388,6 @@ msgstr "" "Referenzname %s ist eine symbolische Referenz, Kopieren wird nicht " "unterstützt" -#, c-format -msgid "invalid refspec '%s'" -msgstr "ungültige Refspec '%s'" - #, c-format msgid "pattern '%s' has no '*'" msgstr "Muster '%s' hat keinen '*'" @@ -21108,8 +20941,8 @@ msgstr "konnte keine Eintragung hinzufügen" msgid "could not set recommended config" msgstr "konnte die empfohlene Konfiguration nicht setzen" -msgid "could not turn on maintenance" -msgstr "konnte die Wartung nicht einschalten" +msgid "could not toggle maintenance" +msgstr "konnte die Wartung nicht umschalten" msgid "could not start the FSMonitor daemon" msgstr "konnte den FSMonitor-Daemon nicht starten" @@ -21156,12 +20989,15 @@ msgstr "Repository im Verzeichnis 'src' erstellen" msgid "specify if tags should be fetched during clone" msgstr "Angabe, ob Tags während des Klonens abgerufen werden sollen" +msgid "specify if background maintenance should be enabled" +msgstr "angeben, ob die Hintergrundwartung aktiviert werden soll" + msgid "" "scalar clone [--single-branch] [--branch ] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] []" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] []" msgstr "" "scalar clone [--single-branch] [--branch ] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] []" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] []" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -21199,18 +21035,32 @@ msgstr "scalar diagnose []" msgid "`scalar list` does not take arguments" msgstr "`scalar list` akzeptiert keine Argumente" -msgid "scalar register []" -msgstr "scalar register []" +msgid "scalar register [--[no-]maintenance] []" +msgstr "scalar register [--[no-]maintenance] []" msgid "reconfigure all registered enlistments" msgstr "alle registrierten Eintragungen neu konfigurieren" -msgid "scalar reconfigure [--all | ]" -msgstr "scalar reconfigure [--all | ]" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +msgid "signal how to adjust background maintenance" +msgstr "Angabe, wie die Hintergrundwartung einzustellen ist" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"]" msgid "--all or , but not both" msgstr "--all oder , aber nicht beides" +#, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "unbekannter Modus für die Option --maintenance: %s" + #, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "konnte veraltetes scalar.repo '%s' nicht entfernen" @@ -22669,6 +22519,9 @@ msgstr "" "Anzahl der Einträge im Cache-Verzeichnis, die ungültig gemacht werden sollen " "(Standardwert 0)" +msgid "the number of objects to write" +msgstr "die Anzahl der zu schreibenden Objekte" + msgid "test-tool path-walk -- " msgstr "test-tool path-walk -- " @@ -23460,6 +23313,14 @@ msgstr "konnte aktuelles Arbeitsverzeichnis nicht bekommen" msgid "unable to get random bytes" msgstr "konnte keine Zufallsbytes abrufen" +#, c-format +msgid "attempting to mmap % over limit %" +msgstr "Versuche mmap % über Limit %." + +#, c-format +msgid "mmap failed%s" +msgstr "mmap fehlgeschlagen%s" + msgid "Unmerged paths:" msgstr "Nicht zusammengeführte Pfade:" @@ -24269,6 +24130,14 @@ msgstr "" "Konfiguration\n" "und benutzen Sie --smtp-debug." +#, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook hat die Message-ID neu zugewiesen: %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "" +"Warnung: Message-ID konnte nicht aus der Serverantwort abgerufen werden.\n" + #, perl-format msgid "Failed to send %s\n" msgstr "Fehler beim Senden %s\n" diff --git a/po/fr.po b/po/fr.po index 8e3339030761a1..7b5cc9bbc50e36 100644 --- a/po/fr.po +++ b/po/fr.po @@ -87,8 +87,8 @@ msgid "" msgstr "" "Project-Id-Version: git\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2025-03-05 22:57+0000\n" -"PO-Revision-Date: 2025-03-06 16:46+0100\n" +"POT-Creation-Date: 2025-05-27 22:57+0000\n" +"PO-Revision-Date: 2025-05-29 12:54+0200\n" "Last-Translator: Cédric Malard \n" "Language-Team: Jean-Noël Avila \n" "Language: fr\n" @@ -3405,11 +3405,8 @@ msgstr "une seule option de traitement ne peut être spécifiée à la fois" msgid "git cat-file " msgstr "git cat-file " -msgid "git cat-file (-e | -p) " -msgstr "git cat-file (-e | -p) " - -msgid "git cat-file (-t | -s) [--allow-unknown-type] " -msgstr "git cat-file (-t | -s) [--allow-unknown-type] " +msgid "git cat-file (-e | -p | -t | -s) " +msgstr "git cat-file (-e | -p | -t | -s) " msgid "" "git cat-file (--textconv | --filters)\n" @@ -3447,9 +3444,6 @@ msgstr "montrer le type de l'objet (parmi 'blob', 'tree', 'commit', 'tag' ...)" msgid "show object size" msgstr "afficher la taille de l'objet" -msgid "allow -s and -t to work with broken/corrupt objects" -msgstr "autoriser -s et -t à travailler sur des objets cassés/corrompus" - msgid "use mail map file" msgstr "utiliser le fichier de correspondance de mail" @@ -3508,6 +3502,13 @@ msgstr "" "utiliser un spécifique pour (--textconv | --filters); pas pour les " "lots" +msgid "objects filter only supported in batch mode" +msgstr "le filtre d'objets n'est pris en charge qu'en mode par lots" + +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "filtre d'objets non pris en charge : '%s'" + #, c-format msgid "'%s=<%s>' needs '%s' or '%s'" msgstr "'%s=<%s>' a besoin de '%s' ou '%s'" @@ -5811,6 +5812,50 @@ msgstr "spécifier une suffixe au format strftime pour le nom de fichier" msgid "specify the content of the diagnostic archive" msgstr "spécifier le contenu de l'archive de diagnostique" +#, c-format +msgid "unable to parse mode: %s" +msgstr "impossible d'analyser le mode : %s" + +#, c-format +msgid "unable to parse object id: %s" +msgstr "impossible d'analyser l'id de l'objet : %s" + +msgid "git diff-pairs -z []" +msgstr "git diff-pairs -z []" + +#, c-format +msgid "unrecognized argument: %s" +msgstr "argument non reconnu : %s" + +msgid "working without -z is not supported" +msgstr "l'invocation sans -z n'est pas supportée" + +msgid "pathspec arguments not supported" +msgstr "les arguments de spécificateurs de chemin ne sont pas pris en charge" + +msgid "revision arguments not allowed" +msgstr "les arguments de type révision ne sont pas pris en charge" + +msgid "invalid raw diff input" +msgstr "entrée de diff brut invalide" + +msgid "tree objects not supported" +msgstr "les objets arbres ne sont pas supportés" + +msgid "got EOF while reading path" +msgstr "EOF rencontré lors de la lecture du chemin" + +msgid "got EOF while reading destination path" +msgstr "EOF rencontré lors de la lecture du chemin destination" + +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "impossible d'analyser le score de renommage/copie : %s" + +#, c-format +msgid "unknown diff status: %c" +msgstr "statut de diff inconnu : %c" + msgid "--merge-base only works with two commits" msgstr "--merge-base ne fonctionne qu'avec deux commits" @@ -5952,6 +5997,9 @@ msgstr "afficher la progression après objets" msgid "select handling of signed tags" msgstr "sélectionner la gestion des étiquettes signées" +msgid "select handling of signed commits" +msgstr "sélectionner la gestion des commits signés" + msgid "select handling of tags that tag filtered objects" msgstr "" "sélectionner la gestion des étiquettes qui pointent sur des objets filtrés" @@ -6604,10 +6652,6 @@ msgstr "%s : incohérence de hachage,trouvé à : %s" msgid "%s: object corrupt or missing: %s" msgstr "%s : objet corrompu ou manquant : %s" -#, c-format -msgid "%s: object is of unknown type '%s': %s" -msgstr "%s : l'objet a un type '%s' inconnu : %s" - #, c-format msgid "%s: object could not be parsed: %s" msgstr "%s : impossible d'analyser : %s" @@ -6665,16 +6709,19 @@ msgstr "impossible de charger le rev-index pour le paquet '%s'" msgid "invalid rev-index for pack '%s'" msgstr "rev-index invalide pour le paquet '%s'" +msgid "Checking ref database" +msgstr "Vérification de la base de données des réferences" + msgid "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" -" [--[no-]name-objects] [...]" +" [--[no-]name-objects] [--[no-]references] [...]" msgstr "" "git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" -" [--[no-]name-objects] [...]" +" [--[no-]name-objects] [--[no-]references] [...]" msgid "show unreachable objects" msgstr "afficher les objets inaccessibles" @@ -6713,6 +6760,9 @@ msgstr "afficher la progression" msgid "show verbose names for reachable objects" msgstr "afficher les noms étendus pour les objets inaccessibles" +msgid "check reference database consistency" +msgstr "vérifier la cohérence de la base de données des références" + msgid "Checking objects" msgstr "Vérification des objets" @@ -7877,10 +7927,6 @@ msgstr "" "tracer l'évolution d'une plage , ou d'une fonction dans " -#, c-format -msgid "unrecognized argument: %s" -msgstr "argument non reconnu : %s" - msgid "-L: cannot be used with pathspec" msgstr "" "-L: ne peut pas être utilisé avec une spécificateur de chemin" @@ -8550,6 +8596,9 @@ msgstr "faire seulement une fusion triviale" msgid "also show informational/conflict messages" msgstr "afficher aussi les messages d'information/de conflit" +msgid "suppress all output; only exit status wanted" +msgstr "supprimer toutes les sorties ; seul le statut de sortie est rendu" + msgid "list filenames without modes/oids/stages" msgstr "lister les noms de fichier sans modes/oids/indexation" @@ -8961,8 +9010,11 @@ msgstr "" "pendant le repaquetage, collecter les fichiers paquet de plus petite taille " "dans un lot plus grand que cette taille" -msgid "git mv [] ... " -msgstr "git mv [] ... " +msgid "git mv [-v] [-f] [-n] [-k] " +msgstr "git mv [-v] [-f] [-n] [-k] " + +msgid "git mv [-v] [-f] [-n] [-k] ... " +msgstr "git mv [-v] [-f] [-n] [-k] ... " #, c-format msgid "Directory %s is in index and no submodule?" @@ -9032,6 +9084,10 @@ msgstr "la destination existe dans l'index" msgid "%s, source=%s, destination=%s" msgstr "%s, source=%s, destination=%s" +#, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "Impossible de déplacer à la fois '%s' et son répertoire parent '%s'" + #, c-format msgid "Renaming %s to %s\n" msgstr "Renommage de %s en %s\n" @@ -9975,6 +10031,10 @@ msgstr "" msgid "unable to access commit %s" msgstr "impossible d'accéder le commit %s" +#, c-format +msgid "invalid refspec '%s'" +msgstr "spécificateur de réference invalide : '%s'" + msgid "ignoring --verify-signatures for rebase" msgstr "--verify-signatures est ignoré pour un rebasage" @@ -10957,6 +11017,9 @@ msgstr "" msgid "git reflog exists " msgstr "git reflog exists " +msgid "git reflog drop [--all [--single-worktree] | ...]" +msgstr "git reflog drop [--all [--single-worktree] | ...]" + #, c-format msgid "invalid timestamp '%s' given to '--%s'" msgstr "horodatage invalide '%s' fourni à '--%s'" @@ -11008,8 +11071,8 @@ msgid "Marking reachable objects..." msgstr "Marquage des objets inaccessibles..." #, c-format -msgid "%s points nowhere!" -msgstr "%s ne pointe nulle part !" +msgid "reflog could not be found: '%s'" +msgstr "impossible de trouver le journal de références : '%s'" msgid "no reflog specified to delete" msgstr "pas de journal de références à supprimer spécifié" @@ -11018,6 +11081,15 @@ msgstr "pas de journal de références à supprimer spécifié" msgid "invalid ref format: %s" msgstr "format de référence invalide : %s" +msgid "drop the reflogs of all references" +msgstr "abandonner les reflogs de toutes les références" + +msgid "drop reflogs from the current worktree only" +msgstr "abandonner les reflogs de l'arbre-de-travail actuel uniquement" + +msgid "references specified along with --all" +msgstr "références spécifiées en même temps que --all" + msgid "git refs migrate --ref-format= [--no-reflog] [--dry-run]" msgstr "git refs migrate --ref-format= [--no-reflog] [--dry-run]" @@ -11581,7 +11653,10 @@ msgid "approxidate" msgstr "date approximative" msgid "with --cruft, expire objects older than this" -msgstr "avec --cruft, faire expirer les objets plus vieux que celui-ci" +msgstr "avec --cruft, faire expirer les objets plus vieux que ceci" + +msgid "with --cruft, only repack cruft packs smaller than this" +msgstr "avec --cruft, ne réempaqueter que les objets plus petits que ceci" msgid "remove redundant packs, and run git-prune-packed" msgstr "supprimer les paquets redondants et lancer git-prune-packed" @@ -12064,6 +12139,9 @@ msgstr "impossible de récupérer l'utilisation du disque de %s" msgid "invalid value for '%s': '%s', the only allowed format is '%s'" msgstr "valeur invalide pour '%s' : '%s', le seul format permis est '%s'" +msgid "-z option used with unsupported option" +msgstr "option -z utilisée avec une option non supportée" + msgid "rev-list does not support display of notes" msgstr "rev-list ne supporte l'affichage des notes" @@ -13970,8 +14048,8 @@ msgid "git update-ref [] []" msgstr "" "git update-ref [] []" -msgid "git update-ref [] --stdin [-z]" -msgstr "git update-ref [] --stdin [-z]" +msgid "git update-ref [] --stdin [-z] [--batch-updates]" +msgstr "git update-ref [] --stdin [-z] [--batch-updates]" msgid "delete the reference" msgstr "supprimer la référence" @@ -13985,6 +14063,9 @@ msgstr "l'entrée standard a des arguments qui se terminent par NUL" msgid "read updates from stdin" msgstr "lire les mises à jour depuis l'entrée standard" +msgid "batch reference updates" +msgstr "traiter les mises à jour par lot" + msgid "update the info files from scratch" msgstr "mettre à jour les fichiers d'information à partir de zéro" @@ -14690,6 +14771,9 @@ msgstr "Compare des fichiers de l'arbre de travail et de l'index" msgid "Compare a tree to the working tree or index" msgstr "Comparer un arbre avec l'arbre de travail ou l'index" +msgid "Compare the content and mode of provided blob pairs" +msgstr "Compare le contenu et le mode des paires de blobs fournies" + msgid "Compares the content and mode of blobs found via two tree objects" msgstr "Compare le contenu et le mode des blobs trouvés via deux objets arbre" @@ -17678,6 +17762,10 @@ msgstr "La délégation de commande n'est pas supporté avec cuRL < 7.22.0" msgid "Unknown value for http.proactiveauth" msgstr "valeur inconnue pour http.proactiveauth" +#, c-format +msgid "failed to parse %s" +msgstr "échec de l'analyse de %s" + #, c-format msgid "Unsupported SSL backend '%s'. Supported SSL backends:" msgstr "Dorsale SSL '%s' non supportée. Dorsales SSL supportées :" @@ -17870,6 +17958,10 @@ msgstr "impossible de formater le message : %s" msgid "invalid marker-size '%s', expecting an integer" msgstr "taille de marqueur invalide '%s', entier attendu" +#, c-format +msgid "Could not parse object '%s'" +msgstr "Impossible d'analyser l'objet '%s'" + #, c-format msgid "Failed to merge submodule %s (not checked out)" msgstr "Échec de la fusion du sous-module %s (non extrait)" @@ -18119,264 +18211,6 @@ msgstr "" msgid "collecting merge info failed for trees %s, %s, %s" msgstr "échec de collecte l'information de fusion pour les arbres %s, %s, %s" -msgid "(bad commit)\n" -msgstr "(mauvais commit)\n" - -#, c-format -msgid "add_cacheinfo failed for path '%s'; merge aborting." -msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." - -#, c-format -msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." -msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." - -#, c-format -msgid "failed to create path '%s'%s" -msgstr "impossible de créer le chemin '%s' %s" - -#, c-format -msgid "Removing %s to make room for subdirectory\n" -msgstr "Suppression de %s pour faire de la place pour le sous-répertoire\n" - -msgid ": perhaps a D/F conflict?" -msgstr ": peut-être un conflit D/F ?" - -#, c-format -msgid "refusing to lose untracked file at '%s'" -msgstr "refus de perdre le fichier non suivi '%s'" - -#, c-format -msgid "blob expected for %s '%s'" -msgstr "blob attendu pour %s '%s'" - -#, c-format -msgid "failed to open '%s': %s" -msgstr "échec à l'ouverture de '%s' : %s" - -#, c-format -msgid "failed to symlink '%s': %s" -msgstr "échec à la création du lien symbolique '%s' : %s" - -#, c-format -msgid "do not know what to do with %06o %s '%s'" -msgstr "ne sait pas traiter %06o %s '%s'" - -#, c-format -msgid "Failed to merge submodule %s (repository corrupt)" -msgstr "Échec de la fusion du sous-module %s (dépôt corrompu)" - -#, c-format -msgid "Fast-forwarding submodule %s to the following commit:" -msgstr "Avance rapide du sous-module %s au commit suivant :" - -#, c-format -msgid "Fast-forwarding submodule %s" -msgstr "Avance rapide du sous-module %s" - -#, c-format -msgid "Failed to merge submodule %s (merge following commits not found)" -msgstr "" -"Échec de fusion du sous-module %s (fusion suivant les commits non trouvée)" - -#, c-format -msgid "Failed to merge submodule %s (not fast-forward)" -msgstr "Échec de fusion du sous-module %s (pas en avance rapide)" - -msgid "Found a possible merge resolution for the submodule:\n" -msgstr "Résolution possible de fusion trouvée pour le sous-module :\n" - -#, c-format -msgid "" -"If this is correct simply add it to the index for example\n" -"by using:\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"which will accept this suggestion.\n" -msgstr "" -"Si c'est correct, ajoutez le simplement à l'index\n" -"en utilisant par exemple :\n" -"\n" -" git update-index --cacheinfo 160000 %s \"%s\"\n" -"\n" -"qui acceptera cette suggestion.\n" - -#, c-format -msgid "Failed to merge submodule %s (multiple merges found)" -msgstr "Échec de fusion du sous-module %s (plusieurs fusions trouvées)" - -msgid "failed to execute internal merge" -msgstr "échec à l'exécution de la fusion interne" - -#, c-format -msgid "unable to add %s to database" -msgstr "impossible d'ajouter %s à la base de données" - -#, c-format -msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." -msgstr "" -"Erreur : refus de perdre le fichier non suivi %s ; écriture dans %s à la " -"place." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s de " -"%s laissée dans l'arbre." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. Version " -"%s de %s laissée dans l'arbre." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " -"in tree at %s." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s de " -"%s laissée dans l'arbre dans le fichier %s." - -#, c-format -msgid "" -"CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of %s " -"left in tree at %s." -msgstr "" -"CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. Version " -"%s de %s laissée dans l'arbre dans le fichier %s." - -msgid "rename" -msgstr "renommage" - -msgid "renamed" -msgstr "renommé" - -#, c-format -msgid "Refusing to lose dirty file at %s" -msgstr "Refus de perdre le fichier modifié %s" - -#, c-format -msgid "Refusing to lose untracked file at %s, even though it's in the way." -msgstr "Refus de perdre le fichier non suivi %s, même s'il gêne." - -#, c-format -msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" -msgstr "" -"CONFLIT (renommage/ajout) : Renommage de %s->%s dans %s. %s ajouté dans %s" - -#, c-format -msgid "%s is a directory in %s adding as %s instead" -msgstr "%s est un répertoire dans %s ajouté plutôt comme %s" - -#, c-format -msgid "Refusing to lose untracked file at %s; adding as %s instead" -msgstr "Refus de perdre le fichier non suivi %s ; ajout comme %s à la place" - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " -"\"%s\"->\"%s\" in \"%s\"%s" -msgstr "" -"CONFLIT (renommage/renommage) : Renommage de \"%s\"->\"%s\" dans la branche " -"\"%s\" et renommage \"%s\"->\"%s\" dans \"%s\"%s" - -msgid " (left unresolved)" -msgstr " (laissé non résolu)" - -#, c-format -msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" -msgstr "" -"CONFLIT (renommage/renommage) : renommage '%s'->'%s' dans %s. Renommage '%s'-" -">'%s' dans %s" - -#, c-format -msgid "" -"CONFLICT (directory rename split): Unclear where to place %s because " -"directory %s was renamed to multiple other directories, with no destination " -"getting a majority of the files." -msgstr "" -"CONFLIT (renommage de répertoire coupé) : la place de %s n'est pas claire " -"parce que le répertoire %s a été renommé en plusieurs autres répertoires, " -"sans aucune destination récupérant la majorité des fichiers." - -#, c-format -msgid "" -"CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory %s-" -">%s in %s" -msgstr "" -"CONFLIT (renommage/renommage) : renommage du répertoire %s->%s dans %s. " -"Renommage de répertoire %s->%s dans %s" - -#, c-format -msgid "cannot read object %s" -msgstr "impossible de lire l'objet %s" - -#, c-format -msgid "object %s is not a blob" -msgstr "l'objet %s n'est pas un blob" - -msgid "modify" -msgstr "modification" - -msgid "modified" -msgstr "modifié" - -#, c-format -msgid "Skipped %s (merged same as existing)" -msgstr "%s sauté (fusion identique à l'existant)" - -#, c-format -msgid "Adding as %s instead" -msgstr "Ajout plutôt comme %s" - -#, c-format -msgid "Removing %s" -msgstr "Suppression de %s" - -msgid "file/directory" -msgstr "fichier/répertoire" - -msgid "directory/file" -msgstr "répertoire/fichier" - -#, c-format -msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" -msgstr "" -"CONFLIT (%s) : Il y a un répertoire nommé %s dans %s. Ajout de %s comme %s" - -#, c-format -msgid "Adding %s" -msgstr "Ajout de %s" - -#, c-format -msgid "CONFLICT (add/add): Merge conflict in %s" -msgstr "CONFLIT (ajout/ajout) : Conflit de fusion dans %s" - -#, c-format -msgid "merging of trees %s and %s failed" -msgstr "échec de fusion des arbres %s et %s" - -msgid "Merging:" -msgstr "Fusion :" - -#, c-format -msgid "found %u common ancestor:" -msgid_plural "found %u common ancestors:" -msgstr[0] "%u ancêtre commun trouvé :" -msgstr[1] "%u ancêtres communs trouvés :" - -msgid "merge returned no commit" -msgstr "la fusion n'a pas retourné de commit" - -#, c-format -msgid "Could not parse object '%s'" -msgstr "Impossible d'analyser l'objet '%s'" - msgid "failed to read the cache" msgstr "impossible de lire le cache" @@ -18418,13 +18252,14 @@ msgstr "impossible de lier '%s' à '%s'" msgid "failed to clear multi-pack-index at %s" msgstr "échec du nettoyage de l'index de multi-paquet à %s" -msgid "cannot write incremental MIDX with bitmap" -msgstr "impossible d'écrire un MIDX incrémental avec des bitmap" - msgid "ignoring existing multi-pack-index; checksum mismatch" msgstr "" "index multi-paquet existant ignoré ; non-concordance de la somme de contrôle" +#, c-format +msgid "could not load reverse index for MIDX %s" +msgstr "impossible de charger l'index inversé pour le MIDX %s" + msgid "Adding packfiles to multi-pack-index" msgstr "Ajout de fichiers paquet à un index multi-paquet" @@ -18691,66 +18526,6 @@ msgstr "impossible de faire correspondre %s %s dans l'objet de commit" msgid "Failed to convert object from %s to %s" msgstr "Échec de conversion de l'objet de %s vers %s" -#, c-format -msgid "object directory %s does not exist; check .git/objects/info/alternates" -msgstr "" -"le répertoire objet %s n'existe pas ; vérifiez .git/objects/info/alternates" - -#, c-format -msgid "unable to normalize alternate object path: %s" -msgstr "impossible de normaliser le chemin d'objet alternatif : %s" - -#, c-format -msgid "%s: ignoring alternate object stores, nesting too deep" -msgstr "%s : magasins d'objets alternatifs ignorés, récursion trop profonde" - -msgid "unable to fdopen alternates lockfile" -msgstr "impossible d'ouvrir (fdopen) le fichier verrou des alternatives" - -msgid "unable to read alternates file" -msgstr "lecture du fichier d'alternatives impossible" - -msgid "unable to move new alternates file into place" -msgstr "impossible de déplacer le nouveau fichier d'alternative" - -#, c-format -msgid "path '%s' does not exist" -msgstr "le chemin '%s' n'existe pas" - -#, c-format -msgid "reference repository '%s' as a linked checkout is not supported yet." -msgstr "" -"extraire le dépôt de référence '%s' comme une extraction liée n'est pas " -"encore supporté." - -#, c-format -msgid "reference repository '%s' is not a local repository." -msgstr "le dépôt de référence '%s' n'est pas un dépôt local." - -#, c-format -msgid "reference repository '%s' is shallow" -msgstr "le dépôt de référence '%s' est superficiel" - -#, c-format -msgid "reference repository '%s' is grafted" -msgstr "le dépôt de référence '%s' est greffé" - -#, c-format -msgid "could not find object directory matching %s" -msgstr "impossible de trouver le répertoire objet correspondant à %s" - -#, c-format -msgid "invalid line while parsing alternate refs: %s" -msgstr "ligne invalide pendant l'analyse des refs alternatives : %s" - -#, c-format -msgid "attempting to mmap % over limit %" -msgstr "essai de mmap % au delà de la limite %" - -#, c-format -msgid "mmap failed%s" -msgstr "échec de mmap%s" - #, c-format msgid "object file %s is empty" msgstr "le fichier objet %s est vide" @@ -18786,18 +18561,6 @@ msgstr "entête de %s trop long, attendu %d octets" msgid "loose object %s (stored in %s) is corrupt" msgstr "l'objet libre %s (stocké dans %s) est corrompu" -#, c-format -msgid "replacement %s not found for %s" -msgstr "remplacement %s non trouvé pour %s" - -#, c-format -msgid "packed object %s (stored in %s) is corrupt" -msgstr "l'objet empaqueté %s (stocké dans %s) est corrompu" - -#, c-format -msgid "missing mapping of %s to %s" -msgstr "correspondance manquante entre %s et %s" - #, c-format msgid "unable to open %s" msgstr "impossible d'ouvrir %s" @@ -18891,10 +18654,6 @@ msgstr "%s : échec de l'insertion dans la base de données" msgid "%s: unsupported file type" msgstr "%s : type de fichier non supporté" -#, c-format -msgid "%s is not a valid '%s' object" -msgstr "%s n'est pas un objet '%s' valide" - #, c-format msgid "hash mismatch for %s (expected %s)" msgstr "incohérence de hachage pour %s (%s attendu)" @@ -18911,6 +18670,10 @@ msgstr "impossible de dépaqueter l'entête de %s" msgid "unable to parse header of %s" msgstr "impossible d'analyser l'entête de %s" +#, c-format +msgid "unable to parse type from header '%s' of %s" +msgstr "impossible d'analyser le type depuis l'entête '%s' de '%s'" + #, c-format msgid "unable to unpack contents of %s" msgstr "impossible de dépaqueter le contenu de %s" @@ -19071,6 +18834,74 @@ msgstr ": nécessaire, seul '%s' a été fourni" msgid "invalid object name '%.*s'." msgstr "nom d'objet invalide : '%.*s'." +#, c-format +msgid "object directory %s does not exist; check .git/objects/info/alternates" +msgstr "" +"le répertoire objet %s n'existe pas ; vérifiez .git/objects/info/alternates" + +#, c-format +msgid "unable to normalize alternate object path: %s" +msgstr "impossible de normaliser le chemin d'objet alternatif : %s" + +#, c-format +msgid "%s: ignoring alternate object stores, nesting too deep" +msgstr "%s : magasins d'objets alternatifs ignorés, récursion trop profonde" + +msgid "unable to fdopen alternates lockfile" +msgstr "impossible d'ouvrir (fdopen) le fichier verrou des alternatives" + +msgid "unable to read alternates file" +msgstr "lecture du fichier d'alternatives impossible" + +msgid "unable to move new alternates file into place" +msgstr "impossible de déplacer le nouveau fichier d'alternative" + +#, c-format +msgid "path '%s' does not exist" +msgstr "le chemin '%s' n'existe pas" + +#, c-format +msgid "reference repository '%s' as a linked checkout is not supported yet." +msgstr "" +"extraire le dépôt de référence '%s' comme une extraction liée n'est pas " +"encore supporté." + +#, c-format +msgid "reference repository '%s' is not a local repository." +msgstr "le dépôt de référence '%s' n'est pas un dépôt local." + +#, c-format +msgid "reference repository '%s' is shallow" +msgstr "le dépôt de référence '%s' est superficiel" + +#, c-format +msgid "reference repository '%s' is grafted" +msgstr "le dépôt de référence '%s' est greffé" + +#, c-format +msgid "could not find object directory matching %s" +msgstr "impossible de trouver le répertoire objet correspondant à %s" + +#, c-format +msgid "invalid line while parsing alternate refs: %s" +msgstr "ligne invalide pendant l'analyse des refs alternatives : %s" + +#, c-format +msgid "replacement %s not found for %s" +msgstr "remplacement %s non trouvé pour %s" + +#, c-format +msgid "packed object %s (stored in %s) is corrupt" +msgstr "l'objet empaqueté %s (stocké dans %s) est corrompu" + +#, c-format +msgid "missing mapping of %s to %s" +msgstr "correspondance manquante entre %s et %s" + +#, c-format +msgid "%s is not a valid '%s' object" +msgstr "%s n'est pas un objet '%s' valide" + #, c-format msgid "invalid object type \"%s\"" msgstr "type d'objet invalide \"%s\"" @@ -19355,9 +19186,18 @@ msgstr "%s n'accepte aucune valeur" msgid "%s isn't available" msgstr "%s n'est pas disponible" +#, c-format +msgid "value %s for %s not in range [%,%]" +msgstr "valeur %s pour %s pas dans la plage [%,%]" + +#, c-format +msgid "%s expects an integer value with an optional k/m/g suffix" +msgstr "%s attend une valeur entière avec un suffixe k/m/g optionnel" + #, c-format msgid "%s expects a non-negative integer value with an optional k/m/g suffix" -msgstr "%s attend une valeur entière non négative avec une suffixe k/m/g" +msgstr "" +"%s attend une valeur entière non négative avec un suffixe k/m/g optionnel" #, c-format msgid "ambiguous option: %s (could be --%s%s or --%s%s)" @@ -19514,10 +19354,6 @@ msgstr "" msgid "bad boolean environment value '%s' for '%s'" msgstr "valeur booléenne d'environnement invalide '%s' pour '%s'" -#, c-format -msgid "failed to parse %s" -msgstr "échec de l'analyse de %s" - #, c-format msgid "failed to walk children of tree %s: not found" msgstr "échec de parcours des enfants de l'arbre %s : non trouvé" @@ -19691,8 +19527,12 @@ msgid "could not fetch %s from promisor remote" msgstr "impossible de récupérer %s depuis le distant de prometteur" #, c-format -msgid "known remote named '%s' but with url '%s' instead of '%s'" -msgstr "distant connu nommé '%s' mais avec l'url '%s' au lieu de '%s'" +msgid "no or empty URL advertised for remote '%s'" +msgstr "URL manquante ou vide annoncée pour le distant '%s'" + +#, c-format +msgid "known remote named '%s' but with URL '%s' instead of '%s'" +msgstr "distant connu nommé '%s' mais avec l'URL '%s' au lieu de '%s'" #, c-format msgid "unknown '%s' value for '%s' config option" @@ -20465,6 +20305,10 @@ msgstr "impossible d'ouvrir le répertoire %s" msgid "Checking references consistency" msgstr "Vérification de la cohérence des références" +#, c-format +msgid "unable to open '%s'" +msgstr "impossible d'ouvrir '%s'" + #, c-format msgid "refname is dangerous: %s" msgstr "le nom de réference est dangereux : %s" @@ -20538,10 +20382,6 @@ msgid "refname %s is a symbolic ref, copying it is not supported" msgstr "" "le nom de réf %s est une réf symbolique, la copie n'est pas prise en charge" -#, c-format -msgid "invalid refspec '%s'" -msgstr "spécificateur de réference invalide : '%s'" - #, c-format msgid "pattern '%s' has no '*'" msgstr "la valeur '%s' du motif n'a pas de '*'" @@ -21097,7 +20937,7 @@ msgstr "impossible d'ajouter l'enrôlement" msgid "could not set recommended config" msgstr "impossible de réglér la configuration recommandée" -msgid "could not turn on maintenance" +msgid "could not toggle maintenance" msgstr "impossible d'activer la maintenance" msgid "could not start the FSMonitor daemon" @@ -21146,13 +20986,16 @@ msgid "specify if tags should be fetched during clone" msgstr "" "spécifier si les étiquettes devraient être récupérées pendant le clonage" +msgid "specify if background maintenance should be enabled" +msgstr "spécifier si la maintenance en tâche de fond doit être activée" + msgid "" "scalar clone [--single-branch] [--branch ] [--full-clone]\n" -"\t[--[no-]src] [--[no-]tags] []" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] []" msgstr "" "scalar clone [--single-branch] [--branch ] [--full-" "clone]\n" -"\t[--[no-]src] [--[no-]tags] []" +"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] []" #, c-format msgid "cannot deduce worktree name from '%s'" @@ -21190,18 +21033,32 @@ msgstr "scalar diagnose []" msgid "`scalar list` does not take arguments" msgstr "`scalar list` n'accepte pas d'argument" -msgid "scalar register []" -msgstr "scalar register []" +msgid "scalar register [--[no-]maintenance] []" +msgstr "scalar register [--[no-]maintenance] []" msgid "reconfigure all registered enlistments" msgstr "reconfigurer tous les enrôlements enregistrés" -msgid "scalar reconfigure [--all | ]" -msgstr "scala reconfigure [--all|]" +msgid "(enable|disable|keep)" +msgstr "(enable|disable|keep)" + +msgid "signal how to adjust background maintenance" +msgstr "signaler comment ajuster la maintenance en tâche de fond" + +msgid "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"]" +msgstr "" +"scalar reconfigure [--maintenance=(enable|disable|keep)] [--all | " +"]" msgid "--all or , but not both" msgstr "--all ou , mais pas les deux" +#, c-format +msgid "unknown mode for --maintenance option: %s" +msgstr "mode inconnu pour l'option --maintenance : %s" + #, c-format msgid "could not remove stale scalar.repo '%s'" msgstr "impossible de supprimé le scalar.repo obsolète '%s'" @@ -22652,6 +22509,9 @@ msgstr "effacer l'arbre de cache avant chaque itération" msgid "number of entries in the cache tree to invalidate (default 0)" msgstr "nombre d'entrées dans l'arbre de cache à invalider (par défaut, 0)" +msgid "the number of objects to write" +msgstr "le nombre d'objets à écrire" + msgid "test-tool path-walk -- " msgstr "test-tool path-walk -- " @@ -23445,6 +23305,14 @@ msgstr "impossible d'accéder au répertoire de travail courant" msgid "unable to get random bytes" msgstr "impossible d'acquérir des octets aléatoires" +#, c-format +msgid "attempting to mmap % over limit %" +msgstr "essai de mmap % au delà de la limite %" + +#, c-format +msgid "mmap failed%s" +msgstr "échec de mmap%s" + msgid "Unmerged paths:" msgstr "Chemins non fusionnés :" @@ -24202,6 +24070,15 @@ msgstr "" "Impossible d'initialiser SMTP. Vérifiez la configuration et utilisez --smtp-" "debug." +#, perl-format +msgid "Outlook reassigned Message-ID to: %s\n" +msgstr "Outlook a réassigné le Message-ID à : %s\n" + +msgid "Warning: Could not retrieve Message-ID from server response.\n" +msgstr "" +"Avertissement : Impossible de récupérer le Message-ID dans la réponse du " +"serveur.\n" + #, perl-format msgid "Failed to send %s\n" msgstr "Échec de l'envoi de %s\n" @@ -24299,6 +24176,278 @@ msgstr "%s sauté avec un suffix de sauvegarde '%s'.\n" msgid "Do you really want to send %s? [y|N]: " msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " +#~ msgid "git cat-file (-t | -s) [--allow-unknown-type] " +#~ msgstr "git cat-file (-t | -s) [--allow-unknown-type] " + +#~ msgid "allow -s and -t to work with broken/corrupt objects" +#~ msgstr "autoriser -s et -t à travailler sur des objets cassés/corrompus" + +#, c-format +#~ msgid "%s: object is of unknown type '%s': %s" +#~ msgstr "%s : l'objet a un type '%s' inconnu : %s" + +#, c-format +#~ msgid "%s points nowhere!" +#~ msgstr "%s ne pointe nulle part !" + +#~ msgid "(bad commit)\n" +#~ msgstr "(mauvais commit)\n" + +#, c-format +#~ msgid "add_cacheinfo failed for path '%s'; merge aborting." +#~ msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." + +#, c-format +#~ msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting." +#~ msgstr "échec de add_cacheinfo pour le chemin '%s' ; abandon de la fusion." + +#, c-format +#~ msgid "failed to create path '%s'%s" +#~ msgstr "impossible de créer le chemin '%s' %s" + +#, c-format +#~ msgid "Removing %s to make room for subdirectory\n" +#~ msgstr "Suppression de %s pour faire de la place pour le sous-répertoire\n" + +#~ msgid ": perhaps a D/F conflict?" +#~ msgstr ": peut-être un conflit D/F ?" + +#, c-format +#~ msgid "refusing to lose untracked file at '%s'" +#~ msgstr "refus de perdre le fichier non suivi '%s'" + +#, c-format +#~ msgid "blob expected for %s '%s'" +#~ msgstr "blob attendu pour %s '%s'" + +#, c-format +#~ msgid "failed to open '%s': %s" +#~ msgstr "échec à l'ouverture de '%s' : %s" + +#, c-format +#~ msgid "failed to symlink '%s': %s" +#~ msgstr "échec à la création du lien symbolique '%s' : %s" + +#, c-format +#~ msgid "do not know what to do with %06o %s '%s'" +#~ msgstr "ne sait pas traiter %06o %s '%s'" + +#, c-format +#~ msgid "Failed to merge submodule %s (repository corrupt)" +#~ msgstr "Échec de la fusion du sous-module %s (dépôt corrompu)" + +#, c-format +#~ msgid "Fast-forwarding submodule %s to the following commit:" +#~ msgstr "Avance rapide du sous-module %s au commit suivant :" + +#, c-format +#~ msgid "Fast-forwarding submodule %s" +#~ msgstr "Avance rapide du sous-module %s" + +#, c-format +#~ msgid "Failed to merge submodule %s (merge following commits not found)" +#~ msgstr "" +#~ "Échec de fusion du sous-module %s (fusion suivant les commits non trouvée)" + +#, c-format +#~ msgid "Failed to merge submodule %s (not fast-forward)" +#~ msgstr "Échec de fusion du sous-module %s (pas en avance rapide)" + +#~ msgid "Found a possible merge resolution for the submodule:\n" +#~ msgstr "Résolution possible de fusion trouvée pour le sous-module :\n" + +#, c-format +#~ msgid "" +#~ "If this is correct simply add it to the index for example\n" +#~ "by using:\n" +#~ "\n" +#~ " git update-index --cacheinfo 160000 %s \"%s\"\n" +#~ "\n" +#~ "which will accept this suggestion.\n" +#~ msgstr "" +#~ "Si c'est correct, ajoutez le simplement à l'index\n" +#~ "en utilisant par exemple :\n" +#~ "\n" +#~ " git update-index --cacheinfo 160000 %s \"%s\"\n" +#~ "\n" +#~ "qui acceptera cette suggestion.\n" + +#, c-format +#~ msgid "Failed to merge submodule %s (multiple merges found)" +#~ msgstr "Échec de fusion du sous-module %s (plusieurs fusions trouvées)" + +#~ msgid "failed to execute internal merge" +#~ msgstr "échec à l'exécution de la fusion interne" + +#, c-format +#~ msgid "unable to add %s to database" +#~ msgstr "impossible d'ajouter %s à la base de données" + +#, c-format +#~ msgid "Error: Refusing to lose untracked file at %s; writing to %s instead." +#~ msgstr "" +#~ "Erreur : refus de perdre le fichier non suivi %s ; écriture dans %s à la " +#~ "place." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s " +#~ "left in tree." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s " +#~ "de %s laissée dans l'arbre." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of " +#~ "%s left in tree." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. " +#~ "Version %s de %s laissée dans l'arbre." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s " +#~ "left in tree at %s." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s " +#~ "de %s laissée dans l'arbre dans le fichier %s." + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s/delete): %s deleted in %s and %s to %s in %s. Version %s of " +#~ "%s left in tree at %s." +#~ msgstr "" +#~ "CONFLIT (%s/suppression) : %s supprimé dans %s et %s à %s dans %s. " +#~ "Version %s de %s laissée dans l'arbre dans le fichier %s." + +#~ msgid "rename" +#~ msgstr "renommage" + +#~ msgid "renamed" +#~ msgstr "renommé" + +#, c-format +#~ msgid "Refusing to lose dirty file at %s" +#~ msgstr "Refus de perdre le fichier modifié %s" + +#, c-format +#~ msgid "Refusing to lose untracked file at %s, even though it's in the way." +#~ msgstr "Refus de perdre le fichier non suivi %s, même s'il gêne." + +#, c-format +#~ msgid "CONFLICT (rename/add): Rename %s->%s in %s. Added %s in %s" +#~ msgstr "" +#~ "CONFLIT (renommage/ajout) : Renommage de %s->%s dans %s. %s ajouté dans %s" + +#, c-format +#~ msgid "%s is a directory in %s adding as %s instead" +#~ msgstr "%s est un répertoire dans %s ajouté plutôt comme %s" + +#, c-format +#~ msgid "Refusing to lose untracked file at %s; adding as %s instead" +#~ msgstr "Refus de perdre le fichier non suivi %s ; ajout comme %s à la place" + +#, c-format +#~ msgid "" +#~ "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename " +#~ "\"%s\"->\"%s\" in \"%s\"%s" +#~ msgstr "" +#~ "CONFLIT (renommage/renommage) : Renommage de \"%s\"->\"%s\" dans la " +#~ "branche \"%s\" et renommage \"%s\"->\"%s\" dans \"%s\"%s" + +#~ msgid " (left unresolved)" +#~ msgstr " (laissé non résolu)" + +#, c-format +#~ msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" +#~ msgstr "" +#~ "CONFLIT (renommage/renommage) : renommage '%s'->'%s' dans %s. Renommage " +#~ "'%s'->'%s' dans %s" + +#, c-format +#~ msgid "" +#~ "CONFLICT (directory rename split): Unclear where to place %s because " +#~ "directory %s was renamed to multiple other directories, with no " +#~ "destination getting a majority of the files." +#~ msgstr "" +#~ "CONFLIT (renommage de répertoire coupé) : la place de %s n'est pas claire " +#~ "parce que le répertoire %s a été renommé en plusieurs autres répertoires, " +#~ "sans aucune destination récupérant la majorité des fichiers." + +#, c-format +#~ msgid "" +#~ "CONFLICT (rename/rename): Rename directory %s->%s in %s. Rename directory " +#~ "%s->%s in %s" +#~ msgstr "" +#~ "CONFLIT (renommage/renommage) : renommage du répertoire %s->%s dans %s. " +#~ "Renommage de répertoire %s->%s dans %s" + +#, c-format +#~ msgid "cannot read object %s" +#~ msgstr "impossible de lire l'objet %s" + +#, c-format +#~ msgid "object %s is not a blob" +#~ msgstr "l'objet %s n'est pas un blob" + +#~ msgid "modify" +#~ msgstr "modification" + +#~ msgid "modified" +#~ msgstr "modifié" + +#, c-format +#~ msgid "Skipped %s (merged same as existing)" +#~ msgstr "%s sauté (fusion identique à l'existant)" + +#, c-format +#~ msgid "Adding as %s instead" +#~ msgstr "Ajout plutôt comme %s" + +#, c-format +#~ msgid "Removing %s" +#~ msgstr "Suppression de %s" + +#~ msgid "file/directory" +#~ msgstr "fichier/répertoire" + +#~ msgid "directory/file" +#~ msgstr "répertoire/fichier" + +#, c-format +#~ msgid "" +#~ "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" +#~ msgstr "" +#~ "CONFLIT (%s) : Il y a un répertoire nommé %s dans %s. Ajout de %s comme %s" + +#, c-format +#~ msgid "Adding %s" +#~ msgstr "Ajout de %s" + +#, c-format +#~ msgid "CONFLICT (add/add): Merge conflict in %s" +#~ msgstr "CONFLIT (ajout/ajout) : Conflit de fusion dans %s" + +#, c-format +#~ msgid "merging of trees %s and %s failed" +#~ msgstr "échec de fusion des arbres %s et %s" + +#~ msgid "Merging:" +#~ msgstr "Fusion :" + +#, c-format +#~ msgid "found %u common ancestor:" +#~ msgid_plural "found %u common ancestors:" +#~ msgstr[0] "%u ancêtre commun trouvé :" +#~ msgstr[1] "%u ancêtres communs trouvés :" + +#~ msgid "merge returned no commit" +#~ msgstr "la fusion n'a pas retourné de commit" + +#~ msgid "cannot write incremental MIDX with bitmap" +#~ msgstr "impossible d'écrire un MIDX incrémental avec des bitmap" + #, c-format #~ msgid "Could not find remote branch %s to clone." #~ msgstr "Impossible de trouver la branche distante '%s' à cloner." @@ -24307,9 +24456,6 @@ msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : " #~ msgid "merging cannot continue; got unclean result of %d" #~ msgstr "la fusion ne peut pas continuer ; résultat non propre retourné %d" -#~ msgid "git repack []" -#~ msgstr "git repack []" - #~ msgid "--onto and --advance are incompatible" #~ msgstr "--onto et --advance sont incompatibles" diff --git a/po/ga.po b/po/ga.po new file mode 100644 index 00000000000000..c03f63756eb34b --- /dev/null +++ b/po/ga.po @@ -0,0 +1,29758 @@ +# Irish translations for Git package. +# Copyright (C) 2025 THE Git'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Git package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: Git\n" +"Report-Msgid-Bugs-To: Git Mailing List \n" +"POT-Creation-Date: 2025-05-29 09:16+0100\n" +"PO-Revision-Date: 2025-05-29 10:10+0100\n" +"Last-Translator: Aindriú Mac Giolla Eoin \n" +"Language-Team: none\n" +"Language: ga\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n" +"X-Generator: Poedit 3.4.4\n" + +#: add-interactive.c +#, c-format +msgid "Huh (%s)?" +msgstr "Huh (%s)?" + +#: add-interactive.c builtin/merge.c builtin/rebase.c reset.c sequencer.c +msgid "could not read index" +msgstr "ní raibh in ann innéacs a léamh" + +#: add-interactive.c +msgid "binary" +msgstr "dénártha" + +#: add-interactive.c +msgid "nothing" +msgstr "rud ar bith" + +#: add-interactive.c +msgid "unchanged" +msgstr "gan athrú" + +#: add-interactive.c +msgid "Update" +msgstr "Nuashonraigh" + +#: add-interactive.c +#, c-format +msgid "could not stage '%s'" +msgstr "ní fhéadfaí '%s' a chéim" + +#: add-interactive.c builtin/stash.c reset.c sequencer.c +msgid "could not write index" +msgstr "ní fhéadfadh innéacs a scríobh" + +#: add-interactive.c +#, c-format +msgid "updated %d path\n" +msgid_plural "updated %d paths\n" +msgstr[0] "nuashonraithe %d cosán\n" +msgstr[1] "nuashonraíodh %d cosán\n" +msgstr[2] "nuashonraíodh %d cosán\n" + +#: add-interactive.c +#, c-format +msgid "note: %s is untracked now.\n" +msgstr "nótaí: Tá %s dírianaithe anois.\n" + +#: add-interactive.c apply.c builtin/checkout.c builtin/reset.c +#, c-format +msgid "make_cache_entry failed for path '%s'" +msgstr "theip ar make_cache_entry le haghaidh cosán '%s'" + +#: add-interactive.c +msgid "Revert" +msgstr "Aisghabháil" + +#: add-interactive.c +msgid "Could not parse HEAD^{tree}" +msgstr "Ní raibh sé in ann HEAD ^ {tree} a pharsáil" + +#: add-interactive.c +#, c-format +msgid "reverted %d path\n" +msgid_plural "reverted %d paths\n" +msgstr[0] "cosán %d aisiompaithe\n" +msgstr[1] "%d cosán aisiompaithe\n" +msgstr[2] "%d cosán aisiompaithe\n" + +#: add-interactive.c +#, c-format +msgid "No untracked files.\n" +msgstr "Gan aon chomhaid neamhrianaithe.\n" + +#: add-interactive.c +msgid "Add untracked" +msgstr "Cuir neamh-rianaithe leis" + +#: add-interactive.c +#, c-format +msgid "added %d path\n" +msgid_plural "added %d paths\n" +msgstr[0] "cuireadh %d cosán leis\n" +msgstr[1] "%d cosán curtha leis\n" +msgstr[2] "%d cosán curtha leis\n" + +#: add-interactive.c +#, c-format +msgid "ignoring unmerged: %s" +msgstr "ag neamhaird a dhéanamh de neamhchumasctha: %s" + +#: add-interactive.c +#, c-format +msgid "Only binary files changed.\n" +msgstr "Níor athraigh ach comhaid dénártha.\n" + +#: add-interactive.c +#, c-format +msgid "No changes.\n" +msgstr "Gan aon athruithe.\n" + +#: add-interactive.c +msgid "Patch update" +msgstr "Nuashonrú paiste" + +#: add-interactive.c +msgid "Review diff" +msgstr "Athbhreithniú diff" + +#: add-interactive.c +msgid "show paths with changes" +msgstr "taispeáin cosáin le hathruithe" + +#: add-interactive.c +msgid "add working tree state to the staged set of changes" +msgstr "cuir stát crann oibre leis an tsraith athruithe céimeádta" + +#: add-interactive.c +msgid "revert staged set of changes back to the HEAD version" +msgstr "tacar athruithe céime a chur ar ais chuig an leagan HEAD" + +#: add-interactive.c +msgid "pick hunks and update selectively" +msgstr "roghnaigh hunks agus nuashonraigh go roghnach" + +#: add-interactive.c +msgid "view diff between HEAD and index" +msgstr "féach ar an difríocht idir HEAD agus innéacs" + +#: add-interactive.c +msgid "add contents of untracked files to the staged set of changes" +msgstr "cuir ábhar comhaid neamhrianaithe leis an tacar athruithe céimeádta" + +#: add-interactive.c +msgid "Prompt help:" +msgstr "Cabhair pras:" + +#: add-interactive.c +msgid "select a single item" +msgstr "roghnaigh mír amháin" + +#: add-interactive.c +msgid "select a range of items" +msgstr "roghnaigh raon earraí" + +#: add-interactive.c +msgid "select multiple ranges" +msgstr "roghnaigh raonta iomadúla" + +#: add-interactive.c +msgid "select item based on unique prefix" +msgstr "roghnaigh mír bunaithe ar réimír uathúil" + +#: add-interactive.c +msgid "unselect specified items" +msgstr "míreanna sonraithe díroghnaigh" + +#: add-interactive.c +msgid "choose all items" +msgstr "roghnaigh gach earra" + +#: add-interactive.c +msgid "(empty) finish selecting" +msgstr "(folamh) críochnaigh a roghnú" + +#: add-interactive.c +msgid "select a numbered item" +msgstr "roghnaigh mír uimhrithe" + +#: add-interactive.c +msgid "(empty) select nothing" +msgstr "(folamh) roghnaigh aon rud" + +#: add-interactive.c builtin/clean.c +msgid "*** Commands ***" +msgstr "*** Orduithe ***" + +#: add-interactive.c builtin/clean.c +msgid "What now" +msgstr "Cad anois" + +#: add-interactive.c +msgid "staged" +msgstr "stáitse" + +#: add-interactive.c +msgid "unstaged" +msgstr "gan stáitse" + +#: add-interactive.c apply.c builtin/am.c builtin/bugreport.c builtin/clone.c +#: builtin/diagnose.c builtin/fetch.c builtin/hook.c builtin/merge.c +#: builtin/pull.c builtin/submodule--helper.c +msgid "path" +msgstr "cosán" + +#: add-interactive.c +msgid "could not refresh index" +msgstr "ní fhéadfadh innéacs a athnuachan" + +#: add-interactive.c builtin/clean.c +#, c-format +msgid "Bye.\n" +msgstr "Slán..\n" + +#: add-patch.c +#, c-format +msgid "Stage mode change [y,n,q,a,d%s,?]? " +msgstr "Athrú modh stáitse [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stage deletion [y,n,q,a,d%s,?]? " +msgstr "Scriosadh céime [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stage addition [y,n,q,a,d%s,?]? " +msgstr "Breiseán céime [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stage this hunk [y,n,q,a,d%s,?]? " +msgstr "Cuir an píosa seo ar stáitse [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"staging." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh stáitsithe." + +#: add-patch.c +msgid "" +"y - stage this hunk\n" +"n - do not stage this hunk\n" +"q - quit; do not stage this hunk or any of the remaining ones\n" +"a - stage this hunk and all later hunks in the file\n" +"d - do not stage this hunk or any of the later hunks in the file\n" +msgstr "" +"y - céim an hunk seo\n" +"n - ná déan an hunk seo a chéile\n" +"q - scor; ná déan an hunk seo ná aon cheann de na cinn atá fágtha a chéile\n" +"a - céim an hunk seo agus gach hunc ina dhiaidh sin sa chomhad\n" +"d - ná déan an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad a " +"chéile\n" + +#: add-patch.c +#, c-format +msgid "Stash mode change [y,n,q,a,d%s,?]? " +msgstr "Athrú modh stash [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stash deletion [y,n,q,a,d%s,?]? " +msgstr "Scriosadh staise [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stash addition [y,n,q,a,d%s,?]? " +msgstr "Breiseán stash [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Stash this hunk [y,n,q,a,d%s,?]? " +msgstr "An bhfuil an carachtar seo [y,n,q,a,d%s,?] i bhfolach? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"stashing." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh stórála." + +#: add-patch.c +msgid "" +"y - stash this hunk\n" +"n - do not stash this hunk\n" +"q - quit; do not stash this hunk or any of the remaining ones\n" +"a - stash this hunk and all later hunks in the file\n" +"d - do not stash this hunk or any of the later hunks in the file\n" +msgstr "" +"y - stash an hunk seo\n" +"n - ná déan an hunk seo a stóráil\n" +"q - scor; ná déan an hunk seo ná aon cheann de na cinn atá fágtha a stóráil\n" +"a - stóráil an hunk seo agus gach hunk ina dhiaidh sin sa chomhad\n" +"d - ná déan an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad a " +"stóráil\n" + +#: add-patch.c +#, c-format +msgid "Unstage mode change [y,n,q,a,d%s,?]? " +msgstr "Athrú ar mhodh gan stáitse [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Unstage deletion [y,n,q,a,d%s,?]? " +msgstr "Scriosadh gan stáitse [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Unstage addition [y,n,q,a,d%s,?]? " +msgstr "Breiseán gan stáitse [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Unstage this hunk [y,n,q,a,d%s,?]? " +msgstr "Dí-stáitseáil an píosa beag seo den stáitse [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"unstaging." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh dístáisithe." + +#: add-patch.c +msgid "" +"y - unstage this hunk\n" +"n - do not unstage this hunk\n" +"q - quit; do not unstage this hunk or any of the remaining ones\n" +"a - unstage this hunk and all later hunks in the file\n" +"d - do not unstage this hunk or any of the later hunks in the file\n" +msgstr "" +"y - déan an hunk seo a dhíchur\n" +"n - ná déan an hunk seo a dhíchur\n" +"q - scor; ná déan an hunk seo nó aon cheann de na cinn atá fágtha a dhíchur\n" +"a - déan an hunk seo a dhíchur agus gach hunk ina dhiaidh sin sa chomhad\n" +"d - ná déan an hunk seo nó aon cheann de na huncanna níos déanaí sa chomhad " +"a dhíchur\n" + +#: add-patch.c +#, c-format +msgid "Apply mode change to index [y,n,q,a,d%s,?]? " +msgstr "Cuir athrú mód i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply deletion to index [y,n,q,a,d%s,?]? " +msgstr "Cuir scriosadh i bhfeidhm ar innéacs [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply addition to index [y,n,q,a,d%s,?]? " +msgstr "Cuir an breiseán i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply this hunk to index [y,n,q,a,d%s,?]? " +msgstr "Cuir an píosa seo i bhfeidhm ar innéacs [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"applying." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach le haghaidh iarratas a dhéanamh." + +#: add-patch.c +msgid "" +"y - apply this hunk to index\n" +"n - do not apply this hunk to index\n" +"q - quit; do not apply this hunk or any of the remaining ones\n" +"a - apply this hunk and all later hunks in the file\n" +"d - do not apply this hunk or any of the later hunks in the file\n" +msgstr "" +"y - cuir an hunk seo i bhfeidhm ar innéacs\n" +"n - ná cuir an hunk seo i bhfeidhm ar innéacs\n" +"q - scor; ná cuir an hunk seo ná aon cheann de na cinn atá fágtha i " +"bhfeidhm\n" +"a - cuir an hunk seo agus gach hunk níos déanaí i bhfeidhm sa chomhad\n" +"d - ná cuir an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad i " +"bhfeidhm\n" + +#: add-patch.c +#, c-format +msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? " +msgstr "Athrú modh a dhiúscairt ó chrann oibre [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? " +msgstr "An scriosadh ón gcrann oibre [y,n,q,a,d%s,?] a sheachaint? " + +#: add-patch.c +#, c-format +msgid "Discard addition from worktree [y,n,q,a,d%s,?]? " +msgstr "Scrios an breiseán ón gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? " +msgstr "" +"An bhfuil an píosa beag seo le fáil réidh ón gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"If the patch applies cleanly, the edited hunk will immediately be marked for " +"discarding." +msgstr "" +"Má chuireann an paiste i bhfeidhm go glan, déanfar an hunk eagarthóireachta " +"a mharcáil láithreach lena dhiúscairt." + +#: add-patch.c +msgid "" +"y - discard this hunk from worktree\n" +"n - do not discard this hunk from worktree\n" +"q - quit; do not discard this hunk or any of the remaining ones\n" +"a - discard this hunk and all later hunks in the file\n" +"d - do not discard this hunk or any of the later hunks in the file\n" +msgstr "" +"y - caitheamh an bonc seo ón gcrann oibre\n" +"n - ná caitheamh an hunk seo ón gcrann oibre\n" +"q - scor; ná caith an hunk seo ná aon cheann de na cinn atá fágtha\n" +"a - caith an hunk seo agus gach hunc ina dhiaidh sin sa chomhad\n" +"d - ná caith an hunk seo ná aon cheann de na huncanna níos déanaí sa " +"chomhad\n" + +#: add-patch.c +#, c-format +msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Athrú modh a dhiúscairt ó innéacs agus crann oibre [y, n, q, a, d %s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"An scriosadh ón innéacs agus ón gcrann oibre [y,n,q,a,d%s,?] a dhíbirt? " + +#: add-patch.c +#, c-format +msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? " +msgstr "Caitheamh breisiú ó innéacs agus crann oibre [y, n, q, a, d %s,?]? " + +#: add-patch.c +#, c-format +msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"An bhfuil an píosa beag seo le fáil réidh ón innéacs agus ón gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"y - discard this hunk from index and worktree\n" +"n - do not discard this hunk from index and worktree\n" +"q - quit; do not discard this hunk or any of the remaining ones\n" +"a - discard this hunk and all later hunks in the file\n" +"d - do not discard this hunk or any of the later hunks in the file\n" +msgstr "" +"y - caitheamh an hunk seo ón innéacs agus ón gcrann oibre\n" +"n - ná caith an hunk seo ón innéacs agus ón gcrann oibre\n" +"q - scor; ná caith an hunk seo ná aon cheann de na cinn atá fágtha\n" +"a - caith an hunk seo agus gach hunc ina dhiaidh sin sa chomhad\n" +"d - ná caith an hunk seo ná aon cheann de na huncanna níos déanaí sa " +"chomhad\n" + +#: add-patch.c +#, c-format +msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir athrú mód i bhfeidhm ar an innéacs agus ar an gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir scriosadh i bhfeidhm ar innéacs agus crann oibre [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir an breiseán i bhfeidhm ar an innéacs agus ar an gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? " +msgstr "" +"Cuir an píosa seo i bhfeidhm ar an innéacs agus ar an gcrann oibre " +"[y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"y - apply this hunk to index and worktree\n" +"n - do not apply this hunk to index and worktree\n" +"q - quit; do not apply this hunk or any of the remaining ones\n" +"a - apply this hunk and all later hunks in the file\n" +"d - do not apply this hunk or any of the later hunks in the file\n" +msgstr "" +"y - cuir an hunk seo i bhfeidhm ar innéacs agus ar chrann oibre\n" +"n - ná cuir an hunk seo i bhfeidhm ar innéacs agus crann oibre\n" +"q - scor; ná cuir an hunk seo ná aon cheann de na cinn atá fágtha i " +"bhfeidhm\n" +"a - cuir an hunk seo agus gach hunk níos déanaí i bhfeidhm sa chomhad\n" +"d - ná cuir an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad i " +"bhfeidhm\n" + +#: add-patch.c +#, c-format +msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir athrú mód i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir scriosadh i bhfeidhm ar chrann oibre [y, n, q, a, d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply addition to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir an breiseán i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +#, c-format +msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? " +msgstr "Cuir an píosa seo i bhfeidhm ar an gcrann oibre [y,n,q,a,d%s,?]? " + +#: add-patch.c +msgid "" +"y - apply this hunk to worktree\n" +"n - do not apply this hunk to worktree\n" +"q - quit; do not apply this hunk or any of the remaining ones\n" +"a - apply this hunk and all later hunks in the file\n" +"d - do not apply this hunk or any of the later hunks in the file\n" +msgstr "" +"y - cuir an hunk seo i bhfeidhm ar chrann oibre\n" +"n - ná cuir an hunk seo i bhfeidhm ar chrann oibre\n" +"q - scor; ná cuir an hunk seo ná aon cheann de na cinn atá fágtha i " +"bhfeidhm\n" +"a - cuir an hunk seo agus gach hunk níos déanaí i bhfeidhm sa chomhad\n" +"d - ná cuir an hunk seo ná aon cheann de na hunks níos déanaí sa chomhad i " +"bhfeidhm\n" + +#: add-patch.c +#, c-format +msgid "could not parse hunk header '%.*s'" +msgstr "níorbh fhéidir ceanntásc an bhlúire '%.*s' a pharsáil" + +#: add-patch.c +msgid "could not parse diff" +msgstr "ní raibh sé in ann difríocht a pharsáil" + +#: add-patch.c +msgid "could not parse colored diff" +msgstr "ní raibh sé in ann difríocht daite a pháirseáil" + +#: add-patch.c +#, c-format +msgid "failed to run '%s'" +msgstr "theip ar '%s' a reáchtáil" + +#: add-patch.c +msgid "mismatched output from interactive.diffFilter" +msgstr "aschur mí-mheaitseáilte ó interactive.diffFilter" + +#: add-patch.c +msgid "" +"Your filter must maintain a one-to-one correspondence\n" +"between its input and output lines." +msgstr "" +"Caithfidh do scagaire comhfhreagras duine le duine a choinneáil\n" +"idir a línte ionchuir agus aschuir." + +#: add-patch.c +#, c-format +msgid "" +"expected context line #%d in\n" +"%.*s" +msgstr "" +"líne comhthéacs a bhfuil súil leo #%d i\n" +"%.*s" + +#: add-patch.c +#, c-format +msgid "" +"hunks do not overlap:\n" +"%.*s\n" +"\tdoes not end with:\n" +"%.*s" +msgstr "" +"ní fhorluíonn hunks:\n" +"%.*s\n" +" ní chríochnaíonn sé le:\n" +"%.*s" + +#: add-patch.c +msgid "Manual hunk edit mode -- see bottom for a quick guide.\n" +msgstr "" +"Modh eagarthóireachta hunk láimhe - féach an bun le haghaidh treoir thapa.\n" + +#: add-patch.c +#, c-format +msgid "" +"---\n" +"To remove '%c' lines, make them ' ' lines (context).\n" +"To remove '%c' lines, delete them.\n" +"Lines starting with %s will be removed.\n" +msgstr "" +"---\n" +"Chun línte '%c' a bhaint, déan línte '' iad (comhthéacs).\n" +"Chun línte '%c' a bhaint, scrios iad.\n" +"Bainfear línte a thosaíonn le %s.\n" + +#: add-patch.c +msgid "" +"If it does not apply cleanly, you will be given an opportunity to\n" +"edit again. If all lines of the hunk are removed, then the edit is\n" +"aborted and the hunk is left unchanged.\n" +msgstr "" +"Mura bhfuil feidhm aige go glan, tabharfar deis duit\n" +"cuir in eagar arís. Má bhaintear gach líne den hunk, ansin is é an t-" +"eagarthóireacht\n" +"cuireadh isteach agus fágtar an hunk gan athrú.\n" + +#: add-patch.c +msgid "could not parse hunk header" +msgstr "ní fhéadfaí ceanntásc hunk a pháirseáil" + +#: add-patch.c +msgid "'git apply --cached' failed" +msgstr "Theip ar 'git apply --cached'" + +#. TRANSLATORS: do not translate [y/n] +#. The program will only accept that input at this point. +#. Consider translating (saying "no" discards!) as +#. (saying "n" for "no" discards!) if the translation +#. of the word "no" does not start with n. +#. +#: add-patch.c +msgid "" +"Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? " +msgstr "" +"Ní bhaineann do chuid eagraithe. Cuir in eagar arís (ag rá \"níl\" cuirtear " +"i leataobh é!) [y/n]? " + +#: add-patch.c +msgid "The selected hunks do not apply to the index!" +msgstr "Ní bhaineann na hunks roghnaithe leis an innéacs!" + +#: add-patch.c +msgid "Apply them to the worktree anyway? " +msgstr "An gcuirfidh tú i bhfeidhm iad ar an gcrann oibre ar aon nós? " + +#: add-patch.c +msgid "Nothing was applied.\n" +msgstr "Ní chuirtear aon rud i bhfeidhm.\n" + +#: add-patch.c +msgid "" +"j - leave this hunk undecided, see next undecided hunk\n" +"J - leave this hunk undecided, see next hunk\n" +"k - leave this hunk undecided, see previous undecided hunk\n" +"K - leave this hunk undecided, see previous hunk\n" +"g - select a hunk to go to\n" +"/ - search for a hunk matching the given regex\n" +"s - split the current hunk into smaller hunks\n" +"e - manually edit the current hunk\n" +"p - print the current hunk, 'P' to use the pager\n" +"? - print help\n" +msgstr "" +"j - fág an hunk seo gan chinneadh, féach an chéad hunk neamhchinnte eile\n" +"J - fág an hunk seo gan chinneadh, féach an chéad hunk eile\n" +"k - fág an hunk seo gan chinneadh, féach an hunk neamhchinnte roimhe seo\n" +"K - fág an hunk seo gan chinneadh, féach an hunk roimhe seo\n" +"g - roghnaigh hunk le dul chuig\n" +"/- cuardaigh hunk a mheaitseann leis an regex a thugtar\n" +"s - roinn an hunk reatha ina huncanna níos lú\n" +"e - cuir an hunk reatha in eagar de láimh\n" +"p - priontáil an hunk reatha, 'P' chun an pager a úsáid\n" +"? - cabhair priontála\n" + +#: add-patch.c +#, c-format +msgid "Only one letter is expected, got '%s'" +msgstr "Níl súil leis ach litir amháin, fuair '%s'" + +#: add-patch.c +msgid "No previous hunk" +msgstr "Níl aon hunk roimhe seo" + +#: add-patch.c +msgid "No next hunk" +msgstr "Níl aon chéad hunk eile" + +#: add-patch.c +msgid "No other hunks to goto" +msgstr "Níl aon ghuncanna eile le dul" + +#: add-patch.c +msgid "go to which hunk ( to see more)? " +msgstr "téigh chuig cén hunk ( le tuilleadh a fheiceáil)? " + +#: add-patch.c +msgid "go to which hunk? " +msgstr "téigh chuig cén hunk? " + +#: add-patch.c +#, c-format +msgid "Invalid number: '%s'" +msgstr "Uimhir neamhbhailí: '%s'" + +#: add-patch.c +#, c-format +msgid "Sorry, only %d hunk available." +msgid_plural "Sorry, only %d hunks available." +msgstr[0] "Tá brón orm, níl ach %d píosa ar fáil." +msgstr[1] "Tá brón orm, níl ach %d hunks ar fáil." +msgstr[2] "Tá brón orm, níl ach %d hunks ar fáil." + +#: add-patch.c +msgid "No other hunks to search" +msgstr "Níl aon ghuncanna eile le cuardach" + +#: add-patch.c +msgid "search for regex? " +msgstr "cuardach a dhéanamh ar regex? " + +#: add-patch.c +#, c-format +msgid "Malformed search regexp %s: %s" +msgstr "Regexp cuardaigh mífheidhmithe %s: %s" + +#: add-patch.c +msgid "No hunk matches the given pattern" +msgstr "Níl aon hunk ag teacht leis an bpatrún tugtha" + +#: add-patch.c +msgid "Sorry, cannot split this hunk" +msgstr "Tá brón orainn, ní féidir an hunk seo a roinnt" + +#: add-patch.c +#, c-format +msgid "Split into %d hunks." +msgstr "Roinn ina %d hunks." + +#: add-patch.c +msgid "Sorry, cannot edit this hunk" +msgstr "Tá brón orainn, ní féidir an hunk seo a chur in eagar" + +#: add-patch.c +#, c-format +msgid "Unknown command '%s' (use '?' for help)" +msgstr "Ordú anaithnid '%s' (bain úsáid as '?' le haghaidh cabhair)" + +#: add-patch.c +msgid "'git apply' failed" +msgstr "Theip ar 'git apply'" + +#: add-patch.c +msgid "No changes." +msgstr "Gan aon athruithe." + +#: add-patch.c +msgid "Only binary files changed." +msgstr "Níor athraigh ach comhaid dénártha." + +#: advice.c +#, c-format +msgid "" +"\n" +"Disable this message with \"git config set advice.%s false\"" +msgstr "" +"\n" +"Díchumasaigh an teachtaireacht seo le \"git config set advice.%s false\"" + +#: advice.c +#, c-format +msgid "%shint:%s%.*s%s\n" +msgstr "%sleid:%s%.*s%s\n" + +#: advice.c +msgid "Cherry-picking is not possible because you have unmerged files." +msgstr "" +"Ní féidir piocadh silíní toisc go bhfuil comhaid neamh-chumasaithe agat." + +#: advice.c +msgid "Committing is not possible because you have unmerged files." +msgstr "" +"Ní féidir tiomantas a dhéanamh toisc go bhfuil comhaid neamh-" +"chomhcheangailte agat." + +#: advice.c +msgid "Merging is not possible because you have unmerged files." +msgstr "" +"Ní féidir cumasc a dhéanamh toisc go bhfuil comhaid neamh-chumasaithe agat." + +#: advice.c +msgid "Pulling is not possible because you have unmerged files." +msgstr "" +"Ní féidir tarraingt a tharraingt toisc go bhfuil comhaid neamh-chumasaithe " +"agat." + +#: advice.c +msgid "Reverting is not possible because you have unmerged files." +msgstr "" +"Ní féidir aisiompú toisc go bhfuil comhaid neamh-chomhcheangailte agat." + +#: advice.c +msgid "Rebasing is not possible because you have unmerged files." +msgstr "" +"Ní féidir athbhunú a dhéanamh toisc go bhfuil comhaid neamh-chumasaithe agat." + +#: advice.c +msgid "" +"Fix them up in the work tree, and then use 'git add/rm '\n" +"as appropriate to mark resolution and make a commit." +msgstr "" +"Socraigh iad sa chrann oibre, agus ansin bain úsáid as 'git add/rm '\n" +"de réir mar is cuí chun réiteach a mharcáil agus tiomantas a dhéanamh." + +#: advice.c +msgid "Exiting because of an unresolved conflict." +msgstr "Ag imeacht mar gheall ar choimhlint neamhréitithe." + +#: advice.c builtin/merge.c +msgid "You have not concluded your merge (MERGE_HEAD exists)." +msgstr "Níor thug tú do chumasc i gcrích (MERGE_HEAD ann)." + +#: advice.c +msgid "Please, commit your changes before merging." +msgstr "Déan d'athruithe a dhéanamh le do thoil sula ndéanann tú cumasc." + +#: advice.c +msgid "Exiting because of unfinished merge." +msgstr "Ag imeacht mar gheall ar chumasc críochnaithe." + +#: advice.c +msgid "" +"Diverging branches can't be fast-forwarded, you need to either:\n" +"\n" +"\tgit merge --no-ff\n" +"\n" +"or:\n" +"\n" +"\tgit rebase\n" +msgstr "" +"Ní féidir brainsí éagsúla a chur ar aghaidh go tapa, ní mór duit:\n" +"\n" +" git merge --no-ff\n" +"\n" +"nó:\n" +"\n" +" git rebase\n" + +#: advice.c +msgid "Not possible to fast-forward, aborting." +msgstr "Ní féidir dul ar aghaidh go tapa, ag cur isteach." + +#: advice.c +#, c-format +msgid "" +"The following paths and/or pathspecs matched paths that exist\n" +"outside of your sparse-checkout definition, so will not be\n" +"updated in the index:\n" +msgstr "" +"Meaitseáil na cosáin agus/nó na cosáin seo a leanas cosáin ann\n" +"lasmuigh de do shainmhíniú seiceála neamhchoitianta, mar sin ní bheidh\n" +"nuashonraithe san innéacs:\n" + +#: advice.c +msgid "" +"If you intend to update such entries, try one of the following:\n" +"* Use the --sparse option.\n" +"* Disable or modify the sparsity rules." +msgstr "" +"Má tá sé ar intinn agat iontrálacha den sórt sin a nuashonrú, bain triail as " +"ceann amháin de\n" +"* Úsáid an rogha --sparse.\n" +"* Díchumasaigh nó modhnaigh na rialacha neamhghnách." + +#: advice.c +#, c-format +msgid "" +"Note: switching to '%s'.\n" +"\n" +"You are in 'detached HEAD' state. You can look around, make experimental\n" +"changes and commit them, and you can discard any commits you make in this\n" +"state without impacting any branches by switching back to a branch.\n" +"\n" +"If you want to create a new branch to retain commits you create, you may\n" +"do so (now or later) by using -c with the switch command. Example:\n" +"\n" +" git switch -c \n" +"\n" +"Or undo this operation with:\n" +"\n" +" git switch -\n" +"\n" +"Turn off this advice by setting config variable advice.detachedHead to " +"false\n" +"\n" +msgstr "" +"Nóta: ag aistriú go '%s'.\n" +"\n" +"Tá tú i stát 'CEANN scoite'. Is féidir leat breathnú timpeall, turgnamhach a " +"dhéanamh\n" +"athruithe agus iad a dhéanamh, agus féadfaidh tú aon gealltanais a dhéanann " +"tú san áireamh a dhiúscairt\n" +"stáit gan dul i bhfeidhm ar aon bhrainsí trí aistriú ar ais chuig brainse.\n" +"\n" +"Más mian leat brainse nua a chruthú chun gealltanais a chruthaíonn tú a " +"choinneáil, féadfaidh tú\n" +"déan amhlaidh (anois nó níos déanaí) trí úsáid a bhaint as -c leis an ordú " +"lasc. Sampla:\n" +"\n" +" git switch -c \n" +"\n" +"Nó cealaigh an oibríocht seo le:\n" +"\n" +" git switch -c \n" +"\n" +"Múch an chomhairle seo trí chomhairle athróg advice.detachedHead a shocrú go " +"false\n" +"\n" + +#: advice.c +#, c-format +msgid "" +"The following paths have been moved outside the\n" +"sparse-checkout definition but are not sparse due to local\n" +"modifications.\n" +msgstr "" +"Tá na cosáin seo a leanas bogadh taobh amuigh den\n" +"sainmhíniú seiceála neamhchoitianta ach níl siad neamhchoitiúil mar gheall " +"ar an\n" +"modhnuithe.\n" + +#: advice.c +msgid "" +"To correct the sparsity of these paths, do the following:\n" +"* Use \"git add --sparse \" to update the index\n" +"* Use \"git sparse-checkout reapply\" to apply the sparsity rules" +msgstr "" +"Chun neamhghnáth na gcosáin seo a cheartú, déan an méid seo a leanas:\n" +"* Úsáid “git add --sparse\" chun an t-innéacs a nuashonrú\n" +"* Úsáid “git sparse-checkout reapply” chun na rialacha neamhchoitianta a " +"chur i bhfeidhm" + +#: alias.c +msgid "cmdline ends with \\" +msgstr "críochnaíonn cmdline le \\" + +#: alias.c +msgid "unclosed quote" +msgstr "luachan neamhdhúnadh" + +#: alias.c builtin/cat-file.c builtin/notes.c builtin/prune-packed.c +#: builtin/receive-pack.c builtin/refs.c builtin/tag.c t/helper/test-pkt-line.c +msgid "too many arguments" +msgstr "an iomarca argóintí" + +#: apply.c +#, c-format +msgid "unrecognized whitespace option '%s'" +msgstr "rogha spás bán gan aithint '%s'" + +#: apply.c +#, c-format +msgid "unrecognized whitespace ignore option '%s'" +msgstr "neamhaird ar spás bán gan aithint neamhaird ar rogha '%s'" + +#: apply.c archive.c builtin/add.c builtin/branch.c builtin/checkout-index.c +#: builtin/checkout.c builtin/clean.c builtin/clone.c builtin/commit.c +#: builtin/describe.c builtin/diff-tree.c builtin/difftool.c +#: builtin/fast-export.c builtin/fetch.c builtin/help.c builtin/index-pack.c +#: builtin/init-db.c builtin/log.c builtin/ls-files.c builtin/merge-base.c +#: builtin/merge-tree.c builtin/merge.c builtin/pack-objects.c builtin/rebase.c +#: builtin/repack.c builtin/replay.c builtin/reset.c builtin/rev-parse.c +#: builtin/show-branch.c builtin/stash.c builtin/submodule--helper.c +#: builtin/tag.c builtin/worktree.c parse-options.c range-diff.c revision.c +#, c-format +msgid "options '%s' and '%s' cannot be used together" +msgstr "ní féidir roghanna '%s' agus '%s' a úsáid le chéile" + +#: apply.c +#, c-format +msgid "'%s' outside a repository" +msgstr "'%s' lasmuigh de stór" + +#: apply.c +msgid "failed to read patch" +msgstr "theip ar phaiste a léamh" + +#: apply.c +msgid "patch too large" +msgstr "paiste ró-mhór" + +#: apply.c +#, c-format +msgid "Cannot prepare timestamp regexp %s" +msgstr "Ní féidir regexp %s aimstampa a ullmhú" + +#: apply.c +#, c-format +msgid "regexec returned %d for input: %s" +msgstr "d'fhill regexec %d le haghaidh ionchur: %s" + +#: apply.c +#, c-format +msgid "unable to find filename in patch at line %d" +msgstr "ní féidir ainm comhaid a aimsiú i bpaiste ag an líne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d" +msgstr "git apply: bad git-diff - ag súil le /dev/null, fuair %s ar líne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - inconsistent new filename on line %d" +msgstr "" +"git apply: bad git-diff - ainm comhaid nua neamhchomhsheasmhach ar líne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - inconsistent old filename on line %d" +msgstr "git apply: bad git-diff - sean-ainm comhaid neamhréireach ar líne %d" + +#: apply.c +#, c-format +msgid "git apply: bad git-diff - expected /dev/null on line %d" +msgstr "git apply: bad git-diff - súil leis /dev/null ar líne %d" + +#: apply.c +#, c-format +msgid "invalid mode on line %d: %s" +msgstr "modh neamhbhailí ar líne %d: %s" + +#: apply.c +#, c-format +msgid "inconsistent header lines %d and %d" +msgstr "línte ceanntásc neamhchomhsheasmhach %d agus %d" + +#: apply.c +#, c-format +msgid "" +"git diff header lacks filename information when removing %d leading pathname " +"component (line %d)" +msgid_plural "" +"git diff header lacks filename information when removing %d leading pathname " +"components (line %d)" +msgstr[0] "" +"tá easpa eolais ainm comhaid ar cheanntásc git diff nuair a bhaintear %d " +"comhpháirt ainm cosáin tosaigh (líne %d)" +msgstr[1] "" +"tá easpa eolais ainm comhaid ar cheanntásc git diff agus %d comhpháirteanna " +"ainm cosáin tosaigh á mbaint (líne %d)" +msgstr[2] "" +"tá easpa eolais ainm comhaid ar cheanntásc git diff agus %d comhpháirteanna " +"ainm cosáin tosaigh á mbaint (líne %d)" + +#: apply.c +#, c-format +msgid "git diff header lacks filename information (line %d)" +msgstr "tá easpa eolais ainm comhaid ar cheanntásc git diff (líne %d)" + +#: apply.c +#, c-format +msgid "recount: unexpected line: %.*s" +msgstr "atháireamh: líne gan choinne: %.*s" + +#: apply.c +#, c-format +msgid "patch fragment without header at line %d: %.*s" +msgstr "blúirt paiste gan ceanntásc ag an líne %d: %.*s" + +#: apply.c +msgid "new file depends on old contents" +msgstr "braitheann comhad nua ar shean-ábhar" + +#: apply.c +msgid "deleted file still has contents" +msgstr "tá ábhar fós ag comhad scriosta" + +#: apply.c +#, c-format +msgid "corrupt patch at line %d" +msgstr "paiste truaillithe ag líne %d" + +#: apply.c +#, c-format +msgid "new file %s depends on old contents" +msgstr "braitheann an comhad nua %s ar an seanábhar" + +#: apply.c +#, c-format +msgid "deleted file %s still has contents" +msgstr "tá ábhar fós ag comhad scriosta %s" + +#: apply.c +#, c-format +msgid "** warning: file %s becomes empty but is not deleted" +msgstr "** rabhadh: éiríonn comhad %s folamh ach ní scriostar é" + +#: apply.c +#, c-format +msgid "corrupt binary patch at line %d: %.*s" +msgstr "paiste dénártha truaillithe ag líne %d: %.*s" + +#: apply.c +#, c-format +msgid "unrecognized binary patch at line %d" +msgstr "paiste dénártha gan aithint ag an líne %d" + +#: apply.c +#, c-format +msgid "patch with only garbage at line %d" +msgstr "paiste gan ach truflais ag an líne %d" + +#: apply.c +#, c-format +msgid "unable to read symlink %s" +msgstr "nach féidir nasc simtéarach %s a léamh" + +#: apply.c +#, c-format +msgid "unable to open or read %s" +msgstr "nach féidir %s a oscailt nó a léamh" + +#: apply.c +#, c-format +msgid "invalid start of line: '%c'" +msgstr "tús neamhbhailí na líne: '%c'" + +#: apply.c +#, c-format +msgid "Hunk #%d succeeded at %d (offset %d line)." +msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." +msgstr[0] "D'éirigh le hunk #%d ag %d (líne fhritháireamh %d)." +msgstr[1] "D'éirigh le hunk #%d ag %d (%d líne curtha as feidhm)." +msgstr[2] "D'éirigh le hunk #%d ag %d (%d líne curtha as feidhm)." + +#: apply.c +#, c-format +msgid "Context reduced to (%ld/%ld) to apply fragment at %d" +msgstr "Laghdaithe comhthéacs go (%ld/%ld) chun blúire a chur i bhfeidhm ag %d" + +#: apply.c +#, c-format +msgid "" +"while searching for:\n" +"%.*s" +msgstr "" +"agus tú ag cuardach:\n" +"%.*s" + +#: apply.c +#, c-format +msgid "missing binary patch data for '%s'" +msgstr "sonraí paiste dénártha in easnamh do '%s'" + +#: apply.c +#, c-format +msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'" +msgstr "" +"ní féidir paiste dénártha a chur i bhfeidhm ar ais gan an hunk droim ar ais " +"chuig '%s'" + +#: apply.c +#, c-format +msgid "cannot apply binary patch to '%s' without full index line" +msgstr "" +"ní féidir paiste dénártha a chur i bhfeidhm ar '%s' gan líne innéacs iomlán" + +#: apply.c +#, c-format +msgid "" +"the patch applies to '%s' (%s), which does not match the current contents." +msgstr "" +"baineann an paiste le '%s' (%s), nach bhfuil comhoiriúnach leis an ábhar " +"reatha." + +#: apply.c +#, c-format +msgid "the patch applies to an empty '%s' but it is not empty" +msgstr "baineann an paiste le '%s' folamh ach níl sé folamh" + +#: apply.c +#, c-format +msgid "the necessary postimage %s for '%s' cannot be read" +msgstr "ní féidir an post riachtanach %s le haghaidh '%s' a léamh" + +#: apply.c +#, c-format +msgid "binary patch does not apply to '%s'" +msgstr "ní bhaineann paiste dénártha le '%s'" + +#: apply.c +#, c-format +msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" +msgstr "" +"cruthaíonn paiste dénártha chuig '%s' toradh mícheart (ag súil le %s, fuair " +"%s)" + +#: apply.c +#, c-format +msgid "patch failed: %s:%ld" +msgstr "theip ar phaiste: %s: %ld" + +#: apply.c builtin/mv.c +#, c-format +msgid "cannot checkout %s" +msgstr "ní féidir %s a sheiceáil" + +#: apply.c midx.c pack-mtimes.c pack-revindex.c setup.c +#, c-format +msgid "failed to read %s" +msgstr "theip ar %s a léamh" + +#: apply.c +#, c-format +msgid "reading from '%s' beyond a symbolic link" +msgstr "léamh ó '%s' níos faide ná nasc siombalach" + +#: apply.c +#, c-format +msgid "path %s has been renamed/deleted" +msgstr "tá conair %s athainmnithe/scriosta" + +#: apply.c +#, c-format +msgid "%s: does not exist in index" +msgstr "%s: níl ann san innéacs" + +#: apply.c +#, c-format +msgid "%s: does not match index" +msgstr "%s: ní mheaitseálann innéacs" + +#: apply.c +msgid "repository lacks the necessary blob to perform 3-way merge." +msgstr "níl an blob riachtanach ag stór chun cumasc trí bhealach a dhéanamh." + +#: apply.c +#, c-format +msgid "Performing three-way merge...\n" +msgstr "Cumaisc trí bhealach a dhéanamh...\n" + +#: apply.c +#, c-format +msgid "cannot read the current contents of '%s'" +msgstr "ní féidir ábhar reatha '%s' a léamh" + +#: apply.c +#, c-format +msgid "Failed to perform three-way merge...\n" +msgstr "Theip ar chumasc trí bhealach a dhéanamh...\n" + +#: apply.c +#, c-format +msgid "Applied patch to '%s' with conflicts.\n" +msgstr "Paiste cuireadh i bhfeidhm ar '%s' le coinbhleachtaí.\n" + +#: apply.c +#, c-format +msgid "Applied patch to '%s' cleanly.\n" +msgstr "Cuireadh paiste i bhfeidhm go '%s' go glan.\n" + +#: apply.c +#, c-format +msgid "Falling back to direct application...\n" +msgstr "Ag titim ar ais chuig feidhmchlár díreach...\n" + +#: apply.c +msgid "removal patch leaves file contents" +msgstr "fágann paiste bainte ábhar an chomhaid" + +#: apply.c +#, c-format +msgid "%s: wrong type" +msgstr "%s: cineál mícheart" + +#: apply.c +#, c-format +msgid "%s has type %o, expected %o" +msgstr "%s tá cineál %o air, ach bhíothas ag súil le %o" + +#: apply.c read-cache.c +#, c-format +msgid "invalid path '%s'" +msgstr "cosán neamhbhailí '%s'" + +#: apply.c +#, c-format +msgid "%s: already exists in index" +msgstr "%s: ann cheana féin san innéacs" + +#: apply.c +#, c-format +msgid "%s: already exists in working directory" +msgstr "%s: ann cheana féin san eolaire oibre" + +#: apply.c +#, c-format +msgid "new mode (%o) of %s does not match old mode (%o)" +msgstr "ní mheaitseálann modh nua (%o) de %s sean-mhodh (%o)" + +#: apply.c +#, c-format +msgid "new mode (%o) of %s does not match old mode (%o) of %s" +msgstr "ní mheaitseálann modh nua (%o) de %s sean-mhodh (%o) de %s" + +#: apply.c +#, c-format +msgid "affected file '%s' is beyond a symbolic link" +msgstr "tá an comhad tionchair '%s' níos faide ná nasc siombalach" + +#: apply.c +#, c-format +msgid "%s: patch does not apply" +msgstr "%s: níl paiste i bhfeidhm" + +#: apply.c +#, c-format +msgid "Checking patch %s..." +msgstr "Seiceáil paiste %s..." + +#: apply.c +#, c-format +msgid "sha1 information is lacking or useless for submodule %s" +msgstr "tá faisnéis sha1 easpa nó gan úsáid le haghaidh fo-mhodúl %s" + +#: apply.c +#, c-format +msgid "mode change for %s, which is not in current HEAD" +msgstr "athrú modh do %s, nach bhfuil i HEAD reatha" + +#: apply.c +#, c-format +msgid "sha1 information is lacking or useless (%s)." +msgstr "tá faisnéis sha1 easpa nó gan úsáid (%s)." + +#: apply.c +#, c-format +msgid "could not add %s to temporary index" +msgstr "ní fhéadfaí %s a chur le hinnéacs sealadach" + +#: apply.c +#, c-format +msgid "could not write temporary index to %s" +msgstr "ní fhéadfaí innéacs sealadach a scríobh chuig %s" + +#: apply.c +#, c-format +msgid "unable to remove %s from index" +msgstr "nach féidir %s a bhaint as innéacs" + +#: apply.c +#, c-format +msgid "corrupt patch for submodule %s" +msgstr "paiste truaillithe do fho-mhodúl %s" + +#: apply.c +#, c-format +msgid "unable to stat newly created file '%s'" +msgstr "nach féidir an comhad nua-chruthaithe '%s' a stáil" + +#: apply.c +#, c-format +msgid "unable to create backing store for newly created file %s" +msgstr "nach féidir stór tacaíochta a chruthú do chomhad nua-chruthaithe %s" + +#: apply.c +#, c-format +msgid "unable to add cache entry for %s" +msgstr "nach féidir iontráil taisce a chur le haghaidh %s" + +#: apply.c builtin/bisect.c builtin/gc.c +#, c-format +msgid "failed to write to '%s'" +msgstr "theip ar scríobh chuig '%s'" + +#: apply.c +#, c-format +msgid "closing file '%s'" +msgstr "comhad dúnadh '%s'" + +#: apply.c +#, c-format +msgid "unable to write file '%s' mode %o" +msgstr "ní féidir an comhad '%s' modh %o a scríobh" + +#: apply.c +#, c-format +msgid "Applied patch %s cleanly." +msgstr "Cuireadh paiste %s i bhfeidhm go glan." + +#: apply.c +msgid "internal error" +msgstr "earráid inmheánach" + +#: apply.c +#, c-format +msgid "Applying patch %%s with %d reject..." +msgid_plural "Applying patch %%s with %d rejects..." +msgstr[0] "Ag cur paiste %%s i bhfeidhm le %d diúltú..." +msgstr[1] "Ag cur paiste %%s i bhfeidhm le %d diúltuithe..." +msgstr[2] "Ag cur paiste %%s i bhfeidhm le %d diúltuithe..." + +#: apply.c +#, c-format +msgid "cannot open %s" +msgstr "ní féidir %s a oscailt" + +#: apply.c rerere.c +#, c-format +msgid "cannot unlink '%s'" +msgstr "ní féidir '%s' a dhínascadh" + +#: apply.c +#, c-format +msgid "Hunk #%d applied cleanly." +msgstr "Cuireadh Hunk #%d i bhfeidhm go glan." + +#: apply.c +#, c-format +msgid "Rejected hunk #%d." +msgstr "Hunk diúltaithe #%d." + +#: apply.c +#, c-format +msgid "Skipped patch '%s'." +msgstr "Paiste scipeáilte '%s'." + +#: apply.c +msgid "No valid patches in input (allow with \"--allow-empty\")" +msgstr "Níl aon paistí bailí san ionchur (cead le “--allow-empty”)" + +#: apply.c t/helper/test-cache-tree.c +msgid "unable to read index file" +msgstr "in ann comhad innéacs a léamh" + +#: apply.c +#, c-format +msgid "can't open patch '%s': %s" +msgstr "ní féidir paiste '%s' a oscailt: %s" + +#: apply.c +#, c-format +msgid "squelched %d whitespace error" +msgid_plural "squelched %d whitespace errors" +msgstr[0] "earráid spás bán %d múchta" +msgstr[1] "%d earráid spás bán múchta" +msgstr[2] "%d earráid spás bán múchta" + +#: apply.c +#, c-format +msgid "%d line adds whitespace errors." +msgid_plural "%d lines add whitespace errors." +msgstr[0] "Cuireann %d líne earráidí spás bán leis." +msgstr[1] "Cuireann %d líne earráidí spás bán leis." +msgstr[2] "Cuireann %d líne earráidí spás bán leis." + +#: apply.c +#, c-format +msgid "%d line applied after fixing whitespace errors." +msgid_plural "%d lines applied after fixing whitespace errors." +msgstr[0] "%d líne curtha i bhfeidhm tar éis earráidí spás bán a shocrú." +msgstr[1] "%d líne curtha i bhfeidhm tar éis earráidí spás bán a shocrú." +msgstr[2] "%d líne curtha i bhfeidhm tar éis earráidí spás bán a shocrú." + +#: apply.c builtin/mv.c builtin/rm.c +msgid "Unable to write new index file" +msgstr "Ní féidir comhad innéacs nua a scríobh" + +#: apply.c +msgid "don't apply changes matching the given path" +msgstr "ná cuir athruithe a mheaitseáil leis an gcosán tugtha" + +#: apply.c +msgid "apply changes matching the given path" +msgstr "athruithe a chur i bhfeidhm a mheaitseálann" + +#: apply.c builtin/am.c +msgid "num" +msgstr "uimhir" + +#: apply.c +msgid "remove leading slashes from traditional diff paths" +msgstr "bain slascanna ceannródaíocha ó chosáin difriúla traidisiúnta" + +#: apply.c +msgid "ignore additions made by the patch" +msgstr "neamhaird a dhéanamh ar bhreiseanna a dhéanann an" + +#: apply.c +msgid "instead of applying the patch, output diffstat for the input" +msgstr "in ionad an paiste a chur i bhfeidhm, diffstat aschuir don ionchur" + +#: apply.c +msgid "show number of added and deleted lines in decimal notation" +msgstr "líon na línte breise agus scriosta a thaispeáint i nótaí deachúil" + +#: apply.c +msgid "instead of applying the patch, output a summary for the input" +msgstr "in ionad an paiste a chur i bhfeidhm, aschur achoimre don ionchur" + +#: apply.c +msgid "instead of applying the patch, see if the patch is applicable" +msgstr "" +"in ionad an paiste a chur i bhfeidhm, féach an bhfuil an paiste infheidhme" + +#: apply.c +msgid "make sure the patch is applicable to the current index" +msgstr "" +"déan cinnte go bhfuil an paiste infheidhme maidir leis an innéacs reatha" + +#: apply.c +msgid "mark new files with `git add --intent-to-add`" +msgstr "comhad nua a mharcáil le `git add --intent-to-add`" + +#: apply.c +msgid "apply a patch without touching the working tree" +msgstr "cuir paiste i bhfeidhm gan teagmháil leis an gcrann oibre" + +#: apply.c +msgid "accept a patch that touches outside the working area" +msgstr "glacadh le paiste a théann lasmuigh den limistéar oibre" + +#: apply.c +msgid "also apply the patch (use with --stat/--summary/--check)" +msgstr "" +"cuir an paiste i bhfeidhm freisin (bain úsáid le --stat/--summary/--check)" + +#: apply.c +msgid "attempt three-way merge, fall back on normal patch if that fails" +msgstr "" +"iarracht a dhéanamh cumasc trí bhealach, titim ar ais ar ghnáthphaiste má " +"theipeann" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use our version" +msgstr "le haghaidh coimhlintí, bain úsáid as ár leagan" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use their version" +msgstr "le haghaidh coimhlintí, bain úsáid as a leagan" + +#: apply.c builtin/merge-file.c +msgid "for conflicts, use a union version" +msgstr "le haghaidh coimhlintí, bain úsáid as leagan aontais" + +#: apply.c +msgid "build a temporary index based on embedded index information" +msgstr "innéacs sealadach a thógáil bunaithe ar eolas innéacs leabaithe" + +#: apply.c builtin/checkout-index.c +msgid "paths are separated with NUL character" +msgstr "tá cosáin scartha le carachtar NUL" + +#: apply.c +msgid "ensure at least lines of context match" +msgstr "a chinntiú go mbe adh línte comhthéacsa" + +#: apply.c builtin/am.c builtin/interpret-trailers.c builtin/pack-objects.c +#: builtin/rebase.c +msgid "action" +msgstr "gníomh" + +#: apply.c +msgid "detect new or modified lines that have whitespace errors" +msgstr "línte nua nó modhnaithe a bhrath a bhfuil earráidí spás bán acu" + +#: apply.c +msgid "ignore changes in whitespace when finding context" +msgstr "neamhaird a dhéanamh ar athruithe ar spás bán agus comhthéacs á" + +#: apply.c +msgid "apply the patch in reverse" +msgstr "cuir an paiste i bhfeidhm ar ais" + +#: apply.c +msgid "don't expect at least one line of context" +msgstr "ná bí ag súil le líne comhthéacs amháin ar a laghad" + +#: apply.c +msgid "leave the rejected hunks in corresponding *.rej files" +msgstr "fág na hunks diúltaithe i gcomhaide*.rej comhfhreagracha" + +#: apply.c +msgid "allow overlapping hunks" +msgstr "cead a cheadú do na huncanna" + +#: apply.c +msgid "tolerate incorrectly detected missing new-line at the end of file" +msgstr "" +"glacadh le líne nua atá in easnamh a bhraitear go mícheart ag deireadh an " +"chomhaid" + +#: apply.c +msgid "do not trust the line counts in the hunk headers" +msgstr "ná bíodh muinín agat as na comhaireamh líne sna ceanntásca hunk" + +#: apply.c builtin/am.c +msgid "root" +msgstr "fréamh" + +#: apply.c +msgid "prepend to all filenames" +msgstr "cuireadh i bhfeidhm ar gach ainm comhaid" + +#: apply.c +msgid "don't return error for empty patches" +msgstr "ná tabhair earráid ar ais le haghaidh paistí folamh" + +#: apply.c +msgid "--ours, --theirs, and --union require --3way" +msgstr "Éilíonn --ours, --theirs, agus --union --3way" + +#: archive-tar.c archive-zip.c +#, c-format +msgid "cannot stream blob %s" +msgstr "ní féidir le blob %s a shruthlú" + +#: archive-tar.c archive-zip.c +#, c-format +msgid "unsupported file mode: 0%o (SHA1: %s)" +msgstr "modh comhad gan tacaíocht: 0%o (SHA1: %s)" + +#: archive-tar.c archive-zip.c builtin/pack-objects.c +#, c-format +msgid "deflate error (%d)" +msgstr "earráid dífhabhtaithe (%d)" + +#: archive-tar.c +#, c-format +msgid "unable to start '%s' filter" +msgstr "nach féidir scagaire '%s' a thosú" + +#: archive-tar.c +msgid "unable to redirect descriptor" +msgstr "nach féidir tuairiscí a atreorú" + +#: archive-tar.c +#, c-format +msgid "'%s' filter reported error" +msgstr "Earráid a thuairiscigh scagaire '%s'" + +#: archive-zip.c +#, c-format +msgid "path is not valid UTF-8: %s" +msgstr "níl cosán bailí UTF-8: %s" + +#: archive-zip.c +#, c-format +msgid "path too long (%d chars, SHA1: %s): %s" +msgstr "cosán rófhada (%d chars, SHA1: %s): %s" + +#: archive-zip.c +#, c-format +msgid "timestamp too large for this system: %" +msgstr "stampa ama ró-mhór don chóras seo:%" + +#: archive.c +msgid "git archive [] [...]" +msgstr "git cartlan n [] [...]" + +#: archive.c +msgid "" +"git archive --remote [--exec ] [] [...]" +msgstr "" +"git archive --remote [--exec] [] [...]" + +#: archive.c +msgid "git archive --remote [--exec ] --list" +msgstr "git archive --remote [--exec] --list" + +#: archive.c builtin/gc.c builtin/notes.c builtin/tag.c +#, c-format +msgid "cannot read '%s'" +msgstr "ní féidir '%s' a léamh" + +#: archive.c +#, c-format +msgid "pathspec '%s' matches files outside the current directory" +msgstr "meaitseálann pathspec '%s' comhaid lasmuigh den eolaire reatha" + +#: archive.c builtin/add.c builtin/rm.c +#, c-format +msgid "pathspec '%s' did not match any files" +msgstr "níor mheaitseáil pathspec '%s' aon chomhaid" + +#: archive.c +#, c-format +msgid "no such ref: %.*s" +msgstr "gan aon tagairt den sórt sin: %.*s" + +#: archive.c +#, c-format +msgid "not a valid object name: %s" +msgstr "ní ainm réad bailí: %s" + +#: archive.c t/helper/test-cache-tree.c +#, c-format +msgid "not a tree object: %s" +msgstr "ní réad crann: %s" + +#: archive.c +#, c-format +msgid "failed to unpack tree object %s" +msgstr "theip ar réad crann %s a dhíphacáil" + +#: archive.c +#, c-format +msgid "File not found: %s" +msgstr "Níor aimsíodh an comhad: %s" + +#: archive.c +#, c-format +msgid "Not a regular file: %s" +msgstr "Ní comhad rialta: %s" + +#: archive.c +#, c-format +msgid "unclosed quote: '%s'" +msgstr "luachan neamhdhúnadh: '%s'" + +#: archive.c +#, c-format +msgid "missing colon: '%s'" +msgstr "colon in easnamh: '%s'" + +#: archive.c +#, c-format +msgid "empty file name: '%s'" +msgstr "ainm comhaid folamh: '%s'" + +#: archive.c +msgid "fmt" +msgstr "fmt" + +#: archive.c +msgid "archive format" +msgstr "formáid cartlann" + +#: archive.c builtin/log.c parse-options.h +msgid "prefix" +msgstr "réimír" + +#: archive.c +msgid "prepend prefix to each pathname in the archive" +msgstr "réimír a pholadh chuig gach ainm cosán sa chartlann" + +#: archive.c builtin/blame.c builtin/commit-tree.c builtin/config.c +#: builtin/fast-export.c builtin/gc.c builtin/grep.c builtin/hash-object.c +#: builtin/ls-files.c builtin/notes.c builtin/read-tree.c parse-options.h +msgid "file" +msgstr "comhad" + +#: archive.c +msgid "add untracked file to archive" +msgstr "cuir comhad neamhrianaithe leis an gcartlann" + +#: archive.c +msgid "path:content" +msgstr "bealach:ábhar" + +#: archive.c builtin/archive.c +msgid "write the archive to this file" +msgstr "scríobh an cartlann chuig an gcomhad seo" + +#: archive.c +msgid "read .gitattributes in working directory" +msgstr "léite.gitattributs san eolaire oibre" + +#: archive.c +msgid "report archived files on stderr" +msgstr "tuairisciú comhaid cartlainne ar stderr" + +#: archive.c builtin/clone.c builtin/fetch.c builtin/pack-objects.c +#: builtin/pull.c +msgid "time" +msgstr "am" + +#: archive.c +msgid "set modification time of archive entries" +msgstr "socraigh am modhnaithe iontrálacha cartlainne" + +#: archive.c +msgid "set compression level" +msgstr "leibhéal comhbhrú a shocrú" + +#: archive.c +msgid "list supported archive formats" +msgstr "liosta formáidí cartlainne tacaíochta" + +#: archive.c builtin/archive.c builtin/clone.c builtin/submodule--helper.c +msgid "repo" +msgstr "stóras" + +#: archive.c builtin/archive.c +msgid "retrieve the archive from remote repository " +msgstr "aisghabháil an cartlann ó stór iargúlta " + +#: archive.c builtin/archive.c builtin/difftool.c builtin/notes.c +msgid "command" +msgstr "ordú" + +#: archive.c builtin/archive.c +msgid "path to the remote git-upload-archive command" +msgstr "cosán chuig an ordú iargúlta git-upload-archive" + +#: archive.c +msgid "Unexpected option --remote" +msgstr "Rogha gan choinne --remote" + +#: archive.c builtin/add.c builtin/checkout.c builtin/clone.c builtin/commit.c +#: builtin/fast-export.c builtin/index-pack.c builtin/log.c builtin/reset.c +#: builtin/rm.c builtin/stash.c builtin/worktree.c fetch-pack.c http-fetch.c +#: revision.c +#, c-format +msgid "the option '%s' requires '%s'" +msgstr "tá %s ag teastáil don rogha '%s'" + +#: archive.c +msgid "Unexpected option --output" +msgstr "Rogha gan choinne --output" + +#: archive.c t/unit-tests/unit-test.c +#, c-format +msgid "extra command line parameter '%s'" +msgstr "paraiméadar líne ordaithe breise '%s'" + +#: archive.c +#, c-format +msgid "Unknown archive format '%s'" +msgstr "Formáid cartlainne anaithnid '%s'" + +#: archive.c +#, c-format +msgid "Argument not supported for format '%s': -%d" +msgstr "Argóint nach dtacaítear le haghaidh formáid '%s': -%d" + +#: attr.c +#, c-format +msgid "%.*s is not a valid attribute name" +msgstr "%.*s ní ainm tréith bailí é" + +#: attr.c +msgid "unable to add additional attribute" +msgstr "in ann tréith bhreise a chur leis" + +#: attr.c +#, c-format +msgid "ignoring overly long attributes line %d" +msgstr "neamhaird a dhéanamh ar líne tréithe ró-fhada %d" + +#: attr.c +#, c-format +msgid "%s not allowed: %s:%d" +msgstr "%s ní cheadaítear %s:%d" + +#: attr.c +msgid "" +"Negative patterns are ignored in git attributes\n" +"Use '\\!' for literal leading exclamation." +msgstr "" +"Déantar neamhaird ar phatrúin dhiúltacha i d\n" +"Úsáid '\\!' le haghaidh brú ceannródaíoch litriúil." + +#: attr.c +#, c-format +msgid "cannot fstat gitattributes file '%s'" +msgstr "ní féidir an comhad gitattributeanna '%s' fstat" + +#: attr.c +#, c-format +msgid "ignoring overly large gitattributes file '%s'" +msgstr "neamhaird a dhéanamh ar chomhad gitattributs ró-mhór '%s'" + +#: attr.c +#, c-format +msgid "ignoring overly large gitattributes blob '%s'" +msgstr "neamhaird a dhéanamh ar ghitattributs ró-mhór blob '%s'" + +#: attr.c +msgid "cannot use --attr-source or GIT_ATTR_SOURCE without repo" +msgstr "ní féidir --attr-source nó GIT_ATTR_SOURCE a úsáid gan repo" + +#: attr.c +msgid "bad --attr-source or GIT_ATTR_SOURCE" +msgstr "olc --attr-source nó GIT_ATTR_SOURCE" + +#: attr.c read-cache.c refs/packed-backend.c +#, c-format +msgid "unable to stat '%s'" +msgstr "ní féidir '%s' a shástáil" + +#: bisect.c builtin/cat-file.c builtin/index-pack.c builtin/notes.c +#: builtin/pack-objects.c combine-diff.c object-file.c rerere.c +#, c-format +msgid "unable to read %s" +msgstr "nach féidir %s a léamh" + +#: bisect.c +#, c-format +msgid "Badly quoted content in file '%s': %s" +msgstr "Ábhar a luaitear go dona sa chomhad '%s': %s" + +#: bisect.c +#, c-format +msgid "We cannot bisect more!\n" +msgstr "Ní féidir linn níos mó a dhícheangal!\n" + +#: bisect.c +#, c-format +msgid "Not a valid commit name %s" +msgstr "Ní ainm tiomanta bailí %s" + +#: bisect.c +#, c-format +msgid "" +"The merge base %s is bad.\n" +"This means the bug has been fixed between %s and [%s].\n" +msgstr "" +"Tá an bonn cumaisc %s go dona.\n" +"Ciallaíonn sé seo go bhfuil an fabht socraithe idir %s agus [%s].\n" + +#: bisect.c +#, c-format +msgid "" +"The merge base %s is new.\n" +"The property has changed between %s and [%s].\n" +msgstr "" +"Tá an bonn cumaisc %s nua.\n" +"Tá athrú tagtha ar an maoin idir %s agus [%s].\n" + +#: bisect.c +#, c-format +msgid "" +"The merge base %s is %s.\n" +"This means the first '%s' commit is between %s and [%s].\n" +msgstr "" +"Is é an bonn cumaisc %s ná %s.\n" +"Ciallaíonn sé seo go bhfuil an chéad thiomantas '%s' idir %s agus [%s].\n" + +#: bisect.c +#, c-format +msgid "" +"Some %s revs are not ancestors of the %s rev.\n" +"git bisect cannot work properly in this case.\n" +"Maybe you mistook %s and %s revs?\n" +msgstr "" +"Ní sinsear an %s rev iad roinnt revs %s\n" +"Ní féidir le git bisect oibriú i gceart sa chás seo.\n" +"B'fhéidir gur mheas tú %s agus %s revs?\n" + +#: bisect.c +#, c-format +msgid "" +"the merge base between %s and [%s] must be skipped.\n" +"So we cannot be sure the first %s commit is between %s and %s.\n" +"We continue anyway." +msgstr "" +"caithfear an bonn cumaisc idir %s agus [%s] a scipeáil.\n" +"Mar sin ní féidir linn a bheith cinnte go bhfuil an chéad thiomantas %s idir " +"%s agus %s.\n" +"Leanaimid orainn ar aon nós." + +#: bisect.c +#, c-format +msgid "Bisecting: a merge base must be tested\n" +msgstr "Déroinnt: ní mór bonn cumaisc a thástáil\n" + +#: bisect.c +#, c-format +msgid "a %s revision is needed" +msgstr "tá athbhreithniú %s ag teastáil" + +#: bisect.c +#, c-format +msgid "could not create file '%s'" +msgstr "ní fhéadfaí comhad '%s' a chruthú" + +#: bisect.c builtin/notes.c +#, c-format +msgid "unable to start 'show' for object '%s'" +msgstr "ní féidir 'show' a thosú le haghaidh réad '%s'" + +#: bisect.c builtin/merge.c +#, c-format +msgid "could not read file '%s'" +msgstr "ní raibh in ann comhad '%s' a léamh" + +#: bisect.c +msgid "reading bisect refs failed" +msgstr "theip ar athbhreithnithe bisect a léamh" + +#: bisect.c +#, c-format +msgid "%s was both %s and %s\n" +msgstr "Bhí %s %s agus %s araon\n" + +#: bisect.c +#, c-format +msgid "" +"No testable commit found.\n" +"Maybe you started with bad path arguments?\n" +msgstr "" +"Níor aimsíodh aon tiomantas intástála.\n" +"B'fhéidir gur thosaigh tú le droch-argóintí cosáin?\n" + +#: bisect.c +#, c-format +msgid "(roughly %d step)" +msgid_plural "(roughly %d steps)" +msgstr[0] "(thart ar %d céim)" +msgstr[1] "(thart ar %d céim)" +msgstr[2] "(thart ar %d céim)" + +#. TRANSLATORS: the last %s will be replaced with "(roughly %d +#. steps)" translation. +#. +#: bisect.c +#, c-format +msgid "Bisecting: %d revision left to test after this %s\n" +msgid_plural "Bisecting: %d revisions left to test after this %s\n" +msgstr[0] "Ag trasnú: %d athbhreithniú fágtha le tástáil tar éis an %s seo\n" +msgstr[1] "" +"Ag roinnt ina dhá leath: %d athbhreithniú fágtha le tástáil tar éis an %s " +"seo\n" +msgstr[2] "" +"Ag roinnt ina dhá leath: %d athbhreithniú fágtha le tástáil tar éis an %s " +"seo\n" + +#: blame.c +msgid "--contents and --reverse do not blend well." +msgstr "Ní chumasc --contents agus --reverse go maith." + +#: blame.c +msgid "--reverse and --first-parent together require specified latest commit" +msgstr "" +"Éilíonn --reverse agus --first-parent le chéile an tiomantas sonraithe is " +"déanaí" + +#: blame.c builtin/bisect.c builtin/commit.c builtin/log.c builtin/merge.c +#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c +#: remote.c sequencer.c submodule.c +msgid "revision walk setup failed" +msgstr "theip ar socrú siúlóid ath" + +#: blame.c +msgid "" +"--reverse --first-parent together require range along first-parent chain" +msgstr "" +"--reverse --first-parent le chéile, teastaíonn raon feadh an tslabhra first-" +"parent" + +#: blame.c +#, c-format +msgid "no such path %s in %s" +msgstr "níl aon chosán den sórt sin %s i %s" + +#: blame.c +#, c-format +msgid "cannot read blob %s for path %s" +msgstr "ní féidir le blob %s a léamh le haghaidh cosán %s" + +#: branch.c +msgid "" +"cannot inherit upstream tracking configuration of multiple refs when " +"rebasing is requested" +msgstr "" +"ní féidir cumraíocht rianaithe suas srutha iolracha a oidhreacht nuair a " +"iarrtar athbhunú" + +#: branch.c +#, c-format +msgid "not setting branch '%s' as its own upstream" +msgstr "gan brainse '%s' a shocrú mar a thuas an sruth féin" + +#: branch.c +#, c-format +msgid "branch '%s' set up to track '%s' by rebasing." +msgstr "bunaíodh brainse '%s' chun '%s' a rianú trí athbhunú." + +#: branch.c +#, c-format +msgid "branch '%s' set up to track '%s'." +msgstr "bunaíodh brainse '%s' chun '%s' a rianú." + +#: branch.c +#, c-format +msgid "branch '%s' set up to track:" +msgstr "bunaíodh brainse '%s' chun rianú:" + +#: branch.c +msgid "unable to write upstream branch configuration" +msgstr "in ann cumraíocht brainse suas srutha a scríobh" + +#: branch.c +msgid "" +"\n" +"After fixing the error cause you may try to fix up\n" +"the remote tracking information by invoking:" +msgstr "" +"\n" +"Tar éis an chúis earráide a shocrú féadfaidh tú iarracht a dhéanamh socrú\n" +"an fhaisnéis cianrianaithe trí ghairm a dhéanamh ar:" + +#: branch.c +#, c-format +msgid "asked to inherit tracking from '%s', but no remote is set" +msgstr "iarradh ar rianú oidhreachta ó '%s', ach níl aon iargúlta socraithe" + +#: branch.c +#, c-format +msgid "asked to inherit tracking from '%s', but no merge configuration is set" +msgstr "" +"iarrtar ar rianú oidhreachta ó '%s', ach níl aon chumraíocht cumaisc " +"socraithe" + +#: branch.c +#, c-format +msgid "not tracking: ambiguous information for ref '%s'" +msgstr "gan rianú: faisnéis dhébhríoch le haghaidh tagairt '%s'" + +#. TRANSLATORS: This is a line listing a remote with duplicate +#. refspecs in the advice message below. For RTL languages you'll +#. probably want to swap the "%s" and leading " " space around. +#. +#. TRANSLATORS: This is line item of ambiguous object output +#. from describe_ambiguous_object() above. For RTL languages +#. you'll probably want to swap the "%s" and leading " " space +#. around. +#. +#: branch.c object-name.c +#, c-format +msgid " %s\n" +msgstr " %s\n" + +#. TRANSLATORS: The second argument is a \n-delimited list of +#. duplicate refspecs, composed above. +#. +#: branch.c +#, c-format +msgid "" +"There are multiple remotes whose fetch refspecs map to the remote\n" +"tracking ref '%s':\n" +"%s\n" +"This is typically a configuration error.\n" +"\n" +"To support setting up tracking branches, ensure that\n" +"different remotes' fetch refspecs map into different\n" +"tracking namespaces." +msgstr "" +"Tá iomadúla iargúlta ann a bhfuil a léarscáil athfheidhmithe a fháil chuig " +"an iargúlta\n" +"tagairt rianaithe '%s':\n" +"%s\n" +"De ghnáth is earráid chumraíochta é seo.\n" +"\n" +"Chun tacú le brainsí rianaithe a bhunú, cinntigh go\n" +"faigheann ciananna éagsúla léarscáil speisiúcháin go difriúil\n" +"spaisí ainmneacha a rianú." + +#: branch.c +#, c-format +msgid "'%s' is not a valid branch name" +msgstr "Ní ainm brainse bailí é '%s'" + +#: branch.c builtin/branch.c +msgid "See `man git check-ref-format`" +msgstr "Féach `man git check-ref-format`" + +#: branch.c +#, c-format +msgid "a branch named '%s' already exists" +msgstr "tá brainse darb ainm '%s' ann cheana" + +#: branch.c +#, c-format +msgid "cannot force update the branch '%s' used by worktree at '%s'" +msgstr "" +"ní féidir an brainse '%s' a úsáideann crann oibre a nuashonrú a chur i " +"bhfeidhm ag '%s'" + +#: branch.c +#, c-format +msgid "cannot set up tracking information; starting point '%s' is not a branch" +msgstr "" +"ní féidir faisnéis rianaithe a chur ar bun; ní brainse é pointe tosaigh '%s'" + +#: branch.c +#, c-format +msgid "the requested upstream branch '%s' does not exist" +msgstr "níl an brainse suas srutha iarrtha '%s' ann" + +#: branch.c +msgid "" +"\n" +"If you are planning on basing your work on an upstream\n" +"branch that already exists at the remote, you may need to\n" +"run \"git fetch\" to retrieve it.\n" +"\n" +"If you are planning to push out a new local branch that\n" +"will track its remote counterpart, you may want to use\n" +"\"git push -u\" to set the upstream config as you push." +msgstr "" +"\n" +"Má tá tú ag pleanáil do chuid oibre a bhunú ar an suas sruth\n" +"brainse atá ann cheana féin ag an iargúlta, b'fhéidir go mbeidh ort\n" +"reáchtáil “git fetch” chun é a aisghabháil.\n" +"\n" +"Má tá tú ag pleanáil brainse áitiúil nua a bhrú amach\n" +"rianóidh sé a mhacasamhail iargúlta, b'fhéidir gur mhaith leat a úsáid\n" +"“git push -u” chun an cumraíocht suas sruth a shocrú agus tú ag brú." + +#: branch.c builtin/replace.c +#, c-format +msgid "not a valid object name: '%s'" +msgstr "ní ainm réad bailí: '%s'" + +#: branch.c +#, c-format +msgid "ambiguous object name: '%s'" +msgstr "ainm réad débhríoch: '%s'" + +#: branch.c +#, c-format +msgid "not a valid branch point: '%s'" +msgstr "ní pointe brainse bailí: '%s'" + +#: branch.c +#, c-format +msgid "submodule '%s': unable to find submodule" +msgstr "fo-mhodúl '%s': in ann fo-mhodúl a aimsiú" + +#: branch.c +#, c-format +msgid "" +"You may try updating the submodules using 'git checkout --no-recurse-" +"submodules %s && git submodule update --init'" +msgstr "" +"Is féidir leat triail a bhaint as na fo-mhodúil a nuashonrú ag baint úsáide " +"as 'git checkout --no-recurse-submodules %s && git submodule update --init'" + +#: branch.c +#, c-format +msgid "submodule '%s': cannot create branch '%s'" +msgstr "fo-mhodúl '%s': ní féidir brainse '%s' a chruthú" + +#: branch.c +#, c-format +msgid "'%s' is already used by worktree at '%s'" +msgstr "Úsáidtear '%s' cheana féin ag an gcrann oibre ag '%s'" + +#: builtin/add.c +msgid "git add [] [--] ..." +msgstr "git add [] [--]..." + +#: builtin/add.c +#, c-format +msgid "cannot chmod %cx '%s'" +msgstr "ní féidir chmod %cx '%s'" + +#: builtin/add.c +msgid "Unstaged changes after refreshing the index:" +msgstr "Athruithe gan stáitse tar éis an t-innéacs a athnuachan:" + +#: builtin/add.c +msgid "could not read the index" +msgstr "ní raibh in ann an t-innéacs a léamh" + +#: builtin/add.c +msgid "editing patch failed" +msgstr "theip ar paiste eagarthóire" + +#: builtin/add.c read-cache.c +#, c-format +msgid "could not stat '%s'" +msgstr "ní fhéadfaí '%s' a stát" + +#: builtin/add.c +msgid "empty patch. aborted" +msgstr "paiste folam. a ghabhrú" + +#: builtin/add.c +#, c-format +msgid "could not apply '%s'" +msgstr "ní fhéadfaí '%s' a chur i bhfeidhm" + +#: builtin/add.c +msgid "The following paths are ignored by one of your .gitignore files:\n" +msgstr "" +"Déanann ceann de do chomhaid .gitignore neamhaird ar na cosáin seo a " +"leanas:\n" + +#: builtin/add.c builtin/clean.c builtin/fetch.c builtin/mv.c +#: builtin/prune-packed.c builtin/pull.c builtin/push.c builtin/remote.c +#: builtin/rm.c builtin/send-pack.c +msgid "dry run" +msgstr "rith tirim" + +#: builtin/add.c builtin/check-ignore.c builtin/commit.c +#: builtin/count-objects.c builtin/fsck.c builtin/log.c builtin/mv.c +#: builtin/read-tree.c builtin/refs.c +msgid "be verbose" +msgstr "a bheith inearálta" + +#: builtin/add.c +msgid "interactive picking" +msgstr "piocadh idirghní" + +#: builtin/add.c builtin/checkout.c builtin/reset.c +msgid "select hunks interactively" +msgstr "roghnaigh hunks idirghníomhach" + +#: builtin/add.c +msgid "edit current diff and apply" +msgstr "athraigh an dif reatha agus cuir i bhfeidhm" + +#: builtin/add.c +msgid "allow adding otherwise ignored files" +msgstr "ligean comhaid a neamhaird a chur leis" + +#: builtin/add.c +msgid "update tracked files" +msgstr "comhaid rianaithe a nuashonrú" + +#: builtin/add.c +msgid "renormalize EOL of tracked files (implies -u)" +msgstr "" +"athormalú a dhéanamh ar EOL na gcomhaid rianaithe (tugann le tuiscint -u)" + +#: builtin/add.c +msgid "record only the fact that the path will be added later" +msgstr "ní thaifeadadh ach an fíric go gcuirfear an cosán leis níos déanaí" + +#: builtin/add.c +msgid "add changes from all tracked and untracked files" +msgstr "cuir athruithe ó gach comhad rianaithe agus neamhrianaithe" + +#: builtin/add.c +msgid "ignore paths removed in the working tree (same as --no-all)" +msgstr "" +"neamhaird a dhéanamh ar chosáin a bhaintear sa chrann oibre (mar an gcéanna " +"le --no-all)" + +#: builtin/add.c +msgid "don't add, only refresh the index" +msgstr "ná cuir leis, ach an t-innéacs a athnuachan" + +#: builtin/add.c +msgid "just skip files which cannot be added because of errors" +msgstr "" +"ní gá ach comhaid a scipeáil nach féidir a chur leis mar gheall ar earráidí" + +#: builtin/add.c +msgid "check if - even missing - files are ignored in dry run" +msgstr "" +"seiceáil an ndéantar neamhaird ar chomhaid - fiú ar iarraidh - ar iarraidh" + +#: builtin/add.c builtin/mv.c builtin/rm.c +msgid "allow updating entries outside of the sparse-checkout cone" +msgstr "ligean iontrálacha a nuashonrú lasmuigh den chón seiceála neamh" + +#: builtin/add.c builtin/update-index.c +msgid "override the executable bit of the listed files" +msgstr "an giotán infhorghníomhaithe de na comhaid liostaithe a sháraigh" + +#: builtin/add.c +msgid "warn when adding an embedded repository" +msgstr "rabhadh agus stór leabaithe á chur leis" + +#: builtin/add.c +#, c-format +msgid "" +"You've added another git repository inside your current repository.\n" +"Clones of the outer repository will not contain the contents of\n" +"the embedded repository and will not know how to obtain it.\n" +"If you meant to add a submodule, use:\n" +"\n" +"\tgit submodule add %s\n" +"\n" +"If you added this path by mistake, you can remove it from the\n" +"index with:\n" +"\n" +"\tgit rm --cached %s\n" +"\n" +"See \"git help submodule\" for more information." +msgstr "" +"Chuir tú stór git eile leis taobh istigh de do stór reatha.\n" +"Ní bheidh ábhar i gclóin an stór seachtrach\n" +"an stór leabaithe agus ní bheidh a fhios acu conas é a fháil.\n" +"Má bhí sé i gceist agat fo-mhodúl a chur leis, bain úsáid as:\n" +"\n" +" Cuir submodule git %s\n" +"\n" +"Má chuir tú an cosán seo le botún, is féidir leat é a bhaint as an\n" +"innéacs le:\n" +"\n" +"\tgit rm --cached %s\n" +"\n" +"Féach “git help submodule” le haghaidh tuilleadh faisnéise." + +#: builtin/add.c +#, c-format +msgid "adding embedded git repository: %s" +msgstr "stór git leabaithe a chur leis: %s" + +#: builtin/add.c +msgid "Use -f if you really want to add them." +msgstr "Úsáid -f más mian leat iad a chur leis i ndáiríre." + +#: builtin/add.c +msgid "adding files failed" +msgstr "theip ar chomhaid a chur leis" + +#: builtin/add.c +#, c-format +msgid "--chmod param '%s' must be either -x or +x" +msgstr "Caithfidh --chmod param '%s' a bheith -x nó +x" + +#: builtin/add.c builtin/checkout.c builtin/commit.c builtin/reset.c +#: builtin/rm.c builtin/stash.c +#, c-format +msgid "'%s' and pathspec arguments cannot be used together" +msgstr "Ní féidir argóintí '%s' agus pathspec a úsáid le chéile" + +#: builtin/add.c +#, c-format +msgid "Nothing specified, nothing added.\n" +msgstr "Níl aon rud sonraithe, ní chuir aon rud leis.\n" + +#: builtin/add.c +msgid "Maybe you wanted to say 'git add .'?" +msgstr "B'fhéidir gur mhaith leat a rá 'git add. '?" + +#: builtin/add.c builtin/check-ignore.c builtin/checkout.c builtin/clean.c +#: builtin/commit.c builtin/diff-tree.c builtin/grep.c builtin/mv.c +#: builtin/reset.c builtin/rm.c builtin/submodule--helper.c read-cache.c +#: rerere.c submodule.c +msgid "index file corrupt" +msgstr "comhad innéacs truaillithe" + +#: builtin/add.c builtin/am.c builtin/checkout.c builtin/clone.c +#: builtin/commit.c builtin/stash.c merge.c rerere.c +msgid "unable to write new index file" +msgstr "in ann comhad innéacs nua a scríobh" + +#: builtin/am.c builtin/mailinfo.c mailinfo.c +#, c-format +msgid "bad action '%s' for '%s'" +msgstr "droch-ghníomh '%s' le haghaidh '%s'" + +#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c +#: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c +#: ls-refs.c parallel-checkout.c sequencer.c setup.c +#, c-format +msgid "invalid value for '%s': '%s'" +msgstr "luach neamhbhailí do '%s': '%s'" + +#: builtin/am.c builtin/commit.c builtin/merge.c sequencer.c +#, c-format +msgid "could not read '%s'" +msgstr "ní raibh in ann '%s' a léamh" + +#: builtin/am.c +msgid "could not parse author script" +msgstr "ní raibh sé in ann script údair a pharsáil" + +#: builtin/am.c builtin/replace.c commit.c sequencer.c +#, c-format +msgid "could not parse %s" +msgstr "ní fhéadfaí %s a pháirseáil" + +#: builtin/am.c +#, c-format +msgid "'%s' was deleted by the applypatch-msg hook" +msgstr "Scriosadh '%s' ag an crúca applypatch-msg" + +#: builtin/am.c +#, c-format +msgid "Malformed input line: '%s'." +msgstr "Líne ionchuir mífhoirmithe: '%s'." + +#: builtin/am.c +#, c-format +msgid "Failed to copy notes from '%s' to '%s'" +msgstr "Theip ar nótaí a chóipeáil ó '%s' go '%s'" + +#: builtin/am.c +msgid "fseek failed" +msgstr "theip ar fseek" + +#: builtin/am.c builtin/rebase.c sequencer.c wrapper.c +#, c-format +msgid "could not open '%s' for reading" +msgstr "ní fhéadfaí '%s' a oscailt le haghaidh léamh" + +#: builtin/am.c builtin/rebase.c editor.c sequencer.c wrapper.c +#, c-format +msgid "could not open '%s' for writing" +msgstr "ní féidir '%s' a oscailt le haghaidh scríbhneoireachta" + +#: builtin/am.c +#, c-format +msgid "could not parse patch '%s'" +msgstr "ní raibh sé in ann paiste '%s' a pháirseáil" + +#: builtin/am.c +msgid "Only one StGIT patch series can be applied at once" +msgstr "" +"Ní féidir ach sraith paiste STGit amháin a chur i bhfeidhm ag an am céanna" + +#: builtin/am.c +msgid "invalid timestamp" +msgstr "stampa ama neamhbhailí" + +#: builtin/am.c +msgid "invalid Date line" +msgstr "líne dáta neamhbhailí" + +#: builtin/am.c +msgid "invalid timezone offset" +msgstr "fhritháireamh crios ama neamh" + +#: builtin/am.c +msgid "Patch format detection failed." +msgstr "Theip ar bhrath formáid paiste." + +#: builtin/am.c builtin/clone.c +#, c-format +msgid "failed to create directory '%s'" +msgstr "theip ar eolaire '%s' a chruthú" + +#: builtin/am.c +msgid "Failed to split patches." +msgstr "Theip ar phaistí a roinnt." + +#: builtin/am.c +#, c-format +msgid "When you have resolved this problem, run \"%s --continue\".\n" +msgstr "" +"Nuair a bheidh an fhadhb seo réitithe agat, reáchtáil “%s --continue”.\n" + +#: builtin/am.c +#, c-format +msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n" +msgstr "" +"Más fearr leat an paiste seo a scipeáil, reáchtáil “%s --skip” ina ionad.\n" + +#: builtin/am.c +#, c-format +msgid "" +"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n" +msgstr "" +"Chun an paiste folamh a thaifeadadh mar thiomantas folamh, reáchtáil “%s --" +"allow-empty”.\n" + +#: builtin/am.c +#, c-format +msgid "To restore the original branch and stop patching, run \"%s --abort\"." +msgstr "" +"Chun an brainse bunaidh a chur ar ais agus stopadh le patáil, reáchtáil “%s " +"--abort”." + +#: builtin/am.c +msgid "Patch sent with format=flowed; space at the end of lines might be lost." +msgstr "" +"Seoladh paiste le formáid = sreabhadh; d'fhéadfaí spás ag deireadh na línte " +"a chailleadh." + +#: builtin/am.c +#, c-format +msgid "missing author line in commit %s" +msgstr "líne údair ar iarraidh i dtiomantas %s" + +#: builtin/am.c +#, c-format +msgid "invalid ident line: %.*s" +msgstr "líne aitheantais neamhbhailí: %.*s" + +#: builtin/am.c builtin/checkout.c builtin/clone.c commit-graph.c +#, c-format +msgid "unable to parse commit %s" +msgstr "nach féidir le tiomantas %s a pharsáil" + +#: builtin/am.c +msgid "Repository lacks necessary blobs to fall back on 3-way merge." +msgstr "" +"Níl na blobanna riachtanacha ag an stór chun titim siar ar chumasc trí " +"bhealach." + +#: builtin/am.c +msgid "Using index info to reconstruct a base tree..." +msgstr "Eolas innéacs a úsáid chun bonn crann a athchóiriú..." + +#: builtin/am.c +msgid "" +"Did you hand edit your patch?\n" +"It does not apply to blobs recorded in its index." +msgstr "" +"Ar chuir tú do phaiste in eagar de láimh?\n" +"Ní bhaineann sé le blobs a taifeadtar ina innéacs." + +#: builtin/am.c +msgid "Falling back to patching base and 3-way merge..." +msgstr "Ag titim ar ais go bonn paiste agus cumasc trí bhealach..." + +#: builtin/am.c +msgid "Failed to merge in the changes." +msgstr "Theip ar na hathruithe a chumasc." + +#: builtin/am.c builtin/merge.c sequencer.c +msgid "git write-tree failed to write a tree" +msgstr "theip ar git write-tree crann a scríobh" + +#: builtin/am.c +msgid "applying to an empty history" +msgstr "iarratas a dhéanamh ar stair folamh" + +#: builtin/am.c builtin/commit.c builtin/merge.c builtin/replay.c sequencer.c +msgid "failed to write commit object" +msgstr "theip ar réad tiomanta a scríobh" + +#: builtin/am.c +#, c-format +msgid "cannot resume: %s does not exist." +msgstr "ní féidir atosú: níl %s ann." + +#: builtin/am.c +msgid "Commit Body is:" +msgstr "Is é an Comhlacht Tiomanta:" + +#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a] +#. in your translation. The program will only accept English +#. input at this point. +#. +#: builtin/am.c +#, c-format +msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: " +msgstr "" +"Cuir i bhfeidhm?[y]es/[n]o/[e]dit/[v]iew patch/[a]glacadh le gach rud: " + +#: builtin/am.c builtin/commit.c +msgid "unable to write index file" +msgstr "in ann comhad innéacs a scríobh" + +#: builtin/am.c +#, c-format +msgid "Dirty index: cannot apply patches (dirty: %s)" +msgstr "Innéacs salach: ní féidir paistí a chur i bhfeidhm (salach: %s)" + +#: builtin/am.c +#, c-format +msgid "Skipping: %.*s" +msgstr "Scipeáil: %.*s" + +#: builtin/am.c +#, c-format +msgid "Creating an empty commit: %.*s" +msgstr "Tiomantas folamh a chruthú: %.*s" + +#: builtin/am.c +msgid "Patch is empty." +msgstr "Tá paiste folamh." + +#: builtin/am.c +#, c-format +msgid "Applying: %.*s" +msgstr "Iarratas a dhéanamh: %.*s" + +#: builtin/am.c +msgid "No changes -- Patch already applied." +msgstr "Gan aon athruithe - paiste curtha i bhfeidhm cheana féin." + +#: builtin/am.c +#, c-format +msgid "Patch failed at %s %.*s" +msgstr "Theip ar phaiste ag %s%.*s" + +#: builtin/am.c +msgid "Use 'git am --show-current-patch=diff' to see the failed patch" +msgstr "" +"Úsáid 'git am --show-current-patch=diff' chun an paiste theip a fheiceáil" + +#: builtin/am.c +msgid "No changes - recorded it as an empty commit." +msgstr "Gan aon athruithe - taifeadadh é mar thiomantas folamh." + +#: builtin/am.c +msgid "" +"No changes - did you forget to use 'git add'?\n" +"If there is nothing left to stage, chances are that something else\n" +"already introduced the same changes; you might want to skip this patch." +msgstr "" +"Gan aon athruithe - ar ndearna tú dearmad 'git add' a úsáid?\n" +"Mura bhfuil aon rud fágtha chun na céime, tá seans ann go bhfuil rud éigin " +"eile\n" +"tugadh na hathruithe céanna isteach cheana féin; b'fhéidir gur mhaith leat " +"an paiste seo a scipeáil." + +#: builtin/am.c +msgid "" +"You still have unmerged paths in your index.\n" +"You should 'git add' each file with resolved conflicts to mark them as " +"such.\n" +"You might run `git rm` on a file to accept \"deleted by them\" for it." +msgstr "" +"Tá cosáin neamh-chumasaithe agat fós i d'innéacs.\n" +"Ba chóir duit gach comhad a 'chur leis 'git' le coinbhleachtaí réitithe chun " +"iad a mharcáil mar sin.\n" +"D'fhéadfá `git rm` a reáchtáil ar chomhad chun glacadh le “scriosta ag siad” " +"dó." + +#: builtin/am.c builtin/reset.c +#, c-format +msgid "Could not parse object '%s'." +msgstr "Ní fhéadfaí réad '%s' a pháirseáil." + +#: builtin/am.c +msgid "failed to clean index" +msgstr "theip ar innéacs a ghlanadh" + +#: builtin/am.c +msgid "" +"You seem to have moved HEAD since the last 'am' failure.\n" +"Not rewinding to ORIG_HEAD" +msgstr "" +"Is cosúil gur bhogadh tú HEAD ón teip 'am' deireanach.\n" +"Gan athfhillte chuig ORIG_HEAD" + +#: builtin/am.c builtin/bisect.c builtin/tag.c worktree.c +#, c-format +msgid "failed to read '%s'" +msgstr "theip ar '%s' a léamh" + +#: builtin/am.c +msgid "git am [] [( | )...]" +msgstr "git am [] [( | )...]" + +#: builtin/am.c +msgid "git am [] (--continue | --skip | --abort)" +msgstr "git am [] (--continue | --skip | --abort)" + +#: builtin/am.c +msgid "run interactively" +msgstr "rith idirghníomhach" + +#: builtin/am.c +msgid "bypass pre-applypatch and applypatch-msg hooks" +msgstr "seachbhóthar crúcaí réamh-applypatch agus applypatch-msg" + +#: builtin/am.c builtin/cat-file.c +msgid "historical option -- no-op" +msgstr "rogha stairiúil -- no-op" + +#: builtin/am.c +msgid "allow fall back on 3way merging if needed" +msgstr "ligean titim siar ar chumasc 3bhealach más gá" + +#: builtin/am.c builtin/init-db.c builtin/prune-packed.c builtin/repack.c +#: builtin/stash.c +msgid "be quiet" +msgstr "a bheith ciúin" + +#: builtin/am.c +msgid "add a Signed-off-by trailer to the commit message" +msgstr "cuir leantóir sínithe amach leis an teachtaireacht tiomanta" + +#: builtin/am.c +msgid "recode into utf8 (default)" +msgstr "athchóiriú isteach i utf8 (réamhshocraithe)" + +#: builtin/am.c +msgid "pass -k flag to git-mailinfo" +msgstr "pas bratach -k chuig git-mailinfo" + +#: builtin/am.c +msgid "pass -b flag to git-mailinfo" +msgstr "pas bratach -b chuig git-mailinfo" + +#: builtin/am.c +msgid "pass -m flag to git-mailinfo" +msgstr "pas bratach -m chuig git-mailinfo" + +#: builtin/am.c +msgid "pass --keep-cr flag to git-mailsplit for mbox format" +msgstr "pas bratach --keep-cr go git-mailsplit le haghaidh formáid mbox" + +#: builtin/am.c +msgid "strip everything before a scissors line" +msgstr "gach rud a tharraingt roimh líne siosúr" + +#: builtin/am.c +msgid "pass it through git-mailinfo" +msgstr "cuir ar aghaidh trí git-mailinfo" + +#: builtin/am.c +msgid "pass it through git-apply" +msgstr "cuir isteach é trí git-apply" + +#: builtin/am.c builtin/commit.c builtin/fmt-merge-msg.c builtin/grep.c +#: builtin/merge.c builtin/pull.c builtin/rebase.c builtin/repack.c +#: builtin/show-branch.c builtin/show-ref.c builtin/tag.c parse-options.h +msgid "n" +msgstr "n" + +#: builtin/am.c builtin/branch.c builtin/bugreport.c builtin/cat-file.c +#: builtin/clone.c builtin/diagnose.c builtin/for-each-ref.c builtin/init-db.c +#: builtin/ls-files.c builtin/ls-tree.c builtin/refs.c builtin/replace.c +#: builtin/submodule--helper.c builtin/tag.c builtin/verify-tag.c +msgid "format" +msgstr "formáid" + +#: builtin/am.c +msgid "format the patch(es) are in" +msgstr "formáid atá na paistea/na paiste iontu" + +#: builtin/am.c +msgid "override error message when patch failure occurs" +msgstr "teachtaireacht earráide a shárú nuair a tharlaíonn teip" + +#: builtin/am.c +msgid "continue applying patches after resolving a conflict" +msgstr "leanúint ar aghaidh ag cur paistí a chur i bhfeidhm tar" + +#: builtin/am.c +msgid "synonyms for --continue" +msgstr "comhchiallaigh do --continue" + +#: builtin/am.c +msgid "skip the current patch" +msgstr "scipeáil an paiste reatha" + +#: builtin/am.c +msgid "restore the original branch and abort the patching operation" +msgstr "" +"an bhrainse bunaidh a chur ar ais agus cuir deireadh leis an oibríocht paiste" + +#: builtin/am.c +msgid "abort the patching operation but keep HEAD where it is" +msgstr "" +"déan deireadh leis an oibríocht paisteála ach coinnigh CEAD san áit a bhfuil " +"sé" + +#: builtin/am.c +msgid "show the patch being applied" +msgstr "taispeáin an paiste atá á chur i bhfeidhm" + +#: builtin/am.c +msgid "try to apply current patch again" +msgstr "déan iarracht paiste reatha a chur i bhfeidhm" + +#: builtin/am.c +msgid "record the empty patch as an empty commit" +msgstr "taifeadadh an paiste folamh mar thiomantas folamh" + +#: builtin/am.c +msgid "lie about committer date" +msgstr "bréag faoi dháta an choimisiúnaithe" + +#: builtin/am.c +msgid "use current timestamp for author date" +msgstr "bain úsáid as stampa ama reatha le haghaidh dáta an údair" + +#: builtin/am.c builtin/commit-tree.c builtin/commit.c builtin/merge.c +#: builtin/pull.c builtin/rebase.c builtin/revert.c builtin/tag.c +msgid "key-id" +msgstr "id eochair" + +#: builtin/am.c builtin/rebase.c +msgid "GPG-sign commits" +msgstr "Tiomanta comhartha GPG-Comhartha" + +#: builtin/am.c +msgid "how to handle empty patches" +msgstr "conas paistí folamh a láimhseáil" + +#: builtin/am.c +msgid "(internal use for git-rebase)" +msgstr "(úsáid inmheánach le haghaidh git-rebase)" + +#: builtin/am.c +msgid "" +"The -b/--binary option has been a no-op for long time, and\n" +"it will be removed. Please do not use it anymore." +msgstr "" +"Tá an rogha -b/--binary neamh-op le fada an lá, agus\n" +"bainfear é. Ná húsáid é níos mó le do thoil." + +#: builtin/am.c +msgid "failed to read the index" +msgstr "theip ar an t-innéacs a léamh" + +#: builtin/am.c +#, c-format +msgid "previous rebase directory %s still exists but mbox given." +msgstr "eolaire rebase roimhe seo %s ann fós ach tugadh mbox." + +#: builtin/am.c +#, c-format +msgid "" +"Stray %s directory found.\n" +"Use \"git am --abort\" to remove it." +msgstr "" +"Fuarthas eolaire %s stray.\n" +"Úsáid “git am --abort” chun é a bhaint." + +#: builtin/am.c +msgid "Resolve operation not in progress, we are not resuming." +msgstr "Réiteach oibríocht nach bhfuil ar siúl, níl muid ag atosú." + +#: builtin/am.c +msgid "interactive mode requires patches on the command line" +msgstr "éilíonn modh idirghníomhach paistí ar an líne ordaithe" + +#: builtin/apply.c +msgid "git apply [] [...]" +msgstr "git feidhm [] [...]" + +#: builtin/archive.c diagnose.c +msgid "could not redirect output" +msgstr "ní fhéadfaí aschur a atreorú" + +#: builtin/archive.c +msgid "git archive: expected ACK/NAK, got a flush packet" +msgstr "cartlann git: ag súil le ACK/NAK, fuair sé paicéad sruthán" + +#: builtin/archive.c +#, c-format +msgid "git archive: NACK %s" +msgstr "git archive: NACK %s" + +#: builtin/archive.c +msgid "git archive: protocol error" +msgstr "git cartlann: earráid prótacal" + +#: builtin/archive.c +msgid "git archive: expected a flush" +msgstr "git archive: bhíothas ag súil le sruthlú" + +#: builtin/backfill.c +msgid "git backfill [--min-batch-size=] [--[no-]sparse]" +msgstr "git backfill [--min-batch-size=] [-- [no-] neart]" + +#: builtin/backfill.c +msgid "problem loading sparse-checkout" +msgstr "fadhb ag luchtú seiceáil neamhchoiti" + +#: builtin/backfill.c +msgid "Minimum number of objects to request at a time" +msgstr "Líon íosta rudaí le iarraidh ag an am" + +#: builtin/backfill.c +msgid "Restrict the missing objects to the current sparse-checkout" +msgstr "Cuir srian ar na rudaí atá in easnamh don tseiceáil neamhchoitianta" + +#: builtin/bisect.c +msgid "" +"git bisect start [--term-(new|bad)= --term-(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) [...]" +msgstr "git bisect (maith|olc) [...]" + +#: builtin/bisect.c +msgid "git bisect skip [(|)...]" +msgstr "git bisect skip [(|)...]" + +#: builtin/bisect.c +msgid "git bisect reset []" +msgstr "athshocrú git bisect []" + +#: builtin/bisect.c +msgid "git bisect replay " +msgstr "athsheinm git bisect " + +#: builtin/bisect.c +msgid "git bisect run [...]" +msgstr "git bisect a rith [...]" + +#: builtin/bisect.c +#, c-format +msgid "cannot open file '%s' in mode '%s'" +msgstr "ní féidir comhad '%s' a oscailt sa mhodh '%s'" + +#: builtin/bisect.c +#, c-format +msgid "could not write to file '%s'" +msgstr "ní fhéadfaí scríobh chuig comhad '%s'" + +#: builtin/bisect.c +#, c-format +msgid "cannot open file '%s' for reading" +msgstr "ní féidir comhad '%s' a oscailt le haghaidh léamh" + +#: builtin/bisect.c +#, c-format +msgid "'%s' is not a valid term" +msgstr "Ní téarma bailí é '%s'" + +#: builtin/bisect.c +#, c-format +msgid "can't use the builtin command '%s' as a term" +msgstr "ní féidir an t-ordú bunaithe '%s' a úsáid mar théarma" + +#: builtin/bisect.c +#, c-format +msgid "can't change the meaning of the term '%s'" +msgstr "ní féidir le brí an téarma '%s' a athrú" + +#: builtin/bisect.c +msgid "please use two different terms" +msgstr "bain úsáid as dhá théarma éagsúla" + +#: builtin/bisect.c +#, c-format +msgid "We are not bisecting.\n" +msgstr "Nílimid ag déileáil.\n" + +#: builtin/bisect.c +#, c-format +msgid "'%s' is not a valid commit" +msgstr "Ní gealltanas bailí é '%s'" + +#: builtin/bisect.c +#, c-format +msgid "" +"could not check out original HEAD '%s'. Try 'git bisect reset '." +msgstr "" +"ní fhéadfaí an HEAD bunaidh '%s' a sheiceáil. Bain triail as 'git " +"bisect reset '." + +#: builtin/bisect.c +#, c-format +msgid "Bad bisect_write argument: %s" +msgstr "Droch-argóint bisect_write: %s" + +#: builtin/bisect.c +#, c-format +msgid "couldn't get the oid of the rev '%s'" +msgstr "ní raibh in ann oid an rev '%s' a fháil" + +#: builtin/bisect.c +#, c-format +msgid "couldn't open the file '%s'" +msgstr "ní raibh in ann an comhad '%s' a oscailt" + +#: builtin/bisect.c +#, c-format +msgid "Invalid command: you're currently in a %s/%s bisect" +msgstr "Ordú neamhbhailí: tá tú i mbeagán %s/%s faoi láthair" + +#: builtin/bisect.c +#, c-format +msgid "" +"You need to give me at least one %s and %s revision.\n" +"You can use \"git bisect %s\" and \"git bisect %s\" for that." +msgstr "" +"Ní mór duit athbhreithniú %s agus %s amháin ar a laghad a thabhairt dom.\n" +"Is féidir leat “git bisect %s” agus “git bisect %s” a úsáid chuige sin." + +#: builtin/bisect.c +#, c-format +msgid "" +"You need to start by \"git bisect start\".\n" +"You then need to give me at least one %s and %s revision.\n" +"You can use \"git bisect %s\" and \"git bisect %s\" for that." +msgstr "" +"Ní mór duit tosú ag “git bisect start”.\n" +"Ansin ní mór duit athbhreithniú %s agus %s amháin ar a laghad a thabhairt " +"dom.\n" +"Is féidir leat “git bisect %s” agus “git bisect %s” a úsáid chuige sin." + +#: builtin/bisect.c +#, c-format +msgid "bisecting only with a %s commit" +msgstr "ag déileáil ach amháin le tiomantas %s" + +#. TRANSLATORS: Make sure to include [Y] and [n] in your +#. translation. The program will only accept English input +#. at this point. +#. +#: builtin/bisect.c +msgid "Are you sure [Y/n]? " +msgstr "An bhfuil tú cinnte [Y/n]? " + +#: builtin/bisect.c +msgid "status: waiting for both good and bad commits\n" +msgstr "stádas: ag fanacht le tiomáintí mhaith agus tiomáintí dona\n" + +#: builtin/bisect.c +#, c-format +msgid "status: waiting for bad commit, %d good commit known\n" +msgid_plural "status: waiting for bad commit, %d good commits known\n" +msgstr[0] "stádas: ag fanacht le droch-thiomnadh, %d dea-thiomnadh ar eolas\n" +msgstr[1] "" +"stádas: ag fanacht le droch-thiomantas, %d dea-thiomantas ar eolas\n" +msgstr[2] "" +"stádas: ag fanacht le droch-thiomantas, %d dea-thiomantas ar eolas\n" + +#: builtin/bisect.c +msgid "status: waiting for good commit(s), bad commit known\n" +msgstr "stádas: ag fanacht le tiomáintí maith, droch-tiomantas ar eolas\n" + +#: builtin/bisect.c +msgid "no terms defined" +msgstr "aon téarmaí sainmhínithe" + +#: builtin/bisect.c +#, c-format +msgid "" +"Your current terms are %s for the old state\n" +"and %s for the new state.\n" +msgstr "" +"Is iad na téarmaí reatha %s don seanstát\n" +"agus %s don stát nua.\n" + +#: builtin/bisect.c +#, c-format +msgid "" +"invalid argument %s for 'git bisect terms'.\n" +"Supported options are: --term-good|--term-old and --term-bad|--term-new." +msgstr "" +"argóint neamhbhailí %s le haghaidh 'git bisect terms'.\n" +"Is iad na roghanna tacaithe ná: --term-good|--term-old agus --term-bad|--" +"term-new." + +#: builtin/bisect.c +#, c-format +msgid "could not open '%s' for appending" +msgstr "ní fhéadfaí '%s' a oscailt le haghaidh cur isteach" + +#: builtin/bisect.c +msgid "'' is not a valid term" +msgstr "'' ní téarma bailí é" + +#: builtin/bisect.c +#, c-format +msgid "unrecognized option: '%s'" +msgstr "rogha gan aithint: '%s'" + +#: builtin/bisect.c +#, c-format +msgid "'%s' does not appear to be a valid revision" +msgstr "Ní cosúil gur athbhreithniú bailí é '%s'" + +#: builtin/bisect.c +msgid "bad HEAD - I need a HEAD" +msgstr "droch HEAD - Teastaíonn HEAD uaim" + +#: builtin/bisect.c +#, c-format +msgid "checking out '%s' failed. Try 'git bisect start '." +msgstr "" +"theip ar '%s' a sheiceáil. Bain triail as 'git bisect start '." + +#: builtin/bisect.c +msgid "bad HEAD - strange symbolic ref" +msgstr "bad HEAD - tagairt siombalach aisteach" + +#: builtin/bisect.c +#, c-format +msgid "invalid ref: '%s'" +msgstr "tagairt neamhbhailí: '%s'" + +#: builtin/bisect.c +msgid "You need to start by \"git bisect start\"\n" +msgstr "Ní mór duit tosú ag “git bisect start”\n" + +#. TRANSLATORS: Make sure to include [Y] and [n] in your +#. translation. The program will only accept English input +#. at this point. +#. +#: builtin/bisect.c +msgid "Do you want me to do it for you [Y/n]? " +msgstr "An dteastaíonn uait go ndéanfaidh mé é duit [Y/n]? " + +#: builtin/bisect.c +msgid "Please call `--bisect-state` with at least one argument" +msgstr "Glaoigh ar `--bisect-state` le do thoil le argóint amháin ar a laghad" + +#: builtin/bisect.c +#, c-format +msgid "'git bisect %s' can take only one argument." +msgstr "Ní féidir le 'git bisect %s' ach argóint amháin a ghlacadh." + +#: builtin/bisect.c +#, c-format +msgid "Bad rev input: %s" +msgstr "Droch-ionchur rev: %s" + +#: builtin/bisect.c +#, c-format +msgid "Bad rev input (not a commit): %s" +msgstr "Droch-ionchur rev (ní tiomantas): %s" + +#: builtin/bisect.c +msgid "We are not bisecting." +msgstr "Nílimid ag déileáil." + +#: builtin/bisect.c +#, c-format +msgid "'%s'?? what are you talking about?" +msgstr "'%s'?? cad atá tú ag caint faoi?" + +#: builtin/bisect.c +#, c-format +msgid "cannot read file '%s' for replaying" +msgstr "ní féidir comhad '%s' a léamh le haghaidh athsheinm" + +#: builtin/bisect.c +#, c-format +msgid "running %s\n" +msgstr "ag rith %s\n" + +#: builtin/bisect.c +msgid "bisect run failed: no command provided." +msgstr "theip ar rith bioctha: níl aon ordú curtha ar fáil." + +#: builtin/bisect.c +#, c-format +msgid "unable to verify %s on good revision" +msgstr "nach féidir %s a fhíorú ar athbhreithniú maith" + +#: builtin/bisect.c +#, c-format +msgid "bogus exit code %d for good revision" +msgstr "cód imeachta bréagach %d le haghaidh athbhreithniú maith" + +#: builtin/bisect.c +#, c-format +msgid "bisect run failed: exit code %d from %s is < 0 or >= 128" +msgstr "< 0 or >Theip ar rith bioctha: is é an cód imeachta %d ó %s = 128" + +#: builtin/bisect.c +#, c-format +msgid "cannot open file '%s' for writing" +msgstr "ní féidir comhad '%s' a oscailt le haghaidh scríobh" + +#: builtin/bisect.c +msgid "bisect run cannot continue any more" +msgstr "ní féidir le rith bisect leanúint ar aghaidh níos mó" + +#: builtin/bisect.c +msgid "bisect run success" +msgstr "rath reatha dhéagsúil" + +#: builtin/bisect.c +msgid "bisect found first bad commit" +msgstr "fuarthas bisect an chéad droch-thiomantas" + +#: builtin/bisect.c +#, c-format +msgid "bisect run failed: 'git bisect %s' exited with error code %d" +msgstr "theip ar rith bisect: D'éirigh 'git bisect %s' le cód earráide %d" + +#: builtin/bisect.c +#, c-format +msgid "'%s' requires either no argument or a commit" +msgstr "Ní éilíonn '%s' aon argóint ná tiomantas" + +#: builtin/bisect.c +#, c-format +msgid "'%s' requires 0 or 1 argument" +msgstr "Éilíonn '%s' argóint 0 nó 1" + +#: builtin/bisect.c +#, c-format +msgid "'%s' requires 0 arguments" +msgstr "Éilíonn '%s' 0 argóint" + +#: builtin/bisect.c +msgid "no logfile given" +msgstr "níl aon logfile tugtha" + +#: builtin/bisect.c +#, c-format +msgid "'%s' failed: no command provided." +msgstr "Theip ar '%s': níl aon ordú curtha ar fáil." + +#: builtin/bisect.c +msgid "need a command" +msgstr "teastaíonn ordú" + +#: builtin/bisect.c builtin/cat-file.c +#, c-format +msgid "unknown command: '%s'" +msgstr "ordú anaithnid: '%s'" + +#: builtin/blame.c +msgid "git blame [] [] [] [--] " +msgstr "git an mille án [] [] [] [--] " + +#: builtin/blame.c +msgid "git annotate [] [] [] [--] " +msgstr "git annotate [] [] [] [--] " + +#: builtin/blame.c +msgid " are documented in git-rev-list(1)" +msgstr "iad doiciméadaithe i git-rev-list (1)" + +#: builtin/blame.c +#, c-format +msgid "expecting a color: %s" +msgstr "ag súil le dath: %s" + +#: builtin/blame.c +msgid "must end with a color" +msgstr "caithfidh deireadh a chur le dath" + +#: builtin/blame.c +#, c-format +msgid "cannot find revision %s to ignore" +msgstr "ní féidir athbhreithniú %s a fháil le neamhair" + +#: builtin/blame.c +msgid "show blame entries as we find them, incrementally" +msgstr "taispeáint iontrálacha milleán de réir mar a aimsímid iad, go chéile" + +#: builtin/blame.c +msgid "do not show object names of boundary commits (Default: off)" +msgstr "" +"ná taispeáin ainmneacha réada na ngealltanais teorann (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "do not treat root commits as boundaries (Default: off)" +msgstr "" +"ná déileáil le gealltanais fréimhe mar theorainneacha (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show work cost statistics" +msgstr "taispeáin staitisticí costas oibre" + +#: builtin/blame.c builtin/checkout.c builtin/clone.c builtin/commit-graph.c +#: builtin/fetch.c builtin/merge.c builtin/multi-pack-index.c builtin/pull.c +#: builtin/push.c builtin/remote.c builtin/send-pack.c +msgid "force progress reporting" +msgstr "tuairisciú dul chun cinn" + +#: builtin/blame.c +msgid "show output score for blame entries" +msgstr "taispeáin scór aschuir d'iontrálacha mille" + +#: builtin/blame.c +msgid "show original filename (Default: auto)" +msgstr "taispeáin ainm comhaid bunaidh (Réamhshocraithe: auto)" + +#: builtin/blame.c +msgid "show original linenumber (Default: off)" +msgstr "taispeáin uimhir líne bunaidh (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show in a format designed for machine consumption" +msgstr "taispeáint i bhformáid atá deartha le haghaidh tomhaltas meaisín" + +#: builtin/blame.c +msgid "show porcelain format with per-line commit information" +msgstr "formáid poircealláin a thaispeáint le faisnéis tiomanta" + +#: builtin/blame.c +msgid "use the same output mode as git-annotate (Default: off)" +msgstr "" +"bain úsáid as an modh aschuir céanna le git-annotate (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show raw timestamp (Default: off)" +msgstr "taispeáin ama amh (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show long commit SHA1 (Default: off)" +msgstr "taispeáin tiomantas fada SHA1 (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "suppress author name and timestamp (Default: off)" +msgstr "ainm an údair agus stampa ama a chur faoi chois (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "show author email instead of name (Default: off)" +msgstr "taispeáin ríomhphost an údair in ionad ainm (Réamhshocraithe: as)" + +#: builtin/blame.c +msgid "ignore whitespace differences" +msgstr "neamhaird a dhéanamh ar dhifríochtaí spás b" + +#: builtin/blame.c builtin/clone.c builtin/log.c +msgid "rev" +msgstr "rev" + +#: builtin/blame.c +msgid "ignore when blaming" +msgstr "neamhaird a dhéanamh agus an milleán" + +#: builtin/blame.c +msgid "ignore revisions from " +msgstr "neamhaird ar athbhreithnithe " + +#: builtin/blame.c +msgid "color redundant metadata from previous line differently" +msgstr "meiteashonraí iomarcach dath ó líne roimhe seo ar bheal" + +#: builtin/blame.c +msgid "color lines by age" +msgstr "línte datha de réir aois" + +#: builtin/blame.c +msgid "spend extra cycles to find better match" +msgstr "timthriallta breise a chaitheamh chun meaitseáil níos fearr" + +#: builtin/blame.c +msgid "use revisions from instead of calling git-rev-list" +msgstr "athbhreithnithe a úsáid as in ionad glaoch ar git-rev-list" + +#: builtin/blame.c +msgid "use 's contents as the final image" +msgstr "úsáid ábhar mar an íomhá deiridh" + +#: builtin/blame.c +msgid "score" +msgstr "scór" + +#: builtin/blame.c +msgid "find line copies within and across files" +msgstr "faigh cóipeanna líne laistigh de chomhaid agus trasna" + +#: builtin/blame.c +msgid "find line movements within and across files" +msgstr "faigh gluaiseachtaí líne laistigh de chomhaid agus trasna" + +#: builtin/blame.c +msgid "range" +msgstr "raon" + +#: builtin/blame.c +msgid "process only line range , or function :" +msgstr "ach raon líne, nó feidh m a phróiseáil: " + +#: builtin/blame.c +msgid "--progress can't be used with --incremental or porcelain formats" +msgstr "Ní féidir --progress a úsáid le formáidí --incremental nó poircealláin" + +#. TRANSLATORS: This string is used to tell us the +#. maximum display width for a relative timestamp in +#. "git blame" output. For C locale, "4 years, 11 +#. months ago", which takes 22 places, is the longest +#. among various forms of relative timestamps, but +#. your language may need more or fewer display +#. columns. +#. +#: builtin/blame.c +msgid "4 years, 11 months ago" +msgstr "4 bliana, 11 mhí ó shin" + +#: builtin/blame.c +#, c-format +msgid "file %s has only %lu line" +msgid_plural "file %s has only %lu lines" +msgstr[0] "comhad %s níl ach %lu líne" +msgstr[1] "comhad %s níl ach %lu línte" +msgstr[2] "comhad %s níl ach %lu línte" + +#: builtin/blame.c +msgid "Blaming lines" +msgstr "An milleán ar línte" + +#: builtin/branch.c +msgid "git branch [] [-r | -a] [--merged] [--no-merged]" +msgstr "git branch [] [-r | -a] [--merged] [--no-merged]" + +#: builtin/branch.c +msgid "" +"git branch [] [-f] [--recurse-submodules] []" +msgstr "" +"git branch [] [-f] [--recurse-submodules] []" + +#: builtin/branch.c +msgid "git branch [] [-l] [...]" +msgstr "git branch [] [-l] [...]" + +#: builtin/branch.c +msgid "git branch [] [-r] (-d | -D) ..." +msgstr "git branch [] [-r] (-d | -D) ..." + +#: builtin/branch.c +msgid "git branch [] (-m | -M) [] " +msgstr "git branch [] (-m | -M) [] " + +#: builtin/branch.c +msgid "git branch [] (-c | -C) [] " +msgstr "git branch [] (-c | -C) [] " + +#: builtin/branch.c +msgid "git branch [] [-r | -a] [--points-at]" +msgstr "git branch [] [-r | -a] [--points-at]" + +#: builtin/branch.c +msgid "git branch [] [-r | -a] [--format]" +msgstr "git branch [] [-r | -a] [--format]" + +#: builtin/branch.c +#, c-format +msgid "" +"deleting branch '%s' that has been merged to\n" +" '%s', but not yet merged to HEAD" +msgstr "" +"brainse '%s' a bhfuil cumasc orthu a scriosadh\n" +" '%s', ach níor chumasc le HEAD go fóill" + +#: builtin/branch.c +#, c-format +msgid "" +"not deleting branch '%s' that is not yet merged to\n" +" '%s', even though it is merged to HEAD" +msgstr "" +"gan brainse '%s' a scriosadh nach bhfuil cumasc fós leis\n" +" '%s', cé go ndéantar é a chumasc le HEAD" + +#: builtin/branch.c +#, c-format +msgid "couldn't look up commit object for '%s'" +msgstr "ní raibh in ann réad tiomanta a lorg suas le haghaidh '%s'" + +#: builtin/branch.c +#, c-format +msgid "the branch '%s' is not fully merged" +msgstr "níl an brainse '%s' cumaisc go hiomlán" + +#: builtin/branch.c +#, c-format +msgid "If you are sure you want to delete it, run 'git branch -D %s'" +msgstr "" +"Má tá tú cinnte gur mhaith leat é a scriosadh, reáchtáil 'git branch -D %s'" + +#: builtin/branch.c +msgid "update of config-file failed" +msgstr "theip ar nuashonrú comhad config-file" + +#: builtin/branch.c +msgid "cannot use -a with -d" +msgstr "ní féidir -a a úsáid le -d" + +#: builtin/branch.c +#, c-format +msgid "cannot delete branch '%s' used by worktree at '%s'" +msgstr "ní féidir brainse '%s' a úsáideann crann oibre ag '%s' a scriosadh" + +#: builtin/branch.c +#, c-format +msgid "remote-tracking branch '%s' not found" +msgstr "níor aimsíodh brainse cianrianaithe '%s'" + +#: builtin/branch.c +#, c-format +msgid "" +"branch '%s' not found.\n" +"Did you forget --remote?" +msgstr "" +"níor aimsíodh brainse '%s'.\n" +"Ar ndearna tú dearmad ar --remote?" + +#: builtin/branch.c +#, c-format +msgid "branch '%s' not found" +msgstr "níor aimsíodh brainse '%s'" + +#: builtin/branch.c +#, c-format +msgid "Deleted remote-tracking branch %s (was %s).\n" +msgstr "Brainse cianrianaithe scriosta %s (bhí %s).\n" + +#: builtin/branch.c +#, c-format +msgid "Deleted branch %s (was %s).\n" +msgstr "Brainse %s scriosta (%s ba é).\n" + +#: builtin/branch.c builtin/tag.c +msgid "unable to parse format string" +msgstr "in ann teaghrán formáide a pháirseáil" + +#: builtin/branch.c +msgid "could not resolve HEAD" +msgstr "ní fhéadfaí HEAD a réiteach" + +#: builtin/branch.c +#, c-format +msgid "HEAD (%s) points outside of refs/heads/" +msgstr "Pointí HEAD (%s) lasmuigh de refs/heads/" + +#: builtin/branch.c +#, c-format +msgid "branch %s is being rebased at %s" +msgstr "tá brainse %s á athbhunú ag %s" + +#: builtin/branch.c +#, c-format +msgid "branch %s is being bisected at %s" +msgstr "tá brainse %s á dhíscaoileadh ag %s" + +#: builtin/branch.c +#, c-format +msgid "HEAD of working tree %s is not updated" +msgstr "Níl CEANN an chrainn oibre %s nuashonraithe" + +#: builtin/branch.c +#, c-format +msgid "invalid branch name: '%s'" +msgstr "ainm brainse neamhbhailí: '%s'" + +#: builtin/branch.c +#, c-format +msgid "no commit on branch '%s' yet" +msgstr "níl aon gealltanas ar bhrainse '%s' go fóill" + +#: builtin/branch.c +#, c-format +msgid "no branch named '%s'" +msgstr "níl aon bhrainse darb ainm '%s'" + +#: builtin/branch.c +msgid "branch rename failed" +msgstr "theip ar athainmniú brainse" + +#: builtin/branch.c +msgid "branch copy failed" +msgstr "theip ar chóip brainse" + +#: builtin/branch.c +#, c-format +msgid "created a copy of a misnamed branch '%s'" +msgstr "chruthaigh cóip de bhrainse mí-ainmnithe '%s'" + +#: builtin/branch.c +#, c-format +msgid "renamed a misnamed branch '%s' away" +msgstr "athainmnigh brainse mí-ainmnithe '%s' ar shiúl" + +#: builtin/branch.c +#, c-format +msgid "branch renamed to %s, but HEAD is not updated" +msgstr "athainmníodh brainse go %s, ach níl HEAD nuashonraithe" + +#: builtin/branch.c +msgid "branch is renamed, but update of config-file failed" +msgstr "athainmnítear brainse, ach theip ar nuashonrú ar chomhad config-file" + +#: builtin/branch.c +msgid "branch is copied, but update of config-file failed" +msgstr "cóipeáiltear brainse, ach theip ar nuashonrú comhad config-file" + +#: builtin/branch.c +#, c-format +msgid "" +"Please edit the description for the branch\n" +" %s\n" +"Lines starting with '%s' will be stripped.\n" +msgstr "" +"Cuir an tuairisc don bhrainse in eagar\n" +" %s\n" +"Déanfar línte a thosaíonn le '%s' a scriosadh.\n" + +#: builtin/branch.c +msgid "Generic options" +msgstr "Roghanna cineálacha" + +#: builtin/branch.c +msgid "show hash and subject, give twice for upstream branch" +msgstr "taispeáin hash agus ábhar, tabhair faoi dhó don bhrainse suas srutha" + +#: builtin/branch.c +msgid "suppress informational messages" +msgstr "teachtaireachtaí faisnéise a chur" + +#: builtin/branch.c builtin/checkout.c builtin/submodule--helper.c +msgid "set branch tracking configuration" +msgstr "cumraíocht rianaithe brainse a shoc" + +#: builtin/branch.c +msgid "do not use" +msgstr "ná húsáid" + +#: builtin/branch.c +msgid "upstream" +msgstr "suas sruth" + +#: builtin/branch.c +msgid "change the upstream info" +msgstr "athraigh an fhaisnéis suas sruth" + +#: builtin/branch.c +msgid "unset the upstream info" +msgstr "díshocraigh an fhaisnéis suas sruth" + +#: builtin/branch.c +msgid "use colored output" +msgstr "úsáid aschur daite" + +#: builtin/branch.c +msgid "act on remote-tracking branches" +msgstr "gníomhú ar bhrainsí cianrianaithe" + +#: builtin/branch.c +msgid "print only branches that contain the commit" +msgstr "ach brainsí a phriontáil ina bhfuil an tiomantas" + +#: builtin/branch.c +msgid "print only branches that don't contain the commit" +msgstr "ach brainsí a phriontáil nach bhfuil an tiomantas" + +#: builtin/branch.c +msgid "Specific git-branch actions:" +msgstr "Gníomhartha sonracha git-branch:" + +#: builtin/branch.c +msgid "list both remote-tracking and local branches" +msgstr "liostáil brainsí cianrianaithe agus áitiúla araon" + +#: builtin/branch.c +msgid "delete fully merged branch" +msgstr "scrios brainse lánchumaisc" + +#: builtin/branch.c +msgid "delete branch (even if not merged)" +msgstr "brainse a scriosadh (fiú mura bhfuil sé cumasaithe)" + +#: builtin/branch.c +msgid "move/rename a branch and its reflog" +msgstr "brainse a bhogadh/athainmniú agus a athainmniú" + +#: builtin/branch.c +msgid "move/rename a branch, even if target exists" +msgstr "brainse a bhogadh/athainmniú, fiú má tá sprioc ann" + +#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c +msgid "do not output a newline after empty formatted refs" +msgstr "ná aschur líne nua tar éis aifeanna formáidithe folamh" + +#: builtin/branch.c +msgid "copy a branch and its reflog" +msgstr "cóipeáil brainse agus a reflog" + +#: builtin/branch.c +msgid "copy a branch, even if target exists" +msgstr "cóipeáil brainse, fiú má tá sprioc ann" + +#: builtin/branch.c +msgid "list branch names" +msgstr "liosta ainmneacha brainse" + +#: builtin/branch.c +msgid "show current branch name" +msgstr "taispeáin ainm brainse reatha" + +#: builtin/branch.c builtin/submodule--helper.c +msgid "create the branch's reflog" +msgstr "athbhreithniú na brainse a chruthú" + +#: builtin/branch.c +msgid "edit the description for the branch" +msgstr "cuir an tuairisc don bhrainse a chur in eagar" + +#: builtin/branch.c +msgid "force creation, move/rename, deletion" +msgstr "cruthú fórsa, gluaise/athainmniú, scriosadh" + +#: builtin/branch.c +msgid "print only branches that are merged" +msgstr "ach brainsí a chumasc a phriontáil" + +#: builtin/branch.c +msgid "print only branches that are not merged" +msgstr "ach brainsí nach ndéantar cumasc a phriontáil" + +#: builtin/branch.c +msgid "list branches in columns" +msgstr "liostáil brainsí i gcolúin" + +#: builtin/branch.c builtin/for-each-ref.c builtin/notes.c builtin/tag.c +msgid "object" +msgstr "réad" + +#: builtin/branch.c +msgid "print only branches of the object" +msgstr "ach brainsí den réad a phriontáil" + +#: builtin/branch.c builtin/for-each-ref.c builtin/tag.c +msgid "sorting and filtering are case insensitive" +msgstr "tá sórtáil agus scagadh neamh-íogair ó thaobh cásanna de" + +#: builtin/branch.c builtin/ls-files.c +msgid "recurse through submodules" +msgstr "athshlánú trí fho-mhodúil" + +#: builtin/branch.c builtin/for-each-ref.c builtin/ls-files.c builtin/ls-tree.c +#: builtin/tag.c builtin/verify-tag.c +msgid "format to use for the output" +msgstr "formáid le húsáid don aschur" + +#: builtin/branch.c +msgid "failed to resolve HEAD as a valid ref" +msgstr "theip ar HEAD a réiteach mar thagartha bailí" + +#: builtin/branch.c builtin/clone.c +msgid "HEAD not found below refs/heads!" +msgstr "Ní fhaightear CEAD thíos na refs/heads!" + +#: builtin/branch.c +msgid "" +"branch with --recurse-submodules can only be used if " +"submodule.propagateBranches is enabled" +msgstr "" +"ní féidir brainse le --recurse-submodules a úsáid ach amháin má tá " +"submodule.propagateBranches cumasaithe" + +#: builtin/branch.c +msgid "--recurse-submodules can only be used to create branches" +msgstr "Ní féidir --recurse-submodules a úsáid ach chun brainsí a chruthú" + +#: builtin/branch.c +msgid "branch name required" +msgstr "ainm brainse ag teastáil" + +#: builtin/branch.c +msgid "cannot give description to detached HEAD" +msgstr "ní féidir cur síos a thabhairt ar HEAD scoite" + +#: builtin/branch.c +msgid "cannot edit description of more than one branch" +msgstr "ní féidir cur síos ar níos mó ná brainse amháin a chur in eagar" + +#: builtin/branch.c +msgid "cannot copy the current branch while not on any" +msgstr "ní féidir leis an mbrainse reatha a chóipeáil cé nach bhfuil ar aon" + +#: builtin/branch.c +msgid "cannot rename the current branch while not on any" +msgstr "ní féidir leis an mbrainse reatha a athainmniú cé nach bhfuil ar aon" + +#: builtin/branch.c +msgid "too many branches for a copy operation" +msgstr "an iomarca brainsí le haghaidh oibríocht cóipeála" + +#: builtin/branch.c +msgid "too many arguments for a rename operation" +msgstr "an iomarca argóintí maidir le hoibríocht athainmnithe" + +#: builtin/branch.c +msgid "too many arguments to set new upstream" +msgstr "an iomarca argóintí chun suas an sruth nua a shocrú" + +#: builtin/branch.c +#, c-format +msgid "" +"could not set upstream of HEAD to %s when it does not point to any branch" +msgstr "" +"ní fhéadfaí suas sruth de HEAD a shocrú go %s nuair nach dtugann sé in iúl " +"go dtí aon bhrainse" + +#: builtin/branch.c +#, c-format +msgid "no such branch '%s'" +msgstr "níl brainse den sórt sin '%s'" + +#: builtin/branch.c +#, c-format +msgid "branch '%s' does not exist" +msgstr "níl brainse '%s' ann" + +#: builtin/branch.c +msgid "too many arguments to unset upstream" +msgstr "an iomarca argóintí le díshocrú suas an sruth" + +#: builtin/branch.c +msgid "could not unset upstream of HEAD when it does not point to any branch" +msgstr "" +"ní fhéadfaí a dhíshuiteáil suas an sruth den HEAD nuair nach dtugann sé in " +"iúl d'aon bhrainse" + +#: builtin/branch.c +#, c-format +msgid "branch '%s' has no upstream information" +msgstr "níl aon fhaisnéis suas sruth ag brainse '%s'" + +#: builtin/branch.c +msgid "" +"the -a, and -r, options to 'git branch' do not take a branch name.\n" +"Did you mean to use: -a|-r --list ?" +msgstr "" +"ní ghlacann na roghanna -a, agus -r, le 'git branch' ainm brainse.\n" +"An raibh sé i gceist agat úsáid a bhaint as: -a|-r --list?" + +#: builtin/branch.c +msgid "" +"the '--set-upstream' option is no longer supported. Please use '--track' or " +"'--set-upstream-to' instead" +msgstr "" +"ní thacaítear leis an rogha '--set-upstream' a thuilleadh. Úsáid '--track' " +"nó '--set-upstream-to' ina ionad" + +#: builtin/bugreport.c +msgid "git version:\n" +msgstr "leagan git:\n" + +#: builtin/bugreport.c +msgid "compiler info: " +msgstr "eolas tiomsaitheora: " + +#: builtin/bugreport.c +msgid "libc info: " +msgstr "eolas libc: " + +#: builtin/bugreport.c +msgid "not run from a git repository - no hooks to show\n" +msgstr "gan rith ó stór git - gan aon chrúcaí le taispeáint\n" + +#: builtin/bugreport.c +msgid "" +"git bugreport [(-o | --output-directory) ]\n" +" [(-s | --suffix) | --no-suffix]\n" +" [--diagnose[=]]" +msgstr "" +"git bugreport [(-o | --output-directory)]\n" +" [(-s | --iarmhír) | --no-iarmhír]\n" +" [--diagnóis [=]]" + +#: builtin/bugreport.c +msgid "" +"Thank you for filling out a Git bug report!\n" +"Please answer the following questions to help us understand your issue.\n" +"\n" +"What did you do before the bug happened? (Steps to reproduce your issue)\n" +"\n" +"What did you expect to happen? (Expected behavior)\n" +"\n" +"What happened instead? (Actual behavior)\n" +"\n" +"What's different between what you expected and what actually happened?\n" +"\n" +"Anything else you want to add:\n" +"\n" +"Please review the rest of the bug report below.\n" +"You can delete any lines you don't wish to share.\n" +msgstr "" +"Go raibh maith agat as tuarascáil fabht Git a líonadh!\n" +"Freagair na ceisteanna seo a leanas le do thoil chun cabhrú linn do cheist a " +"thuiscint\n" +"\n" +"Cad a rinne tú sular tharla an fabht? (Céimeanna chun d'eisiúint a " +"atáirgeadh)\n" +"\n" +"Cad a bhí tú ag súil go dtarlódh? (Iompar ag súil leis)\n" +"\n" +"Cad a tharla ina ionad sin? (Iompar iarbhír)\n" +"\n" +"Cad atá difriúil idir an méid a bhí súil agat leis agus cad a tharla i " +"ndáiríre\n" +"\n" +"Aon rud eile a theastaíonn uait a chur leis:\n" +"\n" +"Déan athbhreithniú ar an chuid eile den tuarascáil fabht thíos.\n" +"Is féidir leat aon línte nach dteastaíonn uait a roinnt a scriosadh.\n" + +#: builtin/bugreport.c builtin/commit.c builtin/fast-export.c builtin/rebase.c +#: parse-options.h +msgid "mode" +msgstr "mód" + +#: builtin/bugreport.c +msgid "" +"create an additional zip archive of detailed diagnostics (default 'stats')" +msgstr "" +"cruthú cartlann zip breise de dhiagnóiseach mionsonraithe ('stats' " +"réamhshocraithe)" + +#: builtin/bugreport.c +msgid "specify a destination for the bugreport file(s)" +msgstr "sonraigh ceann scríbe don chomhad (í) bugreport" + +#: builtin/bugreport.c +msgid "specify a strftime format suffix for the filename(s)" +msgstr "sonraigh iarmhír formáid strftime don ainm (í) comhaid" + +#: builtin/bugreport.c +#, c-format +msgid "unknown argument `%s'" +msgstr "argóint anaithnid `%s'" + +#: builtin/bugreport.c builtin/diagnose.c +#, c-format +msgid "could not create leading directories for '%s'" +msgstr "ní fhéadfaí eolairí tosaigh a chruthú do '%s'" + +#: builtin/bugreport.c builtin/diagnose.c +#, c-format +msgid "unable to create diagnostics archive %s" +msgstr "nach féidir cartlann diagnóiseach %s a chruthú" + +#: builtin/bugreport.c +msgid "System Info" +msgstr "Eolas Córais" + +#: builtin/bugreport.c +msgid "Enabled Hooks" +msgstr "Crúcaí Cumasaithe" + +#: builtin/bugreport.c +#, c-format +msgid "unable to write to %s" +msgstr "nach féidir a scríobh chuig %s" + +#: builtin/bugreport.c +#, c-format +msgid "Created new report at '%s'.\n" +msgstr "Cruthaíodh tuarascáil nua ag '%s'.\n" + +#: builtin/bundle.c +msgid "" +"git bundle create [-q | --quiet | --progress]\n" +" [--version=] " +msgstr "" +"cruthaigh bonn git [-q | --quiet | --progress]\n" +" [--leagan =] " + +#: builtin/bundle.c +msgid "git bundle verify [-q | --quiet] " +msgstr "fíorú beartán git [-q | --quiet] " + +#: builtin/bundle.c +msgid "git bundle list-heads [...]" +msgstr "ceannairí liosta bonn git [...]" + +#: builtin/bundle.c +msgid "git bundle unbundle [--progress] [...]" +msgstr "díbhuntáil bonn git [--progress] [...]" + +#: builtin/bundle.c +msgid "need a argument" +msgstr "teastaíonn ar góint" + +#: builtin/bundle.c builtin/pack-objects.c +msgid "do not show progress meter" +msgstr "ná taispeáin méadar dul chun cinn" + +#: builtin/bundle.c builtin/pack-objects.c +msgid "show progress meter" +msgstr "taispeáin méadar dul chun cinn" + +#: builtin/bundle.c +msgid "historical; same as --progress" +msgstr "stairiúil; mar an gcéanna le --progress" + +#: builtin/bundle.c +msgid "historical; does nothing" +msgstr "stairiúil; ní dhéanann aon rud" + +#: builtin/bundle.c +msgid "specify bundle format version" +msgstr "leagan formáid beartán a shonrú" + +#: builtin/bundle.c +msgid "Need a repository to create a bundle." +msgstr "Teastaíonn stór chun beartán a chruthú." + +#: builtin/bundle.c +msgid "do not show bundle details" +msgstr "ná taispeáin sonraí beartán" + +#: builtin/bundle.c bundle.c +msgid "need a repository to verify a bundle" +msgstr "teastaíonn stór chun beartán a fhíorú" + +#: builtin/bundle.c +#, c-format +msgid "%s is okay\n" +msgstr "%s ceart go leor\n" + +#: builtin/bundle.c +msgid "Need a repository to unbundle." +msgstr "Teastaíonn stór chun dícheangail a dhícheangal." + +#: builtin/bundle.c +msgid "Unbundling objects" +msgstr "Rudaí a dhícheangal" + +#: builtin/cat-file.c +#, c-format +msgid "cannot read object %s '%s'" +msgstr "ní féidir réad %s '%s' a léamh" + +#: builtin/cat-file.c +msgid "flush is only for --buffer mode" +msgstr "níl sruth ach le haghaidh mód --buffer" + +#: builtin/cat-file.c +msgid "empty command in input" +msgstr "ordú folamh san ionchur" + +#: builtin/cat-file.c +#, c-format +msgid "whitespace before command: '%s'" +msgstr "spás bán roimh an ordú: '%s'" + +#: builtin/cat-file.c +#, c-format +msgid "%s requires arguments" +msgstr "Teastaíonn argóintí %s" + +#: builtin/cat-file.c +#, c-format +msgid "%s takes no arguments" +msgstr "Ní ghlacann %s aon argóintí" + +#: builtin/cat-file.c +msgid "only one batch option may be specified" +msgstr "ní féidir ach rogha baisc amháin a shonrú" + +#: builtin/cat-file.c +msgid "git cat-file " +msgstr "git cat-file " + +#: builtin/cat-file.c +msgid "git cat-file (-e | -p | -t | -s) " +msgstr "git cat-file (-e | -p | -t | -s) " + +#: builtin/cat-file.c +msgid "" +"git cat-file (--textconv | --filters)\n" +" [: | --path= ]" +msgstr "" +"git cat-file (--textconv | --filters)\n" +" [: | --path= ]" + +#: builtin/cat-file.c +msgid "" +"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" +"objects]\n" +" [--buffer] [--follow-symlinks] [--unordered]\n" +" [--textconv | --filters] [-Z]" +msgstr "" +"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-" +"objects]\n" +" [--buffer] [--follow-symlinks] [--unordered]\n" +" [--textconv | --filters] [-Z]" + +#: builtin/cat-file.c +msgid "Check object existence or emit object contents" +msgstr "Seiceáil go bhfuil réad ann nó astaigh ábhar réad" + +#: builtin/cat-file.c +msgid "check if exists" +msgstr "seiceáil an bhfuil ann" + +#: builtin/cat-file.c +msgid "pretty-print content" +msgstr " ábhar priontáil álainn" + +#: builtin/cat-file.c +msgid "Emit [broken] object attributes" +msgstr "Easaigh tréithe réada [briste]" + +#: builtin/cat-file.c +msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)" +msgstr "" +"taispeáint cineál réad (ceann de 'blob', 'crann', 'tiomantas', 'tag',...)" + +#: builtin/cat-file.c +msgid "show object size" +msgstr "taispeáin méid an réad" + +#: builtin/cat-file.c builtin/log.c +msgid "use mail map file" +msgstr "úsáid comhad léarscáil ríomhphoist" + +#: builtin/cat-file.c +msgid "Batch objects requested on stdin (or --batch-all-objects)" +msgstr "Baisc rudaí a iarrtar ar stdin (nó --batch-all-objects)" + +#: builtin/cat-file.c +msgid "show full or contents" +msgstr "taispeáin iomlán nó á bhar" + +#: builtin/cat-file.c +msgid "like --batch, but don't emit " +msgstr "cosúil le --batch, ach ná astaíonn " + +#: builtin/cat-file.c +msgid "stdin is NUL-terminated" +msgstr "tá stdin foirceanta ag NUL" + +#: builtin/cat-file.c +msgid "stdin and stdout is NUL-terminated" +msgstr "tá stdin agus stdout foirceannta NUL" + +#: builtin/cat-file.c +msgid "read commands from stdin" +msgstr "léigh orduithe ó stdin" + +#: builtin/cat-file.c +msgid "with --batch[-check]: ignores stdin, batches all known objects" +msgstr "" +"le --batch [-check]: déanann neamhaird ar stdin, déanann baisceanna gach rud " +"aitheanta" + +#: builtin/cat-file.c +msgid "Change or optimize batch output" +msgstr "Athraigh nó barrfheabhsú aschur baisc" + +#: builtin/cat-file.c +msgid "buffer --batch output" +msgstr "maolán --batch baisc" + +#: builtin/cat-file.c +msgid "follow in-tree symlinks" +msgstr "lean naisc shiombailí in-chrann" + +#: builtin/cat-file.c +msgid "do not order objects before emitting them" +msgstr "ná ordaigh rudaí sula n-astaíonn tú iad" + +#: builtin/cat-file.c +msgid "" +"Emit object (blob or tree) with conversion or filter (stand-alone, or with " +"batch)" +msgstr "" +"Rud a astaíonn (blob nó crann) le comhshó nó scagaire (neamhspleách, nó le " +"baisc)" + +#: builtin/cat-file.c +msgid "run textconv on object's content" +msgstr "reáchtáil textconv ar ábhar an réad" + +#: builtin/cat-file.c +msgid "run filters on object's content" +msgstr "reáchtáil scagairí ar ábhar an rud" + +#: builtin/cat-file.c +msgid "blob|tree" +msgstr "blob | crann" + +#: builtin/cat-file.c +msgid "use a for (--textconv | --filters); Not with 'batch'" +msgstr "úsáid a le haghaidh (--textconv | --filters); Ní le 'baisc'" + +#: builtin/cat-file.c +msgid "objects filter only supported in batch mode" +msgstr "ní thacaítear scagaire rudaí ach i mód baisc" + +#: builtin/cat-file.c +#, c-format +msgid "objects filter not supported: '%s'" +msgstr "ní thacaítear le scagaire réadanna: '%s'" + +#: builtin/cat-file.c +#, c-format +msgid "'%s=<%s>' needs '%s' or '%s'" +msgstr "'%s=<%s>' teastaíonn '%s' nó '%s'" + +#: builtin/cat-file.c +msgid "path|tree-ish" +msgstr "cosán | crann-ish" + +#: builtin/cat-file.c +#, c-format +msgid "'%s' requires a batch mode" +msgstr "Éilíonn '%s' modh baisc" + +#: builtin/cat-file.c +#, c-format +msgid "'-%c' is incompatible with batch mode" +msgstr "Níl '-%c' comhoiriúnach le mód baisc" + +#: builtin/cat-file.c +msgid "batch modes take no arguments" +msgstr "ní ghlacann modhanna baisc aon argóintí" + +#: builtin/cat-file.c +#, c-format +msgid " required with '%s'" +msgstr "ag teastáil le '%s'" + +#: builtin/cat-file.c +#, c-format +msgid " required with '-%c'" +msgstr "ag teastáil le '-%c'" + +#: builtin/cat-file.c +#, c-format +msgid "only two arguments allowed in mode, not %d" +msgstr "ní cheadaítear ach dhá argóint sa mhodh, ní %d" + +#: builtin/check-attr.c +msgid "" +"git check-attr [--source ] [-a | --all | ...] [--] " +"..." +msgstr "" +"git check-attr [--source ] [-a | --all | ...] [--] " +"..." + +#: builtin/check-attr.c +msgid "" +"git check-attr --stdin [-z] [--source ] [-a | --all | ...]" +msgstr "" +"git check-attr --stdin [-z] [--source ] [-a | --all | ...]" + +#: builtin/check-attr.c +msgid "report all attributes set on file" +msgstr "tuairisc a thabhairt ar gach tréithe atá leagtha síos" + +#: builtin/check-attr.c +msgid "use .gitattributes only from the index" +msgstr "bain úsáid as .gitattributs ach ón innéacs" + +#: builtin/check-attr.c builtin/check-ignore.c builtin/hash-object.c +msgid "read file names from stdin" +msgstr "léigh ainmneacha comhaid ó stdin" + +#: builtin/check-attr.c builtin/check-ignore.c +msgid "terminate input and output records by a NUL character" +msgstr "taifid ionchuir agus aschuir a fhoirceannadh le carachtar NUL" + +#: builtin/check-attr.c +msgid "" +msgstr "" + +#: builtin/check-attr.c +msgid "which tree-ish to check attributes at" +msgstr "cén crainn le tréithe a sheiceáil ag" + +#: builtin/check-ignore.c builtin/checkout.c builtin/gc.c builtin/worktree.c +msgid "suppress progress reporting" +msgstr "cur chun cinn tuairiscithe" + +#: builtin/check-ignore.c +msgid "show non-matching input paths" +msgstr "cosáin ionchuir neamh-mheaitseála" + +#: builtin/check-ignore.c +msgid "ignore index when checking" +msgstr "neamhaird a dhéanamh ar innéacs agus" + +#: builtin/check-ignore.c +msgid "cannot specify pathnames with --stdin" +msgstr "ní féidir ainmneacha cosáin a shonrú le --stdin" + +#: builtin/check-ignore.c +msgid "-z only makes sense with --stdin" +msgstr "Ní dhéanann -z ciall ach le --stdin" + +#: builtin/check-ignore.c +msgid "no path specified" +msgstr "níl aon chosán sonraithe" + +#: builtin/check-ignore.c +msgid "--quiet is only valid with a single pathname" +msgstr "Níl --quiet bailí ach le ainm cosán amháin" + +#: builtin/check-ignore.c +msgid "cannot have both --quiet and --verbose" +msgstr "ní féidir --quiet agus --verbose araon a bheith agat" + +#: builtin/check-ignore.c +msgid "--non-matching is only valid with --verbose" +msgstr "Níl --non-matching bailí ach le --verbose" + +#: builtin/check-mailmap.c +msgid "git check-mailmap [] ..." +msgstr "git check-mailmap [] ..." + +#: builtin/check-mailmap.c +msgid "also read contacts from stdin" +msgstr "léigh teagmhálacha ó stdin freisin" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from file" +msgstr "léigh iontrálacha ríomhphoist breise ón gcomhad" + +#: builtin/check-mailmap.c +msgid "blob" +msgstr "blob" + +#: builtin/check-mailmap.c +msgid "read additional mailmap entries from blob" +msgstr "léigh iontrálacha ríomhphoist breise ó blob" + +#: builtin/check-mailmap.c +msgid "no contacts specified" +msgstr "aon teagmhálacha sonraithe" + +#: builtin/checkout--worker.c +msgid "git checkout--worker []" +msgstr "git checkout--worker []" + +#: builtin/checkout--worker.c builtin/checkout-index.c builtin/column.c +#: builtin/submodule--helper.c builtin/worktree.c +msgid "string" +msgstr "teaghrán" + +#: builtin/checkout--worker.c builtin/checkout-index.c +msgid "when creating files, prepend " +msgstr "agus comhaid á gcruthú agat, déan iarracht " + +#: builtin/checkout-index.c +msgid "git checkout-index [] [--] [...]" +msgstr "git checkout-index [] [--] [...]" + +#: builtin/checkout-index.c +msgid "stage should be between 1 and 3 or all" +msgstr "ba chóir go mbeadh an chéim idir 1 agus 3 nó gach ceann" + +#: builtin/checkout-index.c +msgid "check out all files in the index" +msgstr "seiceáil gach comhad san innéacs" + +#: builtin/checkout-index.c +msgid "do not skip files with skip-worktree set" +msgstr "ná scipeáil comhaid le tacar scip-work tree" + +#: builtin/checkout-index.c +msgid "force overwrite of existing files" +msgstr "athscríobh fórsa na gcomhaid atá ann cheana" + +#: builtin/checkout-index.c +msgid "no warning for existing files and files not in index" +msgstr "" +"gan aon rabhadh maidir le comhaid agus comhaid atá ann cheana nach bhfuil " +"san innéacs" + +#: builtin/checkout-index.c +msgid "don't checkout new files" +msgstr "ná seiceáil comhaid nua" + +#: builtin/checkout-index.c +msgid "update stat information in the index file" +msgstr "faisnéis stat a nuashonrú sa chomhad innéacs" + +#: builtin/checkout-index.c +msgid "read list of paths from the standard input" +msgstr "léigh liosta na gcosáin ón ionchur caighdeánach" + +#: builtin/checkout-index.c +msgid "write the content to temporary files" +msgstr "scríobh an t-ábhar chuig comhaid sealadacha" + +#: builtin/checkout-index.c +msgid "copy out the files from named stage" +msgstr "cóipeáil amach na comhaid ón gcéim ainmnithe" + +#: builtin/checkout.c +msgid "git checkout [] " +msgstr "git checkout [] " + +#: builtin/checkout.c +msgid "git checkout [] [] -- ..." +msgstr "git checkout [] [] --..." + +#: builtin/checkout.c +msgid "git switch [] []" +msgstr "git switch [] []" + +#: builtin/checkout.c +msgid "git restore [] [--source=] ..." +msgstr "git restore [] [--source=] ..." + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have our version" +msgstr "níl ár leagan ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have their version" +msgstr "níl a leagan ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have all necessary versions" +msgstr "níl gach leagan riachtanach ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' does not have necessary versions" +msgstr "níl leaganacha riachtanacha ag cosán '%s'" + +#: builtin/checkout.c +#, c-format +msgid "path '%s': cannot merge" +msgstr "cosán '%s': ní féidir a chumasc" + +#: builtin/checkout.c +#, c-format +msgid "Unable to add merge result for '%s'" +msgstr "Ní féidir toradh cumaisc a chur le haghaidh '%s'" + +#: builtin/checkout.c +#, c-format +msgid "Recreated %d merge conflict" +msgid_plural "Recreated %d merge conflicts" +msgstr[0] "Athchruthaíodh %d coimhlint chumasc" +msgstr[1] "Athchruthaíodh %d coinbhleachtaí chumaisc" +msgstr[2] "Athchruthaíodh %d coinbhleachtaí chumaisc" + +#: builtin/checkout.c +#, c-format +msgid "Updated %d path from %s" +msgid_plural "Updated %d paths from %s" +msgstr[0] "Nuashonraíodh %d cosán ó %s" +msgstr[1] "Nuashonraíodh %d cosán ó %s" +msgstr[2] "Nuashonraíodh %d cosán ó %s" + +#: builtin/checkout.c +#, c-format +msgid "Updated %d path from the index" +msgid_plural "Updated %d paths from the index" +msgstr[0] "Nuashonraíodh %d cosán ón innéacs" +msgstr[1] "Nuashonraíodh %d cosán ón innéacs" +msgstr[2] "Nuashonraíodh %d cosán ón innéacs" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot be used with updating paths" +msgstr "Ní féidir '%s' a úsáid le cosáin a nuashonrú" + +#: builtin/checkout.c +#, c-format +msgid "Cannot update paths and switch to branch '%s' at the same time." +msgstr "" +"Ní féidir cosáin a nuashonrú agus aistriú go brainse '%s' ag an am céanna." + +#: builtin/checkout.c +#, c-format +msgid "neither '%s' or '%s' is specified" +msgstr "níl '%s' ná '%s' sonraithe" + +#: builtin/checkout.c +#, c-format +msgid "'%s' must be used when '%s' is not specified" +msgstr "Ní mór '%s' a úsáid nuair nach sonraítear '%s'" + +#: builtin/checkout.c +#, c-format +msgid "'%s' or '%s' cannot be used with %s" +msgstr "Ní féidir '%s' nó '%s' a úsáid le %s" + +#: builtin/checkout.c +#, c-format +msgid "'%s', '%s', or '%s' cannot be used when checking out of a tree" +msgstr "" +"Ní féidir '%s', '%s', nó '%s' a úsáid agus tú ag seiceáil amach as crann" + +#: builtin/checkout.c +#, c-format +msgid "path '%s' is unmerged" +msgstr "tá cosán '%s' neamh-chomhcheangailte" + +#: builtin/checkout.c builtin/grep.c builtin/merge-tree.c builtin/reset.c +#: merge-ort.c reset.c sequencer.c tree-walk.c +#, c-format +msgid "unable to read tree (%s)" +msgstr "nach féidir crann a léamh (%s)" + +#: builtin/checkout.c +msgid "you need to resolve your current index first" +msgstr "ní mór duit d'innéacs reatha a réiteach ar dtús" + +#: builtin/checkout.c +#, c-format +msgid "" +"cannot continue with staged changes in the following files:\n" +"%s" +msgstr "" +"ní féidir leanúint ar aghaidh le hathruithe céime sna comhaid seo a leanas:\n" +"%s" + +#: builtin/checkout.c +#, c-format +msgid "Can not do reflog for '%s': %s\n" +msgstr "Ní féidir athbhreithniú a dhéanamh le haghaidh '%s': %s\n" + +#: builtin/checkout.c +msgid "HEAD is now at" +msgstr "Tá HEAD anois ag" + +#: builtin/checkout.c builtin/clone.c +msgid "unable to update HEAD" +msgstr "in ann HEAD a nuashonrú" + +#: builtin/checkout.c +#, c-format +msgid "Reset branch '%s'\n" +msgstr "Athshocraigh brainse '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid "Already on '%s'\n" +msgstr "Ar '%s' cheana féin\n" + +#: builtin/checkout.c +#, c-format +msgid "Switched to and reset branch '%s'\n" +msgstr "Aistrigh agus athshocraigh brainse '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid "Switched to a new branch '%s'\n" +msgstr "Aistrithe go brainse nua '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid "Switched to branch '%s'\n" +msgstr "Aistrithe go brainse '%s'\n" + +#: builtin/checkout.c +#, c-format +msgid " ... and %d more.\n" +msgstr " ... agus %d níos mó.\n" + +#: builtin/checkout.c +#, c-format +msgid "" +"Warning: you are leaving %d commit behind, not connected to\n" +"any of your branches:\n" +"\n" +"%s\n" +msgid_plural "" +"Warning: you are leaving %d commits behind, not connected to\n" +"any of your branches:\n" +"\n" +"%s\n" +msgstr[0] "" +"Rabhadh: tá %d tiomantas á fhágáil agat, gan cheangal le haon cheann de do " +"bhrainsí:\n" +"\n" +"%s\n" +msgstr[1] "" +"Rabhadh: tá %d tiomantas á bhfágáil agat i do dhiaidh, gan aon cheangal le " +"haon cheann de do bhrainsí:\n" +"\n" +"%s\n" +msgstr[2] "" +"Rabhadh: tá %d tiomantas á bhfágáil agat i do dhiaidh, gan aon cheangal le " +"haon cheann de do bhrainsí:\n" +"\n" +"%s\n" + +#: builtin/checkout.c +#, c-format +msgid "" +"If you want to keep it by creating a new branch, this may be a good time\n" +"to do so with:\n" +"\n" +" git branch %s\n" +"\n" +msgid_plural "" +"If you want to keep them by creating a new branch, this may be a good time\n" +"to do so with:\n" +"\n" +" git branch %s\n" +"\n" +msgstr[0] "" +"Más mian leat é a choinneáil trí bhrainse nua a chruthú, b'fhéidir gur dea-" +"am é seo chun é sin a dhéanamh le:\n" +"\n" +"git branch %s\n" +msgstr[1] "" +"Más mian leat iad a choinneáil trí bhrainse nua a chruthú, b'fhéidir gur dea-" +"am é seo chun é sin a dhéanamh le:\n" +"\n" +"git branch %s\n" +msgstr[2] "" +"Más mian leat iad a choinneáil trí bhrainse nua a chruthú, b'fhéidir gur dea-" +"am é seo chun é sin a dhéanamh le:\n" +"\n" +"git branch %s\n" + +#: builtin/checkout.c +msgid "internal error in revision walk" +msgstr "earráid inmheánach i dsiúlóid" + +#: builtin/checkout.c +msgid "Previous HEAD position was" +msgstr "Bhí post CEAD roimhe seo" + +#: builtin/checkout.c +msgid "You are on a branch yet to be born" +msgstr "Tá tú ar bhrainse nach rugadh fós" + +#: builtin/checkout.c +#, c-format +msgid "" +"'%s' could be both a local file and a tracking branch.\n" +"Please use -- (and optionally --no-guess) to disambiguate" +msgstr "" +"D'fhéadfadh '%s' a bheith ina chomhad áitiúil agus ina bhrainse rianaithe " +"araon.\n" +"Úsáid le do thoil -- (agus go roghnach --no-guess) chun a dhíbhriú" + +#: builtin/checkout.c +msgid "" +"If you meant to check out a remote tracking branch on, e.g. 'origin',\n" +"you can do so by fully qualifying the name with the --track option:\n" +"\n" +" git checkout --track origin/\n" +"\n" +"If you'd like to always have checkouts of an ambiguous prefer\n" +"one remote, e.g. the 'origin' remote, consider setting\n" +"checkout.defaultRemote=origin in your config." +msgstr "" +"Má bhí sé i gceist agat brainse cianrianaithe a sheiceáil ar, e.g. " +"'origin',\n" +"is féidir leat é sin a dhéanamh tríd an ainm a cháiliú go hiomlán leis an " +"rogha --track:\n" +"\n" +" git checkout --track origin/\n" +"\n" +"Más mian leat seiceálacha débhríoch a bheith agat i gcónaí is fearr " +"leat\n" +"iargúlta amháin, e.g. an iargúlta 'origin', smaoinigh ar shocrú\n" +"checkout.defaultRemote=origin i do chumraíocht." + +#: builtin/checkout.c +#, c-format +msgid "'%s' matched multiple (%d) remote tracking branches" +msgstr "Mheaitseáil '%s' roinnt (%d) brainsí rianaithe iargúlta" + +#: builtin/checkout.c +msgid "only one reference expected" +msgstr "níl ach tagairt amháin ag súil leis" + +#: builtin/checkout.c +#, c-format +msgid "only one reference expected, %d given." +msgstr "níl ach tagairt amháin ag súil leis, %d tugtha." + +#: builtin/checkout.c builtin/worktree.c +#, c-format +msgid "invalid reference: %s" +msgstr "tagairt neamhbhailí: %s" + +#: builtin/checkout.c +#, c-format +msgid "reference is not a tree: %s" +msgstr "ní crann é tagairt: %s" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got tag '%s'" +msgstr "táthar ag súil le brainse, faightear tag '%s'" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got remote branch '%s'" +msgstr "táthar ag súil le brainse, fuair brainse iargúlta '%s'" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got '%s'" +msgstr "táthar ag súil le brainse, fuair '%s'" + +#: builtin/checkout.c +#, c-format +msgid "a branch is expected, got commit '%s'" +msgstr "táthar ag súil le brainse, fuair sé tiomantas '%s'" + +#: builtin/checkout.c +msgid "" +"If you want to detach HEAD at the commit, try again with the --detach option." +msgstr "" +"Más mian leat HEAD a dhícheangal ag an tiomantas, déan iarracht arís leis an " +"rogha --detach." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while merging\n" +"Consider \"git merge --quit\" or \"git worktree add\"." +msgstr "" +"ní féidir brainse a athrú agus cumasc á dhéanamh\n" +"Smaoinigh ar \"git merge --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch in the middle of an am session\n" +"Consider \"git am --quit\" or \"git worktree add\"." +msgstr "" +"ní féidir brainse a athrú i lár seisiún am\n" +"Smaoinigh ar \"git am --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while rebasing\n" +"Consider \"git rebase --quit\" or \"git worktree add\"." +msgstr "" +"ní féidir brainse a athrú agus athbhunú á dhéanamh\n" +"Smaoinigh ar \"git rebase --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while cherry-picking\n" +"Consider \"git cherry-pick --quit\" or \"git worktree add\"." +msgstr "" +"ní féidir brainse a athrú agus tú ag cherry-picking\n" +"Smaoinigh ar \"git cherry-pick --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "" +"cannot switch branch while reverting\n" +"Consider \"git revert --quit\" or \"git worktree add\"." +msgstr "" +"ní féidir brainse a athrú agus aisiompú á dhéanamh\n" +"Smaoinigh ar \"git revert --quit\" nó \"git worktree add\"." + +#: builtin/checkout.c +msgid "you are switching branch while bisecting" +msgstr "tá tú ag athrú brainse agus tú ag déileáil" + +#: builtin/checkout.c +msgid "paths cannot be used with switching branches" +msgstr "ní féidir cosáin a úsáid le brainsí a athrú" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot be used with switching branches" +msgstr "Ní féidir '%s' a úsáid le brainsí a athrú" + +#: builtin/checkout.c +#, c-format +msgid "'%s' needs the paths to check out" +msgstr "Teastaíonn '%s' na cosáin chun seiceáil" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot be used with '%s'" +msgstr "Ní féidir '%s' a úsáid le '%s'" + +#: builtin/checkout.c +#, c-format +msgid "'%s' cannot take " +msgstr "Ní féidir '%s' a ghlacadh " + +#: builtin/checkout.c +#, c-format +msgid "Cannot switch branch to a non-commit '%s'" +msgstr "Ní féidir brainse a aistriú go '%s' neamh-thiomanta" + +#: builtin/checkout.c +msgid "missing branch or commit argument" +msgstr "brainse ar iarraidh nó argóint a dhéanamh" + +#: builtin/checkout.c +#, c-format +msgid "unknown conflict style '%s'" +msgstr "stíl choimhlinte anaithnid '%s'" + +#: builtin/checkout.c +msgid "perform a 3-way merge with the new branch" +msgstr "cumasc 3 bhealach a dhéanamh leis an mbrainse nua" + +#: builtin/checkout.c builtin/log.c builtin/range-diff.c parse-options.h +msgid "style" +msgstr "stíl" + +#: builtin/checkout.c +msgid "conflict style (merge, diff3, or zdiff3)" +msgstr "stíl choimhlinte (cumaisc, diff3, nó zdiff3)" + +#: builtin/checkout.c builtin/worktree.c +msgid "detach HEAD at named commit" +msgstr "dícheangail HEAD ag an tiomnú ainmnithe" + +#: builtin/checkout.c +msgid "force checkout (throw away local modifications)" +msgstr "seiceáil fórsa (caith modhnuithe áitiúla)" + +#: builtin/checkout.c +msgid "new-branch" +msgstr "brainse-nua" + +#: builtin/checkout.c +msgid "new unborn branch" +msgstr "brainse nua gan breith" + +#: builtin/checkout.c builtin/merge.c +msgid "update ignored files (default)" +msgstr "nuashonrú comhaid a dhéantar neamhaird orthu" + +#: builtin/checkout.c +msgid "do not check if another worktree is using this branch" +msgstr "" +"ná seiceáil an bhfuil crann oibre eile á úsáid ag baint úsáide as an " +"mbrainse seo" + +#: builtin/checkout.c +msgid "checkout our version for unmerged files" +msgstr "seiceáil ár leagan le haghaidh comhaid neamh-chumasaithe" + +#: builtin/checkout.c +msgid "checkout their version for unmerged files" +msgstr "seiceáil a leagan le haghaidh comhaid neamh-chumasaithe" + +#: builtin/checkout.c +msgid "do not limit pathspecs to sparse entries only" +msgstr "ná teorainn le speisiúintí cosáin le hiontrálacha neamhchoitianta" + +#: builtin/checkout.c +#, c-format +msgid "options '-%c', '-%c', and '%s' cannot be used together" +msgstr "ní féidir na roghanna '-%c', '-%c', agus '%s' a úsáid le chéile" + +#: builtin/checkout.c +msgid "--track needs a branch name" +msgstr "--track tá ainm brainse ag teastáil" + +#: builtin/checkout.c +#, c-format +msgid "missing branch name; try -%c" +msgstr "ainm brainse ar iarraidh; iarracht -%c" + +#: builtin/checkout.c +#, c-format +msgid "could not resolve %s" +msgstr "ní fhéadfaí %s a réiteach" + +#: builtin/checkout.c +msgid "invalid path specification" +msgstr "sonraíocht cosáin nebhail" + +#: builtin/checkout.c +#, c-format +msgid "'%s' is not a commit and a branch '%s' cannot be created from it" +msgstr "Ní tiomantas é '%s' agus ní féidir brainse '%s' a chruthú uaidh" + +#: builtin/checkout.c +#, c-format +msgid "git checkout: --detach does not take a path argument '%s'" +msgstr "git checkout: --detach ní ghlacann argóint cosáin '%s'" + +#: builtin/checkout.c +msgid "" +"git checkout: --ours/--theirs, --force and --merge are incompatible when\n" +"checking out of the index." +msgstr "" +"git checkout: --ours/--theirs, --force agus --merge neamhoiriúnach nuair\n" +"seiceáil amach as an innéacs." + +#: builtin/checkout.c +msgid "you must specify path(s) to restore" +msgstr "ní mór duit cosáin(í) a shonrú chun athchóiriú" + +#: builtin/checkout.c builtin/clone.c builtin/remote.c builtin/replay.c +#: builtin/submodule--helper.c builtin/worktree.c +msgid "branch" +msgstr "brainse" + +#: builtin/checkout.c +msgid "create and checkout a new branch" +msgstr "brainse nua a chruthú agus a sheiceáil" + +#: builtin/checkout.c +msgid "create/reset and checkout a branch" +msgstr "cruthaigh/athshocraigh agus seiceáil amach brainse" + +#: builtin/checkout.c +msgid "create reflog for new branch" +msgstr "cruthú reflog do bhrainse nua" + +#: builtin/checkout.c +msgid "second guess 'git checkout ' (default)" +msgstr "an dara tuairim 'git check '(réamhshocraithe)" + +#: builtin/checkout.c +msgid "use overlay mode (default)" +msgstr "úsáid modh forleagtha (réamhshocraithe)" + +#: builtin/checkout.c +msgid "create and switch to a new branch" +msgstr "cruthú agus aistrigh go brainse nua" + +#: builtin/checkout.c +msgid "create/reset and switch to a branch" +msgstr "cruthú/athshocraigh agus aistrigh go brainse" + +#: builtin/checkout.c +msgid "second guess 'git switch '" +msgstr "buille faoi thuairim eile 'git switch '" + +#: builtin/checkout.c +msgid "throw away local modifications" +msgstr "modhnuithe áitiúla a chaitheamh" + +#: builtin/checkout.c +msgid "which tree-ish to checkout from" +msgstr "cén crainn le seiceáil uaidh" + +#: builtin/checkout.c +msgid "restore the index" +msgstr "an t-innéacs a chur ar ais" + +#: builtin/checkout.c +msgid "restore the working tree (default)" +msgstr "an crann oibre a chur ar ais (réamhshocraithe)" + +#: builtin/checkout.c +msgid "ignore unmerged entries" +msgstr "neamhaird a dhéanamh ar iontrálacha" + +#: builtin/checkout.c +msgid "use overlay mode" +msgstr "úsáid modh forleagtha" + +#: builtin/clean.c +msgid "" +"git clean [-d] [-f] [-i] [-n] [-q] [-e ] [-x | -X] [--] " +"[...]" +msgstr "" +"git glan [-d] [-f] [-i] [-n] [-q] [-e] [- x | -X] [--] " +"[...]" + +#: builtin/clean.c +#, c-format +msgid "Removing %s\n" +msgstr "Ag baint %s\n" + +#: builtin/clean.c +#, c-format +msgid "Would remove %s\n" +msgstr "Bainfeadh %s\n" + +#: builtin/clean.c +#, c-format +msgid "Skipping repository %s\n" +msgstr "Ag scipeáil an stóras %s\n" + +#: builtin/clean.c +#, c-format +msgid "Would skip repository %s\n" +msgstr "Scaipfeadh stóras %s\n" + +#: builtin/clean.c midx.c +#, c-format +msgid "failed to remove %s" +msgstr "theip ar %s a bhaint" + +#: builtin/clean.c +#, c-format +msgid "could not lstat %s\n" +msgstr "ní fhéadfaí lstat %s\n" + +#: builtin/clean.c +msgid "Refusing to remove current working directory\n" +msgstr "Ag diúltú an t-eolaire oibre reatha a bhaint\n" + +#: builtin/clean.c +msgid "Would refuse to remove current working directory\n" +msgstr "Dhiúltódh sé/sí an t-eolaire oibre reatha a bhaint\n" + +#: builtin/clean.c +#, c-format +msgid "" +"Prompt help:\n" +"1 - select a numbered item\n" +"foo - select item based on unique prefix\n" +" - (empty) select nothing\n" +msgstr "" +"Cabhair pras:\n" +"1 - roghnaigh mír uimhrithe\n" +"foo - roghnaigh mír bunaithe ar réimír uathúil\n" +" - (folamh) roghnaigh aon rud\n" + +#: builtin/clean.c +#, c-format +msgid "" +"Prompt help:\n" +"1 - select a single item\n" +"3-5 - select a range of items\n" +"2-3,6-9 - select multiple ranges\n" +"foo - select item based on unique prefix\n" +"-... - unselect specified items\n" +"* - choose all items\n" +" - (empty) finish selecting\n" +msgstr "" +"Cabhair pras:\n" +"1 - roghnaigh mír amháin\n" +"3-5 - roghnaigh raon earraí\n" +"2-3,6-9 - roghnaigh raonta iolracha\n" +"foo - roghnaigh mír bunaithe ar réimír uathúil\n" +"-... - míreanna sonraithe a dhíroghnú\n" +"* - roghnaigh gach earra\n" +" - (folamh) bailchríoch a roghnú\n" + +#: builtin/clean.c +#, c-format +msgid "Huh (%s)?\n" +msgstr "Huh (%s)?\n" + +#: builtin/clean.c +#, c-format +msgid "Input ignore patterns>> " +msgstr "Patrúin neamhaird ionchuir >> " + +#: builtin/clean.c +#, c-format +msgid "WARNING: Cannot find items matched by: %s" +msgstr "RABHADH: Ní féidir míreanna a mheaitseáil le: %s a aimsiú" + +#: builtin/clean.c +msgid "Select items to delete" +msgstr "Roghnaigh míreanna le scriosadh" + +#. TRANSLATORS: Make sure to keep [y/N] as is +#: builtin/clean.c +#, c-format +msgid "Remove %s [y/N]? " +msgstr "Bain %s [y/N]? " + +#: builtin/clean.c +msgid "" +"clean - start cleaning\n" +"filter by pattern - exclude items from deletion\n" +"select by numbers - select items to be deleted by numbers\n" +"ask each - confirm each deletion (like \"rm -i\")\n" +"quit - stop cleaning\n" +"help - this screen\n" +"? - help for prompt selection" +msgstr "" +"glan - tosú ag glanadh\n" +"scagadh de réir patrún - eisiamh míreanna ó scriosadh\n" +"roghnaigh de réir uimhreacha - roghnaigh míreanna atá le scriosadh de réir\n" +"fiafraigh gach ceann - deimhnigh gach scriosadh (cosúil le “rm -i”)\n" +"scor - stop glanadh\n" +"cabhair - an scáileán seo\n" +"? - cabhair le haghaidh roghnú pras" + +#: builtin/clean.c +msgid "Would remove the following item:" +msgid_plural "Would remove the following items:" +msgstr[0] "Bhainfeadh sé an mhír seo a leanas:" +msgstr[1] "Bainfí na míreanna seo a leanas:" +msgstr[2] "Bainfí na míreanna seo a leanas:" + +#: builtin/clean.c +msgid "No more files to clean, exiting." +msgstr "Níl aon níos mó comhaid le glanadh, ag imeacht amach." + +#: builtin/clean.c +msgid "do not print names of files removed" +msgstr "ná priontáil ainmneacha na gcomhaid a bhaintear" + +#: builtin/clean.c +msgid "force" +msgstr "fórsa" + +#: builtin/clean.c +msgid "interactive cleaning" +msgstr "glanadh idirghní" + +#: builtin/clean.c +msgid "remove whole directories" +msgstr "bain eolairí iomlána" + +#: builtin/clean.c builtin/config.c builtin/describe.c builtin/grep.c +#: builtin/log.c builtin/ls-files.c builtin/name-rev.c builtin/pack-refs.c +#: builtin/show-ref.c ref-filter.h +msgid "pattern" +msgstr "patrún" + +#: builtin/clean.c +msgid "add to ignore rules" +msgstr "cuir leis na rialacha a neamhaird" + +#: builtin/clean.c +msgid "remove ignored files, too" +msgstr "bain comhaid a neamhaird orthu, freisin" + +#: builtin/clean.c +msgid "remove only ignored files" +msgstr "bain ach comhaid a neamhaird orthu" + +#: builtin/clean.c +msgid "clean.requireForce is true and -f not given: refusing to clean" +msgstr "tá clean.requireForce fíor agus ní thugtar -f: diúltú glanadh" + +#: builtin/clone.c +#, c-format +msgid "info: Could not add alternate for '%s': %s\n" +msgstr "eolas: Ní féidir malartach a chur le haghaidh '%s': %s\n" + +#: builtin/clone.c builtin/diff.c builtin/rm.c grep.c setup.c +#, c-format +msgid "failed to stat '%s'" +msgstr "theip ar '%s' a stáil" + +#: builtin/clone.c +#, c-format +msgid "%s exists and is not a directory" +msgstr "Tá %s ann agus ní eolaire é" + +#: builtin/clone.c +#, c-format +msgid "'%s' is a symlink, refusing to clone with --local" +msgstr "Is nasc comhsheasmhach é '%s', ag diúltú clónú le --local" + +#: builtin/clone.c +#, c-format +msgid "failed to start iterator over '%s'" +msgstr "theip ar an iterator a thosú thar '%s'" + +#: builtin/clone.c +#, c-format +msgid "symlink '%s' exists, refusing to clone with --local" +msgstr "tá nasc symlink '%s' ann, ag diúltú clónú le --local" + +#: builtin/clone.c compat/precompose_utf8.c +#, c-format +msgid "failed to unlink '%s'" +msgstr "theip ar '%s' a dhínascadh" + +#: builtin/clone.c +#, c-format +msgid "hardlink cannot be checked at '%s'" +msgstr "ní féidir crua-nasc a sheiceáil ag '%s'" + +#: builtin/clone.c +#, c-format +msgid "hardlink different from source at '%s'" +msgstr "crua-nasc difriúil ó fhoinse ag '%s'" + +#: builtin/clone.c +#, c-format +msgid "failed to create link '%s'" +msgstr "theip ar nasc '%s' a chruthú" + +#: builtin/clone.c +#, c-format +msgid "failed to copy file to '%s'" +msgstr "theip ar chomhad a chóipeáil chuig '%s'" + +#: builtin/clone.c refs/files-backend.c +#, c-format +msgid "failed to iterate over '%s'" +msgstr "theip ar athrá thar '%s'" + +#: builtin/clone.c +#, c-format +msgid "done.\n" +msgstr "déanta.\n" + +#: builtin/clone.c +msgid "" +"Clone succeeded, but checkout failed.\n" +"You can inspect what was checked out with 'git status'\n" +"and retry with 'git restore --source=HEAD :/'\n" +msgstr "" +"D'éirigh le clón, ach theip ar an tseiceáil.\n" +"Is féidir leat iniúchadh a dhéanamh ar an méid a sheiceáladh le 'git " +"status'\n" +"agus déan iarracht arís le 'git restore --source=HEAD : /'\n" + +#: builtin/clone.c fetch-pack.c +msgid "remote did not send all necessary objects" +msgstr "níor sheol iargúlta gach rud riachtanach" + +#: builtin/clone.c +#, c-format +msgid "unable to update %s" +msgstr "nach féidir %s a nuashonrú" + +#: builtin/clone.c +msgid "failed to initialize sparse-checkout" +msgstr "theip ar sheiceáil éagsúil a thosú" + +#: builtin/clone.c +msgid "remote HEAD refers to nonexistent ref, unable to checkout" +msgstr "" +"tagraíonn iargúlta HEAD do thagartha nach bhfuil ann, nach féidir a sheiceáil" + +#: builtin/clone.c +msgid "unable to checkout working tree" +msgstr "in ann crann oibre a sheiceáil" + +#: builtin/clone.c +msgid "unable to write parameters to config file" +msgstr "in ann paraiméadair a scríobh chuig comhad cumraithe" + +#: builtin/clone.c +msgid "cannot repack to clean up" +msgstr "ní féidir athphacáil chun glanadh" + +#: builtin/clone.c +msgid "cannot unlink temporary alternates file" +msgstr "ní féidir le comhad malartacha sealadacha a dhínascadh" + +#: builtin/clone.c +msgid "don't clone shallow repository" +msgstr "ná clóin stór éadomhain" + +#: builtin/clone.c +msgid "don't create a checkout" +msgstr "ná cruthaigh seiceáil" + +#: builtin/clone.c builtin/init-db.c +msgid "create a bare repository" +msgstr "stóras lom a chruthú" + +#: builtin/clone.c +msgid "create a mirror repository (implies --bare)" +msgstr "stóras scátháin a chruthú (tugann le tuiscint --bare)" + +#: builtin/clone.c +msgid "to clone from a local repository" +msgstr "a chlónú ó stór áitiúil" + +#: builtin/clone.c +msgid "don't use local hardlinks, always copy" +msgstr "ná húsáid crua-naisc áitiúla, cóipeáil i gcónaí" + +#: builtin/clone.c +msgid "setup as shared repository" +msgstr "socrú mar stór roinnte" + +#: builtin/clone.c +msgid "pathspec" +msgstr "sonraíocht chosáin" + +#: builtin/clone.c +msgid "initialize submodules in the clone" +msgstr "fo-mhodúil a thionscnamh sa chlón" + +#: builtin/clone.c +msgid "number of submodules cloned in parallel" +msgstr "líon na bhfo-mhodúil atá clónaithe go comhthreomhar" + +#: builtin/clone.c builtin/init-db.c +msgid "template-directory" +msgstr "eolaire teimpléad" + +#: builtin/clone.c builtin/init-db.c +msgid "directory from which templates will be used" +msgstr "eolaire as a n-úsáidfear teimpléid" + +#: builtin/clone.c builtin/submodule--helper.c +msgid "reference repository" +msgstr "stór tagartha" + +#: builtin/clone.c builtin/submodule--helper.c +msgid "use --reference only while cloning" +msgstr "bain úsáid as --reference amháin agus tú ag clónú" + +#: builtin/clone.c builtin/column.c builtin/fmt-merge-msg.c builtin/init-db.c +#: builtin/merge-file.c builtin/merge.c builtin/pack-objects.c builtin/repack.c +#: builtin/submodule--helper.c t/helper/test-simple-ipc.c +msgid "name" +msgstr "ainm" + +#: builtin/clone.c +msgid "use instead of 'origin' to track upstream" +msgstr "úsáid in ionad 'origin' chun suas an sruth a rianú" + +#: builtin/clone.c +msgid "checkout instead of the remote's HEAD" +msgstr "seiceáil in ionad CEAD an iargúlta" + +#: builtin/clone.c +msgid "clone single revision and check out" +msgstr "clónáil athbhreithniú aonair agus seiceáil amach" + +#: builtin/clone.c +msgid "path to git-upload-pack on the remote" +msgstr "cosán chuig git-upload-pack ar an gcianrialtán" + +#: builtin/clone.c builtin/fetch.c builtin/pull.c +msgid "depth" +msgstr "doimhneacht" + +#: builtin/clone.c +msgid "create a shallow clone of that depth" +msgstr "clón éadomhain den doimhneacht sin a chruthú" + +#: builtin/clone.c +msgid "create a shallow clone since a specific time" +msgstr "clón éadrom a chruthú ó am ar leith" + +#: builtin/clone.c builtin/fetch.c builtin/pull.c +msgid "ref" +msgstr "tagairt" + +#: builtin/clone.c builtin/fetch.c builtin/pull.c +msgid "deepen history of shallow clone, excluding ref" +msgstr "stair an chlóin éadomhain a dhoimhniú, gan tagairt" + +#: builtin/clone.c builtin/submodule--helper.c +msgid "clone only one branch, HEAD or --branch" +msgstr "clóin ach brainse amháin, HEAD nó --branch" + +#: builtin/clone.c +msgid "clone tags, and make later fetches not to follow them" +msgstr "clibeanna clóin, agus tógáil níos déanaí a dhéanamh gan iad a leanúint" + +#: builtin/clone.c +msgid "any cloned submodules will be shallow" +msgstr "beidh aon fho-mhodúil clónaithe éadrom" + +#: builtin/clone.c builtin/init-db.c +msgid "gitdir" +msgstr "gitdir" + +#: builtin/clone.c builtin/init-db.c +msgid "separate git dir from working tree" +msgstr "git dir ar leithligh ó chrann oibre" + +#: builtin/clone.c builtin/init-db.c builtin/submodule--helper.c +msgid "specify the reference format to use" +msgstr "sonraigh an fhormáid tagartha le húsáid" + +#: builtin/clone.c +msgid "key=value" +msgstr "eochair=luach" + +#: builtin/clone.c +msgid "set config inside the new repository" +msgstr "socraigh cumraíocht taobh istigh den stór nua" + +#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c +#: builtin/push.c builtin/send-pack.c +msgid "server-specific" +msgstr "freastalaí-shonrach" + +#: builtin/clone.c builtin/fetch.c builtin/ls-remote.c builtin/pull.c +#: builtin/push.c builtin/send-pack.c +msgid "option to transmit" +msgstr "rogha a tharchur" + +#: builtin/clone.c +msgid "apply partial clone filters to submodules" +msgstr "cuir scagairí clóin páirteacha i bhfeidhm" + +#: builtin/clone.c +msgid "any cloned submodules will use their remote-tracking branch" +msgstr "úsáidfidh aon fho-mhodúil clónaithe a mbrainse cianrianaithe" + +#: builtin/clone.c +msgid "initialize sparse-checkout file to include only files at root" +msgstr "" +"comhad seiceála neamhchoitianta a thosú chun comhaid amháin a áireamh ag " +"fréamh" + +#: builtin/clone.c +msgid "uri" +msgstr "uri" + +#: builtin/clone.c +msgid "a URI for downloading bundles before fetching from origin remote" +msgstr "" +"a URI chun cuachtaí a íoslódáil sula n-iarrtar iad ó chianchéim tionscnaimh" + +#: builtin/clone.c +msgid "git clone [] [--] []" +msgstr "git clone [] [--] []" + +#: builtin/clone.c +msgid "Too many arguments." +msgstr "An iomarca argóintí." + +#: builtin/clone.c scalar.c +msgid "You must specify a repository to clone." +msgstr "Ní mór duit stór a shonrú le clónú." + +#: builtin/clone.c builtin/init-db.c builtin/refs.c builtin/submodule--helper.c +#: setup.c +#, c-format +msgid "unknown ref storage format '%s'" +msgstr "formáid stórála tagartha anaithnid '%s'" + +#: builtin/clone.c +#, c-format +msgid "repository '%s' does not exist" +msgstr "níl an stóras '%s' ann" + +#: builtin/clone.c builtin/fetch.c +#, c-format +msgid "depth %s is not a positive number" +msgstr "ní uimhir dhearfach é doimhneacht %s" + +#: builtin/clone.c +#, c-format +msgid "destination path '%s' already exists and is not an empty directory." +msgstr "tá cosán ceann scríbe '%s' ann cheana féin agus ní eolaire folamh é." + +#: builtin/clone.c +#, c-format +msgid "repository path '%s' already exists and is not an empty directory." +msgstr "tá cosán stórais '%s' ann cheana féin agus ní eolaire folamh é." + +#: builtin/clone.c +#, c-format +msgid "working tree '%s' already exists." +msgstr "tá crann oibre '%s' ann cheana féin." + +#: builtin/clone.c builtin/difftool.c builtin/log.c builtin/worktree.c +#, c-format +msgid "could not create leading directories of '%s'" +msgstr "ní fhéadfaí eolairí tosaigh de '%s' a chruthú" + +#: builtin/clone.c +#, c-format +msgid "could not create work tree dir '%s'" +msgstr "ní fhéadfaí crann oibre a chruthú dir '%s'" + +#: builtin/clone.c +#, c-format +msgid "Cloning into bare repository '%s'...\n" +msgstr "Clónáil isteach i stóras lom '%s'...\n" + +#: builtin/clone.c +#, c-format +msgid "Cloning into '%s'...\n" +msgstr "Clónáil isteach '%s'...\n" + +#: builtin/clone.c +msgid "" +"clone --recursive is not compatible with both --reference and --reference-if-" +"able" +msgstr "" +"níl clón --recursive comhoiriúnach le --reference agus --reference-if-able" + +#: builtin/clone.c builtin/remote.c +#, c-format +msgid "'%s' is not a valid remote name" +msgstr "Ní ainm iargúlta bailí é '%s'" + +#: builtin/clone.c +msgid "--depth is ignored in local clones; use file:// instead." +msgstr "" +"--depth déantar neamhaird de i gclóin áitiúla; bain úsáid as comhad:// ina " +"ionad." + +#: builtin/clone.c +msgid "--shallow-since is ignored in local clones; use file:// instead." +msgstr "" +"--shallow-since déantar neamhaird de i gclóin áitiúla; bain úsáid as file:// " +"ina ionad." + +#: builtin/clone.c +msgid "--shallow-exclude is ignored in local clones; use file:// instead." +msgstr "" +"--shallow-exclude déantar neamhaird de i gclóin áitiúla; bain úsáid as " +"file:// ina ionad." + +#: builtin/clone.c +msgid "--filter is ignored in local clones; use file:// instead." +msgstr "" +"--filter déantar neamhaird de i gclóin áitiúla; bain úsáid as file:// ina " +"ionad." + +#: builtin/clone.c fetch-pack.c +msgid "source repository is shallow, reject to clone." +msgstr "tá stóras foinse éadrom, diúltaigh clóin." + +#: builtin/clone.c +msgid "source repository is shallow, ignoring --local" +msgstr "tá stóras foinse éadrom, ag neamhaird a dhéanamh ar --local" + +#: builtin/clone.c +msgid "--local is ignored" +msgstr "--local déantar neamhaird de" + +#: builtin/clone.c +msgid "cannot clone from filtered bundle" +msgstr "ní féidir clónú ó bhearta scagtha" + +#: builtin/clone.c +msgid "failed to initialize the repo, skipping bundle URI" +msgstr "theip ar an repo a thionscnamh, ag scipeáil URI beartán" + +#: builtin/clone.c +#, c-format +msgid "failed to fetch objects from bundle URI '%s'" +msgstr "theip ar rudaí a fháil ó URI '%s'" + +#: builtin/clone.c +msgid "failed to fetch advertised bundles" +msgstr "theip orthu beartáin fógraithe a fháil" + +#: builtin/clone.c +msgid "remote transport reported error" +msgstr "earráid tuairiscithe ar iompar" + +#: builtin/clone.c +#, c-format +msgid "Remote branch %s not found in upstream %s" +msgstr "Níor aimsíodh brainse iargúlta %s i suas sruth %s" + +#: builtin/clone.c +#, c-format +msgid "Remote revision %s not found in upstream %s" +msgstr "Ní aimsíodh athbhreithniú iargúlta %s i suas sruth %s" + +#: builtin/clone.c +msgid "You appear to have cloned an empty repository." +msgstr "Is cosúil gur chlónaigh tú stór folamh." + +#: builtin/column.c +msgid "git column []" +msgstr "colún git []" + +#: builtin/column.c +msgid "lookup config vars" +msgstr "earraí cumraíochta cuardaigh" + +#: builtin/column.c +msgid "layout to use" +msgstr "leagan amach le húsáid" + +#: builtin/column.c +msgid "maximum width" +msgstr "leithead uasta" + +#: builtin/column.c +msgid "padding space on left border" +msgstr "spás padding ar an teorainn chlé" + +#: builtin/column.c +msgid "padding space on right border" +msgstr "spás padding ar an teorainn dheis" + +#: builtin/column.c +msgid "padding space between columns" +msgstr "spás padding idir colúin" + +#: builtin/column.c +#, c-format +msgid "%s must be non-negative" +msgstr "Caithfidh %s a bheith neamh-diúltach" + +#: builtin/column.c +msgid "--command must be the first argument" +msgstr "Ní mór gurb é --command an chéad argóint" + +#: builtin/commit-graph.c +msgid "" +"git commit-graph verify [--object-dir ] [--shallow] [--[no-]progress]" +msgstr "" +"git commit-graph verify [--object-dir ] [--shallow] [--[no-]progress]" + +#: builtin/commit-graph.c +msgid "" +"git commit-graph write [--object-dir ] [--append]\n" +" [--split[=]] [--reachable | --stdin-packs | " +"--stdin-commits]\n" +" [--changed-paths] [--[no-]max-new-filters ] [--" +"[no-]progress]\n" +" " +msgstr "" +"git commit-graph write [--object-dir ] [--append]\n" +" [--split[=]] [--reachable | --stdin-packs | " +"--stdin-commits]\n" +" [--changed-paths] [--[no-]max-new-filters ] [--" +"[no-]progress]\n" +" " + +#: builtin/commit-graph.c builtin/fetch.c builtin/gc.c builtin/log.c +#: builtin/repack.c +msgid "dir" +msgstr "redir" + +#: builtin/commit-graph.c +msgid "the object directory to store the graph" +msgstr "an eolaire réada chun an graf a stóráil" + +#: builtin/commit-graph.c +msgid "if the commit-graph is split, only verify the tip file" +msgstr "má tá an graf coimite scoilte, ní fhíoraigh ach an comhad leid" + +#: builtin/commit-graph.c +#, c-format +msgid "Could not open commit-graph '%s'" +msgstr "Níor féidir graf coimisiúnaithe '%s' a oscailt" + +#: builtin/commit-graph.c +#, c-format +msgid "could not open commit-graph chain '%s'" +msgstr "ní fhéadfaí slabhra coimisi-graf '%s' a oscailt" + +#: builtin/commit-graph.c +#, c-format +msgid "unrecognized --split argument, %s" +msgstr "argóint --split gan aithint, %s" + +#: builtin/commit-graph.c +#, c-format +msgid "unexpected non-hex object ID: %s" +msgstr "id réada neamh-heicsidheachúlach gan choinne: %s" + +#: builtin/commit-graph.c +#, c-format +msgid "invalid object: %s" +msgstr "réad neamhbhailí: %s" + +#: builtin/commit-graph.c parse-options-cb.c +#, c-format +msgid "option `%s' expects a numerical value" +msgstr "tá rogha `%s' ag súil le luach uimhriúil" + +#: builtin/commit-graph.c +msgid "start walk at all refs" +msgstr "tosú ag siúl ag gach ceann" + +#: builtin/commit-graph.c +msgid "scan pack-indexes listed by stdin for commits" +msgstr "" +"scanadh innéacsanna pacáiste atá liostaithe ag stdin le haghaidh gealltanais" + +#: builtin/commit-graph.c +msgid "start walk at commits listed by stdin" +msgstr "tosú ag siúl ag gealltanais atá liostaithe ag stdin" + +#: builtin/commit-graph.c +msgid "include all commits already in the commit-graph file" +msgstr "" +"áireamh na gealltanais go léir cheana féin sa chomhad gráf coimisiúnaithe" + +#: builtin/commit-graph.c +msgid "enable computation for changed paths" +msgstr "ríomh a chumasú le haghaidh cosáin athraithe" + +#: builtin/commit-graph.c +msgid "allow writing an incremental commit-graph file" +msgstr "ligean comhad gráf choimisiúnaithe a scríobh" + +#: builtin/commit-graph.c +msgid "maximum number of commits in a non-base split commit-graph" +msgstr "uaslíon na ngealltanais i ngráf coiste scoilte neamh-bhonn" + +#: builtin/commit-graph.c +msgid "maximum ratio between two levels of a split commit-graph" +msgstr "cóimheas uasta idir dhá leibhéal de ghraf coimiste scoilte" + +#: builtin/commit-graph.c +msgid "only expire files older than a given date-time" +msgstr "ní rachaidh in éag ach comhaid níos sine ná dáta-am ar leith" + +#: builtin/commit-graph.c +msgid "maximum number of changed-path Bloom filters to compute" +msgstr "líon uasta scagairí Bloom cosáin athraithe le ríomh" + +#: builtin/commit-graph.c +msgid "use at most one of --reachable, --stdin-commits, or --stdin-packs" +msgstr "" +"bain úsáid as ceann de --reachable, --stdin-commits, nó --stdin-packs ar a " +"mhéad" + +#: builtin/commit-graph.c +msgid "Collecting commits from input" +msgstr "Gealltanais a bhailiú ó ionchur" + +#: builtin/commit-tree.c +msgid "git commit-tree [(-p )...]" +msgstr "git commit-tree [(-p)...]" + +#: builtin/commit-tree.c +msgid "" +"git commit-tree [(-p )...] [-S[]] [(-m )...]\n" +" [(-F )...] " +msgstr "" +"git commit-tree [(-p)...] [-S []] [(-m)...]\n" +" [(-F)...] " + +#: builtin/commit-tree.c +#, c-format +msgid "duplicate parent %s ignored" +msgstr "neamhaird déanta ar thuismitheoir dúblach %s" + +#: builtin/commit-tree.c builtin/log.c +#, c-format +msgid "not a valid object name %s" +msgstr "ní ainm réad bailí %s" + +#: builtin/commit-tree.c +#, c-format +msgid "git commit-tree: failed to read '%s'" +msgstr "git commit-tree: theip ar '%s' a léamh" + +#: builtin/commit-tree.c +#, c-format +msgid "git commit-tree: failed to close '%s'" +msgstr "git commit-tree: theip ar '%s' a dhúnadh" + +#: builtin/commit-tree.c +msgid "parent" +msgstr "tuismitheoir" + +#: builtin/commit-tree.c +msgid "id of a parent commit object" +msgstr "id réad tiomanta tuismitheora" + +#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/notes.c +#: builtin/stash.c builtin/tag.c +msgid "message" +msgstr "teachtaireacht" + +#: builtin/commit-tree.c builtin/commit.c +msgid "commit message" +msgstr "teachtaireacht a thabhairt" + +#: builtin/commit-tree.c +msgid "read commit log message from file" +msgstr "léigh teachtaireacht logála tiomanta ón gcomhad" + +#: builtin/commit-tree.c builtin/commit.c builtin/merge.c builtin/pull.c +#: builtin/revert.c +msgid "GPG sign commit" +msgstr "Tiomantas comhartha GPG" + +#: builtin/commit-tree.c +msgid "must give exactly one tree" +msgstr "caithfidh crann amháin a thabhairt go díreach" + +#: builtin/commit-tree.c +msgid "git commit-tree: failed to read" +msgstr "git commit-tree: theip ar léamh" + +#: builtin/commit.c +msgid "" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[]] [--amend]\n" +" [--dry-run] [(-c | -C | --squash) | --fixup [(amend|" +"reword):]]\n" +" [-F | -m ] [--reset-author] [--allow-empty]\n" +" [--allow-empty-message] [--no-verify] [-e] [--author=]\n" +" [--date=] [--cleanup=] [--[no-]status]\n" +" [-i | -o] [--pathspec-from-file= [--pathspec-file-nul]]\n" +" [(--trailer [(=|:)])...] [-S[]]\n" +" [--] [...]" +msgstr "" +"git commit [-a | --interactive | --patch] [-s] [-v] [-u[]] [--amend]\n" +" [--dry-run] [(-c | -C | --squash) | --fixup [(amend|" +"reword):]]\n" +" [-F | -m ] [--reset-author] [--allow-empty]\n" +" [--allow-empty-message] [--no-verify] [-e] [--author=]\n" +" [--date=] [--cleanup=] [--[no-]status]\n" +" [-i | -o] [--pathspec-from-file= [--pathspec-file-nul]]\n" +" [(--trailer [(=|:)])...] [-S[]]\n" +" [--] [...]" + +#: builtin/commit.c +msgid "git status [] [--] [...]" +msgstr "stádas git [] [--] [...]" + +#: builtin/commit.c +msgid "" +"You asked to amend the most recent commit, but doing so would make\n" +"it empty. You can repeat your command with --allow-empty, or you can\n" +"remove the commit entirely with \"git reset HEAD^\".\n" +msgstr "" +"D'iarr tú an gealltanas is déanaí a leasú, ach déanfaí amhlaidh a dhéanamh\n" +"folamh é. Is féidir leat d'ordú a athdhéanamh le --allow-empty, nó is féidir " +"leat\n" +"bain an tiomantas go hiomlán le “git reset HEAD^”.\n" + +#: builtin/commit.c +msgid "" +"The previous cherry-pick is now empty, possibly due to conflict resolution.\n" +"If you wish to commit it anyway, use:\n" +"\n" +" git commit --allow-empty\n" +"\n" +msgstr "" +"Tá an pioc silíní roimhe seo folamh anois, b'fhéidir mar gheall ar réiteach " +"coinbhleachta.\n" +"Más mian leat é a dhéanamh ar aon nós, bain úsáid as:\n" +"\n" +" git commit --allow-empty\n" +"\n" + +#: builtin/commit.c +msgid "Otherwise, please use 'git rebase --skip'\n" +msgstr "Seachas sin, bain úsáid as 'git rebase --skip'\n" + +#: builtin/commit.c +msgid "Otherwise, please use 'git cherry-pick --skip'\n" +msgstr "Seachas sin, bain úsáid as 'git cherry-pick --skip'\n" + +#: builtin/commit.c +msgid "" +"and then use:\n" +"\n" +" git cherry-pick --continue\n" +"\n" +"to resume cherry-picking the remaining commits.\n" +"If you wish to skip this commit, use:\n" +"\n" +" git cherry-pick --skip\n" +"\n" +msgstr "" +"agus ansin bain úsáid as:\n" +"\n" +" git cherry-pick --continue\n" +"\n" +"chun na gealltanais atá fágtha a atosú ag piocadh silíní.\n" +"Más mian leat an tiomantas seo a scipeáil, bain úsáid as:\n" +"\n" +" git cherry-pick --skip\n" + +#: builtin/commit.c read-cache.c +msgid "updating files failed" +msgstr "theip ar nuashonrú comhaid" + +#: builtin/commit.c +msgid "failed to unpack HEAD tree object" +msgstr "theip orthu réad crann HEAD a dhíphacáil" + +#: builtin/commit.c +msgid "No paths with --include/--only does not make sense." +msgstr "Níl ciall ag aon chosáin le --include/--only." + +#: builtin/commit.c +msgid "unable to create temporary index" +msgstr "in ann innéacs sealadach a chruthú" + +#: builtin/commit.c +msgid "interactive add failed" +msgstr "theip ar chur idirghníomh" + +#: builtin/commit.c +msgid "unable to update temporary index" +msgstr "in ann innéacs sealadach a nuashonrú" + +#: builtin/commit.c +msgid "Failed to update main cache tree" +msgstr "Theip ar phríomhchrann taisce a nuashonrú" + +#: builtin/commit.c +msgid "cannot do a partial commit during a merge." +msgstr "ní féidir le tiomantas páirteach a dhéanamh le linn cumaisc." + +#: builtin/commit.c +msgid "cannot do a partial commit during a cherry-pick." +msgstr "ní féidir le tiomantas páirteach a dhéanamh le linn pioc silíní." + +#: builtin/commit.c +msgid "cannot do a partial commit during a rebase." +msgstr "ní féidir le tiomantas páirteach a dhéanamh le linn athbhunaithe." + +#: builtin/commit.c +msgid "cannot read the index" +msgstr "ní féidir leis an innéacs a léamh" + +#: builtin/commit.c +msgid "unable to write temporary index file" +msgstr "in ann comhad innéacs sealadach a scríobh" + +#: builtin/commit.c +#, c-format +msgid "commit '%s' lacks author header" +msgstr "níl ceannteideal údair ag comhoiriú '%s'" + +#: builtin/commit.c +#, c-format +msgid "commit '%s' has malformed author line" +msgstr "comtal tá líne údair mífhoirmithe ag '%s'" + +#: builtin/commit.c +msgid "malformed --author parameter" +msgstr "paraiméadar --author mífhoirmithe" + +#: builtin/commit.c ident.c +#, c-format +msgid "invalid date format: %s" +msgstr "formáid dáta neamhbhailí: %s" + +#: builtin/commit.c +msgid "" +"unable to select a comment character that is not used\n" +"in the current commit message" +msgstr "" +"nach féidir carachtar tráchta a roghnú nach n-úsáidtear\n" +"sa teachtaireacht tiomanta reatha" + +#: builtin/commit.c +#, c-format +msgid "could not lookup commit '%s'" +msgstr "ní fhéadfaí cuardach a dhéanamh ar '%s'" + +#: builtin/commit.c builtin/shortlog.c +#, c-format +msgid "(reading log message from standard input)\n" +msgstr "(teachtaireacht log a léamh ó ionchur caighdeánach)\n" + +#: builtin/commit.c +msgid "could not read log from standard input" +msgstr "ní raibh in ann log a léamh ó ionchur caighdeánach" + +#: builtin/commit.c +#, c-format +msgid "could not read log file '%s'" +msgstr "ní raibh in ann comhad logála '%s' a léamh" + +#: builtin/commit.c +#, c-format +msgid "options '%s' and '%s:%s' cannot be used together" +msgstr "ní féidir roghanna '%s' agus '%s: %s' a úsáid le chéile" + +#: builtin/commit.c +msgid "could not read SQUASH_MSG" +msgstr "ní raibh in ann SQUASH_MSG a léamh" + +#: builtin/commit.c +msgid "could not read MERGE_MSG" +msgstr "ní raibh in ann MERGE_MSG a léamh" + +#: builtin/commit.c bundle.c rerere.c sequencer.c +#, c-format +msgid "could not open '%s'" +msgstr "ní fhéadfaí '%s' a oscailt" + +#: builtin/commit.c +msgid "could not write commit template" +msgstr "ní raibh sé in ann teimpléad tiomanta a" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be ignored.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. Línte ag " +"tosú\n" +"déanfar neamhaird le '%s'.\n" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be ignored, and an empty message aborts the commit.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. Línte ag " +"tosú\n" +"déanfar neamhaird le '%s', agus déanfar teachtaireacht folamh deireadh leis " +"an tiomantas.\n" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be kept; you may remove them yourself if you want to.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. Línte ag " +"tosú\n" +"coimeádfar le '%s'; féadfaidh tú iad a bhaint féin más mian leat.\n" + +#: builtin/commit.c +#, c-format +msgid "" +"Please enter the commit message for your changes. Lines starting\n" +"with '%s' will be kept; you may remove them yourself if you want to.\n" +"An empty message aborts the commit.\n" +msgstr "" +"Cuir isteach an teachtaireacht tiomanta le haghaidh d'athruithe. Línte ag " +"tosú\n" +"coimeádfar le '%s'; féadfaidh tú iad a bhaint féin más mian leat.\n" +"Déanann teachtaireacht folamh deireadh leis an tiomantas.\n" + +#: builtin/commit.c +msgid "" +"\n" +"It looks like you may be committing a merge.\n" +"If this is not correct, please run\n" +"\tgit update-ref -d MERGE_HEAD\n" +"and try again.\n" +msgstr "" +"\n" +"Is cosúil go bhfuil tú ag déanamh cumasc.\n" +"Mura bhfuil sé seo ceart, rith\n" +"git update-ref -d MERGE_HEAD\n" +"agus déan iarracht arís.\n" + +#: builtin/commit.c +msgid "" +"\n" +"It looks like you may be committing a cherry-pick.\n" +"If this is not correct, please run\n" +"\tgit update-ref -d CHERRY_PICK_HEAD\n" +"and try again.\n" +msgstr "" +"\n" +"Is cosúil go bhfuil tú ag déanamh rogha neamhghnách.\n" +"Mura bhfuil sé seo ceart, rith\n" +"\tgit update-ref -d CHERRY_PICK_HEAD\n" +"agus déan iarracht arís.\n" + +#: builtin/commit.c +#, c-format +msgid "%sAuthor: %.*s <%.*s>" +msgstr "%sÚdar: %.*s <%.*s>" + +#: builtin/commit.c +#, c-format +msgid "%sDate: %s" +msgstr "%sDáta: %s" + +#: builtin/commit.c +#, c-format +msgid "%sCommitter: %.*s <%.*s>" +msgstr "%sCeannasaí: %.*s <%.*s>" + +#: builtin/commit.c +msgid "Cannot read index" +msgstr "Ní féidir innéacs a léamh" + +#: builtin/commit.c builtin/tag.c +msgid "unable to pass trailers to --trailers" +msgstr "nach féidir leantóirí a chur chuig --trailers" + +#: builtin/commit.c +msgid "Error building trees" +msgstr "Earráid ag tógáil crainn" + +#: builtin/commit.c builtin/tag.c +#, c-format +msgid "Please supply the message using either -m or -F option.\n" +msgstr "" +"Soláthair an teachtaireacht le do thoil ag baint úsáide as rogha -m nó -F.\n" + +#: builtin/commit.c +#, c-format +msgid "--author '%s' is not 'Name ' and matches no existing author" +msgstr "" +"Ní 'Ainm' é --author '%s' agus ní mheaitseálann aon údar atá ann " +"cheana" + +#: builtin/commit.c +#, c-format +msgid "Invalid ignored mode '%s'" +msgstr "Modh neamhbhailí neamhaird '%s'" + +#: builtin/commit.c +#, c-format +msgid "Invalid untracked files mode '%s'" +msgstr "Modh comhaid neamhrianaithe neamhbhailí '%s'" + +#: builtin/commit.c +msgid "You are in the middle of a merge -- cannot reword." +msgstr "Tá tú i lár cumaisc - ní féidir athfhocal a athfhocal." + +#: builtin/commit.c +msgid "You are in the middle of a cherry-pick -- cannot reword." +msgstr "Tá tú i lár pioc silíní - ní féidir athfhocal a athfhocal." + +#: builtin/commit.c +#, c-format +msgid "reword option of '%s' and path '%s' cannot be used together" +msgstr "ní féidir rogha athfhocal de '%s' agus cosán '%s' a úsáid le chéile" + +#: builtin/commit.c +#, c-format +msgid "reword option of '%s' and '%s' cannot be used together" +msgstr "ní féidir rogha athfhocal de '%s' agus '%s' a úsáid le chéile" + +#: builtin/commit.c +msgid "You have nothing to amend." +msgstr "Níl aon rud le leasú agat." + +#: builtin/commit.c +msgid "You are in the middle of a merge -- cannot amend." +msgstr "Tá tú i lár cumaisc - ní féidir leat leasú." + +#: builtin/commit.c +msgid "You are in the middle of a cherry-pick -- cannot amend." +msgstr "Tá tú i lár rogha silíní - ní féidir leat leasú." + +#: builtin/commit.c +msgid "You are in the middle of a rebase -- cannot amend." +msgstr "Tá tú i lár athbhunaithe - ní féidir leat leasú." + +#: builtin/commit.c +msgid "--reset-author can be used only with -C, -c or --amend." +msgstr "Ní féidir --reset-author a úsáid ach le -C, -c nó --amend." + +#: builtin/commit.c +#, c-format +msgid "unknown option: --fixup=%s:%s" +msgstr "rogha anaithnid: --fixup=%s:%s" + +#: builtin/commit.c +#, c-format +msgid "paths '%s ...' with -a does not make sense" +msgstr "ní chiallaíonn cosáin '%s... 'le -a" + +#: builtin/commit.c +msgid "show status concisely" +msgstr "taispeáin stádas go hachomair" + +#: builtin/commit.c +msgid "show branch information" +msgstr "taispeáin faisnéis bhrainse" + +#: builtin/commit.c +msgid "show stash information" +msgstr "taispeáin faisnéis stash" + +#: builtin/commit.c +msgid "compute full ahead/behind values" +msgstr "luachanna iomlána/taobh thiar de na luachanna a ríomh" + +#: builtin/commit.c +msgid "version" +msgstr "leagan" + +#: builtin/commit.c builtin/fetch.c builtin/push.c builtin/worktree.c +msgid "machine-readable output" +msgstr "aschur inléite meaisín" + +#: builtin/commit.c +msgid "show status in long format (default)" +msgstr "stádas taispeáint i bhformáid fhada (réamhshocraithe)" + +#: builtin/commit.c +msgid "terminate entries with NUL" +msgstr "foirceannadh na hiontrálacha" + +#: builtin/commit.c +msgid "show untracked files, optional modes: all, normal, no. (Default: all)" +msgstr "" +"taispeáin comhaid neamhrianaithe, modhanna roghnacha: gach, gnáth, níl. " +"(Réamhshocraithe: gach)" + +#: builtin/commit.c +msgid "" +"show ignored files, optional modes: traditional, matching, no. (Default: " +"traditional)" +msgstr "" +"taispeáint comhaid neamhaird orthu, modhanna roghnacha: traidisiúnta, " +"meaitseáil, (Réamhshocraithe: traidisiúnta)" + +#: builtin/commit.c parse-options.h +msgid "when" +msgstr "nuair a" + +#: builtin/commit.c +msgid "" +"ignore changes to submodules, optional when: all, dirty, untracked. " +"(Default: all)" +msgstr "" +"neamhaird a dhéanamh ar athruithe ar fho-mhodúil, roghnach nuair a bhíonn: " +"gach, salach, gan rianú. (Réamhshocraithe: gach)" + +#: builtin/commit.c +msgid "list untracked files in columns" +msgstr "liostáil comhaid neamhrianaithe i gcolúin" + +#: builtin/commit.c +msgid "do not detect renames" +msgstr "ná athainmneacha a bhrath" + +#: builtin/commit.c +msgid "detect renames, optionally set similarity index" +msgstr "athainmneacha a bhrath, innéacs cosúlachta a shocrú go ro" + +#: builtin/commit.c +msgid "Unsupported combination of ignored and untracked-files arguments" +msgstr "Teaglaim gan tacaíocht d'argóintí comhaid a neamhaird agus gan rianú" + +#: builtin/commit.c +msgid "suppress summary after successful commit" +msgstr "achoimre a chur faoi chois tar éis tiomantas" + +#: builtin/commit.c +msgid "show diff in commit message template" +msgstr "taispeáin diff i teimpléad teachtaireachta tiomanta" + +#: builtin/commit.c +msgid "Commit message options" +msgstr "Tiomanta roghanna teachtaire" + +#: builtin/commit.c builtin/merge.c builtin/tag.c +msgid "read message from file" +msgstr "léigh teachtaireacht ón gcomhad" + +#: builtin/commit.c +msgid "author" +msgstr "údar" + +#: builtin/commit.c +msgid "override author for commit" +msgstr "an t-údar a shárú le haghaidh tiomantas" + +#: builtin/commit.c builtin/gc.c +msgid "date" +msgstr "dáta" + +#: builtin/commit.c +msgid "override date for commit" +msgstr "dáta athsháraithe le haghaidh tiomanta" + +#: builtin/commit.c parse-options.h ref-filter.h +msgid "commit" +msgstr "tiomantas" + +#: builtin/commit.c +msgid "reuse and edit message from specified commit" +msgstr "teachtaireacht a athúsáid agus a chur in eagar ó thiomantas" + +#: builtin/commit.c +msgid "reuse message from specified commit" +msgstr "teachtaireacht athúsáid ó thiomantas sonraithe" + +#. TRANSLATORS: Leave "[(amend|reword):]" as-is, +#. and only translate . +#. +#: builtin/commit.c +msgid "[(amend|reword):]commit" +msgstr "[(leaso|athfhocal):] comhartha" + +#: builtin/commit.c +msgid "" +"use autosquash formatted message to fixup or amend/reword specified commit" +msgstr "" +"úsáid teachtaireacht fhormáidithe autosquash chun gealltanas sonraithe a " +"shocrú nó a leasú/athfhocal" + +#: builtin/commit.c +msgid "use autosquash formatted message to squash specified commit" +msgstr "" +"úsáid teachtaireacht fhormáidithe autosquash chun tiomantas sonraithe squash" + +#: builtin/commit.c +msgid "the commit is authored by me now (used with -C/-c/--amend)" +msgstr "tá an gealltanas údar agam anois (úsáidtear le -C/-c/--amend)" + +#: builtin/commit.c builtin/interpret-trailers.c builtin/tag.c +msgid "trailer" +msgstr "leantóir" + +#: builtin/commit.c builtin/tag.c +msgid "add custom trailer(s)" +msgstr "cuir leantóir (í) saincheaptha" + +#: builtin/commit.c builtin/log.c builtin/merge.c builtin/pull.c +#: builtin/revert.c +msgid "add a Signed-off-by trailer" +msgstr "cuir leantóir sínithe as" + +#: builtin/commit.c +msgid "use specified template file" +msgstr "úsáid comhad teimpléad sonraithe" + +#: builtin/commit.c +msgid "force edit of commit" +msgstr "eagarthóireacht fórsa ar thiomantas" + +#: builtin/commit.c +msgid "include status in commit message template" +msgstr "áireamh stádas i dteimpléad teachtaireachta" + +#: builtin/commit.c +msgid "Commit contents options" +msgstr "Tiomnaigh roghanna ábhair" + +#: builtin/commit.c +msgid "commit all changed files" +msgstr "gach comhad athraithe a thiomnú" + +#: builtin/commit.c +msgid "add specified files to index for commit" +msgstr "cuir comhaid sonraithe leis an innéacs le haghaidh tiomanta" + +#: builtin/commit.c +msgid "interactively add files" +msgstr "cuir comhaid idirghníomhach" + +#: builtin/commit.c +msgid "interactively add changes" +msgstr "cuir athruithe idirghníomhach" + +#: builtin/commit.c +msgid "commit only specified files" +msgstr "ach comhaid shonraithe a dhéanamh" + +#: builtin/commit.c +msgid "bypass pre-commit and commit-msg hooks" +msgstr "seachbhóthar crúcaí réamh-thiomanta agus comh-msg" + +#: builtin/commit.c +msgid "show what would be committed" +msgstr "taispeáint cad a bheadh tiomanta" + +#: builtin/commit.c +msgid "amend previous commit" +msgstr "leasú a leasú" + +#: builtin/commit.c +msgid "bypass post-rewrite hook" +msgstr "seachbhóthar crúca iar-athsc" + +#: builtin/commit.c +msgid "ok to record an empty change" +msgstr "ceart go leor chun athrú folamh a thaifeadadh" + +#: builtin/commit.c +msgid "ok to record a change with an empty message" +msgstr "ceart go leor chun athrú a thaifeadadh le teachtaireacht folamh" + +#: builtin/commit.c sequencer.c +msgid "could not parse HEAD commit" +msgstr "ní fhéadfadh sé gealltanas HEAD a pharsáil" + +#: builtin/commit.c +#, c-format +msgid "Corrupt MERGE_HEAD file (%s)" +msgstr "Comhad truaillithe MERGE_HEAD (%s)" + +#: builtin/commit.c +msgid "could not read MERGE_MODE" +msgstr "ní raibh in ann MERGE_MODE a léamh" + +#: builtin/commit.c +#, c-format +msgid "could not read commit message: %s" +msgstr "ní féidir teachtaireacht tiomanta a léamh: %s" + +#: builtin/commit.c +#, c-format +msgid "Aborting commit due to empty commit message.\n" +msgstr "Tiomantas a ghabháil mar gheall ar theachtaireacht tiomanta folamh\n" + +#: builtin/commit.c +#, c-format +msgid "Aborting commit; you did not edit the message.\n" +msgstr "Tiomantas a ghearradh; níor chuir tú an teachtaireacht in eagar.\n" + +#: builtin/commit.c +#, c-format +msgid "Aborting commit due to empty commit message body.\n" +msgstr "" +"Tiomantas a ghabháil mar gheall ar chorp teachtaireachta tiomanta folamh.\n" + +#: builtin/commit.c +msgid "" +"repository has been updated, but unable to write\n" +"new index file. Check that disk is not full and quota is\n" +"not exceeded, and then \"git restore --staged :/\" to recover." +msgstr "" +"nuashonraíodh an stór, ach ní féidir scríobh\n" +"comhad innéacs nua. Seiceáil nach bhfuil an diosca \n" +"lán agus nach bhfuil an cuóta sáraithe, agus ansin \"git restore --staged :/" +"\" chun é a aisghabháil." + +#: builtin/config.c +msgid "git config list [] [] [--includes]" +msgstr "liosta config git [] [] [--include]" + +#: builtin/config.c +msgid "" +"git config get [] [] [--includes] [--all] [--" +"regexp] [--value=] [--fixed-value] [--default=] " +msgstr "" +"git config a fháil [] [] [--include] [--all] [--regexp] [--value=] [--luach seasta] [--default=] " + +#: builtin/config.c +msgid "" +"git config set [] [--type=] [--all] [--value=] [--" +"fixed-value] " +msgstr "" +"git config set [] [--type =] [--all] [--value=] [--" +"luach seasta] " + +#: builtin/config.c +msgid "" +"git config unset [] [--all] [--value=] [--fixed-value] " +"" +msgstr "" +"git config gan socrú [] [--gach] [--value=] [--luach " +"seasta] " + +#: builtin/config.c +msgid "git config rename-section [] " +msgstr "roinn athainmnithe git config [] " + +#: builtin/config.c +msgid "git config remove-section [] " +msgstr "roinn aistrithe git config [] " + +#: builtin/config.c +msgid "git config edit []" +msgstr "Eagarthóireacht config git []" + +#: builtin/config.c +msgid "git config [] --get-colorbool []" +msgstr "git config [] --get-colorbool []" + +#: builtin/config.c +msgid "" +"git config get [] [] [--includes] [--all] [--" +"regexp=] [--value=] [--fixed-value] [--default=] " +"" +msgstr "" +"git config a fháil [] [] [--include] [--all] [--regexp=] [-- value=] [--luach seasta] [--" +"default=] " + +#: builtin/config.c +msgid "" +"git config set [] [--type=] [--comment=] [--all] " +"[--value=] [--fixed-value] " +msgstr "" +"git config set [] [--type =] [--comment =] [--all] " +"[--value=] [--luach seasta] " + +#: builtin/config.c +msgid "Config file location" +msgstr "Suíomh comhad Config" + +#: builtin/config.c +msgid "use global config file" +msgstr "bain úsáid as comhad cumraíochta domhanda" + +#: builtin/config.c +msgid "use system config file" +msgstr "bain úsáid as comhad cumraíochta córais" + +#: builtin/config.c +msgid "use repository config file" +msgstr "bain úsáid as comhad cumraíochta stórais" + +#: builtin/config.c +msgid "use per-worktree config file" +msgstr "bain úsáid as comhad cumraíochta in aghaidh an chrann oibre" + +#: builtin/config.c builtin/gc.c +msgid "use given config file" +msgstr "bain úsáid as comhad cumraíochta tugtha" + +#: builtin/config.c +msgid "blob-id" +msgstr "blob-id" + +#: builtin/config.c +msgid "read config from given blob object" +msgstr "léigh cumraíocht ó réad blob a thugtar" + +#: builtin/config.c +msgid "Type" +msgstr "Cineál" + +#: builtin/config.c builtin/hash-object.c +msgid "type" +msgstr "cineál" + +#: builtin/config.c +msgid "value is given this type" +msgstr "tugtar luach an cineál seo" + +#: builtin/config.c +msgid "value is \"true\" or \"false\"" +msgstr "tá luach “fíor” nó “bréagach”" + +#: builtin/config.c +msgid "value is decimal number" +msgstr "is é luach uimhir deachúil" + +#: builtin/config.c +msgid "value is --bool or --int" +msgstr "is é luach --bool nó --int" + +#: builtin/config.c +msgid "value is --bool or string" +msgstr "is é luach --bool nó teaghrán" + +#: builtin/config.c +msgid "value is a path (file or directory name)" +msgstr "is cosán é luach (ainm comhad nó eolaire)" + +#: builtin/config.c +msgid "value is an expiry date" +msgstr "is dáta éaga é luach" + +#: builtin/config.c +msgid "Display options" +msgstr "Roghanna taispeána" + +#: builtin/config.c +msgid "terminate values with NUL byte" +msgstr "foirceannadh luachanna le nóta NUL" + +#: builtin/config.c +msgid "show variable names only" +msgstr "taispeáin ainmneacha athróg amháin" + +#: builtin/config.c +msgid "show origin of config (file, standard input, blob, command line)" +msgstr "" +"taispeáint bunús an chumraíochta (comhad, ionchur caighdeánach, blob, líne " +"ordaithe)" + +#: builtin/config.c +msgid "show scope of config (worktree, local, global, system, command)" +msgstr "" +"taispeáin raon feidhme an chumraíochta (crann oibre, áitiúil, domhanda, " +"córas, ordú)" + +#: builtin/config.c +msgid "show config keys in addition to their values" +msgstr "taispeáin eochracha cumraithe i dteannta lena luachanna" + +#: builtin/config.c +#, c-format +msgid "unrecognized --type argument, %s" +msgstr "argóint --type gan aithint, %s" + +#: builtin/config.c +msgid "only one type at a time" +msgstr "ach cineál amháin ag an am" + +#: builtin/config.c +#, c-format +msgid "wrong number of arguments, should be %d" +msgstr "líon mícheart na n-argóintí, ba chóir go mbeadh %d" + +#: builtin/config.c +#, c-format +msgid "wrong number of arguments, should be from %d to %d" +msgstr "ba chóir go mbeadh líon mícheart na n-argóintí ó %d go %d" + +#: builtin/config.c +#, c-format +msgid "invalid key pattern: %s" +msgstr "patrún eochair neamhbhailí: %s" + +#: builtin/config.c config.c +#, c-format +msgid "invalid pattern: %s" +msgstr "patrún neamhbhailí: %s" + +#: builtin/config.c +#, c-format +msgid "failed to format default config value: %s" +msgstr "theip ar luach cumraíochta réamhshocraithe a fhormáidiú: %s" + +#: builtin/config.c +#, c-format +msgid "cannot parse color '%s'" +msgstr "ní féidir dath '%s' a pháirseáil" + +#: builtin/config.c +msgid "unable to parse default color value" +msgstr "in ann luach dath réamhshocraithe a pharsáil" + +#: builtin/config.c +msgid "not in a git directory" +msgstr "nach bhfuil i eolaire git" + +#: builtin/config.c +msgid "writing to stdin is not supported" +msgstr "ní thacaítear le scríobh chuig stdin" + +#: builtin/config.c +msgid "writing config blobs is not supported" +msgstr "ní thacaítear le blobs cumraíochta a scríobh" + +#: builtin/config.c +#, c-format +msgid "" +"# This is Git's per-user configuration file.\n" +"[user]\n" +"# Please adapt and uncomment the following lines:\n" +"#\tname = %s\n" +"#\temail = %s\n" +msgstr "" +"# Seo comhad cumraíochta Git in aghaidh an úsáideora.\n" +"[úsáideoir]\n" +"# Oiriúnaigh agus bain trácht de na línte seo a leanas le do thoil:\n" +"#\tainm = %s\n" +"#\tríomhphost = %s\n" + +#: builtin/config.c +msgid "only one config file at a time" +msgstr "ach comhad cumraithe amháin ag an am" + +#: builtin/config.c +msgid "--local can only be used inside a git repository" +msgstr "Ní féidir --local a úsáid ach taobh istigh de stór git" + +#: builtin/config.c +msgid "--blob can only be used inside a git repository" +msgstr "Ní féidir --blob a úsáid ach taobh istigh de stór git" + +#: builtin/config.c +msgid "--worktree can only be used inside a git repository" +msgstr "Ní féidir --worktree a úsáid ach taobh istigh de stór git" + +#: builtin/config.c builtin/gc.c +msgid "$HOME not set" +msgstr "Níl $HOME socraithe" + +#: builtin/config.c +msgid "" +"--worktree cannot be used with multiple working trees unless the config\n" +"extension worktreeConfig is enabled. Please read \"CONFIGURATION FILE\"\n" +"section in \"git help worktree\" for details" +msgstr "" +"Ní féidir --worktree a úsáid le crainn oibre iolracha mura bhfuil an " +"cumraíocht\n" +"Tá síneadh WorkTreeConfig cumasaithe. Léigh “COMHAD CUMRAÍOCHTA”\n" +"roinn i “git help worktree” le haghaidh sonraí" + +#: builtin/config.c +msgid "Other" +msgstr "Eile" + +#: builtin/config.c +msgid "respect include directives on lookup" +msgstr "meas lena n-áirítear treoracha maidir le cuardach" + +#: builtin/config.c +#, c-format +msgid "unable to read config file '%s'" +msgstr "nach féidir an comhad cumraithe '%s' a léamh" + +#: builtin/config.c +msgid "error processing config file(s)" +msgstr "comhad (í) cumraíochta próiseála earráide" + +#: builtin/config.c +msgid "Filter options" +msgstr "Roghanna scagaire" + +#: builtin/config.c +msgid "return all values for multi-valued config options" +msgstr "" +"gach luach a thabhairt ar ais le haghaidh roghanna cumraithe illuachmhara" + +#: builtin/config.c +msgid "interpret the name as a regular expression" +msgstr "léirmhíniú an t-ainm mar abairt rialta" + +#: builtin/config.c +msgid "show config with values matching the pattern" +msgstr "taispeáin cumraíocht le luachanna a mheaitseann an phatrún" + +#: builtin/config.c +msgid "use string equality when comparing values to value pattern" +msgstr "bain úsáid as comhionannas sreangán agus luachanna á gcomparáid" + +#: builtin/config.c +msgid "URL" +msgstr "URL" + +#: builtin/config.c +msgid "show config matching the given URL" +msgstr "taispeáin configí a mheaitseáil leis an URL tugtha" + +#: builtin/config.c +msgid "value" +msgstr "luach" + +#: builtin/config.c +msgid "use default value when missing entry" +msgstr "bain úsáid as luach réamhshocraithe agus iontráil" + +#: builtin/config.c +msgid "--fixed-value only applies with 'value-pattern'" +msgstr "Ní bhaineann --fixed-value ach le 'patrún luacha'" + +#: builtin/config.c +msgid "--default= cannot be used with --all or --url=" +msgstr "Ní féidir --default= a úsáid le --all nó --url =" + +#: builtin/config.c +msgid "--url= cannot be used with --all, --regexp or --value" +msgstr "Ní féidir --url = a úsáid le --all, --regexp nó --value" + +#: builtin/config.c +msgid "Filter" +msgstr "Scagaire" + +#: builtin/config.c +msgid "replace multi-valued config option with new value" +msgstr "luach nua a chur in ionad rogha cumraíochta illuachmhara" + +#: builtin/config.c +msgid "human-readable comment string (# will be prepended as needed)" +msgstr "" +"teaghrán tráchtaireachta inléite don duine (déanfar # a ullmhú de réir mar " +"is gá)" + +#: builtin/config.c +msgid "add a new line without altering any existing values" +msgstr "líne nua a chur leis gan aon luachanna atá ann cheana a athrú" + +#: builtin/config.c +msgid "--fixed-value only applies with --value=" +msgstr "ní bhaineann --fixed-value ach le --value=" + +#: builtin/config.c +msgid "--append cannot be used with --value=" +msgstr "Ní féidir --append a úsáid le --value=" + +#: builtin/config.c +#, c-format +msgid "" +"cannot overwrite multiple values with a single value\n" +" Use a regexp, --add or --replace-all to change %s." +msgstr "" +"ní féidir luachanna iolracha a fhorscríobh le luach amháin\n" +" Úsáid regexp, --add nó --replace-all chun %s a athrú." + +#: builtin/config.c +#, c-format +msgid "no such section: %s" +msgstr "gan aon chuid den sórt sin: %s" + +#: builtin/config.c +msgid "editing stdin is not supported" +msgstr "ní thacaítear le stdin eagarthóireachta" + +#: builtin/config.c +msgid "editing blobs is not supported" +msgstr "ní thacaítear le blobs eagarthóireachta" + +#: builtin/config.c +#, c-format +msgid "cannot create configuration file %s" +msgstr "ní féidir comhad cumraíochta %s a chruthú" + +#: builtin/config.c +msgid "Action" +msgstr "Gníomhaíocht" + +#: builtin/config.c +msgid "get value: name []" +msgstr "luach a fháil: ainm []" + +#: builtin/config.c +msgid "get all values: key []" +msgstr "faigh na luachanna go léir: eochair []" + +#: builtin/config.c +msgid "get values for regexp: name-regex []" +msgstr "luachanna a fháil do regexp: ainm-regex []" + +#: builtin/config.c +msgid "get value specific for the URL: section[.var] URL" +msgstr "faigh luach sonrach don URL: rannán [.var] URL" + +#: builtin/config.c +msgid "replace all matching variables: name value []" +msgstr "athróg meaitseála go léir in ionad: luach ainm []" + +#: builtin/config.c +msgid "add a new variable: name value" +msgstr "cuir athróg nua leis: luach ainm" + +#: builtin/config.c +msgid "remove a variable: name []" +msgstr "bhaint athróg: ainm []" + +#: builtin/config.c +msgid "remove all matches: name []" +msgstr "bhaint gach cluiche: ainm []" + +#: builtin/config.c +msgid "rename section: old-name new-name" +msgstr "athainmnigh an chuid: sean-ainm nua-ainm" + +#: builtin/config.c +msgid "remove a section: name" +msgstr "cuid a bhaint: ainm" + +#: builtin/config.c +msgid "list all" +msgstr "liostáil go léir" + +#: builtin/config.c +msgid "open an editor" +msgstr "eagarthóir a oscailt" + +#: builtin/config.c +msgid "find the color configured: slot []" +msgstr "faigh an dath cumraithe: sliotán []" + +#: builtin/config.c +msgid "find the color setting: slot []" +msgstr "faigh an socrú dath: sliotán []" + +#: builtin/config.c +msgid "with --get, use default value when missing entry" +msgstr "le --get, bain úsáid as luach réamhshocraithe agus iontráil in easnamh" + +#: builtin/config.c +msgid "--get-color and variable type are incoherent" +msgstr "Tá --get-color agus cineál athraitheach neamhchomhtháite" + +#: builtin/config.c +msgid "no action specified" +msgstr "aon ghníomh sonraithe" + +#: builtin/config.c +msgid "--name-only is only applicable to --list or --get-regexp" +msgstr "Níl --name-only infheidhme ach le --list nó --get-regexp" + +#: builtin/config.c +msgid "" +"--show-origin is only applicable to --get, --get-all, --get-regexp, and --" +"list" +msgstr "" +"Níl --show-origin infheidhme ach le --get, --get-all, --get-regexp, agus --" +"list" + +#: builtin/config.c +msgid "--default is only applicable to --get" +msgstr "Níl --default infheidhme ach le --get" + +#: builtin/config.c +msgid "--comment is only applicable to add/set/replace operations" +msgstr "" +"Níl --comment infheidhme ach le hoibríochtaí a chur leis /socraí/athsholáthar" + +#: builtin/count-objects.c +msgid "print sizes in human readable format" +msgstr "méideanna priontála i bhformáid inléite don duine" + +#: builtin/credential-cache--daemon.c +#, c-format +msgid "" +"The permissions on your socket directory are too loose; other\n" +"users may be able to read your cached credentials. Consider running:\n" +"\n" +"\tchmod 0700 %s" +msgstr "" +"Tá na ceadanna ar d'eolaire soicéad ró-scaoilte; eile\n" +"b'fhéidir go mbeidh úsáideoirí in ann do dhintiúir taiscéadaithe a léamh. " +"Smaoinigh ar rith:\n" +"\n" +" chmod 0700 %s" + +#: builtin/credential-cache--daemon.c +msgid "print debugging messages to stderr" +msgstr "teachtaireachtaí dífhabhtaithe a phriontáil chuig stderr" + +#: builtin/credential-cache--daemon.c +msgid "credential-cache--daemon unavailable; no unix socket support" +msgstr "credential-cache--daemon ar fáil; gan aon tacaíocht soicéad unix" + +#: builtin/credential-cache.c +msgid "credential-cache unavailable; no unix socket support" +msgstr "taisce creidiúnaithe ar fáil; gan aon tacaíocht soicéad unix" + +#: builtin/credential-store.c +#, c-format +msgid "unable to get credential storage lock in %d ms" +msgstr "in ann glas stórála creidiúnaithe a fháil in %d ms" + +#: builtin/describe.c +msgid "" +"git describe [--all] [--tags] [--contains] [--abbrev=] [...]" +msgstr "" +"git describe [--all] [--tags] [--contains] [--abbrev=] [...]" + +#: builtin/describe.c +msgid "" +"git describe [--all] [--tags] [--contains] [--abbrev=] --dirty[=]" +msgstr "" +"git describe [--all] [--tags] [--contains] [--abbrev=] --dirty[=]" + +#: builtin/describe.c +msgid "git describe " +msgstr "git cur síos " + +#: builtin/describe.c +msgid "head" +msgstr "ceann" + +#: builtin/describe.c +msgid "lightweight" +msgstr "éadrom" + +#: builtin/describe.c +msgid "annotated" +msgstr "anótáilte" + +#: builtin/describe.c +#, c-format +msgid "annotated tag %s not available" +msgstr "níl clib anótáilte %s ar fáil" + +#: builtin/describe.c +#, c-format +msgid "tag '%s' is externally known as '%s'" +msgstr "tugtar '%s' ar an gclib '%s' go seachtrach" + +#: builtin/describe.c +#, c-format +msgid "no tag exactly matches '%s'" +msgstr "níl aon chlib ag teacht go díreach le '%s'" + +#: builtin/describe.c +#, c-format +msgid "No exact match on refs or tags, searching to describe\n" +msgstr "" +"Níl aon mheaitseáil cruinn ar thaifeanna nó clibeanna, ag cuardach chun cur " +"síos\n" + +#: builtin/describe.c +#, c-format +msgid "finished search at %s\n" +msgstr "cuardach críochnaithe ag %s\n" + +#: builtin/describe.c +#, c-format +msgid "" +"No annotated tags can describe '%s'.\n" +"However, there were unannotated tags: try --tags." +msgstr "" +"Ní féidir le haon chlibeanna anótaithe cur síos a dhéanamh ar '%s'.\n" +"Mar sin féin, bhí clibeanna gan anótáil ann: triail as --tags." + +#: builtin/describe.c +#, c-format +msgid "" +"No tags can describe '%s'.\n" +"Try --always, or create some tags." +msgstr "" +"Ní féidir le clibeanna cur síos a dhéanamh ar '%s'.\n" +"Bain triail as --always, nó cruthaigh roinnt clibeanna." + +#: builtin/describe.c +#, c-format +msgid "traversed %lu commits\n" +msgstr "gealltanais %lu a thrasnaíodh\n" + +#: builtin/describe.c +#, c-format +msgid "found %i tags; gave up search at %s\n" +msgstr "fuarthas %i clibeanna; thréig an cuardach ag %s\n" + +#: builtin/describe.c +#, c-format +msgid "describe %s\n" +msgstr "déan cur síos ar %s\n" + +#: builtin/describe.c +#, c-format +msgid "Not a valid object name %s" +msgstr "Ní ainm réad bailí %s" + +#: builtin/describe.c +#, c-format +msgid "%s is neither a commit nor blob" +msgstr "Ní gealltanas ná blob é %s" + +#: builtin/describe.c +msgid "find the tag that comes after the commit" +msgstr "faigh an chlib a thagann tar éis an tiomanta" + +#: builtin/describe.c +msgid "debug search strategy on stderr" +msgstr "straitéis cuardaigh dífhabhtú ar stderr" + +#: builtin/describe.c +msgid "use any ref" +msgstr "bain úsáid as aon tagairt" + +#: builtin/describe.c +msgid "use any tag, even unannotated" +msgstr "úsáid aon chlib, fiú gan anótáil" + +#: builtin/describe.c +msgid "always use long format" +msgstr "úsáid formáid fada i gcónaí" + +#: builtin/describe.c +msgid "only follow first parent" +msgstr "lean ach an chéad thuismitheoir" + +#: builtin/describe.c +msgid "only output exact matches" +msgstr "ach cluichí cruinne aschuir" + +#: builtin/describe.c +msgid "consider most recent tags (default: 10)" +msgstr "machnamh ar na clibeanna is déanaí (réamhshocraithe: 10)" + +#: builtin/describe.c +msgid "only consider tags matching " +msgstr "ní mheas ach meaitseáil clibeanna " + +#: builtin/describe.c +msgid "do not consider tags matching " +msgstr "ná smaoinigh ar mheaitseáil clibeanna " + +#: builtin/describe.c builtin/name-rev.c +msgid "show abbreviated commit object as fallback" +msgstr "taispeáint réad tiomanta giorraithe mar fhilleadh" + +#: builtin/describe.c +msgid "mark" +msgstr "marc" + +#: builtin/describe.c +msgid "append on dirty working tree (default: \"-dirty\")" +msgstr "cuir isteach ar chrann oibre salach (réamhshocraithe: “-salach”)" + +#: builtin/describe.c +msgid "append on broken working tree (default: \"-broken\")" +msgstr "cuir isteach ar chrann oibre briste (réamhshocraithe: “-broken”)" + +#: builtin/describe.c +msgid "No names found, cannot describe anything." +msgstr "" +"Níor aimsíodh aon ainmneacha, ní féidir cur síos a dhéanamh ar aon rud." + +#: builtin/describe.c +#, c-format +msgid "option '%s' and commit-ishes cannot be used together" +msgstr "ní féidir rogha '%s' agus coimistí a úsáid le chéile" + +#: builtin/diagnose.c +msgid "" +"git diagnose [(-o | --output-directory) ] [(-s | --suffix) ]\n" +" [--mode=]" +msgstr "" +"git diagnosis [(-o | --output-directory)] [(-s | -- suffix)]\n" +" [--mód =]" + +#: builtin/diagnose.c +msgid "specify a destination for the diagnostics archive" +msgstr "sonraigh ceann scríbe don chartlann diagnóisic" + +#: builtin/diagnose.c +msgid "specify a strftime format suffix for the filename" +msgstr "sonraigh iarmhír formáid strftime don ainm comhaid" + +#: builtin/diagnose.c +msgid "specify the content of the diagnostic archive" +msgstr "sonraigh ábhar an chartlann dhiagnóiseach" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse mode: %s" +msgstr "nach féidir modh a pháirseáil: %s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse object id: %s" +msgstr "nach féidir id réad a pháirseáil: %s" + +#: builtin/diff-pairs.c +msgid "git diff-pairs -z []" +msgstr "git diff-pairs -z []" + +#: builtin/diff-pairs.c builtin/log.c builtin/replay.c builtin/shortlog.c +#: bundle.c +#, c-format +msgid "unrecognized argument: %s" +msgstr "argóint gan aithint: %s" + +#: builtin/diff-pairs.c +msgid "working without -z is not supported" +msgstr "ní thacaítear le bheith ag obair gan -z" + +#: builtin/diff-pairs.c +msgid "pathspec arguments not supported" +msgstr "argóintí pathspec nach dtacaítear leis" + +#: builtin/diff-pairs.c +msgid "revision arguments not allowed" +msgstr "argóintí athbhreithnithe nach" + +#: builtin/diff-pairs.c +msgid "invalid raw diff input" +msgstr "ionchur diff amh neamhbhailí" + +#: builtin/diff-pairs.c +msgid "tree objects not supported" +msgstr "rudaí crann nach dtacaítear leis" + +#: builtin/diff-pairs.c +msgid "got EOF while reading path" +msgstr "fuair EOF agus tú ag léamh cosán" + +#: builtin/diff-pairs.c +msgid "got EOF while reading destination path" +msgstr "fuair EOF agus tú ag léamh cosán ceann scríbe" + +#: builtin/diff-pairs.c +#, c-format +msgid "unable to parse rename/copy score: %s" +msgstr "nach féidir scór athainmniú/cóipeáil a pháirseáil: %s" + +#: builtin/diff-pairs.c +#, c-format +msgid "unknown diff status: %c" +msgstr "stádas diff anaithnid: %c" + +#: builtin/diff-tree.c +msgid "--merge-base only works with two commits" +msgstr "Ní oibríonn --merge-base ach le dhá thiomantas" + +#: builtin/diff.c +#, c-format +msgid "'%s': not a regular file or symlink" +msgstr "'%s': ní comhad rialta nó comhnasc" + +#: builtin/diff.c +msgid "no merge given, only parents." +msgstr "ní thugtar aon chumasc, tuismitheoirí amháin." + +#: builtin/diff.c +#, c-format +msgid "invalid option: %s" +msgstr "rogha neamhbhailí: %s" + +#: builtin/diff.c +#, c-format +msgid "%s...%s: no merge base" +msgstr "%s... %s: gan aon bhonn cumaisc" + +#: builtin/diff.c +msgid "Not a git repository" +msgstr "Ní stór git" + +#: builtin/diff.c builtin/grep.c +#, c-format +msgid "invalid object '%s' given." +msgstr "réad neamhbhailí '%s' tugtha." + +#: builtin/diff.c +#, c-format +msgid "more than two blobs given: '%s'" +msgstr "níos mó ná dhá bhlob a thugtar: '%s'" + +#: builtin/diff.c +#, c-format +msgid "unhandled object '%s' given." +msgstr "réad neamh-láimhseáilte '%s' tugtha." + +#: builtin/diff.c +#, c-format +msgid "%s...%s: multiple merge bases, using %s" +msgstr "%s... %s: bonn cumaisc iolracha, ag baint úsáide as %s" + +#: builtin/difftool.c +msgid "git difftool [] [ []] [--] [...]" +msgstr "git difftool [[]] [[]] [--] [...]" + +#: builtin/difftool.c +#, c-format +msgid "could not read symlink %s" +msgstr "ní fhéadfaí nasc simtéarach %s a léamh" + +#: builtin/difftool.c +#, c-format +msgid "could not read symlink file %s" +msgstr "ní raibh in ann comhad simnasc %s a léamh" + +#: builtin/difftool.c +#, c-format +msgid "could not read object %s for symlink %s" +msgstr "ní raibh in ann réad %s a léamh le haghaidh nasc simtéarach %s" + +#: builtin/difftool.c +msgid "" +"combined diff formats ('-c' and '--cc') are not supported in\n" +"directory diff mode ('-d' and '--dir-diff')." +msgstr "" +"ní thacaítear le formáidí diff comhcheangailte ('-c' agus '--cc') i\n" +"modh diff eolaire ('-d' agus '--dir-diff')." + +#: builtin/difftool.c +#, c-format +msgid "both files modified: '%s' and '%s'." +msgstr "modhnaigh an dá chomhad: '%s' agus '%s'." + +#: builtin/difftool.c +msgid "working tree file has been left." +msgstr "tá comhad crann oibre fágtha." + +#: builtin/difftool.c sequencer.c +#, c-format +msgid "could not copy '%s' to '%s'" +msgstr "ní fhéadfaí '%s' a chóipeáil chuig '%s'" + +#: builtin/difftool.c +#, c-format +msgid "temporary files exist in '%s'." +msgstr "tá comhaid shealadacha ann i '%s'." + +#: builtin/difftool.c +msgid "you may want to cleanup or recover these." +msgstr "b'fhéidir gur mhaith leat iad seo a ghlanadh nó a aisghabháil." + +#: builtin/difftool.c +#, c-format +msgid "failed: %d" +msgstr "theip ar: %d" + +#: builtin/difftool.c +msgid "use `diff.guitool` instead of `diff.tool`" +msgstr "bain úsáid as `diff.guitool` in ionad `diff.tool`" + +#: builtin/difftool.c +msgid "perform a full-directory diff" +msgstr "éagsúlacht eolaire lán-eolaire a dhéanamh" + +#: builtin/difftool.c +msgid "do not prompt before launching a diff tool" +msgstr "ná spreag sula seolann tú uirlis diff" + +#: builtin/difftool.c +msgid "use symlinks in dir-diff mode" +msgstr "bain úsáid as naisc siombailte i mód dir-diff" + +#: builtin/difftool.c +msgid "tool" +msgstr "uirlis" + +#: builtin/difftool.c +msgid "use the specified diff tool" +msgstr "bain úsáid as an uirlis diff sonraithe" + +#: builtin/difftool.c +msgid "print a list of diff tools that may be used with `--tool`" +msgstr "liosta d'uirlisí diff is féidir a úsáid le `--tool` a phriontáil" + +#: builtin/difftool.c +msgid "" +"make 'git-difftool' exit when an invoked diff tool returns a non-zero exit " +"code" +msgstr "" +"imeacht 'git-difftool' a dhéanamh nuair a fhilleann uirlis diff a ghairmtear " +"cód imeachta neamh-nialasach" + +#: builtin/difftool.c +msgid "specify a custom command for viewing diffs" +msgstr "sonraigh ordú saincheaptha chun féachaint ar dhifríochtaí" + +#: builtin/difftool.c +msgid "passed to `diff`" +msgstr "cuireadh chuig `diff`" + +#: builtin/difftool.c +msgid "difftool requires worktree or --no-index" +msgstr "éilíonn difftool crann oibre nó --no-index" + +#: builtin/difftool.c +msgid "no given for --tool=" +msgstr "níl aon tu gadh le haghaidh --tool=" + +#: builtin/difftool.c +msgid "no given for --extcmd=" +msgstr "níl tugtha do --extcmd=" + +#: builtin/fast-export.c +msgid "git fast-export []" +msgstr "git fast-export []" + +#: builtin/fast-export.c +msgid "Error: Cannot export nested tags unless --mark-tags is specified." +msgstr "" +"Earráid: Ní féidir clibeanna neadaithe a onnmhairiú mura sonraítear --mark-" +"tags." + +#: builtin/fast-export.c +msgid "--anonymize-map token cannot be empty" +msgstr "Ní féidir le comhartha --anonymize-map a bheith folamh" + +#: builtin/fast-export.c +msgid "show progress after objects" +msgstr "dhul chun cinn a thaispe áint" + +#: builtin/fast-export.c +msgid "select handling of signed tags" +msgstr "roghnaigh láimhseáil na clibeanna" + +#: builtin/fast-export.c +msgid "select handling of signed commits" +msgstr "roghnaigh láimhseáil tiomantas sínithe" + +#: builtin/fast-export.c +msgid "select handling of tags that tag filtered objects" +msgstr "roghnaigh láimhseáil clibeanna a ligeann rudaí" + +#: builtin/fast-export.c +msgid "select handling of commit messages in an alternate encoding" +msgstr "roghnaigh láimhseáil teachtaireachtaí tiomanta i ionchódú" + +#: builtin/fast-export.c +msgid "dump marks to this file" +msgstr "marcanna dumpáil chuig an gcomhad seo" + +#: builtin/fast-export.c +msgid "import marks from this file" +msgstr "marcanna iompórtáil ón gcomhad seo" + +#: builtin/fast-export.c +msgid "import marks from this file if it exists" +msgstr "marcanna a iompórtáil ón gcomhad seo má tá sé ann" + +#: builtin/fast-export.c +msgid "fake a tagger when tags lack one" +msgstr "clibeoir bréige nuair nach bhfuil ceann ag clibeanna" + +#: builtin/fast-export.c +msgid "output full tree for each commit" +msgstr "aschur crann iomlán do gach tiomantas" + +#: builtin/fast-export.c +msgid "use the done feature to terminate the stream" +msgstr "úsáid an ghné déanta chun an sruth a fhoirceannadh" + +#: builtin/fast-export.c +msgid "skip output of blob data" +msgstr "scipeáil aschur sonraí blob" + +#: builtin/fast-export.c builtin/log.c +msgid "refspec" +msgstr "refspec" + +#: builtin/fast-export.c +msgid "apply refspec to exported refs" +msgstr "refspec a chur i bhfeidhm ar thaifeanna onnmhair" + +#: builtin/fast-export.c +msgid "anonymize output" +msgstr "aschur gan ainm" + +#: builtin/fast-export.c +msgid "from:to" +msgstr "ó:go" + +#: builtin/fast-export.c +msgid "convert to in anonymized output" +msgstr "tiontaigh go in aschur gan ainm" + +#: builtin/fast-export.c +msgid "reference parents which are not in fast-export stream by object id" +msgstr "" +"tuismitheoirí tagartha nach bhfuil i sruth tapa onnmhairithe de réir id réad" + +#: builtin/fast-export.c +msgid "show original object ids of blobs/commits" +msgstr "taispeáin id réad bunaidh de bhlobanna/gealltanna" + +#: builtin/fast-export.c +msgid "label tags with mark ids" +msgstr "clibeanna lipéad le id marc" + +#: builtin/fast-import.c +#, c-format +msgid "Missing from marks for submodule '%s'" +msgstr "Ar iarraidh ó mharcanna don fho-mhodúl '%s'" + +#: builtin/fast-import.c +#, c-format +msgid "Missing to marks for submodule '%s'" +msgstr "Ar iarraidh marcanna don fho-mhodúl '%s'" + +#: builtin/fast-import.c +#, c-format +msgid "Expected 'mark' command, got %s" +msgstr "Táthar ag súil leis an ordú 'marc', fuair %s" + +#: builtin/fast-import.c +#, c-format +msgid "Expected 'to' command, got %s" +msgstr "Táthar ag súil leis an ordú 'to', fuair %s" + +#: builtin/fast-import.c +msgid "Expected format name:filename for submodule rewrite option" +msgstr "" +"Ainm formáid a bhfuil súil leis ainm comhaid don rogha athscríobh fo-mhodúil" + +#: builtin/fast-import.c +#, c-format +msgid "feature '%s' forbidden in input without --allow-unsafe-features" +msgstr "feature '%s' forbidden in input without --allow-unsafe-features" + +#: builtin/fetch-pack.c +#, c-format +msgid "Lockfile created but not reported: %s" +msgstr "Cruthaíodh comhad Lockfile ach nár tuairiscigh: %s" + +#: builtin/fetch.c +msgid "git fetch [] [ [...]]" +msgstr "git fetch [] [ [...]]" + +#: builtin/fetch.c +msgid "git fetch [] " +msgstr "git fetch [] " + +#: builtin/fetch.c +msgid "git fetch --multiple [] [( | )...]" +msgstr "git fetch --multiple [] [( | )...]" + +#: builtin/fetch.c +msgid "git fetch --all []" +msgstr "git fetch --all []" + +#: builtin/fetch.c +msgid "fetch.parallel cannot be negative" +msgstr "ní féidir fetch.parallel a bheith diúltach" + +#: builtin/fetch.c +msgid "couldn't find remote ref HEAD" +msgstr "ní raibh in ann ciantagartha HEAD a fháil" + +#: builtin/fetch.c +#, c-format +msgid "From %.*s\n" +msgstr "Ó %.*s\n" + +#: builtin/fetch.c +#, c-format +msgid "object %s not found" +msgstr "níor aimsíodh réad %s" + +#: builtin/fetch.c +msgid "[up to date]" +msgstr "[cothrom le dáta]" + +#: builtin/fetch.c +msgid "[rejected]" +msgstr "[diúltaithe]" + +#: builtin/fetch.c +msgid "can't fetch into checked-out branch" +msgstr "ní féidir teacht isteach i mbrainse seiceáilte" + +#: builtin/fetch.c +msgid "[tag update]" +msgstr "[Nuashonrú tag]" + +#: builtin/fetch.c +msgid "unable to update local ref" +msgstr "in ann tagairt áitiúil a nuashonrú" + +#: builtin/fetch.c +msgid "would clobber existing tag" +msgstr "chuirfeadh an chlib atá ann cheana" + +#: builtin/fetch.c +msgid "[new tag]" +msgstr "[tag nua]" + +#: builtin/fetch.c +msgid "[new branch]" +msgstr "[brainse nua]" + +#: builtin/fetch.c +msgid "[new ref]" +msgstr "[tagartha nua]" + +#: builtin/fetch.c +msgid "forced update" +msgstr "nuashonrú éigeant" + +#: builtin/fetch.c +msgid "non-fast-forward" +msgstr "neamh-tapa ar aghaidh" + +#: builtin/fetch.c builtin/grep.c sequencer.c +#, c-format +msgid "cannot open '%s'" +msgstr "ní féidir '%s' a oscailt" + +#: builtin/fetch.c +msgid "" +"fetch normally indicates which branches had a forced update,\n" +"but that check has been disabled; to re-enable, use '--show-forced-updates'\n" +"flag or run 'git config fetch.showForcedUpdates true'" +msgstr "" +"is gnách go léiríonn teacht na brainsí a raibh nuashonrú éigeantach orthu,\n" +"ach tá an seiceáil sin díchumasaithe; chun athchumasú, bain úsáid as '--show-" +"forced-updates'\n" +"bratach nó rith 'git config fetch.showForcedUpdates true'" + +#: builtin/fetch.c +#, c-format +msgid "" +"it took %.2f seconds to check forced updates; you can use\n" +"'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates " +"false'\n" +"to avoid this check\n" +msgstr "" +"thóg sé %.2f soicind chun nuashonruithe éigeantacha a sheiceáil; is féidir " +"leat úsáid\n" +"'--no-show-forced-updates 'nó rith 'git config fetch.showForcedUpdates " +"bréaga'\n" +"chun an seiceáil seo a sheachaint\n" + +#: builtin/fetch.c +#, c-format +msgid "%s did not send all necessary objects" +msgstr "Níor sheol %s na rudaí riachtanacha go léir" + +#: builtin/fetch.c +#, c-format +msgid "rejected %s because shallow roots are not allowed to be updated" +msgstr "dhiúltaigh %s toisc nach gceadaítear fréamhacha éadmhara a nuashonrú" + +#: builtin/fetch.c +#, c-format +msgid "" +"some local refs could not be updated; try running\n" +" 'git remote prune %s' to remove any old, conflicting branches" +msgstr "" +"ní fhéadfaí roinnt fios áitiúla a nuashonrú; déan iarracht rith\n" +" 'git remote prune%s' chun aon bhrainsí sean-fhrithsheasmhach a bhaint" + +#: builtin/fetch.c +#, c-format +msgid " (%s will become dangling)" +msgstr " (beidh %s ag crochadh)" + +#: builtin/fetch.c +#, c-format +msgid " (%s has become dangling)" +msgstr " (%s has become dangling)" + +#: builtin/fetch.c +msgid "[deleted]" +msgstr "[scriosta]" + +#: builtin/fetch.c builtin/remote.c +msgid "(none)" +msgstr "(níl aon)" + +#: builtin/fetch.c +#, c-format +msgid "refusing to fetch into branch '%s' checked out at '%s'" +msgstr "ag diúltú teacht isteach i mbrainse '%s' a sheiceáil amach ag '%s'" + +#: builtin/fetch.c +#, c-format +msgid "option \"%s\" value \"%s\" is not valid for %s" +msgstr "níl an rogha “%s” luach “%s” bailí do %s" + +#: builtin/fetch.c +#, c-format +msgid "option \"%s\" is ignored for %s" +msgstr "déantar neamhaird ar rogha “%s” do %s" + +#: builtin/fetch.c object-store.c +#, c-format +msgid "%s is not a valid object" +msgstr "Ní réad bailí é %s" + +#: builtin/fetch.c +#, c-format +msgid "the object %s does not exist" +msgstr "níl an réad %s ann" + +#: builtin/fetch.c +#, c-format +msgid "" +"Run 'git remote set-head %s %s' to follow the change, or set\n" +"'remote.%s.followRemoteHEAD' configuration option to a different value\n" +"if you do not want to see this message. Specifically running\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"will disable the warning until the remote changes HEAD to something else." +msgstr "" +"Rith 'git remote set-head %s %s' chun an t-athrú a leanúint, nó socraigh\n" +"rogha cumraíochta 'remote.%s.followRemoteHEAD' go luach difriúil\n" +"mura mian leat an teachtaireacht seo a fheiceáil. Go sonrach, má ritheann " +"tú\n" +"'git config set remote.%s.followRemoteHEAD warn-if-not-branch-%s'\n" +"díchumasófar an rabhadh go dtí go n-athraíonn an cianda HEAD go rud éigin " +"eile." + +#: builtin/fetch.c +msgid "multiple branches detected, incompatible with --set-upstream" +msgstr "brainsí iolracha brainsí braite, gan oiriúint le --set-upstream" + +#: builtin/fetch.c +#, c-format +msgid "" +"could not set upstream of HEAD to '%s' from '%s' when it does not point to " +"any branch." +msgstr "" +"ní fhéadfaí suas sruth de HEAD a shocrú go '%s' ó '%s' nuair nach dtugann sé " +"in iúl go dtí aon bhrainse." + +#: builtin/fetch.c +msgid "not setting upstream for a remote remote-tracking branch" +msgstr "gan socrú suas sruth do bhrainse cianrianaithe" + +#: builtin/fetch.c +msgid "not setting upstream for a remote tag" +msgstr "gan a shocrú suas sruth le haghaidh clib iargúlta" + +#: builtin/fetch.c +msgid "unknown branch type" +msgstr "cineál brainse anaithnid" + +#: builtin/fetch.c +msgid "" +"no source branch found;\n" +"you need to specify exactly one branch with the --set-upstream option" +msgstr "" +"ní bhfuarthas aon bhrainse foinse;\n" +"ní mór duit brainse amháin a shonrú go díreach leis an rogha --set-upstream" + +#: builtin/fetch.c +#, c-format +msgid "Fetching %s\n" +msgstr "Ag tarraingt %s\n" + +#: builtin/fetch.c +#, c-format +msgid "could not fetch %s" +msgstr "ní fhéadfaí %s a fháil" + +#: builtin/fetch.c +#, c-format +msgid "could not fetch '%s' (exit code: %d)\n" +msgstr "níorbh fhéidir '%s' a fháil (cód scoir: %d)\n" + +#: builtin/fetch.c +msgid "" +"no remote repository specified; please specify either a URL or a\n" +"remote name from which new revisions should be fetched" +msgstr "" +"níl aon stór iargúlta sonraithe; sonraigh URL nó a\n" +"ainm iargúlta ar chóir athbhreithnithe nua a fháil" + +#: builtin/fetch.c +msgid "you need to specify a tag name" +msgstr "ní mór duit ainm clib a shonrú" + +#: builtin/fetch.c builtin/pull.c +msgid "fetch from all remotes" +msgstr "faigh ó gach iargúlta" + +#: builtin/fetch.c builtin/pull.c +msgid "set upstream for git pull/fetch" +msgstr "socraigh suas sruth le haghaidh git pull/fetch" + +#: builtin/fetch.c builtin/pull.c +msgid "append to .git/FETCH_HEAD instead of overwriting" +msgstr "cuir chuig .git/FETCH_HEAD in ionad athscríobh" + +#: builtin/fetch.c +msgid "use atomic transaction to update references" +msgstr "úsáid idirbheart adamach chun tagairtí a nuashonrú" + +#: builtin/fetch.c builtin/pull.c +msgid "path to upload pack on remote end" +msgstr "cosán chun pacáiste a uaslódáil ar iargúlta" + +#: builtin/fetch.c +msgid "force overwrite of local reference" +msgstr "tagairt áitiúil a fhorscríobh" + +#: builtin/fetch.c +msgid "fetch from multiple remotes" +msgstr "a fháil ó iomadúla iargúlta" + +#: builtin/fetch.c builtin/pull.c +msgid "fetch all tags and associated objects" +msgstr "gach clib agus rudaí gaolmhara a fháil" + +#: builtin/fetch.c +msgid "do not fetch all tags (--no-tags)" +msgstr "ná faigh gach clib (--no-tags)" + +#: builtin/fetch.c +msgid "number of submodules fetched in parallel" +msgstr "líon na bhfo-mhodúil a fuarthas go comhthreomhar" + +#: builtin/fetch.c +msgid "modify the refspec to place all refs within refs/prefetch/" +msgstr "an refspec a mhodhnú chun gach refs a chur laistigh de refs/prefetch/" + +#: builtin/fetch.c builtin/pull.c +msgid "prune remote-tracking branches no longer on remote" +msgstr "brainsí cianrianaithe a ghearradh nach bhfuil ar iargúlta a" + +#: builtin/fetch.c +msgid "prune local tags no longer on remote and clobber changed tags" +msgstr "" +"clibeanna áitiúla a ghearradh nach bhfuil ar chlibeanna iargúlta agus " +"athraithe clobber" + +#: builtin/fetch.c builtin/pull.c +msgid "on-demand" +msgstr "ar éileamh" + +#: builtin/fetch.c +msgid "control recursive fetching of submodules" +msgstr "tógáil athfhillteach fo-mhodúil a rialú" + +#: builtin/fetch.c +msgid "write fetched references to the FETCH_HEAD file" +msgstr "scríobh tagairtí faighte don chomhad FETCH_HEAD" + +#: builtin/fetch.c builtin/pull.c +msgid "keep downloaded pack" +msgstr "pacáiste íoslódáilte" + +#: builtin/fetch.c +msgid "allow updating of HEAD ref" +msgstr "cead a thabhairt do nuashonrú HEAD ref" + +#: builtin/fetch.c builtin/pull.c +msgid "deepen history of shallow clone" +msgstr "stair clón éadomhain a dhoimhniú" + +#: builtin/fetch.c builtin/pull.c +msgid "deepen history of shallow repository based on time" +msgstr "stair stór éadomhain a dhoimhniú bunaithe ar am" + +#: builtin/fetch.c builtin/pull.c +msgid "convert to a complete repository" +msgstr "tiontaigh go stór iomlán" + +#: builtin/fetch.c +msgid "re-fetch without negotiating common commits" +msgstr "athghabháil gan gealltanais choiteanna a chaibidliú" + +#: builtin/fetch.c +msgid "prepend this to submodule path output" +msgstr "é seo a chur ar aghaidh chuig aschur cosán fo-mhodúil" + +#: builtin/fetch.c +msgid "" +"default for recursive fetching of submodules (lower priority than config " +"files)" +msgstr "" +"réamhshocraithe maidir le fo-mhodúil a fháil athshlánach (tosaíocht níos " +"ísle ná comhaid chumraithe)" + +#: builtin/fetch.c builtin/pull.c +msgid "accept refs that update .git/shallow" +msgstr "glacadh le hiarrachtaí a nuashonraíonn .git/shalach" + +#: builtin/fetch.c builtin/pull.c +msgid "refmap" +msgstr "athléarscáil" + +#: builtin/fetch.c builtin/pull.c +msgid "specify fetch refmap" +msgstr "sonraigh refmap a fháil" + +#: builtin/fetch.c builtin/pull.c builtin/rebase.c builtin/replay.c +msgid "revision" +msgstr "athbhreithiú" + +#: builtin/fetch.c builtin/pull.c +msgid "report that we have only objects reachable from this object" +msgstr "tuairisciú nach bhfuil ach rudaí inrochtana againn ón réad seo" + +#: builtin/fetch.c +msgid "do not fetch a packfile; instead, print ancestors of negotiation tips" +msgstr "" +"ná faigh comhad pacáiste; ina ionad sin, priontáil sinsear leideanna " +"idirbheartaíochta" + +#: builtin/fetch.c +msgid "run 'maintenance --auto' after fetching" +msgstr "reáchtáil 'cothabháil --auto' tar éis a fháil" + +#: builtin/fetch.c builtin/pull.c +msgid "check for forced-updates on all updated branches" +msgstr "seiceáil ar nuashonruithe éigeantacha ar gach brainse nuashonraithe" + +#: builtin/fetch.c +msgid "write the commit-graph after fetching" +msgstr "scríobh an graf coimisiúnaithe tar éis a fháil" + +#: builtin/fetch.c +msgid "accept refspecs from stdin" +msgstr "glacadh le refspecs ó stdin" + +#: builtin/fetch.c +msgid "--negotiate-only needs one or more --negotiation-tip=*" +msgstr "" +"--negotiate-only teastaíonn ceann amháin nó níos mó --negotiation-tip=*" + +#: builtin/fetch.c +msgid "negative depth in --deepen is not supported" +msgstr "ní thacaítear le doimhneacht dhiúltach i --deepen" + +#: builtin/fetch.c +msgid "--unshallow on a complete repository does not make sense" +msgstr "níl ciall le --unshallow ar stórlann iomlán" + +#: builtin/fetch.c +#, c-format +msgid "failed to fetch bundles from '%s'" +msgstr "theip ar bhaclaí a fháil ó '%s'" + +#: builtin/fetch.c +msgid "fetch --all does not take a repository argument" +msgstr "ní ghlacann fetch --all argóint stór" + +#: builtin/fetch.c +msgid "fetch --all does not make sense with refspecs" +msgstr "ní bhíonn ciall ag teacht --all le refspecs" + +#: builtin/fetch.c +#, c-format +msgid "no such remote or remote group: %s" +msgstr "gan aon ghrúpa iargúlta nó cianda den sórt sin: %s" + +#: builtin/fetch.c +msgid "fetching a group and specifying refspecs does not make sense" +msgstr "níl ciall grúpa a fháil agus refspecs a shonrú" + +#: builtin/fetch.c +msgid "must supply remote when using --negotiate-only" +msgstr "ní mór iargúlta a sholáthar agus tú ag úsáid --negotiate-only" + +#: builtin/fetch.c +msgid "protocol does not support --negotiate-only, exiting" +msgstr "ní thacaíonn an prótacal le --negotiate-only, ag scoir" + +#: builtin/fetch.c +msgid "" +"--filter can only be used with the remote configured in " +"extensions.partialclone" +msgstr "" +"--filter Ní féidir ach an scagaire a úsáid ach leis an iargúlta cumraithe in " +"extensions.partialclone" + +#: builtin/fetch.c +msgid "--atomic can only be used when fetching from one remote" +msgstr "" +"--atomic ní féidir ach adamhach a úsáid ach amháin nuair a bhíonn sé á fháil " +"ó chianrialtán amháin" + +#: builtin/fetch.c +msgid "--stdin can only be used when fetching from one remote" +msgstr "" +"Ní féidir --stdin a úsáid ach amháin nuair a bhfaightear é ó iargúlta amháin" + +#: builtin/fmt-merge-msg.c +msgid "" +"git fmt-merge-msg [-m ] [--log[=] | --no-log] [--file ]" +msgstr "" +"git fmt-merge-msg [-m] [--log [=] | --no-log] [--comhad]" + +#: builtin/fmt-merge-msg.c +msgid "populate log with at most entries from shortlog" +msgstr "logáil a chomhlánú le hiontrálacha is mó ó ghearrlog" + +#: builtin/fmt-merge-msg.c +msgid "alias for --log (deprecated)" +msgstr "alias le haghaidh --log (mísheasmhach)" + +#: builtin/fmt-merge-msg.c +msgid "text" +msgstr "téacs" + +#: builtin/fmt-merge-msg.c +msgid "use as start of message" +msgstr "úsáid mar thús na teachtaireachta" + +#: builtin/fmt-merge-msg.c +msgid "use instead of the real target branch" +msgstr "úsáid in ionad na fíor-spriocbhrainse" + +#: builtin/fmt-merge-msg.c +msgid "file to read from" +msgstr "comhad le léamh ó" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [] []" +msgstr "git for-each-ref [] []" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [--points-at ]" +msgstr "git for-each-ref [--points-at ]" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [--merged []] [--no-merged []]" +msgstr "git for-each-ref [--merged []] [--no-merged []]" + +#: builtin/for-each-ref.c +msgid "git for-each-ref [--contains []] [--no-contains []]" +msgstr "git for-each-ref [--contains []] [--no-contains []]" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for shells" +msgstr "sealbhóirí áiteanna a luachan go oiriúnach do" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for perl" +msgstr "sealbhóirí áiteanna a luachan go oiriúnach do perl" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for python" +msgstr "sealbhóirí áiteanna a luaigh go oiriúnach do python" + +#: builtin/for-each-ref.c +msgid "quote placeholders suitably for Tcl" +msgstr "sealbhóirí áiteanna a luachan go oiriúnach do Tcl" + +#: builtin/for-each-ref.c +msgid "show only matched refs" +msgstr "taispeáin ach sonraí com hoiriúnaithe" + +#: builtin/for-each-ref.c builtin/tag.c +msgid "respect format colors" +msgstr "meas dathanna formáid" + +#: builtin/for-each-ref.c +msgid "print only refs which points at the given object" +msgstr "ní phriontáil ach téacsanna a phointíonn ar an réad a thugtar" + +#: builtin/for-each-ref.c +msgid "print only refs that are merged" +msgstr "ní phriontáil ach scríbhneoireachtaí atá cumasaithe" + +#: builtin/for-each-ref.c +msgid "print only refs that are not merged" +msgstr "priontáil ach scríbhinní nach bhfuil cumasc" + +#: builtin/for-each-ref.c +msgid "print only refs which contain the commit" +msgstr "ní phriontáil ach téifeanna ina bhfuil an tiomantas" + +#: builtin/for-each-ref.c +msgid "print only refs which don't contain the commit" +msgstr "ní phriontáil ach scríbhneoirí nach bhfuil an tiomantas" + +#: builtin/for-each-ref.c +msgid "read reference patterns from stdin" +msgstr "léigh patrúin tagartha ó stdin" + +#: builtin/for-each-ref.c +msgid "also include HEAD ref and pseudorefs" +msgstr "san áireamh freisin HEAD ref agus pseudorefs" + +#: builtin/for-each-ref.c +msgid "unknown arguments supplied with --stdin" +msgstr "argóintí anaithnid a sholáthraítear le --stdin" + +#: builtin/for-each-repo.c +msgid "git for-each-repo --config= [--] " +msgstr "git for-each-repo --config= [--] " + +#: builtin/for-each-repo.c +msgid "config" +msgstr "cumraíocht" + +#: builtin/for-each-repo.c +msgid "config key storing a list of repository paths" +msgstr "eochair chumraithe a stóráil liosta de chosáin stórais" + +#: builtin/for-each-repo.c +msgid "keep going even if command fails in a repository" +msgstr "coinnigh ort fiú má theipeann an t-ordú i stóras" + +#: builtin/for-each-repo.c +msgid "missing --config=" +msgstr "ar iarraidh --config=" + +#: builtin/for-each-repo.c +#, c-format +msgid "got bad config --config=%s" +msgstr "fuair go dona cumraíocht --config=%s" + +#: builtin/fsck.c +msgid "unknown" +msgstr "anaithnid" + +#. TRANSLATORS: e.g. error in tree 01bfda: +#: builtin/fsck.c +#, c-format +msgid "error in %s %s: %s" +msgstr "earráid i %s %s: %s" + +#. TRANSLATORS: e.g. warning in tree 01bfda: +#: builtin/fsck.c +#, c-format +msgid "warning in %s %s: %s" +msgstr "rabhadh i %s %s: %s" + +#: builtin/fsck.c +#, c-format +msgid "broken link from %7s %s" +msgstr "nasc briste ó %7s %s" + +#: builtin/fsck.c +msgid "wrong object type in link" +msgstr "cineál réad mícheart i nasc" + +#: builtin/fsck.c +#, c-format +msgid "" +"broken link from %7s %s\n" +" to %7s %s" +msgstr "" +"nasc briste ó %7s %s\n" +" chuig %7s %s" + +#: builtin/fsck.c builtin/prune.c connected.c +msgid "Checking connectivity" +msgstr "Nascacht a sheiceáil" + +#: builtin/fsck.c +#, c-format +msgid "missing %s %s" +msgstr "%s %s ar iarraidh" + +#: builtin/fsck.c +#, c-format +msgid "unreachable %s %s" +msgstr "%s %s neamh-inrochtana" + +#: builtin/fsck.c +#, c-format +msgid "dangling %s %s" +msgstr "ag crochadh %s %s" + +#: builtin/fsck.c +msgid "could not create lost-found" +msgstr "ní fhéadfaí a chruthú a aimsíodh caillte" + +#: builtin/fsck.c builtin/gc.c builtin/rebase.c rebase-interactive.c rerere.c +#: sequencer.c +#, c-format +msgid "could not write '%s'" +msgstr "ní fhéadfaí '%s' a scríobh" + +#: builtin/fsck.c +#, c-format +msgid "could not finish '%s'" +msgstr "ní raibh '%s' in ann a chríochnú" + +#: builtin/fsck.c +#, c-format +msgid "Checking %s" +msgstr "Seiceáil %s" + +#: builtin/fsck.c +#, c-format +msgid "Checking connectivity (%d objects)" +msgstr "Ag seiceáil nascachta (%d réad)" + +#: builtin/fsck.c +#, c-format +msgid "Checking %s %s" +msgstr "Seiceáil %s %s" + +#: builtin/fsck.c +msgid "broken links" +msgstr "naisc briste" + +#: builtin/fsck.c +#, c-format +msgid "root %s" +msgstr "fréamh %s" + +#: builtin/fsck.c +#, c-format +msgid "tagged %s %s (%s) in %s" +msgstr "clib %s %s (%s) i %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: object corrupt or missing" +msgstr "%s: réad truaillithe nó ar iarraidh" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid reflog entry %s" +msgstr "%s: iontráil reflog neamhbhailí %s" + +#: builtin/fsck.c +#, c-format +msgid "Checking reflog %s->%s" +msgstr "Seiceáil reflog %s->%s" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid sha1 pointer %s" +msgstr "%s: pointeoir sha1 neamhbhailí %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: not a commit" +msgstr "%s: ní gealltanas" + +#: builtin/fsck.c +msgid "notice: No default references" +msgstr "fógra: Gan aon tagairtí réamhshocraithe" + +#: builtin/fsck.c +#, c-format +msgid "%s: hash-path mismatch, found at: %s" +msgstr "%s: míchomhoiriúnú hash-path, le fáil ag: %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: object corrupt or missing: %s" +msgstr "%s: réad truaillithe nó ar iarraidh: %s" + +#: builtin/fsck.c +#, c-format +msgid "%s: object could not be parsed: %s" +msgstr "%s: ní fhéadfaí réad a pháirseáil: %s" + +#: builtin/fsck.c +#, c-format +msgid "bad sha1 file: %s" +msgstr "comhad sha1 olc: %s" + +#: builtin/fsck.c +msgid "Checking object directory" +msgstr "Seiceáil eolaire réada" + +#: builtin/fsck.c +msgid "Checking object directories" +msgstr "Seiceáil eolairí réada" + +#: builtin/fsck.c +#, c-format +msgid "Checking %s link" +msgstr "Nasc %s a sheiceáil" + +#: builtin/fsck.c builtin/index-pack.c +#, c-format +msgid "invalid %s" +msgstr "%s neamhbhailí" + +#: builtin/fsck.c +#, c-format +msgid "%s points to something strange (%s)" +msgstr "Léiríonn %s rud éigin aisteach (%s)" + +#: builtin/fsck.c +#, c-format +msgid "%s: detached HEAD points at nothing" +msgstr "%s: pointí HEAD scoite ag aon rud" + +#: builtin/fsck.c +#, c-format +msgid "notice: %s points to an unborn branch (%s)" +msgstr "fógra: Díríonn %s chuig brainse neamhbhreithe (%s)" + +#: builtin/fsck.c +#, c-format +msgid "Checking cache tree of %s" +msgstr "Crann taisce de %s a sheiceáil" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid sha1 pointer in cache-tree of %s" +msgstr "%s: pointeoir sha1 neamhbhailí i gcrann cache-%s" + +#: builtin/fsck.c +msgid "non-tree in cache-tree" +msgstr "neamh-chrann i gcrann cache-" + +#: builtin/fsck.c +#, c-format +msgid "%s: invalid sha1 pointer in resolve-undo of %s" +msgstr "%s: pointeoir sha1 neamhbhailí i réiteach a chealú de %s" + +#: builtin/fsck.c +#, c-format +msgid "unable to load rev-index for pack '%s'" +msgstr "in ann innéacs rev-innéacs a luchtú do phacáiste '%s'" + +#: builtin/fsck.c +#, c-format +msgid "invalid rev-index for pack '%s'" +msgstr "innéacs rev-neamhbhailí do phacáiste '%s'" + +#: builtin/fsck.c +msgid "Checking ref database" +msgstr "Seiceáil bunachar sonraí tagairt" + +#: builtin/fsck.c +msgid "" +"git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" +" [--[no-]full] [--strict] [--verbose] [--lost-found]\n" +" [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" +" [--[no-]name-objects] [--[no-]references] [...]" +msgstr "" +"git fsck [--tags] [--root] [--inrochtana] [--cache] [--no-reflogs]\n" +" [-- [no-] iomlán] [--dian] [--verbose] [--caillte]\n" +" [-- [gan-] ag crochadh] [-- [gan-] dul chun cinn] [--nascacht amháin]\n" +" [-- [no-] ainm-rudaí] [-- [aon-] tagairtí] [...]" + +#: builtin/fsck.c +msgid "show unreachable objects" +msgstr "taispeáint rudaí dochreidte" + +#: builtin/fsck.c +msgid "show dangling objects" +msgstr "taispeáin rudaí crochtanacha" + +#: builtin/fsck.c +msgid "report tags" +msgstr "clibeanna tuarascála" + +#: builtin/fsck.c +msgid "report root nodes" +msgstr "nóid fréimhe a thuairisc" + +#: builtin/fsck.c +msgid "make index objects head nodes" +msgstr "nóid ceann rudaí innéacs a dhéanamh" + +#: builtin/fsck.c +msgid "make reflogs head nodes (default)" +msgstr "nóid ceann reflogs a dhéanamh (réamhshocraithe)" + +#: builtin/fsck.c +msgid "also consider packs and alternate objects" +msgstr "smaoinigh freisin ar phacáistí agus rudaí" + +#: builtin/fsck.c +msgid "check only connectivity" +msgstr "seiceáil ach nascacht" + +#: builtin/fsck.c builtin/mktag.c +msgid "enable more strict checking" +msgstr "cumasú seiceáil níos docht" + +#: builtin/fsck.c +msgid "write dangling objects in .git/lost-found" +msgstr "scríobh rudaí crochta in .git/lost-found" + +#: builtin/fsck.c builtin/prune.c +msgid "show progress" +msgstr "taispeáin dul chun cinn" + +#: builtin/fsck.c +msgid "show verbose names for reachable objects" +msgstr "taispeáint ainmneacha fabhracha do rudaí inrochtana" + +#: builtin/fsck.c +msgid "check reference database consistency" +msgstr "seiceáil comhsheasmhacht bunachair" + +#: builtin/fsck.c builtin/index-pack.c +msgid "Checking objects" +msgstr "Rud a sheiceáil" + +#: builtin/fsck.c +#, c-format +msgid "%s: object missing" +msgstr "%s: réad ar iarraidh" + +#: builtin/fsck.c +#, c-format +msgid "invalid parameter: expected sha1, got '%s'" +msgstr "paraiméadar neamhbhailí: súil le sha1, fuair '%s'" + +#: builtin/fsmonitor--daemon.c +msgid "git fsmonitor--daemon start []" +msgstr "git fsmonitor--daemon start []" + +#: builtin/fsmonitor--daemon.c +msgid "git fsmonitor--daemon run []" +msgstr "git fsmonitor--daemon run []" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "value of '%s' out of range: %d" +msgstr "luach '%s' lasmuigh den raon: %d" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "value of '%s' not bool or int: %d" +msgstr "luach '%s' gan bool nó int: %d" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor-daemon is watching '%s'\n" +msgstr "tá fsmonitor-daemon ag féachaint ar '%s'\n" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor-daemon is not watching '%s'\n" +msgstr "níl fsmonitor-daemon ag féachaint ar '%s'\n" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "could not create fsmonitor cookie '%s'" +msgstr "ní fhéadfaí fianán fsmonitor '%s' a chruthú" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor: cookie_result '%d' != SEEN" +msgstr "fsmonitor: cookie_result '%d' != SEEN" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "could not start IPC thread pool on '%s'" +msgstr "ní fhéadfaí linn snáithe IPC a thosú ar '%s'" + +#: builtin/fsmonitor--daemon.c +msgid "could not start fsmonitor listener thread" +msgstr "ní fhéadfaí snáithe éisteora fsmonitor a thosú" + +#: builtin/fsmonitor--daemon.c +msgid "could not start fsmonitor health thread" +msgstr "ní fhéadfaí snáithe sláinte fsmonitor a thosú" + +#: builtin/fsmonitor--daemon.c +msgid "could not initialize listener thread" +msgstr "ní fhéadfadh snáithe éisteora a thionscnamh" + +#: builtin/fsmonitor--daemon.c +msgid "could not initialize health thread" +msgstr "ní fhéadfaí snáithe sláinte a thionscnamh" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "could not cd home '%s'" +msgstr "ní fhéadfaí cd baile '%s'" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "fsmonitor--daemon is already running '%s'" +msgstr "tá fsmonitor--daemon ag rith '%s' cheana féin" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "running fsmonitor-daemon in '%s'\n" +msgstr "ag rith fsmonitor-daemon i '%s'\n" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "starting fsmonitor-daemon in '%s'\n" +msgstr "ag tosú fsmonitor-daemon i '%s'\n" + +#: builtin/fsmonitor--daemon.c +msgid "daemon failed to start" +msgstr "theip ar daemon a thosú" + +#: builtin/fsmonitor--daemon.c +msgid "daemon not online yet" +msgstr "daemon nach bhfuil ar líne fós" + +#: builtin/fsmonitor--daemon.c +msgid "daemon terminated" +msgstr "deireadh le déemon" + +#: builtin/fsmonitor--daemon.c +msgid "detach from console" +msgstr "dícheangal ón gconsól" + +#: builtin/fsmonitor--daemon.c +msgid "use ipc worker threads" +msgstr "úsáid snái theanna oibrithe ipc" + +#: builtin/fsmonitor--daemon.c +msgid "max seconds to wait for background daemon startup" +msgstr "soicind uasta chun fanacht le tosú daemon cúlra" + +#: builtin/fsmonitor--daemon.c +#, c-format +msgid "invalid 'ipc-threads' value (%d)" +msgstr "luach 'ipc-snáitheanna' neamhbhailí (%d)" + +#: builtin/fsmonitor--daemon.c t/helper/test-cache-tree.c +#, c-format +msgid "Unhandled subcommand '%s'" +msgstr "Foordú neamh-láimhseáilte '%s'" + +#: builtin/fsmonitor--daemon.c +msgid "fsmonitor--daemon not supported on this platform" +msgstr "fsmonitor--daemon nach dtacaíonn sé ar an ardán seo" + +#: builtin/gc.c +msgid "git gc []" +msgstr "git gc []" + +#: builtin/gc.c +#, c-format +msgid "Failed to fstat %s: %s" +msgstr "Theip ar fstat %s: %s" + +#: builtin/gc.c +#, c-format +msgid "failed to parse '%s' value '%s'" +msgstr "theip ar luach '%s' a pharsáil '%s'" + +#: builtin/gc.c setup.c +#, c-format +msgid "cannot stat '%s'" +msgstr "ní féidir '%s' a stát" + +#: builtin/gc.c +#, c-format +msgid "" +"The last gc run reported the following. Please correct the root cause\n" +"and remove %s\n" +"Automatic cleanup will not be performed until the file is removed.\n" +"\n" +"%s" +msgstr "" +"Tuairiscigh an rith gc deireanach an méid seo a leanas Ceartaigh an bunchúis " +"le do thoil\n" +"agus bain %s\n" +"Ní dhéanfar glantachán uathoibríoch go dtí go mbainfear an comhad.\n" +"\n" +"%s" + +#: builtin/gc.c +msgid "prune unreferenced objects" +msgstr "rudaí gan tagairt a ghearradh" + +#: builtin/gc.c +msgid "pack unreferenced objects separately" +msgstr "rudaí gan tagairt a phacáil ar leithligh" + +#: builtin/gc.c builtin/repack.c +msgid "with --cruft, limit the size of new cruft packs" +msgstr "le --cruft, teorainn le méid pacáistí cruft nua" + +#: builtin/gc.c +msgid "be more thorough (increased runtime)" +msgstr "a bheith níos críochnúla (tréimhse méadaithe)" + +#: builtin/gc.c +msgid "enable auto-gc mode" +msgstr "mód auto-gc a chumasú" + +#: builtin/gc.c +msgid "perform garbage collection in the background" +msgstr "bailiú truflais a dhéanamh sa chúlra" + +#: builtin/gc.c +msgid "force running gc even if there may be another gc running" +msgstr "fórsa ag rith gc fiú má d'fhéadfadh gc eile a bheith ag rith" + +#: builtin/gc.c +msgid "repack all other packs except the largest pack" +msgstr "gach pacáiste eile a athphacáil ach amháin an pacáiste is mó" + +#: builtin/gc.c builtin/repack.c +msgid "pack prefix to store a pack containing pruned objects" +msgstr "réimír pacáiste chun pacáiste ina bhfuil rudaí gearrtha a stóráil" + +#: builtin/gc.c +#, c-format +msgid "failed to parse gc.logExpiry value %s" +msgstr "theip ar luach gc.logExpiry %s a pháirseáil" + +#: builtin/gc.c +#, c-format +msgid "failed to parse prune expiry value %s" +msgstr "theip ar luach éaga brúite %s a pharsáil" + +#: builtin/gc.c +#, c-format +msgid "Auto packing the repository in background for optimum performance.\n" +msgstr "Pacáil uathoibríoch an stór sa chúlra chun an fheidhmíocht is fearr\n" + +#: builtin/gc.c +#, c-format +msgid "Auto packing the repository for optimum performance.\n" +msgstr "Pacáil uathoibríoch an stór chun an fheidhmíocht is fearr\n" + +#: builtin/gc.c +#, c-format +msgid "See \"git help gc\" for manual housekeeping.\n" +msgstr "Féach \"git help gc\" le haghaidh obair tí láimhe.\n" + +#: builtin/gc.c +#, c-format +msgid "" +"gc is already running on machine '%s' pid % (use --force if not)" +msgstr "" +"tá gc ag rith cheana féin ar mheaisín '%s' pid%(bain úsáid as --" +"force mura bhfuil)" + +#: builtin/gc.c +msgid "" +"There are too many unreachable loose objects; run 'git prune' to remove them." +msgstr "" +"Tá an iomarca rudaí scaoilte neamh-inrochtana ann; reáchtáil 'git prune' " +"chun iad a bhaint." + +#: builtin/gc.c +msgid "" +"git maintenance run [--auto] [--[no-]quiet] [--task=] [--schedule]" +msgstr "" +"rith cothabhála git [--auto] [-- [no-] ciúin] [--task=] [--schedule]" + +#: builtin/gc.c +msgid "--no-schedule is not allowed" +msgstr "Ní cheadaítear --no-schedule" + +#: builtin/gc.c +#, c-format +msgid "unrecognized --schedule argument '%s'" +msgstr "argóint --schedule gan aithint '%s'" + +#: builtin/gc.c +msgid "failed to write commit-graph" +msgstr "theip orthu graf coimisiúnaithe a scríobh" + +#: builtin/gc.c +msgid "failed to prefetch remotes" +msgstr "theip ar iargúlta iargúlta a réamhghabháil" + +#: builtin/gc.c +msgid "failed to start 'git pack-objects' process" +msgstr "theip ar phróiseas 'git pack-objects' a thosú" + +#: builtin/gc.c +msgid "failed to finish 'git pack-objects' process" +msgstr "theip ar phróiseas 'git pack-objects' a chríochnú" + +#: builtin/gc.c +msgid "failed to write multi-pack-index" +msgstr "theip ar innéacs il-phacáiste a scríobh" + +#: builtin/gc.c +msgid "'git multi-pack-index expire' failed" +msgstr "Theip ar 'git multi-pack-index in éag'" + +#: builtin/gc.c +msgid "'git multi-pack-index repack' failed" +msgstr "Theip ar 'git multi-pack-index repack'" + +#: builtin/gc.c +msgid "" +"skipping incremental-repack task because core.multiPackIndex is disabled" +msgstr "" +"tasc athphacáil fáis a scipeáil toisc go bhfuil core.multiPackIndex " +"díchumasaithe" + +#: builtin/gc.c +#, c-format +msgid "lock file '%s' exists, skipping maintenance" +msgstr "tá comhad glasála '%s' ann, ag scipeáil cothabháil" + +#: builtin/gc.c +#, c-format +msgid "task '%s' failed" +msgstr "theip ar thasc '%s'" + +#: builtin/gc.c +#, c-format +msgid "'%s' is not a valid task" +msgstr "Ní tasc bailí é '%s'" + +#: builtin/gc.c +#, c-format +msgid "task '%s' cannot be selected multiple times" +msgstr "ní féidir tasc '%s' a roghnú arís agus arís eile" + +#: builtin/gc.c +msgid "run tasks based on the state of the repository" +msgstr "tascanna a reáchtáil bunaithe ar staid an stór" + +#: builtin/gc.c +msgid "perform maintenance in the background" +msgstr "cothabháil a dhéanamh sa chúlra" + +#: builtin/gc.c +msgid "frequency" +msgstr "minicíocht" + +#: builtin/gc.c +msgid "run tasks based on frequency" +msgstr "tascanna a rith bunaithe ar mhinicíocht" + +#: builtin/gc.c +msgid "do not report progress or other information over stderr" +msgstr "ná tuairiscigh dul chun cinn nó faisnéis eile faoi stderr" + +#: builtin/gc.c +msgid "task" +msgstr "tasc" + +#: builtin/gc.c +msgid "run a specific task" +msgstr "tasc ar leith a reáchtáil" + +#: builtin/gc.c +msgid "use at most one of --auto and --schedule=" +msgstr "bain úsáid as --auto agus --schedule= ar a mhéad" + +#: builtin/gc.c +#, c-format +msgid "unable to add '%s' value of '%s'" +msgstr "nach féidir luach '%s' de '%s' a chur leis" + +#: builtin/gc.c +msgid "return success even if repository was not registered" +msgstr "rath ar ais fiú mura raibh stór cláraithe" + +#: builtin/gc.c +#, c-format +msgid "unable to unset '%s' value of '%s'" +msgstr "nach féidir luach '%s' de '%s' a dhíshocrú" + +#: builtin/gc.c +#, c-format +msgid "repository '%s' is not registered" +msgstr "níl stór '%s' cláraithe" + +#: builtin/gc.c +#, c-format +msgid "failed to expand path '%s'" +msgstr "theip ar an gcosán '%s' a leathnú" + +#: builtin/gc.c +msgid "failed to start launchctl" +msgstr "theip ar launchctl a thosú" + +#: builtin/gc.c +#, c-format +msgid "failed to create directories for '%s'" +msgstr "theip ar eolairí a chruthú do '%s'" + +#: builtin/gc.c +#, c-format +msgid "failed to bootstrap service %s" +msgstr "theip ar sheirbhís bootstrap %s" + +#: builtin/gc.c +msgid "failed to create temp xml file" +msgstr "theip ar chomhad xml temp a chruthú" + +#: builtin/gc.c +msgid "failed to start schtasks" +msgstr "theip ar schasks a thosú" + +#: builtin/gc.c +msgid "failed to run 'crontab -l'; your system might not support 'cron'" +msgstr "" +"theip ar 'crontab -l' a reáchtáil; b'fhéidir nach dtacaíonn do chóras le " +"'cron'" + +#: builtin/gc.c +msgid "failed to create crontab temporary file" +msgstr "theip ar chomhad sealadach crontab a chruthú" + +#: builtin/gc.c +msgid "failed to open temporary file" +msgstr "theip ar chomhad sealadach a oscailt" + +#: builtin/gc.c +msgid "failed to run 'crontab'; your system might not support 'cron'" +msgstr "" +"theip ar 'crontab' a reáchtáil; b'fhéidir nach dtacaíonn do chóras le 'cron'" + +#: builtin/gc.c +msgid "'crontab' died" +msgstr "Fuair 'crontab' bás" + +#: builtin/gc.c builtin/worktree.c +#, c-format +msgid "failed to delete '%s'" +msgstr "theip ar '%s' a scriosadh" + +#: builtin/gc.c rerere.c +#, c-format +msgid "failed to flush '%s'" +msgstr "theip ar '%s' a shruthlú" + +#: builtin/gc.c +msgid "failed to start systemctl" +msgstr "theip ar systemctl a thosú" + +#: builtin/gc.c +msgid "failed to run systemctl" +msgstr "theip ar systemctl a reáchtáil" + +#: builtin/gc.c +#, c-format +msgid "unrecognized --scheduler argument '%s'" +msgstr "argóint --scheduler gan aithint '%s'" + +#: builtin/gc.c +msgid "neither systemd timers nor crontab are available" +msgstr "níl uaireoirí systemd ná crontab ar fáil" + +#: builtin/gc.c +#, c-format +msgid "%s scheduler is not available" +msgstr "Níl sceidealóir %s ar fáil" + +#: builtin/gc.c +#, c-format +msgid "" +"unable to create '%s.lock': %s.\n" +"\n" +"Another scheduled git-maintenance(1) process seems to be running in this\n" +"repository. Please make sure no other maintenance processes are running and\n" +"then try again. If it still fails, a git-maintenance(1) process may have\n" +"crashed in this repository earlier: remove the file manually to continue." +msgstr "" +"nach féidir '%s.lock' a chruthú: %s.\n" +"\n" +"Is cosúil go bhfuil próiseas sceidealaithe eile git-maintenance(1) ag rith " +"sa\n" +"stórlann seo\n" +"Déan cinnte go bhfuil aon phróisis chothabhála eile ag rith agus\n" +"ansin déan iarracht arís. Má theipeann air fós, d'fhéadfadh go mbeadh " +"próiseas cothabhála git-maintenance (1)\n" +"tháinig isteach sa stór seo níos luaithe: bain an comhad de láimh chun " +"leanúint ar aghaidh." + +#: builtin/gc.c +msgid "cannot acquire lock for scheduled background maintenance" +msgstr "ní féidir glas a fháil le haghaidh cothabháil sceidealta cúlra" + +#: builtin/gc.c +msgid "git maintenance start [--scheduler=]" +msgstr "tús cothabhála git [--scheduler=]" + +#: builtin/gc.c +msgid "scheduler" +msgstr "sceidealóir" + +#: builtin/gc.c +msgid "scheduler to trigger git maintenance run" +msgstr "sceidealóir chun rith cothabhála git a spreagadh" + +#: builtin/gc.c +msgid "failed to set up maintenance schedule" +msgstr "theip ar sceideal cothabhála a chur ar bun" + +#: builtin/gc.c +msgid "failed to add repo to global config" +msgstr "theip ar repo a chur le cumraíocht domhanda" + +#: builtin/gc.c +msgid "git maintenance []" +msgstr "cothabháil git []" + +#: builtin/grep.c +msgid "git grep [] [-e] [...] [[--] ...]" +msgstr "git grep [] [-e] [...] [[--]...]" + +#: builtin/grep.c +#, c-format +msgid "grep: failed to create thread: %s" +msgstr "grep: theip ar shnáithe a chruthú: %s" + +#: builtin/grep.c +#, c-format +msgid "invalid number of threads specified (%d) for %s" +msgstr "líon neamhbhailí na snáitheanna a shonraítear (%d) do %s" + +#. TRANSLATORS: %s is the configuration +#. variable for tweaking threads, currently +#. grep.threads +#. +#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "no threads support, ignoring %s" +msgstr "gan tacaíocht do shnáitheanna, ag déanamh neamhaird ar %s" + +#: builtin/grep.c +#, c-format +msgid "unable to read tree %s" +msgstr "nach féidir crann %s a léamh" + +#: builtin/grep.c +#, c-format +msgid "unable to grep from object of type %s" +msgstr "in ann grep ó réad de chineál %s" + +#: builtin/grep.c +#, c-format +msgid "switch `%c' expects a numerical value" +msgstr "tá an lasc `%c' ag súil le luach uimhriúil" + +#: builtin/grep.c +msgid "search in index instead of in the work tree" +msgstr "cuardaigh san innéacs in ionad sa chrann oibre" + +#: builtin/grep.c +msgid "find in contents not managed by git" +msgstr "aimsigh in ábhar nach mbainistíonn git" + +#: builtin/grep.c +msgid "search in both tracked and untracked files" +msgstr "cuardach i gcomhaid rianaithe agus neamhrianaithe araon" + +#: builtin/grep.c +msgid "ignore files specified via '.gitignore'" +msgstr "neamhaird a dhéanamh ar chomhaid a shonraítear trí '.gitignore'" + +#: builtin/grep.c +msgid "recursively search in each submodule" +msgstr "cuardach athshlánach i ngach fo-mhodúl" + +#: builtin/grep.c +msgid "show non-matching lines" +msgstr "línte neamh-mheaitseála a" + +#: builtin/grep.c +msgid "case insensitive matching" +msgstr "meaitseáil cás neamhíogair" + +#: builtin/grep.c +msgid "match patterns only at word boundaries" +msgstr "patrúin a mheaitseáil ach ag teorainneacha focal" + +#: builtin/grep.c +msgid "process binary files as text" +msgstr "comhaid dénártha a phróiseáil mar th" + +#: builtin/grep.c +msgid "don't match patterns in binary files" +msgstr "ná meaitseáil patrúin i gcomhaid dénártha" + +#: builtin/grep.c +msgid "process binary files with textconv filters" +msgstr "comhaid dénártha a phróiseáil le scagairí textconv" + +#: builtin/grep.c +msgid "search in subdirectories (default)" +msgstr "cuardaigh i bhfo-eolairí (réamhshocrú)" + +#: builtin/grep.c +msgid "descend at most levels" +msgstr "síos ag an bhformhór na leibh" + +#: builtin/grep.c +msgid "use extended POSIX regular expressions" +msgstr "bain úsáid as nathanna rialta POSIX leathnaithe" + +#: builtin/grep.c +msgid "use basic POSIX regular expressions (default)" +msgstr "úsáid abairtí rialta bunúsacha POSIX (réamhshocraithe)" + +#: builtin/grep.c +msgid "interpret patterns as fixed strings" +msgstr "patrúin a léiriú mar teaghráin seasta" + +#: builtin/grep.c +msgid "use Perl-compatible regular expressions" +msgstr "úsáid abairtí rialta atá comhoiriúnach le PERL" + +#: builtin/grep.c +msgid "show line numbers" +msgstr "taispeáin uimhreacha líne" + +#: builtin/grep.c +msgid "show column number of first match" +msgstr "taispeáin uimhir cholún an chéad chluiche" + +#: builtin/grep.c +msgid "don't show filenames" +msgstr "ná taispeáin ainmneacha comhaid" + +#: builtin/grep.c +msgid "show filenames" +msgstr "taispeáin ainmneacha comhaid" + +#: builtin/grep.c +msgid "show filenames relative to top directory" +msgstr "ainmneacha comhaid a thaispeáint i gcoibhneas" + +#: builtin/grep.c +msgid "show only filenames instead of matching lines" +msgstr "taispeáint ach ainmneacha comhaid in ionad línte meaitseála" + +#: builtin/grep.c +msgid "synonym for --files-with-matches" +msgstr "comhchiallach do --files-with-matches" + +#: builtin/grep.c +msgid "show only the names of files without match" +msgstr "taispeáint ach ainmneacha na gcomhaid gan meaitseáil" + +#: builtin/grep.c +msgid "print NUL after filenames" +msgstr "priontáil NUL tar éis ainmneacha comhaid" + +#: builtin/grep.c +msgid "show only matching parts of a line" +msgstr "taispeáin ach codanna de líne a mheaitseáil" + +#: builtin/grep.c +msgid "show the number of matches instead of matching lines" +msgstr "taispeáint líon na gcluichí in ionad línte meaitseála" + +#: builtin/grep.c +msgid "highlight matches" +msgstr "cluichí aibhsithe" + +#: builtin/grep.c +msgid "print empty line between matches from different files" +msgstr "priontáil líne folamh idir cluichí ó chomhaid éagsúla" + +#: builtin/grep.c +msgid "show filename only once above matches from same file" +msgstr "" +"taispeáin ainm comhaid ach uair amháin thuas na cluichí ón gcomhad céanna" + +#: builtin/grep.c +msgid "show context lines before and after matches" +msgstr "línte comhthéacs a thaispeáint roimh agus tar" + +#: builtin/grep.c +msgid "show context lines before matches" +msgstr "línte comhthéacs a thaispeáint" + +#: builtin/grep.c +msgid "show context lines after matches" +msgstr "línte comhthéacs a thaispeáint" + +#: builtin/grep.c +msgid "use worker threads" +msgstr "úsáid sná itheanna oibrithe" + +#: builtin/grep.c +msgid "shortcut for -C NUM" +msgstr "aicearra le haghaidh -C NUM" + +#: builtin/grep.c +msgid "show a line with the function name before matches" +msgstr "taispeáint líne leis an ainm feidhme roimh mheaitseálacha" + +#: builtin/grep.c +msgid "show the surrounding function" +msgstr "taispeáin an fheidhm máguaird" + +#: builtin/grep.c +msgid "read patterns from file" +msgstr "patrúin a léamh ón gcomhad" + +#: builtin/grep.c +msgid "match " +msgstr "comhoiriúnú " + +#: builtin/grep.c +msgid "combine patterns specified with -e" +msgstr "comhcheangal patrúin a shonraítear le -e" + +#: builtin/grep.c +msgid "indicate hit with exit status without output" +msgstr "léirigh bualadh le stádas imeachta gan aschur" + +#: builtin/grep.c +msgid "show only matches from files that match all patterns" +msgstr "taispeáin ach cluichí ó chomhaid a mheaitseálann gach patrún" + +#: builtin/grep.c +msgid "pager" +msgstr "pager" + +#: builtin/grep.c +msgid "show matching files in the pager" +msgstr "taispeáint comhaid mheaitseála sa pager" + +#: builtin/grep.c +msgid "allow calling of grep(1) (ignored by this build)" +msgstr "cead a ghlaoch grep (1) (neamhaird ag an tógáil seo)" + +#: builtin/grep.c +msgid "maximum number of results per file" +msgstr "líon uasta na dtorthaí in aghaidh an chomhad" + +#: builtin/grep.c +msgid "no pattern given" +msgstr "aon phatrún a thugtar" + +#: builtin/grep.c +msgid "--no-index or --untracked cannot be used with revs" +msgstr "Ní féidir --no-index nó --untracked a úsáid le hathairí" + +#: builtin/grep.c +#, c-format +msgid "unable to resolve revision: %s" +msgstr "nach féidir athbhreithniú a réiteach: %s" + +#: builtin/grep.c +msgid "--untracked not supported with --recurse-submodules" +msgstr "--untracked nach dtacaítear le --recurse-submodules" + +#: builtin/grep.c +msgid "invalid option combination, ignoring --threads" +msgstr "teaglaim roghanna neamhbhailí, ag neamhaird --threads" + +#: builtin/grep.c builtin/pack-objects.c +msgid "no threads support, ignoring --threads" +msgstr "níl aon tacaíocht do shnáitheanna, ag déanamh neamhaird ar --threads" + +#: builtin/grep.c builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "invalid number of threads specified (%d)" +msgstr "líon neamhbhailí na snáitheanna sonraithe (%d)" + +#: builtin/grep.c +msgid "--open-files-in-pager only works on the worktree" +msgstr "Ní oibríonn --open-files-in-pager ach ar an gcrann oibre" + +#: builtin/grep.c +msgid "--[no-]exclude-standard cannot be used for tracked contents" +msgstr "" +"- ní féidir caighdeán eisiach [no-] a úsáid le haghaidh ábhar rianaithe" + +#: builtin/grep.c +msgid "both --cached and trees are given" +msgstr "tugtar --cached agus crainn araon" + +#: builtin/hash-object.c +msgid "" +"git hash-object [-t ] [-w] [--path= | --no-filters]\n" +" [--stdin [--literally]] [--] ..." +msgstr "" +"git hash-object [-t ] [-w] [--path= | --no-filters]\n" +" [--stdin [--literally]] [--] ..." + +#: builtin/hash-object.c +msgid "git hash-object [-t ] [-w] --stdin-paths [--no-filters]" +msgstr "git hash-object [-t ] [-w] --stdin-paths [--no-filters]" + +#: builtin/hash-object.c +msgid "object type" +msgstr "cineál réad" + +#: builtin/hash-object.c +msgid "write the object into the object database" +msgstr "scríobh an réad isteach sa bhunachar sonraí réad" + +#: builtin/hash-object.c +msgid "read the object from stdin" +msgstr "léigh an réad ó stdin" + +#: builtin/hash-object.c +msgid "store file as is without filters" +msgstr "comhad a stóráil mar atá gan scagairí" + +#: builtin/hash-object.c +msgid "" +"just hash any random garbage to create corrupt objects for debugging Git" +msgstr "" +"ní gá ach aon truflais randamach a chur chun rudaí truaillithe a chruthú le " +"haghaidh dífhab" + +#: builtin/hash-object.c +msgid "process file as it were from this path" +msgstr "comhad próiseála mar a bhí sé ón gcosán seo" + +#: builtin/help.c +msgid "print all available commands" +msgstr "gach ordú atá ar fáil a phriontáil" + +#: builtin/help.c +msgid "show external commands in --all" +msgstr "taispeáint orduithe seachtracha i --all" + +#: builtin/help.c +msgid "show aliases in --all" +msgstr "taispeáin ainmneacha in --all" + +#: builtin/help.c +msgid "exclude guides" +msgstr "treoracha a eisiamh" + +#: builtin/help.c +msgid "show man page" +msgstr "taispeáin leathanach fear" + +#: builtin/help.c +msgid "show manual in web browser" +msgstr "taispeáin lámhleabhar sa bhrabhsála" + +#: builtin/help.c +msgid "show info page" +msgstr "taispeáin leathanach faisnéise" + +#: builtin/help.c +msgid "print command description" +msgstr "cur síos ordaithe priontála" + +#: builtin/help.c +msgid "print list of useful guides" +msgstr "liosta priontáil de threoracha úsáideacha" + +#: builtin/help.c +msgid "print list of user-facing repository, command and file interfaces" +msgstr "" +"liosta priontála de stór, comhéadain ordaithe agus comhad atá os comhair " +"úsáideora" + +#: builtin/help.c +msgid "print list of file formats, protocols and other developer interfaces" +msgstr "" +"liosta priontála formáidí comhaid, prótacail agus comhéadain forbróra eile" + +#: builtin/help.c +msgid "print all configuration variable names" +msgstr "priontáil gach ainm athróg cumraíochta" + +#: builtin/help.c +msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [|]" +msgstr "git help [[-i|--eolas] [-m|--fear] [-w|--gréasáin]] [|]" + +#: builtin/help.c +#, c-format +msgid "unrecognized help format '%s'" +msgstr "formáid cabhrach gan aithint '%s'" + +#: builtin/help.c +msgid "Failed to start emacsclient." +msgstr "Theip ar emacsclient a thosú." + +#: builtin/help.c +msgid "Failed to parse emacsclient version." +msgstr "Theip ar leagan emacsclient a pháirseáil." + +#: builtin/help.c +#, c-format +msgid "emacsclient version '%d' too old (< 22)." +msgstr "leagan imacsclient '%d' ró-sean (< 22)." + +#: builtin/help.c +#, c-format +msgid "failed to exec '%s'" +msgstr "theip ar '%s' a fheidhmiú" + +#: builtin/help.c +#, c-format +msgid "" +"'%s': path for unsupported man viewer.\n" +"Please consider using 'man..cmd' instead." +msgstr "" +"'%s': cosán do lucht féachana fear gan tacaíocht.\n" +"Smaoinigh ar 'fear a úsáid le do thoil. .cmd' ina ionad." + +#: builtin/help.c +#, c-format +msgid "" +"'%s': cmd for supported man viewer.\n" +"Please consider using 'man..path' instead." +msgstr "" +"'%s': cmd do lucht féachana fear tacaithe.\n" +"Smaoinigh ar 'fear a úsáid le do thoil. .path' ina ionad sin." + +#: builtin/help.c +#, c-format +msgid "'%s': unknown man viewer." +msgstr "'%s': féachtóir fear anaithnid." + +#: builtin/help.c +msgid "no man viewer handled the request" +msgstr "níl aon fhéachtóir fear ar an iarraidh" + +#: builtin/help.c +msgid "no info viewer handled the request" +msgstr "níl aon fhéachtóir faisnéise ag láimhseáil" + +#: builtin/help.c git.c +#, c-format +msgid "'%s' is aliased to '%s'" +msgstr "Tá '%s' aistrithe go '%s'" + +#: builtin/help.c git.c +#, c-format +msgid "bad alias.%s string: %s" +msgstr "droch-ainm. Teagán %s: %s" + +#: builtin/help.c +#, c-format +msgid "the '%s' option doesn't take any non-option arguments" +msgstr "ní ghlacann an rogha '%s' aon argóintí neamh-rogha" + +#: builtin/help.c +msgid "" +"the '--no-[external-commands|aliases]' options can only be used with '--all'" +msgstr "" +"ní féidir na roghanna '--no- [external-commands|aliases] 'a úsáid ach le' --" +"all '" + +#: builtin/help.c +#, c-format +msgid "usage: %s%s" +msgstr "úsáid: %s%s" + +#: builtin/help.c +msgid "'git help config' for more information" +msgstr "'git help config' le haghaidh tuilleadh faisnéise" + +#: builtin/hook.c +msgid "" +"git hook run [--ignore-missing] [--to-stdin=] [-- ]" +msgstr "" +"git hook run [--ignore-missing] [--to-stdin =] " +"[--]" + +#: builtin/hook.c +msgid "silently ignore missing requested " +msgstr "neamhaird go ciúin a iarrtar ar " + +#: builtin/hook.c +msgid "file to read into hooks' stdin" +msgstr "comhad le léamh isteach i stdin na hracaí" + +#: builtin/index-pack.c +#, c-format +msgid "object type mismatch at %s" +msgstr "mímheaitseáil cineál réad ag %s" + +#: builtin/index-pack.c +#, c-format +msgid "did not receive expected object %s" +msgstr "nár bhfuair sé réad ag súil leis %s" + +#: builtin/index-pack.c +#, c-format +msgid "object %s: expected type %s, found %s" +msgstr "réad %s: súil leis an gcineál %s, aimsíodh %s" + +#: builtin/index-pack.c +#, c-format +msgid "cannot fill %d byte" +msgid_plural "cannot fill %d bytes" +msgstr[0] "ní féidir %d beart a líonadh" +msgstr[1] "ní féidir %d beart a líonadh" +msgstr[2] "ní féidir %d beart a líonadh" + +#: builtin/index-pack.c +msgid "early EOF" +msgstr "luath EOF" + +#: builtin/index-pack.c +msgid "read error on input" +msgstr "earráid léigh ar ionchur" + +#: builtin/index-pack.c +msgid "used more bytes than were available" +msgstr "úsáideadh níos mó bytes ná mar a bhí ar fáil" + +#: builtin/index-pack.c builtin/pack-objects.c +msgid "pack too large for current definition of off_t" +msgstr "pacáiste ró-mhór le haghaidh sainmhíniú reatha ar off_t" + +#: builtin/index-pack.c +#, c-format +msgid "pack exceeds maximum allowed size (%s)" +msgstr "sáraíonn an pacáiste an méid uasta ceadaithe (%s)" + +#: builtin/index-pack.c +msgid "pack signature mismatch" +msgstr "mímheaitseáil sínithe pacáiste" + +#: builtin/index-pack.c +#, c-format +msgid "pack version % unsupported" +msgstr "leagan pacáiste % gan tacaíocht" + +#: builtin/index-pack.c +#, c-format +msgid "pack has bad object at offset %: %s" +msgstr "tá réad lochtach sa phacáiste ag an bhfritháireamh %: %s" + +#: builtin/index-pack.c +#, c-format +msgid "inflate returned %d" +msgstr "infleáil ar ais %d" + +#: builtin/index-pack.c +msgid "offset value overflow for delta base object" +msgstr "ró-shreabhadh luacha a fhritháireamh do réad" + +#: builtin/index-pack.c +msgid "delta base offset is out of bound" +msgstr "tá fhritháireamh bonn delta as ceangailte" + +#: builtin/index-pack.c +#, c-format +msgid "unknown object type %d" +msgstr "cineál réad anaithnid %d" + +#: builtin/index-pack.c +msgid "cannot pread pack file" +msgstr "ní féidir comhad pacáiste a roghnú" + +#: builtin/index-pack.c +#, c-format +msgid "premature end of pack file, % byte missing" +msgid_plural "premature end of pack file, % bytes missing" +msgstr[0] "deireadh roimh am comhaid phacáiste, % beart ar iarraidh" +msgstr[1] "deireadh roimh am comhaid phacáiste, % beart ar iarraidh" +msgstr[2] "deireadh roimh am comhaid phacáiste, % beart ar iarraidh" + +#: builtin/index-pack.c +msgid "serious inflate inconsistency" +msgstr "neamhchomhsheasmhacht tromchúiseach" + +#: builtin/index-pack.c +#, c-format +msgid "SHA1 COLLISION FOUND WITH %s !" +msgstr "FUARTHAS IMBHALL SHA1 LE %s!" + +#: builtin/index-pack.c +#, c-format +msgid "cannot read existing object info %s" +msgstr "ní féidir faisnéis réad atá ann cheana %s a léamh" + +#: builtin/index-pack.c +#, c-format +msgid "cannot read existing object %s" +msgstr "ní féidir réad %s atá ann cheana a léamh" + +#: builtin/index-pack.c +#, c-format +msgid "invalid blob object %s" +msgstr "réad blob neamhbhailí %s" + +#: builtin/index-pack.c +msgid "fsck error in packed object" +msgstr "earráid fsck i réad pacáilte" + +#: builtin/index-pack.c +#, c-format +msgid "Not all child objects of %s are reachable" +msgstr "Níl gach réad leanbh de %s inrochtana" + +#: builtin/index-pack.c +msgid "failed to apply delta" +msgstr "theip ar delta a chur i bhfeidhm" + +#: builtin/index-pack.c +msgid "Receiving objects" +msgstr "Rudaí a fháil" + +#: builtin/index-pack.c +msgid "Indexing objects" +msgstr "Rudaí innéacsála" + +#: builtin/index-pack.c +msgid "pack is corrupted (SHA1 mismatch)" +msgstr "tá an pacáiste truaillithe (neamhoiriúnú SHA1)" + +#: builtin/index-pack.c +msgid "cannot fstat packfile" +msgstr "ní féidir le pacáiste fstat" + +#: builtin/index-pack.c +msgid "pack has junk at the end" +msgstr "tá bruscar ag an bpacáiste ag an deireadh" + +#: builtin/index-pack.c +msgid "confusion beyond insanity in parse_pack_objects()" +msgstr "mearbhall níos faide ná imní i parse_pack_objects()" + +#: builtin/index-pack.c +msgid "Resolving deltas" +msgstr "Deltas a réiteach" + +#: builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "unable to create thread: %s" +msgstr "nach féidir snáithe a chruthú: %s" + +#: builtin/index-pack.c +msgid "confusion beyond insanity" +msgstr "mearbhall níos faide ná mar gheall" + +#: builtin/index-pack.c +#, c-format +msgid "completed with %d local object" +msgid_plural "completed with %d local objects" +msgstr[0] "críochnaithe le %d réad áitiúil" +msgstr[1] "críochnaithe le %d réad áitiúil" +msgstr[2] "críochnaithe le %d réad áitiúil" + +#: builtin/index-pack.c +#, c-format +msgid "Unexpected tail checksum for %s (disk corruption?)" +msgstr "Seicsum eireaball gan choinne do %s (éilliú diosca?)" + +#: builtin/index-pack.c +#, c-format +msgid "pack has %d unresolved delta" +msgid_plural "pack has %d unresolved deltas" +msgstr[0] "tá %d delta gan réiteach sa phacáiste" +msgstr[1] "tá %d deiltí gan réiteach sa phacáiste" +msgstr[2] "tá %d deiltí gan réiteach sa phacáiste" + +#: builtin/index-pack.c +#, c-format +msgid "unable to deflate appended object (%d)" +msgstr "nach féidir réad cuibheangailte a dhíscaoileadh (%d)" + +#: builtin/index-pack.c +#, c-format +msgid "local object %s is corrupt" +msgstr "tá réad áitiúil %s truaillithe" + +#: builtin/index-pack.c +#, c-format +msgid "packfile name '%s' does not end with '.%s'" +msgstr "ní chríochnaíonn ainm pacáiste '%s' le '.%s'" + +#: builtin/index-pack.c +#, c-format +msgid "cannot write %s file '%s'" +msgstr "ní féidir comhad %s '%s' a scríobh" + +#: builtin/index-pack.c +#, c-format +msgid "cannot close written %s file '%s'" +msgstr "ní féidir comhad %s scríofa '%s' a dhúnadh" + +#: builtin/index-pack.c +#, c-format +msgid "unable to rename temporary '*.%s' file to '%s'" +msgstr "in ann athainmniú sealadach '*.%s' comhad chuig '%s'" + +#: builtin/index-pack.c +msgid "error while closing pack file" +msgstr "earráid agus comhad pacáiste á dúnadh" + +#: builtin/index-pack.c builtin/pack-objects.c +#, c-format +msgid "bad pack.indexVersion=%" +msgstr "droch-pack.indexVersion=%" + +#: builtin/index-pack.c +#, c-format +msgid "Cannot open existing pack file '%s'" +msgstr "Ní féidir comhad pacáiste atá ann cheana '%s' a oscailt" + +#: builtin/index-pack.c +#, c-format +msgid "Cannot open existing pack idx file for '%s'" +msgstr "Ní féidir comhad idx pacáiste atá ann cheana a oscailt do '%s'" + +#: builtin/index-pack.c +#, c-format +msgid "non delta: %d object" +msgid_plural "non delta: %d objects" +msgstr[0] "neamh-delta: %d réad" +msgstr[1] "neamh-delta: %d réad" +msgstr[2] "neamh-delta: %d réad" + +#: builtin/index-pack.c +#, c-format +msgid "chain length = %d: %lu object" +msgid_plural "chain length = %d: %lu objects" +msgstr[0] "fad slabhra = %d: %lu réad" +msgstr[1] "fad slabhra = %d: %lu réada" +msgstr[2] "fad slabhra = %d: %lu réada" + +#: builtin/index-pack.c +msgid "could not start pack-objects to repack local links" +msgstr "ní fhéadfaí pacáiste-earraí a thosú chun naisc áitiúla a athphacáil" + +#: builtin/index-pack.c +msgid "failed to feed local object to pack-objects" +msgstr "theip ar réad áitiúil a bheathú ar rudaí pacáiste" + +#: builtin/index-pack.c +msgid "index-pack: Expecting full hex object ID lines only from pack-objects." +msgstr "" +"index-pack: Ag súil le línte aitheantais réada heicsidheachúlach iomlán ó " +"pack-objects amháin." + +#: builtin/index-pack.c +msgid "could not finish pack-objects to repack local links" +msgstr "ní fhéadfaí pacáistí a chríochnú chun naisc áitiúla a athphacáil" + +#: builtin/index-pack.c +msgid "Cannot come back to cwd" +msgstr "Ní féidir teacht ar ais chuig cwd" + +#: builtin/index-pack.c builtin/unpack-objects.c +#, c-format +msgid "bad --pack_header: %s" +msgstr "droch --pack_header: %s" + +#: builtin/index-pack.c +#, c-format +msgid "bad %s" +msgstr "droch %s" + +#: builtin/index-pack.c builtin/init-db.c setup.c +#, c-format +msgid "unknown hash algorithm '%s'" +msgstr "algartam hais anaithnid '%s'" + +#: builtin/index-pack.c +msgid "--promisor cannot be used with a pack name" +msgstr "--promisor ní féidir é a úsáid le hainm pacáiste" + +#: builtin/index-pack.c +msgid "--stdin requires a git repository" +msgstr "--stdin teastaíonn stórlann git" + +#: builtin/index-pack.c +msgid "--verify with no packfile name given" +msgstr "--verify gan ainm comhaid pacáiste tugtha" + +#: builtin/index-pack.c builtin/unpack-objects.c +msgid "fsck error in pack objects" +msgstr "fsck earráid i rudaí pacáiste" + +#: builtin/init-db.c +msgid "" +"git init [-q | --quiet] [--bare] [--template=]\n" +" [--separate-git-dir ] [--object-format=]\n" +" [--ref-format=]\n" +" [-b | --initial-branch=]\n" +" [--shared[=]] []" +msgstr "" +"git init [-q | --quiet] [--bare] [--template=]\n" +" [--separate-git-dir ] [--object-format=]\n" +" [--ref-format=]\n" +" [-b | --initial-branch=]\n" +" [--shared[=]] []" + +#: builtin/init-db.c +msgid "permissions" +msgstr "ceadanna" + +#: builtin/init-db.c +msgid "specify that the git repository is to be shared amongst several users" +msgstr "sonraigh go bhfuil an stór git le roinnt i measc roinnt úsáideoirí" + +#: builtin/init-db.c +msgid "override the name of the initial branch" +msgstr "ainm na brainse tosaigh a shárú" + +#: builtin/init-db.c builtin/verify-pack.c +msgid "hash" +msgstr "hash" + +#: builtin/init-db.c builtin/show-index.c builtin/verify-pack.c +msgid "specify the hash algorithm to use" +msgstr "sonraigh an algartam hash le húsáid" + +#: builtin/init-db.c +#, c-format +msgid "cannot mkdir %s" +msgstr "ní féidir teacht ar %s" + +#: builtin/init-db.c +#, c-format +msgid "cannot chdir to %s" +msgstr "ní féidir teacht chuig %s" + +#: builtin/init-db.c +#, c-format +msgid "" +"%s (or --work-tree=) not allowed without specifying %s (or --git-" +"dir=)" +msgstr "" +"%s (or --work-tree=) ní cheadaítear gan sonrú %s (or --git-" +"dir=)" + +#: builtin/init-db.c +#, c-format +msgid "Cannot access work tree '%s'" +msgstr "Ní féidir rochtain a fháil ar chrann oibre '%s'" + +#: builtin/init-db.c +msgid "--separate-git-dir incompatible with bare repository" +msgstr "--separate-git-dir neamhoiriúnach le stór lom" + +#: builtin/interpret-trailers.c +msgid "" +"git interpret-trailers [--in-place] [--trim-empty]\n" +" [(--trailer (|)[(=|:)])...]\n" +" [--parse] [...]" +msgstr "" +"git interpret-trailers [--in-place] [--trim-empty]\n" +" [(--trailer (|)[(=|:)])...]\n" +" [--parse] [...]" + +#: builtin/interpret-trailers.c wrapper.c +#, c-format +msgid "could not stat %s" +msgstr "ní raibh ann %s a shástáil" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not a regular file" +msgstr "ní comhad rialta é comhad %s" + +#: builtin/interpret-trailers.c +#, c-format +msgid "file %s is not writable by user" +msgstr "ní féidir an t-úsáideoir comhad %s a scríobh" + +#: builtin/interpret-trailers.c +msgid "could not open temporary file" +msgstr "ní fhéadfadh comhad sealadach a oscailt" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not read input file '%s'" +msgstr "ní raibh in ann comhad ionchuir '%s' a léamh" + +#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c +msgid "could not read from stdin" +msgstr "ní fhéadfaí léamh ó stdin" + +#: builtin/interpret-trailers.c +#, c-format +msgid "could not rename temporary file to %s" +msgstr "ní fhéadfaí comhad sealadach a athainmniú go %s" + +#: builtin/interpret-trailers.c +msgid "edit files in place" +msgstr "comhaid in áit a chur in eagar" + +#: builtin/interpret-trailers.c +msgid "trim empty trailers" +msgstr "leantóirí folamh a ghear" + +#: builtin/interpret-trailers.c +msgid "placement" +msgstr "socrúcháin" + +#: builtin/interpret-trailers.c +msgid "where to place the new trailer" +msgstr "cá háit a chuirfear an leantóir nua" + +#: builtin/interpret-trailers.c +msgid "action if trailer already exists" +msgstr "gníomh má tá leantóir ann cheana féin" + +#: builtin/interpret-trailers.c +msgid "action if trailer is missing" +msgstr "gníomh má tá leantóir ar iarraidh" + +#: builtin/interpret-trailers.c +msgid "output only the trailers" +msgstr "aschur ach na leantóirí" + +#: builtin/interpret-trailers.c +msgid "do not apply trailer.* configuration variables" +msgstr "ná cuir leantóir i bhfeidhm.* athróga cumraíochta" + +#: builtin/interpret-trailers.c +msgid "reformat multiline trailer values as single-line values" +msgstr "luachanna leantóra illíne a athfhormáidiú mar luachanna aon-líne" + +#: builtin/interpret-trailers.c +msgid "alias for --only-trailers --only-input --unfold" +msgstr "ainm le haghaidh --only-trailers --only-input --unfold" + +#: builtin/interpret-trailers.c +msgid "do not treat \"---\" as the end of input" +msgstr "ná déileáil le “---” mar dheireadh an ionchuir" + +#: builtin/interpret-trailers.c +msgid "trailer(s) to add" +msgstr "leantóir (í) le cur leis" + +#: builtin/interpret-trailers.c +msgid "--trailer with --only-input does not make sense" +msgstr "níl ciall le --trailer le --only-input" + +#: builtin/interpret-trailers.c +msgid "no input file given for in-place editing" +msgstr "níl aon chomhad ionchuir a thugtar le haghaidh eagarthóireachta" + +#: builtin/log.c +msgid "git log [] [] [[--] ...]" +msgstr "logáil git [] [] [[--]...]" + +#: builtin/log.c +msgid "git show [] ..." +msgstr "git show []..." + +#: builtin/log.c +#, c-format +msgid "invalid --decorate option: %s" +msgstr "rogha neamhbhailí --decorate: %s" + +#: builtin/log.c diff.c +msgid "suppress diff output" +msgstr "aschur diff a chur faoi chois" + +#: builtin/log.c +msgid "show source" +msgstr "foinse taispeáin" + +#: builtin/log.c +msgid "clear all previously-defined decoration filters" +msgstr "glan na scagairí maisiúcháin atá sainmhínithe roimhe seo" + +#: builtin/log.c +msgid "only decorate refs that match " +msgstr "ní mhaisigh ach na cinn a mheaitseálann " + +#: builtin/log.c +msgid "do not decorate refs that match " +msgstr "ná maisigh na cinn a mheaitseálann " + +#: builtin/log.c +msgid "decorate options" +msgstr "roghanna maisiú" + +#: builtin/log.c +msgid "" +"trace the evolution of line range , or function : in " +"" +msgstr "éabhlóid raon líne, nó feidhm a rianú: i " + +#: builtin/log.c +msgid "-L: cannot be used with pathspec" +msgstr "-L: ní féidir é a úsáid le pathspec" + +#: builtin/log.c +#, c-format +msgid "Final output: %d %s\n" +msgstr "Aschur deiridh: %d %s\n" + +#: builtin/log.c +#, c-format +msgid "git show %s: bad file" +msgstr "git show %s: droch-chomhad" + +#: builtin/log.c +#, c-format +msgid "could not read object %s" +msgstr "ní raibh in ann réad %s a léamh" + +#: builtin/log.c +#, c-format +msgid "unknown type: %d" +msgstr "cineál anaithnid: %d" + +#: builtin/log.c +#, c-format +msgid "%s: invalid cover from description mode" +msgstr "%s: clúdach neamhbhailí ó mhodh tuairisc" + +#: builtin/log.c +msgid "format.headers without value" +msgstr "format.headers gan luach" + +#: builtin/log.c +#, c-format +msgid "cannot open patch file %s" +msgstr "ní féidir comhad paiste %s a oscailt" + +#: builtin/log.c +msgid "need exactly one range" +msgstr "teastaíonn raon amháin díreach" + +#: builtin/log.c +msgid "not a range" +msgstr "ní raon" + +#: builtin/log.c +#, c-format +msgid "unable to read branch description file '%s'" +msgstr "nach féidir an comhad tuairisc brainse '%s' a léamh" + +#: builtin/log.c +msgid "cover letter needs email format" +msgstr "teastaíonn formáid ríomhphoist ó litir" + +#: builtin/log.c +msgid "failed to create cover-letter file" +msgstr "theip ar chomhad litir chlúdaigh a chruthú" + +#: builtin/log.c +#, c-format +msgid "insane in-reply-to: %s" +msgstr "in-fhreagairt daingniúil: %s" + +#: builtin/log.c +msgid "git format-patch [] [ | ]" +msgstr "git format-patch [] [<ó> | ]" + +#: builtin/log.c +msgid "two output directories?" +msgstr "dhá eolaire aschuir?" + +#: builtin/log.c +#, c-format +msgid "unknown commit %s" +msgstr "tiomantas anaithnid %s" + +#: builtin/log.c builtin/replace.c +#, c-format +msgid "failed to resolve '%s' as a valid ref" +msgstr "theip ar '%s' a réiteach mar thagartha bailí" + +#: builtin/log.c +msgid "could not find exact merge base" +msgstr "ní fhéadfaí bonn cumaisc cruinn a fháil" + +#: builtin/log.c +msgid "" +"failed to get upstream, if you want to record base commit automatically,\n" +"please use git branch --set-upstream-to to track a remote branch.\n" +"Or you could specify base commit by --base= manually" +msgstr "" +"theip ar an dul suas sruth, más mian leat an gealltanas bonn a thaifeadadh " +"go huathoibríoch,\n" +"bain úsáid as git branch --set-upstream-to chun brainse iargúlta a rianú.\n" +"Nó d'fhéadfá an gealltanas bonn a shonrú trí --base= de láimh" + +#: builtin/log.c +msgid "failed to find exact merge base" +msgstr "theip orthu bonn cumaisc cruinn a fháil" + +#: builtin/log.c +msgid "base commit should be the ancestor of revision list" +msgstr "ba cheart gurb é bonn tiomantas ina sinsear an liosta athbhrei" + +#: builtin/log.c +msgid "base commit shouldn't be in revision list" +msgstr "níor cheart go mbeadh tiomantas bonn sa liosta athbhrei" + +#: builtin/log.c +msgid "cannot get patch id" +msgstr "ní féidir id paiste a fháil" + +#: builtin/log.c +msgid "failed to infer range-diff origin of current series" +msgstr "theip ar thionscnamh raon difriúil na sraithe reatha a thabhairt amach" + +#: builtin/log.c +#, c-format +msgid "using '%s' as range-diff origin of current series" +msgstr "ag baint úsáide as '%s' mar bhunús diff raon na sraithe reatha" + +#: builtin/log.c +msgid "use [PATCH n/m] even with a single patch" +msgstr "bain úsáid as [PATCH n/m] fiú le paiste amháin" + +#: builtin/log.c +msgid "use [PATCH] even with multiple patches" +msgstr "bain úsáid as [PATCH] fiú le paistí iolracha" + +#: builtin/log.c +msgid "print patches to standard out" +msgstr "paistí a phriontáil chun caighdeánach" + +#: builtin/log.c +msgid "generate a cover letter" +msgstr "litir chlúdaigh a ghiniúint" + +#: builtin/log.c +msgid "use simple number sequence for output file names" +msgstr "úsáid seicheamh uimhreacha simplí d'ainmneacha comhaid aschu" + +#: builtin/log.c +msgid "sfx" +msgstr "sfx" + +#: builtin/log.c +msgid "use instead of '.patch'" +msgstr "úsáid in ionad '.patch'" + +#: builtin/log.c +msgid "start numbering patches at instead of 1" +msgstr "tosú ag uimhriú paistí ag seachas 1" + +#: builtin/log.c +msgid "reroll-count" +msgstr "comhaireamh ath-rollta" + +#: builtin/log.c +msgid "mark the series as Nth re-roll" +msgstr "marcáil an tsraith mar Nú ath-rolla" + +#: builtin/log.c +msgid "max length of output filename" +msgstr "fad uasta ainm an chomhaid aschuir" + +#: builtin/log.c +msgid "rfc" +msgstr "rfc" + +#: builtin/log.c +msgid "add (default 'RFC') before 'PATCH'" +msgstr "cuir (réamhshocraithe 'RFC') roimh 'PATCH'" + +#: builtin/log.c +msgid "cover-from-description-mode" +msgstr "modh clúdaigh ó-tuairiscríbhinní" + +#: builtin/log.c +msgid "generate parts of a cover letter based on a branch's description" +msgstr "codanna de litir chlúdaigh a ghiniúint bunaithe ar thuairisc brainse" + +#: builtin/log.c +msgid "use branch description from file" +msgstr "úsáid cur síos brainse ón gcomhad" + +#: builtin/log.c +msgid "use [] instead of [PATCH]" +msgstr "úsáid [] in ionad [PATCH]" + +#: builtin/log.c +msgid "store resulting files in " +msgstr "comhaid mar thoradh air a stóráil i " + +#: builtin/log.c +msgid "don't strip/add [PATCH]" +msgstr "ná stiall/cuir [PATCH] leis" + +#: builtin/log.c +msgid "don't output binary diffs" +msgstr "ná aschur difríochtaí dénártha" + +#: builtin/log.c +msgid "output all-zero hash in From header" +msgstr "aschur hash uile-nialas i Ó cheanntásc" + +#: builtin/log.c +msgid "don't include a patch matching a commit upstream" +msgstr "ná cuir paiste a mheaitseann le tiomantas suas an sruth" + +#: builtin/log.c +msgid "show patch format instead of default (patch + stat)" +msgstr "taispeáin formáid paiste in ionad réamhshocraithe (paiste + stat)" + +#: builtin/log.c +msgid "Messaging" +msgstr "Teachtaireachtaí" + +#: builtin/log.c +msgid "header" +msgstr "ceanntásc" + +#: builtin/log.c +msgid "add email header" +msgstr "ceanntásc ríomhphoist leis" + +#: builtin/log.c +msgid "email" +msgstr "ríomhphost" + +#: builtin/log.c +msgid "add To: header" +msgstr "cuir Le: ceanntásc" + +#: builtin/log.c +msgid "add Cc: header" +msgstr "cuir Cc leis: ceanntásc" + +#: builtin/log.c +msgid "ident" +msgstr "idirghníomhaire" + +#: builtin/log.c +msgid "set From address to (or committer ident if absent)" +msgstr "" +"socraigh Ó sheoladh go dtí (nó aitheantas an tiomantais mura bhfuil " +"sé ann)" + +#: builtin/log.c +msgid "message-id" +msgstr "id teachtaireachta" + +#: builtin/log.c +msgid "make first mail a reply to " +msgstr "déan freagra ar an gcéad phost " + +#: builtin/log.c +msgid "boundary" +msgstr "teorainn" + +#: builtin/log.c +msgid "attach the patch" +msgstr "ceangail an paiste" + +#: builtin/log.c +msgid "inline the patch" +msgstr "inlíne an paiste" + +#: builtin/log.c +msgid "enable message threading, styles: shallow, deep" +msgstr "cumasú snáithe teachtaireachta, stíleanna: éadomhain, domhain" + +#: builtin/log.c +msgid "signature" +msgstr "síniú" + +#: builtin/log.c +msgid "add a signature" +msgstr "cuir síniú" + +#: builtin/log.c +msgid "base-commit" +msgstr "bun-tiomantas" + +#: builtin/log.c +msgid "add prerequisite tree info to the patch series" +msgstr "cuir faisnéis rainn réamhriachtanais leis an tsraith paiste" + +#: builtin/log.c +msgid "add a signature from a file" +msgstr "cuir síniú ó chomhad" + +#: builtin/log.c +msgid "don't print the patch filenames" +msgstr "ná priontáil na hainmneacha comhaid paiste" + +#: builtin/log.c +msgid "show progress while generating patches" +msgstr "dul chun cinn a thaispeáint agus paistí" + +#: builtin/log.c +msgid "show changes against in cover letter or single patch" +msgstr "athruithe a thaispeá int i gcoinne i litir chlúdaigh nó" + +#: builtin/log.c +msgid "show changes against in cover letter or single patch" +msgstr "athruithe a thaispeá int i gcoinne i litir chlúdaigh nó" + +#: builtin/log.c builtin/range-diff.c +msgid "percentage by which creation is weighted" +msgstr "céatadán faoina n-ualaítear an cruthú" + +#: builtin/log.c +msgid "show in-body From: even if identical to the e-mail header" +msgstr "" +"taispeáin in-chorp Ó: fiú más comhionann leis an gceannteideal ríomhphoist" + +#: builtin/log.c +#, c-format +msgid "invalid ident line: %s" +msgstr "líne aitheantais neamhbhailí: %s" + +#: builtin/log.c +msgid "--name-only does not make sense" +msgstr "Ní bhíonn ciall ag --name-only" + +#: builtin/log.c +msgid "--name-status does not make sense" +msgstr "Ní bhíonn ciall ag --name-status" + +#: builtin/log.c +msgid "--check does not make sense" +msgstr "Ní bhíonn ciall ag --check" + +#: builtin/log.c +msgid "--remerge-diff does not make sense" +msgstr "Ní bhíonn ciall ag --remerge-diff" + +#: builtin/log.c builtin/submodule--helper.c rerere.c submodule.c +#, c-format +msgid "could not create directory '%s'" +msgstr "ní fhéadfaí eolaire '%s' a chruthú" + +#: builtin/log.c +msgid "--interdiff requires --cover-letter or single patch" +msgstr "éilíonn --interdiff --cover-letter nó paiste singil" + +#: builtin/log.c +msgid "Interdiff:" +msgstr "Interdiff:" + +#: builtin/log.c +#, c-format +msgid "Interdiff against v%d:" +msgstr "Interdiff i gcoinne v%d:" + +#: builtin/log.c +msgid "--range-diff requires --cover-letter or single patch" +msgstr "Éilíonn --range-diff --cover-letter nó paiste aonair" + +#: builtin/log.c +msgid "Range-diff:" +msgstr "Difríocht raon:" + +#: builtin/log.c +#, c-format +msgid "Range-diff against v%d:" +msgstr "Difríocht raon i gcoinne v%d:" + +#: builtin/log.c +#, c-format +msgid "unable to read signature file '%s'" +msgstr "nach féidir an comhad sínithe '%s' a léamh" + +#: builtin/log.c +msgid "Generating patches" +msgstr "Giniúint paistí" + +#: builtin/log.c +msgid "failed to create output files" +msgstr "theip ar chomhaid aschuir a chruthú" + +#: builtin/log.c +msgid "git cherry [-v] [ [ []]]" +msgstr "git cherry [-v] [ [ []]]" + +#: builtin/log.c +#, c-format +msgid "" +"Could not find a tracked remote branch, please specify manually.\n" +msgstr "" +"Níor féidir brainse iargúlta rianaithe a fháil, sonraigh de láimh le do th " +"oil.\n" + +#: builtin/ls-files.c builtin/ls-tree.c +#, c-format +msgid "could not get object info about '%s'" +msgstr "ní fhéadfaí faisnéis réada a fháil faoi '%s'" + +#: builtin/ls-files.c +msgid "git ls-files [] [...]" +msgstr "git ls-files [] [...]" + +#: builtin/ls-files.c builtin/merge-tree.c +msgid "separate paths with the NUL character" +msgstr "cosáin ar leithligh leis an carachtar NUL" + +#: builtin/ls-files.c +msgid "identify the file status with tags" +msgstr "stádas an chomhaid a aithint le clibeanna" + +#: builtin/ls-files.c +msgid "use lowercase letters for 'assume unchanged' files" +msgstr "" +"bain úsáid as litreacha beaga le haghaidh comhaid 'glacadh leis gan " +"athraithe'" + +#: builtin/ls-files.c +msgid "use lowercase letters for 'fsmonitor clean' files" +msgstr "bain úsáid as litreacha beaga le haghaidh comhaid 'fsmonitor clean'" + +#: builtin/ls-files.c +msgid "show cached files in the output (default)" +msgstr "taispeáint comhaid taispeána san aschur (réamhshocraithe)" + +#: builtin/ls-files.c +msgid "show deleted files in the output" +msgstr "taispeáint comhaid scriosta san aschur" + +#: builtin/ls-files.c +msgid "show modified files in the output" +msgstr "taispeáint comhaid modhnaithe san aschur" + +#: builtin/ls-files.c +msgid "show other files in the output" +msgstr "taispeáint comhaid eile san aschur" + +#: builtin/ls-files.c +msgid "show ignored files in the output" +msgstr "taispeáint comhaid a neamhaird san aschur" + +#: builtin/ls-files.c +msgid "show staged contents' object name in the output" +msgstr "taispeáin ainm réad ábhair stáitseáilte san aschur" + +#: builtin/ls-files.c +msgid "show files on the filesystem that need to be removed" +msgstr "taispeáint comhaid ar an gcóras comhaid is gá a bhaint" + +#: builtin/ls-files.c +msgid "show 'other' directories' names only" +msgstr "taispeáin ainmneacha 'eile' amháin" + +#: builtin/ls-files.c +msgid "show line endings of files" +msgstr "taispeáint deireadh líne na gcomhaid" + +#: builtin/ls-files.c +msgid "don't show empty directories" +msgstr "ná taispeáin eolairí folamh" + +#: builtin/ls-files.c +msgid "show unmerged files in the output" +msgstr "taispeáint comhaid neamh-chumhdaithe san aschur" + +#: builtin/ls-files.c +msgid "show resolve-undo information" +msgstr "taispeáin faisnéis réitigh a chealú" + +#: builtin/ls-files.c +msgid "skip files matching pattern" +msgstr "patrún meaitseála comhaid scipeála" + +#: builtin/ls-files.c +msgid "read exclude patterns from " +msgstr "léigh patrúin eisiamh ó " + +#: builtin/ls-files.c +msgid "read additional per-directory exclude patterns in " +msgstr "léigh patrúin breise in aghaidh eolaire a eisiamh i " + +#: builtin/ls-files.c +msgid "add the standard git exclusions" +msgstr "cuir na heisiaimh caighdeánacha git" + +#: builtin/ls-files.c +msgid "make the output relative to the project top directory" +msgstr "déan an t-aschur i gcoibhneas le barr-eolaire an tion" + +#: builtin/ls-files.c +msgid "if any is not in the index, treat this as an error" +msgstr "" +"mura bhfuil aon cheann san innéacs, déileáil leis seo mar earráid" + +#: builtin/ls-files.c builtin/merge-tree.c +msgid "tree-ish" +msgstr "crainn" + +#: builtin/ls-files.c +msgid "pretend that paths removed since are still present" +msgstr "ligean go bhfuil cosáin a bhain tear ó shin fós i láthair" + +#: builtin/ls-files.c +msgid "show debugging data" +msgstr "taispeáin sonraí dífhabhtaithe" + +#: builtin/ls-files.c +msgid "suppress duplicate entries" +msgstr "iontrálacha dúbailte a chur" + +#: builtin/ls-files.c +msgid "show sparse directories in the presence of a sparse index" +msgstr "taispeáint eolairí neamhchoitianta i láthair innéacs neamhchoitianta" + +#: builtin/ls-files.c +msgid "" +"--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, " +"--eol" +msgstr "" +"Ní féidir --format a úsáid le -s, -o, -k, -t, --resolve-undo, --deduplicate, " +"--eol" + +#: builtin/ls-remote.c +msgid "" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=]\n" +" [-q | --quiet] [--exit-code] [--get-url] [--sort=]\n" +" [--symref] [ [...]]" +msgstr "" +"git ls-remote [--branches] [--tags] [--refs] [--upload-pack=]\n" +" [-q | --quiet] [--exit-code] [--get-url] [--sort=]\n" +" [--symref] [ [...]]" + +#: builtin/ls-remote.c +msgid "do not print remote URL" +msgstr "ná priontáil URL iargúlta" + +#: builtin/ls-remote.c builtin/rebase.c +msgid "exec" +msgstr "feidhmiúcháin" + +#: builtin/ls-remote.c +msgid "path of git-upload-pack on the remote host" +msgstr "cosán git-upload-pack ar an óstach cianda" + +#: builtin/ls-remote.c +msgid "limit to tags" +msgstr "teorainn le clibeanna" + +#: builtin/ls-remote.c +msgid "limit to branches" +msgstr "teorainn le brainsí" + +#: builtin/ls-remote.c builtin/show-ref.c +msgid "deprecated synonym for --branches" +msgstr "comhchiallach scoite do --branches" + +#: builtin/ls-remote.c +msgid "do not show peeled tags" +msgstr "ná taispeáin clibeanna scáilte" + +#: builtin/ls-remote.c +msgid "take url..insteadOf into account" +msgstr "glacadh url. .insteadOf san áireamh" + +#: builtin/ls-remote.c +msgid "exit with exit code 2 if no matching refs are found" +msgstr "imeacht le cód imeachta 2 mura bhfaightear aon aifeanna meaitseála" + +#: builtin/ls-remote.c +msgid "show underlying ref in addition to the object pointed by it" +msgstr "taispeáint an tagairt bhunúsach i dteannta leis an réad a thug sé" + +#: builtin/ls-tree.c +msgid "git ls-tree [] [...]" +msgstr "git ls-tree [] [...]" + +#: builtin/ls-tree.c +msgid "only show trees" +msgstr "ach crainn a thaispeáint" + +#: builtin/ls-tree.c +msgid "recurse into subtrees" +msgstr "athshlánú isteach i bhfo-chrainn" + +#: builtin/ls-tree.c +msgid "show trees when recursing" +msgstr "crainn a thaispeáint agus tú ag athf" + +#: builtin/ls-tree.c +msgid "terminate entries with NUL byte" +msgstr "foirceannadh iontrálacha le bait NUL" + +#: builtin/ls-tree.c +msgid "include object size" +msgstr "méid an rud san áireamh" + +#: builtin/ls-tree.c +msgid "list only filenames" +msgstr "ainmneacha comhaid amháin a liostáil" + +#: builtin/ls-tree.c +msgid "list only objects" +msgstr "rudaí amháin a liostáil" + +#: builtin/ls-tree.c +msgid "use full path names" +msgstr "úsáid ainmneacha cosáin iomlána" + +#: builtin/ls-tree.c +msgid "list entire tree; not just current directory (implies --full-name)" +msgstr "" +"liostáil crann iomlán; ní hamháin eolaire reatha (tugann le tuiscint --full-" +"name)" + +#: builtin/ls-tree.c +msgid "--format can't be combined with other format-altering options" +msgstr "" +"Ní féidir --format a chomhcheangal le roghanna eile a athraíonn formáidí" + +#. TRANSLATORS: keep <> in "<" mail ">" info. +#: builtin/mailinfo.c +msgid "git mailinfo [] < mail >info" +msgstr "git mailinfo [] < mail >info" + +#: builtin/mailinfo.c +msgid "keep subject" +msgstr "coinnigh ábhar" + +#: builtin/mailinfo.c +msgid "keep non patch brackets in subject" +msgstr "coinnigh lúibíní gan paiste san ábhar" + +#: builtin/mailinfo.c +msgid "copy Message-ID to the end of commit message" +msgstr "" +"cóipeáil ID teachtaireachtaí go dtí deireadh na teachtaireachta tiomanta" + +#: builtin/mailinfo.c +msgid "re-code metadata to i18n.commitEncoding" +msgstr "meiteashonraí a athchódú chuig i18N.CommitEncoding" + +#: builtin/mailinfo.c +msgid "disable charset re-coding of metadata" +msgstr "díchumasú ath-chódú charset meiteashonraí" + +#: builtin/mailinfo.c +msgid "encoding" +msgstr "ionchódú" + +#: builtin/mailinfo.c +msgid "re-code metadata to this encoding" +msgstr "athchódú meiteashonraí don ionchódú seo" + +#: builtin/mailinfo.c +msgid "use scissors" +msgstr "siosúr a úsáid" + +#: builtin/mailinfo.c +msgid "" +msgstr "" + +#: builtin/mailinfo.c +msgid "action when quoted CR is found" +msgstr "gníomh nuair a aimsítear CR a luaitear" + +#: builtin/mailinfo.c +msgid "use headers in message's body" +msgstr "ceanntásca a úsáid i gcorp na teachtaireachta" + +#: builtin/mailsplit.c +msgid "reading patches from stdin/tty..." +msgstr "paistí a léamh ó stdin/tty..." + +#: builtin/mailsplit.c +#, c-format +msgid "empty mbox: '%s'" +msgstr "mbox folamh: '%s'" + +#: builtin/merge-base.c +msgid "git merge-base [-a | --all] ..." +msgstr "git merge-base [-a | --all] ..." + +#: builtin/merge-base.c +msgid "git merge-base [-a | --all] --octopus ..." +msgstr "git merge-base [-a | --all] --octopus ..." + +#: builtin/merge-base.c +msgid "git merge-base --is-ancestor " +msgstr "git merge-base --is-ancestor " + +#: builtin/merge-base.c +msgid "git merge-base --independent ..." +msgstr "git merge-base --independent ..." + +#: builtin/merge-base.c +msgid "git merge-base --fork-point []" +msgstr "git merge-base --fork-point []" + +#: builtin/merge-base.c +msgid "output all common ancestors" +msgstr "aschur gach sinsear coitianta" + +#: builtin/merge-base.c +msgid "find ancestors for a single n-way merge" +msgstr "aimsigh sinsear le haghaidh cumasc n-bhealach amháin" + +#: builtin/merge-base.c +msgid "list revs not reachable from others" +msgstr "liosta revs nach féidir teacht ó dhaoine eile" + +#: builtin/merge-base.c +msgid "is the first one ancestor of the other?" +msgstr "an é an chéad sinsear amháin den duine eile?" + +#: builtin/merge-base.c +msgid "find where forked from reflog of " +msgstr "faigh cén áit a bhforcáladh ó athbhreithniú " + +#: builtin/merge-file.c +msgid "" +"git merge-file [] [-L [-L [-L ]]] " +" " +msgstr "" +"git merge-file [] [-L [-L [-L ]]] " +" " + +#: builtin/merge-file.c diff.c +msgid "" +"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and " +"\"histogram\"" +msgstr "" +"glacann difr-algartam rogha le “myers”, “íosta”, “foighne” agus “histogram”" + +#: builtin/merge-file.c +msgid "send results to standard output" +msgstr "torthaí a sheoladh chuig aschur caigh" + +#: builtin/merge-file.c +msgid "use object IDs instead of filenames" +msgstr "úsáid ID réad in ionad ainmneacha comhaid" + +#: builtin/merge-file.c +msgid "use a diff3 based merge" +msgstr "bain úsáid as cumaisc atá bunaithe ar diff3" + +#: builtin/merge-file.c +msgid "use a zealous diff3 based merge" +msgstr "bain úsáid as cumaisc díograiseach bunaithe ar diff3" + +#: builtin/merge-file.c diff.c +msgid "" +msgstr "" + +#: builtin/merge-file.c diff.c +msgid "choose a diff algorithm" +msgstr "roghnaigh algartam diff" + +#: builtin/merge-file.c +msgid "for conflicts, use this marker size" +msgstr "le haghaidh coinbhleachtaí, bain úsáid as an méid marcóra" + +#: builtin/merge-file.c +msgid "do not warn about conflicts" +msgstr "ná tabhair rabhadh faoi choimhlintí" + +#: builtin/merge-file.c +msgid "set labels for file1/orig-file/file2" +msgstr "lipéid a shocrú le haghaidh comhad1/orig-file/file2" + +#: builtin/merge-file.c +#, c-format +msgid "object '%s' does not exist" +msgstr "níl réad '%s' ann" + +#: builtin/merge-file.c +msgid "Could not write object file" +msgstr "Ní fhéadfaí comhad réad a scríobh" + +#: builtin/merge-recursive.c +#, c-format +msgid "unknown option %s" +msgstr "rogha anaithnid %s" + +#: builtin/merge-recursive.c +#, c-format +msgid "could not parse object '%s'" +msgstr "ní fhéadfaí réad '%s' a pháirseáil" + +#: builtin/merge-recursive.c +#, c-format +msgid "cannot handle more than %d base. Ignoring %s." +msgid_plural "cannot handle more than %d bases. Ignoring %s." +msgstr[0] "ní féidir níos mó ná %d bonn a láimhseáil. Ag neamhaird de %s." +msgstr[1] "ní féidir níos mó ná %d bonn a láimhseáil. Ag neamhaird de %s." +msgstr[2] "ní féidir níos mó ná %d bonn a láimhseáil. Ag neamhaird de %s." + +#: builtin/merge-recursive.c +msgid "not handling anything other than two heads merge." +msgstr "gan láimhseáil aon rud seachas dhá cheann a chumasc." + +#: builtin/merge-recursive.c +#, c-format +msgid "could not resolve ref '%s'" +msgstr "ní fhéadfaí tagairt '%s' a réiteach" + +#: builtin/merge-recursive.c +#, c-format +msgid "Merging %s with %s\n" +msgstr "Cumasc %s le %s\n" + +#: builtin/merge-tree.c +#, c-format +msgid "could not parse as tree '%s'" +msgstr "ní fhéadfaí parsáil mar chrann '%s'" + +#: builtin/merge-tree.c builtin/merge.c +msgid "not something we can merge" +msgstr "ní rud is féidir linn a chumasc" + +#: builtin/merge-tree.c builtin/merge.c +msgid "refusing to merge unrelated histories" +msgstr "diúltú stair neamhghaolmhara a chumasc" + +#: builtin/merge-tree.c +msgid "failure to merge" +msgstr "teip a chumasc" + +#: builtin/merge-tree.c +msgid "git merge-tree [--write-tree] [] " +msgstr "git merge-tree [--write-tree] [] " + +#: builtin/merge-tree.c +msgid "git merge-tree [--trivial-merge] " +msgstr "git merge-tree [--trivial-cumaisc] " + +#: builtin/merge-tree.c +msgid "do a real merge instead of a trivial merge" +msgstr "déan fíor-chumasc in ionad cumaisc triobháideach" + +#: builtin/merge-tree.c +msgid "do a trivial merge only" +msgstr "déan cumaisc thréimhseach amháin" + +#: builtin/merge-tree.c +msgid "also show informational/conflict messages" +msgstr "taispeáin teachtaireachtaí faisnéis/coinbhleachta freisin" + +#: builtin/merge-tree.c +msgid "suppress all output; only exit status wanted" +msgstr "cosc a chur ar an aschur go léir; níl uaim ach stádas scoir" + +#: builtin/merge-tree.c +msgid "list filenames without modes/oids/stages" +msgstr "ainmneacha comhaid a liostáil gan modhair/oids/céimeanna" + +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c +msgid "allow merging unrelated histories" +msgstr "ligean stair neamhghaolmhara a chumasc" + +#: builtin/merge-tree.c +msgid "perform multiple merges, one per line of input" +msgstr "cumaisc iolracha a dhéanamh, ceann in aghaidh an líne ionchuir" + +#: builtin/merge-tree.c +msgid "specify a merge-base for the merge" +msgstr "sonraigh bonn cumaisc don chumasc" + +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c +msgid "option=value" +msgstr "rogha = luach" + +#: builtin/merge-tree.c builtin/merge.c builtin/pull.c +msgid "option for selected merge strategy" +msgstr "rogha do straitéis cumaisc roghnaithe" + +#: builtin/merge-tree.c +msgid "--trivial-merge is incompatible with all other options" +msgstr "Tá --trivial-merge neamhoiriúnach le gach rogha eile" + +#: builtin/merge-tree.c builtin/merge.c +#, c-format +msgid "unknown strategy option: -X%s" +msgstr "rogha straitéise anaithnid: -X%s" + +#: builtin/merge-tree.c builtin/notes.c +#, c-format +msgid "malformed input line: '%s'." +msgstr "líne ionchuir mífhoirmithe: '%s'." + +#: builtin/merge.c +msgid "git merge [] [...]" +msgstr "git cumaisc [] [...]" + +#: builtin/merge.c +msgid "switch `m' requires a value" +msgstr "teastaíonn luach ag lasc `m'" + +#: builtin/merge.c +#, c-format +msgid "option `%s' requires a value" +msgstr "teastaíonn luach ag rogha `%s'" + +#: builtin/merge.c +#, c-format +msgid "Could not find merge strategy '%s'.\n" +msgstr "Níorbh fhéidir straitéis cumaisc '%s' a fháil.\n" + +#: builtin/merge.c +#, c-format +msgid "Available strategies are:" +msgstr "Is iad straitéisí atá ar fáil:" + +#: builtin/merge.c +#, c-format +msgid "Available custom strategies are:" +msgstr "Is iad seo a leanas na straitéisí saincheaptha atá ar fáil:" + +#: builtin/merge.c builtin/pull.c +msgid "do not show a diffstat at the end of the merge" +msgstr "ná taispeáin diffstat ag deireadh an chumaisc" + +#: builtin/merge.c builtin/pull.c +msgid "show a diffstat at the end of the merge" +msgstr "taispeáin diffstat ag deireadh an chumaisc" + +#: builtin/merge.c builtin/pull.c +msgid "(synonym to --stat)" +msgstr "(Comhchiallach le --stat)" + +#: builtin/merge.c builtin/pull.c +msgid "add (at most ) entries from shortlog to merge commit message" +msgstr "" +"cuir iontrálacha (ar a mh éad) ó gearrlog chun teachtaireacht tiomanta a " +"chumasc" + +#: builtin/merge.c builtin/pull.c +msgid "create a single commit instead of doing a merge" +msgstr "tiomantas amháin a chruthú in ionad cumaisc a dhéanamh" + +#: builtin/merge.c builtin/pull.c +msgid "perform a commit if the merge succeeds (default)" +msgstr "tiomantas a dhéanamh má éireoidh leis an gcumasc (réamhshocraithe)" + +#: builtin/merge.c builtin/pull.c +msgid "edit message before committing" +msgstr "teachtaireacht in eagar sula ndéanann" + +#: builtin/merge.c +msgid "allow fast-forward (default)" +msgstr "ligean go tapa ar aghaidh (réamhshocraithe)" + +#: builtin/merge.c builtin/pull.c +msgid "abort if fast-forward is not possible" +msgstr "déan deireadh a chur ar aghaidh mura féidir go tapa ar aghaidh" + +#: builtin/merge.c builtin/pull.c +msgid "verify that the named commit has a valid GPG signature" +msgstr "fíorú go bhfuil síniú bailí GPG ag an tiomantas ainmnithe" + +#: builtin/merge.c builtin/notes.c builtin/pull.c builtin/rebase.c +#: builtin/revert.c +msgid "strategy" +msgstr "straitéis" + +#: builtin/merge.c builtin/pull.c +msgid "merge strategy to use" +msgstr "straitéis a chumasc le húsáid" + +#: builtin/merge.c +msgid "merge commit message (for a non-fast-forward merge)" +msgstr "" +"teachtaireacht tiomanta a chumasc (le haghaidh cumaisc neamh-tapa ar aghaidh)" + +#: builtin/merge.c +msgid "use instead of the real target" +msgstr "úsáid in ionad an sprioc fíor" + +#: builtin/merge.c +msgid "abort the current in-progress merge" +msgstr "deireadh a chur leis an gcumasc reatha atá ar siúl" + +#: builtin/merge.c +msgid "--abort but leave index and working tree alone" +msgstr "--abort ach fág an t-innéacs agus an crann oibre ina n-aonar" + +#: builtin/merge.c +msgid "continue the current in-progress merge" +msgstr "leanúint leis an gcumasc atá ar siúl reatha" + +#: builtin/merge.c +msgid "bypass pre-merge-commit and commit-msg hooks" +msgstr "seachbhóthar crúcaí réamh-chumaisc-tiomantas agus comh-msg" + +#: builtin/merge.c +msgid "could not run stash." +msgstr "ní fhéadfadh stash a reáchtáil." + +#: builtin/merge.c +msgid "stash failed" +msgstr "theip ar stash" + +#: builtin/merge.c +#, c-format +msgid "not a valid object: %s" +msgstr "ní réad bailí: %s" + +#: builtin/merge.c +msgid "read-tree failed" +msgstr "theip ar chrann léitheoireachta" + +#: builtin/merge.c +msgid "Already up to date. (nothing to squash)" +msgstr "Cothrom le dáta cheana féin. (rud ar bith le squash)" + +#: builtin/merge.c merge-ort-wrappers.c +msgid "Already up to date." +msgstr "Cothrom le dáta cheana féin." + +#: builtin/merge.c +#, c-format +msgid "Squash commit -- not updating HEAD\n" +msgstr "Tiomantas Squash - gan HEAD a nuashonrú\n" + +#: builtin/merge.c +#, c-format +msgid "No merge message -- not updating HEAD\n" +msgstr "Gan aon teachtaireacht cumaisc - gan HEAD a nuashonrú\n" + +#: builtin/merge.c +#, c-format +msgid "'%s' does not point to a commit" +msgstr "Ní thugann '%s' in iúl do thiomantas" + +#: builtin/merge.c +#, c-format +msgid "Bad branch.%s.mergeoptions string: %s" +msgstr "Drochbhrainse. %s.mergeoptions teaghrán: %s" + +#: builtin/merge.c merge-ort-wrappers.c +msgid "Unable to write index." +msgstr "Ní féidir innéacs a scríobh." + +#: builtin/merge.c +msgid "Not handling anything other than two heads merge." +msgstr "Gan aon rud a láimhseáil seachas dhá cheann cumasc." + +#: builtin/merge.c builtin/sparse-checkout.c +#, c-format +msgid "unable to write %s" +msgstr "nach féidir %s a scríobh" + +#: builtin/merge.c +#, c-format +msgid "Could not read from '%s'" +msgstr "Ní féidir léamh ó '%s'" + +#: builtin/merge.c +#, c-format +msgid "Not committing merge; use 'git commit' to complete the merge.\n" +msgstr "" +"Gan cumasc a dhéanamh; bain úsáid as 'git commit' chun an cumaisc a chur i " +"gcrích.\n" + +#: builtin/merge.c +msgid "" +"Please enter a commit message to explain why this merge is necessary,\n" +"especially if it merges an updated upstream into a topic branch.\n" +"\n" +msgstr "" +"Cuir isteach teachtaireacht tiomanta le do thoil chun a mhíniú cén fáth go " +"bhfuil gá leis\n" +"go háirithe má chomhcheanglaíonn sé nuashonraithe suas sruth i mbrainse " +"ábhair.\n" + +#: builtin/merge.c +msgid "An empty message aborts the commit.\n" +msgstr "Cuireann teachtaireacht fholamh deireadh leis an tiomantas.\n" + +#: builtin/merge.c +#, c-format +msgid "" +"Lines starting with '%s' will be ignored, and an empty message aborts\n" +"the commit.\n" +msgstr "" +"Déanfar neamhaird ar línte a thosaíonn le '%s', \n" +"agus cuirfidh teachtaireacht fholamh deireadh leis an tiomantas.\n" + +#: builtin/merge.c +msgid "Empty commit message." +msgstr "Teachtaireacht tiomanta folamh." + +#: builtin/merge.c +#, c-format +msgid "Wonderful.\n" +msgstr "Iontach.\n" + +#: builtin/merge.c +#, c-format +msgid "Automatic merge failed; fix conflicts and then commit the result.\n" +msgstr "" +"Theip ar chumasc uathoibríoch; coimhlintí a shocrú agus ansin an toradh\n" + +#: builtin/merge.c +msgid "No current branch." +msgstr "Níl aon bhrainse reatha." + +#: builtin/merge.c +msgid "No remote for the current branch." +msgstr "Níl aon iargúlta don bhrainse reatha." + +#: builtin/merge.c +msgid "No default upstream defined for the current branch." +msgstr "Níl aon réamhshocraithe suas sruth sainithe don bhrainse reatha." + +#: builtin/merge.c +#, c-format +msgid "No remote-tracking branch for %s from %s" +msgstr "Gan aon bhrainse cianrianaithe do %s ó %s" + +#: builtin/merge.c +#, c-format +msgid "Bad value '%s' in environment '%s'" +msgstr "Drochluach '%s' sa timpeallacht '%s'" + +#: builtin/merge.c editor.c read-cache.c wrapper.c +#, c-format +msgid "could not close '%s'" +msgstr "ní fhéadfaí '%s' a dhúnadh" + +#: builtin/merge.c +#, c-format +msgid "not something we can merge in %s: %s" +msgstr "ní rud is féidir linn a chumasc i %s: %s" + +#: builtin/merge.c +msgid "--abort expects no arguments" +msgstr "--abort ag súil nach bhfuil aon argóintí" + +#: builtin/merge.c +msgid "There is no merge to abort (MERGE_HEAD missing)." +msgstr "Níl aon chumasc ann chun deireadh a chur (MERGE_HEAD ar iarraidh)." + +#: builtin/merge.c +msgid "--quit expects no arguments" +msgstr "Tá --quit ag súil nach bhfuil aon argóintí" + +#: builtin/merge.c +msgid "--continue expects no arguments" +msgstr "--continue gan aon argóintí ag súil leo" + +#: builtin/merge.c +msgid "There is no merge in progress (MERGE_HEAD missing)." +msgstr "Níl aon chumasc ar siúl (MERGE_HEAD ar iarraidh)." + +#: builtin/merge.c +msgid "" +"You have not concluded your merge (MERGE_HEAD exists).\n" +"Please, commit your changes before you merge." +msgstr "" +"Níor thug tú do chumasc i gcrích (MERGE_HEAD ann).\n" +"Déan do chuid athruithe a dhéanamh sula ndéanann tú cumasc." + +#: builtin/merge.c +msgid "" +"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" +"Please, commit your changes before you merge." +msgstr "" +"Níor thug tú do phiocadh silíní i gcrích (CHERRY_PICK_HEAD ann).\n" +"Déan do chuid athruithe a dhéanamh sula ndéanann tú cumasc." + +#: builtin/merge.c +msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)." +msgstr "Níor thug tú do phiocadh silíní i gcrích (CHERRY_PICK_HEAD ann)." + +#: builtin/merge.c +msgid "No commit specified and merge.defaultToUpstream not set." +msgstr "" +"Níl aon tiomantas sonraithe agus níl merge.defaultToUpstream socraithe." + +#: builtin/merge.c +msgid "Squash commit into empty head not supported yet" +msgstr "Tiomann squash isteach i gceann folamh nach dtacaítear go fóill" + +#: builtin/merge.c +msgid "Non-fast-forward commit does not make sense into an empty head" +msgstr "Níl ciall ar thiomantas neamh-thapa ar aghaidh i gceann folamh" + +#: builtin/merge.c +#, c-format +msgid "%s - not something we can merge" +msgstr "%s - ní rud is féidir linn a chumasc" + +#: builtin/merge.c +msgid "Can merge only exactly one commit into empty head" +msgstr "Ní féidir ach tiomantas amháin a chumasc i gceann folamh" + +#: builtin/merge.c +#, c-format +msgid "Updating %s..%s\n" +msgstr "Ag nuashonrú %s..%s\n" + +#: builtin/merge.c merge-ort-wrappers.c +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by merge:\n" +" %s" +msgstr "" +"Déanfaí d'athruithe áitiúla ar na comhaid seo a leanas a fhorscríobh trí " +"chumasc:\n" +" %s" + +#: builtin/merge.c +#, c-format +msgid "Trying really trivial in-index merge...\n" +msgstr "Ag triail a dhéanamh cumasc in-innéacs fíor-thrá\n" + +#: builtin/merge.c +#, c-format +msgid "Nope.\n" +msgstr "Ní hea..\n" + +#: builtin/merge.c +#, c-format +msgid "Rewinding the tree to pristine...\n" +msgstr "Ag athchasadh an chrainn go dtí go mbeidh sé foirfe...\n" + +#: builtin/merge.c +#, c-format +msgid "Trying merge strategy %s...\n" +msgstr "Ag iarraidh straitéis cumaisc %s...\n" + +#: builtin/merge.c +#, c-format +msgid "No merge strategy handled the merge.\n" +msgstr "Níor láimhseáil aon straitéis chumaisc an cumasc.\n" + +#: builtin/merge.c +#, c-format +msgid "Merge with strategy %s failed.\n" +msgstr "Theip ar chumasc le straitéis %s.\n" + +#: builtin/merge.c +#, c-format +msgid "Using the %s strategy to prepare resolving by hand.\n" +msgstr "Ag baint úsáide as straitéis %s chun réiteach a ullmhú de láimh.\n" + +#: builtin/merge.c +#, c-format +msgid "Automatic merge went well; stopped before committing as requested\n" +msgstr "Chuaigh cumaisc uathoibríoch go maith; stad sula ndearna sé tiomanta\n" + +#: builtin/merge.c +#, c-format +msgid "When finished, apply stashed changes with `git stash pop`\n" +msgstr "" +"Nuair a bheidh críochnaithe, cuir athruithe stashed i bhfeidhm le `git stash " +"pop`\n" + +#: builtin/mktag.c +#, c-format +msgid "warning: tag input does not pass fsck: %s" +msgstr "rabhadh: ní théann ionchur clib ar fsck: %s" + +#: builtin/mktag.c +#, c-format +msgid "error: tag input does not pass fsck: %s" +msgstr "earráid: ní théann ionchur clib ar fsck: %s" + +#: builtin/mktag.c +#, c-format +msgid "%d (FSCK_IGNORE?) should never trigger this callback" +msgstr "%d (FSCK_IGNORE?) níor cheart go spreagfadh an t-aisghlaoch seo" + +#: builtin/mktag.c +#, c-format +msgid "could not read tagged object '%s'" +msgstr "ní fhéadfaí réad clibeáilte '%s' a léamh" + +#: builtin/mktag.c +#, c-format +msgid "object '%s' tagged as '%s', but is a '%s' type" +msgstr "réad '%s' clibeáilte mar '%s', ach is cineál '%s' é" + +#: builtin/mktag.c +msgid "tag on stdin did not pass our strict fsck check" +msgstr "níor rith tag ar stdin ár seiceáil dhian fsck" + +#: builtin/mktag.c +msgid "tag on stdin did not refer to a valid object" +msgstr "níor thagraigh an chlib ar stdin do réad bailí" + +#: builtin/mktag.c builtin/tag.c +msgid "unable to write tag file" +msgstr "in ann comhad clib a scríobh" + +#: builtin/mktree.c +msgid "input is NUL terminated" +msgstr "cuirtear deireadh le hionchur NUL" + +#: builtin/mktree.c builtin/write-tree.c +msgid "allow missing objects" +msgstr "cead a cheadú rudaí" + +#: builtin/mktree.c +msgid "allow creation of more than one tree" +msgstr "cead níos mó ná crann amháin a chruthú" + +#: builtin/multi-pack-index.c +msgid "" +"git multi-pack-index [] write [--preferred-pack=][--refs-" +"snapshot=]" +msgstr "" +"git multi-pack-index [] write [--preferred-pack=][--refs-" +"snapshot=]" + +#: builtin/multi-pack-index.c +msgid "git multi-pack-index [] verify" +msgstr "git multi-pack-index [] verify" + +#: builtin/multi-pack-index.c +msgid "git multi-pack-index [] expire" +msgstr "git multi-pack-index [] expire" + +#: builtin/multi-pack-index.c +msgid "git multi-pack-index [] repack [--batch-size=]" +msgstr "git multi-pack-index [] repack [--batch-size=]" + +#: builtin/multi-pack-index.c +msgid "directory" +msgstr "eolaire" + +#: builtin/multi-pack-index.c +msgid "object directory containing set of packfile and pack-index pairs" +msgstr "" +"eolaire réada ina bhfuil tacar de phéirí pacáiste agus innéacs pacáiste" + +#: builtin/multi-pack-index.c +msgid "preferred-pack" +msgstr "pacáiste is fearr leat" + +#: builtin/multi-pack-index.c +msgid "pack for reuse when computing a multi-pack bitmap" +msgstr "pacáiste le húsáid agus bitmap il-phacáiste á ríomh" + +#: builtin/multi-pack-index.c +msgid "write multi-pack bitmap" +msgstr "scríobh bitmap il-phacáiste" + +#: builtin/multi-pack-index.c +msgid "write a new incremental MIDX" +msgstr "scríobh MIDX incrementach nua" + +#: builtin/multi-pack-index.c +msgid "write multi-pack index containing only given indexes" +msgstr "scríobh innéacs il-phacáiste nach bhfuil ach innéacsanna ar leith" + +#: builtin/multi-pack-index.c +msgid "refs snapshot for selecting bitmap commits" +msgstr "léargas refs chun gealltanais bitmap a roghnú" + +#: builtin/multi-pack-index.c +msgid "" +"during repack, collect pack-files of smaller size into a batch that is " +"larger than this size" +msgstr "" +"le linn athphacáil, bailigh comhaid pacáiste de mhéid níos lú i mbaisc atá " +"níos mó ná an méid seo" + +#: builtin/mv.c +msgid "git mv [-v] [-f] [-n] [-k] " +msgstr "git mv [-v] [-f] [-n] [-k] " + +#: builtin/mv.c +msgid "git mv [-v] [-f] [-n] [-k] ... " +msgstr "git mv [-v] [-f] [-n] [-k]... " + +#: builtin/mv.c +#, c-format +msgid "Directory %s is in index and no submodule?" +msgstr "Tá eolaire %s in innéacs agus níl aon fho-mhodúl ann?" + +#: builtin/mv.c +msgid "Please stage your changes to .gitmodules or stash them to proceed" +msgstr "" +"Cuir do chuid athruithe ar .gitmodules nó iad a stóráil chun dul ar aghaidh" + +#: builtin/mv.c +#, c-format +msgid "%.*s is in index" +msgstr "%.*s atá san innéacs" + +#: builtin/mv.c +msgid "force move/rename even if target exists" +msgstr "aistriúin/athainmniú a fhorbairt fiú má tá sprioc ann" + +#: builtin/mv.c +msgid "skip move/rename errors" +msgstr "scipeáil earráidí a bhogadh/athainmniú" + +#: builtin/mv.c +#, c-format +msgid "destination '%s' is not a directory" +msgstr "ní eolaire é ceann scríbe '%s'" + +#: builtin/mv.c +#, c-format +msgid "Checking rename of '%s' to '%s'\n" +msgstr "Seiceáil athainmniú '%s' go '%s'\n" + +#: builtin/mv.c +msgid "bad source" +msgstr "droch-fhoinse" + +#: builtin/mv.c +msgid "destination exists" +msgstr "ceann scríbe ann" + +#: builtin/mv.c +msgid "can not move directory into itself" +msgstr "ní féidir eolaire a bhogadh isteach ina féin" + +#: builtin/mv.c +msgid "destination already exists" +msgstr "ceann scríbe ann cheana féin" + +#: builtin/mv.c +msgid "source directory is empty" +msgstr "tá eolaire foinse folamh" + +#: builtin/mv.c +msgid "not under version control" +msgstr "nach bhfuil faoi rialú leagan" + +#: builtin/mv.c +msgid "conflicted" +msgstr "coimhlinneach" + +#: builtin/mv.c +#, c-format +msgid "overwriting '%s'" +msgstr "athscríobh '%s'" + +#: builtin/mv.c +msgid "Cannot overwrite" +msgstr "Ní féidir athscríobh" + +#: builtin/mv.c +msgid "multiple sources for the same target" +msgstr "foinsí iolracha don sprioc chéanna" + +#: builtin/mv.c +msgid "destination directory does not exist" +msgstr "níl eolaire ceann scríbe ann" + +#: builtin/mv.c +msgid "destination exists in the index" +msgstr "ceann scríbe ann san innéacs" + +#: builtin/mv.c +#, c-format +msgid "%s, source=%s, destination=%s" +msgstr "%s, foinse = %s, ceann scríbe = %s" + +#: builtin/mv.c +#, c-format +msgid "cannot move both '%s' and its parent directory '%s'" +msgstr "ní féidir '%s' agus a eolaire tuismitheora '%s' a bhogadh" + +#: builtin/mv.c +#, c-format +msgid "Renaming %s to %s\n" +msgstr "Athainmniú %s go %s\n" + +#: builtin/mv.c builtin/remote.c +#, c-format +msgid "renaming '%s' failed" +msgstr "theip ar athainmniú '%s'" + +#: builtin/name-rev.c +msgid "git name-rev [] ..." +msgstr "git name-rev [] ..." + +#: builtin/name-rev.c +msgid "git name-rev [] --all" +msgstr "git name-rev [] --all" + +#: builtin/name-rev.c +msgid "git name-rev [] --annotate-stdin" +msgstr "git name-rev [] --annotate-stdin" + +#: builtin/name-rev.c +msgid "print only ref-based names (no object names)" +msgstr "ainmneacha ref-bhunaithe amháin a phriontáil (gan ainmneacha réada)" + +#: builtin/name-rev.c +msgid "only use tags to name the commits" +msgstr "ní húsáid ach clibeanna chun na gealltanais a ainmniú" + +#: builtin/name-rev.c +msgid "only use refs matching " +msgstr "ní úsáideann ach meaitseáil refs " + +#: builtin/name-rev.c +msgid "ignore refs matching " +msgstr "neamhaird a dhéanamh ar mheaitseáil " + +#: builtin/name-rev.c +msgid "list all commits reachable from all refs" +msgstr "liostáil na gealltanais go léir atá inrochtana ó gach ceann" + +#: builtin/name-rev.c +msgid "deprecated: use --annotate-stdin instead" +msgstr "díscríofa: bain úsáid as --annotate-stdin ina ionad" + +#: builtin/name-rev.c +msgid "annotate text from stdin" +msgstr "téacs a anótáil ó stdin" + +#: builtin/name-rev.c +msgid "allow to print `undefined` names (default)" +msgstr "" +"cead a thabhairt d'ainmneacha “neamhshainithe” a phriontáil (réamhshocrú" + +#: builtin/name-rev.c +msgid "dereference tags in the input (internal use)" +msgstr "clibeanna dereference san ionchur (úsáid inmheánach)" + +#: builtin/notes.c +msgid "git notes [--ref ] [list []]" +msgstr "git notes [--ref ] [list []]" + +#: builtin/notes.c +msgid "" +"git notes [--ref ] add [-f] [--allow-empty] [--[no-]separator|--" +"separator=] [--[no-]stripspace] [-m | -F | (-c " +"| -C) ] [] [-e]" +msgstr "" +"git notes [--ref ] add [-f] [--allow-empty] [--[no-]separator|--" +"separator=] [--[no-]stripspace] [-m | -F | (-c " +"| -C) ] [] [-e]" + +#: builtin/notes.c +msgid "git notes [--ref ] copy [-f] " +msgstr "git notes [--ref] cóipeáil [-f] " + +#: builtin/notes.c +msgid "" +"git notes [--ref ] append [--allow-empty] [--[no-]separator|--" +"separator=] [--[no-]stripspace] [-m | -F | (-c " +"| -C) ] [] [-e]" +msgstr "" +"git notes [--ref ] append [--allow-empty] [--[no-]separator|--" +"separator=] [--[no-]stripspace] [-m | -F | (-c " +"| -C) ] [] [-e]" + +#: builtin/notes.c +msgid "git notes [--ref ] edit [--allow-empty] []" +msgstr "git notes [--ref ] edit [--allow-empty] []" + +#: builtin/notes.c +msgid "git notes [--ref ] show []" +msgstr "git notes [--ref ] show []" + +#: builtin/notes.c +msgid "" +"git notes [--ref ] merge [-v | -q] [-s ] " +msgstr "" +"git notes [--ref ] merge [-v | -q] [-s ] " + +#: builtin/notes.c +msgid "git notes [--ref ] remove [...]" +msgstr "git notes [--ref ] remove [...]" + +#: builtin/notes.c +msgid "git notes [--ref ] prune [-n] [-v]" +msgstr "git notes [--ref ] prune [-n] [-v]" + +#: builtin/notes.c +msgid "git notes [--ref ] get-ref" +msgstr "git notes [--ref ] get-ref" + +#: builtin/notes.c +msgid "git notes [list []]" +msgstr "git notes [list []]" + +#: builtin/notes.c +msgid "git notes add [] []" +msgstr "git notes add [] []" + +#: builtin/notes.c +msgid "git notes copy [] " +msgstr "git notes copy [] " + +#: builtin/notes.c +msgid "git notes copy --stdin [ ]..." +msgstr "git notes copy --stdin [ ]..." + +#: builtin/notes.c +msgid "git notes append [] []" +msgstr "git notes append [] []" + +#: builtin/notes.c +msgid "git notes edit []" +msgstr "nótaí git a chur in eagar []" + +#: builtin/notes.c +msgid "git notes show []" +msgstr "taispeánann nótaí git []" + +#: builtin/notes.c +msgid "git notes merge [] " +msgstr "cumaisc nótaí git [] " + +#: builtin/notes.c +msgid "git notes merge --commit []" +msgstr "git notes merge --commit []" + +#: builtin/notes.c +msgid "git notes merge --abort []" +msgstr "git notes merge --abort []" + +#: builtin/notes.c +msgid "git notes remove []" +msgstr "git notes remove []" + +#: builtin/notes.c +msgid "git notes prune []" +msgstr "git notes prune []" + +#: builtin/notes.c +msgid "Write/edit the notes for the following object:" +msgstr "Scríobh/cuir in eagar na nótaí don réad seo a leanas:" + +#: builtin/notes.c +msgid "could not read 'show' output" +msgstr "ní raibh in ann aschur 'taispeáin' a léamh" + +#: builtin/notes.c +#, c-format +msgid "failed to finish 'show' for object '%s'" +msgstr "theip ar 'show' a chríochnú le haghaidh réad '%s'" + +#: builtin/notes.c +msgid "please supply the note contents using either -m or -F option" +msgstr "soláthar ábhar an nóta le do thoil ag baint úsáide as rogha -m nó -F" + +#: builtin/notes.c +msgid "unable to write note object" +msgstr "in ann réad nótaí a scríobh" + +#: builtin/notes.c +#, c-format +msgid "the note contents have been left in %s" +msgstr "tá ábhar an nóta fágtha i %s" + +#: builtin/notes.c builtin/tag.c +#, c-format +msgid "could not open or read '%s'" +msgstr "ní fhéadfaí '%s' a oscailt nó a léamh" + +#: builtin/notes.c +#, c-format +msgid "failed to resolve '%s' as a valid ref." +msgstr "theip ar '%s' a réiteach mar thagartha bailí." + +#: builtin/notes.c +#, c-format +msgid "failed to read object '%s'." +msgstr "theip ar réad '%s' a léamh." + +#: builtin/notes.c +#, c-format +msgid "cannot read note data from non-blob object '%s'." +msgstr "ní féidir sonraí nótaí a léamh ó réad neamh-blob '%s'." + +#: builtin/notes.c +#, c-format +msgid "failed to copy notes from '%s' to '%s'" +msgstr "theip ar nótaí a chóipeáil ó '%s' go '%s'" + +#. TRANSLATORS: the first %s will be replaced by a git +#. notes command: 'add', 'merge', 'remove', etc. +#. +#: builtin/notes.c +#, c-format +msgid "refusing to %s notes in %s (outside of refs/notes/)" +msgstr "diúltú do %s nótaí i %s (lasmuigh de refs/notes/)" + +#: builtin/notes.c +#, c-format +msgid "no note found for object %s." +msgstr "ní bhfuarthas aon nóta do réad %s." + +#: builtin/notes.c +msgid "note contents as a string" +msgstr "tabhair faoi deara ábhar mar shreang" + +#: builtin/notes.c +msgid "note contents in a file" +msgstr "tabhair faoi deara ábhar i gcomhad" + +#: builtin/notes.c +msgid "reuse and edit specified note object" +msgstr "réad nóta sonraithe a úsáid agus a chur in eagar" + +#: builtin/notes.c +msgid "edit note message in editor" +msgstr "teachtaireacht nóta in eagar san eagarthóir" + +#: builtin/notes.c +msgid "reuse specified note object" +msgstr "réad nóta sonraithe a athúsáid" + +#: builtin/notes.c +msgid "allow storing empty note" +msgstr "ligean nóta folamh a stóráil" + +#: builtin/notes.c +msgid "replace existing notes" +msgstr "nótaí atá ann cheana in ionad" + +#: builtin/notes.c +msgid "" +msgstr "" + +#: builtin/notes.c +msgid "insert between paragraphs" +msgstr "cuir isteach idir míreanna" + +#: builtin/notes.c +msgid "remove unnecessary whitespace" +msgstr "bain spás bán neamhriachtanach" + +#: builtin/notes.c +#, c-format +msgid "" +"Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite " +"existing notes" +msgstr "" +"Ní féidir nótaí a chur leis. Fuarthas nótaí atá ann cheana don réad %s. " +"Úsáid '-f' chun nótaí atá ann cheana a fhorscríobh" + +#: builtin/notes.c +#, c-format +msgid "Overwriting existing notes for object %s\n" +msgstr "Athscríobh nótaí atá ann cheana don réad %s\n" + +#: builtin/notes.c +#, c-format +msgid "Removing note for object %s\n" +msgstr "Nóta a bhaint le haghaidh réad %s\n" + +#: builtin/notes.c +msgid "read objects from stdin" +msgstr "léigh rudaí ó stdin" + +#: builtin/notes.c +msgid "load rewriting config for (implies --stdin)" +msgstr "" +"cumraíocht athscríbhneoireachta ualaigh le haghaidh (tugann le " +"tuiscint --stdin)" + +#: builtin/notes.c +msgid "too few arguments" +msgstr "ró-bheag argóintí" + +#: builtin/notes.c +#, c-format +msgid "" +"Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite " +"existing notes" +msgstr "" +"Ní féidir nótaí a chóipeáil. Fuarthas nótaí atá ann cheana don réad %s. " +"Úsáid '-f' chun nótaí atá ann cheana a fhorscríobh" + +#: builtin/notes.c +#, c-format +msgid "missing notes on source object %s. Cannot copy." +msgstr "nótaí in easnamh ar réad foinse %s. Ní féidir cóipeáil." + +#: builtin/notes.c +#, c-format +msgid "" +"The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n" +"Please use 'git notes add -f -m/-F/-c/-C' instead.\n" +msgstr "" +"Tá na roghanna -M/-f/-c/-c curtha as an bhfo-ordú 'eagarthóireach'.\n" +"Úsáid le do thoil 'git notes add -f -m/-f/-c/-C' ina ionad.\n" + +#: builtin/notes.c +msgid "failed to delete ref NOTES_MERGE_PARTIAL" +msgstr "theip ar an tagairt NOTES_MERGE_PARTIAL a scriosadh" + +#: builtin/notes.c +msgid "failed to delete ref NOTES_MERGE_REF" +msgstr "theip ar an ref a scriosadh NOTES_MERGE_REF" + +#: builtin/notes.c +msgid "failed to remove 'git notes merge' worktree" +msgstr "theip ar chrann oibre 'git notes merge' a bhaint" + +#: builtin/notes.c +msgid "failed to read ref NOTES_MERGE_PARTIAL" +msgstr "theip ar an tagairt NOTES_MERGE_PARTIAL a léamh" + +#: builtin/notes.c +msgid "could not find commit from NOTES_MERGE_PARTIAL." +msgstr "ní raibh sé in ann tiomantas a fháil ó NOTES_MERGE_PARTIAL." + +#: builtin/notes.c +msgid "could not parse commit from NOTES_MERGE_PARTIAL." +msgstr "ní raibh sé in ann tiomantas a pharsáil ó NOTES_MERGE_PARTIAL." + +#: builtin/notes.c +msgid "failed to resolve NOTES_MERGE_REF" +msgstr "theip orthu NOTES_MERGE_REF a réiteach" + +#: builtin/notes.c +msgid "failed to finalize notes merge" +msgstr "theip orthu nótaí a chumasc a chur i gcrích" + +#: builtin/notes.c +#, c-format +msgid "unknown notes merge strategy %s" +msgstr "straitéis cumaisc nótaí anaithnid %s" + +#: builtin/notes.c +msgid "General options" +msgstr "Roghanna ginearálta" + +#: builtin/notes.c +msgid "Merge options" +msgstr "Roghanna cumaisc" + +#: builtin/notes.c +msgid "" +"resolve notes conflicts using the given strategy (manual/ours/theirs/union/" +"cat_sort_uniq)" +msgstr "" +"coimhlintí nótaí a réiteach ag baint úsáide as an straitéis a thugtar " +"(lámhleabhair/innir/a nd/union/cat_sort_uniq)" + +#: builtin/notes.c +msgid "Committing unmerged notes" +msgstr "Nótaí neamh-mheánaithe a dhéanamh" + +#: builtin/notes.c +msgid "finalize notes merge by committing unmerged notes" +msgstr "cumasc nótaí a chríochnú trí nótaí neamh-chumasaithe a dhéanamh" + +#: builtin/notes.c +msgid "Aborting notes merge resolution" +msgstr "Rún cumasc le nótaí a ghearradh" + +#: builtin/notes.c +msgid "abort notes merge" +msgstr "cumaisc nótaí abort" + +#: builtin/notes.c +msgid "cannot mix --commit, --abort or -s/--strategy" +msgstr "ní féidir --commit, --abort nó -s/--strategy a mheascadh" + +#: builtin/notes.c +msgid "must specify a notes ref to merge" +msgstr "ní mór tagairt nótaí a shonrú chun cumasc" + +#: builtin/notes.c +#, c-format +msgid "unknown -s/--strategy: %s" +msgstr "anaithnid -s/--strategy: %s" + +#: builtin/notes.c +#, c-format +msgid "a notes merge into %s is already in-progress at %s" +msgstr "tá nótaí a chumasc i %s ar siúl cheana féin ag %s" + +#: builtin/notes.c +#, c-format +msgid "failed to store link to current notes ref (%s)" +msgstr "theip ar nasc a stóráil le nótaí reatha tagairt (%s)" + +#: builtin/notes.c +#, c-format +msgid "" +"Automatic notes merge failed. Fix conflicts in %s and commit the result with " +"'git notes merge --commit', or abort the merge with 'git notes merge --" +"abort'.\n" +msgstr "" +"Theip ar chumasc nótaí uathoibríoch Socraigh coinbhleachtaí i %s agus déan " +"an toradh a dhéanamh le 'git notes merge --commit', nó cuir deireadh leis an " +"cumasc le 'git notes merge --abort'.\n" + +#: builtin/notes.c builtin/tag.c +#, c-format +msgid "Failed to resolve '%s' as a valid ref." +msgstr "Theip ar '%s' a réiteach mar thagartha bailí." + +#: builtin/notes.c +#, c-format +msgid "Object %s has no note\n" +msgstr "Níl aon nóta ag réad %s\n" + +#: builtin/notes.c +msgid "attempt to remove non-existent note is not an error" +msgstr "ní earráid é iarracht nóta nach bhfuil ann a bhaint" + +#: builtin/notes.c +msgid "read object names from the standard input" +msgstr "léigh ainmneacha réada ón ionchur caighdeánach" + +#: builtin/notes.c builtin/prune.c builtin/worktree.c +msgid "do not remove, show only" +msgstr "ná bain, taispeáin amháin" + +#: builtin/notes.c +msgid "report pruned notes" +msgstr "nótaí gearrtha a thuairisciú" + +#: builtin/notes.c +msgid "notes-ref" +msgstr "nótairea-tagairt" + +#: builtin/notes.c +msgid "use notes from " +msgstr "úsáid nótaí ó " + +#: builtin/notes.c builtin/remote.c parse-options.c +#, c-format +msgid "unknown subcommand: `%s'" +msgstr "fo-ordú anaithnid: `%s'" + +#: builtin/pack-objects.c +msgid "git pack-objects --stdout [] [< | < ]" +msgstr "git pack-objects --stdout [] [< | < ]" + +#: builtin/pack-objects.c +msgid "" +"git pack-objects [] [< | < ]" +msgstr "" +"git pack-objects [] [< | < ]" + +#: builtin/pack-objects.c +#, c-format +msgid "invalid --name-hash-version option: %d" +msgstr "rogha neamhbhailí --name-hash-version: %d" + +#: builtin/pack-objects.c +msgid "currently, --write-bitmap-index requires --name-hash-version=1" +msgstr "faoi láthair, teastaíonn --write-bitmap-index --name-hash-version=1" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"write_reuse_object: could not locate %s, expected at offset % in " +"pack %s" +msgstr "" +"write_reuse_object: níorbh fhéidir %s a aimsiú, bhíothas ag súil leis ag an " +"bhfritháireamh % sa phacáiste %s" + +#: builtin/pack-objects.c +#, c-format +msgid "bad packed object CRC for %s" +msgstr "réad pacáilte dona CRC le haghaidh %s" + +#: builtin/pack-objects.c +#, c-format +msgid "corrupt packed object for %s" +msgstr "réad pacáilte truaillithe do %s" + +#: builtin/pack-objects.c +#, c-format +msgid "recursive delta detected for object %s" +msgstr "braithíodh delta athfhillteach do réad %s" + +#: builtin/pack-objects.c +#, c-format +msgid "ordered %u objects, expected %" +msgstr "rudaí %u ordaithe, súil leis% " + +#: builtin/pack-objects.c +#, c-format +msgid "expected object at offset % in pack %s" +msgstr "" +"réad a bhíothas ag súil leis ag an bhfritháireamh % sa phacáiste %s" + +#: builtin/pack-objects.c +msgid "disabling bitmap writing, packs are split due to pack.packSizeLimit" +msgstr "" +"scríobh bitmap a dhíchumasú, roinntear pacáistí mar gheall ar " +"pack.packSizeLimit" + +#: builtin/pack-objects.c +msgid "Writing objects" +msgstr "Rudaí a scríobh" + +#: builtin/pack-objects.c builtin/update-index.c +#, c-format +msgid "failed to stat %s" +msgstr "theip ar stát %s" + +#: builtin/pack-objects.c object-file.c +#, c-format +msgid "failed utime() on %s" +msgstr "theip ar utime () ar %s" + +#: builtin/pack-objects.c +msgid "failed to write bitmap index" +msgstr "theip ar innéacs bitmap a scríobh" + +#: builtin/pack-objects.c +#, c-format +msgid "wrote % objects while expecting %" +msgstr "scríobh % rudaí agus iad ag súil leis %" + +#: builtin/pack-objects.c builtin/repack.c +msgid "disabling bitmap writing, as some objects are not being packed" +msgstr "scríobh bitmap a dhíchumasú, toisc nach bhfuil roinnt rudaí á phacáil" + +#: builtin/pack-objects.c +#, c-format +msgid "delta base offset overflow in pack for %s" +msgstr "forsreabhadh fhritháireamh bonn delta i bpacáiste do %s" + +#: builtin/pack-objects.c +#, c-format +msgid "delta base offset out of bound for %s" +msgstr "bonn delta a fhritháireamh as ceangailte do %s" + +#: builtin/pack-objects.c +msgid "Counting objects" +msgstr "Rud a chomhaireamh" + +#: builtin/pack-objects.c pack-bitmap.c +#, c-format +msgid "unable to get size of %s" +msgstr "nach féidir méid %s a fháil" + +#: builtin/pack-objects.c +#, c-format +msgid "unable to parse object header of %s" +msgstr "nach féidir ceanntásc réad %s a pháirseáil" + +#: builtin/pack-objects.c +#, c-format +msgid "object %s cannot be read" +msgstr "ní féidir réad %s a léamh" + +#: builtin/pack-objects.c +#, c-format +msgid "object %s inconsistent object length (% vs %)" +msgstr "fad réada neamhréireach réad %s (% vs %)" + +#: builtin/pack-objects.c +msgid "suboptimal pack - out of memory" +msgstr "pacáiste suboptimal - as cuimhne" + +#: builtin/pack-objects.c +#, c-format +msgid "Delta compression using up to %d threads" +msgstr "Comhbhrú Delta ag úsáid suas le snáitheanna %d" + +#: builtin/pack-objects.c +#, c-format +msgid "unable to pack objects reachable from tag %s" +msgstr "nach féidir rudaí a phacáil inrochtana ó chlib %s" + +#: builtin/pack-objects.c commit-graph.c +#, c-format +msgid "unable to get type of object %s" +msgstr "nach féidir cineál réada %s a fháil" + +#: builtin/pack-objects.c +msgid "Compressing objects" +msgstr "Rudaí comhbhrúite" + +#: builtin/pack-objects.c +msgid "inconsistency with delta count" +msgstr "neamhréireacht le comhaireamh delta" + +#: builtin/pack-objects.c +#, c-format +msgid "invalid pack.allowPackReuse value: '%s'" +msgstr "luach pack.allowPackReuse neamhbhailí: '%s'" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"value of uploadpack.blobpackfileuri must be of the form ' ' (got '%s')" +msgstr "" +"caithfidh luach uploadpack.blobpackfileuri a " +"bheith den fhoirm '' (fuair '%s')" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"object already configured in another uploadpack.blobpackfileuri (got '%s')" +msgstr "" +"réad cumraithe cheana féin i uploadpack.blobpackfileuri eile (fuair '%s')" + +#: builtin/pack-objects.c +#, c-format +msgid "could not get type of object %s in pack %s" +msgstr "ní fhéadfaí cineál réada %s a fháil i bpacáiste %s" + +#: builtin/pack-objects.c +#, c-format +msgid "could not find pack '%s'" +msgstr "ní raibh an pacáiste '%s' in ann a aimsiú" + +#: builtin/pack-objects.c +#, c-format +msgid "packfile %s cannot be accessed" +msgstr "ní féidir teacht ar chomhad pacáiste %s" + +#: builtin/pack-objects.c +msgid "Enumerating cruft objects" +msgstr "Ag áireamh rudaí cruft" + +#: builtin/pack-objects.c +msgid "unable to add cruft objects" +msgstr "in ann rudaí cruft a chur leis" + +#: builtin/pack-objects.c +msgid "Traversing cruft objects" +msgstr "Ag trasnú ar rudaí cruth" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"expected edge object ID, got garbage:\n" +" %s" +msgstr "" +"ag súil le haitheantas réada imeall, fuarthas bruscar:\n" +"%s" + +#: builtin/pack-objects.c +#, c-format +msgid "" +"expected object ID, got garbage:\n" +" %s" +msgstr "" +"aitheantas réada a bhfuil súil leis, fuair truflais:\n" +" %s" + +#: builtin/pack-objects.c reachable.c +msgid "could not load cruft pack .mtimes" +msgstr "ní fhéadfaí pacáiste cruft a luchtú .mtimes" + +#: builtin/pack-objects.c +msgid "cannot open pack index" +msgstr "ní féidir innéacs pacáiste a osc" + +#: builtin/pack-objects.c +#, c-format +msgid "loose object at %s could not be examined" +msgstr "ní fhéadfaí réad scaoilte ag %s a scrúdú" + +#: builtin/pack-objects.c +msgid "unable to force loose object" +msgstr "in ann rud scaoilte a chur i bhfeidhm" + +#: builtin/pack-objects.c +#, c-format +msgid "not a rev '%s'" +msgstr "ní rev '%s'" + +#: builtin/pack-objects.c builtin/rev-parse.c +#, c-format +msgid "bad revision '%s'" +msgstr "droch-athbhreithniú '%s'" + +#: builtin/pack-objects.c +msgid "unable to add recent objects" +msgstr "in ann rudaí le déanaí a chur leis" + +#: builtin/pack-objects.c +#, c-format +msgid "unsupported index version %s" +msgstr "leagan innéacs neamhthacaithe %s" + +#: builtin/pack-objects.c +#, c-format +msgid "bad index version '%s'" +msgstr "droch-leagan innéacs '%s'" + +#: builtin/pack-objects.c +msgid "show progress meter during object writing phase" +msgstr "méadar dul chun cinn a thaispeáint le linn céim sc" + +#: builtin/pack-objects.c +msgid "similar to --all-progress when progress meter is shown" +msgstr "cosúil le --all-progress nuair a thaispeántar méadar dul chun cinn" + +#: builtin/pack-objects.c +msgid "[,]" +msgstr "[,]" + +#: builtin/pack-objects.c +msgid "write the pack index file in the specified idx format version" +msgstr "scríobh an comhad innéacs pacáiste sa leagan formáid idx sonraithe" + +#: builtin/pack-objects.c +msgid "maximum size of each output pack file" +msgstr "uasmhéid gach comhad pacáiste aschuir" + +#: builtin/pack-objects.c +msgid "ignore borrowed objects from alternate object store" +msgstr "neamhaird a dhéanamh ar rudaí atá ar iasacht ó stór" + +#: builtin/pack-objects.c +msgid "ignore packed objects" +msgstr "neamhaird a dhéanamh ar earraí" + +#: builtin/pack-objects.c +msgid "limit pack window by objects" +msgstr "teorainn fuinneog pacáiste de réir rudaí" + +#: builtin/pack-objects.c +msgid "limit pack window by memory in addition to object limit" +msgstr "teorainn le fuinneog pacáiste de réir chuimhne i dteannta le teorainn" + +#: builtin/pack-objects.c +msgid "maximum length of delta chain allowed in the resulting pack" +msgstr "fad uasta an slabhra delta a cheadaítear sa phacáiste mar thoradh air" + +#: builtin/pack-objects.c +msgid "reuse existing deltas" +msgstr "déltaí atá ann cheana a athúsáid" + +#: builtin/pack-objects.c +msgid "reuse existing objects" +msgstr "athúsáid rudaí atá ann cheana" + +#: builtin/pack-objects.c +msgid "use OFS_DELTA objects" +msgstr "bain úsáid as rudaí OFS_DELTA" + +#: builtin/pack-objects.c +msgid "use threads when searching for best delta matches" +msgstr "úsáid snáitheanna agus tú ag cuardach na cluichí delta is fearr" + +#: builtin/pack-objects.c +msgid "do not create an empty pack output" +msgstr "ná cruthaigh aschur pacáiste folamh" + +#: builtin/pack-objects.c +msgid "read revision arguments from standard input" +msgstr "léigh argóintí athbhreithnithe ó ionchur" + +#: builtin/pack-objects.c +msgid "limit the objects to those that are not yet packed" +msgstr "teorainn leis na rudaí dóibh siúd nach bhfuil pacáilte fós" + +#: builtin/pack-objects.c +msgid "include objects reachable from any reference" +msgstr "áireamh rudaí atá inrochtana ó aon tagairt" + +#: builtin/pack-objects.c +msgid "include objects referred by reflog entries" +msgstr "áireamh rudaí a dtagraítear ag iontrálacha reflog" + +#: builtin/pack-objects.c +msgid "include objects referred to by the index" +msgstr "áireamh rudaí dá dtagraíonn an t-innéacs" + +#: builtin/pack-objects.c +msgid "read packs from stdin" +msgstr "léigh pacáistí ó stdin" + +#: builtin/pack-objects.c +msgid "output pack to stdout" +msgstr "pacáiste aschuir go stdout" + +#: builtin/pack-objects.c +msgid "include tag objects that refer to objects to be packed" +msgstr "áireamh rudaí clibeanna a thagraíonn do rudaí atá le pacáil" + +#: builtin/pack-objects.c +msgid "keep unreachable objects" +msgstr "rudaí nach féidir a choinneáil" + +#: builtin/pack-objects.c +msgid "pack loose unreachable objects" +msgstr "rudaí scaoilte nach féidir a phacáil" + +#: builtin/pack-objects.c +msgid "unpack unreachable objects newer than