From: Junio C Hamano Date: Mon, 27 Jun 2016 16:56:24 +0000 (-0700) Subject: Merge branch 'rs/xdiff-hunk-with-func-line' into maint X-Git-Tag: v2.9.1~36 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/fda65fadb6e98b5b8ea8058bbeaa29d983f335cb?hp=6f8d9bccb2c3694c62d14225976689c1e8c50fa5 Merge branch 'rs/xdiff-hunk-with-func-line' into maint "git show -W" (extend hunks to cover the entire function, delimited by lines that match the "funcname" pattern) used to show the entire file when a change added an entire function at the end of the file, which has been fixed. * rs/xdiff-hunk-with-func-line: xdiff: fix merging of appended hunk with -W grep: -W: don't extend context to trailing empty lines t7810: add test for grep -W and trailing empty context lines xdiff: don't trim common tail with -W xdiff: -W: don't include common trailing empty lines in context xdiff: ignore empty lines before added functions with -W xdiff: handle appended chunks better with -W xdiff: factor out match_func_rec() t4051: rewrite, add more tests --- diff --git a/.gitignore b/.gitignore index 5087ce1eb7..05cb58a3d4 100644 --- a/.gitignore +++ b/.gitignore @@ -179,39 +179,6 @@ /gitweb/gitweb.cgi /gitweb/static/gitweb.js /gitweb/static/gitweb.min.* -/test-chmtime -/test-ctype -/test-config -/test-date -/test-delta -/test-dump-cache-tree -/test-dump-split-index -/test-dump-untracked-cache -/test-fake-ssh -/test-scrap-cache-tree -/test-genrandom -/test-hashmap -/test-index-version -/test-line-buffer -/test-match-trees -/test-mergesort -/test-mktemp -/test-parse-options -/test-path-utils -/test-prio-queue -/test-read-cache -/test-regex -/test-revision-walking -/test-run-command -/test-sha1 -/test-sha1-array -/test-sigchain -/test-string-list -/test-submodule-config -/test-subprocess -/test-svn-fe -/test-urlmatch-normalization -/test-wildmatch /common-cmds.h *.tar.gz *.dsc diff --git a/.mailmap b/.mailmap index e5b4126bec..a9162c0095 100644 --- a/.mailmap +++ b/.mailmap @@ -51,6 +51,7 @@ Dirk Süsserott Eric Blake Eric Hanchrow Eric S. Raymond +Eric Wong Erik Faye-Lund Eyvind Bernhardsen Florian Achleitner diff --git a/.travis.yml b/.travis.yml index 78e433ba71..c20ec540c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,12 +18,16 @@ addons: apt: packages: - language-pack-is + - git-svn env: global: - DEVELOPER=1 - - P4_VERSION="15.2" - - GIT_LFS_VERSION="1.1.0" + # The Linux build installs the defined dependency versions below. + # The OS X build installs the latest available versions. Keep that + # in mind when you encounter a broken OS X build! + - LINUX_P4_VERSION="16.1" + - LINUX_GIT_LFS_VERSION="1.2.0" - DEFAULT_TEST_TARGET=prove - GIT_PROVE_OPTS="--timer --jobs 3 --state=failed,slow,save" - GIT_TEST_OPTS="--verbose --tee" @@ -32,23 +36,38 @@ env: # t9816 occasionally fails with "TAP out of sequence errors" on Travis CI OS X - GIT_SKIP_TESTS="t9810 t9816" +matrix: + include: + - env: Documentation + os: linux + compiler: clang + addons: + apt: + packages: + - asciidoc + - xmlto + before_install: + before_script: + script: ci/test-documentation.sh + after_failure: + before_install: - > case "${TRAVIS_OS_NAME:-linux}" in linux) mkdir --parents custom/p4 pushd custom/p4 - wget --quiet http://filehost.perforce.com/perforce/r$P4_VERSION/bin.linux26x86_64/p4d - wget --quiet http://filehost.perforce.com/perforce/r$P4_VERSION/bin.linux26x86_64/p4 + wget --quiet http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION/bin.linux26x86_64/p4d + wget --quiet http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION/bin.linux26x86_64/p4 chmod u+x p4d chmod u+x p4 export PATH="$(pwd):$PATH" popd mkdir --parents custom/git-lfs pushd custom/git-lfs - wget --quiet https://github.com/github/git-lfs/releases/download/v$GIT_LFS_VERSION/git-lfs-linux-amd64-$GIT_LFS_VERSION.tar.gz - tar --extract --gunzip --file "git-lfs-linux-amd64-$GIT_LFS_VERSION.tar.gz" - cp git-lfs-$GIT_LFS_VERSION/git-lfs . + wget --quiet https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz + tar --extract --gunzip --file "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" + cp git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs . export PATH="$(pwd):$PATH" popd ;; diff --git a/Documentation/Makefile b/Documentation/Makefile index 3e39e2815b..35c1385ef7 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -146,7 +146,7 @@ else ASCIIDOC_EXTRA += -a git-asciidoc-no-roff endif endif -ifdef MAN_BOLD_LITERAL +ifndef NO_MAN_BOLD_LITERAL XMLTO_EXTRA += -m manpage-bold-literal.xsl endif ifdef DOCBOOK_SUPPRESS_SP @@ -204,6 +204,7 @@ ifndef V QUIET_DBLATEX = @echo ' ' DBLATEX $@; QUIET_XSLTPROC = @echo ' ' XSLTPROC $@; QUIET_GEN = @echo ' ' GEN $@; + QUIET_LINT = @echo ' ' LINT $@; QUIET_STDERR = 2> /dev/null QUIET_SUBDIR0 = +@subdir= QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ @@ -427,4 +428,7 @@ quick-install-html: require-htmlrepo print-man1: @for i in $(MAN1_TXT); do echo $$i; done +lint-docs:: + $(QUIET_LINT)$(PERL_PATH) lint-gitlink.perl + .PHONY: FORCE diff --git a/Documentation/RelNotes/2.8.1.txt b/Documentation/RelNotes/2.8.1.txt new file mode 100644 index 0000000000..ef6d80b008 --- /dev/null +++ b/Documentation/RelNotes/2.8.1.txt @@ -0,0 +1,9 @@ +Git v2.8.1 Release Notes +======================== + +Fixes since v2.8 +---------------- + + * "make rpmbuild" target was broken as its input, git.spec.in, was + not updated to match a file it describes that has been renamed + recently. This has been fixed. diff --git a/Documentation/RelNotes/2.8.2.txt b/Documentation/RelNotes/2.8.2.txt new file mode 100644 index 0000000000..447b1933a8 --- /dev/null +++ b/Documentation/RelNotes/2.8.2.txt @@ -0,0 +1,70 @@ +Git v2.8.2 Release Notes +======================== + +Fixes since v2.8.1 +------------------ + + * The embedded args argv-array in the child process is used to build + the command line to run pack-objects instead of using a separate + array of strings. + + * Bunch of tests on "git clone" has been renumbered for better + organization. + + * The tests that involve running httpd leaked the system-wide + configuration in /etc/gitconfig to the tested environment. + + * "index-pack --keep=" was broken since v2.1.0 timeframe. + + * "git config --get-urlmatch", unlike other variants of the "git + config --get" family, did not signal error with its exit status + when there was no matching configuration. + + * The "--local-env-vars" and "--resolve-git-dir" options of "git + rev-parse" failed to work outside a repository when the command's + option parsing was rewritten in 1.8.5 era. + + * Fetching of history by naming a commit object name directly didn't + work across remote-curl transport. + + * A small memory leak in an error codepath has been plugged in xdiff + code. + + * strbuf_getwholeline() did not NUL-terminate the buffer on certain + corner cases in its error codepath. + + * The startup_info data, which records if we are working inside a + repository (among other things), are now uniformly available to Git + subcommand implementations, and Git avoids attempting to touch + references when we are not in a repository. + + * "git mergetool" did not work well with conflicts that both sides + deleted. + + * "git send-email" had trouble parsing alias file in mailrc format + when lines in it had trailing whitespaces on them. + + * When "git merge --squash" stopped due to conflict, the concluding + "git commit" failed to read in the SQUASH_MSG that shows the log + messages from all the squashed commits. + + * "git merge FETCH_HEAD" dereferenced NULL pointer when merging + nothing into an unborn history (which is arguably unusual usage, + which perhaps was the reason why nobody noticed it). + + * Build updates for MSVC. + + * "git diff -M" used to work better when two originally identical + files A and B got renamed to X/A and X/B by pairing A to X/A and B + to X/B, but this was broken in the 2.0 timeframe. + + * "git send-pack --all " was broken when its command line + option parsing was written in the 2.6 timeframe. + + * When running "git blame $path" with unnormalized data in the index + for the path, the data in the working tree was blamed, even though + "git add" would not have changed what is already in the index, due + to "safe crlf" that disables the line-end conversion. It has been + corrected. + +Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.8.3.txt b/Documentation/RelNotes/2.8.3.txt new file mode 100644 index 0000000000..fedd9968e5 --- /dev/null +++ b/Documentation/RelNotes/2.8.3.txt @@ -0,0 +1,101 @@ +Git v2.8.3 Release Notes +======================== + +Fixes since v2.8.2 +------------------ + + * "git send-email" now uses a more readable timestamps when + formulating a message ID. + + * The repository set-up sequence has been streamlined (the biggest + change is that there is no longer git_config_early()), so that we + do not attempt to look into refs/* when we know we do not have a + Git repository. + + * When "git worktree" feature is in use, "git branch -d" allowed + deletion of a branch that is checked out in another worktree + + * When "git worktree" feature is in use, "git branch -m" renamed a + branch that is checked out in another worktree without adjusting + the HEAD symbolic ref for the worktree. + + * "git format-patch --help" showed `-s` and `--no-patch` as if these + are valid options to the command. We already hide `--patch` option + from the documentation, because format-patch is about showing the + diff, and the documentation now hides these options as well. + + * A change back in version 2.7 to "git branch" broke display of a + symbolic ref in a non-standard place in the refs/ hierarchy (we + expect symbolic refs to appear in refs/remotes/*/HEAD to point at + the primary branch the remote has, and as .git/HEAD to point at the + branch we locally checked out). + + * A partial rewrite of "git submodule" in the 2.7 timeframe changed + the way the gitdir: pointer in the submodules point at the real + repository location to use absolute paths by accident. This has + been corrected. + + * "git commit" misbehaved in a few minor ways when an empty message + is given via -m '', all of which has been corrected. + + * Support for CRAM-MD5 authentication method in "git imap-send" did + not work well. + + * The socks5:// proxy support added back in 2.6.4 days was not aware + that socks5h:// proxies behave differently. + + * "git config" had a codepath that tried to pass a NULL to + printf("%s"), which nobody seems to have noticed. + + * On Cygwin, object creation uses the "create a temporary and then + rename it to the final name" pattern, not "create a temporary, + hardlink it to the final name and then unlink the temporary" + pattern. + + This is necessary to use Git on Windows shared directories, and is + already enabled for the MinGW and plain Windows builds. It also + has been used in Cygwin packaged versions of Git for quite a while. + See http://thread.gmane.org/gmane.comp.version-control.git/291853 + and http://thread.gmane.org/gmane.comp.version-control.git/275680. + + * "git replace -e" did not honour "core.editor" configuration. + + * Upcoming OpenSSL 1.1.0 will break compilation b updating a few APIs + we use in imap-send, which has been adjusted for the change. + + * "git submodule" reports the paths of submodules the command + recurses into, but this was incorrect when the command was not run + from the root level of the superproject. + + * The test scripts for "git p4" (but not "git p4" implementation + itself) has been updated so that they would work even on a system + where the installed version of Python is python 3. + + * The "user.useConfigOnly" configuration variable makes it an error + if users do not explicitly set user.name and user.email. However, + its check was not done early enough and allowed another error to + trigger, reporting that the default value we guessed from the + system setting was unusable. This was a suboptimal end-user + experience as we want the users to set user.name/user.email without + relying on the auto-detection at all. + + * "git mv old new" did not adjust the path for a submodule that lives + as a subdirectory inside old/ directory correctly. + + * "git push" from a corrupt repository that attempts to push a large + number of refs deadlocked; the thread to relay rejection notices + for these ref updates blocked on writing them to the main thread, + after the main thread at the receiving end notices that the push + failed and decides not to read these notices and return a failure. + + * A question by "git send-email" to ask the identity of the sender + has been updated. + + * Recent update to Git LFS broke "git p4" by changing the output from + its "lfs pointer" subcommand. + + * Some multi-byte encoding can have a backslash byte as a later part + of one letter, which would confuse "highlight" filter used in + gitweb. + +Also contains minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.8.4.txt b/Documentation/RelNotes/2.8.4.txt new file mode 100644 index 0000000000..f4e2552836 --- /dev/null +++ b/Documentation/RelNotes/2.8.4.txt @@ -0,0 +1,69 @@ +Git v2.8.4 Release Notes +======================== + +Fixes since v2.8.3 +------------------ + + * Documentation for "git merge --verify-signatures" has been updated + to clarify that the signature of only the commit at the tip is + verified. Also the phrasing used for signature and key validity is + adjusted to align with that used by OpenPGP. + + * On Windows, .git and optionally any files whose name starts with a + dot are now marked as hidden, with a core.hideDotFiles knob to + customize this behaviour. + + * Portability enhancement for "rebase -i" to help platforms whose + shell does not like "for i in " (which is not POSIX-kosher). + + * "git fsck" learned to catch NUL byte in a commit object as + potential error and warn. + + * CI test was taught to build documentation pages. + + * Many 'linkgit:' references were broken, + which are all fixed with this. + + * "git describe --contains" often made a hard-to-justify choice of + tag to give name to a given commit, because it tried to come up + with a name with smallest number of hops from a tag, causing an old + commit whose close descendant that is recently tagged were not + described with respect to an old tag but with a newer tag. It did + not help that its computation of "hop" count was further tweaked to + penalize being on a side branch of a merge. The logic has been + updated to favor using the tag with the oldest tagger date, which + is a lot easier to explain to the end users: "We describe a commit + in terms of the (chronologically) oldest tag that contains the + commit." + + * Running tests with '-x' option to trace the individual command + executions is a useful way to debug test scripts, but some tests + that capture the standard error stream and check what the command + said can be broken with the trace output mixed in. When running + our tests under "bash", however, we can redirect the trace output + to another file descriptor to keep the standard error of programs + being tested intact. + + * "http.cookieFile" configuration variable clearly wants a pathname, + but we forgot to treat it as such by e.g. applying tilde expansion. + + * When de-initialising all submodules, "git submodule deinit" gave a + faulty recommendation to use "git submodule deinit .", which would + result in a strange error message in a pathological corner case. + This has been corrected to suggest "submodule deinit --all" instead. + + * Many commands normalize command line arguments from NFD to NFC + variant of UTF-8 on OSX, but commands in the "diff" family did + not, causing "git diff $path" to complain that no such path is + known to Git. They have been taught to do the normalization. + + * A couple of bugs around core.autocrlf have been fixed. + + * "git difftool" learned to handle unmerged paths correctly in + dir-diff mode. + + * The "are we talking with TTY, doing an interactive session?" + detection has been updated to work better for "Git for Windows". + + +Also contains other minor documentation updates and code clean-ups. diff --git a/Documentation/RelNotes/2.9.0.txt b/Documentation/RelNotes/2.9.0.txt new file mode 100644 index 0000000000..b61d36712f --- /dev/null +++ b/Documentation/RelNotes/2.9.0.txt @@ -0,0 +1,512 @@ +Git 2.9 Release Notes +===================== + +Backward compatibility notes +---------------------------- + +The end-user facing Porcelain level commands in the "git diff" and +"git log" family by default enable the rename detection; you can still +use "diff.renames" configuration variable to disable this. + +Merging two branches that have no common ancestor with "git merge" is +by default forbidden now to prevent creating such an unusual merge by +mistake. + +The output formats of "git log" that indents the commit log message by +4 spaces now expands HT in the log message by default. You can use +the "--no-expand-tabs" option to disable this. + +"git commit-tree" plumbing command required the user to always sign +its result when the user sets the commit.gpgsign configuration +variable, which was an ancient mistake, which this release corrects. +A script that drives commit-tree, if it relies on this mistake, now +needs to read commit.gpgsign and pass the -S option as necessary. + + +Updates since v2.8 +------------------ + +UI, Workflows & Features + + * Comes with git-multimail 1.3.1 (in contrib/). + + * The end-user facing commands like "git diff" and "git log" + now enable the rename detection by default. + + * The credential.helper configuration variable is cumulative and + there is no good way to override it from the command line. As + a special case, giving an empty string as its value now serves + as the signal to clear the values specified in various files. + + * A new "interactive.diffFilter" configuration can be used to + customize the diff shown in "git add -i" sessions. + + * "git p4" now allows P4 author names to be mapped to Git author + names. + + * "git rebase -x" can be used without passing "-i" option. + + * "git -c credential.= submodule" can now be used to + propagate configuration variables related to credential helper + down to the submodules. + + * "git tag" can create an annotated tag without explicitly given an + "-a" (or "-s") option (i.e. when a tag message is given). A new + configuration variable, tag.forceSignAnnotated, can be used to tell + the command to create signed tag in such a situation. + + * "git merge" used to allow merging two branches that have no common + base by default, which led to a brand new history of an existing + project created and then get pulled by an unsuspecting maintainer, + which allowed an unnecessary parallel history merged into the + existing project. The command has been taught not to allow this by + default, with an escape hatch "--allow-unrelated-histories" option + to be used in a rare event that merges histories of two projects + that started their lives independently. + + * "git pull" has been taught to pass the "--allow-unrelated-histories" + option to underlying "git merge". + + * "git apply -v" learned to report paths in the patch that were + skipped via --include/--exclude mechanism or being outside the + current working directory. + + * Shell completion (in contrib/) updates. + + * The commit object name reported when "rebase -i" stops has been + shortened. + + * "git worktree add" can be given "--no-checkout" option to only + create an empty worktree without checking out the files. + + * "git mergetools" learned to drive ExamDiff. + + * "git pull --rebase" learned "--[no-]autostash" option, so that + the rebase.autostash configuration variable set to true can be + overridden from the command line. + + * When "git log" shows the log message indented by 4-spaces, the + remainder of a line after a HT does not align in the way the author + originally intended. The command now expands tabs by default to help + such a case, and allows the users to override it with a new option, + "--no-expand-tabs". + + * "git send-email" now uses a more readable timestamps when + formulating a message ID. + + * "git rerere" can encounter two or more files with the same conflict + signature that have to be resolved in different ways, but there was + no way to record these separate resolutions. + + * "git p4" learned to record P4 jobs in Git commit that imports from + the history in Perforce. + + * "git describe --contains" often made a hard-to-justify choice of + tag to name a given commit, because it tried to come up + with a name with smallest number of hops from a tag, causing an old + commit whose close descendant that is recently tagged were not + described with respect to an old tag but with a newer tag. It did + not help that its computation of "hop" count was further tweaked to + penalize being on a side branch of a merge. The logic has been + updated to favor using the tag with the oldest tagger date, which + is a lot easier to explain to the end users: "We describe a commit + in terms of the (chronologically) oldest tag that contains the + commit." + + * "git clone" learned the "--shallow-submodules" option. + + * HTTP transport clients learned to throw extra HTTP headers at the + server, specified via http.extraHeader configuration variable. + + * The "--compaction-heuristic" option to "git diff" family of + commands enables a heuristic to make the patch output more readable + by using a blank line as a strong hint that the contents before and + after it belong to logically separate units. It is still + experimental. + + * A new configuration variable core.hooksPath allows customizing + where the hook directory is. + + * An earlier addition of "sanitize_submodule_env" with 14111fc4 (git: + submodule honor -c credential.* from command line, 2016-02-29) + turned out to be a convoluted no-op; implement what it wanted to do + correctly, and stop filtering settings given via "git -c var=val". + + * "git commit --dry-run" reported "No, no, you cannot commit." in one + case where "git commit" would have allowed you to commit, and this + improves it a little bit ("git commit --dry-run --short" still does + not give you the correct answer, for example). This is a stop-gap + measure in that "commit --short --dry-run" still gives an incorrect + result. + + * The experimental "multiple worktree" feature gains more safety to + forbid operations on a branch that is checked out or being actively + worked on elsewhere, by noticing that e.g. it is being rebased. + + * "git format-patch" learned a new "--base" option to record what + (public, well-known) commit the original series was built on in + its output. + + * "git commit" learned to pay attention to the "commit.verbose" + configuration variable and act as if the "--verbose" option + was given from the command line. + + * Updated documentation gives hints to GMail users with two-factor + auth enabled that they need app-specific-password when using + "git send-email". + + * The manpage output of our documentation did not render well in + terminal; typeset literals in bold by default to make them stand + out more. + + * The mark-up in the top-level README.md file has been updated to + typeset CLI command names differently from the body text. + + +Performance, Internal Implementation, Development Support etc. + + * The embedded args argv-array in the child process is used to build + the command line to run pack-objects instead of using a separate + array of strings. + + * A test for tags has been restructured so that more parts of it can + easily be run on a platform without a working GnuPG. + + * The startup_info data, which records if we are working inside a + repository (among other things), are now uniformly available to Git + subcommand implementations, and Git avoids attempting to touch + references when we are not in a repository. + + * The command line argument parser for "receive-pack" has been + rewritten to use parse-options. + + * A major part of "git submodule update" has been ported to C to take + advantage of the recently added framework to run download tasks in + parallel. Other updates to "git submodule" that move pieces of + logic to C continues. + + * Rename bunch of tests on "git clone" for better organization. + + * The tests that involve running httpd leaked the system-wide + configuration in /etc/gitconfig to the tested environment. + + * Build updates for MSVC. + + * The repository set-up sequence has been streamlined (the biggest + change is that there is no longer git_config_early()), so that we + do not attempt to look into refs/* when we know we do not have a + Git repository. + + * Code restructuring around the "refs" API to prepare for pluggable + refs backends. + + * Sources to many test helper binaries and the generated helpers + have been moved to t/helper/ subdirectory to reduce clutter at the + top level of the tree. + + * Unify internal logic between "git tag -v" and "git verify-tag" + commands by making one directly call into the other. + + * "merge-recursive" strategy incorrectly checked if a path that is + involved in its internal merge exists in the working tree. + + * The test scripts for "git p4" (but not "git p4" implementation + itself) has been updated so that they would work even on a system + where the installed version of Python is python 3. + + * As nobody maintains our in-tree git.spec.in and distros use their + own spec file, we stopped pretending that we support "make rpm". + + * Move from "unsigned char[20]" to "struct object_id" continues. + + * The code for warning_errno/die_errno has been refactored and a new + error_errno() reporting helper is introduced. + (merge 1da045f nd/error-errno later to maint). + + * Running tests with '-x' option to trace the individual command + executions is a useful way to debug test scripts, but some tests + that capture the standard error stream and check what the command + said can be broken with the trace output mixed in. When running + our tests under "bash", however, we can redirect the trace output + to another file descriptor to keep the standard error of programs + being tested intact. + + * t0040 had too many unnecessary repetitions in its test data. Teach + test-parse-options program so that a caller can tell what it + expects in its output, so that these repetitions can be cleaned up. + + * Add perf test for "rebase -i". + + * Common mistakes when writing gitlink: in our documentation are + found by "make check-docs". + + * t9xxx series has been updated primarily for readability, while + fixing small bugs in it. A few scripted Porcelain commands have + also been updated to fix possible bugs around their use of + "test -z" and "test -n". + + * CI test was taught to run git-svn tests. + + * "git cat-file --batch-all" has been sped up, by taking advantage + of the fact that it does not have to read a list of objects, in two + ways. + + * test updates to make it more readable and maintainable. + (merge e6273f4 es/t1500-modernize later to maint). + + * "make DEVELOPER=1" worked as expected; setting DEVELOPER=1 in + config.mak didn't. + (merge 51dd3e8 mm/makefile-developer-can-be-in-config-mak later to maint). + + * The way how "submodule--helper list" signals unmatch error to its + callers has been updated. + + * A bash-ism "local" has been removed from "git submodule" scripted + Porcelain. + + +Also contains various documentation updates and code clean-ups. + + +Fixes since v2.8 +---------------- + +Unless otherwise noted, all the fixes since v2.8 in the maintenance +track are contained in this release (see the maintenance releases' +notes for details). + + * "git config --get-urlmatch", unlike other variants of the "git + config --get" family, did not signal error with its exit status + when there was no matching configuration. + + * The "--local-env-vars" and "--resolve-git-dir" options of "git + rev-parse" failed to work outside a repository when the command's + option parsing was rewritten in 1.8.5 era. + + * "git index-pack --keep[=] pack-$name.pack" simply did not work. + + * Fetching of history by naming a commit object name directly didn't + work across remote-curl transport. + + * A small memory leak in an error codepath has been plugged in xdiff + code. + + * strbuf_getwholeline() did not NUL-terminate the buffer on certain + corner cases in its error codepath. + + * "git mergetool" did not work well with conflicts that both sides + deleted. + + * "git send-email" had trouble parsing alias file in mailrc format + when lines in it had trailing whitespaces on them. + + * When "git merge --squash" stopped due to conflict, the concluding + "git commit" failed to read in the SQUASH_MSG that shows the log + messages from all the squashed commits. + + * "git merge FETCH_HEAD" dereferenced NULL pointer when merging + nothing into an unborn history (which is arguably unusual usage, + which perhaps was the reason why nobody noticed it). + + * When "git worktree" feature is in use, "git branch -d" allowed + deletion of a branch that is checked out in another worktree, + which was wrong. + + * When "git worktree" feature is in use, "git branch -m" renamed a + branch that is checked out in another worktree without adjusting + the HEAD symbolic ref for the worktree. + + * "git diff -M" used to work better when two originally identical + files A and B got renamed to X/A and X/B by pairing A to X/A and B + to X/B, but this was broken in the 2.0 timeframe. + + * "git send-pack --all " was broken when its command line + option parsing was written in the 2.6 timeframe. + + * "git format-patch --help" showed `-s` and `--no-patch` as if these + are valid options to the command. We already hide `--patch` option + from the documentation, because format-patch is about showing the + diff, and the documentation now hides these options as well. + + * When running "git blame $path" with unnormalized data in the index + for the path, the data in the working tree was blamed, even though + "git add" would not have changed what is already in the index, due + to "safe crlf" that disables the line-end conversion. It has been + corrected. + + * A change back in version 2.7 to "git branch" broke display of a + symbolic ref in a non-standard place in the refs/ hierarchy (we + expect symbolic refs to appear in refs/remotes/*/HEAD to point at + the primary branch the remote has, and as .git/HEAD to point at the + branch we locally checked out). + + * A partial rewrite of "git submodule" in the 2.7 timeframe changed + the way the gitdir: pointer in the submodules point at the real + repository location to use absolute paths by accident. This has + been corrected. + + * "git commit" misbehaved in a few minor ways when an empty message + is given via -m '', all of which has been corrected. + + * Support for CRAM-MD5 authentication method in "git imap-send" did + not work well. + + * Upcoming OpenSSL 1.1.0 will break compilation by updating a few API + elements we use in imap-send, which has been adjusted for the change. + + * The socks5:// proxy support added back in 2.6.4 days was not aware + that socks5h:// proxies behave differently from socks5:// proxies. + + * "git config" had a codepath that tried to pass a NULL to + printf("%s"), which nobody seems to have noticed. + + * On Cygwin, object creation uses the "create a temporary and then + rename it to the final name" pattern, not "create a temporary, + hardlink it to the final name and then unlink the temporary" + pattern. + + This is necessary to use Git on Windows shared directories, and is + already enabled for the MinGW and plain Windows builds. It also + has been used in Cygwin packaged versions of Git for quite a while. + See http://thread.gmane.org/gmane.comp.version-control.git/291853 + + * "merge-octopus" strategy did not ensure that the index is clean + when merge begins. + + * When "git merge" notices that the merge can be resolved purely at + the tree level (without having to merge blobs) and the resulting + tree happens to already exist in the object store, it forgot to + update the index, which left an inconsistent state that would + break later operations. + + * "git submodule" reports the paths of submodules the command + recurses into, but these paths were incorrectly reported when + the command was not run from the root level of the superproject. + + * The "user.useConfigOnly" configuration variable makes it an error + if users do not explicitly set user.name and user.email. However, + its check was not done early enough and allowed another error to + trigger, reporting that the default value we guessed from the + system setting was unusable. This was a suboptimal end-user + experience as we want the users to set user.name/user.email without + relying on the auto-detection at all. + + * "git mv old new" did not adjust the path for a submodule that lives + as a subdirectory inside old/ directory correctly. + + * "git replace -e" did not honour "core.editor" configuration. + + * "git push" from a corrupt repository that attempts to push a large + number of refs deadlocked; the thread to relay rejection notices + for these ref updates blocked on writing them to the main thread, + after the main thread at the receiving end notices that the push + failed and decides not to read these notices and return a failure. + + * mmap emulation on Windows has been optimized and work better without + consuming paging store when not needed. + + * A question by "git send-email" to ask the identity of the sender + has been updated. + + * UI consistency improvements for "git mergetool". + + * "git rebase -m" could be asked to rebase an entire branch starting + from the root, but failed by assuming that there always is a parent + commit to the first commit on the branch. + + * Fix a broken "p4 lfs" test. + + * Recent update to Git LFS broke "git p4" by changing the output from + its "lfs pointer" subcommand. + + * "git fetch" test t5510 was flaky while running a (forced) automagic + garbage collection. + + * Documentation updates to help contributors setting up Travis CI + test for their patches. + + * Some multi-byte encoding can have a backslash byte as a later part + of one letter, which would confuse "highlight" filter used in + gitweb. + + * "git commit-tree" plumbing command required the user to always sign + its result when the user sets the commit.gpgsign configuration + variable, which was an ancient mistake. Rework "git rebase" that + relied on this mistake so that it reads commit.gpgsign and pass (or + not pass) the -S option to "git commit-tree" to keep the end-user + expectation the same, while teaching "git commit-tree" to ignore + the configuration variable. This will stop requiring the users to + sign commit objects used internally as an implementation detail of + "git stash". + + * "http.cookieFile" configuration variable clearly wants a pathname, + but we forgot to treat it as such by e.g. applying tilde expansion. + + * Consolidate description of tilde-expansion that is done to + configuration variables that take pathname to a single place. + + * Correct faulty recommendation to use "git submodule deinit ." when + de-initialising all submodules, which would result in a strange + error message in a pathological corner case. + + * Many 'linkgit:' references were broken, + which are all fixed with this. + + * "git rerere" can get confused by conflict markers deliberately left + by the inner merge step, because they are indistinguishable from + the real conflict markers left by the outermost merge which are + what the end user and "rerere" need to look at. This was fixed by + making the conflict markers left by the inner merges a bit longer. + (merge 0f9fd5c jc/ll-merge-internal later to maint). + + * CI test was taught to build documentation pages. + + * "git fsck" learned to catch NUL byte in a commit object as + potential error and warn. + + * Portability enhancement for "rebase -i" to help platforms whose + shell does not like "for i in " (which is not POSIX-kosher). + + * On Windows, .git and optionally any files whose name starts with a + dot are now marked as hidden, with a core.hideDotFiles knob to + customize this behaviour. + + * Documentation for "git merge --verify-signatures" has been updated + to clarify that the signature of only the commit at the tip is + verified. Also the phrasing used for signature and key validity is + adjusted to align with that used by OpenPGP. + + * A couple of bugs around core.autocrlf have been fixed. + + * Many commands normalize command line arguments from NFD to NFC + variant of UTF-8 on OSX, but commands in the "diff" family did + not, causing "git diff $path" to complain that no such path is + known to Git. They have been taught to do the normalization. + + * "git difftool" learned to handle unmerged paths correctly in + dir-diff mode. + + * The "are we talking with TTY, doing an interactive session?" + detection has been updated to work better for "Git for Windows". + + * We forgot to add "git log --decorate=auto" to documentation when we + added the feature back in v2.1.0 timeframe. + (merge 462cbb4 rj/log-decorate-auto later to maint). + + * "git fast-import --export-marks" would overwrite the existing marks + file even when it makes a dump from its custom die routine. + Prevent it from doing so when we have an import-marks file but + haven't finished reading it. + (merge f4beed6 fc/fast-import-broken-marks-file later to maint). + + * "git rebase -i", after it fails to auto-resolve the conflict, had + an unnecessary call to "git rerere" from its very early days, which + was spotted recently; the call has been removed. + (merge 7063693 js/rebase-i-dedup-call-to-rerere later to maint). + + * Other minor clean-ups and documentation updates + (merge cd82b7a pa/cherry-pick-doc-typo later to maint). + (merge 2bb73ae rs/patch-id-use-skip-prefix later to maint). + (merge aa20cbc rs/apply-name-terminate later to maint). + (merge fe17fc0 jc/t2300-setup later to maint). + (merge e256eec jk/shell-portability later to maint). diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 98fc4cc1d0..e8ad978824 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -61,23 +61,28 @@ Make sure that you have tests for the bug you are fixing. See t/README for guidance. When adding a new feature, make sure that you have new tests to show -the feature triggers the new behaviour when it should, and to show the -feature does not trigger when it shouldn't. Also make sure that the -test suite passes after your commit. Do not forget to update the -documentation to describe the updated behaviour. - -Speaking of the documentation, it is currently a liberal mixture of US -and UK English norms for spelling and grammar, which is somewhat -unfortunate. A huge patch that touches the files all over the place -only to correct the inconsistency is not welcome, though. Potential -clashes with other changes that can result from such a patch are not -worth it. We prefer to gradually reconcile the inconsistencies in -favor of US English, with small and easily digestible patches, as a -side effect of doing some other real work in the vicinity (e.g. -rewriting a paragraph for clarity, while turning en_UK spelling to -en_US). Obvious typographical fixes are much more welcomed ("teh -> -"the"), preferably submitted as independent patches separate from -other documentation changes. +the feature triggers the new behavior when it should, and to show the +feature does not trigger when it shouldn't. After any code change, make +sure that the entire test suite passes. + +If you have an account at GitHub (and you can get one for free to work +on open source projects), you can use their Travis CI integration to +test your changes on Linux, Mac (and hopefully soon Windows). See +GitHub-Travis CI hints section for details. + +Do not forget to update the documentation to describe the updated +behavior and make sure that the resulting documentation set formats +well. It is currently a liberal mixture of US and UK English norms for +spelling and grammar, which is somewhat unfortunate. A huge patch that +touches the files all over the place only to correct the inconsistency +is not welcome, though. Potential clashes with other changes that can +result from such a patch are not worth it. We prefer to gradually +reconcile the inconsistencies in favor of US English, with small and +easily digestible patches, as a side effect of doing some other real +work in the vicinity (e.g. rewriting a paragraph for clarity, while +turning en_UK spelling to en_US). Obvious typographical fixes are much +more welcomed ("teh -> "the"), preferably submitted as independent +patches separate from other documentation changes. Oh, another thing. We are picky about whitespaces. Make sure your changes do not trigger errors with the sample pre-commit hook shipped @@ -370,6 +375,47 @@ Know the status of your patch after submission entitled "What's cooking in git.git" and "What's in git.git" giving the status of various proposed changes. +-------------------------------------------------- +GitHub-Travis CI hints + +With an account at GitHub (you can get one for free to work on open +source projects), you can use Travis CI to test your changes on Linux, +Mac (and hopefully soon Windows). You can find a successful example +test build here: https://travis-ci.org/git/git/builds/120473209 + +Follow these steps for the initial setup: + + (1) Fork https://github.com/git/git to your GitHub account. + You can find detailed instructions how to fork here: + https://help.github.com/articles/fork-a-repo/ + + (2) Open the Travis CI website: https://travis-ci.org + + (3) Press the "Sign in with GitHub" button. + + (4) Grant Travis CI permissions to access your GitHub account. + You can find more information about the required permissions here: + https://docs.travis-ci.com/user/github-oauth-scopes + + (5) Open your Travis CI profile page: https://travis-ci.org/profile + + (6) Enable Travis CI builds for your Git fork. + +After the initial setup, Travis CI will run whenever you push new changes +to your fork of Git on GitHub. You can monitor the test state of all your +branches here: https://travis-ci.org//git/branches + +If a branch did not pass all test cases then it is marked with a red +cross. In that case you can click on the failing Travis CI job and +scroll all the way down in the log. Find the line "<-- Click here to see +detailed test output!" and click on the triangle next to the log line +number to expand the detailed test output. Here is such a failing +example: https://travis-ci.org/git/git/jobs/122676187 + +Fix the problem and push your fix to your Git fork. This will trigger +a new Travis CI build to ensure all tests pass. + + ------------------------------------------------ MUA specific hints diff --git a/Documentation/config.txt b/Documentation/config.txt index 2cd6bdd7d2..2e1b2e486e 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -81,13 +81,16 @@ Includes You can include one config file from another by setting the special `include.path` variable to the name of the file to be included. The +variable takes a pathname as its value, and is subject to tilde +expansion. + +The included file is expanded immediately, as if its contents had been found at the location of the include directive. If the value of the `include.path` variable is a relative path, the path is considered to be relative to the configuration file in which the include directive was -found. The value of `include.path` is subject to tilde expansion: `~/` -is expanded to the value of `$HOME`, and `~user/` to the specified -user's home directory. See below for examples. +found. See below for examples. + Example ~~~~~~~ @@ -114,7 +117,7 @@ Example [include] path = /path/to/foo.inc ; include by absolute path path = foo ; expand "foo" relative to the current file - path = ~/foo ; expand "foo" in your $HOME directory + path = ~/foo ; expand "foo" in your `$HOME` directory Values @@ -169,6 +172,13 @@ thing on the same output line (e.g. opening parenthesis before the list of branch names in `log --decorate` output) is set to be painted with `bold` or some other attribute. +pathname:: + A variable that takes a pathname value can be given a + string that begins with "`~/`" or "`~user/`", and the usual + tilde expansion happens to such a string: `~/` + is expanded to the value of `$HOME`, and `~user/` to the + specified user's home directory. + Variables ~~~~~~~~~ @@ -269,6 +279,12 @@ See linkgit:git-update-index[1]. + The default is true (when core.filemode is not specified in the config file). +core.hideDotFiles:: + (Windows-only) If true, mark newly-created directories and files whose + name starts with a dot as hidden. If 'dotGitOnly', only the `.git/` + directory is hidden, but no other files starting with a dot. The + default mode is 'dotGitOnly'. + core.ignoreCase:: If true, this option enables various workarounds to enable Git to work better on filesystems that are not case sensitive, @@ -337,9 +353,9 @@ core.quotePath:: core.eol:: Sets the line ending type to use in the working directory for - files that have the `text` property set. Alternatives are - 'lf', 'crlf' and 'native', which uses the platform's native - line ending. The default value is `native`. See + files that have the `text` property set when core.autocrlf is false. + Alternatives are 'lf', 'crlf' and 'native', which uses the platform's + native line ending. The default value is `native`. See linkgit:gitattributes[5] for more information on end-of-line conversion. @@ -486,10 +502,10 @@ repository's usual working tree). core.logAllRefUpdates:: Enable the reflog. Updates to a ref is logged to the file - "$GIT_DIR/logs/", by appending the new and old + "`$GIT_DIR/logs/`", by appending the new and old SHA-1, the date/time and the reason of the update, but only when the file exists. If this configuration - variable is set to true, missing "$GIT_DIR/logs/" + variable is set to true, missing "`$GIT_DIR/logs/`" file is automatically created for branch heads (i.e. under refs/heads/), remote refs (i.e. under refs/remotes/), note refs (i.e. under refs/notes/), and the symbolic ref HEAD. @@ -593,12 +609,11 @@ be delta compressed, but larger binary media files won't be. Common unit suffixes of 'k', 'm', or 'g' are supported. core.excludesFile:: - In addition to '.gitignore' (per-directory) and - '.git/info/exclude', Git looks into this file for patterns - of files which are not meant to be tracked. "`~/`" is expanded - to the value of `$HOME` and "`~user/`" to the specified user's - home directory. Its default value is $XDG_CONFIG_HOME/git/ignore. - If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/ignore + Specifies the pathname to the file that contains patterns to + describe paths that are not meant to be tracked, in addition + to '.gitignore' (per-directory) and '.git/info/exclude'. + Defaults to `$XDG_CONFIG_HOME/git/ignore`. + If `$XDG_CONFIG_HOME` is either not set or empty, `$HOME/.config/git/ignore` is used instead. See linkgit:gitignore[5]. core.askPass:: @@ -615,8 +630,25 @@ core.attributesFile:: '.git/info/attributes', Git looks into this file for attributes (see linkgit:gitattributes[5]). Path expansions are made the same way as for `core.excludesFile`. Its default value is - $XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not - set or empty, $HOME/.config/git/attributes is used instead. + `$XDG_CONFIG_HOME/git/attributes`. If `$XDG_CONFIG_HOME` is either not + set or empty, `$HOME/.config/git/attributes` is used instead. + +core.hooksPath:: + By default Git will look for your hooks in the + '$GIT_DIR/hooks' directory. Set this to different path, + e.g. '/etc/git/hooks', and Git will try to find your hooks in + that directory, e.g. '/etc/git/hooks/pre-receive' instead of + in '$GIT_DIR/hooks/pre-receive'. ++ +The path can be either absolute or relative. A relative path is +taken as relative to the directory where the hooks are run (see +the "DESCRIPTION" section of linkgit:githooks[5]). ++ +This configuration variable is useful in cases where you'd like to +centrally configure your Git hooks instead of configuring them on a +per-repository basis, or as a more flexible and centralized +alternative to having an `init.templateDir` where you've changed +default hooks. core.editor:: Commands such as `commit` and `tag` that lets you edit @@ -1106,15 +1138,19 @@ commit.status:: message. Defaults to true. commit.template:: - Specify a file to use as the template for new commit messages. - "`~/`" is expanded to the value of `$HOME` and "`~user/`" to the - specified user's home directory. + Specify the pathname of a file to use as the template for + new commit messages. + +commit.verbose:: + A boolean or int to specify the level of verbose with `git commit`. + See linkgit:git-commit[1]. credential.helper:: Specify an external helper to be called when a username or password credential is needed; the helper may consult external - storage to avoid prompting the user for the credentials. See - linkgit:gitcredentials[7] for details. + storage to avoid prompting the user for the credentials. Note + that multiple helpers may be defined. See linkgit:gitcredentials[7] + for details. credential.useHttpPath:: When acquiring credentials, consider the "path" component of an http @@ -1258,6 +1294,10 @@ format.outputDirectory:: Set a custom directory to store the resulting files instead of the current working directory. +format.useAutoBase:: + A boolean value which lets you enable the `--base=auto` option of + format-patch by default. + filter..clean:: The command which is used to convert the content of a worktree file to a blob upon checkin. See linkgit:gitattributes[5] for @@ -1334,7 +1374,7 @@ gc.worktreePruneExpire:: 'git worktree prune --expire 3.months.ago'. This config variable can be used to set a different grace period. The value "now" may be used to disable the grace - period and prune $GIT_DIR/worktrees immediately, or "never" + period and prune `$GIT_DIR/worktrees` immediately, or "never" may be used to suppress pruning. gc.reflogExpire:: @@ -1474,13 +1514,13 @@ grep.fallbackToNoIndex:: is executed outside of a git repository. Defaults to false. gpg.program:: - Use this custom program instead of "gpg" found on $PATH when + Use this custom program instead of "`gpg`" found on `$PATH` when making or verifying a PGP signature. The program must support the same command-line interface as GPG, namely, to verify a detached - signature, "gpg --verify $file - <$signature" is run, and the + signature, "`gpg --verify $file - <$signature`" is run, and the program is expected to signal a good signature by exiting with code 0, and to generate an ASCII-armored detached signature, the - standard input of "gpg -bsau $key" is fed with the contents to be + standard input of "`gpg -bsau $key`" is fed with the contents to be signed, and the program is expected to send the result to its standard output. @@ -1493,7 +1533,7 @@ gui.diffContext:: made by the linkgit:git-gui[1]. The default is "5". gui.displayUntracked:: - Determines if linkgit::git-gui[1] shows untracked files + Determines if linkgit:git-gui[1] shows untracked files in the file list. The default is "true". gui.encoding:: @@ -1654,12 +1694,19 @@ http.emptyAuth:: a username in the URL, as libcurl normally requires a username for authentication. +http.extraHeader:: + Pass an additional HTTP header when communicating with a server. If + more than one such entry exists, all of them are added as extra + headers. To allow overriding the settings inherited from the system + config, an empty value will reset the extra headers to the empty list. + http.cookieFile:: - File containing previously stored cookie lines which should be used + The pathname of a file containing previously stored cookie lines, + which should be used in the Git http session, if they match the server. The file format of the file to read cookies from should be plain HTTP headers or - the Netscape/Mozilla cookie file format (see linkgit:curl[1]). - NOTE that the file specified with http.cookieFile is only used as + the Netscape/Mozilla cookie file format (see `curl(1)`). + NOTE that the file specified with http.cookieFile is used only as input unless http.saveCookies is set. http.saveCookies:: @@ -1886,6 +1933,14 @@ interactive.singleKey:: setting is silently ignored if portable keystroke input is not available; requires the Perl module Term::ReadKey. +interactive.diffFilter:: + When an interactive command (such as `git add --patch`) shows + a colorized diff, git will pipe the diff through the shell + command defined by this configuration variable. The command may + mark up the diff further for human consumption, provided that it + retains a one-to-one correspondence with the lines in the + original diff. Defaults to disabled (no filtering). + log.abbrevCommit:: If true, makes linkgit:git-log[1], linkgit:git-show[1], and linkgit:git-whatchanged[1] assume `--abbrev-commit`. You may @@ -1901,7 +1956,10 @@ log.decorate:: command. If 'short' is specified, the ref name prefixes 'refs/heads/', 'refs/tags/' and 'refs/remotes/' will not be printed. If 'full' is specified, the full ref name (including prefix) will be printed. - This is the same as the log commands '--decorate' option. + If 'auto' is specified, then if the output is going to a terminal, + the ref names are shown as if 'short' were given, otherwise no ref + names are shown. This is the same as the '--decorate' option + of the `git log`. log.follow:: If `true`, `git log` will act as if the `--follow` option was used when @@ -2147,8 +2205,11 @@ pack.packSizeLimit:: The maximum size of a pack. This setting only affects packing to a file when repacking, i.e. the git:// protocol is unaffected. It can be overridden by the `--max-pack-size` - option of linkgit:git-repack[1]. The minimum size allowed is - limited to 1 MiB. The default is unlimited. + option of linkgit:git-repack[1]. Reaching this limit results + in the creation of multiple packfiles; which in turn prevents + bitmaps from being created. + The minimum size allowed is limited to 1 MiB. + The default is unlimited. Common unit suffixes of 'k', 'm', or 'g' are supported. @@ -2548,8 +2609,9 @@ repack.writeBitmaps:: objects to disk (e.g., when `git repack -a` is run). This index can speed up the "counting objects" phase of subsequent packs created for clones and fetches, at the cost of some disk - space and extra time spent on the initial repack. Defaults to - false. + space and extra time spent on the initial repack. This has + no effect if multiple packfiles are created. + Defaults to false. rerere.autoUpdate:: When set to true, `git-rerere` updates the index with the @@ -2729,6 +2791,17 @@ submodule..ignore:: "--ignore-submodules" option. The 'git submodule' commands are not affected by this setting. +submodule.fetchJobs:: + Specifies how many submodules are fetched/cloned at the same time. + A positive integer allows up to that number of submodules fetched + in parallel. A value of 0 will give some reasonable default. + If unset, it defaults to 1. + +tag.forceSignAnnotated:: + A boolean to specify whether annotated tags created should be GPG signed. + If `--annotate` is specified on the command line, it takes + precedence over this option. + tag.sort:: This variable controls the sort ordering of tags when displayed by linkgit:git-tag[1]. Without the "--sort=" option provided, the diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt index 6eaa45271c..d78cfc5a37 100644 --- a/Documentation/diff-config.txt +++ b/Documentation/diff-config.txt @@ -108,9 +108,13 @@ diff.renameLimit:: detection; equivalent to the 'git diff' option '-l'. diff.renames:: - Tells Git to detect renames. If set to any boolean value, it - will enable basic rename detection. If set to "copies" or - "copy", it will detect copies, as well. + Whether and how Git detects renames. If set to "false", + rename detection is disabled. If set to "true", basic rename + detection is enabled. If set to "copies" or "copy", Git will + detect copies, as well. Defaults to true. Note that this + affects only 'git diff' Porcelain like linkgit:git-diff[1] and + linkgit:git-log[1], and not lower level commands such as + linkgit:git-diff-files[1]. diff.suppressBlankEmpty:: A boolean to inhibit the standard behavior of printing a space @@ -166,6 +170,11 @@ diff.tool:: include::mergetools-diff.txt[] +diff.compactionHeuristic:: + Set this option to `true` to enable an experimental heuristic that + shifts the hunk boundary in an attempt to make the resulting + patch easier to read. + diff.algorithm:: Choose a diff algorithm. The variants are as follows: + diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 306b7e3604..d9ae681d8f 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -26,12 +26,12 @@ ifndef::git-format-patch[] ifdef::git-diff[] This is the default. endif::git-diff[] -endif::git-format-patch[] -s:: --no-patch:: Suppress diff output. Useful for commands like `git show` that show the patch by default, or to cancel the effect of `--patch`. +endif::git-format-patch[] -U:: --unified=:: @@ -63,6 +63,13 @@ ifndef::git-format-patch[] Synonym for `-p --raw`. endif::git-format-patch[] +--compaction-heuristic:: +--no-compaction-heuristic:: + These are to help debugging and tuning an experimental + heuristic (which is off by default) that shifts the hunk + boundary in an attempt to make the resulting patch easier + to read. + --minimal:: Spend extra time to make sure the smallest possible diff is produced. @@ -271,7 +278,7 @@ For example, `--word-diff-regex=.` will treat each character as a word and, correspondingly, show differences character by character. + The regex can also be set via a diff driver or configuration option, see -linkgit:gitattributes[1] or linkgit:git-config[1]. Giving it explicitly +linkgit:gitattributes[5] or linkgit:git-config[1]. Giving it explicitly overrides any diff driver or configuration setting. Diff drivers override configuration settings. @@ -286,8 +293,8 @@ endif::git-format-patch[] ifndef::git-format-patch[] --check:: - Warn if changes introduce whitespace errors. What are - considered whitespace errors is controlled by `core.whitespace` + Warn if changes introduce conflict markers or whitespace errors. + What are considered whitespace errors is controlled by `core.whitespace` configuration. By default, trailing whitespaces (including lines that solely consist of whitespaces) and a space character that is immediately followed by a tab character inside the diff --git a/Documentation/everyday.txto b/Documentation/everyday.txto index c5047d8f9b..ae555bd47e 100644 --- a/Documentation/everyday.txto +++ b/Documentation/everyday.txto @@ -1,7 +1,7 @@ Everyday Git With 20 Commands Or So =================================== -This document has been moved to linkgit:giteveryday[1]. +This document has been moved to linkgit:giteveryday[7]. Please let the owners of the referring site know so that they can update the link you clicked to get here. diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index d9ed6a1a4e..8ddb207409 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -13,7 +13,7 @@ SYNOPSIS [--apply] [--no-add] [--build-fake-ancestor=] [-R | --reverse] [--allow-binary-replacement | --binary] [--reject] [-z] [-p] [-C] [--inaccurate-eof] [--recount] [--cached] - [--ignore-space-change | --ignore-whitespace ] + [--ignore-space-change | --ignore-whitespace] [--whitespace=(nowarn|warn|fix|error|error-all)] [--exclude=] [--include=] [--directory=] [--verbose] [--unsafe-paths] [...] @@ -21,6 +21,8 @@ SYNOPSIS DESCRIPTION ----------- Reads the supplied diff output (i.e. "a patch") and applies it to files. +When running from a subdirectory in a repository, patched paths +outside the directory are ignored. With the `--index` option the patch is also applied to the index, and with the `--cached` option the patch is only applied to the index. Without these options, the command applies the patch only to files, diff --git a/Documentation/git-check-ignore.txt b/Documentation/git-check-ignore.txt index e94367a5ed..611754f10b 100644 --- a/Documentation/git-check-ignore.txt +++ b/Documentation/git-check-ignore.txt @@ -112,7 +112,7 @@ EXIT STATUS SEE ALSO -------- linkgit:gitignore[5] -linkgit:gitconfig[5] +linkgit:git-config[1] linkgit:git-ls-files[1] GIT diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 6154e57238..c104a594af 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -128,7 +128,7 @@ effect to your index in a row. --allow-empty-message:: By default, cherry-picking a commit with an empty message will fail. - This option overrides that behaviour, allowing commits with empty + This option overrides that behavior, allowing commits with empty messages to be cherry picked. --keep-redundant-commits:: diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index b7c467a001..1b15cd7b16 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -14,8 +14,8 @@ SYNOPSIS [-o ] [-b ] [-u ] [--reference ] [--dissociate] [--separate-git-dir ] [--depth ] [--[no-]single-branch] - [--recursive | --recurse-submodules] [--] - [] + [--recursive | --recurse-submodules] [--[no-]shallow-submodules] + [--jobs ] [--] [] DESCRIPTION ----------- @@ -191,7 +191,9 @@ objects from the source repository into a pack in the cloned repository. Create a 'shallow' clone with a history truncated to the specified number of commits. Implies `--single-branch` unless `--no-single-branch` is given to fetch the histories near the - tips of all branches. + tips of all branches. This implies `--shallow-submodules`. If + you want to have a shallow superproject clone, but full submodules, + also pass `--no-shallow-submodules`. --[no-]single-branch:: Clone only the history leading to the tip of a single branch, @@ -212,6 +214,9 @@ objects from the source repository into a pack in the cloned repository. repository does not have a worktree/checkout (i.e. if any of `--no-checkout`/`-n`, `--bare`, or `--mirror` is given) +--[no-]shallow-submodules:: + All submodules which are cloned will be shallow with a depth of 1. + --separate-git-dir=:: Instead of placing the cloned repository where it is supposed to be, place the cloned repository at the specified directory, @@ -219,6 +224,10 @@ objects from the source repository into a pack in the cloned repository. The result is Git repository can be separated from working tree. +-j :: +--jobs :: + The number of submodules fetched at the same time. + Defaults to the `submodule.fetchJobs` option. :: The (possibly remote) repository to clone from. See the diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt index 48c33d7ed7..cb69faab68 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.txt @@ -61,8 +61,8 @@ OPTIONS stuck to the option without a space. --no-gpg-sign:: - Countermand `commit.gpgSign` configuration variable that is - set to force each and every commit to be signed. + Do not GPG-sign commit, to countermand a `--gpg-sign` option + given earlier on the command line. Commit Information diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 9ec6b3cc17..d474226eb7 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -290,7 +290,8 @@ configuration variable documented in linkgit:git-config[1]. what changes the commit has. Note that this diff output doesn't have its lines prefixed with '#'. This diff will not be a part - of the commit message. + of the commit message. See the `commit.verbose` configuration + variable in linkgit:git-config[1]. + If specified twice, show in addition the unified diff between what would be committed and the worktree files, i.e. the unstaged diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 153b2d89b5..6843114fc0 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -58,13 +58,13 @@ that location (you can say '--local' but that is the default). This command will fail with non-zero status upon error. Some exit codes are: -. The config file is invalid (ret=3), -. can not write to the config file (ret=4), -. no section or name was provided (ret=2), -. the section or key is invalid (ret=1), -. you try to unset an option which does not exist (ret=5), -. you try to unset/set an option for which multiple lines match (ret=5), or -. you try to use an invalid regexp (ret=6). +- The section or key is invalid (ret=1), +- no section or name was provided (ret=2), +- the config file is invalid (ret=3), +- the config file cannot be written (ret=4), +- you try to unset an option which does not exist (ret=5), +- you try to unset/set an option for which multiple lines match (ret=5), or +- you try to use an invalid regexp (ret=6). On success, the command returns the exit code 0. @@ -86,8 +86,7 @@ OPTIONS found and the last value if multiple key values were found. --get-all:: - Like get, but does not fail if the number of values for the key - is not exactly one. + Like get, but returns all values for a multi-valued key. --get-regexp:: Like --get-all, but interprets the name as a regular expression and @@ -102,7 +101,7 @@ OPTIONS given URL is returned (if no such key exists, the value for section.key is used as a fallback). When given just the section as name, do so for all the keys in the section and - list them. + list them. Returns error code 1 if no value is found. --global:: For writing options: write to global `~/.gitconfig` file diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 8680f45f8d..239623cc24 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -104,6 +104,10 @@ be in a separate packet, and the list must end with a flush packet. The remote heads to update from. This is relative to $GIT_DIR (e.g. "HEAD", "refs/heads/master"). When unspecified, update from all heads the remote side has. ++ +If the remote has enabled the options `uploadpack.allowTipSHA1InWant` or +`uploadpack.allowReachableSHA1InWant`, they may alternatively be 40-hex +sha1s present on the remote. SEE ALSO -------- diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index 73fd9e8230..003731f6a9 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -205,7 +205,7 @@ to other tags will be rewritten to point to the underlying commit. Remap to ancestor ~~~~~~~~~~~~~~~~~ -By using linkgit:rev-list[1] arguments, e.g., path limiters, you can limit the +By using linkgit:git-rev-list[1] arguments, e.g., path limiters, you can limit the set of revisions which get rewritten. However, positive refs on the command line are distinguished: we don't let them be excluded by such limiters. For this purpose, they are instead rewritten to point at the nearest ancestor that diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index 012e8f9a08..d9d406dcfb 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -76,7 +76,7 @@ OPTIONS specified commit (HEAD if not specified). --contains []:: - Only list tags which contain the specified commit (HEAD if not + Only list refs which contain the specified commit (HEAD if not specified). FIELD NAMES @@ -179,7 +179,7 @@ returns an empty string instead. As a special case for the date-type fields, you may specify a format for the date by adding `:` followed by date format name (see the -values the `--date` option to linkgit::git-rev-list[1] takes). +values the `--date` option to linkgit:git-rev-list[1] takes). EXAMPLES diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 6821441d7d..bdeecd59e0 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -265,6 +265,11 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`. Output an all-zero hash in each patch's From header instead of the hash of the commit. +--base=:: + Record the base tree information to identify the state the + patch series applies to. See the BASE TREE INFORMATION section + below for details. + --root:: Treat the revision argument as a , even if it is just a single commit (that would normally be treated as a @@ -520,6 +525,61 @@ This should help you to submit patches inline using KMail. 5. Back in the compose window: add whatever other text you wish to the message, complete the addressing and subject fields, and press send. +BASE TREE INFORMATION +--------------------- + +The base tree information block is used for maintainers or third party +testers to know the exact state the patch series applies to. It consists +of the 'base commit', which is a well-known commit that is part of the +stable part of the project history everybody else works off of, and zero +or more 'prerequisite patches', which are well-known patches in flight +that is not yet part of the 'base commit' that need to be applied on top +of 'base commit' in topological order before the patches can be applied. + +The 'base commit' is shown as "base-commit: " followed by the 40-hex of +the commit object name. A 'prerequisite patch' is shown as +"prerequisite-patch-id: " followed by the 40-hex 'patch id', which can +be obtained by passing the patch through the `git patch-id --stable` +command. + +Imagine that on top of the public commit P, you applied well-known +patches X, Y and Z from somebody else, and then built your three-patch +series A, B, C, the history would be like: + +................................................ +---P---X---Y---Z---A---B---C +................................................ + +With `git format-patch --base=P -3 C` (or variants thereof, e.g. with +`--cover-letter` of using `Z..C` instead of `-3 C` to specify the +range), the base tree information block is shown at the end of the +first message the command outputs (either the first patch, or the +cover letter), like this: + +------------ +base-commit: P +prerequisite-patch-id: X +prerequisite-patch-id: Y +prerequisite-patch-id: Z +------------ + +For non-linear topology, such as + +................................................ +---P---X---A---M---C + \ / + Y---Z---B +................................................ + +You can also use `git format-patch --base=P -3 C` to generate patches +for A, B and C, and the identifiers for P, X, Y, Z are appended at the +end of the first message. + +If set `--base=auto` in cmdline, it will track base commit automatically, +the base commit will be the merge base of tip commit of the remote-tracking +branch and revision-range specified in cmdline. +For a local branch, you need to track a remote branch by `git branch +--set-upstream-to` before using this option. EXAMPLES -------- diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt index 8174d27efd..6364e5dc45 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.txt @@ -130,7 +130,12 @@ The template directory will be one of the following (in order): - the default template directory: `/usr/share/git-core/templates`. The default template directory includes some directory structure, suggested -"exclude patterns" (see linkgit:gitignore[5]), and sample hook files (see linkgit:githooks[5]). +"exclude patterns" (see linkgit:gitignore[5]), and sample hook files. + +The sample hooks are all disabled by default, To enable one of the +sample hooks rename it by removing its `.sample` suffix. + +See linkgit:githooks[5] for more general info on hook execution. EXAMPLES -------- diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 03f958029a..dec379b3e2 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -29,12 +29,14 @@ OPTIONS (works only for a single file). --no-decorate:: ---decorate[=short|full|no]:: +--decorate[=short|full|auto|no]:: Print out the ref names of any commits that are shown. If 'short' is specified, the ref name prefixes 'refs/heads/', 'refs/tags/' and 'refs/remotes/' will not be printed. If 'full' is specified, the - full ref name (including prefix) will be printed. The default option - is 'short'. + full ref name (including prefix) will be printed. If 'auto' is + specified, then if the output is going to a terminal, the ref names + are shown as if 'short' were given, otherwise no ref names are + shown. The default option is 'short'. --source:: Print out the ref name given on the command line by which each diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt index 0947084140..3bbc731f67 100644 --- a/Documentation/git-mailinfo.txt +++ b/Documentation/git-mailinfo.txt @@ -85,7 +85,7 @@ with comments and suggestions on the message you are responding to, and to conclude it with a patch submission, separating the discussion and the beginning of the proposed commit log message with a scissors line. + -This can enabled by default with the configuration option mailinfo.scissors. +This can be enabled by default with the configuration option mailinfo.scissors. --no-scissors:: Ignore scissors lines. Useful for overriding mailinfo.scissors settings. diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 07f7295ec8..b758d5556c 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -11,6 +11,7 @@ SYNOPSIS [verse] 'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] [-s ] [-X ] [-S[]] + [--[no-]allow-unrelated-histories] [--[no-]rerere-autoupdate] [-m ] [...] 'git merge' HEAD ... 'git merge' --abort diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index 8de349968a..9c4fd6812c 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -402,4 +402,4 @@ on the `notes.rewrite.` and `notes.rewriteRef` settings. GIT --- -Part of the linkgit:git[7] suite +Part of the linkgit:git[1] suite diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt index 35e3170918..88ba42b455 100644 --- a/Documentation/git-p4.txt +++ b/Documentation/git-p4.txt @@ -551,6 +551,17 @@ git-p4.keepEmptyCommits:: A changelist that contains only excluded files will be imported as an empty commit if this boolean option is set to true. +git-p4.mapUser:: + Map a P4 user to a name and email address in Git. Use a string + with the following format to create a mapping: ++ +------------- +git config --add git-p4.mapUser "p4user = First Last " +------------- ++ +A mapping will override any user information from P4. Mappings for +multiple P4 user can be defined. + Submit variables ~~~~~~~~~~~~~~~~ git-p4.detectRenames:: diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index bbea5294ca..19cdcd0341 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -110,7 +110,8 @@ base-name:: --max-pack-size=:: Maximum size of each output pack file. The size can be suffixed with "k", "m", or "g". The minimum size allowed is limited to 1 MiB. - If specified, multiple packfiles may be created. + If specified, multiple packfiles may be created, which also + prevents the creation of a bitmap index. The default is unlimited, unless the config variable `pack.packSizeLimit` is set. diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index a62a2a615d..d033b258e5 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -128,6 +128,15 @@ unless you have read linkgit:git-rebase[1] carefully. --no-rebase:: Override earlier --rebase. +--autostash:: +--no-autostash:: + Before starting rebase, stash local modifications away (see + linkgit:git-stash[1]) if needed, and apply the stash when + done. `--no-autostash` is useful to override the `rebase.autoStash` + configuration variable (see linkgit:git-config[1]). ++ +This option is only valid when "--rebase" is used. + Options related to fetching ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 6ed610a031..0387b40e0a 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -391,9 +391,6 @@ idea unless you know what you are doing (see BUGS below). final history. will be interpreted as one or more shell commands. + -This option can only be used with the `--interactive` option -(see INTERACTIVE MODE below). -+ You may execute several commands by either using one instance of `--exec` with several commands: + @@ -406,6 +403,9 @@ or by giving more than one `--exec`: If `--autosquash` is used, "exec" lines will not be appended for the intermediate commits, and will only appear at the end of each squash/fixup series. ++ +This uses the `--interactive` machinery internally, but it can be run +without an explicit `--interactive`. --root:: Rebase all commits reachable from , instead of diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index af230d0647..b9c02ce481 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -106,7 +106,8 @@ other objects in that pack they already have locally. --max-pack-size=:: Maximum size of each output pack file. The size can be suffixed with "k", "m", or "g". The minimum size allowed is limited to 1 MiB. - If specified, multiple packfiles may be created. + If specified, multiple packfiles may be created, which also + prevents the creation of a bitmap index. The default is unlimited, unless the config variable `pack.packSizeLimit` is set. @@ -115,7 +116,8 @@ other objects in that pack they already have locally. Write a reachability bitmap index as part of the repack. This only makes sense when used with `-a` or `-A`, as the bitmaps must be able to refer to all reachable objects. This option - overrides the setting of `pack.writeBitmaps`. + overrides the setting of `repack.writeBitmaps`. This option + has no effect if multiple packfiles are created. --pack-kept-objects:: Include objects in `.keep` files when repacking. Note that we @@ -123,7 +125,7 @@ other objects in that pack they already have locally. This means that we may duplicate objects, but this makes the option safe to use when there are concurrent pushes or fetches. This option is generally only useful if you are writing bitmaps - with `-b` or `pack.writeBitmaps`, as it ensures that the + with `-b` or `repack.writeBitmaps`, as it ensures that the bitmapped packfile has the necessary objects. Configuration diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 771a7b5b09..a88d18604a 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -450,6 +450,19 @@ edit ~/.gitconfig to specify your account settings: smtpUser = yourname@gmail.com smtpServerPort = 587 +If you have multifactor authentication setup on your gmail account, you will +need to generate an app-specific password for use with 'git send-email'. Visit +https://security.google.com/settings/security/apppasswords to setup an +app-specific password. Once setup, you can store it with the credentials +helper: + + $ git credential fill + protocol=smtp + host=smtp.gmail.com + username=youname@gmail.com + password=app-password + + Once your commits are ready to be sent to the mailing list, run the following commands: diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index 1572f058f5..9226c4380c 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -13,10 +13,10 @@ SYNOPSIS [--reference ] [--depth ] [--] [] 'git submodule' [--quiet] status [--cached] [--recursive] [--] [...] 'git submodule' [--quiet] init [--] [...] -'git submodule' [--quiet] deinit [-f|--force] [--] ... +'git submodule' [--quiet] deinit [-f|--force] (--all|[--] ...) 'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase|--merge] [--reference ] - [--depth ] [--recursive] [--] [...] + [--depth ] [--recursive] [--jobs ] [--] [...] 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) ] [commit] [--] [...] 'git submodule' [--quiet] foreach [--recursive] @@ -140,12 +140,15 @@ deinit:: tree. Further calls to `git submodule update`, `git submodule foreach` and `git submodule sync` will skip any unregistered submodules until they are initialized again, so use this command if you don't want to - have a local checkout of the submodule in your work tree anymore. If + have a local checkout of the submodule in your working tree anymore. If you really want to remove a submodule from the repository and commit that use linkgit:git-rm[1] instead. + -If `--force` is specified, the submodule's work tree will be removed even if -it contains local modifications. +When the command is run without pathspec, it errors out, +instead of deinit-ing everything, to prevent mistakes. ++ +If `--force` is specified, the submodule's working tree will +be removed even if it contains local modifications. update:: + @@ -247,6 +250,10 @@ OPTIONS --quiet:: Only print error messages. +--all:: + This option is only valid for the deinit command. Unregister all + submodules in the working tree. + -b:: --branch:: Branch of repository to add as submodule. @@ -257,8 +264,8 @@ OPTIONS --force:: This option is only valid for add, deinit and update commands. When running add, allow adding an otherwise ignored submodule path. - When running deinit the submodule work trees will be removed even if - they contain local changes. + When running deinit the submodule working trees will be removed even + if they contain local changes. When running update (only effective with the checkout procedure), throw away local changes in submodules when switching to a different commit; and always run a checkout operation in the @@ -377,6 +384,11 @@ for linkgit:git-clone[1]'s `--reference` and `--shared` options carefully. clone with a history truncated to the specified number of revisions. See linkgit:git-clone[1] +-j :: +--jobs :: + This option is only valid for the update command. + Clone new submodules in parallel with as many jobs. + Defaults to the `submodule.fetchJobs` option. ...:: Paths to submodule(s). When specified this will restrict the command diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 62c76c1c89..c62234538b 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -9,7 +9,7 @@ git-worktree - Manage multiple working trees SYNOPSIS -------- [verse] -'git worktree add' [-f] [--detach] [-b ] [] +'git worktree add' [-f] [--detach] [--checkout] [-b ] [] 'git worktree prune' [-n] [-v] [--expire ] 'git worktree list' [--porcelain] @@ -87,6 +87,12 @@ OPTIONS With `add`, detach HEAD in the new working tree. See "DETACHED HEAD" in linkgit:git-checkout[1]. +--[no-]checkout:: + By default, `add` checks out ``, however, `--no-checkout` can + be used to suppress checkout in order to make customizations, + such as configuring sparse-checkout. See "Sparse checkout" + in linkgit:git-read-tree[1]. + -n:: --dry-run:: With `prune`, do not remove anything; just report what it would diff --git a/Documentation/git.txt b/Documentation/git.txt index adc940bf75..5490d3c601 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,18 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.8.0/git.html[documentation for release 2.8] +* link:v2.9.0/git.html[documentation for release 2.9] * release notes for + link:RelNotes/2.9.0.txt[2.9]. + +* link:v2.8.4/git.html[documentation for release 2.8.4] + +* release notes for + link:RelNotes/2.8.4.txt[2.8.4], + link:RelNotes/2.8.3.txt[2.8.3], + link:RelNotes/2.8.2.txt[2.8.2], + link:RelNotes/2.8.1.txt[2.8.1], link:RelNotes/2.8.0.txt[2.8]. * link:v2.7.3/git.html[documentation for release 2.7.3] diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.txt index 1c75be0803..f3a75d1ce1 100644 --- a/Documentation/gitcredentials.txt +++ b/Documentation/gitcredentials.txt @@ -106,6 +106,11 @@ variable, each helper will be tried in turn, and may provide a username, password, or nothing. Once Git has acquired both a username and a password, no more helpers will be tried. +If `credential.helper` is configured to the empty string, this resets +the helper list to empty (so you may override a helper set by a +lower-priority config file by configuring the empty-string helper, +followed by whatever set of helpers you would like). + CREDENTIAL CONTEXTS ------------------- diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index a2f59b194c..d82e912e55 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -7,24 +7,35 @@ githooks - Hooks used by Git SYNOPSIS -------- -$GIT_DIR/hooks/* +$GIT_DIR/hooks/* (or \`git config core.hooksPath`/*) DESCRIPTION ----------- -Hooks are little scripts you can place in `$GIT_DIR/hooks` -directory to trigger action at certain points. When -'git init' is run, a handful of example hooks are copied into the -`hooks` directory of the new repository, but by default they are -all disabled. To enable a hook, rename it by removing its `.sample` -suffix. +Hooks are programs you can place in a hooks directory to trigger +actions at certain points in git's execution. Hooks that don't have +the executable bit set are ignored. -NOTE: It is also a requirement for a given hook to be executable. -However - in a freshly initialized repository - the `.sample` files are -executable by default. +By default the hooks directory is `$GIT_DIR/hooks`, but that can be +changed via the `core.hooksPath` configuration variable (see +linkgit:git-config[1]). -This document describes the currently defined hooks. +Before Git invokes a hook, it changes its working directory to either +the root of the working tree in a non-bare repository, or to the +$GIT_DIR in a bare repository. + +Hooks can get their arguments via the environment, command-line +arguments, and stdin. See the documentation for each hook below for +details. + +'git init' may copy hooks to the new repository, depending on its +configuration. See the "TEMPLATE DIRECTORY" section in +linkgit:git-init[1] for details. When the rest of this document refers +to "default hooks" it's talking about the default template shipped +with Git. + +The currently supported hooks are described below. HOOKS ----- @@ -32,15 +43,15 @@ HOOKS applypatch-msg ~~~~~~~~~~~~~~ -This hook is invoked by 'git am' script. It takes a single +This hook is invoked by 'git am'. It takes a single parameter, the name of the file that holds the proposed commit -log message. Exiting with non-zero status causes -'git am' to abort before applying the patch. +log message. Exiting with a non-zero status causes 'git am' to abort +before applying the patch. The hook is allowed to edit the message file in place, and can be used to normalize the message into some project standard -format (if the project has one). It can also be used to refuse -the commit after inspecting the message file. +format. It can also be used to refuse the commit after inspecting +the message file. The default 'applypatch-msg' hook, when enabled, runs the 'commit-msg' hook, if the latter is enabled. @@ -73,10 +84,10 @@ pre-commit ~~~~~~~~~~ This hook is invoked by 'git commit', and can be bypassed -with `--no-verify` option. It takes no parameter, and is +with the `--no-verify` option. It takes no parameters, and is invoked before obtaining the proposed commit log message and -making a commit. Exiting with non-zero status from this script -causes the 'git commit' to abort. +making a commit. Exiting with a non-zero status from this script +causes the 'git commit' command to abort before creating a commit. The default 'pre-commit' hook, when enabled, catches introduction of lines with trailing whitespaces and aborts the commit when @@ -115,15 +126,15 @@ commit-msg ~~~~~~~~~~ This hook is invoked by 'git commit', and can be bypassed -with `--no-verify` option. It takes a single parameter, the +with the `--no-verify` option. It takes a single parameter, the name of the file that holds the proposed commit log message. -Exiting with non-zero status causes the 'git commit' to +Exiting with a non-zero status causes the 'git commit' to abort. -The hook is allowed to edit the message file in place, and can -be used to normalize the message into some project standard -format (if the project has one). It can also be used to refuse -the commit after inspecting the message file. +The hook is allowed to edit the message file in place, and can be used +to normalize the message into some project standard format. It +can also be used to refuse the commit after inspecting the message +file. The default 'commit-msg' hook, when enabled, detects duplicate "Signed-off-by" lines, and aborts the commit if one is found. @@ -131,8 +142,8 @@ The default 'commit-msg' hook, when enabled, detects duplicate post-commit ~~~~~~~~~~~ -This hook is invoked by 'git commit'. It takes no -parameter, and is invoked after a commit is made. +This hook is invoked by 'git commit'. It takes no parameters, and is +invoked after a commit is made. This hook is meant primarily for notification, and cannot affect the outcome of 'git commit'. @@ -267,9 +278,11 @@ does not know the entire set of branches, so it would end up firing one e-mail per ref when used naively, though. The <> hook is more suited to that. -Another use suggested on the mailing list is to use this hook to -implement access control which is finer grained than the one -based on filesystem group. +In an environment that restricts the users' access only to git +commands over the wire, this hook can be used to implement access +control without relying on filesystem ownership and group +membership. See linkgit:git-shell[1] for how you might use the login +shell to restrict the user's access to only git commands. Both standard output and standard error output are forwarded to 'git send-pack' on the other end, so you can simply `echo` messages diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index cafc284359..8ad29e61a9 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -145,7 +145,7 @@ current branch integrates with) obviously do not work, as there is no A fast-forward is a special type of <> where you have a <> and you are "merging" another <>'s changes that happen to be a descendant of what - you have. In such these cases, you do not make a new <> + you have. In such a case, you do not make a new <> <> but instead just update to his revision. This will happen frequently on a <> of a remote diff --git a/Documentation/lint-gitlink.perl b/Documentation/lint-gitlink.perl new file mode 100755 index 0000000000..476cc30b83 --- /dev/null +++ b/Documentation/lint-gitlink.perl @@ -0,0 +1,71 @@ +#!/usr/bin/perl + +use File::Find; +use Getopt::Long; + +my $basedir = "."; +GetOptions("basedir=s" => \$basedir) + or die("Cannot parse command line arguments\n"); + +my $found_errors = 0; + +sub report { + my ($where, $what, $error) = @_; + print "$where: $error: $what\n"; + $found_errors = 1; +} + +sub grab_section { + my ($page) = @_; + open my $fh, "<", "$basedir/$page.txt"; + my $firstline = <$fh>; + chomp $firstline; + close $fh; + my ($section) = ($firstline =~ /.*\((\d)\)$/); + return $section; +} + +sub lint { + my ($file) = @_; + open my $fh, "<", $file + or return; + while (<$fh>) { + my $where = "$file:$."; + while (s/linkgit:((.*?)\[(\d)\])//) { + my ($target, $page, $section) = ($1, $2, $3); + + # De-AsciiDoc + $page =~ s/{litdd}/--/g; + + if ($page !~ /^git/) { + report($where, $target, "nongit link"); + next; + } + if (! -f "$basedir/$page.txt") { + report($where, $target, "no such source"); + next; + } + $real_section = grab_section($page); + if ($real_section != $section) { + report($where, $target, + "wrong section (should be $real_section)"); + next; + } + } + } + close $fh; +} + +sub lint_it { + lint($File::Find::name) if -f && /\.txt$/; +} + +if (!@ARGV) { + find({ wanted => \&lint_it, no_chdir => 1 }, $basedir); +} else { + for (@ARGV) { + lint($_); + } +} + +exit $found_errors; diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index f08e9b80c5..5b4a62e936 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -89,8 +89,11 @@ option can be used to override --squash. --verify-signatures:: --no-verify-signatures:: - Verify that the commits being merged have good and trusted GPG signatures - and abort the merge in case they do not. + Verify that the tip commit of the side branch being merged is + signed with a valid key, i.e. a key that has a valid uid: in the + default trust model, this means the signing key has been signed by + a trusted key. If the tip commit of the side branch is not signed + with a valid key, the merge is aborted. --summary:: --no-summary:: @@ -114,3 +117,11 @@ ifndef::git-pull[] reporting. endif::git-pull[] + +--allow-unrelated-histories:: + By default, `git merge` command refuses to merge histories + that do not share a common ancestor. This option can be + used to override this safety when merging histories of two + projects that started their lives independently. As that is + a very rare occasion, no configuration variable to enable + this by default exists and will not be added. diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index 671cebd95c..29b19b992f 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -143,8 +143,8 @@ ifndef::git-rev-list[] - '%N': commit notes endif::git-rev-list[] - '%GG': raw verification message from GPG for a signed commit -- '%G?': show "G" for a Good signature, "B" for a Bad signature, "U" for a good, - untrusted signature and "N" for no signature +- '%G?': show "G" for a good (valid) signature, "B" for a bad signature, + "U" for a good signature with unknown validity and "N" for no signature - '%GS': show the name of the signer for a signed commit - '%GK': show the key used to sign a signed commit - '%gD': reflog selector, e.g., `refs/stash@{1}` diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt index 54b88b6dca..6c67182728 100644 --- a/Documentation/pretty-options.txt +++ b/Documentation/pretty-options.txt @@ -42,6 +42,20 @@ people using 80-column terminals. verbatim; this means that invalid sequences in the original commit may be copied to the output. +--expand-tabs=:: +--expand-tabs:: +--no-expand-tabs:: + Perform a tab expansion (replace each tab with enough spaces + to fill to the next display column that is multiple of '') + in the log message before showing it in the output. + `--expand-tabs` is a short-hand for `--expand-tabs=8`, and + `--no-expand-tabs` is a short-hand for `--expand-tabs=0`, + which disables tab expansion. ++ +By default, tabs are expanded in pretty formats that indent the log +message by 4 spaces (i.e. 'medium', which is the default, 'full', +and 'fuller'). + ifndef::git-rev-list[] --notes[=]:: Show the notes (see linkgit:git-notes[1]) that annotate the diff --git a/Documentation/technical/api-config.txt b/Documentation/technical/api-config.txt index 0d8b99b368..20741f345e 100644 --- a/Documentation/technical/api-config.txt +++ b/Documentation/technical/api-config.txt @@ -63,13 +63,6 @@ parse for configuration, rather than looking in the usual files. Regular Specify whether include directives should be followed in parsed files. Regular `git_config` defaults to `1`. -There is a special version of `git_config` called `git_config_early`. -This version takes an additional parameter to specify the repository -config, instead of having it looked up via `git_path`. This is useful -early in a Git program before the repository has been found. Unless -you're working with early setup code, you probably don't want to use -this. - Reading Specific Files ---------------------- diff --git a/Documentation/technical/api-credentials.txt b/Documentation/technical/api-credentials.txt index e44426dd04..75368f26ca 100644 --- a/Documentation/technical/api-credentials.txt +++ b/Documentation/technical/api-credentials.txt @@ -243,7 +243,7 @@ appended to its command line, which is one of: The details of the credential will be provided on the helper's stdin stream. The exact format is the same as the input/output format of the `git credential` plumbing command (see the section `INPUT/OUTPUT -FORMAT` in linkgit:git-credential[7] for a detailed specification). +FORMAT` in linkgit:git-credential[1] for a detailed specification). For a `get` operation, the helper should produce a list of attributes on stdout in the same format. A helper is free to produce a subset, or @@ -268,4 +268,4 @@ See also linkgit:gitcredentials[7] -linkgit:git-config[5] (See configuration variables `credential.*`) +linkgit:git-config[1] (See configuration variables `credential.*`) diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt index 5f0757dcc9..27bd701c0d 100644 --- a/Documentation/technical/api-parse-options.txt +++ b/Documentation/technical/api-parse-options.txt @@ -144,8 +144,12 @@ There are some macros to easily define options: `OPT_COUNTUP(short, long, &int_var, description)`:: Introduce a count-up option. - `int_var` is incremented on each use of `--option`, and - reset to zero with `--no-option`. + Each use of `--option` increments `int_var`, starting from zero + (even if initially negative), and `--no-option` resets it to + zero. To determine if `--option` or `--no-option` was encountered at + all, initialize `int_var` to a negative value, and if it is still + negative after parse_options(), then neither `--option` nor + `--no-option` was seen. `OPT_BIT(short, long, &int_var, description, mask)`:: Introduce a boolean option. @@ -231,6 +235,13 @@ There are some macros to easily define options: pass the command-line option, which can be specified multiple times, to another command. +`OPT_CMDMODE(short, long, &int_var, description, enum_val)`:: + Define an "operation mode" option, only one of which in the same + group of "operating mode" options that share the same `int_var` + can be given by the user. `enum_val` is set to `int_var` when the + option is used, but an error is reported if other "operating mode" + option has already set its value to the same `int_var`. + The last element of the array must be `OPT_END()`. diff --git a/Documentation/technical/api-trace.txt b/Documentation/technical/api-trace.txt index 097a651d96..fadb5979c4 100644 --- a/Documentation/technical/api-trace.txt +++ b/Documentation/technical/api-trace.txt @@ -28,7 +28,7 @@ static struct trace_key trace_foo = TRACE_KEY_INIT(FOO); static void trace_print_foo(const char *message) { - trace_print_key(&trace_foo, message); + trace_printf_key(&trace_foo, "%s", message); } ------------ + @@ -95,3 +95,46 @@ for (;;) { } trace_performance(t, "frotz"); ------------ + +Bugs & Caveats +-------------- + +GIT_TRACE_* environment variables can be used to tell Git to show +trace output to its standard error stream. Git can often spawn a pager +internally to run its subcommand and send its standard output and +standard error to it. + +Because GIT_TRACE_PERFORMANCE trace is generated only at the very end +of the program with atexit(), which happens after the pager exits, it +would not work well if you send its log to the standard error output +and let Git spawn the pager at the same time. + +As a work around, you can for example use '--no-pager', or set +GIT_TRACE_PERFORMANCE to another file descriptor which is redirected +to stderr, or set GIT_TRACE_PERFORMANCE to a file specified by its +absolute path. + +For example instead of the following command which by default may not +print any performance information: + +------------ +GIT_TRACE_PERFORMANCE=2 git log -1 +------------ + +you may want to use: + +------------ +GIT_TRACE_PERFORMANCE=2 git --no-pager log -1 +------------ + +or: + +------------ +GIT_TRACE_PERFORMANCE=3 3>&2 git log -1 +------------ + +or: + +------------ +GIT_TRACE_PERFORMANCE=/path/to/log/file git log -1 +------------ diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt index c6977bbc5a..8b36343802 100644 --- a/Documentation/technical/pack-protocol.txt +++ b/Documentation/technical/pack-protocol.txt @@ -526,7 +526,7 @@ Push Certificate A push certificate begins with a set of header lines. After the header and an empty line, the protocol commands follow, one per -line. Note that the the trailing LF in push-cert PKT-LINEs is _not_ +line. Note that the trailing LF in push-cert PKT-LINEs is _not_ optional; it must be present. Currently, the following header fields are defined: diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 4e9450b3ae..ae4f560385 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.8.0 +DEF_VER=v2.9.0 LF=' ' diff --git a/Makefile b/Makefile index 2742a6977c..de5a030256 100644 --- a/Makefile +++ b/Makefile @@ -355,9 +355,6 @@ all:: # # Define HAVE_CLOCK_MONOTONIC if your platform has CLOCK_MONOTONIC in librt. # -# Define NO_HMAC_CTX_CLEANUP if your OpenSSL is version 0.9.6b or earlier to -# cleanup the HMAC context with the older HMAC_cleanup function. -# # Define USE_PARENS_AROUND_GETTEXT_N to "yes" if your compiler happily # compiles the following initialization: # @@ -378,13 +375,7 @@ GIT-VERSION-FILE: FORCE # CFLAGS and LDFLAGS are for the users to override from the command line. CFLAGS = -g -O2 -Wall -LDFLAGS = -ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS) -ALL_LDFLAGS = $(LDFLAGS) -STRIP ?= strip - -ifdef DEVELOPER -CFLAGS += -Werror \ +DEVELOPER_CFLAGS = -Werror \ -Wdeclaration-after-statement \ -Wno-format-zero-length \ -Wold-style-definition \ @@ -393,7 +384,10 @@ CFLAGS += -Werror \ -Wstrict-prototypes \ -Wunused \ -Wvla -endif +LDFLAGS = +ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS) +ALL_LDFLAGS = $(LDFLAGS) +STRIP ?= strip # Create as necessary, replace existing, make ranlib unneeded. ARFLAGS = rcs @@ -443,7 +437,6 @@ DIFF = diff TAR = tar FIND = find INSTALL = install -RPMBUILD = rpmbuild TCL_PATH = tclsh TCLTK_PATH = wish XGETTEXT = xgettext @@ -624,7 +617,7 @@ TEST_PROGRAMS_NEED_X += test-svn-fe TEST_PROGRAMS_NEED_X += test-urlmatch-normalization TEST_PROGRAMS_NEED_X += test-wildmatch -TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X)) +TEST_PROGRAMS = $(patsubst %,t/helper/%$X,$(TEST_PROGRAMS_NEED_X)) # List built-in command $C whose implementation cmd_$C() is not in # builtin/$C.o but is linked in as part of some other command. @@ -955,6 +948,10 @@ include config.mak.uname -include config.mak.autogen -include config.mak +ifdef DEVELOPER +CFLAGS += $(DEVELOPER_CFLAGS) +endif + ifndef sysconfdir ifeq ($(prefix),/usr) sysconfdir = /etc @@ -1138,9 +1135,6 @@ ifndef NO_OPENSSL ifdef NEEDS_CRYPTO_WITH_SSL OPENSSL_LIBSSL += -lcrypto endif - ifdef NO_HMAC_CTX_CLEANUP - BASIC_CFLAGS += -DNO_HMAC_CTX_CLEANUP - endif else BASIC_CFLAGS += -DNO_OPENSSL BLK_SHA1 = 1 @@ -1904,7 +1898,7 @@ VCSSVN_OBJS += vcs-svn/fast_export.o VCSSVN_OBJS += vcs-svn/svndiff.o VCSSVN_OBJS += vcs-svn/svndump.o -TEST_OBJS := $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS)) +TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \ $(XDIFF_OBJS) \ $(VCSSVN_OBJS) \ @@ -2069,7 +2063,7 @@ XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \ --keyword=gettextln --keyword=eval_gettextln XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H) -LOCALIZED_SH = $(SCRIPT_SH) +LOCALIZED_SH = $(SCRIPT_SH) git-parse-remote.sh LOCALIZED_PERL = $(SCRIPT_PERL) ifdef XGETTEXT_INCLUDE_TESTS @@ -2211,7 +2205,7 @@ bin-wrappers/%: wrap-for-bin.sh @mkdir -p bin-wrappers $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e 's|@@BUILD_DIR@@|$(shell pwd)|' \ - -e 's|@@PROG@@|$(@F)|' < $< > $@ && \ + -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%,$(@F))|' < $< > $@ && \ chmod +x $@ # GNU make supports exporting all variables by "export" without parameters. @@ -2231,25 +2225,25 @@ perf: all .PHONY: test perf -test-ctype$X: ctype.o +t/helper/test-ctype$X: ctype.o -test-date$X: date.o ctype.o +t/helper/test-date$X: date.o ctype.o -test-delta$X: diff-delta.o patch-delta.o +t/helper/test-delta$X: diff-delta.o patch-delta.o -test-line-buffer$X: vcs-svn/lib.a +t/helper/test-line-buffer$X: vcs-svn/lib.a -test-parse-options$X: parse-options.o parse-options-cb.o +t/helper/test-parse-options$X: parse-options.o parse-options-cb.o -test-svn-fe$X: vcs-svn/lib.a +t/helper/test-svn-fe$X: vcs-svn/lib.a .PRECIOUS: $(TEST_OBJS) -test-%$X: test-%.o GIT-LDFLAGS $(GITLIBS) +t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS) -check-sha1:: test-sha1$X - ./test-sha1.sh +check-sha1:: t/helper/test-sha1$X + t/helper/test-sha1.sh SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ)) @@ -2263,10 +2257,10 @@ sparse: $(SP_OBJ) check: common-cmds.h @if sparse; \ then \ - echo 2>&1 "Use 'make sparse' instead"; \ + echo >&2 "Use 'make sparse' instead"; \ $(MAKE) --no-print-directory sparse; \ else \ - echo 2>&1 "Did you mean 'make test'?"; \ + echo >&2 "Did you mean 'make test'?"; \ exit 1; \ fi @@ -2396,31 +2390,25 @@ quick-install-html: ### Maintainer's dist rules -git.spec: git.spec.in GIT-VERSION-FILE - sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@+ - mv $@+ $@ - GIT_TARNAME = git-$(GIT_VERSION) -dist: git.spec git-archive$(X) configure +dist: git-archive$(X) configure ./git-archive --format=tar \ --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar @mkdir -p $(GIT_TARNAME) - @cp git.spec configure $(GIT_TARNAME) + @cp configure $(GIT_TARNAME) @echo $(GIT_VERSION) > $(GIT_TARNAME)/version @$(MAKE) -C git-gui TARDIR=../$(GIT_TARNAME)/git-gui dist-version $(TAR) rf $(GIT_TARNAME).tar \ - $(GIT_TARNAME)/git.spec \ $(GIT_TARNAME)/configure \ $(GIT_TARNAME)/version \ $(GIT_TARNAME)/git-gui/version @$(RM) -r $(GIT_TARNAME) gzip -f -9 $(GIT_TARNAME).tar -rpm: dist - $(RPMBUILD) \ - --define "_source_filedigest_algorithm md5" \ - --define "_binary_filedigest_algorithm md5" \ - -ta $(GIT_TARNAME).tar.gz +rpm:: + @echo >&2 "Use distro packaged sources to run rpmbuild" + @false +.PHONY: rpm htmldocs = git-htmldocs-$(GIT_VERSION) manpages = git-manpages-$(GIT_VERSION) @@ -2456,8 +2444,8 @@ profile-clean: $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs))) clean: profile-clean coverage-clean - $(RM) *.o *.res refs/*.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o - $(RM) xdiff/*.o vcs-svn/*.o ewah/*.o builtin/*.o + $(RM) *.res + $(RM) $(OBJECTS) $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB) $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X $(RM) $(TEST_PROGRAMS) $(NO_INSTALL) @@ -2496,6 +2484,7 @@ ALL_COMMANDS += git-gui git-citool .PHONY: check-docs check-docs:: + $(MAKE) -C Documentation lint-docs @(for v in $(ALL_COMMANDS); \ do \ case "$$v" in \ diff --git a/README.md b/README.md index d1ffbb6170..bd8a918a9b 100644 --- a/README.md +++ b/README.md @@ -17,14 +17,14 @@ including full documentation and Git related tools. See [Documentation/gittutorial.txt][] to get started, then see [Documentation/giteveryday.txt][] for a useful minimum set of commands, and -[Documentation/git-commandname.txt][] for documentation of each command. +Documentation/git-.txt 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-commandname" or "git help -commandname". +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.txt][] -("man gitcvs-migration" or "git help cvs-migration" if git is +(`man gitcvs-migration` or `git help cvs-migration` if git is installed). The user discussion and development of Git take place on the Git @@ -57,6 +57,5 @@ and the name as (depending on your mood): [INSTALL]: INSTALL [Documentation/gittutorial.txt]: Documentation/gittutorial.txt [Documentation/giteveryday.txt]: Documentation/giteveryday.txt -[Documentation/git-commandname.txt]: Documentation/git-commandname.txt [Documentation/gitcvs-migration.txt]: Documentation/gitcvs-migration.txt [Documentation/SubmittingPatches]: Documentation/SubmittingPatches diff --git a/RelNotes b/RelNotes index 7db30403c3..66606735cb 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.8.0.txt \ No newline at end of file +Documentation/RelNotes/2.9.0.txt \ No newline at end of file diff --git a/abspath.c b/abspath.c index 5edb4e7816..2825de8591 100644 --- a/abspath.c +++ b/abspath.c @@ -167,7 +167,6 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg) strbuf_add(&path, pfx, pfx_len); strbuf_addstr(&path, arg); #else - char *p; /* don't add prefix to absolute paths, but still replace '\' by '/' */ strbuf_reset(&path); if (is_absolute_path(arg)) @@ -175,9 +174,7 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg) else if (pfx_len) strbuf_add(&path, pfx, pfx_len); strbuf_addstr(&path, arg); - for (p = path.buf + pfx_len; *p; p++) - if (*p == '\\') - *p = '/'; + convert_slashes(path.buf + pfx_len); #endif return path.buf; } diff --git a/archive-tar.c b/archive-tar.c index 501ca97760..cb99df2814 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -181,7 +181,7 @@ static void prepare_header(struct archiver_args *args, memcpy(header->magic, "ustar", 6); memcpy(header->version, "00", 2); - snprintf(header->chksum, sizeof(header->chksum), "%07o", ustar_header_chksum(header)); + xsnprintf(header->chksum, sizeof(header->chksum), "%07o", ustar_header_chksum(header)); } static int write_extended_header(struct archiver_args *args, diff --git a/attr.c b/attr.c index 6537a433da..eec5d7d15a 100644 --- a/attr.c +++ b/attr.c @@ -122,7 +122,7 @@ struct pattern { const char *pattern; int patternlen; int nowildcardlen; - int flags; /* EXC_FLAG_* */ + unsigned flags; /* EXC_FLAG_* */ }; /* diff --git a/bisect.c b/bisect.c index 7996c2907b..6d93edbcb9 100644 --- a/bisect.c +++ b/bisect.c @@ -860,8 +860,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) /* Create file BISECT_ANCESTORS_OK. */ fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (fd < 0) - warning("could not create file '%s': %s", - filename, strerror(errno)); + warning_errno("could not create file '%s'", + filename); else close(fd); done: @@ -910,8 +910,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good) *read_good = "good"; return; } else { - die("could not read file '%s': %s", filename, - strerror(errno)); + die_errno("could not read file '%s'", filename); } } else { strbuf_getline_lf(&str, fp); diff --git a/branch.c b/branch.c index c50ea42172..a5a8dcbd0e 100644 --- a/branch.c +++ b/branch.c @@ -334,13 +334,38 @@ void remove_branch_state(void) unlink(git_path_squash_msg()); } -void die_if_checked_out(const char *branch) +void die_if_checked_out(const char *branch, int ignore_current_worktree) { - char *existing; + const struct worktree *wt; - existing = find_shared_symref("HEAD", branch); - if (existing) { - skip_prefix(branch, "refs/heads/", &branch); - die(_("'%s' is already checked out at '%s'"), branch, existing); + wt = find_shared_symref("HEAD", branch); + if (!wt || (ignore_current_worktree && wt->is_current)) + return; + skip_prefix(branch, "refs/heads/", &branch); + die(_("'%s' is already checked out at '%s'"), + branch, wt->path); +} + +int replace_each_worktree_head_symref(const char *oldref, const char *newref) +{ + int ret = 0; + struct worktree **worktrees = get_worktrees(); + int i; + + for (i = 0; worktrees[i]; i++) { + if (worktrees[i]->is_detached) + continue; + if (strcmp(oldref, worktrees[i]->head_ref)) + continue; + + if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]), + newref)) { + ret = -1; + error(_("HEAD of working tree %s is not updated"), + worktrees[i]->path); + } } + + free_worktrees(worktrees); + return ret; } diff --git a/branch.h b/branch.h index 78ad4387cd..b2f9649332 100644 --- a/branch.h +++ b/branch.h @@ -58,6 +58,13 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name); * worktree and die (with a message describing its checkout location) if * it is. */ -extern void die_if_checked_out(const char *branch); +extern void die_if_checked_out(const char *branch, int ignore_current_worktree); + +/* + * Update all per-worktree HEADs pointing at the old ref to point the new ref. + * This will be used when renaming a branch. Returns 0 if successful, non-zero + * otherwise. + */ +extern int replace_each_worktree_head_symref(const char *oldref, const char *newref); #endif diff --git a/builtin/am.c b/builtin/am.c index d003939bc5..3dfe70b7a0 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -769,15 +769,15 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state, in = fopen(*paths, "r"); if (!in) - return error(_("could not open '%s' for reading: %s"), - *paths, strerror(errno)); + return error_errno(_("could not open '%s' for reading"), + *paths); mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1); out = fopen(mail, "w"); if (!out) - return error(_("could not open '%s' for writing: %s"), - mail, strerror(errno)); + return error_errno(_("could not open '%s' for writing"), + mail); ret = fn(out, in, keep_cr); @@ -857,8 +857,7 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths, fp = fopen(*paths, "r"); if (!fp) - return error(_("could not open '%s' for reading: %s"), *paths, - strerror(errno)); + return error_errno(_("could not open '%s' for reading"), *paths); while (!strbuf_getline_lf(&sb, fp)) { if (*sb.buf == '#') diff --git a/builtin/apply.c b/builtin/apply.c index 42c610e2ec..c770d7d3d9 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -442,7 +442,7 @@ static int is_dev_null(const char *str) #define TERM_SPACE 1 #define TERM_TAB 2 -static int name_terminate(const char *name, int namelen, int c, int terminate) +static int name_terminate(int c, int terminate) { if (c == ' ' && !(terminate & TERM_SPACE)) return 0; @@ -671,7 +671,7 @@ static char *find_name_common(const char *line, const char *def, if (!end && isspace(c)) { if (c == '\n') break; - if (name_terminate(start, line-start, c, terminate)) + if (name_terminate(c, terminate)) break; } line++; @@ -931,22 +931,19 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, return find_name(line, NULL, p_value, TERM_TAB); if (orig_name) { - int len; - const char *name; + int len = strlen(orig_name); char *another; - name = orig_name; - len = strlen(name); if (isnull) - die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), name, linenr); + die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), + orig_name, linenr); another = find_name(line, NULL, p_value, TERM_TAB); - if (!another || memcmp(another, name, len + 1)) + if (!another || memcmp(another, orig_name, len + 1)) die((side == DIFF_NEW_NAME) ? _("git apply: bad git-diff - inconsistent new filename on line %d") : _("git apply: bad git-diff - inconsistent old filename on line %d"), linenr); free(another); return orig_name; - } - else { + } else { /* expect "/dev/null" */ if (memcmp("/dev/null", line, 9) || line[9] != '\n') die(_("git apply: bad git-diff - expected /dev/null on line %d"), linenr); @@ -956,21 +953,15 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, static int gitdiff_oldname(const char *line, struct patch *patch) { - char *orig = patch->old_name; patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, DIFF_OLD_NAME); - if (orig != patch->old_name) - free(orig); return 0; } static int gitdiff_newname(const char *line, struct patch *patch) { - char *orig = patch->new_name; patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, DIFF_NEW_NAME); - if (orig != patch->new_name) - free(orig); return 0; } @@ -1872,6 +1863,11 @@ static struct fragment *parse_binary_hunk(char **buf_p, return NULL; } +/* + * Returns: + * -1 in case of error, + * the length of the parsed binary patch otherwise + */ static int parse_binary(char *buffer, unsigned long size, struct patch *patch) { /* @@ -2017,6 +2013,8 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) linenr++; used = parse_binary(buffer + hd + llen, size - hd - llen, patch); + if (used < 0) + return -1; if (used) patchsize = used + llen; else @@ -4373,8 +4371,10 @@ static int apply_patch(int fd, const char *filename, int options) patch->inaccurate_eof = !!(options & INACCURATE_EOF); patch->recount = !!(options & RECOUNT); nr = parse_chunk(buf.buf + offset, buf.len - offset, patch); - if (nr < 0) + if (nr < 0) { + free_patch(patch); break; + } if (apply_in_reverse) reverse_patches(patch); if (use_patch(patch)) { @@ -4383,6 +4383,8 @@ static int apply_patch(int fd, const char *filename, int options) listp = &patch->next; } else { + if (apply_verbosely) + say_patch_name(stderr, _("Skipped patch '%s'."), patch); free_patch(patch); skipped_patch++; } diff --git a/builtin/blame.c b/builtin/blame.c index e982fb8137..21f42b0b62 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -2307,6 +2307,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, unsigned mode; struct strbuf msg = STRBUF_INIT; + read_cache(); time(&now); commit = alloc_commit_node(); commit->object.parsed = 1; diff --git a/builtin/branch.c b/builtin/branch.c index 7b45b6bd6b..2ecde53bf8 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -20,6 +20,7 @@ #include "utf8.h" #include "wt-status.h" #include "ref-filter.h" +#include "worktree.h" static const char * const builtin_branch_usage[] = { N_("git branch [] [-r | -a] [--merged | --no-merged]"), @@ -215,16 +216,21 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, int flags = 0; strbuf_branchname(&bname, argv[i]); - if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) { - error(_("Cannot delete the branch '%s' " - "which you are currently on."), bname.buf); - ret = 1; - continue; - } - free(name); - name = mkpathdup(fmt, bname.buf); + + if (kinds == FILTER_REFS_BRANCHES) { + const struct worktree *wt = + find_shared_symref("HEAD", name); + if (wt) { + error(_("Cannot delete branch '%s' " + "checked out at '%s'"), + bname.buf, wt->path); + ret = 1; + continue; + } + } + target = resolve_ref_unsafe(name, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE @@ -369,12 +375,14 @@ static char *get_head_description(void) strbuf_addf(&desc, _("(no branch, bisect started on %s)"), state.branch); else if (state.detached_from) { - /* TRANSLATORS: make sure these match _("HEAD detached at ") - and _("HEAD detached from ") in wt-status.c */ if (state.detached_at) + /* TRANSLATORS: make sure this matches + "HEAD detached at " in wt-status.c */ strbuf_addf(&desc, _("(HEAD detached at %s)"), state.detached_from); else + /* TRANSLATORS: make sure this matches + "HEAD detached from " in wt-status.c */ strbuf_addf(&desc, _("(HEAD detached from %s)"), state.detached_from); } @@ -393,22 +401,25 @@ static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth, int current = 0; int color; struct strbuf out = STRBUF_INIT, name = STRBUF_INIT; - const char *prefix = ""; + const char *prefix_to_show = ""; + const char *prefix_to_skip = NULL; const char *desc = item->refname; char *to_free = NULL; switch (item->kind) { case FILTER_REFS_BRANCHES: - skip_prefix(desc, "refs/heads/", &desc); + prefix_to_skip = "refs/heads/"; + skip_prefix(desc, prefix_to_skip, &desc); if (!filter->detached && !strcmp(desc, head)) current = 1; else color = BRANCH_COLOR_LOCAL; break; case FILTER_REFS_REMOTES: - skip_prefix(desc, "refs/remotes/", &desc); + prefix_to_skip = "refs/remotes/"; + skip_prefix(desc, prefix_to_skip, &desc); color = BRANCH_COLOR_REMOTE; - prefix = remote_prefix; + prefix_to_show = remote_prefix; break; case FILTER_REFS_DETACHED_HEAD: desc = to_free = get_head_description(); @@ -425,7 +436,7 @@ static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth, color = BRANCH_COLOR_CURRENT; } - strbuf_addf(&name, "%s%s", prefix, desc); + strbuf_addf(&name, "%s%s", prefix_to_show, desc); if (filter->verbose) { int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf); strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color), @@ -436,8 +447,10 @@ static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth, name.buf, branch_get_color(BRANCH_COLOR_RESET)); if (item->symref) { - skip_prefix(item->symref, "refs/remotes/", &desc); - strbuf_addf(&out, " -> %s", desc); + const char *symref = item->symref; + if (prefix_to_skip) + skip_prefix(symref, prefix_to_skip, &symref); + strbuf_addf(&out, " -> %s", symref); } else if (filter->verbose) /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */ @@ -513,6 +526,29 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin ref_array_clear(&array); } +static void reject_rebase_or_bisect_branch(const char *target) +{ + struct worktree **worktrees = get_worktrees(); + int i; + + for (i = 0; worktrees[i]; i++) { + struct worktree *wt = worktrees[i]; + + if (!wt->is_detached) + continue; + + if (is_worktree_being_rebased(wt, target)) + die(_("Branch %s is being rebased at %s"), + target, wt->path); + + if (is_worktree_being_bisected(wt, target)) + die(_("Branch %s is being bisected at %s"), + target, wt->path); + } + + free_worktrees(worktrees); +} + static void rename_branch(const char *oldname, const char *newname, int force) { struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT; @@ -542,6 +578,8 @@ static void rename_branch(const char *oldname, const char *newname, int force) validate_new_branchname(newname, &newref, force, clobber_head_ok); + reject_rebase_or_bisect_branch(oldref.buf); + strbuf_addf(&logmsg, "Branch: renamed %s to %s", oldref.buf, newref.buf); @@ -552,8 +590,7 @@ static void rename_branch(const char *oldname, const char *newname, int force) if (recovery) warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 11); - /* no need to pass logmsg here as HEAD didn't really move */ - if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL)) + if (replace_each_worktree_head_symref(oldref.buf, newref.buf)) die(_("Branch renamed to %s, but HEAD is not updated!"), newname); strbuf_addf(&oldsection, "branch.%s", oldref.buf + 11); @@ -583,8 +620,7 @@ static int edit_branch_description(const char *branch_name) branch_name, comment_line_char); if (write_file_gently(git_path(edit_description), "%s", buf.buf)) { strbuf_release(&buf); - return error(_("could not write branch description template: %s"), - strerror(errno)); + return error_errno(_("could not write branch description template")); } strbuf_reset(&buf); if (launch_editor(git_path(edit_description), &buf, NULL)) { @@ -620,7 +656,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) BRANCH_TRACK_EXPLICIT), OPT_SET_INT( 0, "set-upstream", &track, N_("change upstream info"), BRANCH_TRACK_OVERRIDE), - OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"), + OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")), OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"), OPT__COLOR(&branch_use_color, N_("use colored output")), OPT_SET_INT('r', "remotes", &filter.kind, N_("act on remote-tracking branches"), @@ -828,8 +864,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (argc == 1 && track == BRANCH_TRACK_OVERRIDE && !branch_existed && remote_tracking) { fprintf(stderr, _("\nIf you wanted to make '%s' track '%s', do this:\n\n"), head, branch->name); - fprintf(stderr, _(" git branch -d %s\n"), branch->name); - fprintf(stderr, _(" git branch --set-upstream-to %s\n"), branch->name); + fprintf(stderr, " git branch -d %s\n", branch->name); + fprintf(stderr, " git branch --set-upstream-to %s\n", branch->name); } } else diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 54db1184a0..618103fdee 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -154,6 +154,13 @@ struct expand_data { * elements above, so you can retrieve the response from there. */ struct object_info info; + + /* + * This flag will be true if the requested batch format and options + * don't require us to call sha1_object_info, which can then be + * optimized out. + */ + unsigned skip_object_info : 1; }; static int is_atom(const char *atom, const char *s, int slen) @@ -258,7 +265,8 @@ static void batch_object_write(const char *obj_name, struct batch_options *opt, { struct strbuf buf = STRBUF_INIT; - if (sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { + if (!data->skip_object_info && + sha1_object_info_extended(data->sha1, &data->info, LOOKUP_REPLACE_OBJECT) < 0) { printf("%s missing\n", obj_name ? obj_name : sha1_to_hex(data->sha1)); fflush(stdout); return; @@ -369,6 +377,13 @@ static int batch_objects(struct batch_options *opt) strbuf_expand(&buf, opt->format, expand_format, &data); data.mark_query = 0; + if (opt->all_objects) { + struct object_info empty; + memset(&empty, 0, sizeof(empty)); + if (!memcmp(&data.info, &empty, sizeof(empty))) + data.skip_object_info = 1; + } + /* * If we are printing out the object, then always fill in the type, * since we will want to decide whether or not to stream. @@ -489,6 +504,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) git_config(git_cat_file_config, NULL); + batch.buffer_output = -1; argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0); if (opt) { @@ -512,6 +528,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) usage_with_options(cat_file_usage, options); } + if (batch.buffer_output < 0) + batch.buffer_output = batch.all_objects; + if (batch.enabled) return batch_objects(&batch); diff --git a/builtin/checkout.c b/builtin/checkout.c index efcbd8f6b5..3398c61e9a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -242,7 +242,6 @@ static int checkout_paths(const struct checkout_opts *opts, struct checkout state; static char *ps_matched; unsigned char rev[20]; - int flag; struct commit *head; int errs = 0; struct lock_file *lock_file; @@ -375,7 +374,7 @@ static int checkout_paths(const struct checkout_opts *opts, if (write_locked_index(&the_index, lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); - read_ref_full("HEAD", 0, rev, &flag); + read_ref_full("HEAD", 0, rev, NULL); head = lookup_commit_reference_gently(rev, 1); errs |= post_checkout_hook(head, head, 0); @@ -1111,7 +1110,7 @@ static int checkout_branch(struct checkout_opts *opts, char *head_ref = resolve_refdup("HEAD", 0, sha1, &flag); if (head_ref && (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path))) - die_if_checked_out(new->path); + die_if_checked_out(new->path, 1); free(head_ref); } diff --git a/builtin/clone.c b/builtin/clone.c index 661639255c..5f867e67d8 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -40,6 +40,7 @@ static const char * const builtin_clone_usage[] = { static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1; static int option_local = -1, option_no_hardlinks, option_shared, option_recursive; +static int option_shallow_submodules = -1; static char *option_template, *option_depth; static char *option_origin = NULL; static char *option_branch = NULL; @@ -51,6 +52,7 @@ static enum transport_family family; static struct string_list option_config; static struct string_list option_reference; static int option_dissociate; +static int max_jobs = -1; static struct option builtin_clone_options[] = { OPT__VERBOSITY(&option_verbosity), @@ -73,6 +75,8 @@ static struct option builtin_clone_options[] = { N_("initialize submodules in the clone")), OPT_BOOL(0, "recurse-submodules", &option_recursive, N_("initialize submodules in the clone")), + OPT_INTEGER('j', "jobs", &max_jobs, + N_("number of submodules cloned in parallel")), OPT_STRING(0, "template", &option_template, N_("template-directory"), N_("directory from which templates will be used")), OPT_STRING_LIST(0, "reference", &option_reference, N_("repo"), @@ -89,6 +93,8 @@ static struct option builtin_clone_options[] = { N_("create a shallow clone of that depth")), OPT_BOOL(0, "single-branch", &option_single_branch, N_("clone only one branch, HEAD or --branch")), + OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules, + N_("any cloned submodules will be shallow")), OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), N_("separate git dir from working tree")), OPT_STRING_LIST('c', "config", &option_config, N_("key=value"), @@ -100,10 +106,6 @@ static struct option builtin_clone_options[] = { OPT_END() }; -static const char *argv_submodule[] = { - "submodule", "update", "--init", "--recursive", NULL -}; - static const char *get_repo_path_1(struct strbuf *path, int *is_bundle) { static char *suffix[] = { "/.git", "", ".git/.git", ".git" }; @@ -732,8 +734,20 @@ static int checkout(void) err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1), sha1_to_hex(sha1), "1", NULL); - if (!err && option_recursive) - err = run_command_v_opt(argv_submodule, RUN_GIT_CMD); + if (!err && option_recursive) { + struct argv_array args = ARGV_ARRAY_INIT; + argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL); + + if (option_shallow_submodules == 1 + || (option_shallow_submodules == -1 && option_depth)) + argv_array_push(&args, "--depth=1"); + + if (max_jobs != -1) + argv_array_pushf(&args, "--jobs=%d", max_jobs); + + err = run_command_v_opt(args.argv, RUN_GIT_CMD); + argv_array_clear(&args); + } return err; } diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index 3feeffeab1..8a674bc9e7 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -33,10 +33,6 @@ static int commit_tree_config(const char *var, const char *value, void *cb) int status = git_gpg_config(var, value, NULL); if (status) return status; - if (!strcmp(var, "commit.gpgsign")) { - sign_commit = git_config_bool(var, value) ? "" : NULL; - return 0; - } return git_default_config(var, value, cb); } diff --git a/builtin/commit.c b/builtin/commit.c index b3bd2d4181..443ff9196d 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -114,6 +114,7 @@ static char *fixup_message, *squash_message; static int all, also, interactive, patch_interactive, only, amend, signoff; static int edit_flag = -1; /* unspecified */ static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship; +static int config_commit_verbose = -1; /* unspecified */ static int no_post_rewrite, allow_empty_message; static char *untracked_files_arg, *force_date, *ignore_submodule_arg; static char *sign_commit; @@ -186,6 +187,7 @@ static void status_init_config(struct wt_status *s, config_fn_t fn) gitmodules_config(); git_config(fn, s); determine_whence(s); + init_diff_ui_defaults(); s->hints = advice_status_hints; /* must come after git_config() */ } @@ -694,7 +696,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, } } - if (message.len) { + if (have_option_m) { strbuf_addbuf(&sb, &message); hook_arg1 = "message"; } else if (logfile && !strcmp(logfile, "-")) { @@ -726,9 +728,18 @@ static int prepare_to_commit(const char *index_file, const char *prefix, &sb, &ctx); hook_arg1 = "message"; } else if (!stat(git_path_merge_msg(), &statbuf)) { + /* + * prepend SQUASH_MSG here if it exists and a + * "merge --squash" was originally performed + */ + if (!stat(git_path_squash_msg(), &statbuf)) { + if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0) + die_errno(_("could not read SQUASH_MSG")); + hook_arg1 = "squash"; + } else + hook_arg1 = "merge"; if (strbuf_read_file(&sb, git_path_merge_msg(), 0) < 0) die_errno(_("could not read MERGE_MSG")); - hook_arg1 = "merge"; } else if (!stat(git_path_squash_msg(), &statbuf)) { if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0) die_errno(_("could not read SQUASH_MSG")); @@ -1162,9 +1173,9 @@ static int parse_and_validate_options(int argc, const char *argv[], f++; if (f > 1) die(_("Only one of -c/-C/-F/--fixup can be used.")); - if (message.len && f > 0) + if (have_option_m && f > 0) die((_("Option -m cannot be combined with -c/-C/-F/--fixup."))); - if (f || message.len) + if (f || have_option_m) template_file = NULL; if (edit_message) use_message = edit_message; @@ -1505,6 +1516,11 @@ static int git_commit_config(const char *k, const char *v, void *cb) sign_commit = git_config_bool(k, v) ? "" : NULL; return 0; } + if (!strcmp(k, "commit.verbose")) { + int is_bool; + config_commit_verbose = git_config_bool_or_int(k, v, &is_bool); + return 0; + } status = git_gpg_config(k, v, NULL); if (status) @@ -1651,9 +1667,13 @@ int cmd_commit(int argc, const char **argv, const char *prefix) if (parse_commit(current_head)) die(_("could not parse HEAD commit")); } + verbose = -1; /* unspecified */ argc = parse_and_validate_options(argc, argv, builtin_commit_options, builtin_commit_usage, prefix, current_head, &s); + if (verbose == -1) + verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose; + if (dry_run) return dry_run_commit(argc, argv, prefix, current_head, &s); index_file = prepare_index(argc, argv, prefix, current_head, 0); diff --git a/builtin/config.c b/builtin/config.c index ca9f834ae6..1d7c6ef558 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -417,6 +417,7 @@ static int urlmatch_collect_fn(const char *var, const char *value, void *cb) static int get_urlmatch(const char *var, const char *url) { + int ret; char *section_tail; struct string_list_item *item; struct urlmatch_config config = { STRING_LIST_INIT_DUP }; @@ -443,6 +444,8 @@ static int get_urlmatch(const char *var, const char *url) git_config_with_options(urlmatch_config_entry, &config, &given_config_source, respect_includes); + ret = !values.nr; + for_each_string_list_item(item, &values) { struct urlmatch_current_candidate_value *matched = item->util; struct strbuf buf = STRBUF_INIT; @@ -459,7 +462,7 @@ static int get_urlmatch(const char *var, const char *url) free(config.url.url); free((void *)config.section); - return 0; + return ret; } static char *default_user_config(void) diff --git a/builtin/diff-files.c b/builtin/diff-files.c index 8ed2eb8813..15c61fd8d1 100644 --- a/builtin/diff-files.c +++ b/builtin/diff-files.c @@ -24,6 +24,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; + precompose_argv(argc, argv); argc = setup_revisions(argc, argv, &rev, NULL); while (1 < argc && argv[1][0] == '-') { diff --git a/builtin/diff-index.c b/builtin/diff-index.c index d979824f93..1af373d002 100644 --- a/builtin/diff-index.c +++ b/builtin/diff-index.c @@ -21,6 +21,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) gitmodules_config(); git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; + precompose_argv(argc, argv); argc = setup_revisions(argc, argv, &rev, NULL); for (i = 1; i < argc; i++) { diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c index 2a12b81e06..806dd7a885 100644 --- a/builtin/diff-tree.c +++ b/builtin/diff-tree.c @@ -114,6 +114,8 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) opt->disable_stdin = 1; memset(&s_r_opt, 0, sizeof(s_r_opt)); s_r_opt.tweak = diff_tree_tweak_rev; + + precompose_argv(argc, argv); argc = setup_revisions(argc, argv, opt, &s_r_opt); while (--argc > 0) { diff --git a/builtin/diff.c b/builtin/diff.c index 52c98a9217..b7a9405d9f 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -318,7 +318,9 @@ int cmd_diff(int argc, const char **argv, const char *prefix) if (!no_index) gitmodules_config(); + init_diff_ui_defaults(); git_config(git_diff_ui_config, NULL); + precompose_argv(argc, argv); init_revisions(&rev, prefix); diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index 79a611fda1..bfd0be44a9 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -16,10 +16,20 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, struct ref *ref; struct object_id oid; - if (!get_oid_hex(name, &oid) && name[GIT_SHA1_HEXSZ] == ' ') - name += GIT_SHA1_HEXSZ + 1; - else + if (!get_oid_hex(name, &oid)) { + if (name[GIT_SHA1_HEXSZ] == ' ') { + /* , find refname */ + name += GIT_SHA1_HEXSZ + 1; + } else if (name[GIT_SHA1_HEXSZ] == '\0') { + ; /* , leave sha1 as name */ + } else { + /* , clear cruft from oid */ + oidclr(&oid); + } + } else { + /* , clear cruft from get_oid_hex */ oidclr(&oid); + } ref = alloc_ref(name); oidcpy(&ref->old_oid, &oid); diff --git a/builtin/fetch.c b/builtin/fetch.c index e4639d8eb1..1582ca7184 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -37,7 +37,7 @@ static int prune = -1; /* unspecified */ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity; static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; static int tags = TAGS_DEFAULT, unshallow, update_shallow; -static int max_children = 1; +static int max_children = -1; static enum transport_family family; static const char *depth; static const char *upload_pack; @@ -607,7 +607,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, fp = fopen(filename, "a"); if (!fp) - return error(_("cannot open %s: %s\n"), filename, strerror(errno)); + return error_errno(_("cannot open %s"), filename); if (raw_url) url = transport_anonymize_url(raw_url); @@ -848,7 +848,7 @@ static int truncate_fetch_head(void) FILE *fp = fopen_for_writing(filename); if (!fp) - return error(_("cannot open %s: %s\n"), filename, strerror(errno)); + return error_errno(_("cannot open %s"), filename); fclose(fp); return 0; } diff --git a/builtin/fsck.c b/builtin/fsck.c index 55eac756f7..3f27456883 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -493,13 +493,12 @@ static void fsck_object_dir(const char *path) static int fsck_head_link(void) { - int flag; int null_is_error = 0; if (verbose) fprintf(stderr, "Checking HEAD link\n"); - head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid.hash, &flag); + head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid.hash, NULL); if (!head_points_at) { errors_found |= ERROR_REFS; return error("Invalid HEAD"); diff --git a/builtin/grep.c b/builtin/grep.c index aa7435f380..462e607901 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -438,7 +438,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, strbuf_add(base, entry.path, te_len); if (S_ISREG(entry.mode)) { - hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len, + hit |= grep_sha1(opt, entry.oid->hash, base->buf, tn_len, check_attr ? base->buf + tn_len : NULL); } else if (S_ISDIR(entry.mode)) { @@ -447,10 +447,10 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec, void *data; unsigned long size; - data = lock_and_read_sha1_file(entry.sha1, &type, &size); + data = lock_and_read_sha1_file(entry.oid->hash, &type, &size); if (!data) die(_("unable to read tree (%s)"), - sha1_to_hex(entry.sha1)); + oid_to_hex(entry.oid)); strbuf_addch(base, '/'); init_tree_desc(&sub, data, size); @@ -522,12 +522,14 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec, } static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec, - int exc_std) + int exc_std, int use_index) { struct dir_struct dir; int i, hit = 0; memset(&dir, 0, sizeof(dir)); + if (!use_index) + dir.flags |= DIR_NO_GITLINKS; if (exc_std) setup_standard_excludes(&dir); @@ -902,7 +904,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude; if (list.nr) die(_("--no-index or --untracked cannot be used with revs.")); - hit = grep_directory(&opt, &pathspec, use_exclude); + hit = grep_directory(&opt, &pathspec, use_exclude, use_index); } else if (0 <= opt_exclude) { die(_("--[no-]exclude-standard cannot be used for tracked contents.")); } else if (!list.nr) { diff --git a/builtin/help.c b/builtin/help.c index 3c55ce4563..88480131cf 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -127,7 +127,7 @@ static void exec_woman_emacs(const char *path, const char *page) path = "emacsclient"; strbuf_addf(&man_page, "(woman \"%s\")", page); execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL); - warning(_("failed to exec '%s': %s"), path, strerror(errno)); + warning_errno(_("failed to exec '%s'"), path); } } @@ -148,7 +148,7 @@ static void exec_man_konqueror(const char *path, const char *page) path = "kfmclient"; strbuf_addf(&man_page, "man:%s(1)", page); execlp(path, filename, "newTab", man_page.buf, (char *)NULL); - warning(_("failed to exec '%s': %s"), path, strerror(errno)); + warning_errno(_("failed to exec '%s'"), path); } } @@ -157,7 +157,7 @@ static void exec_man_man(const char *path, const char *page) if (!path) path = "man"; execlp(path, "man", page, (char *)NULL); - warning(_("failed to exec '%s': %s"), path, strerror(errno)); + warning_errno(_("failed to exec '%s'"), path); } static void exec_man_cmd(const char *cmd, const char *page) @@ -165,7 +165,7 @@ static void exec_man_cmd(const char *cmd, const char *page) struct strbuf shell_cmd = STRBUF_INIT; strbuf_addf(&shell_cmd, "%s %s", cmd, page); execl(SHELL_PATH, SHELL_PATH, "-c", shell_cmd.buf, (char *)NULL); - warning(_("failed to exec '%s': %s"), cmd, strerror(errno)); + warning(_("failed to exec '%s'"), cmd); } static void add_man_viewer(const char *name) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 45245199ae..e8c71fc1d2 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1250,7 +1250,9 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha nr_unresolved * sizeof(*objects)); f = sha1fd(output_fd, curr_pack); fix_unresolved_deltas(f); - strbuf_addf(&msg, _("completed with %d local objects"), + strbuf_addf(&msg, Q_("completed with %d local object", + "completed with %d local objects", + nr_objects - nr_objects_initial), nr_objects - nr_objects_initial); stop_progress_msg(&progress, msg.buf); strbuf_release(&msg); @@ -1599,6 +1601,18 @@ static void show_pack_info(int stat_only) } } +static const char *derive_filename(const char *pack_name, const char *suffix, + struct strbuf *buf) +{ + size_t len; + if (!strip_suffix(pack_name, ".pack", &len)) + die(_("packfile name '%s' does not end with '.pack'"), + pack_name); + strbuf_add(buf, pack_name, len); + strbuf_addstr(buf, suffix); + return buf->buf; +} + int cmd_index_pack(int argc, const char **argv, const char *prefix) { int i, fix_thin_pack = 0, verify = 0, stat_only = 0; @@ -1707,24 +1721,11 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) usage(index_pack_usage); if (fix_thin_pack && !from_stdin) die(_("--fix-thin cannot be used without --stdin")); - if (!index_name && pack_name) { - size_t len; - if (!strip_suffix(pack_name, ".pack", &len)) - die(_("packfile name '%s' does not end with '.pack'"), - pack_name); - strbuf_add(&index_name_buf, pack_name, len); - strbuf_addstr(&index_name_buf, ".idx"); - index_name = index_name_buf.buf; - } - if (keep_msg && !keep_name && pack_name) { - size_t len; - if (!strip_suffix(pack_name, ".pack", &len)) - die(_("packfile name '%s' does not end with '.pack'"), - pack_name); - strbuf_add(&keep_name_buf, pack_name, len); - strbuf_addstr(&keep_name_buf, ".idx"); - keep_name = keep_name_buf.buf; - } + if (!index_name && pack_name) + index_name = derive_filename(pack_name, ".idx", &index_name_buf); + if (keep_msg && !keep_name && pack_name) + keep_name = derive_filename(pack_name, ".keep", &keep_name_buf); + if (verify) { if (!index_name) die(_("--verify with no packfile name given")); diff --git a/builtin/init-db.c b/builtin/init-db.c index 6223b7d46a..b2d8d40a67 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -95,6 +95,8 @@ static void copy_templates(const char *template_dir) struct strbuf path = STRBUF_INIT; struct strbuf template_path = STRBUF_INIT; size_t template_len; + struct repository_format template_format; + struct strbuf err = STRBUF_INIT; DIR *dir; char *to_free = NULL; @@ -121,17 +123,18 @@ static void copy_templates(const char *template_dir) /* Make sure that template is from the correct vintage */ strbuf_addstr(&template_path, "config"); - repository_format_version = 0; - git_config_from_file(check_repository_format_version, - template_path.buf, NULL); + read_repository_format(&template_format, template_path.buf); strbuf_setlen(&template_path, template_len); - if (repository_format_version && - repository_format_version != GIT_REPO_VERSION) { - warning(_("not copying templates of " - "a wrong format version %d from '%s'"), - repository_format_version, - template_dir); + /* + * No mention of version at all is OK, but anything else should be + * verified. + */ + if (template_format.version >= 0 && + verify_repository_format(&template_format, &err) < 0) { + warning(_("not copying templates from '%s': %s"), + template_dir, err.buf); + strbuf_release(&err); goto close_free_return; } @@ -199,13 +202,13 @@ static int create_default_files(const char *template_path) /* reading existing config may have overwrote it */ if (init_shared_repository != -1) - shared_repository = init_shared_repository; + set_shared_repository(init_shared_repository); /* * We would have created the above under user's umask -- under * shared-repository settings, we would need to fix them up. */ - if (shared_repository) { + if (get_shared_repository()) { adjust_shared_perm(get_git_dir()); adjust_shared_perm(git_path_buf(&buf, "refs")); adjust_shared_perm(git_path_buf(&buf, "refs/heads")); @@ -322,6 +325,7 @@ int set_git_dir_init(const char *git_dir, const char *real_git_dir, set_git_dir(real_path(git_dir)); git_link = NULL; } + startup_info->have_repository = 1; return 0; } @@ -369,7 +373,7 @@ int init_db(const char *template_dir, unsigned int flags) create_object_directory(); - if (shared_repository) { + if (get_shared_repository()) { char buf[10]; /* We do not spell "group" and such, so that * the configuration can be read by older version @@ -377,12 +381,12 @@ int init_db(const char *template_dir, unsigned int flags) * and compatibility values for PERM_GROUP and * PERM_EVERYBODY. */ - if (shared_repository < 0) + if (get_shared_repository() < 0) /* force to the mode value */ - xsnprintf(buf, sizeof(buf), "0%o", -shared_repository); - else if (shared_repository == PERM_GROUP) + xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository()); + else if (get_shared_repository() == PERM_GROUP) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP); - else if (shared_repository == PERM_EVERYBODY) + else if (get_shared_repository() == PERM_EVERYBODY) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY); else die("BUG: invalid value for shared_repository"); @@ -398,7 +402,7 @@ int init_db(const char *template_dir, unsigned int flags) "", and the last '%s%s' is the verbatim directory name. */ printf(_("%s%s Git repository in %s%s\n"), reinit ? _("Reinitialized existing") : _("Initialized empty"), - shared_repository ? _(" shared") : "", + get_shared_repository() ? _(" shared") : "", git_dir, len && git_dir[len-1] != '/' ? "/" : ""); } @@ -493,8 +497,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) * and we know shared_repository should always be 0; * but just in case we play safe. */ - saved = shared_repository; - shared_repository = 0; + saved = get_shared_repository(); + set_shared_repository(0); switch (safe_create_leading_directories_const(argv[0])) { case SCLD_OK: case SCLD_PERMS: @@ -506,7 +510,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) die_errno(_("cannot mkdir %s"), argv[0]); break; } - shared_repository = saved; + set_shared_repository(saved); if (mkdir(argv[0], 0777) < 0) die_errno(_("cannot mkdir %s"), argv[0]); mkdir_tried = 1; @@ -524,7 +528,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) } if (init_shared_repository != -1) - shared_repository = init_shared_repository; + set_shared_repository(init_shared_repository); /* * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR diff --git a/builtin/log.c b/builtin/log.c index 0d738d6ddc..099f4f7be9 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -100,6 +100,12 @@ static int log_line_range_callback(const struct option *option, const char *arg, return 0; } +static void init_log_defaults(void) +{ + init_grep_defaults(); + init_diff_ui_defaults(); +} + static void cmd_log_init_defaults(struct rev_info *rev) { if (fmt_pretty) @@ -416,7 +422,7 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) struct rev_info rev; struct setup_revision_opt opt; - init_grep_defaults(); + init_log_defaults(); git_config(git_log_config, NULL); init_revisions(&rev, prefix); @@ -527,7 +533,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) struct pathspec match_all; int i, count, ret = 0; - init_grep_defaults(); + init_log_defaults(); git_config(git_log_config, NULL); memset(&match_all, 0, sizeof(match_all)); @@ -608,7 +614,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) struct rev_info rev; struct setup_revision_opt opt; - init_grep_defaults(); + init_log_defaults(); git_config(git_log_config, NULL); init_revisions(&rev, prefix); @@ -647,7 +653,7 @@ int cmd_log(int argc, const char **argv, const char *prefix) struct rev_info rev; struct setup_revision_opt opt; - init_grep_defaults(); + init_log_defaults(); git_config(git_log_config, NULL); init_revisions(&rev, prefix); @@ -696,6 +702,7 @@ static void add_header(const char *value) #define THREAD_DEEP 2 static int thread; static int do_signoff; +static int base_auto; static const char *signature = git_version_string; static const char *signature_file; static int config_cover_letter; @@ -780,6 +787,10 @@ static int git_format_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "format.outputdirectory")) return git_config_string(&config_output_directory, var, value); + if (!strcmp(var, "format.useautobase")) { + base_auto = git_config_bool(var, value); + return 0; + } return git_log_config(var, value, cb); } @@ -1185,6 +1196,155 @@ static int from_callback(const struct option *opt, const char *arg, int unset) return 0; } +struct base_tree_info { + struct object_id base_commit; + int nr_patch_id, alloc_patch_id; + struct object_id *patch_id; +}; + +static struct commit *get_base_commit(const char *base_commit, + struct commit **list, + int total) +{ + struct commit *base = NULL; + struct commit **rev; + int i = 0, rev_nr = 0; + + if (base_commit && strcmp(base_commit, "auto")) { + base = lookup_commit_reference_by_name(base_commit); + if (!base) + die(_("Unknown commit %s"), base_commit); + } else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) { + struct branch *curr_branch = branch_get(NULL); + const char *upstream = branch_get_upstream(curr_branch, NULL); + if (upstream) { + struct commit_list *base_list; + struct commit *commit; + unsigned char sha1[20]; + + if (get_sha1(upstream, sha1)) + die(_("Failed to resolve '%s' as a valid ref."), upstream); + commit = lookup_commit_or_die(sha1, "upstream base"); + base_list = get_merge_bases_many(commit, total, list); + /* There should be one and only one merge base. */ + if (!base_list || base_list->next) + die(_("Could not find exact merge base.")); + base = base_list->item; + free_commit_list(base_list); + } else { + die(_("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.")); + } + } + + ALLOC_ARRAY(rev, total); + for (i = 0; i < total; i++) + rev[i] = list[i]; + + rev_nr = total; + /* + * Get merge base through pair-wise computations + * and store it in rev[0]. + */ + while (rev_nr > 1) { + for (i = 0; i < rev_nr / 2; i++) { + struct commit_list *merge_base; + merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]); + if (!merge_base || merge_base->next) + die(_("Failed to find exact merge base")); + + rev[i] = merge_base->item; + } + + if (rev_nr % 2) + rev[i] = rev[2 * i]; + rev_nr = (rev_nr + 1) / 2; + } + + if (!in_merge_bases(base, rev[0])) + die(_("base commit should be the ancestor of revision list")); + + for (i = 0; i < total; i++) { + if (base == list[i]) + die(_("base commit shouldn't be in revision list")); + } + + free(rev); + return base; +} + +static void prepare_bases(struct base_tree_info *bases, + struct commit *base, + struct commit **list, + int total) +{ + struct commit *commit; + struct rev_info revs; + struct diff_options diffopt; + int i; + + if (!base) + return; + + diff_setup(&diffopt); + DIFF_OPT_SET(&diffopt, RECURSIVE); + diff_setup_done(&diffopt); + + oidcpy(&bases->base_commit, &base->object.oid); + + init_revisions(&revs, NULL); + revs.max_parents = 1; + revs.topo_order = 1; + for (i = 0; i < total; i++) { + list[i]->object.flags &= ~UNINTERESTING; + add_pending_object(&revs, &list[i]->object, "rev_list"); + list[i]->util = (void *)1; + } + base->object.flags |= UNINTERESTING; + add_pending_object(&revs, &base->object, "base"); + + if (prepare_revision_walk(&revs)) + die(_("revision walk setup failed")); + /* + * Traverse the commits list, get prerequisite patch ids + * and stuff them in bases structure. + */ + while ((commit = get_revision(&revs)) != NULL) { + unsigned char sha1[20]; + struct object_id *patch_id; + if (commit->util) + continue; + if (commit_patch_id(commit, &diffopt, sha1)) + die(_("cannot get patch id")); + ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id); + patch_id = bases->patch_id + bases->nr_patch_id; + hashcpy(patch_id->hash, sha1); + bases->nr_patch_id++; + } +} + +static void print_bases(struct base_tree_info *bases) +{ + int i; + + /* Only do this once, either for the cover or for the first one */ + if (is_null_oid(&bases->base_commit)) + return; + + /* Show the base commit */ + printf("base-commit: %s\n", oid_to_hex(&bases->base_commit)); + + /* Show the prerequisite patches */ + for (i = bases->nr_patch_id - 1; i >= 0; i--) + printf("prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i])); + + free(bases->patch_id); + bases->nr_patch_id = 0; + bases->alloc_patch_id = 0; + oidclr(&bases->base_commit); +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -1209,6 +1369,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int reroll_count = -1; char *branch_name = NULL; char *from = NULL; + char *base_commit = NULL; + struct base_tree_info bases; + const struct option builtin_format_patch_options[] = { { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL, N_("use [PATCH n/m] even with a single patch"), @@ -1271,6 +1434,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) PARSE_OPT_OPTARG, thread_callback }, OPT_STRING(0, "signature", &signature, N_("signature"), N_("add a signature")), + OPT_STRING(0, "base", &base_commit, N_("base-commit"), + N_("add prerequisite tree info to the patch series")), OPT_FILENAME(0, "signature-file", &signature_file, N_("add a signature from a file")), OPT__QUIET(&quiet, N_("don't print the patch filenames")), @@ -1280,10 +1445,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) extra_hdr.strdup_strings = 1; extra_to.strdup_strings = 1; extra_cc.strdup_strings = 1; - init_grep_defaults(); + init_log_defaults(); git_config(git_format_config, NULL); init_revisions(&rev, prefix); rev.commit_format = CMIT_FMT_EMAIL; + rev.expand_tabs_in_log_default = 0; rev.verbose_header = 1; rev.diff = 1; rev.max_parents = 1; @@ -1507,6 +1673,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) signature = strbuf_detach(&buf, NULL); } + memset(&bases, 0, sizeof(bases)); + if (base_commit || base_auto) { + struct commit *base = get_base_commit(base_commit, list, nr); + reset_revision_walk(); + prepare_bases(&bases, base, list, nr); + } + if (in_reply_to || thread || cover_letter) rev.ref_message_ids = xcalloc(1, sizeof(struct string_list)); if (in_reply_to) { @@ -1520,6 +1693,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) gen_message_id(&rev, "cover"); make_cover_letter(&rev, use_stdout, origin, nr, list, branch_name, quiet); + print_bases(&bases); total++; start_number--; } @@ -1585,6 +1759,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.mime_boundary); else print_signature(); + print_bases(&bases); } if (!use_stdout) fclose(stdout); diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c index 104277acc4..4859ede38a 100644 --- a/builtin/mailsplit.c +++ b/builtin/mailsplit.c @@ -109,7 +109,7 @@ static int populate_maildir_list(struct string_list *list, const char *path) if ((dir = opendir(name)) == NULL) { if (errno == ENOENT) continue; - error("cannot opendir %s (%s)", name, strerror(errno)); + error_errno("cannot opendir %s", name); goto out; } @@ -174,12 +174,12 @@ static int split_maildir(const char *maildir, const char *dir, f = fopen(file, "r"); if (!f) { - error("cannot open mail %s (%s)", file, strerror(errno)); + error_errno("cannot open mail %s", file); goto out; } if (strbuf_getwholeline(&buf, f, '\n')) { - error("cannot read mail %s (%s)", file, strerror(errno)); + error_errno("cannot read mail %s", file); goto out; } @@ -210,7 +210,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare, int file_done = 0; if (!f) { - error("cannot open mbox %s", file); + error_errno("cannot open mbox %s", file); goto out; } @@ -318,7 +318,7 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix) } if (stat(arg, &argstat) == -1) { - error("cannot stat %s (%s)", arg, strerror(errno)); + error_errno("cannot stat %s", arg); return 1; } diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 55447053f2..13e22a2f0b 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -62,8 +62,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) usage_with_options(merge_file_usage, options); if (quiet) { if (!freopen("/dev/null", "w", stderr)) - return error("failed to redirect stderr to /dev/null: " - "%s", strerror(errno)); + return error_errno("failed to redirect stderr to /dev/null"); } if (prefix) @@ -95,12 +94,13 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) FILE *f = to_stdout ? stdout : fopen(fpath, "wb"); if (!f) - ret = error("Could not open %s for writing", filename); + ret = error_errno("Could not open %s for writing", + filename); else if (result.size && fwrite(result.ptr, result.size, 1, f) != 1) - ret = error("Could not write to %s", filename); + ret = error_errno("Could not write to %s", filename); else if (fclose(f)) - ret = error("Could not close %s", filename); + ret = error_errno("Could not close %s", filename); free(result.ptr); } diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index ca570041df..5b7ab9b967 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -150,15 +150,15 @@ static void show_result(void) /* An empty entry never compares same, not even to another empty entry */ static int same_entry(struct name_entry *a, struct name_entry *b) { - return a->sha1 && - b->sha1 && - !hashcmp(a->sha1, b->sha1) && + return a->oid && + b->oid && + !oidcmp(a->oid, b->oid) && a->mode == b->mode; } static int both_empty(struct name_entry *a, struct name_entry *b) { - return !(a->sha1 || b->sha1); + return !(a->oid || b->oid); } static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsigned char *sha1, const char *path) @@ -188,8 +188,8 @@ static void resolve(const struct traverse_info *info, struct name_entry *ours, s return; path = traverse_path(info, result); - orig = create_entry(2, ours->mode, ours->sha1, path); - final = create_entry(0, result->mode, result->sha1, path); + orig = create_entry(2, ours->mode, ours->oid->hash, path); + final = create_entry(0, result->mode, result->oid->hash, path); final->link = orig; @@ -213,7 +213,7 @@ static void unresolved_directory(const struct traverse_info *info, newbase = traverse_path(info, p); -#define ENTRY_SHA1(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->sha1 : NULL) +#define ENTRY_SHA1(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->oid->hash : NULL) buf0 = fill_tree_descriptor(t+0, ENTRY_SHA1(n + 0)); buf1 = fill_tree_descriptor(t+1, ENTRY_SHA1(n + 1)); buf2 = fill_tree_descriptor(t+2, ENTRY_SHA1(n + 2)); @@ -239,7 +239,7 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info path = entry->path; else path = traverse_path(info, n); - link = create_entry(stage, n->mode, n->sha1, path); + link = create_entry(stage, n->mode, n->oid->hash, path); link->link = entry; return link; } @@ -314,7 +314,7 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s } if (same_entry(entry+0, entry+1)) { - if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) { + if (entry[2].oid && !S_ISDIR(entry[2].mode)) { /* We did not touch, they modified -- take theirs */ resolve(info, entry+1, entry+2); return mask; diff --git a/builtin/merge.c b/builtin/merge.c index 101ffeff4c..b555a1bf9c 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -64,6 +64,7 @@ static int option_renormalize; static int verbosity; static int allow_rerere_auto; static int abort_current_merge; +static int allow_unrelated_histories; static int show_progress = -1; static int default_to_upstream = 1; static const char *sign_commit; @@ -221,6 +222,8 @@ static struct option builtin_merge_options[] = { OPT__VERBOSITY(&verbosity), OPT_BOOL(0, "abort", &abort_current_merge, N_("abort the current in-progress merge")), + OPT_BOOL(0, "allow-unrelated-histories", &allow_unrelated_histories, + N_("allow merging unrelated histories")), OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1), { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, @@ -819,6 +822,14 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads) { unsigned char result_tree[20], result_commit[20]; struct commit_list *parents, **pptr = &parents; + static struct lock_file lock; + + hold_locked_index(&lock, 1); + refresh_cache(REFRESH_QUIET); + if (active_cache_changed && + write_locked_index(&the_index, &lock, COMMIT_LOCK)) + return error(_("Unable to write index.")); + rollback_lock_file(&lock); write_tree_trivial(result_tree); printf(_("Wonderful.\n")); @@ -1165,7 +1176,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) struct commit *head_commit; struct strbuf buf = STRBUF_INIT; const char *head_arg; - int flag, i, ret = 0, head_subsumed; + int i, ret = 0, head_subsumed; int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0; struct commit_list *common = NULL; const char *best_strategy = NULL, *wt_strategy = NULL; @@ -1179,7 +1190,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * Check if we are _not_ on a detached HEAD, i.e. if there is a * current branch. */ - branch = branch_to_free = resolve_refdup("HEAD", 0, head_sha1, &flag); + branch = branch_to_free = resolve_refdup("HEAD", 0, head_sha1, NULL); if (branch && starts_with(branch, "refs/heads/")) branch += 11; if (!branch || is_null_sha1(head_sha1)) @@ -1187,6 +1198,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) else head_commit = lookup_commit_or_die(head_sha1, "HEAD"); + init_diff_ui_defaults(); git_config(git_merge_config, NULL); if (branch_mergeoptions) @@ -1257,12 +1269,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix) builtin_merge_options); if (!head_commit) { - struct commit *remote_head; /* * If the merged head is a valid one there is no reason * to forbid "git merge" into a branch yet to be born. * We do the same for "git pull". */ + unsigned char *remote_head_sha1; if (squash) die(_("Squash commit into empty head not supported yet")); if (fast_forward == FF_NO) @@ -1270,13 +1282,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix) "an empty head")); remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv, NULL); - remote_head = remoteheads->item; - if (!remote_head) + if (!remoteheads) die(_("%s - not something we can merge"), argv[0]); if (remoteheads->next) die(_("Can merge only exactly one commit into empty head")); - read_empty(remote_head->object.oid.hash, 0); - update_ref("initial pull", "HEAD", remote_head->object.oid.hash, + remote_head_sha1 = remoteheads->item->object.oid.hash; + read_empty(remote_head_sha1, 0); + update_ref("initial pull", "HEAD", remote_head_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); goto done; } @@ -1397,9 +1409,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix) update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.oid.hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); - if (remoteheads && !common) - ; /* No common ancestors found. We need a real merge. */ - else if (!remoteheads || + if (remoteheads && !common) { + /* No common ancestors found. */ + if (!allow_unrelated_histories) + die(_("refusing to merge unrelated histories")); + /* otherwise, we need a real merge. */ + } else if (!remoteheads || (!remoteheads->next && !common->next && common->item == remoteheads->item)) { /* diff --git a/builtin/mv.c b/builtin/mv.c index aeae855e2b..a2014266b6 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -252,15 +252,18 @@ int cmd_mv(int argc, const char **argv, const char *prefix) int pos; if (show_only || verbose) printf(_("Renaming %s to %s\n"), src, dst); - if (!show_only && mode != INDEX) { - if (rename(src, dst) < 0 && !ignore_errors) - die_errno(_("renaming '%s' failed"), src); - if (submodule_gitfile[i]) { - if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR) - connect_work_tree_and_git_dir(dst, submodule_gitfile[i]); - if (!update_path_in_gitmodules(src, dst)) - gitmodules_modified = 1; - } + if (show_only) + continue; + if (mode != INDEX && rename(src, dst) < 0) { + if (ignore_errors) + continue; + die_errno(_("renaming '%s' failed"), src); + } + if (submodule_gitfile[i]) { + if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR) + connect_work_tree_and_git_dir(dst, submodule_gitfile[i]); + if (!update_path_in_gitmodules(src, dst)) + gitmodules_modified = 1; } if (mode == WORKING_DIRECTORY) diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 092e03c3cc..57be35faf5 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -10,6 +10,7 @@ typedef struct rev_name { const char *tip_name; + unsigned long taggerdate; int generation; int distance; } rev_name; @@ -20,7 +21,8 @@ static long cutoff = LONG_MAX; #define MERGE_TRAVERSAL_WEIGHT 65535 static void name_rev(struct commit *commit, - const char *tip_name, int generation, int distance, + const char *tip_name, unsigned long taggerdate, + int generation, int distance, int deref) { struct rev_name *name = (struct rev_name *)commit->util; @@ -43,9 +45,12 @@ static void name_rev(struct commit *commit, name = xmalloc(sizeof(rev_name)); commit->util = name; goto copy_data; - } else if (name->distance > distance) { + } else if (name->taggerdate > taggerdate || + (name->taggerdate == taggerdate && + name->distance > distance)) { copy_data: name->tip_name = tip_name; + name->taggerdate = taggerdate; name->generation = generation; name->distance = distance; } else @@ -66,11 +71,11 @@ static void name_rev(struct commit *commit, new_name = xstrfmt("%.*s^%d", (int)len, tip_name, parent_number); - name_rev(parents->item, new_name, 0, + name_rev(parents->item, new_name, taggerdate, 0, distance + MERGE_TRAVERSAL_WEIGHT, 0); } else { - name_rev(parents->item, tip_name, generation + 1, - distance + 1, 0); + name_rev(parents->item, tip_name, taggerdate, + generation + 1, distance + 1, 0); } } } @@ -140,6 +145,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo struct name_ref_data *data = cb_data; int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; + unsigned long taggerdate = ULONG_MAX; if (data->tags_only && !starts_with(path, "refs/tags/")) return 0; @@ -164,12 +170,13 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo break; /* broken repository */ o = parse_object(t->tagged->oid.hash); deref = 1; + taggerdate = t->date; } if (o && o->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)o; path = name_ref_abbrev(path, can_abbreviate_output); - name_rev(commit, xstrdup(path), 0, 0, deref); + name_rev(commit, xstrdup(path), taggerdate, 0, 0, deref); } return 0; } diff --git a/builtin/notes.c b/builtin/notes.c index ed6f2222f4..c65b59ad9a 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -744,13 +744,14 @@ static int merge_commit(struct notes_merge_options *o) static int git_config_get_notes_strategy(const char *key, enum notes_merge_strategy *strategy) { - const char *value; + char *value; - if (git_config_get_string_const(key, &value)) + if (git_config_get_string(key, &value)) return 1; if (parse_notes_merge_strategy(value, strategy)) git_die_config(key, "unknown notes merge strategy %s", value); + free(value); return 0; } @@ -846,15 +847,15 @@ static int merge(int argc, const char **argv, const char *prefix) update_ref(msg.buf, default_notes_ref(), result_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); else { /* Merge has unresolved conflicts */ - char *existing; + const struct worktree *wt; /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL, 0, UPDATE_REFS_DIE_ON_ERR); /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ - existing = find_shared_symref("NOTES_MERGE_REF", default_notes_ref()); - if (existing) + wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref()); + if (wt) die(_("A notes merge into %s is already in-progress at %s"), - default_notes_ref(), existing); + default_notes_ref(), wt->path); if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) die("Failed to store link to current notes ref (%s)", default_notes_ref()); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index a27de5b323..8f5e358e22 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -759,6 +759,10 @@ static off_t write_reused_pack(struct sha1file *f) return reuse_packfile_offset - sizeof(struct pack_header); } +static const char no_split_warning[] = N_( +"disabling bitmap writing, packs are split due to pack.packSizeLimit" +); + static void write_pack_file(void) { uint32_t i = 0, j; @@ -813,7 +817,10 @@ static void write_pack_file(void) fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written, sha1, offset); close(fd); - write_bitmap_index = 0; + if (write_bitmap_index) { + warning(_(no_split_warning)); + write_bitmap_index = 0; + } } if (!pack_to_stdout) { @@ -828,8 +835,7 @@ static void write_pack_file(void) * to preserve this property. */ if (stat(pack_tmp_name, &st) < 0) { - warning("failed to stat %s: %s", - pack_tmp_name, strerror(errno)); + warning_errno("failed to stat %s", pack_tmp_name); } else if (!last_mtime) { last_mtime = st.st_mtime; } else { @@ -837,8 +843,7 @@ static void write_pack_file(void) utb.actime = st.st_atime; utb.modtime = --last_mtime; if (utime(pack_tmp_name, &utb) < 0) - warning("failed utime() on %s: %s", - pack_tmp_name, strerror(errno)); + warning_errno("failed utime() on %s", pack_tmp_name); } strbuf_addf(&tmpname, "%s-", base_name); @@ -1186,7 +1191,7 @@ static void add_pbase_object(struct tree_desc *tree, if (cmp < 0) return; if (name[cmplen] != '/') { - add_object_entry(entry.sha1, + add_object_entry(entry.oid->hash, object_type(entry.mode), fullname, 1); return; @@ -1197,7 +1202,7 @@ static void add_pbase_object(struct tree_desc *tree, const char *down = name+cmplen+1; int downlen = name_cmp_len(down); - tree = pbase_tree_get(entry.sha1); + tree = pbase_tree_get(entry.oid->hash); if (!tree) return; init_tree_desc(&sub, tree->tree_data, tree->tree_size); diff --git a/builtin/patch-id.c b/builtin/patch-id.c index 366ce5a5d4..a84d0003a3 100644 --- a/builtin/patch-id.c +++ b/builtin/patch-id.c @@ -81,16 +81,13 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result, while (strbuf_getwholeline(line_buf, stdin, '\n') != EOF) { char *line = line_buf->buf; - char *p = line; + const char *p = line; int len; - if (!memcmp(line, "diff-tree ", 10)) - p += 10; - else if (!memcmp(line, "commit ", 7)) - p += 7; - else if (!memcmp(line, "From ", 5)) - p += 5; - else if (!memcmp(line, "\\ ", 2) && 12 < strlen(line)) + if (!skip_prefix(line, "diff-tree ", &p) && + !skip_prefix(line, "commit ", &p) && + !skip_prefix(line, "From ", &p) && + starts_with(line, "\\ ") && 12 < strlen(line)) continue; if (!get_oid_hex(p, next_oid)) { @@ -99,14 +96,14 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result, } /* Ignore commit comments */ - if (!patchlen && memcmp(line, "diff ", 5)) + if (!patchlen && !starts_with(line, "diff ")) continue; /* Parsing diff header? */ if (before == -1) { - if (!memcmp(line, "index ", 6)) + if (starts_with(line, "index ")) continue; - else if (!memcmp(line, "--- ", 4)) + else if (starts_with(line, "--- ")) before = after = 1; else if (!isalpha(line[0])) break; @@ -114,14 +111,14 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result, /* Looking for a valid hunk header? */ if (before == 0 && after == 0) { - if (!memcmp(line, "@@ -", 4)) { + if (starts_with(line, "@@ -")) { /* Parse next hunk, but ignore line numbers. */ scan_hunk_header(line, &before, &after); continue; } /* Split at the end of the patch. */ - if (memcmp(line, "diff ", 5)) + if (!starts_with(line, "diff ")) break; /* Else we're parsing another header. */ diff --git a/builtin/pull.c b/builtin/pull.c index 10eff03967..1d7333c8a1 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -86,9 +86,12 @@ static char *opt_commit; static char *opt_edit; static char *opt_ff; static char *opt_verify_signatures; +static int opt_autostash = -1; +static int config_autostash; static struct argv_array opt_strategies = ARGV_ARRAY_INIT; static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT; static char *opt_gpg_sign; +static int opt_allow_unrelated_histories; /* Options passed to git-fetch */ static char *opt_all; @@ -149,6 +152,8 @@ static struct option pull_options[] = { OPT_PASSTHRU(0, "verify-signatures", &opt_verify_signatures, NULL, N_("verify that the named commit has a valid GPG signature"), PARSE_OPT_NOARG), + OPT_BOOL(0, "autostash", &opt_autostash, + N_("automatically stash/stash pop before and after rebase")), OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"), N_("merge strategy to use"), 0), @@ -159,6 +164,9 @@ static struct option pull_options[] = { OPT_PASSTHRU('S', "gpg-sign", &opt_gpg_sign, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG), + OPT_SET_INT(0, "allow-unrelated-histories", + &opt_allow_unrelated_histories, + N_("allow merging unrelated histories"), 1), /* Options passed to git-fetch */ OPT_GROUP(N_("Options related to fetching")), @@ -305,6 +313,18 @@ static enum rebase_type config_get_rebase(void) return REBASE_FALSE; } +/** + * Read config variables. + */ +static int git_pull_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "rebase.autostash")) { + config_autostash = git_config_bool(var, value); + return 0; + } + return git_default_config(var, value, cb); +} + /** * Returns 1 if there are unstaged changes, 0 otherwise. */ @@ -458,13 +478,13 @@ static void NORETURN die_no_merge_candidates(const char *repo, const char **refs fprintf_ln(stderr, _("Please specify which branch you want to merge with.")); fprintf_ln(stderr, _("See git-pull(1) for details.")); fprintf(stderr, "\n"); - fprintf_ln(stderr, " git pull "); + fprintf_ln(stderr, " git pull %s %s", _(""), _("")); fprintf(stderr, "\n"); } else if (!curr_branch->merge_nr) { const char *remote_name = NULL; if (for_each_remote(get_only_remote, &remote_name) || !remote_name) - remote_name = ""; + remote_name = _(""); fprintf_ln(stderr, _("There is no tracking information for the current branch.")); if (opt_rebase) @@ -473,12 +493,12 @@ static void NORETURN die_no_merge_candidates(const char *repo, const char **refs fprintf_ln(stderr, _("Please specify which branch you want to merge with.")); fprintf_ln(stderr, _("See git-pull(1) for details.")); fprintf(stderr, "\n"); - fprintf_ln(stderr, " git pull "); + fprintf_ln(stderr, " git pull %s %s", _(""), _("")); fprintf(stderr, "\n"); - fprintf_ln(stderr, _("If you wish to set tracking information for this branch you can do so with:\n" - "\n" - " git branch --set-upstream-to=%s/ %s\n"), - remote_name, curr_branch->name); + fprintf_ln(stderr, _("If you wish to set tracking information for this branch you can do so with:")); + fprintf(stderr, "\n"); + fprintf_ln(stderr, " git branch --set-upstream-to=%s/%s %s\n", + remote_name, _(""), curr_branch->name); } else fprintf_ln(stderr, _("Your configuration specifies to merge with the ref '%s'\n" "from the remote, but no such ref was fetched."), @@ -612,6 +632,8 @@ static int run_merge(void) argv_array_pushv(&args, opt_strategy_opts.argv); if (opt_gpg_sign) argv_array_push(&args, opt_gpg_sign); + if (opt_allow_unrelated_histories > 0) + argv_array_push(&args, "--allow-unrelated-histories"); argv_array_push(&args, "FETCH_HEAD"); ret = run_command_v_opt(args.argv, RUN_GIT_CMD); @@ -789,6 +811,10 @@ static int run_rebase(const unsigned char *curr_head, argv_array_pushv(&args, opt_strategy_opts.argv); if (opt_gpg_sign) argv_array_push(&args, opt_gpg_sign); + if (opt_autostash == 0) + argv_array_push(&args, "--no-autostash"); + else if (opt_autostash == 1) + argv_array_push(&args, "--autostash"); argv_array_push(&args, "--onto"); argv_array_push(&args, sha1_to_hex(merge_head)); @@ -823,7 +849,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (opt_rebase < 0) opt_rebase = config_get_rebase(); - git_config(git_default_config, NULL); + git_config(git_pull_config, NULL); if (read_cache_unmerged()) die_resolve_conflict("Pull"); @@ -834,13 +860,17 @@ int cmd_pull(int argc, const char **argv, const char *prefix) if (get_sha1("HEAD", orig_head)) hashclr(orig_head); + if (!opt_rebase && opt_autostash != -1) + die(_("--[no-]autostash option is only valid with --rebase.")); + if (opt_rebase) { - int autostash = 0; + int autostash = config_autostash; + if (opt_autostash != -1) + autostash = opt_autostash; if (is_null_sha1(orig_head) && !is_cache_unborn()) die(_("Updating an unborn branch with changes added to the index.")); - git_config_get_bool("rebase.autostash", &autostash); if (!autostash) die_on_unclean_work_tree(prefix); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index c8e32b297c..a744437b58 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -21,7 +21,10 @@ #include "sigchain.h" #include "fsck.h" -static const char receive_pack_usage[] = "git receive-pack "; +static const char * const receive_pack_usage[] = { + N_("git receive-pack "), + NULL +}; enum deny_action { DENY_UNCONFIGURED, @@ -49,7 +52,7 @@ static int quiet; static int prefer_ofs_delta = 1; static int auto_update_server_info; static int auto_gc = 1; -static int fix_thin = 1; +static int reject_thin; static int stateless_rpc; static const char *service_dir; static const char *head_name; @@ -1081,13 +1084,13 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) if (!(flag & REF_ISSYMREF)) return; - dst_name = strip_namespace(dst_name); if (!dst_name) { rp_error("refusing update to broken symref '%s'", cmd->ref_name); cmd->skip_update = 1; cmd->error_string = "broken symref"; return; } + dst_name = strip_namespace(dst_name); if ((item = string_list_lookup(list, dst_name)) == NULL) return; @@ -1548,7 +1551,7 @@ static const char *unpack(int err_fd, struct shallow_info *si) if (fsck_objects) argv_array_pushf(&child.args, "--strict%s", fsck_msg_types.buf); - if (fix_thin) + if (!reject_thin) argv_array_push(&child.args, "--fix-thin"); child.out = -1; child.err = err_fd; @@ -1707,45 +1710,29 @@ static int delete_only(struct command *commands) int cmd_receive_pack(int argc, const char **argv, const char *prefix) { int advertise_refs = 0; - int i; struct command *commands; struct sha1_array shallow = SHA1_ARRAY_INIT; struct sha1_array ref = SHA1_ARRAY_INIT; struct shallow_info si; - packet_trace_identity("receive-pack"); + struct option options[] = { + OPT__QUIET(&quiet, N_("quiet")), + OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL), + OPT_HIDDEN_BOOL(0, "advertise-refs", &advertise_refs, NULL), + OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL), + OPT_END() + }; - argv++; - for (i = 1; i < argc; i++) { - const char *arg = *argv++; + packet_trace_identity("receive-pack"); - if (*arg == '-') { - if (!strcmp(arg, "--quiet")) { - quiet = 1; - continue; - } + argc = parse_options(argc, argv, prefix, options, receive_pack_usage, 0); - if (!strcmp(arg, "--advertise-refs")) { - advertise_refs = 1; - continue; - } - if (!strcmp(arg, "--stateless-rpc")) { - stateless_rpc = 1; - continue; - } - if (!strcmp(arg, "--reject-thin-pack-for-testing")) { - fix_thin = 0; - continue; - } + if (argc > 1) + usage_msg_opt(_("Too many arguments."), receive_pack_usage, options); + if (argc == 0) + usage_msg_opt(_("You must specify a directory."), receive_pack_usage, options); - usage(receive_pack_usage); - } - if (service_dir) - usage(receive_pack_usage); - service_dir = arg; - } - if (!service_dir) - usage(receive_pack_usage); + service_dir = argv[0]; setup_path(); diff --git a/builtin/reflog.c b/builtin/reflog.c index 2d46b6482a..7a7136e53e 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -84,8 +84,8 @@ static int tree_is_complete(const unsigned char *sha1) init_tree_desc(&desc, tree->buffer, tree->size); complete = 1; while (tree_entry(&desc, &entry)) { - if (!has_sha1_file(entry.sha1) || - (S_ISDIR(entry.mode) && !tree_is_complete(entry.sha1))) { + if (!has_sha1_file(entry.oid->hash) || + (S_ISDIR(entry.mode) && !tree_is_complete(entry.oid->hash))) { tree->object.flags |= INCOMPLETE; complete = 0; } diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c index 7457c743e8..88eb8f9013 100644 --- a/builtin/remote-ext.c +++ b/builtin/remote-ext.c @@ -168,7 +168,7 @@ static int command_loop(const char *child) size_t i; if (!fgets(buffer, MAXCOMMAND - 1, stdin)) { if (ferror(stdin)) - die("Comammand input error"); + die("Command input error"); exit(0); } /* Strip end of line characters. */ diff --git a/builtin/remote.c b/builtin/remote.c index fda5c2e53d..d33766be39 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -1154,6 +1154,8 @@ static int show(int argc, const char **argv) url_nr = states.remote->url_nr; } for (i = 0; i < url_nr; i++) + /* TRANSLATORS: the colon ':' should align with + the one in " Fetch URL: %s" translation */ printf_ln(_(" Push URL: %s"), url[i]); if (!i) printf_ln(_(" Push URL: %s"), "(no URL)"); diff --git a/builtin/replace.c b/builtin/replace.c index 748c6ca954..b58c714cb8 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -440,6 +440,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix) }; check_replace_refs = 0; + git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 275da0d647..b82bcc3436 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -358,12 +358,16 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (use_bitmap_index && !revs.prune) { if (revs.count && !revs.left_right && !revs.cherry_mark) { uint32_t commit_count; + int max_count = revs.max_count; if (!prepare_bitmap_walk(&revs)) { count_bitmap_commit_list(&commit_count, NULL, NULL, NULL); + if (max_count >= 0 && max_count < commit_count) + commit_count = max_count; printf("%d\n", commit_count); return 0; } - } else if (revs.tag_objects && revs.tree_objects && revs.blob_objects) { + } else if (revs.max_count < 0 && + revs.tag_objects && revs.tree_objects && revs.blob_objects) { if (!prepare_bitmap_walk(&revs)) { traverse_bitmap_commit_list(&show_object_fast); return 0; diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index cf8487b3b9..c961b74c5a 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -505,6 +505,7 @@ N_("git rev-parse --parseopt [] -- [...]\n" int cmd_rev_parse(int argc, const char **argv, const char *prefix) { int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0; + int did_repo_setup = 0; int has_dashdash = 0; int output_prefix = 0; unsigned char sha1[20]; @@ -528,11 +529,40 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } } - prefix = setup_git_directory(); - git_config(git_default_config, NULL); + /* No options; just report on whether we're in a git repo or not. */ + if (argc == 1) { + setup_git_directory(); + git_config(git_default_config, NULL); + return 0; + } + for (i = 1; i < argc; i++) { const char *arg = argv[i]; + if (!strcmp(arg, "--local-env-vars")) { + int i; + for (i = 0; local_repo_env[i]; i++) + printf("%s\n", local_repo_env[i]); + continue; + } + if (!strcmp(arg, "--resolve-git-dir")) { + const char *gitdir = argv[++i]; + if (!gitdir) + die("--resolve-git-dir requires an argument"); + gitdir = resolve_gitdir(gitdir); + if (!gitdir) + die("not a gitdir '%s'", argv[i]); + puts(gitdir); + continue; + } + + /* The rest of the options require a git repository. */ + if (!did_repo_setup) { + prefix = setup_git_directory(); + git_config(git_default_config, NULL); + did_repo_setup = 1; + } + if (!strcmp(arg, "--git-path")) { if (!argv[i + 1]) die("--git-path requires an argument"); @@ -706,12 +736,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) add_ref_exclusion(&ref_excludes, arg + 10); continue; } - if (!strcmp(arg, "--local-env-vars")) { - int i; - for (i = 0; local_repo_env[i]; i++) - printf("%s\n", local_repo_env[i]); - continue; - } if (!strcmp(arg, "--show-toplevel")) { const char *work_tree = get_git_work_tree(); if (work_tree) @@ -767,16 +791,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) puts(prefix_filename(pfx, strlen(pfx), get_git_common_dir())); continue; } - if (!strcmp(arg, "--resolve-git-dir")) { - const char *gitdir = argv[++i]; - if (!gitdir) - die("--resolve-git-dir requires an argument"); - gitdir = resolve_gitdir(gitdir); - if (!gitdir) - die("not a gitdir '%s'", argv[i]); - puts(gitdir); - continue; - } if (!strcmp(arg, "--is-inside-git-dir")) { printf("%s\n", is_inside_git_dir() ? "true" : "false"); diff --git a/builtin/rm.c b/builtin/rm.c index 8829b09d0b..8abb0207fa 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -152,7 +152,7 @@ static int check_local_mod(unsigned char *head, int index_only) if (lstat(ce->name, &st) < 0) { if (errno != ENOENT && errno != ENOTDIR) - warning("'%s': %s", ce->name, strerror(errno)); + warning_errno(_("failed to stat '%s'"), ce->name); /* It already vanished from the working tree */ continue; } @@ -314,7 +314,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix) list.entry[list.nr].is_submodule = S_ISGITLINK(ce->ce_mode); if (list.entry[list.nr++].is_submodule && !is_staging_gitmodules_ok()) - die (_("Please, stage your changes to .gitmodules or stash them to proceed")); + die (_("Please stage your changes to .gitmodules or stash them to proceed")); } if (pathspec.nr) { diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 5b9dd6a9d8..1ff5a67538 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -225,7 +225,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) * --all and --mirror are incompatible; neither makes sense * with any refspecs. */ - if ((refspecs && (send_all || args.send_mirror)) || + if ((nr_refspecs > 0 && (send_all || args.send_mirror)) || (send_all && args.send_mirror)) usage_with_options(send_pack_usage, options); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 5295b727d4..926d205162 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -9,6 +9,211 @@ #include "submodule-config.h" #include "string-list.h" #include "run-command.h" +#include "remote.h" +#include "refs.h" +#include "connect.h" + +static char *get_default_remote(void) +{ + char *dest = NULL, *ret; + unsigned char sha1[20]; + struct strbuf sb = STRBUF_INIT; + const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL); + + if (!refname) + die(_("No such ref: %s"), "HEAD"); + + /* detached HEAD */ + if (!strcmp(refname, "HEAD")) + return xstrdup("origin"); + + if (!skip_prefix(refname, "refs/heads/", &refname)) + die(_("Expecting a full ref name, got %s"), refname); + + strbuf_addf(&sb, "branch.%s.remote", refname); + if (git_config_get_string(sb.buf, &dest)) + ret = xstrdup("origin"); + else + ret = dest; + + strbuf_release(&sb); + return ret; +} + +static int starts_with_dot_slash(const char *str) +{ + return str[0] == '.' && is_dir_sep(str[1]); +} + +static int starts_with_dot_dot_slash(const char *str) +{ + return str[0] == '.' && str[1] == '.' && is_dir_sep(str[2]); +} + +/* + * Returns 1 if it was the last chop before ':'. + */ +static int chop_last_dir(char **remoteurl, int is_relative) +{ + char *rfind = find_last_dir_sep(*remoteurl); + if (rfind) { + *rfind = '\0'; + return 0; + } + + rfind = strrchr(*remoteurl, ':'); + if (rfind) { + *rfind = '\0'; + return 1; + } + + if (is_relative || !strcmp(".", *remoteurl)) + die(_("cannot strip one component off url '%s'"), + *remoteurl); + + free(*remoteurl); + *remoteurl = xstrdup("."); + return 0; +} + +/* + * The `url` argument is the URL that navigates to the submodule origin + * repo. When relative, this URL is relative to the superproject origin + * URL repo. The `up_path` argument, if specified, is the relative + * path that navigates from the submodule working tree to the superproject + * working tree. Returns the origin URL of the submodule. + * + * Return either an absolute URL or filesystem path (if the superproject + * origin URL is an absolute URL or filesystem path, respectively) or a + * relative file system path (if the superproject origin URL is a relative + * file system path). + * + * When the output is a relative file system path, the path is either + * relative to the submodule working tree, if up_path is specified, or to + * the superproject working tree otherwise. + * + * NEEDSWORK: This works incorrectly on the domain and protocol part. + * remote_url url outcome expectation + * http://a.com/b ../c http://a.com/c as is + * http://a.com/b ../../c http://c error out + * http://a.com/b ../../../c http:/c error out + * http://a.com/b ../../../../c http:c error out + * http://a.com/b ../../../../../c .:c error out + * NEEDSWORK: Given how chop_last_dir() works, this function is broken + * when a local part has a colon in its path component, too. + */ +static char *relative_url(const char *remote_url, + const char *url, + const char *up_path) +{ + int is_relative = 0; + int colonsep = 0; + char *out; + char *remoteurl = xstrdup(remote_url); + struct strbuf sb = STRBUF_INIT; + size_t len = strlen(remoteurl); + + if (is_dir_sep(remoteurl[len])) + remoteurl[len] = '\0'; + + if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl)) + is_relative = 0; + else { + is_relative = 1; + /* + * Prepend a './' to ensure all relative + * remoteurls start with './' or '../' + */ + if (!starts_with_dot_slash(remoteurl) && + !starts_with_dot_dot_slash(remoteurl)) { + strbuf_reset(&sb); + strbuf_addf(&sb, "./%s", remoteurl); + free(remoteurl); + remoteurl = strbuf_detach(&sb, NULL); + } + } + /* + * When the url starts with '../', remove that and the + * last directory in remoteurl. + */ + while (url) { + if (starts_with_dot_dot_slash(url)) { + url += 3; + colonsep |= chop_last_dir(&remoteurl, is_relative); + } else if (starts_with_dot_slash(url)) + url += 2; + else + break; + } + strbuf_reset(&sb); + strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url); + free(remoteurl); + + if (starts_with_dot_slash(sb.buf)) + out = xstrdup(sb.buf + 2); + else + out = xstrdup(sb.buf); + strbuf_reset(&sb); + + if (!up_path || !is_relative) + return out; + + strbuf_addf(&sb, "%s%s", up_path, out); + free(out); + return strbuf_detach(&sb, NULL); +} + +static int resolve_relative_url(int argc, const char **argv, const char *prefix) +{ + char *remoteurl = NULL; + char *remote = get_default_remote(); + const char *up_path = NULL; + char *res; + const char *url; + struct strbuf sb = STRBUF_INIT; + + if (argc != 2 && argc != 3) + die("resolve-relative-url only accepts one or two arguments"); + + url = argv[1]; + strbuf_addf(&sb, "remote.%s.url", remote); + free(remote); + + if (git_config_get_string(sb.buf, &remoteurl)) + /* the repository is its own authoritative upstream */ + remoteurl = xgetcwd(); + + if (argc == 3) + up_path = argv[2]; + + res = relative_url(remoteurl, url, up_path); + puts(res); + free(res); + free(remoteurl); + return 0; +} + +static int resolve_relative_url_test(int argc, const char **argv, const char *prefix) +{ + char *remoteurl, *res; + const char *up_path, *url; + + if (argc != 4) + die("resolve-relative-url-test only accepts three arguments: "); + + up_path = argv[1]; + remoteurl = xstrdup(argv[2]); + url = argv[3]; + + if (!strcmp(up_path, "(null)")) + up_path = NULL; + + res = relative_url(remoteurl, url, up_path); + puts(res); + free(res); + free(remoteurl); + return 0; +} struct module_list { const struct cache_entry **entries; @@ -82,10 +287,8 @@ static int module_list(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, module_list_options, git_submodule_helper_usage, 0); - if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) { - printf("#unmatched\n"); + if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) return 1; - } for (i = 0; i < list.nr; i++) { const struct cache_entry *ce = list.entries[i]; @@ -100,6 +303,125 @@ static int module_list(int argc, const char **argv, const char *prefix) return 0; } +static void init_submodule(const char *path, const char *prefix, int quiet) +{ + const struct submodule *sub; + struct strbuf sb = STRBUF_INIT; + char *upd = NULL, *url = NULL, *displaypath; + + /* Only loads from .gitmodules, no overlay with .git/config */ + gitmodules_config(); + + if (prefix) { + strbuf_addf(&sb, "%s%s", prefix, path); + displaypath = strbuf_detach(&sb, NULL); + } else + displaypath = xstrdup(path); + + sub = submodule_from_path(null_sha1, path); + + if (!sub) + die(_("No url found for submodule path '%s' in .gitmodules"), + displaypath); + + /* + * Copy url setting when it is not set yet. + * To look up the url in .git/config, we must not fall back to + * .gitmodules, so look it up directly. + */ + strbuf_reset(&sb); + strbuf_addf(&sb, "submodule.%s.url", sub->name); + if (git_config_get_string(sb.buf, &url)) { + url = xstrdup(sub->url); + + if (!url) + die(_("No url found for submodule path '%s' in .gitmodules"), + displaypath); + + /* Possibly a url relative to parent */ + if (starts_with_dot_dot_slash(url) || + starts_with_dot_slash(url)) { + char *remoteurl, *relurl; + char *remote = get_default_remote(); + struct strbuf remotesb = STRBUF_INIT; + strbuf_addf(&remotesb, "remote.%s.url", remote); + free(remote); + + if (git_config_get_string(remotesb.buf, &remoteurl)) + /* + * The repository is its own + * authoritative upstream + */ + remoteurl = xgetcwd(); + relurl = relative_url(remoteurl, url, NULL); + strbuf_release(&remotesb); + free(remoteurl); + free(url); + url = relurl; + } + + if (git_config_set_gently(sb.buf, url)) + die(_("Failed to register url for submodule path '%s'"), + displaypath); + if (!quiet) + fprintf(stderr, + _("Submodule '%s' (%s) registered for path '%s'\n"), + sub->name, url, displaypath); + } + + /* Copy "update" setting when it is not set yet */ + strbuf_reset(&sb); + strbuf_addf(&sb, "submodule.%s.update", sub->name); + if (git_config_get_string(sb.buf, &upd) && + sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) { + if (sub->update_strategy.type == SM_UPDATE_COMMAND) { + fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"), + sub->name); + upd = xstrdup("none"); + } else + upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy)); + + if (git_config_set_gently(sb.buf, upd)) + die(_("Failed to register update mode for submodule path '%s'"), displaypath); + } + strbuf_release(&sb); + free(displaypath); + free(url); + free(upd); +} + +static int module_init(int argc, const char **argv, const char *prefix) +{ + struct pathspec pathspec; + struct module_list list = MODULE_LIST_INIT; + int quiet = 0; + int i; + + struct option module_init_options[] = { + OPT_STRING(0, "prefix", &prefix, + N_("path"), + N_("alternative anchor for relative paths")), + OPT__QUIET(&quiet, N_("Suppress output for initializing a submodule")), + OPT_END() + }; + + const char *const git_submodule_helper_usage[] = { + N_("git submodule--helper init []"), + NULL + }; + + argc = parse_options(argc, argv, prefix, module_init_options, + git_submodule_helper_usage, 0); + + if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0) + return 1; + + for (i = 0; i < list.nr; i++) + init_submodule(list.entries[i]->name, prefix, quiet); + + return 0; +} + static int module_name(int argc, const char **argv, const char *prefix) { const struct submodule *sub; @@ -118,6 +440,7 @@ static int module_name(int argc, const char **argv, const char *prefix) return 0; } + static int clone_submodule(const char *path, const char *gitdir, const char *url, const char *depth, const char *reference, int quiet) { @@ -139,7 +462,7 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url argv_array_push(&cp.args, path); cp.git_cmd = 1; - cp.env = local_repo_env; + prepare_submodule_repo_env(&cp.env_array); cp.no_stdin = 1; return run_command(&cp); @@ -147,11 +470,11 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url static int module_clone(int argc, const char **argv, const char *prefix) { - const char *path = NULL, *name = NULL, *url = NULL; + const char *name = NULL, *url = NULL; const char *reference = NULL, *depth = NULL; int quiet = 0; FILE *submodule_dot_git; - char *sm_gitdir, *cwd, *p; + char *p, *path = NULL, *sm_gitdir; struct strbuf rel_path = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; @@ -180,16 +503,27 @@ static int module_clone(int argc, const char **argv, const char *prefix) const char *const git_submodule_helper_usage[] = { N_("git submodule--helper clone [--prefix=] [--quiet] " - "[--reference ] [--name ] [--url ]" - "[--depth ] [--] [...]"), + "[--reference ] [--name ] [--depth ] " + "--url --path "), NULL }; argc = parse_options(argc, argv, prefix, module_clone_options, git_submodule_helper_usage, 0); + if (argc || !url || !path || !*path) + usage_with_options(git_submodule_helper_usage, + module_clone_options); + strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name); - sm_gitdir = strbuf_detach(&sb, NULL); + sm_gitdir = xstrdup(absolute_path(sb.buf)); + strbuf_reset(&sb); + + if (!is_absolute_path(path)) { + strbuf_addf(&sb, "%s/%s", get_git_work_tree(), path); + path = strbuf_detach(&sb, NULL); + } else + path = xstrdup(path); if (!file_exists(sm_gitdir)) { if (safe_create_leading_directories_const(sm_gitdir) < 0) @@ -206,49 +540,308 @@ static int module_clone(int argc, const char **argv, const char *prefix) } /* Write a .git file in the submodule to redirect to the superproject. */ - if (safe_create_leading_directories_const(path) < 0) - die(_("could not create directory '%s'"), path); - - if (path && *path) - strbuf_addf(&sb, "%s/.git", path); - else - strbuf_addstr(&sb, ".git"); - + strbuf_addf(&sb, "%s/.git", path); if (safe_create_leading_directories_const(sb.buf) < 0) die(_("could not create leading directories of '%s'"), sb.buf); submodule_dot_git = fopen(sb.buf, "w"); if (!submodule_dot_git) die_errno(_("cannot open file '%s'"), sb.buf); - fprintf(submodule_dot_git, "gitdir: %s\n", - relative_path(sm_gitdir, path, &rel_path)); + fprintf_or_die(submodule_dot_git, "gitdir: %s\n", + relative_path(sm_gitdir, path, &rel_path)); if (fclose(submodule_dot_git)) die(_("could not close file %s"), sb.buf); strbuf_reset(&sb); strbuf_reset(&rel_path); - cwd = xgetcwd(); /* Redirect the worktree of the submodule in the superproject's config */ - if (!is_absolute_path(sm_gitdir)) { - strbuf_addf(&sb, "%s/%s", cwd, sm_gitdir); - free(sm_gitdir); - sm_gitdir = strbuf_detach(&sb, NULL); - } - - strbuf_addf(&sb, "%s/%s", cwd, path); p = git_pathdup_submodule(path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), path); git_config_set_in_file(p, "core.worktree", - relative_path(sb.buf, sm_gitdir, &rel_path)); + relative_path(path, sm_gitdir, &rel_path)); strbuf_release(&sb); strbuf_release(&rel_path); free(sm_gitdir); - free(cwd); + free(path); free(p); return 0; } +struct submodule_update_clone { + /* index into 'list', the list of submodules to look into for cloning */ + int current; + struct module_list list; + unsigned warn_if_uninitialized : 1; + + /* update parameter passed via commandline */ + struct submodule_update_strategy update; + + /* configuration parameters which are passed on to the children */ + int quiet; + const char *reference; + const char *depth; + const char *recursive_prefix; + const char *prefix; + + /* Machine-readable status lines to be consumed by git-submodule.sh */ + struct string_list projectlines; + + /* If we want to stop as fast as possible and return an error */ + unsigned quickstop : 1; +}; +#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \ + SUBMODULE_UPDATE_STRATEGY_INIT, 0, NULL, NULL, NULL, NULL, \ + STRING_LIST_INIT_DUP, 0} + + +static void next_submodule_warn_missing(struct submodule_update_clone *suc, + struct strbuf *out, const char *displaypath) +{ + /* + * Only mention uninitialized submodules when their + * paths have been specified. + */ + if (suc->warn_if_uninitialized) { + strbuf_addf(out, + _("Submodule path '%s' not initialized"), + displaypath); + strbuf_addch(out, '\n'); + strbuf_addstr(out, + _("Maybe you want to use 'update --init'?")); + strbuf_addch(out, '\n'); + } +} + +/** + * Determine whether 'ce' needs to be cloned. If so, prepare the 'child' to + * run the clone. Returns 1 if 'ce' needs to be cloned, 0 otherwise. + */ +static int prepare_to_clone_next_submodule(const struct cache_entry *ce, + struct child_process *child, + struct submodule_update_clone *suc, + struct strbuf *out) +{ + const struct submodule *sub = NULL; + struct strbuf displaypath_sb = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT; + const char *displaypath = NULL; + char *url = NULL; + int needs_cloning = 0; + + if (ce_stage(ce)) { + if (suc->recursive_prefix) + strbuf_addf(&sb, "%s/%s", suc->recursive_prefix, ce->name); + else + strbuf_addf(&sb, "%s", ce->name); + strbuf_addf(out, _("Skipping unmerged submodule %s"), sb.buf); + strbuf_addch(out, '\n'); + goto cleanup; + } + + sub = submodule_from_path(null_sha1, ce->name); + + if (suc->recursive_prefix) + displaypath = relative_path(suc->recursive_prefix, + ce->name, &displaypath_sb); + else + displaypath = ce->name; + + if (!sub) { + next_submodule_warn_missing(suc, out, displaypath); + goto cleanup; + } + + if (suc->update.type == SM_UPDATE_NONE + || (suc->update.type == SM_UPDATE_UNSPECIFIED + && sub->update_strategy.type == SM_UPDATE_NONE)) { + strbuf_addf(out, _("Skipping submodule '%s'"), displaypath); + strbuf_addch(out, '\n'); + goto cleanup; + } + + /* + * Looking up the url in .git/config. + * We must not fall back to .gitmodules as we only want + * to process configured submodules. + */ + strbuf_reset(&sb); + strbuf_addf(&sb, "submodule.%s.url", sub->name); + git_config_get_string(sb.buf, &url); + if (!url) { + next_submodule_warn_missing(suc, out, displaypath); + goto cleanup; + } + + strbuf_reset(&sb); + strbuf_addf(&sb, "%s/.git", ce->name); + needs_cloning = !file_exists(sb.buf); + + strbuf_reset(&sb); + strbuf_addf(&sb, "%06o %s %d %d\t%s\n", ce->ce_mode, + sha1_to_hex(ce->sha1), ce_stage(ce), + needs_cloning, ce->name); + string_list_append(&suc->projectlines, sb.buf); + + if (!needs_cloning) + goto cleanup; + + child->git_cmd = 1; + child->no_stdin = 1; + child->stdout_to_stderr = 1; + child->err = -1; + argv_array_push(&child->args, "submodule--helper"); + argv_array_push(&child->args, "clone"); + if (suc->quiet) + argv_array_push(&child->args, "--quiet"); + if (suc->prefix) + argv_array_pushl(&child->args, "--prefix", suc->prefix, NULL); + argv_array_pushl(&child->args, "--path", sub->path, NULL); + argv_array_pushl(&child->args, "--name", sub->name, NULL); + argv_array_pushl(&child->args, "--url", url, NULL); + if (suc->reference) + argv_array_push(&child->args, suc->reference); + if (suc->depth) + argv_array_push(&child->args, suc->depth); + +cleanup: + free(url); + strbuf_reset(&displaypath_sb); + strbuf_reset(&sb); + + return needs_cloning; +} + +static int update_clone_get_next_task(struct child_process *child, + struct strbuf *err, + void *suc_cb, + void **void_task_cb) +{ + struct submodule_update_clone *suc = suc_cb; + + for (; suc->current < suc->list.nr; suc->current++) { + const struct cache_entry *ce = suc->list.entries[suc->current]; + if (prepare_to_clone_next_submodule(ce, child, suc, err)) { + suc->current++; + return 1; + } + } + return 0; +} + +static int update_clone_start_failure(struct strbuf *err, + void *suc_cb, + void *void_task_cb) +{ + struct submodule_update_clone *suc = suc_cb; + suc->quickstop = 1; + return 1; +} + +static int update_clone_task_finished(int result, + struct strbuf *err, + void *suc_cb, + void *void_task_cb) +{ + struct submodule_update_clone *suc = suc_cb; + + if (!result) + return 0; + + suc->quickstop = 1; + return 1; +} + +static int update_clone(int argc, const char **argv, const char *prefix) +{ + const char *update = NULL; + int max_jobs = -1; + struct string_list_item *item; + struct pathspec pathspec; + struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT; + + struct option module_update_clone_options[] = { + OPT_STRING(0, "prefix", &prefix, + N_("path"), + N_("path into the working tree")), + OPT_STRING(0, "recursive-prefix", &suc.recursive_prefix, + N_("path"), + N_("path into the working tree, across nested " + "submodule boundaries")), + OPT_STRING(0, "update", &update, + N_("string"), + N_("rebase, merge, checkout or none")), + OPT_STRING(0, "reference", &suc.reference, N_("repo"), + N_("reference repository")), + OPT_STRING(0, "depth", &suc.depth, "", + N_("Create a shallow clone truncated to the " + "specified number of revisions")), + OPT_INTEGER('j', "jobs", &max_jobs, + N_("parallel jobs")), + OPT__QUIET(&suc.quiet, N_("don't print cloning progress")), + OPT_END() + }; + + const char *const git_submodule_helper_usage[] = { + N_("git submodule--helper update_clone [--prefix=] [...]"), + NULL + }; + suc.prefix = prefix; + + argc = parse_options(argc, argv, prefix, module_update_clone_options, + git_submodule_helper_usage, 0); + + if (update) + if (parse_submodule_update_strategy(update, &suc.update) < 0) + die(_("bad value for update parameter")); + + if (module_list_compute(argc, argv, prefix, &pathspec, &suc.list) < 0) + return 1; + + if (pathspec.nr) + suc.warn_if_uninitialized = 1; + + /* Overlay the parsed .gitmodules file with .git/config */ + gitmodules_config(); + git_config(submodule_config, NULL); + + if (max_jobs < 0) + max_jobs = parallel_submodules(); + + run_processes_parallel(max_jobs, + update_clone_get_next_task, + update_clone_start_failure, + update_clone_task_finished, + &suc); + + /* + * We saved the output and put it out all at once now. + * That means: + * - the listener does not have to interleave their (checkout) + * work with our fetching. The writes involved in a + * checkout involve more straightforward sequential I/O. + * - the listener can avoid doing any work if fetching failed. + */ + if (suc.quickstop) + return 1; + + for_each_string_list_item(item, &suc.projectlines) + utf8_fprintf(stdout, "%s", item->string); + + return 0; +} + +static int resolve_relative_path(int argc, const char **argv, const char *prefix) +{ + struct strbuf sb = STRBUF_INIT; + if (argc != 3) + die("submodule--helper relative_path takes exactly 2 arguments, got %d", argc); + + printf("%s", relative_path(argv[1], argv[2], &sb)); + strbuf_release(&sb); + return 0; +} + struct cmd_struct { const char *cmd; int (*fn)(int, const char **, const char *); @@ -258,19 +851,24 @@ static struct cmd_struct commands[] = { {"list", module_list}, {"name", module_name}, {"clone", module_clone}, + {"update-clone", update_clone}, + {"relative-path", resolve_relative_path}, + {"resolve-relative-url", resolve_relative_url}, + {"resolve-relative-url-test", resolve_relative_url_test}, + {"init", module_init} }; int cmd_submodule__helper(int argc, const char **argv, const char *prefix) { int i; if (argc < 2) - die(_("fatal: submodule--helper subcommand must be " + die(_("submodule--helper subcommand must be " "called with a subcommand")); for (i = 0; i < ARRAY_SIZE(commands); i++) if (!strcmp(argv[1], commands[i].cmd)) return commands[i].fn(argc - 1, argv + 1, prefix); - die(_("fatal: '%s' is not a valid submodule--helper " + die(_("'%s' is not a valid submodule--helper " "subcommand"), argv[1]); } diff --git a/builtin/tag.c b/builtin/tag.c index 1705c94665..50e4ae5678 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -29,6 +29,7 @@ static const char * const git_tag_usage[] = { }; static unsigned int colopts; +static int force_sign_annotate; static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, const char *format) { @@ -104,13 +105,7 @@ static int delete_tag(const char *name, const char *ref, static int verify_tag(const char *name, const char *ref, const unsigned char *sha1) { - const char *argv_verify_tag[] = {"verify-tag", - "-v", "SHA1_HEX", NULL}; - argv_verify_tag[2] = sha1_to_hex(sha1); - - if (run_command_v_opt(argv_verify_tag, RUN_GIT_CMD)) - return error(_("could not verify the tag '%s'"), name); - return 0; + return gpg_verify_tag(sha1, name, GPG_VERIFY_VERBOSE); } static int do_sign(struct strbuf *buffer) @@ -166,6 +161,11 @@ static int git_tag_config(const char *var, const char *value, void *cb) status = git_gpg_config(var, value, cb); if (status) return status; + if (!strcmp(var, "tag.forcesignannotated")) { + force_sign_annotate = git_config_bool(var, value); + return 0; + } + if (starts_with(var, "column.")) return git_column_config(var, value, "tag", &colopts); return git_default_config(var, value, cb); @@ -327,7 +327,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) char *cleanup_arg = NULL; int create_reflog = 0; int annotate = 0, force = 0; - int cmdmode = 0; + int cmdmode = 0, create_tag_object = 0; const char *msgfile = NULL, *keyid = NULL; struct msg_arg msg = { 0, STRBUF_INIT }; struct ref_transaction *transaction; @@ -385,12 +385,12 @@ int cmd_tag(int argc, const char **argv, const char *prefix) opt.sign = 1; set_signing_key(keyid); } - if (opt.sign) - annotate = 1; + create_tag_object = (opt.sign || annotate || msg.given || msgfile); + if (argc == 0 && !cmdmode) cmdmode = 'l'; - if ((annotate || msg.given || msgfile || force) && (cmdmode != 0)) + if ((create_tag_object || force) && (cmdmode != 0)) usage_with_options(git_tag_usage, options); finalize_colopts(&colopts, -1); @@ -431,7 +431,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (msg.given || msgfile) { if (msg.given && msgfile) die(_("only one -F or -m option is allowed.")); - annotate = 1; if (msg.given) strbuf_addbuf(&buf, &(msg.buf)); else { @@ -474,8 +473,11 @@ int cmd_tag(int argc, const char **argv, const char *prefix) else die(_("Invalid cleanup mode %s"), cleanup_arg); - if (annotate) + if (create_tag_object) { + if (force_sign_annotate && !annotate) + opt.sign = 1; create_tag(object, tag, &buf, &opt, prev, object); + } transaction = ref_transaction_begin(&err); if (!transaction || diff --git a/builtin/update-index.c b/builtin/update-index.c index 1c94ca59bf..b8b8522249 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -255,7 +255,7 @@ static int process_lstat_error(const char *path, int err) { if (err == ENOENT || err == ENOTDIR) return remove_one_path(path); - return error("lstat(\"%s\"): %s", path, strerror(errno)); + return error("lstat(\"%s\"): %s", path, strerror(err)); } static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st) diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index dbfe14f3fe..2caedf1849 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -104,8 +104,7 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix) pfd[1].events = POLLIN; if (poll(pfd, 2, -1) < 0) { if (errno != EINTR) { - error("poll failed resuming: %s", - strerror(errno)); + error_errno("poll failed resuming"); sleep(1); } continue; diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index 00663f6a30..99f8148cf7 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -18,55 +18,6 @@ static const char * const verify_tag_usage[] = { NULL }; -static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags) -{ - struct signature_check sigc; - int len; - int ret; - - memset(&sigc, 0, sizeof(sigc)); - - len = parse_signature(buf, size); - - if (size == len) { - if (flags & GPG_VERIFY_VERBOSE) - write_in_full(1, buf, len); - return error("no signature found"); - } - - ret = check_signature(buf, len, buf + len, size - len, &sigc); - print_signature_buffer(&sigc, flags); - - signature_check_clear(&sigc); - return ret; -} - -static int verify_tag(const char *name, unsigned flags) -{ - enum object_type type; - unsigned char sha1[20]; - char *buf; - unsigned long size; - int ret; - - if (get_sha1(name, sha1)) - return error("tag '%s' not found.", name); - - type = sha1_object_info(sha1, NULL); - if (type != OBJ_TAG) - return error("%s: cannot verify a non-tag object of type %s.", - name, typename(type)); - - buf = read_sha1_file(sha1, &type, &size); - if (!buf) - return error("%s: unable to read file.", name); - - ret = run_gpg_verify(buf, size, flags); - - free(buf); - return ret; -} - static int git_verify_tag_config(const char *var, const char *value, void *cb) { int status = git_gpg_config(var, value, cb); @@ -95,11 +46,13 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) if (verbose) flags |= GPG_VERIFY_VERBOSE; - /* sometimes the program was terminated because this signal - * was received in the process of writing the gpg input: */ - signal(SIGPIPE, SIG_IGN); - while (i < argc) - if (verify_tag(argv[i++], flags)) + while (i < argc) { + unsigned char sha1[20]; + const char *name = argv[i++]; + if (get_sha1(name, sha1)) + had_error = !!error("tag '%s' not found.", name); + else if (gpg_verify_tag(sha1, name, flags)) had_error = 1; + } return had_error; } diff --git a/builtin/worktree.c b/builtin/worktree.c index 38b56096bd..96a2834a18 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -21,6 +21,7 @@ static const char * const worktree_usage[] = { struct add_opts { int force; int detach; + int checkout; const char *new_branch; int force_new_branch; }; @@ -109,7 +110,7 @@ static void prune_worktrees(void) if (ret < 0 && errno == ENOTDIR) ret = unlink(path.buf); if (ret) - error(_("failed to remove: %s"), strerror(errno)); + error_errno(_("failed to remove '%s'"), path.buf); } closedir(dir); if (!show_only) @@ -204,7 +205,7 @@ static int add_worktree(const char *path, const char *refname, if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) && ref_exists(symref.buf)) { /* it's a branch */ if (!opts->force) - die_if_checked_out(symref.buf); + die_if_checked_out(symref.buf, 0); } else { /* must be a commit */ commit = lookup_commit_reference_by_name(refname); if (!commit) @@ -284,18 +285,22 @@ static int add_worktree(const char *path, const char *refname, if (ret) goto done; - cp.argv = NULL; - argv_array_clear(&cp.args); - argv_array_pushl(&cp.args, "reset", "--hard", NULL); - cp.env = child_env.argv; - ret = run_command(&cp); - if (!ret) { - is_junk = 0; - free(junk_work_tree); - free(junk_git_dir); - junk_work_tree = NULL; - junk_git_dir = NULL; + if (opts->checkout) { + cp.argv = NULL; + argv_array_clear(&cp.args); + argv_array_pushl(&cp.args, "reset", "--hard", NULL); + cp.env = child_env.argv; + ret = run_command(&cp); + if (ret) + goto done; } + + is_junk = 0; + free(junk_work_tree); + free(junk_git_dir); + junk_work_tree = NULL; + junk_git_dir = NULL; + done: strbuf_reset(&sb); strbuf_addf(&sb, "%s/locked", sb_repo.buf); @@ -320,10 +325,12 @@ static int add(int ac, const char **av, const char *prefix) OPT_STRING('B', NULL, &new_branch_force, N_("branch"), N_("create or reset a branch")), OPT_BOOL(0, "detach", &opts.detach, N_("detach HEAD at named commit")), + OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")), OPT_END() }; memset(&opts, 0, sizeof(opts)); + opts.checkout = 1; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); if (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1) die(_("-b, -B, and --detach are mutually exclusive")); @@ -342,7 +349,7 @@ static int add(int ac, const char **av, const char *prefix) if (!opts.force && !strbuf_check_branch_ref(&symref, opts.new_branch) && ref_exists(symref.buf)) - die_if_checked_out(symref.buf); + die_if_checked_out(symref.buf, 0); strbuf_release(&symref); } diff --git a/bundle.c b/bundle.c index 506ac49691..bbf4efa0a0 100644 --- a/bundle.c +++ b/bundle.c @@ -435,12 +435,14 @@ int create_bundle(struct bundle_header *header, const char *path, /* write prerequisites */ if (compute_and_write_prerequisites(bundle_fd, &revs, argc, argv)) - return -1; + goto err; argc = setup_revisions(argc, argv, &revs, NULL); - if (argc > 1) - return error(_("unrecognized argument: %s"), argv[1]); + if (argc > 1) { + error(_("unrecognized argument: %s"), argv[1]); + goto err; + } object_array_remove_duplicates(&revs.pending); @@ -448,17 +450,26 @@ int create_bundle(struct bundle_header *header, const char *path, if (!ref_count) die(_("Refusing to create empty bundle.")); else if (ref_count < 0) - return -1; + goto err; /* write pack */ - if (write_pack_data(bundle_fd, &revs)) - return -1; + if (write_pack_data(bundle_fd, &revs)) { + bundle_fd = -1; /* already closed by the above call */ + goto err; + } if (!bundle_to_stdout) { if (commit_lock_file(&lock)) die_errno(_("cannot create '%s'"), path); } return 0; +err: + if (!bundle_to_stdout) { + if (0 <= bundle_fd) + close(bundle_fd); + rollback_lock_file(&lock); + } + return -1; } int unbundle(struct bundle_header *header, int bundle_fd, int flags) diff --git a/cache-tree.c b/cache-tree.c index 3ebf9c3aa4..ddf0cc9f9a 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -663,7 +663,7 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) cnt++; else { struct cache_tree_sub *sub; - struct tree *subtree = lookup_tree(entry.sha1); + struct tree *subtree = lookup_tree(entry.oid->hash); if (!subtree->object.parsed) parse_tree(subtree); sub = cache_tree_sub(it, entry.path); @@ -710,7 +710,7 @@ int cache_tree_matches_traversal(struct cache_tree *root, it = find_cache_tree_from_traversal(root, info); it = cache_tree_find(it, ent->path); - if (it && it->entry_count > 0 && !hashcmp(ent->sha1, it->sha1)) + if (it && it->entry_count > 0 && !hashcmp(ent->oid->hash, it->sha1)) return it->entry_count; return 0; } diff --git a/cache.h b/cache.h index b829410f6d..6049f86711 100644 --- a/cache.h +++ b/cache.h @@ -651,10 +651,10 @@ extern int prefer_symlink_refs; extern int log_all_ref_updates; extern int warn_ambiguous_refs; extern int warn_on_object_refname_ambiguity; -extern int shared_repository; extern const char *apply_default_whitespace; extern const char *apply_default_ignorewhitespace; extern const char *git_attributes_file; +extern const char *git_hooks_path; extern int zlib_compression_level; extern int core_compression_level; extern int core_compression_seen; @@ -664,6 +664,9 @@ extern size_t delta_base_cache_limit; extern unsigned long big_file_threshold; extern unsigned long pack_size_limit_cfg; +void set_shared_repository(int value); +int get_shared_repository(void); + /* * Do replace refs need to be checked this run? This variable is * initialized to true unless --no-replace-object is used or @@ -698,6 +701,14 @@ extern int ref_paranoia; extern char comment_line_char; extern int auto_comment_line_char; +/* Windows only */ +enum hide_dotfiles_type { + HIDE_DOTFILES_FALSE = 0, + HIDE_DOTFILES_TRUE, + HIDE_DOTFILES_DOTGITONLY +}; +extern enum hide_dotfiles_type hide_dotfiles; + enum branch_track { BRANCH_TRACK_UNSPECIFIED = -1, BRANCH_TRACK_NEVER = 0, @@ -745,9 +756,39 @@ extern int grafts_replace_parents; */ #define GIT_REPO_VERSION 0 #define GIT_REPO_VERSION_READ 1 -extern int repository_format_version; extern int repository_format_precious_objects; -extern int check_repository_format(void); + +struct repository_format { + int version; + int precious_objects; + int is_bare; + char *work_tree; + struct string_list unknown_extensions; +}; + +/* + * Read the repository format characteristics from the config file "path" into + * "format" struct. Returns the numeric version. On error, -1 is returned, + * format->version is set to -1, and all other fields in the struct are + * undefined. + */ +int read_repository_format(struct repository_format *format, const char *path); + +/* + * Verify that the repository described by repository_format is something we + * can read. If it is, return 0. Otherwise, return -1, and "err" will describe + * any errors encountered. + */ +int verify_repository_format(const struct repository_format *format, + struct strbuf *err); + +/* + * Check the repository format version in the path found in get_git_dir(), + * and die if it is a version we don't understand. Generally one would + * set_git_dir() before calling this, and use it only for "are we in a valid + * repo?". + */ +extern void check_repository_format(void); #define MTIME_CHANGED 0x0001 #define CTIME_CHANGED 0x0002 @@ -767,11 +808,14 @@ extern int check_repository_format(void); */ extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +extern const char *git_common_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern char *mksnpath(char *buf, size_t n, const char *fmt, ...) __attribute__((format (printf, 3, 4))); extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +extern void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...) + __attribute__((format (printf, 2, 3))); extern char *git_path_buf(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3))); extern void strbuf_git_path_submodule(struct strbuf *sb, const char *path, @@ -926,8 +970,6 @@ static inline int is_empty_blob_sha1(const unsigned char *sha1) int git_mkstemp(char *path, size_t n, const char *template); -int git_mkstemps(char *path, size_t n, const char *template, int suffix_len); - /* set default permissions by passing mode arguments to open(2) */ int git_mkstemps_mode(char *pattern, int suffix_len, int mode); int git_mkstemp_mode(char *pattern, int mode); @@ -1124,6 +1166,8 @@ extern int get_sha1_blob(const char *str, unsigned char *sha1); extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix); extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc); +extern int get_oid(const char *str, struct object_id *oid); + typedef int each_abbrev_fn(const unsigned char *sha1, void *); extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *); @@ -1526,7 +1570,6 @@ extern void git_config(config_fn_t fn, void *); extern int git_config_with_options(config_fn_t fn, void *, struct git_config_source *config_source, int respect_includes); -extern int git_config_early(config_fn_t fn, void *, const char *repo_config); extern int git_parse_ulong(const char *, unsigned long *); extern int git_parse_maybe_bool(const char *); extern int git_config_int(const char *, const char *); @@ -1550,7 +1593,6 @@ extern void git_config_set_multivar_in_file(const char *, const char *, const ch extern int git_config_rename_section(const char *, const char *); extern int git_config_rename_section_in_file(const char *, const char *, const char *); extern const char *git_etc_gitconfig(void); -extern int check_repository_format_version(const char *var, const char *value, void *cb); extern int git_env_bool(const char *, int); extern unsigned long git_env_ulong(const char *, unsigned long); extern int git_config_system(void); @@ -1736,8 +1778,8 @@ int add_files_to_cache(const char *prefix, const struct pathspec *pathspec, int extern int diff_auto_refresh_index; /* match-trees.c */ -void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int); -void shift_tree_by(const unsigned char *, const unsigned char *, unsigned char *, const char *); +void shift_tree(const struct object_id *, const struct object_id *, struct object_id *, int); +void shift_tree_by(const struct object_id *, const struct object_id *, struct object_id *, const char *); /* * whitespace rules. @@ -1771,7 +1813,7 @@ int split_cmdline(char *cmdline, const char ***argv); /* Takes a negative value returned by split_cmdline */ const char *split_cmdline_strerror(int cmdline_errno); -/* git.c */ +/* setup.c */ struct startup_info { int have_repository; const char *prefix; diff --git a/check-racy.c b/check-racy.c index 00d92a1663..24b6542352 100644 --- a/check-racy.c +++ b/check-racy.c @@ -12,7 +12,7 @@ int main(int ac, char **av) struct stat st; if (lstat(ce->name, &st)) { - error("lstat(%s): %s", ce->name, strerror(errno)); + error_errno("lstat(%s)", ce->name); continue; } diff --git a/ci/test-documentation.sh b/ci/test-documentation.sh new file mode 100755 index 0000000000..579d540d32 --- /dev/null +++ b/ci/test-documentation.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Perform sanity checks on documentation and build it. +# + +set -e + +make check-builtins +make check-docs +make doc + +test -s Documentation/git.html +test -s Documentation/git.xml +test -s Documentation/git.1 diff --git a/combine-diff.c b/combine-diff.c index 0e1d4b0893..8f2313d502 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -1005,8 +1005,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, struct strbuf buf = STRBUF_INIT; if (strbuf_readlink(&buf, elem->path, st.st_size) < 0) { - error("readlink(%s): %s", elem->path, - strerror(errno)); + error_errno("readlink(%s)", elem->path); return; } result_size = buf.len; diff --git a/commit.h b/commit.h index 5d58be0017..b06db4d5d9 100644 --- a/commit.h +++ b/commit.h @@ -147,6 +147,7 @@ struct pretty_print_context { int preserve_subject; struct date_mode date_mode; unsigned date_mode_explicit:1; + int expand_tabs_in_log; int need_8bit_cte; char *notes_message; struct reflog_walk_info *reflog_info; diff --git a/compat/apple-common-crypto.h b/compat/apple-common-crypto.h index d3fb264181..11727f3e1e 100644 --- a/compat/apple-common-crypto.h +++ b/compat/apple-common-crypto.h @@ -3,12 +3,18 @@ #define HEADER_HMAC_H #define HEADER_SHA_H #include -#define HMAC_CTX CCHmacContext -#define HMAC_Init(hmac, key, len, algo) CCHmacInit(hmac, algo, key, len) -#define HMAC_Update CCHmacUpdate -#define HMAC_Final(hmac, hash, ptr) CCHmacFinal(hmac, hash) -#define HMAC_CTX_cleanup(ignore) #define EVP_md5(...) kCCHmacAlgMD5 +/* CCHmac doesn't take md_len and the return type is void */ +#define HMAC git_CC_HMAC +static inline unsigned char *git_CC_HMAC(CCHmacAlgorithm alg, + const void *key, int key_len, + const unsigned char *data, size_t data_len, + unsigned char *md, unsigned int *md_len) +{ + CCHmac(alg, key, key_len, data, data_len, md); + return md; +} + #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 #define APPLE_LION_OR_NEWER #include diff --git a/compat/mingw.c b/compat/mingw.c index 54c82ecf20..a8218e6f0f 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -286,6 +286,49 @@ int mingw_rmdir(const char *pathname) return ret; } +static inline int needs_hiding(const char *path) +{ + const char *basename; + + if (hide_dotfiles == HIDE_DOTFILES_FALSE) + return 0; + + /* We cannot use basename(), as it would remove trailing slashes */ + mingw_skip_dos_drive_prefix((char **)&path); + if (!*path) + return 0; + + for (basename = path; *path; path++) + if (is_dir_sep(*path)) { + do { + path++; + } while (is_dir_sep(*path)); + /* ignore trailing slashes */ + if (*path) + basename = path; + } + + if (hide_dotfiles == HIDE_DOTFILES_TRUE) + return *basename == '.'; + + assert(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY); + return !strncasecmp(".git", basename, 4) && + (!basename[4] || is_dir_sep(basename[4])); +} + +static int set_hidden_flag(const wchar_t *path, int set) +{ + DWORD original = GetFileAttributesW(path), modified; + if (set) + modified = original | FILE_ATTRIBUTE_HIDDEN; + else + modified = original & ~FILE_ATTRIBUTE_HIDDEN; + if (original == modified || SetFileAttributesW(path, modified)) + return 0; + errno = err_win_to_posix(GetLastError()); + return -1; +} + int mingw_mkdir(const char *path, int mode) { int ret; @@ -293,6 +336,8 @@ int mingw_mkdir(const char *path, int mode) if (xutftowcs_path(wpath, path) < 0) return -1; ret = _wmkdir(wpath); + if (!ret && needs_hiding(path)) + return set_hidden_flag(wpath, 1); return ret; } @@ -319,6 +364,21 @@ int mingw_open (const char *filename, int oflags, ...) if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) errno = EISDIR; } + if ((oflags & O_CREAT) && needs_hiding(filename)) { + /* + * Internally, _wopen() uses the CreateFile() API which errors + * out with an ERROR_ACCESS_DENIED if CREATE_ALWAYS was + * specified and an already existing file's attributes do not + * match *exactly*. As there is no mode or flag we can set that + * would correspond to FILE_ATTRIBUTE_HIDDEN, let's just try + * again *without* the O_CREAT flag (that corresponds to the + * CREATE_ALWAYS flag of CreateFile()). + */ + if (fd < 0 && errno == EACCES) + fd = _wopen(wfilename, oflags & ~O_CREAT, mode); + if (fd >= 0 && set_hidden_flag(wfilename, 1)) + warning("could not mark '%s' as hidden.", filename); + } return fd; } @@ -350,6 +410,7 @@ int mingw_fgetc(FILE *stream) #undef fopen FILE *mingw_fopen (const char *filename, const char *otype) { + int hide = needs_hiding(filename); FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; if (filename && !strcmp(filename, "/dev/null")) @@ -357,12 +418,19 @@ FILE *mingw_fopen (const char *filename, const char *otype) if (xutftowcs_path(wfilename, filename) < 0 || xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0) return NULL; + if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) { + error("could not unhide %s", filename); + return NULL; + } file = _wfopen(wfilename, wotype); + if (file && hide && set_hidden_flag(wfilename, 1)) + warning("could not mark '%s' as hidden.", filename); return file; } FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream) { + int hide = needs_hiding(filename); FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; if (filename && !strcmp(filename, "/dev/null")) @@ -370,7 +438,13 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream) if (xutftowcs_path(wfilename, filename) < 0 || xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0) return NULL; + if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) { + error("could not unhide %s", filename); + return NULL; + } file = _wfreopen(wfilename, wotype, stream); + if (file && hide && set_hidden_flag(wfilename, 1)) + warning("could not mark '%s' as hidden.", filename); return file; } @@ -763,15 +837,12 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) char *mingw_getcwd(char *pointer, int len) { - int i; wchar_t wpointer[MAX_PATH]; if (!_wgetcwd(wpointer, ARRAY_SIZE(wpointer))) return NULL; if (xwcstoutf(pointer, wpointer, len) < 0) return NULL; - for (i = 0; pointer[i]; i++) - if (pointer[i] == '\\') - pointer[i] = '/'; + convert_slashes(pointer); return pointer; } @@ -2112,9 +2183,7 @@ static void setup_windows_environment() * executable (by not mistaking the dir separators * for escape characters). */ - for (; *tmp; tmp++) - if (*tmp == '\\') - *tmp = '/'; + convert_slashes(tmp); } /* simulate TERM to enable auto-color (see color.c) */ diff --git a/compat/mingw.h b/compat/mingw.h index c008694639..69bb43dc35 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -142,6 +142,7 @@ static inline int fcntl(int fd, int cmd, ...) #define sigemptyset(x) (void)0 static inline int sigaddset(sigset_t *set, int signum) { return 0; } +#define SIG_BLOCK 0 #define SIG_UNBLOCK 0 static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) { return 0; } @@ -406,7 +407,7 @@ static inline void convert_slashes(char *path) int mingw_offset_1st_component(const char *path); #define offset_1st_component mingw_offset_1st_component #define PATH_SEP ';' -#ifndef __MINGW64_VERSION_MAJOR +#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800) #define PRIuMAX "I64u" #define PRId64 "I64d" #else @@ -416,9 +417,6 @@ int mingw_offset_1st_component(const char *path); void mingw_open_html(const char *path); #define open_html mingw_open_html -void mingw_mark_as_git_dir(const char *dir); -#define mark_as_git_dir mingw_mark_as_git_dir - /** * Converts UTF-8 encoded string to UTF-16LE. * diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c index dfbe6d8408..4293b53b17 100644 --- a/compat/precompose_utf8.c +++ b/compat/precompose_utf8.c @@ -147,7 +147,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir) if (errno || inleft) { /* * iconv() failed and errno could be E2BIG, EILSEQ, EINVAL, EBADF - * MacOS X avoids illegal byte sequemces. + * MacOS X avoids illegal byte sequences. * If they occur on a mounted drive (e.g. NFS) it is not worth to * die() for that, but rather let the user see the original name */ diff --git a/compat/snprintf.c b/compat/snprintf.c index 42ea1ac110..0b11688537 100644 --- a/compat/snprintf.c +++ b/compat/snprintf.c @@ -9,7 +9,7 @@ * always have room for a trailing NUL byte. */ #ifndef SNPRINTF_SIZE_CORR -#if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) +#if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) && (!defined(_MSC_VER) || _MSC_VER < 1900) #define SNPRINTF_SIZE_CORR 1 #else #define SNPRINTF_SIZE_CORR 0 diff --git a/compat/vcbuild/include/unistd.h b/compat/vcbuild/include/unistd.h index c65c2cd566..3a959d124c 100644 --- a/compat/vcbuild/include/unistd.h +++ b/compat/vcbuild/include/unistd.h @@ -45,11 +45,15 @@ typedef unsigned long long uintmax_t; typedef int64_t off64_t; +#if !defined(_MSC_VER) || _MSC_VER < 1600 #define INTMAX_MIN _I64_MIN #define INTMAX_MAX _I64_MAX #define UINTMAX_MAX _UI64_MAX #define UINT32_MAX 0xffffffff /* 4294967295U */ +#else +#include +#endif #define STDIN_FILENO 0 #define STDOUT_FILENO 1 diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h index b6ed9e7462..1c164088fb 100644 --- a/compat/win32/pthread.h +++ b/compat/win32/pthread.h @@ -104,4 +104,11 @@ static inline void *pthread_getspecific(pthread_key_t key) return TlsGetValue(key); } +#ifndef __MINGW64_VERSION_MAJOR +static inline int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + return 0; +} +#endif + #endif /* PTHREAD_H */ diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c index b905aea31b..6c7c9b6053 100644 --- a/compat/win32/syslog.c +++ b/compat/win32/syslog.c @@ -28,13 +28,13 @@ void syslog(int priority, const char *fmt, ...) va_end(ap); if (str_len < 0) { - warning("vsnprintf failed: '%s'", strerror(errno)); + warning_errno("vsnprintf failed"); return; } str = malloc(st_add(str_len, 1)); if (!str) { - warning("malloc failed: '%s'", strerror(errno)); + warning_errno("malloc failed"); return; } @@ -45,7 +45,7 @@ void syslog(int priority, const char *fmt, ...) while ((pos = strstr(str, "%1")) != NULL) { str = realloc(str, st_add(++str_len, 1)); if (!str) { - warning("realloc failed: '%s'", strerror(errno)); + warning_errno("realloc failed"); return; } memmove(pos + 2, pos + 1, strlen(pos)); diff --git a/compat/win32mmap.c b/compat/win32mmap.c index 80a8c9af4f..519d51f2b6 100644 --- a/compat/win32mmap.c +++ b/compat/win32mmap.c @@ -2,37 +2,42 @@ void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { - HANDLE hmap; + HANDLE osfhandle, hmap; void *temp; - off_t len; - struct stat st; + LARGE_INTEGER len; uint64_t o = offset; uint32_t l = o & 0xFFFFFFFF; uint32_t h = (o >> 32) & 0xFFFFFFFF; - if (!fstat(fd, &st)) - len = st.st_size; - else + osfhandle = (HANDLE)_get_osfhandle(fd); + if (!GetFileSizeEx(osfhandle, &len)) die("mmap: could not determine filesize"); - if ((length + offset) > len) - length = xsize_t(len - offset); + if ((length + offset) > len.QuadPart) + length = xsize_t(len.QuadPart - offset); if (!(flags & MAP_PRIVATE)) die("Invalid usage of mmap when built with USE_WIN32_MMAP"); - hmap = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, - PAGE_WRITECOPY, 0, 0, NULL); + hmap = CreateFileMapping(osfhandle, NULL, + prot == PROT_READ ? PAGE_READONLY : PAGE_WRITECOPY, 0, 0, NULL); - if (!hmap) + if (!hmap) { + errno = EINVAL; return MAP_FAILED; + } - temp = MapViewOfFileEx(hmap, FILE_MAP_COPY, h, l, length, start); + temp = MapViewOfFileEx(hmap, prot == PROT_READ ? + FILE_MAP_READ : FILE_MAP_COPY, h, l, length, start); if (!CloseHandle(hmap)) warning("unable to close file mapping handle"); - return temp ? temp : MAP_FAILED; + if (temp) + return temp; + + errno = GetLastError() == ERROR_COMMITMENT_LIMIT ? EFBIG : EINVAL; + return MAP_FAILED; } int git_munmap(void *start, size_t length) diff --git a/compat/winansi.c b/compat/winansi.c index 5dfa5ed61f..3be60ce1c6 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -483,6 +483,7 @@ static size_t sizeof_ioinfo = 0; #define IOINFO_L2E 5 #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) +#define FPIPE 0x08 #define FDEV 0x40 static inline ioinfo* _pioinfo(int fd) @@ -530,6 +531,45 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle) return old_handle; } +#ifdef DETECT_MSYS_TTY + +#include +#include + +static void detect_msys_tty(int fd) +{ + ULONG result; + BYTE buffer[1024]; + POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer; + PWSTR name; + + /* check if fd is a pipe */ + HANDLE h = (HANDLE) _get_osfhandle(fd); + if (GetFileType(h) != FILE_TYPE_PIPE) + return; + + /* get pipe name */ + if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation, + buffer, sizeof(buffer) - 2, &result))) + return; + name = nameinfo->Name.Buffer; + name[nameinfo->Name.Length] = 0; + + /* check if this could be a MSYS2 pty pipe ('msys-XXXX-ptyN-XX') */ + if (!wcsstr(name, L"msys-") || !wcsstr(name, L"-pty")) + return; + + /* init ioinfo size if we haven't done so */ + if (init_sizeof_ioinfo()) + return; + + /* set FDEV flag, reset FPIPE flag */ + _pioinfo(fd)->osflags &= ~FPIPE; + _pioinfo(fd)->osflags |= FDEV; +} + +#endif + void winansi_init(void) { int con1, con2; @@ -538,8 +578,15 @@ void winansi_init(void) /* check if either stdout or stderr is a console output screen buffer */ con1 = is_console(1); con2 = is_console(2); - if (!con1 && !con2) + if (!con1 && !con2) { +#ifdef DETECT_MSYS_TTY + /* check if stdin / stdout / stderr are MSYS2 pty pipes */ + detect_msys_tty(0); + detect_msys_tty(1); + detect_msys_tty(2); +#endif return; + } /* create a named pipe to communicate with the console thread */ xsnprintf(name, sizeof(name), "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId()); @@ -575,8 +622,11 @@ void winansi_init(void) HANDLE winansi_get_osfhandle(int fd) { HANDLE hnd = (HANDLE) _get_osfhandle(fd); - if ((fd == 1 || fd == 2) && isatty(fd) - && GetFileType(hnd) == FILE_TYPE_PIPE) - return (fd == 1) ? hconsole1 : hconsole2; + if (isatty(fd) && GetFileType(hnd) == FILE_TYPE_PIPE) { + if (fd == 1 && hconsole1) + return hconsole1; + else if (fd == 2 && hconsole2) + return hconsole2; + } return hnd; } diff --git a/config.c b/config.c index 9ba40bc1b0..f51c56bf92 100644 --- a/config.c +++ b/config.c @@ -108,7 +108,7 @@ static int handle_path_include(const char *path, struct config_include_data *inc expanded = expand_user_path(path); if (!expanded) - return error("Could not expand include path '%s'", path); + return error("could not expand include path '%s'", path); path = expanded; /* @@ -162,7 +162,7 @@ void git_config_push_parameter(const char *text) { struct strbuf env = STRBUF_INIT; const char *old = getenv(CONFIG_DATA_ENVIRONMENT); - if (old) { + if (old && *old) { strbuf_addstr(&env, old); strbuf_addch(&env, ' '); } @@ -717,6 +717,9 @@ static int git_default_core_config(const char *var, const char *value) if (!strcmp(var, "core.attributesfile")) return git_config_pathname(&git_attributes_file, var, value); + if (!strcmp(var, "core.hookspath")) + return git_config_pathname(&git_hooks_path, var, value); + if (!strcmp(var, "core.bare")) { is_bare_repository_cfg = git_config_bool(var, value); return 0; @@ -803,8 +806,6 @@ static int git_default_core_config(const char *var, const char *value) if (!strcmp(var, "core.autocrlf")) { if (value && !strcasecmp(value, "input")) { - if (core_eol == EOL_CRLF) - return error("core.autocrlf=input conflicts with core.eol=crlf"); auto_crlf = AUTO_CRLF_INPUT; return 0; } @@ -830,8 +831,6 @@ static int git_default_core_config(const char *var, const char *value) core_eol = EOL_NATIVE; else core_eol = EOL_UNSET; - if (core_eol == EOL_CRLF && auto_crlf == AUTO_CRLF_INPUT) - return error("core.autocrlf=input conflicts with core.eol=crlf"); return 0; } @@ -912,6 +911,14 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.hidedotfiles")) { + if (value && !strcasecmp(value, "dotgitonly")) + hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; + else + hide_dotfiles = git_config_bool(var, value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } @@ -950,7 +957,7 @@ static int git_default_branch_config(const char *var, const char *value) else if (!strcmp(value, "always")) autorebase = AUTOREBASE_ALWAYS; else - return error("Malformed value for %s", var); + return error("malformed value for %s", var); return 0; } @@ -976,7 +983,7 @@ static int git_default_push_config(const char *var, const char *value) else if (!strcmp(value, "current")) push_default = PUSH_DEFAULT_CURRENT; else { - error("Malformed value for %s: %s", var, value); + error("malformed value for %s: %s", var, value); return error("Must be one of nothing, matching, simple, " "upstream or current."); } @@ -1188,11 +1195,12 @@ int git_config_system(void) return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0); } -int git_config_early(config_fn_t fn, void *data, const char *repo_config) +static int do_git_config_sequence(config_fn_t fn, void *data) { int ret = 0, found = 0; char *xdg_config = xdg_config_home("config"); char *user_config = expand_user_path("~/.gitconfig"); + char *repo_config = git_pathdup("config"); if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) { ret += git_config_from_file(fn, git_etc_gitconfig(), @@ -1228,6 +1236,7 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config) free(xdg_config); free(user_config); + free(repo_config); return ret == 0 ? found : ret; } @@ -1235,8 +1244,6 @@ int git_config_with_options(config_fn_t fn, void *data, struct git_config_source *config_source, int respect_includes) { - char *repo_config = NULL; - int ret; struct config_include_data inc = CONFIG_INCLUDE_INIT; if (respect_includes) { @@ -1257,11 +1264,7 @@ int git_config_with_options(config_fn_t fn, void *data, else if (config_source && config_source->blob) return git_config_from_blob_ref(fn, config_source->blob, data); - repo_config = git_pathdup("config"); - ret = git_config_early(fn, data, repo_config); - if (repo_config) - free(repo_config); - return ret; + return do_git_config_sequence(fn, data); } static void git_config_raw(config_fn_t fn, void *data) @@ -1313,14 +1316,11 @@ static struct config_set_element *configset_find_element(struct config_set *cs, struct config_set_element k; struct config_set_element *found_entry; char *normalized_key; - int ret; /* * `key` may come from the user, so normalize it before using it * for querying entries from the hashmap. */ - ret = git_config_parse_key(key, &normalized_key, NULL); - - if (ret) + if (git_config_parse_key(key, &normalized_key, NULL)) return NULL; hashmap_entry_init(&k, strhash(normalized_key)); @@ -2016,7 +2016,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, lock = xcalloc(1, sizeof(struct lock_file)); fd = hold_lock_file_for_update(lock, config_filename, 0); if (fd < 0) { - error("could not lock config file %s: %s", config_filename, strerror(errno)); + error_errno("could not lock config file %s", config_filename); free(store.key); ret = CONFIG_NO_LOCK; goto out_free; @@ -2030,8 +2030,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, free(store.key); if ( ENOENT != errno ) { - error("opening %s: %s", config_filename, - strerror(errno)); + error_errno("opening %s", config_filename); ret = CONFIG_INVALID_FILE; /* same as "invalid config file" */ goto out_free; } @@ -2115,8 +2114,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, if (contents == MAP_FAILED) { if (errno == ENODEV && S_ISDIR(st.st_mode)) errno = EISDIR; - error("unable to mmap '%s': %s", - config_filename, strerror(errno)); + error_errno("unable to mmap '%s'", config_filename); ret = CONFIG_INVALID_FILE; contents = NULL; goto out_free; @@ -2125,8 +2123,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, in_fd = -1; if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) { - error("chmod on %s failed: %s", - get_lock_file_path(lock), strerror(errno)); + error_errno("chmod on %s failed", get_lock_file_path(lock)); ret = CONFIG_NO_WRITE; goto out_free; } @@ -2182,8 +2179,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, } if (commit_lock_file(lock) < 0) { - error("could not write config file %s: %s", config_filename, - strerror(errno)); + error_errno("could not write config file %s", config_filename); ret = CONFIG_NO_WRITE; lock = NULL; goto out_free; @@ -2221,9 +2217,13 @@ void git_config_set_multivar_in_file(const char *config_filename, const char *key, const char *value, const char *value_regex, int multi_replace) { - if (git_config_set_multivar_in_file_gently(config_filename, key, value, - value_regex, multi_replace) < 0) - die(_("Could not set '%s' to '%s'"), key, value); + if (!git_config_set_multivar_in_file_gently(config_filename, key, value, + value_regex, multi_replace)) + return; + if (value) + die(_("could not set '%s' to '%s'"), key, value); + else + die(_("could not unset '%s'"), key); } int git_config_set_multivar_gently(const char *key, const char *value, @@ -2330,8 +2330,8 @@ int git_config_rename_section_in_file(const char *config_filename, fstat(fileno(config_file), &st); if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) { - ret = error("chmod on %s failed: %s", - get_lock_file_path(lock), strerror(errno)); + ret = error_errno("chmod on %s failed", + get_lock_file_path(lock)); goto out; } @@ -2385,8 +2385,8 @@ int git_config_rename_section_in_file(const char *config_filename, fclose(config_file); unlock_and_out: if (commit_lock_file(lock) < 0) - ret = error("could not write config file %s: %s", - config_filename, strerror(errno)); + ret = error_errno("could not write config file %s", + config_filename); out: free(filename_buf); return ret; @@ -2404,7 +2404,7 @@ int git_config_rename_section(const char *old_name, const char *new_name) #undef config_error_nonbool int config_error_nonbool(const char *var) { - return error("Missing value for '%s'", var); + return error("missing value for '%s'", var); } int parse_config_key(const char *var, diff --git a/config.mak.uname b/config.mak.uname index fe8096f8a6..a88f13989a 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -187,6 +187,7 @@ ifeq ($(uname_O),Cygwin) X = .exe UNRELIABLE_FSTAT = UnfortunatelyYes SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield + OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo endif ifeq ($(uname_S),FreeBSD) NEEDS_LIBICONV = YesPlease @@ -556,7 +557,8 @@ else BASIC_LDFLAGS += -Wl,--large-address-aware endif CC = gcc - COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 + COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY + EXTLIBS += -lntdll INSTALL = /bin/install NO_R_TO_GCC_LINKER = YesPlease INTERNAL_QSORT = YesPlease diff --git a/configure.ac b/configure.ac index 0cd9f4680b..c279025747 100644 --- a/configure.ac +++ b/configure.ac @@ -970,10 +970,6 @@ AC_CHECK_LIB([iconv], [locale_charset], [CHARSET_LIB=-lcharset])]) GIT_CONF_SUBST([CHARSET_LIB]) # -# Define NO_HMAC_CTX_CLEANUP=YesPlease if HMAC_CTX_cleanup is missing. -AC_CHECK_LIB([crypto], [HMAC_CTX_cleanup], - [], [GIT_CONF_SUBST([NO_HMAC_CTX_CLEANUP], [YesPlease])]) -# # Define HAVE_CLOCK_GETTIME=YesPlease if clock_gettime is available. GIT_CHECK_FUNC(clock_gettime, [HAVE_CLOCK_GETTIME=YesPlease], diff --git a/connected.c b/connected.c index 299c56090b..bf1b12e7ec 100644 --- a/connected.c +++ b/connected.c @@ -86,17 +86,14 @@ static int check_everything_connected_real(sha1_iterate_fn fn, memcpy(commit, sha1_to_hex(sha1), 40); if (write_in_full(rev_list.in, commit, 41) < 0) { if (errno != EPIPE && errno != EINVAL) - error(_("failed write to rev-list: %s"), - strerror(errno)); + error_errno(_("failed write to rev-list")); err = -1; break; } } while (!fn(cb_data, sha1)); - if (close(rev_list.in)) { - error(_("failed to close rev-list's stdin: %s"), strerror(errno)); - err = -1; - } + if (close(rev_list.in)) + err = error_errno(_("failed to close rev-list's stdin")); sigchain_pop(SIGPIPE); return finish_command(&rev_list) || err; diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index e3918c87e3..34024754d9 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1339,15 +1339,15 @@ _git_help () { case "$cur" in --*) - __gitcomp "--all --info --man --web" + __gitcomp "--all --guides --info --man --web" return ;; esac __git_compute_all_commands __gitcomp "$__git_all_commands $(__git_aliases) attributes cli core-tutorial cvs-migration - diffcore gitk glossary hooks ignore modules - namespaces repository-layout tutorial tutorial-2 + diffcore everyday gitk glossary hooks ignore modules + namespaces repository-layout revisions tutorial tutorial-2 workflows " } @@ -1458,6 +1458,7 @@ _git_log () --relative-date --date= --pretty= --format= --oneline --show-signature + --cherry-mark --cherry-pick --graph --decorate --decorate= diff --git a/contrib/hooks/multimail/CHANGES b/contrib/hooks/multimail/CHANGES index bc77e66b85..100cc7a6d3 100644 --- a/contrib/hooks/multimail/CHANGES +++ b/contrib/hooks/multimail/CHANGES @@ -1,3 +1,46 @@ +Release 1.3.1 (bugfix-only release) +=================================== + +* Generate links to commits in combined emails (it was done only for + commit emails in 1.3.0). + +* Fix broken links on PyPi. + +Release 1.3.0 +============= + +* New options multimailhook.htmlInIntro and multimailhook.htmlInFooter + now allow using HTML in the introduction and footer of emails (e.g. + for a more pleasant formatting or to insert a link to the commit on + a web interface). + +* A new option multimailhook.commitBrowseURL gives a simpler (and less + flexible) way to add a link to a web interface for commit emails + than multimailhook.htmlInIntro and multimailhook.htmlInFooter. + +* A new public function config.add_config_parameters was added to + allow custom hooks to set specific Git configuration variables + without modifying the configuration files. See an example in + post-receive.example. + +* Error handling for SMTP has been improved (we used to print Python + backtraces for legitimate errors). + +* The SMTP mailer can now check TLS certificates when the newly added + configuration variable multimailhook.smtpCACerts. + +* Python 3 portability has been improved. + +* The documentation's formatting has been improved. + +* The testsuite has been improved (we now use pyflakes to check for + errors in the code). + +This version has been tested with Python 2.4 and 2.6 to 3.5, and Git +v1.7.10-406-gdc801e7, 2.1.4 and 2.8.1.339.g3ad15fd. + +No change since 1.3 RC1. + Release 1.2.0 ============= diff --git a/contrib/hooks/multimail/CONTRIBUTING.rst b/contrib/hooks/multimail/CONTRIBUTING.rst index 09efdb059c..530ecbfcf1 100644 --- a/contrib/hooks/multimail/CONTRIBUTING.rst +++ b/contrib/hooks/multimail/CONTRIBUTING.rst @@ -1,3 +1,6 @@ +Contributing +============ + git-multimail is an open-source project, built by volunteers. We would welcome your help! @@ -6,9 +9,7 @@ and Matthieu Moy . Please note that although a copy of git-multimail is distributed in the "contrib" section of the main Git project, development takes place -in a separate git-multimail repository on GitHub: - - https://github.com/git-multimail/git-multimail +in a separate `git-multimail repository on GitHub`_. Whenever enough changes to git-multimail have accumulated, a new code-drop of git-multimail will be submitted for inclusion in the Git @@ -21,10 +22,12 @@ to the maintainers). Please sign off your patches as per the `Git project practice `__. -General discussion of git-multimail can take place on the main Git -mailing list, - - git@vger.kernel.org +General discussion of git-multimail can take place on the main `Git +mailing list`_. Please CC emails regarding git-multimail to the maintainers so that we don't overlook them. + + +.. _`git-multimail repository on GitHub`: https://github.com/git-multimail/git-multimail +.. _`Git mailing list`: git@vger.kernel.org diff --git a/contrib/hooks/multimail/README b/contrib/hooks/multimail/README index 55120685f0..0c91d19a57 100644 --- a/contrib/hooks/multimail/README +++ b/contrib/hooks/multimail/README @@ -1,5 +1,5 @@ -git-multimail (version 1.2.0) -============================= +git-multimail 1.3.1 +=================== .. image:: https://travis-ci.org/git-multimail/git-multimail.svg?branch=master :target: https://travis-ci.org/git-multimail/git-multimail @@ -127,6 +127,13 @@ changes of this type, please consider sharing them with the community.) +Troubleshooting/FAQ +------------------- + +Please read ``__ for frequently asked +questions and common issues with git-multimail. + + Configuration ------------- @@ -134,19 +141,16 @@ By default, git-multimail mostly takes its configuration from the following ``git config`` settings: multimailhook.environment - This describes the general environment of the repository. In most cases, you do not need to specify a value for this variable: `git-multimail` will autodetect which environment to use. Currently supported values: - * generic - + generic the username of the pusher is read from $USER or $USERNAME and the repository name is derived from the repository's path. - * gitolite - + gitolite the username of the pusher is read from $GL_USER, the repository name is read from $GL_REPO, and the From: header value is optionally read from gitolite.conf (see multimailhook.from). @@ -154,8 +158,7 @@ multimailhook.environment For more information about gitolite and git-multimail, read ``__ - * stash - + stash Environment to use when ``git-multimail`` is ran as an Atlassian BitBucket Server (formerly known as Atlassian Stash) hook. @@ -169,8 +172,7 @@ multimailhook.environment and repo come from these two command line flags, which must be specified. - * gerrit - + gerrit Environment to use when ``git-multimail`` is ran as a ``ref-updated`` Gerrit hook. @@ -205,14 +207,12 @@ multimailhook.environment * If none of the above apply, then ``generic`` is used. multimailhook.repoName - A short name of this Git repository, to be used in various places in the notification email text. The default is to use $GL_REPO for gitolite repositories, or otherwise to derive this value from the repository path name. multimailhook.mailingList - The list of email addresses to which notification emails should be sent, as RFC 2822 email addresses separated by commas. This configuration option can be multivalued. Leave it unset or set it @@ -221,7 +221,6 @@ multimailhook.mailingList specific types of notification email. multimailhook.refchangeList - The list of email addresses to which summary emails about reference changes should be sent, as RFC 2822 email addresses separated by commas. This configuration option can be @@ -231,7 +230,6 @@ multimailhook.refchangeList multimailhook.mailingList is set. multimailhook.announceList - The list of email addresses to which emails about new annotated tags should be sent, as RFC 2822 email addresses separated by commas. This configuration option can be multivalued. The @@ -241,7 +239,6 @@ multimailhook.announceList even if one of the other values is set. multimailhook.commitList - The list of email addresses to which emails about individual new commits should be sent, as RFC 2822 email addresses separated by commas. This configuration option can be multivalued. The @@ -251,7 +248,6 @@ multimailhook.commitList multimailhook.mailingList is set. multimailhook.announceShortlog - If this option is set to true, then emails about changes to annotated tags include a shortlog of changes since the previous tag. This can be useful if the annotated tags represent releases; @@ -261,7 +257,6 @@ multimailhook.announceShortlog rather than useful. Default is false. multimailhook.commitEmailFormat - The format of email messages for the individual commits, can be "text" or "html". In the latter case, the emails will include diffs using colorized HTML instead of plain text used by default. Note that this currently the @@ -274,8 +269,43 @@ multimailhook.commitEmailFormat the message starting with ``+++`` or ``---`` colored in red or green). -multimailhook.refchangeShowGraph + By default, all the message is HTML-escaped. See + ``multimailhook.htmlInIntro`` to change this behavior. + +multimailhook.commitBrowseURL + Used to generate a link to an online repository browser in commit + emails. This variable must be a string. Format directives like + ``%()s`` will be expanded the same way as template + strings. In particular, ``%(id)s`` will be replaced by the full + Git commit identifier (40-chars hexadecimal). + + If the string does not contain any format directive, then + ``%(id)s`` will be automatically added to the string. If you don't + want ``%(id)s`` to be automatically added, use the empty format + directive ``%()s`` anywhere in the string. + + For example, a suitable value for the git-multimail project itself + would be + ``https://github.com/git-multimail/git-multimail/commit/%(id)s``. + +multimailhook.htmlInIntro, multimailhook.htmlInFooter + When generating an HTML message, git-multimail escapes any HTML + sequence by default. This means that if a template contains HTML + like ``link``, the reader will see the HTML + source code and not a proper link. + + Set ``multimailhook.htmlInIntro`` to true to allow writting HTML + formatting in introduction templates. Similarly, set + ``multimailhook.htmlInFooter`` for HTML in the footer. + Variables expanded in the template are still escaped. For example, + if a repository's path contains a ``<``, it will be rendered as + such in the message. + + Read ``__ for more details and + examples. + +multimailhook.refchangeShowGraph If this option is set to true, then summary emails about reference changes will additionally include: @@ -287,7 +317,6 @@ multimailhook.refchangeShowGraph specified in graphOpts. The default is false. multimailhook.refchangeShowLog - If this option is set to true, then summary emails about reference changes will include a detailed log of the added commits in addition to the one line summary. The log is generated by running @@ -295,71 +324,80 @@ multimailhook.refchangeShowLog Default is false. multimailhook.mailer - This option changes the way emails are sent. Accepted values are: - - sendmail (the default): use the command ``/usr/sbin/sendmail`` or + * **sendmail (the default)**: use the command ``/usr/sbin/sendmail`` or ``/usr/lib/sendmail`` (or sendmailCommand, if configured). This mode can be further customized via the following options: - * multimailhook.sendmailCommand - - The command used by mailer ``sendmail`` to send emails. Shell - quoting is allowed in the value of this setting, but remember that - Git requires double-quotes to be escaped; e.g.:: + multimailhook.sendmailCommand + The command used by mailer ``sendmail`` to send emails. Shell + quoting is allowed in the value of this setting, but remember that + Git requires double-quotes to be escaped; e.g.:: - git config multimailhook.sendmailcommand '/usr/sbin/sendmail -oi -t -F \"Git Repo\"' + git config multimailhook.sendmailcommand '/usr/sbin/sendmail -oi -t -F \"Git Repo\"' - Default is '/usr/sbin/sendmail -oi -t' or - '/usr/lib/sendmail -oi -t' (depending on which file is - present and executable). + Default is '/usr/sbin/sendmail -oi -t' or + '/usr/lib/sendmail -oi -t' (depending on which file is + present and executable). - * multimailhook.envelopeSender + multimailhook.envelopeSender + If set then pass this value to sendmail via the -f option to set + the envelope sender address. - If set then pass this value to sendmail via the -f option to set - the envelope sender address. - - - smtp: use Python's smtplib. This is useful when the sendmail + * **smtp**: use Python's smtplib. This is useful when the sendmail command is not available on the system. This mode can be further customized via the following options: - * multimailhook.smtpServer - - The name of the SMTP server to connect to. The value can - also include a colon and a port number; e.g., - ``mail.example.com:25``. Default is 'localhost' using port 25. - - * multimailhook.smtpUser - * multimailhook.smtpPass - - Server username and password. Required if smtpEncryption is 'ssl'. - Note that the username and password currently need to be - set cleartext in the configuration file, which is not - recommended. If you need to use this option, be sure your - configuration file is read-only. + multimailhook.smtpServer + The name of the SMTP server to connect to. The value can + also include a colon and a port number; e.g., + ``mail.example.com:25``. Default is 'localhost' using port 25. - * multimailhook.envelopeSender + multimailhook.smtpUser, multimailhook.smtpPass + Server username and password. Required if smtpEncryption is 'ssl'. + Note that the username and password currently need to be + set cleartext in the configuration file, which is not + recommended. If you need to use this option, be sure your + configuration file is read-only. + multimailhook.envelopeSender The sender address to be passed to the SMTP server. If unset, then the value of multimailhook.from is used. - * multimailhook.smtpServerTimeout - + multimailhook.smtpServerTimeout Timeout in seconds. - * multimailhook.smtpEncryption - - Set the security type. Allowed values: none, ssl, tls. - Default=none. - - * multimailhook.smtpServerDebugLevel - + multimailhook.smtpEncryption + Set the security type. Allowed values: ``none``, ``ssl``, ``tls`` (starttls). + Default is ``none``. + + multimailhook.smtpCACerts + Set the path to a list of trusted CA certificate to verify the + server certificate, only supported when ``smtpEncryption`` is + ``tls``. If unset or empty, the server certificate is not + verified. If it targets a file containing a list of trusted CA + certificates (PEM format) these CAs will be used to verify the + server certificate. For debian, you can set + ``/etc/ssl/certs/ca-certificates.crt`` for using the system + trusted CAs. For self-signed server, you can add your server + certificate to the system store:: + + cd /usr/local/share/ca-certificates/ + openssl s_client -starttls smtp \ + -connect mail.example.net:587 -showcerts \ + /dev/null \ + | openssl x509 -outform PEM >mail.example.net.crt + update-ca-certificates + + and used the updated ``/etc/ssl/certs/ca-certificates.crt``. Or + directly use your ``/path/to/mail.example.net.crt``. Default is + unset. + + multimailhook.smtpServerDebugLevel Integer number. Set to greater than 0 to activate debugging. -multimailhook.from -multimailhook.fromCommit -multimailhook.fromRefchange - +multimailhook.from, multimailhook.fromCommit, multimailhook.fromRefchange If set, use this value in the From: field of generated emails. ``fromCommit`` is used for commit emails, ``fromRefchange`` is used for refchange emails, and ``from`` is used as fall-back in @@ -372,7 +410,7 @@ multimailhook.fromRefchange - The value ``pusher``, in which case the pusher's address (if available) will be used. - - The value ``author`` (meaningful only for replyToCommit), in which + - The value ``author`` (meaningful only for ``fromCommit``), in which case the commit author's address will be used. If config values are unset, the value of the From: header is @@ -396,14 +434,12 @@ multimailhook.fromRefchange 3. Use the value of multimailhook.envelopeSender. multimailhook.administrator - The name and/or email address of the administrator of the Git repository; used in FOOTER_TEMPLATE. Default is multimailhook.envelopesender if it is set; otherwise a generic string is used. multimailhook.emailPrefix - All emails have this string prepended to their subjects, to aid email filtering (though filtering based on the X-Git-* email headers is probably more robust). Default is the short name of @@ -411,16 +447,14 @@ multimailhook.emailPrefix value to the empty string to suppress the email prefix. multimailhook.emailMaxLines - The maximum number of lines that should be included in the body of a generated email. If not specified, there is no limit. Lines beyond the limit are suppressed and counted, and a final line is added indicating the number of suppressed lines. multimailhook.emailMaxLineLength - The maximum length of a line in the email body. Lines longer than - this limit are truncated to this length with a trailing `` [...]`` + this limit are truncated to this length with a trailing ``[...]`` added to indicate the missing text. The default is 500, because (a) diffs with longer lines are probably from binary files, for which a diff is useless, and (b) even if a text file has such long @@ -428,7 +462,6 @@ multimailhook.emailMaxLineLength truncation, set this option to 0. multimailhook.maxCommitEmails - The maximum number of commit emails to send for a given change. When the number of patches is larger that this value, only the summary refchange email is sent. This can avoid accidental @@ -436,14 +469,12 @@ multimailhook.maxCommitEmails emails limit, set this option to 0. The default is 500. multimailhook.emailStrictUTF8 - If this boolean option is set to `true`, then the main part of the email body is forced to be valid UTF-8. Any characters that are not valid UTF-8 are converted to the Unicode replacement character, U+FFFD. The default is `true`. multimailhook.diffOpts - Options passed to ``git diff-tree`` when generating the summary information for ReferenceChange emails. Default is ``--stat --summary --find-copies-harder``. Add -p to those options to @@ -452,7 +483,6 @@ multimailhook.diffOpts details. multimailhook.graphOpts - Options passed to ``git log --graph`` when generating graphs for the reference change summary emails (used only if refchangeShowGraph is true). The default is '--oneline --decorate'. @@ -460,7 +490,6 @@ multimailhook.graphOpts Shell quoting is allowed; see logOpts for details. multimailhook.logOpts - Options passed to ``git log`` to generate additional info for reference change emails (used only if refchangeShowLog is set). For example, adding -p will show each commit's complete diff. The @@ -479,7 +508,6 @@ multimailhook.logOpts logopts = --pretty=format:\"%h %aN <%aE>%n%s%n%n%b%n\" multimailhook.commitLogOpts - Options passed to ``git log`` to generate additional info for revision change emails. For example, adding --ignore-all-spaces will suppress whitespace changes. The default options are ``-C @@ -487,26 +515,21 @@ multimailhook.commitLogOpts multimailhook.logOpts for details. multimailhook.dateSubstitute - String to use as a substitute for ``Date:`` in the output of ``git log`` while formatting commit messages. This is usefull to avoid emitting a line that can be interpreted by mailers as the start of a cited message (Zimbra webmail in particular). Defaults to - ``CommitDate: ``. Set to an empty string or ``none`` to deactivate + ``CommitDate:``. Set to an empty string or ``none`` to deactivate the behavior. multimailhook.emailDomain - Domain name appended to the username of the person doing the push to convert it into an email address (via ``"%s@%s" % (username, emaildomain)``). More complicated schemes can be implemented by overriding Environment and overriding its get_pusher_email() method. -multimailhook.replyTo -multimailhook.replyToCommit -multimailhook.replyToRefchange - +multimailhook.replyTo, multimailhook.replyToCommit, multimailhook.replyToRefchange Addresses to use in the Reply-To: field for commit emails (replyToCommit) and refchange emails (replyToRefchange). multimailhook.replyTo is used as default when replyToCommit or @@ -519,32 +542,24 @@ multimailhook.replyToRefchange commit emails. multimailhook.quiet - Do not output the list of email recipients from the hook multimailhook.stdout - For debugging, send emails to stdout rather than to the mailer. Equivalent to the --stdout command line option multimailhook.scanCommitForCc - If this option is set to true, than recipients from lines in commit body that starts with ``CC:`` will be added to CC list. Default: false multimailhook.combineWhenSingleCommit - If this option is set to true and a single new commit is pushed to a branch, combine the summary and commit email messages into a single email. Default: true -multimailhook.refFilterInclusionRegex -multimailhook.refFilterExclusionRegex -multimailhook.refFilterDoSendRegex -multimailhook.refFilterDontSendRegex - +multimailhook.refFilterInclusionRegex, multimailhook.refFilterExclusionRegex, multimailhook.refFilterDoSendRegex, multimailhook.refFilterDontSendRegex **Warning:** these options are experimental. They should work, but the user-interface is not stable yet (in particular, the option names may change). If you want to participate in stabilizing the @@ -626,14 +641,16 @@ git-multimail is mostly customized via an "environment" that describes the local environment in which Git is running. Two types of environment are built in: -* GenericEnvironment: a stand-alone Git repository. +GenericEnvironment + a stand-alone Git repository. -* GitoliteEnvironment: a Git repository that is managed by gitolite - [3]_. For such repositories, the identity of the pusher is read from - environment variable $GL_USER, the name of the repository is read - from $GL_REPO (if it is not overridden by multimailhook.reponame), - and the From: header value is optionally read from gitolite.conf - (see multimailhook.from). +GitoliteEnvironment + a Git repository that is managed by gitolite + [3]_. For such repositories, the identity of the pusher is read from + environment variable $GL_USER, the name of the repository is read + from $GL_REPO (if it is not overridden by multimailhook.reponame), + and the From: header value is optionally read from gitolite.conf + (see multimailhook.from). By default, git-multimail assumes GitoliteEnvironment if $GL_USER and $GL_REPO are set, and otherwise assumes GenericEnvironment. diff --git a/contrib/hooks/multimail/README.Git b/contrib/hooks/multimail/README.Git index 300a2a4d2d..1210bde045 100644 --- a/contrib/hooks/multimail/README.Git +++ b/contrib/hooks/multimail/README.Git @@ -6,10 +6,10 @@ website: https://github.com/git-multimail/git-multimail The version in this directory was obtained from the upstream project -on October 11 2015 and consists of the "git-multimail" subdirectory from +on May 13 2016 and consists of the "git-multimail" subdirectory from revision - c0791b9ef5821a746fc3475c25765e640452eaae refs/tags/1.2.0 + 3ce5470d4abf7251604cbf64e73a962e1b617f5e refs/tags/1.3.1 Please see the README file in this directory for information about how to report bugs or contribute to git-multimail. diff --git a/contrib/hooks/multimail/doc/customizing-emails.rst b/contrib/hooks/multimail/doc/customizing-emails.rst new file mode 100644 index 0000000000..3f5b67f768 --- /dev/null +++ b/contrib/hooks/multimail/doc/customizing-emails.rst @@ -0,0 +1,56 @@ +Customizing the content and formatting of emails +================================================ + +Overloading template strings +---------------------------- + +The content of emails is generated based on template strings defined +in ``git_multimail.py``. You can customize these template strings +without changing the script itself, by defining a Python wrapper +around it. The python wrapper should ``import git_multimail`` and then +override the ``git_multimail.*`` strings like this:: + + import sys # needed for sys.argv + + # Import and customize git_multimail: + import git_multimail + git_multimail.REVISION_INTRO_TEMPLATE = """...""" + git_multimail.COMBINED_INTRO_TEMPLATE = git_multimail.REVISION_INTRO_TEMPLATE + + # start git_multimail itself: + git_multimail.main(sys.argv[1:]) + +The template strings can use any value already used in the existing +templates (read the source code). + +Using HTML in template strings +------------------------------ + +If ``multimailhook.commitEmailFormat`` is set to HTML, then +git-multimail will generate HTML emails for commit notifications. The +log and diff will be formatted automatically by git-multimail. By +default, any HTML special character in the templates will be escaped. + +To use HTML formatting in the introduction of the email, set +``multimailhook.htmlInIntro`` to ``true``. Then, the template can +contain any HTML tags, that will be sent as-is in the email. For +example, to add some formatting and a link to the online commit, use +a format like:: + + git_multimail.REVISION_INTRO_TEMPLATE = """\ + This is an automated email from the git hooks/post-receive script.

+ + %(pusher)s pushed a commit to %(refname_type)s %(short_refname)s + in repository %(repo_shortname)s.
+ + View on GitHub. + """ + +Note that the values expanded from ``%(variable)s`` in the format +strings will still be escaped. + +For a less flexible but easier to set up way to add a link to commit +emails, see ``multimailhook.commitBrowseURL``. + +Similarly, one can set ``multimailhook.htmlInFooter`` and override any +of the ``*_FOOTER*`` template strings. diff --git a/contrib/hooks/multimail/doc/troubleshooting.rst b/contrib/hooks/multimail/doc/troubleshooting.rst new file mode 100644 index 0000000000..d3f346f076 --- /dev/null +++ b/contrib/hooks/multimail/doc/troubleshooting.rst @@ -0,0 +1,44 @@ +Troubleshooting issues with git-multimail: a FAQ +================================================ + +Git is not using the right address in the From/To/Reply-To field +---------------------------------------------------------------- + +First, make sure that git-multimail actually uses what you think it is +using. A lot happens to your email (especially when posting to a +mailing-list) between the time `git_multimail.py` sends it and the +time it reaches your inbox. + +A simple test (to do on a test repository, do not use in production as +it would disable email sending): change your post-receive hook to call +`git_multimail.py` with the `--stdout` option, and try to push to the +repository. You should see something like:: + + Counting objects: 3, done. + Writing objects: 100% (3/3), 263 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + remote: Sending notification emails to: foo.bar@example.com + remote: =========================================================================== + remote: Date: Mon, 25 Apr 2016 18:39:59 +0200 + remote: To: foo.bar@example.com + remote: Subject: [git] branch master updated: foo + remote: MIME-Version: 1.0 + remote: Content-Type: text/plain; charset=utf-8 + remote: Content-Transfer-Encoding: 8bit + remote: Message-ID: <20160425163959.2311.20498@anie> + remote: From: Auth Or + remote: Reply-To: Auth Or + remote: X-Git-Host: example + ... + remote: -- + remote: To stop receiving notification emails like this one, please contact + remote: the administrator of this repository. + remote: =========================================================================== + To /path/to/repo + 6278f04..e173f20 master -> master + +Note: this does not include the sender (Return-Path: header), as it is +not part of the message content but passed to the mailer. Some mailer +show the ``Sender:`` field instead of the ``From:`` field (for +example, Zimbra Webmail shows ``From: on behalf of +``). diff --git a/contrib/hooks/multimail/git_multimail.py b/contrib/hooks/multimail/git_multimail.py index 0180dba431..54ab4a4942 100755 --- a/contrib/hooks/multimail/git_multimail.py +++ b/contrib/hooks/multimail/git_multimail.py @@ -1,6 +1,6 @@ #! /usr/bin/env python -__version__ = '1.2.0' +__version__ = '1.3.1' # Copyright (c) 2015 Matthieu Moy and others # Copyright (c) 2012-2014 Michael Haggerty and others @@ -57,6 +57,11 @@ import shlex import optparse import smtplib +try: + import ssl +except ImportError: + # Python < 2.6 do not have ssl, but that's OK if we don't use it. + pass import time import cgi @@ -75,6 +80,9 @@ def is_ascii(s): if PYTHON3: + def is_string(s): + return isinstance(s, str) + def str_to_bytes(s): return s.encode(ENCODING) @@ -91,6 +99,12 @@ def write_str(f, msg): except UnicodeEncodeError: f.buffer.write(msg.encode(ENCODING)) else: + def is_string(s): + try: + return isinstance(s, basestring) + except NameError: # Silence Pyflakes warning + raise + def str_to_bytes(s): return s @@ -313,6 +327,16 @@ def next(it): """ +LINK_TEXT_TEMPLATE = """\ +View the commit online: +%(browse_url)s + +""" + +LINK_HTML_TEMPLATE = """\ +

View the commit online.

+""" + REVISION_FOOTER_TEMPLATE = FOOTER_TEMPLATE @@ -532,6 +556,28 @@ def _split(s): assert words[-1] == '' return words[:-1] + @staticmethod + def add_config_parameters(c): + """Add configuration parameters to Git. + + c is either an str or a list of str, each element being of the + form 'var=val' or 'var', with the same syntax and meaning as + the argument of 'git -c var=val'. + """ + if isinstance(c, str): + c = (c,) + parameters = os.environ.get('GIT_CONFIG_PARAMETERS', '') + if parameters: + parameters += ' ' + # git expects GIT_CONFIG_PARAMETERS to be of the form + # "'name1=value1' 'name2=value2' 'name3=value3'" + # including everything inside the double quotes (but not the double + # quotes themselves). Spacing is critical. Also, if a value contains + # a literal single quote that quote must be represented using the + # four character sequence: '\'' + parameters += ' '.join("'" + x.replace("'", "'\\''") + "'" for x in c) + os.environ['GIT_CONFIG_PARAMETERS'] = parameters + def get(self, name, default=None): try: values = self._split(read_git_output( @@ -745,6 +791,12 @@ def _compute_values(self): values['multimail_version'] = get_version() return values + # Aliases usable in template strings. Tuple of pairs (destination, + # source). + VALUES_ALIAS = ( + ("id", "newrev"), + ) + def get_values(self, **extra_values): """Return a dictionary {keyword: expansion} for this Change. @@ -760,6 +812,9 @@ def get_values(self, **extra_values): values = self._values.copy() if extra_values: values.update(extra_values) + + for alias, val in self.VALUES_ALIAS: + values[alias] = values[val] return values def expand(self, template, **extra_values): @@ -772,10 +827,14 @@ def expand(self, template, **extra_values): return template % self.get_values(**extra_values) - def expand_lines(self, template, **extra_values): + def expand_lines(self, template, html_escape_val=False, **extra_values): """Break template into lines and expand each line.""" values = self.get_values(**extra_values) + if html_escape_val: + for k in values: + if is_string(values[k]): + values[k] = cgi.escape(values[k], True) for line in template.splitlines(True): yield line % values @@ -787,9 +846,10 @@ def expand_header_lines(self, template, **extra_values): values = self.get_values(**extra_values) if self._contains_html_diff: - values['contenttype'] = 'html' + self._content_type = 'html' else: - values['contenttype'] = 'plain' + self._content_type = 'plain' + values['contenttype'] = self._content_type for line in template.splitlines(): (name, value) = line.split(': ', 1) @@ -819,7 +879,11 @@ def generate_email_header(self): raise NotImplementedError() - def generate_email_intro(self): + def generate_browse_link(self, base_url): + """Generate a link to an online repository browser.""" + return iter(()) + + def generate_email_intro(self, html_escape_val=False): """Generate the email intro for this Change, a line at a time. The output will be used as the standard boilerplate at the top @@ -835,7 +899,7 @@ def generate_email_body(self): raise NotImplementedError() - def generate_email_footer(self): + def generate_email_footer(self, html_escape_val): """Generate the footer of the email, a line at a time. The footer is always included, irrespective of @@ -876,9 +940,18 @@ def generate_email(self, push, body_filter=None, extra_header_values={}): for line in self.generate_email_header(**extra_header_values): yield line yield '\n' - for line in self._wrap_for_html(self.generate_email_intro()): + html_escape_val = (self.environment.html_in_intro and + self._contains_html_diff) + intro = self.generate_email_intro(html_escape_val) + if not self.environment.html_in_intro: + intro = self._wrap_for_html(intro) + for line in intro: yield line + if self.environment.commitBrowseURL: + for line in self.generate_browse_link(self.environment.commitBrowseURL): + yield line + body = self.generate_email_body(push) if body_filter is not None: body = body_filter(body) @@ -939,8 +1012,12 @@ def generate_email(self, push, body_filter=None, extra_header_values={}): yield line if self._contains_html_diff: yield '' - - for line in self._wrap_for_html(self.generate_email_footer()): + html_escape_val = (self.environment.html_in_footer and + self._contains_html_diff) + footer = self.generate_email_footer(html_escape_val) + if not self.environment.html_in_footer: + footer = self._wrap_for_html(footer) + for line in footer: yield line def get_alt_fromaddr(self): @@ -992,6 +1069,7 @@ def _compute_values(self): values['rev_short'] = self.rev.short values['change_type'] = self.change_type values['refname'] = self.refname + values['newrev'] = self.rev.sha1 values['short_refname'] = self.reference_change.short_refname values['refname_type'] = self.reference_change.refname_type values['reply_to_msgid'] = self.reference_change.msgid @@ -1015,8 +1093,26 @@ def generate_email_header(self, **extra_values): ): yield line - def generate_email_intro(self): - for line in self.expand_lines(REVISION_INTRO_TEMPLATE): + def generate_browse_link(self, base_url): + if '%(' not in base_url: + base_url += '%(id)s' + url = "".join(self.expand_lines(base_url)) + if self._content_type == 'html': + for line in self.expand_lines(LINK_HTML_TEMPLATE, + html_escape_val=True, + browse_url=url): + yield line + elif self._content_type == 'plain': + for line in self.expand_lines(LINK_TEXT_TEMPLATE, + html_escape_val=False, + browse_url=url): + yield line + else: + raise NotImplementedError("Content-type %s unsupported. Please report it as a bug.") + + def generate_email_intro(self, html_escape_val=False): + for line in self.expand_lines(REVISION_INTRO_TEMPLATE, + html_escape_val=html_escape_val): yield line def generate_email_body(self, push): @@ -1031,8 +1127,9 @@ def generate_email_body(self, push): else: yield line - def generate_email_footer(self): - return self.expand_lines(REVISION_FOOTER_TEMPLATE) + def generate_email_footer(self, html_escape_val): + return self.expand_lines(REVISION_FOOTER_TEMPLATE, + html_escape_val=html_escape_val) def generate_email(self, push, body_filter=None, extra_header_values={}): self._contains_diff() @@ -1217,8 +1314,9 @@ def generate_email_header(self, **extra_values): ): yield line - def generate_email_intro(self): - for line in self.expand_lines(self.intro_template): + def generate_email_intro(self, html_escape_val=False): + for line in self.expand_lines(self.intro_template, + html_escape_val=html_escape_val): yield line def generate_email_body(self, push): @@ -1238,8 +1336,9 @@ def generate_email_body(self, push): for line in self.generate_revision_change_summary(push): yield line - def generate_email_footer(self): - return self.expand_lines(self.footer_template) + def generate_email_footer(self, html_escape_val): + return self.expand_lines(self.footer_template, + html_escape_val=html_escape_val) def generate_revision_change_graph(self, push): if self.showgraph: @@ -1605,6 +1704,14 @@ def generate_combined_email(self, push, revision, body_filter=None, extra_header self.header_template = COMBINED_HEADER_TEMPLATE self.intro_template = COMBINED_INTRO_TEMPLATE self.footer_template = COMBINED_FOOTER_TEMPLATE + + def revision_gen_link(base_url): + # revision is used only to generate the body, and + # _content_type is set while generating headers. Get it + # from the BranchChange object. + revision._content_type = self._content_type + return revision.generate_browse_link(base_url) + self.generate_browse_link = revision_gen_link for line in self.generate_email(push, body_filter, values): yield line @@ -1896,6 +2003,7 @@ def __init__(self, envelopesender, smtpserver, smtpservertimeout=10.0, smtpserverdebuglevel=0, smtpencryption='none', smtpuser='', smtppass='', + smtpcacerts='' ): if not envelopesender: sys.stderr.write( @@ -1915,6 +2023,7 @@ def __init__(self, envelopesender, smtpserver, self.security = smtpencryption self.username = smtpuser self.password = smtppass + self.smtpcacerts = smtpcacerts try: def call(klass, server, timeout): try: @@ -1925,13 +2034,56 @@ def call(klass, server, timeout): if self.security == 'none': self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout) elif self.security == 'ssl': + if self.smtpcacerts: + raise smtplib.SMTPException( + "Checking certificate is not supported for ssl, prefer starttls" + ) self.smtp = call(smtplib.SMTP_SSL, self.smtpserver, timeout=self.smtpservertimeout) elif self.security == 'tls': + if 'ssl' not in sys.modules: + sys.stderr.write( + '*** Your Python version does not have the ssl library installed\n' + '*** smtpEncryption=tls is not available.\n' + '*** Either upgrade Python to 2.6 or later\n' + ' or use git_multimail.py version 1.2.\n') if ':' not in self.smtpserver: self.smtpserver += ':587' # default port for TLS self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout) + # start: ehlo + starttls + # equivalent to + # self.smtp.ehlo() + # self.smtp.starttls() + # with acces to the ssl layer self.smtp.ehlo() - self.smtp.starttls() + if not self.smtp.has_extn("starttls"): + raise smtplib.SMTPException("STARTTLS extension not supported by server") + resp, reply = self.smtp.docmd("STARTTLS") + if resp != 220: + raise smtplib.SMTPException("Wrong answer to the STARTTLS command") + if self.smtpcacerts: + self.smtp.sock = ssl.wrap_socket( + self.smtp.sock, + ca_certs=self.smtpcacerts, + cert_reqs=ssl.CERT_REQUIRED + ) + else: + self.smtp.sock = ssl.wrap_socket( + self.smtp.sock, + cert_reqs=ssl.CERT_NONE + ) + sys.stderr.write( + '*** Warning, the server certificat is not verified (smtp) ***\n' + '*** set the option smtpCACerts ***\n' + ) + if not hasattr(self.smtp.sock, "read"): + # using httplib.FakeSocket with Python 2.5.x or earlier + self.smtp.sock.read = self.smtp.sock.recv + self.smtp.file = smtplib.SSLFakeFile(self.smtp.sock) + self.smtp.helo_resp = None + self.smtp.ehlo_resp = None + self.smtp.esmtp_features = {} + self.smtp.does_esmtp = 0 + # end: ehlo + starttls self.smtp.ehlo() else: sys.stdout.write('*** Error: Control reached an invalid option. ***') @@ -1951,6 +2103,7 @@ def call(klass, server, timeout): def __del__(self): if hasattr(self, 'smtp'): self.smtp.quit() + del self.smtp def send(self, lines, to_addrs): try: @@ -1958,13 +2111,24 @@ def send(self, lines, to_addrs): self.smtp.login(self.username, self.password) msg = ''.join(lines) # turn comma-separated list into Python list if needed. - if isinstance(to_addrs, basestring): + if is_string(to_addrs): to_addrs = [email for (name, email) in getaddresses([to_addrs])] self.smtp.sendmail(self.envelopesender, to_addrs, msg) - except Exception: + except smtplib.SMTPResponseException: sys.stderr.write('*** Error sending email ***\n') - sys.stderr.write('*** %s\n' % sys.exc_info()[1]) - self.smtp.quit() + err = sys.exc_info()[1] + sys.stderr.write('*** Error %d: %s\n' % (err.smtp_code, + bytes_to_str(err.smtp_error))) + try: + smtp = self.smtp + # delete the field before quit() so that in case of + # error, self.smtp is deleted anyway. + del self.smtp + smtp.quit() + except: + sys.stderr.write('*** Error closing the SMTP connection ***\n') + sys.stderr.write('*** Exiting anyway ... ***\n') + sys.stderr.write('*** %s\n' % sys.exc_info()[1]) sys.exit(1) @@ -2097,6 +2261,14 @@ class Environment(object): If "html", generate commit emails in HTML instead of plain text used by default. + html_in_intro (bool) + html_in_footer (bool) + + When generating HTML emails, the introduction (respectively, + the footer) will be HTML-escaped iff html_in_intro (respectively, + the footer) is true. When false, only the values used to expand + the template are escaped. + refchange_showgraph (bool) True iff refchanges emails should include a detailed graph. @@ -2160,6 +2332,9 @@ def __init__(self, osenv=None): self.osenv = osenv or os.environ self.announce_show_shortlog = False self.commit_email_format = "text" + self.html_in_intro = False + self.html_in_footer = False + self.commitBrowseURL = None self.maxcommitemails = 500 self.diffopts = ['--stat', '--summary', '--find-copies-harder'] self.graphopts = ['--oneline', '--decorate'] @@ -2236,7 +2411,7 @@ def get_values(self): The return value is always a new dictionary.""" if self._values is None: - values = {} + values = {'': ''} # %()s expands to the empty string. for key in self.COMPUTED_KEYS: value = getattr(self, 'get_%s' % (key,))() @@ -2375,6 +2550,16 @@ def __init__(self, config, **kw): else: self.commit_email_format = commit_email_format + html_in_intro = config.get_bool('htmlInIntro') + if html_in_intro is not None: + self.html_in_intro = html_in_intro + + html_in_footer = config.get_bool('htmlInFooter') + if html_in_footer is not None: + self.html_in_footer = html_in_footer + + self.commitBrowseURL = config.get('commitBrowseURL') + maxcommitemails = config.get('maxcommitemails') if maxcommitemails is not None: try: @@ -2415,7 +2600,6 @@ def __init__(self, config, **kw): ['author']) self.__reply_to_commit = config.get('replyToCommit', default=reply_to) - from_addr = self.config.get('from') self.from_refchange = config.get('fromRefchange') self.forbid_field_values('fromRefchange', self.from_refchange, @@ -3390,6 +3574,8 @@ def run_as_post_receive_hook(environment, mailer): if changes: push = Push(environment, changes) push.send_emails(mailer, body_filter=environment.filter_body) + if hasattr(mailer, '__del__'): + mailer.__del__() def run_as_update_hook(environment, mailer, refname, oldrev, newrev, force_send=False): @@ -3406,6 +3592,8 @@ def run_as_update_hook(environment, mailer, refname, oldrev, newrev, force_send= ] push = Push(environment, changes, force_send) push.send_emails(mailer, body_filter=environment.filter_body) + if hasattr(mailer, '__del__'): + mailer.__del__() def choose_mailer(config, environment): @@ -3418,6 +3606,7 @@ def choose_mailer(config, environment): smtpencryption = config.get('smtpencryption', default='none') smtpuser = config.get('smtpuser', default='') smtppass = config.get('smtppass', default='') + smtpcacerts = config.get('smtpcacerts', default='') mailer = SMTPMailer( envelopesender=(environment.get_sender() or environment.get_fromaddr()), smtpserver=smtpserver, smtpservertimeout=smtpservertimeout, @@ -3425,6 +3614,7 @@ def choose_mailer(config, environment): smtpencryption=smtpencryption, smtpuser=smtpuser, smtppass=smtppass, + smtpcacerts=smtpcacerts ) elif mailer == 'sendmail': command = config.get('sendmailcommand') @@ -3691,17 +3881,7 @@ def main(args): return if options.c: - parameters = os.environ.get('GIT_CONFIG_PARAMETERS', '') - if parameters: - parameters += ' ' - # git expects GIT_CONFIG_PARAMETERS to be of the form - # "'name1=value1' 'name2=value2' 'name3=value3'" - # including everything inside the double quotes (but not the double - # quotes themselves). Spacing is critical. Also, if a value contains - # a literal single quote that quote must be represented using the - # four character sequence: '\'' - parameters += ' '.join("'" + x.replace("'", "'\\''") + "'" for x in options.c) - os.environ['GIT_CONFIG_PARAMETERS'] = parameters + Config.add_config_parameters(options.c) config = Config('multimailhook') diff --git a/contrib/hooks/multimail/post-receive.example b/contrib/hooks/multimail/post-receive.example index 9975df7107..1ea113d274 100755 --- a/contrib/hooks/multimail/post-receive.example +++ b/contrib/hooks/multimail/post-receive.example @@ -55,6 +55,12 @@ import git_multimail # git-multimail: config = git_multimail.Config('multimailhook') +# Set some Git configuration variables. Equivalent to passing var=val +# to "git -c var=val" each time git is called, or to adding the +# configuration in .git/config (must come before instanciating the +# environment) : +#git_multimail.Config.add_config_parameters('multimailhook.commitEmailFormat=html') +#git_multimail.Config.add_config_parameters(('user.name=foo', 'user.email=foo@example.com')) # Select the type of environment: try: diff --git a/convert.c b/convert.c index f524b8d7f4..b1614bf7ff 100644 --- a/convert.c +++ b/convert.c @@ -1380,27 +1380,22 @@ static struct stream_filter *ident_filter(const unsigned char *sha1) struct stream_filter *get_stream_filter(const char *path, const unsigned char *sha1) { struct conv_attrs ca; - enum crlf_action crlf_action; struct stream_filter *filter = NULL; convert_attrs(&ca, path); - if (ca.drv && (ca.drv->smudge || ca.drv->clean)) - return filter; + return NULL; + + if (ca.crlf_action == CRLF_AUTO || ca.crlf_action == CRLF_AUTO_CRLF) + return NULL; if (ca.ident) filter = ident_filter(sha1); - crlf_action = ca.crlf_action; - - if ((crlf_action == CRLF_BINARY) || - crlf_action == CRLF_AUTO_INPUT || - (crlf_action == CRLF_TEXT_INPUT)) - filter = cascade_filter(filter, &null_filter_singleton); - - else if (output_eol(crlf_action) == EOL_CRLF && - !(crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_CRLF)) + if (output_eol(ca.crlf_action) == EOL_CRLF) filter = cascade_filter(filter, lf_to_crlf_filter()); + else + filter = cascade_filter(filter, &null_filter_singleton); return filter; } diff --git a/copy.c b/copy.c index 574fa1f09d..4de6a110f0 100644 --- a/copy.c +++ b/copy.c @@ -42,15 +42,15 @@ int copy_file(const char *dst, const char *src, int mode) status = copy_fd(fdi, fdo); switch (status) { case COPY_READ_ERROR: - error("copy-fd: read returned %s", strerror(errno)); + error_errno("copy-fd: read returned"); break; case COPY_WRITE_ERROR: - error("copy-fd: write returned %s", strerror(errno)); + error_errno("copy-fd: write returned"); break; } close(fdi); if (close(fdo) != 0) - return error("%s: close error: %s", dst, strerror(errno)); + return error_errno("%s: close error", dst); if (!status && adjust_shared_perm(dst)) return -1; diff --git a/credential-cache--daemon.c b/credential-cache--daemon.c index caef21e4fc..1f14d56e98 100644 --- a/credential-cache--daemon.c +++ b/credential-cache--daemon.c @@ -126,8 +126,17 @@ static void serve_one_client(FILE *in, FILE *out) fprintf(out, "password=%s\n", e->item.password); } } - else if (!strcmp(action.buf, "exit")) + else if (!strcmp(action.buf, "exit")) { + /* + * It's important that we clean up our socket first, and then + * signal the client only once we have finished the cleanup. + * Calling exit() directly does this, because we clean up in + * our atexit() handler, and then signal the client when our + * process actually ends, which closes the socket and gives + * them EOF. + */ exit(0); + } else if (!strcmp(action.buf, "erase")) remove_credential(&c); else if (!strcmp(action.buf, "store")) { @@ -170,12 +179,12 @@ static int serve_cache_loop(int fd) client = accept(fd, NULL, NULL); if (client < 0) { - warning("accept failed: %s", strerror(errno)); + warning_errno("accept failed"); return 1; } client2 = dup(client); if (client2 < 0) { - warning("dup failed: %s", strerror(errno)); + warning_errno("dup failed"); close(client); return 1; } diff --git a/credential-cache.c b/credential-cache.c index f4afdc6988..86e21de49b 100644 --- a/credential-cache.c +++ b/credential-cache.c @@ -32,6 +32,7 @@ static int send_request(const char *socket, const struct strbuf *out) write_or_die(1, in, r); got_data = 1; } + close(fd); return got_data; } diff --git a/credential.c b/credential.c index 7d6501d190..aa996669fc 100644 --- a/credential.c +++ b/credential.c @@ -63,9 +63,12 @@ static int credential_config_callback(const char *var, const char *value, key = dot + 1; } - if (!strcmp(key, "helper")) - string_list_append(&c->helpers, value); - else if (!strcmp(key, "username")) { + if (!strcmp(key, "helper")) { + if (*value) + string_list_append(&c->helpers, value); + else + string_list_clear(&c->helpers, 0); + } else if (!strcmp(key, "username")) { if (!c->username) c->username = xstrdup(value); } diff --git a/daemon.c b/daemon.c index 8d45c336f5..46dddaca5a 100644 --- a/daemon.c +++ b/daemon.c @@ -669,6 +669,15 @@ static void hostinfo_clear(struct hostinfo *hi) strbuf_release(&hi->tcp_port); } +static void set_keep_alive(int sockfd) +{ + int ka = 1; + + if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0) + logerror("unable to set SO_KEEPALIVE on socket: %s", + strerror(errno)); +} + static int execute(void) { char *line = packet_buffer; @@ -681,6 +690,7 @@ static int execute(void) if (addr) loginfo("Connection from %s:%s", addr, port); + set_keep_alive(0); alarm(init_timeout ? init_timeout : timeout); pktlen = packet_read(0, NULL, NULL, packet_buffer, sizeof(packet_buffer), 0); alarm(0); @@ -951,6 +961,8 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis continue; } + set_keep_alive(sockfd); + if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { logerror("Could not bind to %s: %s", ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen), @@ -1010,6 +1022,8 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis return 0; } + set_keep_alive(sockfd); + if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) { logerror("Could not bind to %s: %s", ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)), diff --git a/diff-no-index.c b/diff-no-index.c index 03daadb25a..1f8999b9ca 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -65,8 +65,7 @@ static int populate_from_stdin(struct diff_filespec *s) size_t size = 0; if (strbuf_read(&buf, 0, 0) < 0) - return error("error while reading from stdin %s", - strerror(errno)); + return error_errno("error while reading from stdin"); s->should_munmap = 0; s->data = strbuf_detach(&buf, &size); diff --git a/diff.c b/diff.c index 059123c5dc..fa78fc189c 100644 --- a/diff.c +++ b/diff.c @@ -26,6 +26,7 @@ #endif static int diff_detect_rename_default; +static int diff_compaction_heuristic; /* experimental */ static int diff_rename_limit_default = 400; static int diff_suppress_blank_empty; static int diff_use_color_default = -1; @@ -168,6 +169,11 @@ long parse_algorithm_value(const char *value) * never be affected by the setting of diff.renames * the user happens to have in the configuration file. */ +void init_diff_ui_defaults(void) +{ + diff_detect_rename_default = 1; +} + int git_diff_ui_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { @@ -184,6 +190,10 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) diff_detect_rename_default = git_config_rename(var, value); return 0; } + if (!strcmp(var, "diff.compactionheuristic")) { + diff_compaction_heuristic = git_config_bool(var, value); + return 0; + } if (!strcmp(var, "diff.autorefreshindex")) { diff_auto_refresh_index = git_config_bool(var, value); return 0; @@ -3273,6 +3283,8 @@ void diff_setup(struct diff_options *options) options->use_color = diff_use_color_default; options->detect_rename = diff_detect_rename_default; options->xdl_opts |= diff_algorithm; + if (diff_compaction_heuristic) + DIFF_XDL_SET(options, COMPACTION_HEURISTIC); options->orderfile = diff_order_file_cfg; @@ -3793,6 +3805,10 @@ int diff_opt_parse(struct diff_options *options, DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL); else if (!strcmp(arg, "--ignore-blank-lines")) DIFF_XDL_SET(options, IGNORE_BLANK_LINES); + else if (!strcmp(arg, "--compaction-heuristic")) + DIFF_XDL_SET(options, COMPACTION_HEURISTIC); + else if (!strcmp(arg, "--no-compaction-heuristic")) + DIFF_XDL_CLR(options, COMPACTION_HEURISTIC); else if (!strcmp(arg, "--patience")) options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF); else if (!strcmp(arg, "--histogram")) diff --git a/diff.h b/diff.h index e7d68edaf9..125447be09 100644 --- a/diff.h +++ b/diff.h @@ -266,6 +266,7 @@ extern int parse_long_opt(const char *opt, const char **argv, const char **optarg); extern int git_diff_basic_config(const char *var, const char *value, void *cb); +extern void init_diff_ui_defaults(void); extern int git_diff_ui_config(const char *var, const char *value, void *cb); extern void diff_setup(struct diff_options *); extern int diff_opt_parse(struct diff_options *, const char **, int, const char *); diff --git a/diffcore-rename.c b/diffcore-rename.c index 3b3c1ed535..7f03eb5a04 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -340,9 +340,11 @@ static int find_exact_renames(struct diff_options *options) int i, renames = 0; struct hashmap file_table; - /* Add all sources to the hash table */ + /* Add all sources to the hash table in reverse order, because + * later on they will be retrieved in LIFO order. + */ hashmap_init(&file_table, NULL, rename_src_nr); - for (i = 0; i < rename_src_nr; i++) + for (i = rename_src_nr-1; i >= 0; i--) insert_file_table(&file_table, i, rename_src[i].p->one); /* Walk the destinations and find best source match */ diff --git a/dir.c b/dir.c index a4a9d9fae1..6172b3438d 100644 --- a/dir.c +++ b/dir.c @@ -53,24 +53,16 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir, int check_only, const struct path_simplify *simplify); static int get_dtype(struct dirent *de, const char *path, int len); -/* helper string functions with support for the ignore_case flag */ -int strcmp_icase(const char *a, const char *b) +int fspathcmp(const char *a, const char *b) { return ignore_case ? strcasecmp(a, b) : strcmp(a, b); } -int strncmp_icase(const char *a, const char *b, size_t count) +int fspathncmp(const char *a, const char *b, size_t count) { return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count); } -int fnmatch_icase(const char *pattern, const char *string, int flags) -{ - return wildmatch(pattern, string, - flags | (ignore_case ? WM_CASEFOLD : 0), - NULL); -} - int git_fnmatch(const struct pathspec_item *item, const char *pattern, const char *string, int prefix) @@ -457,7 +449,7 @@ int no_wildcard(const char *string) void parse_exclude_pattern(const char **pattern, int *patternlen, - int *flags, + unsigned *flags, int *nowildcardlen) { const char *p = *pattern; @@ -498,7 +490,7 @@ void add_exclude(const char *string, const char *base, { struct exclude *x; int patternlen; - int flags; + unsigned flags; int nowildcardlen; parse_exclude_pattern(&string, &patternlen, &flags, &nowildcardlen); @@ -798,16 +790,16 @@ void add_excludes_from_file(struct dir_struct *dir, const char *fname) int match_basename(const char *basename, int basenamelen, const char *pattern, int prefix, int patternlen, - int flags) + unsigned flags) { if (prefix == patternlen) { if (patternlen == basenamelen && - !strncmp_icase(pattern, basename, basenamelen)) + !fspathncmp(pattern, basename, basenamelen)) return 1; } else if (flags & EXC_FLAG_ENDSWITH) { /* "*literal" matching against "fooliteral" */ if (patternlen - 1 <= basenamelen && - !strncmp_icase(pattern + 1, + !fspathncmp(pattern + 1, basename + basenamelen - (patternlen - 1), patternlen - 1)) return 1; @@ -823,7 +815,7 @@ int match_basename(const char *basename, int basenamelen, int match_pathname(const char *pathname, int pathlen, const char *base, int baselen, const char *pattern, int prefix, int patternlen, - int flags) + unsigned flags) { const char *name; int namelen; @@ -844,7 +836,7 @@ int match_pathname(const char *pathname, int pathlen, */ if (pathlen < baselen + 1 || (baselen && pathname[baselen] != '/') || - strncmp_icase(pathname, base, baselen)) + fspathncmp(pathname, base, baselen)) return 0; namelen = baselen ? pathlen - baselen - 1 : pathlen; @@ -858,7 +850,7 @@ int match_pathname(const char *pathname, int pathlen, if (prefix > namelen) return 0; - if (strncmp_icase(pattern, name, prefix)) + if (fspathncmp(pattern, name, prefix)) return 0; pattern += prefix; patternlen -= prefix; diff --git a/dir.h b/dir.h index cd46f30017..bfde698c48 100644 --- a/dir.h +++ b/dir.h @@ -27,7 +27,7 @@ struct exclude { int nowildcardlen; const char *base; int baselen; - int flags; + unsigned flags; /* EXC_FLAG_* */ /* * Counting starts from 1 for line numbers in ignore files, @@ -226,10 +226,10 @@ struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, * attr.c:path_matches() */ extern int match_basename(const char *, int, - const char *, int, int, int); + const char *, int, int, unsigned); extern int match_pathname(const char *, int, const char *, int, - const char *, int, int, int); + const char *, int, int, unsigned); extern struct exclude *last_exclude_matching(struct dir_struct *dir, const char *name, int *dtype); @@ -241,7 +241,7 @@ extern struct exclude_list *add_exclude_list(struct dir_struct *dir, extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen, struct exclude_list *el, int check_index); extern void add_excludes_from_file(struct dir_struct *, const char *fname); -extern void parse_exclude_pattern(const char **string, int *patternlen, int *flags, int *nowildcardlen); +extern void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen); extern void add_exclude(const char *string, const char *base, int baselen, struct exclude_list *el, int srcpos); extern void clear_exclude_list(struct exclude_list *el); @@ -270,9 +270,8 @@ extern int remove_dir_recursively(struct strbuf *path, int flag); /* tries to remove the path with empty directories along it, ignores ENOENT */ extern int remove_path(const char *path); -extern int strcmp_icase(const char *a, const char *b); -extern int strncmp_icase(const char *a, const char *b, size_t count); -extern int fnmatch_icase(const char *pattern, const char *string, int flags); +extern int fspathcmp(const char *a, const char *b); +extern int fspathncmp(const char *a, const char *b, size_t count); /* * The prefix part of pattern must not contains wildcards. diff --git a/editor.c b/editor.c index 01c644cddb..7519edecdc 100644 --- a/editor.c +++ b/editor.c @@ -63,7 +63,6 @@ int launch_editor(const char *path, struct strbuf *buffer, const char *const *en if (!buffer) return 0; if (strbuf_read_file(buffer, path, 0) < 0) - return error("could not read file '%s': %s", - path, strerror(errno)); + return error_errno("could not read file '%s'", path); return 0; } diff --git a/entry.c b/entry.c index a4109574fa..519e04227b 100644 --- a/entry.c +++ b/entry.c @@ -168,8 +168,8 @@ static int write_entry(struct cache_entry *ce, ret = symlink(new, path); free(new); if (ret) - return error("unable to create symlink %s (%s)", - path, strerror(errno)); + return error_errno("unable to create symlink %s", + path); break; } @@ -186,8 +186,7 @@ static int write_entry(struct cache_entry *ce, fd = open_output_fd(path, ce, to_tempfile); if (fd < 0) { free(new); - return error("unable to create file %s (%s)", - path, strerror(errno)); + return error_errno("unable to create file %s", path); } wrote = write_in_full(fd, new, size); @@ -284,8 +283,7 @@ int checkout_entry(struct cache_entry *ce, return error("%s is a directory", path.buf); remove_subtree(&path); } else if (unlink(path.buf)) - return error("unable to unlink old '%s' (%s)", - path.buf, strerror(errno)); + return error_errno("unable to unlink old '%s'", path.buf); } else if (state->not_new) return 0; diff --git a/environment.c b/environment.c index 6dec9d0403..ca72464a98 100644 --- a/environment.c +++ b/environment.c @@ -25,14 +25,13 @@ int log_all_ref_updates = -1; /* unspecified */ int warn_ambiguous_refs = 1; int warn_on_object_refname_ambiguity = 1; int ref_paranoia = -1; -int repository_format_version; int repository_format_precious_objects; const char *git_commit_encoding; const char *git_log_output_encoding; -int shared_repository = PERM_UMASK; const char *apply_default_whitespace; const char *apply_default_ignorewhitespace; const char *git_attributes_file; +const char *git_hooks_path; int zlib_compression_level = Z_BEST_SPEED; int core_compression_level; int core_compression_seen; @@ -64,8 +63,8 @@ int grafts_replace_parents = 1; int core_apply_sparse_checkout; int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ -struct startup_info *startup_info; unsigned long pack_size_limit_cfg; +enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; #ifndef PROTECT_HFS_DEFAULT #define PROTECT_HFS_DEFAULT 0 @@ -325,3 +324,24 @@ const char *get_commit_output_encoding(void) { return git_commit_encoding ? git_commit_encoding : "UTF-8"; } + +static int the_shared_repository = PERM_UMASK; +static int need_shared_repository_from_config = 1; + +void set_shared_repository(int value) +{ + the_shared_repository = value; + need_shared_repository_from_config = 0; +} + +int get_shared_repository(void) +{ + if (need_shared_repository_from_config) { + const char *var = "core.sharedrepository"; + const char *value; + if (!git_config_get_value(var, &value)) + the_shared_repository = git_config_perm(var, value); + need_shared_repository_from_config = 0; + } + return the_shared_repository; +} diff --git a/fast-import.c b/fast-import.c index 9fc7093406..c504ef752d 100644 --- a/fast-import.c +++ b/fast-import.c @@ -329,6 +329,7 @@ static const char *export_marks_file; static const char *import_marks_file; static int import_marks_file_from_stream; static int import_marks_file_ignore_missing; +static int import_marks_file_done; static int relative_marks_paths; /* Our last blob */ @@ -414,7 +415,7 @@ static void write_crash_report(const char *err) struct recent_command *rc; if (!rpt) { - error("can't write crash report %s: %s", loc, strerror(errno)); + error_errno("can't write crash report %s", loc); free(loc); return; } @@ -1512,7 +1513,7 @@ static int tree_content_set( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (!*slash1) { if (!S_ISDIR(mode) && e->versions[1].mode == mode @@ -1602,7 +1603,7 @@ static int tree_content_remove( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (*slash1 && !S_ISDIR(e->versions[1].mode)) /* * If p names a file in some subdirectory, and a @@ -1669,7 +1670,7 @@ static int tree_content_get( t = root->tree; for (i = 0; i < t->entry_count; i++) { e = t->entries[i]; - if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) { + if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) { if (!*slash1) goto found_entry; if (!S_ISDIR(e->versions[1].mode)) @@ -1802,12 +1803,12 @@ static void dump_marks(void) static struct lock_file mark_lock; FILE *f; - if (!export_marks_file) + if (!export_marks_file || (import_marks_file && !import_marks_file_done)) return; if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) { - failure |= error("Unable to write marks file %s: %s", - export_marks_file, strerror(errno)); + failure |= error_errno("Unable to write marks file %s", + export_marks_file); return; } @@ -1822,8 +1823,8 @@ static void dump_marks(void) dump_marks_helper(f, 0, marks); if (commit_lock_file(&mark_lock)) { - failure |= error("Unable to write file %s: %s", - export_marks_file, strerror(errno)); + failure |= error_errno("Unable to write file %s", + export_marks_file); return; } } @@ -1835,7 +1836,7 @@ static void read_marks(void) if (f) ; else if (import_marks_file_ignore_missing && errno == ENOENT) - return; /* Marks file does not exist */ + goto done; /* Marks file does not exist */ else die_errno("cannot read '%s'", import_marks_file); while (fgets(line, sizeof(line), f)) { @@ -1865,6 +1866,8 @@ static void read_marks(void) insert_mark(mark, e); } fclose(f); +done: + import_marks_file_done = 1; } diff --git a/fetch-pack.c b/fetch-pack.c index f96f6dfb35..b501d5c320 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -15,7 +15,6 @@ #include "version.h" #include "prio-queue.h" #include "sha1-array.h" -#include "sigchain.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -674,10 +673,8 @@ static int sideband_demux(int in, int out, void *data) int *xd = data; int ret; - sigchain_push(SIGPIPE, SIG_IGN); ret = recv_sideband("fetch-pack", xd[0], out); close(out); - sigchain_pop(SIGPIPE); return ret; } @@ -701,6 +698,7 @@ static int get_pack(struct fetch_pack_args *args, demux.proc = sideband_demux; demux.data = xd; demux.out = -1; + demux.isolate_sigpipe = 1; if (start_async(&demux)) die("fetch-pack: unable to fork off sideband" " demultiplexer"); diff --git a/fsck.c b/fsck.c index ca4c685377..05315451c5 100644 --- a/fsck.c +++ b/fsck.c @@ -59,6 +59,7 @@ FUNC(HAS_DOTGIT, WARN) \ FUNC(NULL_SHA1, WARN) \ FUNC(ZERO_PADDED_FILEMODE, WARN) \ + FUNC(NUL_IN_COMMIT, WARN) \ /* infos (reported as warnings, but ignored by default) */ \ FUNC(BAD_TAG_NAME, INFO) \ FUNC(MISSING_TAGGER_ENTRY, INFO) @@ -312,9 +313,9 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op if (S_ISGITLINK(entry.mode)) continue; if (S_ISDIR(entry.mode)) - result = options->walk(&lookup_tree(entry.sha1)->object, OBJ_TREE, data, options); + result = options->walk(&lookup_tree(entry.oid->hash)->object, OBJ_TREE, data, options); else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) - result = options->walk(&lookup_blob(entry.sha1)->object, OBJ_BLOB, data, options); + result = options->walk(&lookup_blob(entry.oid->hash)->object, OBJ_BLOB, data, options); else { result = error("in tree %s: entry %s has bad mode %.6o", oid_to_hex(&tree->object.oid), entry.path, entry.mode); @@ -450,11 +451,11 @@ static int fsck_tree(struct tree *item, struct fsck_options *options) while (desc.size) { unsigned mode; const char *name; - const unsigned char *sha1; + const struct object_id *oid; - sha1 = tree_entry_extract(&desc, &name, &mode); + oid = tree_entry_extract(&desc, &name, &mode); - has_null_sha1 |= is_null_sha1(sha1); + has_null_sha1 |= is_null_oid(oid); has_full_path |= !!strchr(name, '/'); has_empty_name |= !*name; has_dot |= !strcmp(name, "."); @@ -610,6 +611,7 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer, struct commit_graft *graft; unsigned parent_count, parent_line_count = 0, author_count; int err; + const char *buffer_begin = buffer; if (verify_headers(buffer, size, &commit->object, options)) return -1; @@ -666,9 +668,17 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer, err = fsck_ident(&buffer, &commit->object, options); if (err) return err; - if (!commit->tree) - return report(options, &commit->object, FSCK_MSG_BAD_TREE, "could not load commit's tree %s", sha1_to_hex(tree_sha1)); - + if (!commit->tree) { + err = report(options, &commit->object, FSCK_MSG_BAD_TREE, "could not load commit's tree %s", sha1_to_hex(tree_sha1)); + if (err) + return err; + } + if (memchr(buffer_begin, '\0', size)) { + err = report(options, &commit->object, FSCK_MSG_NUL_IN_COMMIT, + "NUL byte in the commit object body"); + if (err) + return err; + } return 0; } diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 77876d433a..822f857038 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -45,6 +45,7 @@ my $normal_color = $repo->get_color("", "reset"); my $diff_algorithm = $repo->config('diff.algorithm'); +my $diff_filter = $repo->config('interactive.difffilter'); my $use_readkey = 0; my $use_termcap = 0; @@ -754,7 +755,14 @@ sub parse_diff { my @diff = run_cmd_pipe("git", @diff_cmd, "--", $path); my @colored = (); if ($diff_use_color) { - @colored = run_cmd_pipe("git", @diff_cmd, qw(--color --), $path); + my @display_cmd = ("git", @diff_cmd, qw(--color --), $path); + if (defined $diff_filter) { + # quotemeta is overkill, but sufficient for shell-quoting + my $diff = join(' ', map { quotemeta } @display_cmd); + @display_cmd = ("$diff | $diff_filter"); + } + + @colored = run_cmd_pipe(@display_cmd); } my (@hunk) = { TEXT => [], DISPLAY => [], TYPE => 'header' }; @@ -765,7 +773,7 @@ sub parse_diff { } push @{$hunk[-1]{TEXT}}, $diff[$i]; push @{$hunk[-1]{DISPLAY}}, - ($diff_use_color ? $colored[$i] : $diff[$i]); + (@colored ? $colored[$i] : $diff[$i]); } return @hunk; } diff --git a/git-compat-util.h b/git-compat-util.h index 474395471f..49d4029b8d 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -279,9 +279,6 @@ extern char *gitdirname(char *); #endif #include #include -#ifdef NO_HMAC_CTX_CLEANUP -#define HMAC_CTX_cleanup HMAC_cleanup -#endif #endif /* On most systems would have given us this, but @@ -412,7 +409,9 @@ extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2))); extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); +extern int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); +extern void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2))); #ifndef NO_OPENSSL #ifdef APPLE_COMMON_CRYPTO diff --git a/git-cvsserver.perl b/git-cvsserver.perl index 02c0445be1..d50c85ed7b 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -1156,7 +1156,7 @@ sub prepDirForOutput # FUTURE: This would more accurately emulate CVS by sending # another copy of sticky after processing the files in that # directory. Or intermediate: perhaps send all sticky's for - # $seendirs after after processing all files. + # $seendirs after processing all files. } # update \n @@ -2824,7 +2824,7 @@ sub statecleanup } # Return working directory CVS revision "1.X" out -# of the the working directory "entries" state, for the given filename. +# of the working directory "entries" state, for the given filename. # This is prefixed with a dash if the file is scheduled for removal # when it is committed. sub revparse @@ -2935,7 +2935,7 @@ sub filecleanup return $filename; } -# Remove prependdir from the path, so that is is relative to the directory +# Remove prependdir from the path, so that it is relative to the directory # the CVS client was started from, rather than the top of the project. # Essentially the inverse of filecleanup(). sub remove_prependdir diff --git a/git-difftool--helper.sh b/git-difftool--helper.sh index 2b11b1d6fe..84d6cc021c 100755 --- a/git-difftool--helper.sh +++ b/git-difftool--helper.sh @@ -44,10 +44,10 @@ launch_merge_tool () { "$GIT_DIFF_PATH_TOTAL" "$MERGED" if use_ext_cmd then - printf "Launch '%s' [Y/n]: " \ + printf "Launch '%s' [Y/n]? " \ "$GIT_DIFFTOOL_EXTCMD" else - printf "Launch '%s' [Y/n]: " "$merge_tool" + printf "Launch '%s' [Y/n]? " "$merge_tool" fi read ans || return if test "$ans" = n diff --git a/git-difftool.perl b/git-difftool.perl index 488d14b153..ebd13baa6e 100755 --- a/git-difftool.perl +++ b/git-difftool.perl @@ -138,6 +138,7 @@ sub setup_dir_diff my %submodule; my %symlink; my @working_tree = (); + my %working_tree_dups = (); my @rawdiff = split('\0', $diffrtn); my $i = 0; @@ -188,6 +189,10 @@ sub setup_dir_diff } if ($rmode ne $null_mode) { + # Avoid duplicate working_tree entries + if ($working_tree_dups{$dst_path}++) { + next; + } my ($use, $wt_sha1) = use_wt_file($repo, $workdir, $dst_path, $rsha1); if ($use) { @@ -273,7 +278,7 @@ sub setup_dir_diff # temporary file to both the left and right directories to show the # change in the recorded SHA1 for the submodule. for my $path (keys %submodule) { - my $ok; + my $ok = 0; if (defined($submodule{$path}{left})) { $ok = write_to_file("$ldir/$path", "Subproject commit $submodule{$path}{left}"); @@ -289,7 +294,7 @@ sub setup_dir_diff # shows only the link itself, not the contents of the link target. # This loop replicates that behavior. for my $path (keys %symlink) { - my $ok; + my $ok = 0; if (defined($symlink{$path}{left})) { $ok = write_to_file("$ldir/$path", $symlink{$path}{left}); diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh index 8643f74cb0..dc2fd1b5a4 100755 --- a/git-merge-octopus.sh +++ b/git-merge-octopus.sh @@ -44,6 +44,12 @@ esac # MRC is the current "merge reference commit" # MRT is the current "merge result tree" +if ! git diff-index --quiet --cached HEAD -- +then + echo "Error: Your local changes to the following files would be overwritten by merge" + git diff-index --cached --name-only HEAD -- | sed -e 's/^/ /' + exit 2 +fi MRC=$(git rev-parse --verify -q $head) MRT=$(git write-tree) NON_FF_MERGE=0 diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh index 54ac8e4846..9abd00be21 100644 --- a/git-mergetool--lib.sh +++ b/git-mergetool--lib.sh @@ -100,7 +100,7 @@ check_unchanged () { while true do echo "$MERGED seems unchanged." - printf "Was the merge successful? [y/n] " + printf "Was the merge successful [y/n]? " read answer || return 1 case "$answer" in y*|Y*) return 0 ;; @@ -372,3 +372,28 @@ get_merge_tool () { fi echo "$merge_tool" } + +mergetool_find_win32_cmd () { + executable=$1 + sub_directory=$2 + + # Use $executable if it exists in $PATH + if type -p "$executable" >/dev/null 2>&1 + then + printf '%s' "$executable" + return + fi + + # Look for executable in the typical locations + for directory in $(env | grep -Ei '^PROGRAM(FILES(\(X86\))?|W6432)=' | + cut -d '=' -f 2- | sort -u) + do + if test -n "$directory" && test -x "$directory/$sub_directory/$executable" + then + printf '%s' "$directory/$sub_directory/$executable" + return + fi + done + + printf '%s' "$executable" +} diff --git a/git-mergetool.sh b/git-mergetool.sh index 9f77e3a8bb..bf862705d8 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -126,7 +126,12 @@ resolve_deleted_merge () { case "$ans" in [mMcC]*) git add -- "$MERGED" - cleanup_temp_files --save-backup + if test "$merge_keep_backup" = "true" + then + cleanup_temp_files --save-backup + else + cleanup_temp_files + fi return 0 ;; [dD]*) @@ -135,6 +140,10 @@ resolve_deleted_merge () { return 0 ;; [aA]*) + if test "$merge_keep_temporaries" = "false" + then + cleanup_temp_files + fi return 1 ;; esac @@ -282,8 +291,14 @@ merge_file () { return fi - mv -- "$MERGED" "$BACKUP" - cp -- "$BACKUP" "$MERGED" + if test -f "$MERGED" + then + mv -- "$MERGED" "$BACKUP" + cp -- "$BACKUP" "$MERGED" + fi + # Create a parent directory to handle delete/delete conflicts + # where the base's directory no longer exists. + mkdir -p "$(dirname "$MERGED")" checkout_staged_file 1 "$MERGED" "$BASE" checkout_staged_file 2 "$MERGED" "$LOCAL" @@ -295,7 +310,9 @@ merge_file () { describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" resolve_deleted_merge - return + status=$? + rmdir -p "$(dirname "$MERGED")" 2>/dev/null + return $status fi if is_symlink "$local_mode" || is_symlink "$remote_mode" @@ -396,7 +413,7 @@ done prompt_after_failed_merge () { while true do - printf "Continue merging other unresolved paths (y/n) ? " + printf "Continue merging other unresolved paths [y/n]? " read ans || return 1 case "$ans" in [yY]*) diff --git a/git-p4.py b/git-p4.py index 825b9f32d5..b6593cf9a1 100755 --- a/git-p4.py +++ b/git-p4.py @@ -1064,8 +1064,15 @@ def generatePointer(self, contentFile): if pointerProcess.wait(): os.remove(contentFile) die('git-lfs pointer command failed. Did you install the extension?') - pointerContents = [i+'\n' for i in pointerFile.split('\n')[2:][:-1]] - oid = pointerContents[1].split(' ')[1].split(':')[1][:-1] + + # Git LFS removed the preamble in the output of the 'pointer' command + # starting from version 1.2.0. Check for the preamble here to support + # earlier versions. + # c.f. https://github.com/github/git-lfs/commit/da2935d9a739592bc775c98d8ef4df9c72ea3b43 + if pointerFile.startswith('Git LFS pointer for'): + pointerFile = re.sub(r'Git LFS pointer for.*\n\n', '', pointerFile) + + oid = re.search(r'^oid \w+:(\w+)', pointerFile, re.MULTILINE).group(1) localLargeFile = os.path.join( os.getcwd(), '.git', 'lfs', 'objects', oid[:2], oid[2:4], @@ -1073,7 +1080,7 @@ def generatePointer(self, contentFile): ) # LFS Spec states that pointer files should not have the executable bit set. gitMode = '100644' - return (gitMode, pointerContents, localLargeFile) + return (gitMode, pointerFile, localLargeFile) def pushFile(self, localLargeFile): uploadProcess = subprocess.Popen( @@ -1160,6 +1167,15 @@ def getUserMapFromPerforceServer(self): self.users[output["User"]] = output["FullName"] + " <" + output["Email"] + ">" self.emails[output["Email"]] = output["User"] + mapUserConfigRegex = re.compile(r"^\s*(\S+)\s*=\s*(.+)\s*<(\S+)>\s*$", re.VERBOSE) + for mapUserConfig in gitConfigList("git-p4.mapUser"): + mapUser = mapUserConfigRegex.findall(mapUserConfig) + if mapUser and len(mapUser[0]) == 3: + user = mapUser[0][0] + fullname = mapUser[0][1] + email = mapUser[0][2] + self.users[user] = fullname + " <" + email + ">" + self.emails[email] = user s = '' for (key, val) in self.users.items(): @@ -2311,6 +2327,15 @@ def extractFilesFromCommit(self, commit): fnum = fnum + 1 return files + def extractJobsFromCommit(self, commit): + jobs = [] + jnum = 0 + while commit.has_key("job%s" % jnum): + job = commit["job%s" % jnum] + jobs.append(job) + jnum = jnum + 1 + return jobs + def stripRepoPath(self, path, prefixes): """When streaming files, this is called to map a p4 depot path to where it should go in git. The prefixes are either @@ -2656,6 +2681,7 @@ def hasBranchPrefix(self, path): def commit(self, details, files, branch, parent = ""): epoch = details["time"] author = details["user"] + jobs = self.extractJobsFromCommit(details) if self.verbose: print('commit into {0}'.format(branch)) @@ -2683,6 +2709,8 @@ def commit(self, details, files, branch, parent = ""): self.gitStream.write("data < 0: + self.gitStream.write("\nJobs: %s" % (' '.join(jobs))) self.gitStream.write("\n[git-p4: depot-paths = \"%s\": change = %s" % (','.join(self.branchPrefixes), details["change"])) if len(details['options']) > 0: diff --git a/git-parse-remote.sh b/git-parse-remote.sh index 55fe8d56c9..d3c39980f3 100644 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -56,11 +56,13 @@ get_remote_merge_branch () { error_on_missing_default_upstream () { cmd="$1" op_type="$2" - op_prep="$3" + op_prep="$3" # FIXME: op_prep is no longer used example="$4" branch_name=$(git symbolic-ref -q HEAD) + display_branch_name="${branch_name#refs/heads/}" # If there's only one remote, use that in the suggestion - remote="" + remote="$(gettext "")" + branch="$(gettext "")" if test $(git remote | wc -l) = 1 then remote=$(git remote) @@ -68,22 +70,32 @@ error_on_missing_default_upstream () { if test -z "$branch_name" then - echo "You are not currently on a branch. Please specify which -branch you want to $op_type $op_prep. See git-${cmd}(1) for details. - - $example -" + gettextln "You are not currently on a branch." else - echo "There is no tracking information for the current branch. -Please specify which branch you want to $op_type $op_prep. -See git-${cmd}(1) for details - - $example - -If you wish to set tracking information for this branch you can do so with: - - git branch --set-upstream-to=$remote/ ${branch_name#refs/heads/} -" + gettextln "There is no tracking information for the current branch." + fi + case "$op_type" in + rebase) + gettextln "Please specify which branch you want to rebase against." + ;; + merge) + gettextln "Please specify which branch you want to merge with." + ;; + *) + echo >&2 "BUG: unknown operation type: $op_type" + exit 1 + ;; + esac + eval_gettextln "See git-\${cmd}(1) for details." + echo + echo " $example" + echo + if test -n "$branch_name" + then + gettextln "If you wish to set tracking information for this branch you can do so with:" + echo + echo " git branch --set-upstream-to=$remote/$branch $display_branch_name" + echo fi exit 1 } diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 4cde685b43..6e96abcc3c 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -82,6 +82,7 @@ rewritten_pending="$state_dir"/rewritten-pending cr=$(printf "\015") strategy_args=${strategy:+--strategy=$strategy} +test -n "$strategy_opts" && eval ' for strategy_opt in '"$strategy_opts"' do @@ -191,7 +192,6 @@ make_patch () { die_with_patch () { echo "$1" > "$state_dir"/stopped-sha make_patch "$1" - git rerere die "$2" } @@ -548,7 +548,8 @@ do_next () { mark_action_done do_pick $sha1 "$rest" - warn "Stopped at $sha1... $rest" + sha1_abbrev=$(git rev-parse --short $sha1) + warn "Stopped at $sha1_abbrev... $rest" exit_with_patch $sha1 0 ;; squash|s|fixup|f) @@ -865,12 +866,12 @@ add_exec_commands () { # $3: the input filename check_commit_sha () { badsha=0 - if test -z $1 + if test -z "$1" then badsha=1 else sha1_verif="$(git rev-parse --verify --quiet $1^{commit})" - if test -z $sha1_verif + if test -z "$sha1_verif" then badsha=1 fi diff --git a/git-rebase--merge.sh b/git-rebase--merge.sh index 2cc2a6d273..8d43db9069 100644 --- a/git-rebase--merge.sh +++ b/git-rebase--merge.sh @@ -67,7 +67,9 @@ call_merge () { GIT_MERGE_VERBOSITY=1 && export GIT_MERGE_VERBOSITY fi test -z "$strategy" && strategy=recursive - eval 'git-merge-$strategy' $strategy_opts '"$cmt^" -- "$hd" "$cmt"' + # If cmt doesn't have a parent, don't include it as a base + base=$(git rev-parse --verify --quiet $cmt^) + eval 'git-merge-$strategy' $strategy_opts $base ' -- "$hd" "$cmt"' rv=$? case "$rv" in 0) diff --git a/git-rebase.sh b/git-rebase.sh index cf60c43908..44ede367ae 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -87,7 +87,10 @@ preserve_merges= autosquash= keep_empty= test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t -gpg_sign_opt= +case "$(git config --bool commit.gpgsign)" in +true) gpg_sign_opt=-S ;; +*) gpg_sign_opt= ;; +esac read_basic_state () { test -f "$state_dir/head-name" && @@ -248,6 +251,7 @@ do ;; --exec=*) cmd="${cmd}exec ${1#--exec=}${LF}" + test -z "$interactive_rebase" && interactive_rebase=implied ;; --interactive) interactive_rebase=explicit @@ -348,12 +352,6 @@ do done test $# -gt 2 && usage -if test -n "$cmd" && - test "$interactive_rebase" != explicit -then - die "$(gettext "The --exec option must be used with the --interactive option")" -fi - if test -n "$action" then test -z "$in_progress" && die "$(gettext "No rebase in progress?")" diff --git a/git-send-email.perl b/git-send-email.perl index d356901348..69587856df 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -19,10 +19,10 @@ use 5.008; use strict; use warnings; +use POSIX qw/strftime/; use Term::ReadLine; use Getopt::Long; use Text::ParseWords; -use Data::Dumper; use Term::ANSIColor; use File::Temp qw/ tempdir tempfile /; use File::Spec::Functions qw(catfile); @@ -533,7 +533,7 @@ sub parse_sendmail_aliases { $aliases{$alias} = \@addr }}}, mailrc => sub { my $fh = shift; while (<$fh>) { - if (/^alias\s+(\S+)\s+(.*)$/) { + if (/^alias\s+(\S+)\s+(.*?)\s*$/) { # spaces delimit multiple addresses $aliases{$1} = [ quotewords('\s+', 0, $2) ]; }}}, @@ -827,9 +827,10 @@ sub file_declares_8bit_cte { # But it's a no-op to run sanitize_address on an already sanitized address. $sender = sanitize_address($sender); +my $to_whom = "To whom should the emails be sent (if anyone)?"; my $prompting = 0; if (!@initial_to && !defined $to_cmd) { - my $to = ask("Who should the emails be sent to (if any)? ", + my $to = ask("$to_whom ", default => "", valid_re => qr/\@.*\./, confirm_only => 1); push @initial_to, parse_address_line($to) if defined $to; # sanitized/validated later @@ -924,7 +925,7 @@ sub validate_address { cleanup_compose_files(); exit(0); } - $address = ask("Who should the email be sent to (if any)? ", + $address = ask("$to_whom ", default => "", valid_re => qr/\@.*\./, confirm_only => 1); } @@ -949,7 +950,7 @@ sub validate_address_list { sub make_message_id { my $uniq; if (!defined $message_id_stamp) { - $message_id_stamp = sprintf("%s-%s", time, $$); + $message_id_stamp = strftime("%Y%m%d%H%M%S.$$", gmtime(time)); $message_id_serial = 0; } $message_id_serial++; @@ -964,7 +965,7 @@ sub make_message_id { require Sys::Hostname; $du_part = 'user@' . Sys::Hostname::hostname(); } - my $message_id_template = "<%s-git-send-email-%s>"; + my $message_id_template = "<%s-%s>"; $message_id = sprintf($message_id_template, $uniq, $du_part); #print "new message id = $message_id\n"; # Was useful for debugging } diff --git a/git-stash.sh b/git-stash.sh index c7c65e25f5..c7509e8da4 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -185,7 +185,7 @@ store_stash () { git update-ref --create-reflog -m "$stash_msg" $ref_stash $w_commit ret=$? - test $ret != 0 && test -z $quiet && + test $ret != 0 && test -z "$quiet" && die "$(eval_gettext "Cannot update \$ref_stash with \$w_commit")" return $ret } @@ -277,7 +277,7 @@ save_stash () { git clean --force --quiet -d $CLEAN_X_OPTION fi - if test "$keep_index" = "t" && test -n $i_tree + if test "$keep_index" = "t" && test -n "$i_tree" then git read-tree --reset -u $i_tree fi diff --git a/git-submodule.sh b/git-submodule.sh index 43c68deee9..7fe8a511b3 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /') USAGE="[--quiet] add [-b ] [-f|--force] [--name ] [--reference ] [--] [] or: $dashless [--quiet] status [--cached] [--recursive] [--] [...] or: $dashless [--quiet] init [--] [...] - or: $dashless [--quiet] deinit [-f|--force] [--] ... + or: $dashless [--quiet] deinit [-f|--force] (--all| [--] ...) or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--reference ] [--recursive] [--] [...] or: $dashless [--quiet] summary [--cached|--files] [--summary-limit ] [commit] [--] [...] or: $dashless [--quiet] foreach [--recursive] @@ -46,114 +46,6 @@ prefix= custom_name= depth= -# The function takes at most 2 arguments. The first argument is the -# URL that navigates to the submodule origin repo. When relative, this URL -# is relative to the superproject origin URL repo. The second up_path -# argument, if specified, is the relative path that navigates -# from the submodule working tree to the superproject working tree. -# -# The output of the function is the origin URL of the submodule. -# -# The output will either be an absolute URL or filesystem path (if the -# superproject origin URL is an absolute URL or filesystem path, -# respectively) or a relative file system path (if the superproject -# origin URL is a relative file system path). -# -# When the output is a relative file system path, the path is either -# relative to the submodule working tree, if up_path is specified, or to -# the superproject working tree otherwise. -resolve_relative_url () -{ - remote=$(get_default_remote) - remoteurl=$(git config "remote.$remote.url") || - remoteurl=$(pwd) # the repository is its own authoritative upstream - url="$1" - remoteurl=${remoteurl%/} - sep=/ - up_path="$2" - - case "$remoteurl" in - *:*|/*) - is_relative= - ;; - ./*|../*) - is_relative=t - ;; - *) - is_relative=t - remoteurl="./$remoteurl" - ;; - esac - - while test -n "$url" - do - case "$url" in - ../*) - url="${url#../}" - case "$remoteurl" in - */*) - remoteurl="${remoteurl%/*}" - ;; - *:*) - remoteurl="${remoteurl%:*}" - sep=: - ;; - *) - if test -z "$is_relative" || test "." = "$remoteurl" - then - die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")" - else - remoteurl=. - fi - ;; - esac - ;; - ./*) - url="${url#./}" - ;; - *) - break;; - esac - done - remoteurl="$remoteurl$sep${url%/}" - echo "${is_relative:+${up_path}}${remoteurl#./}" -} - -# Resolve a path to be relative to another path. This is intended for -# converting submodule paths when git-submodule is run in a subdirectory -# and only handles paths where the directory separator is '/'. -# -# The output is the first argument as a path relative to the second argument, -# which defaults to $wt_prefix if it is omitted. -relative_path () -{ - local target curdir result - target=$1 - curdir=${2-$wt_prefix} - curdir=${curdir%/} - result= - - while test -n "$curdir" - do - case "$target" in - "$curdir/"*) - target=${target#"$curdir"/} - break - ;; - esac - - result="${result}../" - if test "$curdir" = "${curdir%/*}" - then - curdir= - else - curdir="${curdir%/*}" - fi - done - - echo "$result$target" -} - die_if_unmatched () { if test "$1" = "#unmatched" @@ -192,6 +84,17 @@ isnumber() n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1" } +# Sanitize the local git environment for use within a submodule. We +# can't simply use clear_local_git_env since we want to preserve some +# of the settings from GIT_CONFIG_PARAMETERS. +sanitize_submodule_env() +{ + save_config=$GIT_CONFIG_PARAMETERS + clear_local_git_env + GIT_CONFIG_PARAMETERS=$save_config + export GIT_CONFIG_PARAMETERS +} + # # Add a new submodule to the working tree, .gitmodules and the index # @@ -281,7 +184,7 @@ cmd_add() die "$(gettext "Relative path can only be used from the toplevel of the working tree")" # dereference source url relative to parent's url - realrepo=$(resolve_relative_url "$repo") || exit + realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit ;; *:*|/*) # absolute url @@ -347,9 +250,9 @@ Use -f if you really want to add it." >&2 echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")" fi fi - git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" "$reference" "$depth" || exit + git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${depth:+"$depth"} || exit ( - clear_local_git_env + sanitize_submodule_env cd "$sm_path" && # ash fails to wordsplit ${branch:+-b "$branch"...} case "$branch" in @@ -407,20 +310,23 @@ cmd_foreach() # command in the subshell (and a recursive call to this function) exec 3<&0 - git submodule--helper list --prefix "$wt_prefix"| + { + git submodule--helper list --prefix "$wt_prefix" || + echo "#unmatched" + } | while read mode sha1 stage sm_path do die_if_unmatched "$mode" if test -e "$sm_path"/.git then - displaypath=$(relative_path "$sm_path") - say "$(eval_gettext "Entering '\$prefix\$displaypath'")" + displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") + say "$(eval_gettext "Entering '\$displaypath'")" name=$(git submodule--helper name "$sm_path") ( prefix="$prefix$sm_path/" - clear_local_git_env + sanitize_submodule_env cd "$sm_path" && - sm_path=$(relative_path "$sm_path") && + sm_path=$(git submodule--helper relative-path "$sm_path" "$wt_prefix") && # we make $path available to scripts ... path=$sm_path && if test $# -eq 1 @@ -434,7 +340,7 @@ cmd_foreach() cmd_foreach "--recursive" "$@" fi ) <&3 3<&- || - die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")" + die "$(eval_gettext "Stopping at '\$displaypath'; script returned non-zero status.")" fi done } @@ -467,50 +373,7 @@ cmd_init() shift done - git submodule--helper list --prefix "$wt_prefix" "$@" | - while read mode sha1 stage sm_path - do - die_if_unmatched "$mode" - name=$(git submodule--helper name "$sm_path") || exit - - displaypath=$(relative_path "$sm_path") - - # Copy url setting when it is not set yet - if test -z "$(git config "submodule.$name.url")" - then - url=$(git config -f .gitmodules submodule."$name".url) - test -z "$url" && - die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")" - - # Possibly a url relative to parent - case "$url" in - ./*|../*) - url=$(resolve_relative_url "$url") || exit - ;; - esac - git config submodule."$name".url "$url" || - die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")" - - say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")" - fi - - # Copy "update" setting when it is not set yet - if upd="$(git config -f .gitmodules submodule."$name".update)" && - test -n "$upd" && - test -z "$(git config submodule."$name".update)" - then - case "$upd" in - checkout | rebase | merge | none) - ;; # known modes of updating - *) - echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'" - upd=none - ;; - esac - git config submodule."$name".update "$upd" || - die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")" - fi - done + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} "$@" } # @@ -521,6 +384,7 @@ cmd_init() cmd_deinit() { # parse $args after "submodule ... deinit". + deinit_all= while test $# -ne 0 do case "$1" in @@ -530,6 +394,9 @@ cmd_deinit() -q|--quiet) GIT_QUIET=1 ;; + --all) + deinit_all=t + ;; --) shift break @@ -544,18 +411,26 @@ cmd_deinit() shift done - if test $# = 0 + if test -n "$deinit_all" && test "$#" -ne 0 + then + echo >&2 "$(eval_gettext "pathspec and --all are incompatible")" + usage + fi + if test $# = 0 && test -z "$deinit_all" then - die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")" + die "$(eval_gettext "Use '--all' if you really want to deinitialize all submodules")" fi - git submodule--helper list --prefix "$wt_prefix" "$@" | + { + git submodule--helper list --prefix "$wt_prefix" "$@" || + echo "#unmatched" + } | while read mode sha1 stage sm_path do die_if_unmatched "$mode" name=$(git submodule--helper name "$sm_path") || exit - displaypath=$(relative_path "$sm_path") + displaypath=$(git submodule--helper relative-path "$sm_path" "$wt_prefix") # Remove the submodule work tree (unless the user already did it) if test -d "$sm_path" @@ -592,14 +467,14 @@ cmd_deinit() } is_tip_reachable () ( - clear_local_git_env + sanitize_submodule_env && cd "$1" && rev=$(git rev-list -n 1 "$2" --not --all 2>/dev/null) && test -z "$rev" ) fetch_in_submodule () ( - clear_local_git_env + sanitize_submodule_env && cd "$1" && case "$2" in '') @@ -663,6 +538,14 @@ cmd_update() --depth=*) depth=$1 ;; + -j|--jobs) + case "$2" in '') usage ;; esac + jobs="--jobs=$2" + shift + ;; + --jobs=*) + jobs=$1 + ;; --) shift break @@ -682,17 +565,21 @@ cmd_update() cmd_init "--" "$@" || return fi - cloned_modules= - git submodule--helper list --prefix "$wt_prefix" "$@" | { + { + git submodule--helper update-clone ${GIT_QUIET:+--quiet} \ + ${wt_prefix:+--prefix "$wt_prefix"} \ + ${prefix:+--recursive-prefix "$prefix"} \ + ${update:+--update "$update"} \ + ${reference:+--reference "$reference"} \ + ${depth:+--depth "$depth"} \ + ${jobs:+$jobs} \ + "$@" || echo "#unmatched" + } | { err= - while read mode sha1 stage sm_path + while read mode sha1 stage just_cloned sm_path do die_if_unmatched "$mode" - if test "$stage" = U - then - echo >&2 "Skipping unmerged submodule $prefix$sm_path" - continue - fi + name=$(git submodule--helper name "$sm_path") || exit url=$(git config submodule."$name".url) branch=$(get_submodule_config "$name" branch master) @@ -707,31 +594,14 @@ cmd_update() fi fi - displaypath=$(relative_path "$prefix$sm_path") + displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") - if test "$update_module" = "none" + if test $just_cloned -eq 1 then - echo "Skipping submodule '$displaypath'" - continue - fi - - if test -z "$url" - then - # Only mention uninitialized submodules when its - # path have been specified - test "$#" != "0" && - say "$(eval_gettext "Submodule path '\$displaypath' not initialized -Maybe you want to use 'update --init'?")" - continue - fi - - if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git - then - git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit - cloned_modules="$cloned_modules;$name" subsha1= + update_module=checkout else - subsha1=$(clear_local_git_env; cd "$sm_path" && + subsha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD) || die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")" fi @@ -741,11 +611,11 @@ Maybe you want to use 'update --init'?")" if test -z "$nofetch" then # Fetch remote before determining tracking $sha1 - (clear_local_git_env; cd "$sm_path" && git-fetch) || + (sanitize_submodule_env; cd "$sm_path" && git-fetch) || die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")" fi - remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote) - sha1=$(clear_local_git_env; cd "$sm_path" && + remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote) + sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify "${remote_name}/${branch}") || die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")" fi @@ -774,13 +644,6 @@ Maybe you want to use 'update --init'?")" die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain $sha1. Direct fetching of that commit failed.")" fi - # Is this something we just cloned? - case ";$cloned_modules;" in - *";$name;"*) - # then there is no local change to integrate - update_module=checkout ;; - esac - must_die_on_failure= case "$update_module" in checkout) @@ -802,15 +665,15 @@ Maybe you want to use 'update --init'?")" ;; !*) command="${update_module#!}" - die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")" - say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")" + die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$displaypath'")" + say_msg="$(eval_gettext "Submodule path '\$displaypath': '\$command \$sha1'")" must_die_on_failure=yes ;; *) die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")" esac - if (clear_local_git_env; cd "$sm_path" && $command "$sha1") + if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1") then say "$say_msg" elif test -n "$must_die_on_failure" @@ -825,8 +688,9 @@ Maybe you want to use 'update --init'?")" if test -n "$recursive" then ( - prefix="$prefix$sm_path/" - clear_local_git_env + prefix=$(git submodule--helper relative-path "$prefix$sm_path/" "$wt_prefix") + wt_prefix= + sanitize_submodule_env cd "$sm_path" && eval cmd_update ) @@ -864,7 +728,7 @@ Maybe you want to use 'update --init'?")" set_name_rev () { revname=$( ( - clear_local_git_env + sanitize_submodule_env cd "$1" && { git describe "$2" 2>/dev/null || git describe --tags "$2" 2>/dev/null || @@ -1008,7 +872,7 @@ cmd_summary() { ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null && missing_dst=t - display_name=$(relative_path "$name") + display_name=$(git submodule--helper relative-path "$name" "$wt_prefix") total_commits= case "$missing_src,$missing_dst" in @@ -1120,13 +984,16 @@ cmd_status() shift done - git submodule--helper list --prefix "$wt_prefix" "$@" | + { + git submodule--helper list --prefix "$wt_prefix" "$@" || + echo "#unmatched" + } | while read mode sha1 stage sm_path do die_if_unmatched "$mode" name=$(git submodule--helper name "$sm_path") || exit url=$(git config submodule."$name".url) - displaypath=$(relative_path "$prefix$sm_path") + displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") if test "$stage" = U then say "U$sha1 $displaypath" @@ -1148,7 +1015,7 @@ cmd_status() else if test -z "$cached" then - sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD) + sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD) fi set_name_rev "$sm_path" "$sha1" say "+$sha1 $displaypath$revname" @@ -1158,7 +1025,8 @@ cmd_status() then ( prefix="$displaypath/" - clear_local_git_env + sanitize_submodule_env + wt_prefix= cd "$sm_path" && eval cmd_status ) || @@ -1197,7 +1065,10 @@ cmd_sync() esac done cd_to_toplevel - git submodule--helper list --prefix "$wt_prefix" "$@" | + { + git submodule--helper list --prefix "$wt_prefix" "$@" || + echo "#unmatched" + } | while read mode sha1 stage sm_path do die_if_unmatched "$mode" @@ -1213,9 +1084,9 @@ cmd_sync() # guarantee a trailing / up_path=${up_path%/}/ && # path from submodule work tree to submodule origin repo - sub_origin_url=$(resolve_relative_url "$url" "$up_path") && + sub_origin_url=$(git submodule--helper resolve-relative-url "$url" "$up_path") && # path from superproject work tree to submodule origin repo - super_config_url=$(resolve_relative_url "$url") || exit + super_config_url=$(git submodule--helper resolve-relative-url "$url") || exit ;; *) sub_origin_url="$url" @@ -1225,14 +1096,14 @@ cmd_sync() if git config "submodule.$name.url" >/dev/null 2>/dev/null then - displaypath=$(relative_path "$prefix$sm_path") + displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")" git config submodule."$name".url "$super_config_url" if test -e "$sm_path"/.git then ( - clear_local_git_env + sanitize_submodule_env cd "$sm_path" remote=$(get_default_remote) git config remote."$remote".url "$sub_origin_url" diff --git a/git.c b/git.c index 6cc0c077f9..968a8a4645 100644 --- a/git.c +++ b/git.c @@ -15,7 +15,6 @@ const char git_more_info_string[] = "concept guides. See 'git help ' or 'git help '\n" "to read about a specific subcommand or concept."); -static struct startup_info git_startup_info; static int use_pager = -1; static char *orig_cwd; static const char *env_names[] = { @@ -637,8 +636,6 @@ int main(int argc, char **av) const char *cmd; int done_help = 0; - startup_info = &git_startup_info; - cmd = git_extract_argv0_path(argv[0]); if (!cmd) cmd = "git-help"; diff --git a/git.spec.in b/git.spec.in deleted file mode 100644 index d61d537ef0..0000000000 --- a/git.spec.in +++ /dev/null @@ -1,330 +0,0 @@ -# Pass --without docs to rpmbuild if you don't want the documentation - -Name: git -Version: @@VERSION@@ -Release: 1%{?dist} -Summary: Core git tools -License: GPL -Group: Development/Tools -URL: http://kernel.org/pub/software/scm/git/ -Source: http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz -BuildRequires: zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel, gettext %{!?_without_docs:, xmlto, asciidoc > 6.0.3} -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) - -Requires: perl-Git = %{version}-%{release} -Requires: zlib >= 1.2, rsync, less, openssh-clients, expat -Provides: git-core = %{version}-%{release} -Obsoletes: git-core <= 1.5.4.2 -Obsoletes: git-p4 - -%description -Git is a fast, scalable, distributed revision control system with an -unusually rich command set that provides both high-level operations -and full access to internals. - -The git rpm installs the core tools with minimal dependencies. To -install all git packages, including tools for integrating with other -SCMs, install the git-all meta-package. - -%package all -Summary: Meta-package to pull in all git tools -Group: Development/Tools -Requires: git = %{version}-%{release} -Requires: git-svn = %{version}-%{release} -Requires: git-cvs = %{version}-%{release} -Requires: git-arch = %{version}-%{release} -Requires: git-email = %{version}-%{release} -Requires: gitk = %{version}-%{release} -Requires: gitweb = %{version}-%{release} -Requires: git-gui = %{version}-%{release} -Obsoletes: git <= 1.5.4.2 - -%description all -Git is a fast, scalable, distributed revision control system with an -unusually rich command set that provides both high-level operations -and full access to internals. - -This is a dummy package which brings in all subpackages. - -%package svn -Summary: Git tools for importing Subversion repositories -Group: Development/Tools -Requires: git = %{version}-%{release}, subversion -%description svn -Git tools for importing Subversion repositories. - -%package cvs -Summary: Git tools for importing CVS repositories -Group: Development/Tools -Requires: git = %{version}-%{release}, cvs, cvsps -%description cvs -Git tools for importing CVS repositories. - -%package arch -Summary: Git tools for importing Arch repositories -Group: Development/Tools -Requires: git = %{version}-%{release}, tla -%description arch -Git tools for importing Arch repositories. - -%package email -Summary: Git tools for sending email -Group: Development/Tools -Requires: git = %{version}-%{release} -%description email -Git tools for sending email. - -%package gui -Summary: Git GUI tool -Group: Development/Tools -Requires: git = %{version}-%{release}, tk >= 8.4 -%description gui -Git GUI tool - -%package -n gitk -Summary: Git revision tree visualiser ('gitk') -Group: Development/Tools -Requires: git = %{version}-%{release}, tk >= 8.4 -%description -n gitk -Git revision tree visualiser ('gitk') - -%package -n gitweb -Summary: Git web interface -Group: Development/Tools -Requires: git = %{version}-%{release} -%description -n gitweb -Browsing git repository on the web - -%package -n perl-Git -Summary: Perl interface to Git -Group: Development/Libraries -Requires: git = %{version}-%{release} -Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) -BuildRequires: perl(Error) -BuildRequires: perl(ExtUtils::MakeMaker) - -%description -n perl-Git -Perl interface to Git - -%define path_settings ETC_GITCONFIG=/etc/gitconfig prefix=%{_prefix} mandir=%{_mandir} htmldir=%{_docdir}/%{name}-%{version} -%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} - -%prep -%setup -q - -%build -make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" \ - %{path_settings} \ - all %{!?_without_docs: doc} - -%install -rm -rf $RPM_BUILD_ROOT -make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" DESTDIR=$RPM_BUILD_ROOT \ - %{path_settings} \ - INSTALLDIRS=vendor install %{!?_without_docs: install-doc} -test ! -d $RPM_BUILD_ROOT%{python_sitelib} || rm -fr $RPM_BUILD_ROOT%{python_sitelib} -find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';' -find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';' -find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';' - -(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files -(find $RPM_BUILD_ROOT%{_libexecdir}/git-core -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) >> bin-man-doc-files -(find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files -%if %{!?_without_docs:1}0 -(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files -%else -rm -rf $RPM_BUILD_ROOT%{_mandir} -%endif -rm -rf $RPM_BUILD_ROOT%{_datadir}/locale - -mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d -install -m 644 -T contrib/completion/git-completion.bash $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d/git - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -f bin-man-doc-files -%defattr(-,root,root) -%{_datadir}/git-core/ -%doc README COPYING Documentation/*.txt -%{!?_without_docs: %doc Documentation/*.html Documentation/howto} -%{!?_without_docs: %doc Documentation/technical} -%{_sysconfdir}/bash_completion.d - -%files svn -%defattr(-,root,root) -%{_libexecdir}/git-core/*svn* -%doc Documentation/*svn*.txt -%{!?_without_docs: %{_mandir}/man1/*svn*.1*} -%{!?_without_docs: %doc Documentation/*svn*.html } - -%files cvs -%defattr(-,root,root) -%doc Documentation/*git-cvs*.txt -%{_bindir}/git-cvsserver -%{_libexecdir}/git-core/*cvs* -%{!?_without_docs: %{_mandir}/man1/*cvs*.1*} -%{!?_without_docs: %doc Documentation/*git-cvs*.html } - -%files arch -%defattr(-,root,root) -%doc Documentation/git-archimport.txt -%{_libexecdir}/git-core/git-archimport -%{!?_without_docs: %{_mandir}/man1/git-archimport.1*} -%{!?_without_docs: %doc Documentation/git-archimport.html } - -%files email -%defattr(-,root,root) -%doc Documentation/*email*.txt -%{_libexecdir}/git-core/*email* -%{!?_without_docs: %{_mandir}/man1/*email*.1*} -%{!?_without_docs: %doc Documentation/*email*.html } - -%files gui -%defattr(-,root,root) -%{_libexecdir}/git-core/git-gui -%{_libexecdir}/git-core/git-citool -%{_libexecdir}/git-core/git-gui--askpass -%{_datadir}/git-gui/ -%{!?_without_docs: %{_mandir}/man1/git-gui.1*} -%{!?_without_docs: %doc Documentation/git-gui.html} -%{!?_without_docs: %{_mandir}/man1/git-citool.1*} -%{!?_without_docs: %doc Documentation/git-citool.html} - -%files -n gitk -%defattr(-,root,root) -%doc Documentation/*gitk*.txt -%{_bindir}/*gitk* -%{_datadir}/gitk/ -%{!?_without_docs: %{_mandir}/man1/*gitk*.1*} -%{!?_without_docs: %doc Documentation/*gitk*.html } - -%files -n gitweb -%defattr(-,root,root) -%doc gitweb/README gitweb/INSTALL Documentation/*gitweb*.txt -%{_datadir}/gitweb -%{!?_without_docs: %{_mandir}/man1/*gitweb*.1*} -%{!?_without_docs: %{_mandir}/man5/*gitweb*.5*} -%{!?_without_docs: %doc Documentation/*gitweb*.html } - -%files -n perl-Git -f perl-files -%defattr(-,root,root) - -%files all -# No files for you! - -%changelog -* Sun Sep 18 2011 Jakub Narebski -- Add gitweb manpages to 'gitweb' subpackage - -* Wed Jun 30 2010 Junio C Hamano -- Add 'gitweb' subpackage. - -* Fri Mar 26 2010 Ian Ward Comfort -- Ship bash completion support from contrib/ in the core package. - -* Sun Jan 31 2010 Junio C Hamano -- Do not use %define inside %{!?...} construct. - -* Sat Jan 30 2010 Junio C Hamano -- We don't ship Python bits until a real foreign scm interface comes. - -* Mon Feb 04 2009 David J. Mellor -- fixed broken git help -w after renaming the git-core package to git. - -* Fri Sep 12 2008 Quy Tonthat -- move git-cvsserver to bindir. - -* Sun Jun 15 2008 Junio C Hamano -- Remove curl from Requires list. - -* Fri Feb 15 2008 Kristian Høgsberg -- Rename git-core to just git and rename meta package from git to git-all. - -* Sun Feb 03 2008 James Bowes -- Add a BuildRequires for gettext - -* Fri Jan 11 2008 Junio C Hamano -- Include gitk message files - -* Sun Jan 06 2008 James Bowes -- Make the metapackage require the same version of the subpackages. - -* Wed Dec 12 2007 Junio C Hamano -- Adjust htmldir to point at /usr/share/doc/git-core-$version/ - -* Sun Jul 15 2007 Sean Estabrooks -- Removed p4import. - -* Tue Jun 26 2007 Quy Tonthat -- Fixed problems looking for wrong manpages. - -* Thu Jun 21 2007 Shawn O. Pearce -- Added documentation files for git-gui - -* Tue May 13 2007 Quy Tonthat -- Added lib files for git-gui -- Added Documentation/technical (As needed by Git Users Manual) - -* Tue May 8 2007 Quy Tonthat -- Added howto files - -* Tue Mar 27 2007 Eygene Ryabinkin -- Added the git-p4 package: Perforce import stuff. - -* Mon Feb 13 2007 Nicolas Pitre -- Update core package description (Git isn't as stupid as it used to be) - -* Mon Feb 12 2007 Junio C Hamano -- Add git-gui and git-citool. - -* Mon Nov 14 2005 H. Peter Anvin 0.99.9j-1 -- Change subpackage names to git- instead of git-core- -- Create empty root package which brings in all subpackages -- Rename git-tk -> gitk - -* Thu Nov 10 2005 Chris Wright 0.99.9g-1 -- zlib dependency fix -- Minor cleanups from split -- Move arch import to separate package as well - -* Tue Sep 27 2005 Jim Radford -- Move programs with non-standard dependencies (svn, cvs, email) - into separate packages - -* Tue Sep 27 2005 H. Peter Anvin -- parallelize build -- COPTS -> CFLAGS - -* Fri Sep 16 2005 Chris Wright 0.99.6-1 -- update to 0.99.6 - -* Fri Sep 16 2005 Horst H. von Brand -- Linus noticed that less is required, added to the dependencies - -* Sun Sep 11 2005 Horst H. von Brand -- Updated dependencies -- Don't assume manpages are gzipped - -* Thu Aug 18 2005 Chris Wright 0.99.4-4 -- drop sh_utils, sh-utils, diffutils, mktemp, and openssl Requires -- use RPM_OPT_FLAGS in spec file, drop patch0 - -* Wed Aug 17 2005 Tom "spot" Callaway 0.99.4-3 -- use dist tag to differentiate between branches -- use rpm optflags by default (patch0) -- own %{_datadir}/git-core/ - -* Mon Aug 15 2005 Chris Wright -- update spec file to fix Buildroot, Requires, and drop Vendor - -* Sun Aug 07 2005 Horst H. von Brand -- Redid the description -- Cut overlong make line, loosened changelog a bit -- I think Junio (or perhaps OSDL?) should be vendor... - -* Thu Jul 14 2005 Eric Biederman -- Add the man pages, and the --without docs build option - -* Wed Jul 7 2005 Chris Wright -- initial git spec file diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 05d7910b7c..2fddf750fa 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3935,6 +3935,9 @@ sub run_highlighter { close $fd; open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ". + quote_command($^X, '-CO', '-MEncode=decode,FB_DEFAULT', '-pse', + '$_ = decode($fe, $_, FB_DEFAULT) if !utf8::decode($_);', + '--', "-fe=$fallback_encoding")." | ". quote_command($highlight_bin). " --replace-tabs=8 --fragment --syntax $syntax |" or die_error(500, "Couldn't open file or run syntax highlighter"); diff --git a/gpg-interface.c b/gpg-interface.c index 3dc2fe397e..c4b1e8c78d 100644 --- a/gpg-interface.c +++ b/gpg-interface.c @@ -219,11 +219,9 @@ int verify_signed_buffer(const char *payload, size_t payload_size, args_gpg[0] = gpg_program; fd = git_mkstemp(path, PATH_MAX, ".git_vtag_tmpXXXXXX"); if (fd < 0) - return error(_("could not create temporary file '%s': %s"), - path, strerror(errno)); + return error_errno(_("could not create temporary file '%s'"), path); if (write_in_full(fd, signature, signature_size) < 0) - return error(_("failed writing detached signature to '%s': %s"), - path, strerror(errno)); + return error_errno(_("failed writing detached signature to '%s'"), path); close(fd); gpg.argv = args_gpg; @@ -237,6 +235,7 @@ int verify_signed_buffer(const char *payload, size_t payload_size, return error(_("could not run gpg.")); } + sigchain_push(SIGPIPE, SIG_IGN); write_in_full(gpg.in, payload, payload_size); close(gpg.in); @@ -250,6 +249,7 @@ int verify_signed_buffer(const char *payload, size_t payload_size, close(gpg.out); ret = finish_command(&gpg); + sigchain_pop(SIGPIPE); unlink_or_warn(path); diff --git a/grep.c b/grep.c index fafb8b58e0..1e15b6292d 100644 --- a/grep.c +++ b/grep.c @@ -1756,7 +1756,7 @@ static int grep_source_load_file(struct grep_source *gs) if (lstat(filename, &st) < 0) { err_ret: if (errno != ENOENT) - error(_("'%s': %s"), filename, strerror(errno)); + error_errno(_("failed to stat '%s'"), filename); return -1; } if (!S_ISREG(st.st_mode)) @@ -1767,7 +1767,7 @@ static int grep_source_load_file(struct grep_source *gs) goto err_ret; data = xmallocz(size); if (st.st_size != read_in_full(i, data, size)) { - error(_("'%s': short read %s"), filename, strerror(errno)); + error_errno(_("'%s': short read"), filename); close(i); free(data); return -1; diff --git a/http-backend.c b/http-backend.c index 8870a2681e..214881459d 100644 --- a/http-backend.c +++ b/http-backend.c @@ -484,9 +484,9 @@ static int show_head_ref(const char *refname, const struct object_id *oid, const char *target = resolve_ref_unsafe(refname, RESOLVE_REF_READING, unused.hash, NULL); - const char *target_nons = strip_namespace(target); - strbuf_addf(buf, "ref: %s\n", target_nons); + if (target) + strbuf_addf(buf, "ref: %s\n", strip_namespace(target)); } else { strbuf_addf(buf, "%s\n", oid_to_hex(oid)); } diff --git a/http-push.c b/http-push.c index bd60668707..a092f0288b 100644 --- a/http-push.c +++ b/http-push.c @@ -211,7 +211,7 @@ static void curl_setup_http(CURL *curl, const char *url, static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options) { struct strbuf buf = STRBUF_INIT; - struct curl_slist *dav_headers = NULL; + struct curl_slist *dav_headers = http_copy_default_headers(); if (options & DAV_HEADER_IF) { strbuf_addf(&buf, "If: (<%s>)", lock->token); @@ -417,7 +417,7 @@ static void start_put(struct transfer_request *request) static void start_move(struct transfer_request *request) { struct active_request_slot *slot; - struct curl_slist *dav_headers = NULL; + struct curl_slist *dav_headers = http_copy_default_headers(); slot = get_active_slot(); slot->callback_func = process_response; @@ -845,7 +845,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout) char *ep; char timeout_header[25]; struct remote_lock *lock = NULL; - struct curl_slist *dav_headers = NULL; + struct curl_slist *dav_headers = http_copy_default_headers(); struct xml_ctx ctx; char *escaped; @@ -1126,7 +1126,7 @@ static void remote_ls(const char *path, int flags, struct slot_results results; struct strbuf in_buffer = STRBUF_INIT; struct buffer out_buffer = { STRBUF_INIT, 0 }; - struct curl_slist *dav_headers = NULL; + struct curl_slist *dav_headers = http_copy_default_headers(); struct xml_ctx ctx; struct remote_ls_ctx ls; @@ -1204,7 +1204,7 @@ static int locking_available(void) struct slot_results results; struct strbuf in_buffer = STRBUF_INIT; struct buffer out_buffer = { STRBUF_INIT, 0 }; - struct curl_slist *dav_headers = NULL; + struct curl_slist *dav_headers = http_copy_default_headers(); struct xml_ctx ctx; int lock_flags = 0; char *escaped; @@ -1312,10 +1312,10 @@ static struct object_list **process_tree(struct tree *tree, while (tree_entry(&desc, &entry)) switch (object_type(entry.mode)) { case OBJ_TREE: - p = process_tree(lookup_tree(entry.sha1), p); + p = process_tree(lookup_tree(entry.oid->hash), p); break; case OBJ_BLOB: - p = process_blob(lookup_blob(entry.sha1), p); + p = process_blob(lookup_blob(entry.oid->hash), p); break; default: /* Subproject commit - not in this repository */ diff --git a/http.c b/http.c index 69da4454d8..df6dd01594 100644 --- a/http.c +++ b/http.c @@ -114,6 +114,7 @@ static unsigned long http_auth_methods = CURLAUTH_ANY; static struct curl_slist *pragma_header; static struct curl_slist *no_pragma_header; +static struct curl_slist *extra_http_headers; static struct active_request_slot *active_queue_head; @@ -293,7 +294,7 @@ static int http_options(const char *var, const char *value, void *cb) return git_config_string(&http_proxy_authmethod, var, value); if (!strcmp("http.cookiefile", var)) - return git_config_string(&curl_cookie_file, var, value); + return git_config_pathname(&curl_cookie_file, var, value); if (!strcmp("http.savecookies", var)) { curl_save_cookies = git_config_bool(var, value); return 0; @@ -323,6 +324,19 @@ static int http_options(const char *var, const char *value, void *cb) #endif } + if (!strcmp("http.extraheader", var)) { + if (!value) { + return config_error_nonbool(var); + } else if (!*value) { + curl_slist_free_all(extra_http_headers); + extra_http_headers = NULL; + } else { + extra_http_headers = + curl_slist_append(extra_http_headers, value); + } + return 0; + } + /* Fall back on the default ones */ return git_default_config(var, value, cb); } @@ -446,8 +460,7 @@ static int sockopt_callback(void *client, curl_socket_t fd, curlsocktype type) rc = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&ka, len); if (rc < 0) - warning("unable to set SO_KEEPALIVE on socket %s", - strerror(errno)); + warning_errno("unable to set SO_KEEPALIVE on socket"); return 0; /* CURL_SOCKOPT_OK only exists since curl 7.21.5 */ } @@ -605,7 +618,10 @@ static CURL *get_curl_handle(void) if (curl_http_proxy) { curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy); #if LIBCURL_VERSION_NUM >= 0x071800 - if (starts_with(curl_http_proxy, "socks5")) + if (starts_with(curl_http_proxy, "socks5h")) + curl_easy_setopt(result, + CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); + else if (starts_with(curl_http_proxy, "socks5")) curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); else if (starts_with(curl_http_proxy, "socks4a")) @@ -675,8 +691,10 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) if (remote) var_override(&http_proxy_authmethod, remote->http_proxy_authmethod); - pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache"); - no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); + pragma_header = curl_slist_append(http_copy_default_headers(), + "Pragma: no-cache"); + no_pragma_header = curl_slist_append(http_copy_default_headers(), + "Pragma:"); #ifdef USE_CURL_MULTI { @@ -762,6 +780,9 @@ void http_cleanup(void) #endif curl_global_cleanup(); + curl_slist_free_all(extra_http_headers); + extra_http_headers = NULL; + curl_slist_free_all(pragma_header); pragma_header = NULL; @@ -1160,6 +1181,16 @@ int run_one_slot(struct active_request_slot *slot, return handle_curl_result(results); } +struct curl_slist *http_copy_default_headers(void) +{ + struct curl_slist *headers = NULL, *h; + + for (h = extra_http_headers; h; h = h->next) + headers = curl_slist_append(headers, h->data); + + return headers; +} + static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf) { char *ptr; @@ -1377,7 +1408,7 @@ static int http_request(const char *url, { struct active_request_slot *slot; struct slot_results results; - struct curl_slist *headers = NULL; + struct curl_slist *headers = http_copy_default_headers(); struct strbuf buf = STRBUF_INIT; const char *accept_language; int ret; @@ -1891,8 +1922,7 @@ struct http_object_request *new_http_object_request(const char *base_url, } if (freq->localfile < 0) { - error("Couldn't create temporary file %s: %s", - freq->tmpfile, strerror(errno)); + error_errno("Couldn't create temporary file %s", freq->tmpfile); goto abort; } @@ -1937,8 +1967,8 @@ struct http_object_request *new_http_object_request(const char *base_url, prev_posn = 0; lseek(freq->localfile, 0, SEEK_SET); if (ftruncate(freq->localfile, 0) < 0) { - error("Couldn't truncate temporary file %s: %s", - freq->tmpfile, strerror(errno)); + error_errno("Couldn't truncate temporary file %s", + freq->tmpfile); goto abort; } } diff --git a/http.h b/http.h index 4ef4bbda7d..36f558bfb3 100644 --- a/http.h +++ b/http.h @@ -106,6 +106,7 @@ extern void step_active_slots(void); extern void http_init(struct remote *remote, const char *url, int proactive_auth); extern void http_cleanup(void); +extern struct curl_slist *http_copy_default_headers(void); extern long int git_curl_ipresolve; extern int active_requests; diff --git a/ident.c b/ident.c index 6e125821f0..139c5289d0 100644 --- a/ident.c +++ b/ident.c @@ -75,14 +75,12 @@ static int add_mailname_host(struct strbuf *buf) mailname = fopen("/etc/mailname", "r"); if (!mailname) { if (errno != ENOENT) - warning("cannot open /etc/mailname: %s", - strerror(errno)); + warning_errno("cannot open /etc/mailname"); return -1; } if (strbuf_getline(&mailnamebuf, mailname) == EOF) { if (ferror(mailname)) - warning("cannot read /etc/mailname: %s", - strerror(errno)); + warning_errno("cannot read /etc/mailname"); strbuf_release(&mailnamebuf); fclose(mailname); return -1; @@ -125,7 +123,7 @@ static void add_domainname(struct strbuf *out, int *is_bogus) char buf[1024]; if (gethostname(buf, sizeof(buf))) { - warning("cannot get host name: %s", strerror(errno)); + warning_errno("cannot get host name"); strbuf_addstr(out, "(none)"); *is_bogus = 1; return; @@ -351,15 +349,17 @@ const char *fmt_ident(const char *name, const char *email, if (want_name) { int using_default = 0; if (!name) { + if (strict && ident_use_config_only + && !(ident_config_given & IDENT_NAME_GIVEN)) { + fputs(env_hint, stderr); + die("no name was given and auto-detection is disabled"); + } name = ident_default_name(); using_default = 1; if (strict && default_name_is_bogus) { fputs(env_hint, stderr); die("unable to auto-detect name (got '%s')", name); } - if (strict && ident_use_config_only - && !(ident_config_given & IDENT_NAME_GIVEN)) - die("user.useConfigOnly set but no name given"); } if (!*name) { struct passwd *pw; @@ -374,14 +374,16 @@ const char *fmt_ident(const char *name, const char *email, } if (!email) { + if (strict && ident_use_config_only + && !(ident_config_given & IDENT_MAIL_GIVEN)) { + fputs(env_hint, stderr); + die("no email was given and auto-detection is disabled"); + } email = ident_default_email(); if (strict && default_email_is_bogus) { fputs(env_hint, stderr); die("unable to auto-detect email address (got '%s')", email); } - if (strict && ident_use_config_only - && !(ident_config_given & IDENT_MAIL_GIVEN)) - die("user.useConfigOnly set but no mail given"); } strbuf_reset(&ident); diff --git a/imap-send.c b/imap-send.c index 2c52027c84..938c691585 100644 --- a/imap-send.c +++ b/imap-send.c @@ -287,17 +287,20 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve SSL_library_init(); SSL_load_error_strings(); - if (use_tls_only) - meth = TLSv1_method(); - else - meth = SSLv23_method(); - + meth = SSLv23_method(); if (!meth) { ssl_socket_perror("SSLv23_method"); return -1; } ctx = SSL_CTX_new(meth); + if (!ctx) { + ssl_socket_perror("SSL_CTX_new"); + return -1; + } + + if (use_tls_only) + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); if (verify) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); @@ -862,7 +865,6 @@ static char hexchar(unsigned int b) static char *cram(const char *challenge_64, const char *user, const char *pass) { int i, resp_len, encoded_len, decoded_len; - HMAC_CTX hmac; unsigned char hash[16]; char hex[33]; char *response, *response_64, *challenge; @@ -877,10 +879,8 @@ static char *cram(const char *challenge_64, const char *user, const char *pass) (unsigned char *)challenge_64, encoded_len); if (decoded_len < 0) die("invalid challenge %s", challenge_64); - HMAC_Init(&hmac, (unsigned char *)pass, strlen(pass), EVP_md5()); - HMAC_Update(&hmac, (unsigned char *)challenge, decoded_len); - HMAC_Final(&hmac, hash, NULL); - HMAC_CTX_cleanup(&hmac); + if (!HMAC(EVP_md5(), pass, strlen(pass), (unsigned char *)challenge, decoded_len, hash, NULL)) + die("HMAC error"); hex[32] = 0; for (i = 0; i < 16; i++) { @@ -890,7 +890,7 @@ static char *cram(const char *challenge_64, const char *user, const char *pass) /* response: " " */ response = xstrfmt("%s %s", user, hex); - resp_len = strlen(response) + 1; + resp_len = strlen(response); response_64 = xmallocz(ENCODED_SIZE(resp_len)); encoded_len = EVP_EncodeBlock((unsigned char *)response_64, @@ -1095,11 +1095,6 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *f srvc->pass = xstrdup(cred.password); } - if (CAP(NOLOGIN)) { - fprintf(stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host); - goto bail; - } - if (srvc->auth_method) { struct imap_cmd_cb cb; @@ -1123,6 +1118,11 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *f goto bail; } } else { + if (CAP(NOLOGIN)) { + fprintf(stderr, "Skipping account %s@%s, server forbids LOGIN\n", + srvc->user, srvc->host); + goto bail; + } if (!imap->buf.sock.ssl) imap_warn("*** IMAP Warning *** Password is being " "sent in the clear\n"); diff --git a/list-objects.c b/list-objects.c index 917cc5d7c9..f3ca6aafb7 100644 --- a/list-objects.c +++ b/list-objects.c @@ -110,16 +110,16 @@ static void process_tree(struct rev_info *revs, if (S_ISDIR(entry.mode)) process_tree(revs, - lookup_tree(entry.sha1), + lookup_tree(entry.oid->hash), show, base, entry.path, cb_data); else if (S_ISGITLINK(entry.mode)) - process_gitlink(revs, entry.sha1, + process_gitlink(revs, entry.oid->hash, show, base, entry.path, cb_data); else process_blob(revs, - lookup_blob(entry.sha1), + lookup_blob(entry.oid->hash), show, base, entry.path, cb_data); } diff --git a/ll-merge.c b/ll-merge.c index ff4a43a982..ad8be42f91 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -47,7 +47,9 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused, assert(opts); /* - * The tentative merge result is the or common ancestor for an internal merge. + * The tentative merge result is the common ancestor for an + * internal merge. For the final merge, it is "ours" by + * default but -Xours/-Xtheirs can tweak the choice. */ if (opts->virtual_ancestor) { stolen = orig; @@ -383,8 +385,12 @@ int ll_merge(mmbuffer_t *result_buf, } } driver = find_ll_merge_driver(ll_driver_name); - if (opts->virtual_ancestor && driver->recursive) - driver = find_ll_merge_driver(driver->recursive); + + if (opts->virtual_ancestor) { + if (driver->recursive) + driver = find_ll_merge_driver(driver->recursive); + marker_size += 2; + } return driver->fn(driver, result_buf, path, ancestor, ancestor_label, ours, our_label, theirs, their_label, opts, marker_size); diff --git a/lockfile.c b/lockfile.c index 80d056d2ed..9268cdf325 100644 --- a/lockfile.c +++ b/lockfile.c @@ -149,13 +149,15 @@ static int lock_file_timeout(struct lock_file *lk, const char *path, void unable_to_lock_message(const char *path, int err, struct strbuf *buf) { if (err == EEXIST) { - strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n" - "If no other git process is currently running, this probably means a\n" - "git process crashed in this repository earlier. Make sure no other git\n" - "process is running and remove the file manually to continue.", + strbuf_addf(buf, _("Unable to create '%s.lock': %s.\n\n" + "Another git process seems to be running in this repository, e.g.\n" + "an editor opened by 'git commit'. Please make sure all processes\n" + "are terminated then try again. If it still fails, a git process\n" + "may have crashed in this repository earlier:\n" + "remove the file manually to continue."), absolute_path(path), strerror(err)); } else - strbuf_addf(buf, "Unable to create '%s.lock': %s", + strbuf_addf(buf, _("Unable to create '%s.lock': %s"), absolute_path(path), strerror(err)); } diff --git a/log-tree.c b/log-tree.c index 60f983934d..78a5381d0e 100644 --- a/log-tree.c +++ b/log-tree.c @@ -683,6 +683,7 @@ void show_log(struct rev_info *opt) ctx.fmt = opt->commit_format; ctx.mailmap = opt->mailmap; ctx.color = opt->diffopt.use_color; + ctx.expand_tabs_in_log = opt->expand_tabs_in_log; ctx.output_encoding = get_log_output_encoding(); if (opt->from_ident.mail_begin && opt->from_ident.name_begin) ctx.from_ident = &opt->from_ident; diff --git a/mailmap.c b/mailmap.c index f4a0f1cf27..b5c521fdea 100644 --- a/mailmap.c +++ b/mailmap.c @@ -189,8 +189,7 @@ static int read_mailmap_file(struct string_list *map, const char *filename, if (!f) { if (errno == ENOENT) return 0; - return error("unable to open mailmap at %s: %s", - filename, strerror(errno)); + return error_errno("unable to open mailmap at %s", filename); } while (fgets(buffer, sizeof(buffer), f) != NULL) @@ -250,7 +249,8 @@ int read_mailmap(struct string_list *map, char **repo_abbrev) git_mailmap_blob = "HEAD:.mailmap"; err |= read_mailmap_file(map, ".mailmap", repo_abbrev); - err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev); + if (startup_info->have_repository) + err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev); err |= read_mailmap_file(map, git_mailmap_file, repo_abbrev); return err; } diff --git a/match-trees.c b/match-trees.c index 1ce0954a3e..396b7338df 100644 --- a/match-trees.c +++ b/match-trees.c @@ -48,17 +48,17 @@ static int score_matches(unsigned mode1, unsigned mode2, const char *path) } static void *fill_tree_desc_strict(struct tree_desc *desc, - const unsigned char *hash) + const struct object_id *hash) { void *buffer; enum object_type type; unsigned long size; - buffer = read_sha1_file(hash, &type, &size); + buffer = read_sha1_file(hash->hash, &type, &size); if (!buffer) - die("unable to read tree (%s)", sha1_to_hex(hash)); + die("unable to read tree (%s)", oid_to_hex(hash)); if (type != OBJ_TREE) - die("%s is not a tree", sha1_to_hex(hash)); + die("%s is not a tree", oid_to_hex(hash)); init_tree_desc(desc, buffer, size); return buffer; } @@ -73,7 +73,7 @@ static int base_name_entries_compare(const struct name_entry *a, /* * Inspect two trees, and give a score that tells how similar they are. */ -static int score_trees(const unsigned char *hash1, const unsigned char *hash2) +static int score_trees(const struct object_id *hash1, const struct object_id *hash2) { struct tree_desc one; struct tree_desc two; @@ -104,7 +104,7 @@ static int score_trees(const unsigned char *hash1, const unsigned char *hash2) else if (cmp > 0) /* path2 does not appear in one */ score += score_missing(e2.mode, e2.path); - else if (hashcmp(e1.sha1, e2.sha1)) + else if (oidcmp(e1.oid, e2.oid)) /* they are different */ score += score_differs(e1.mode, e2.mode, e1.path); else @@ -119,8 +119,8 @@ static int score_trees(const unsigned char *hash1, const unsigned char *hash2) /* * Match one itself and its subtrees with two and pick the best match. */ -static void match_trees(const unsigned char *hash1, - const unsigned char *hash2, +static void match_trees(const struct object_id *hash1, + const struct object_id *hash2, int *best_score, char **best_match, const char *base, @@ -131,7 +131,7 @@ static void match_trees(const unsigned char *hash1, while (one.size) { const char *path; - const unsigned char *elem; + const struct object_id *elem; unsigned mode; int score; @@ -191,15 +191,15 @@ static int splice_tree(const unsigned char *hash1, while (desc.size) { const char *name; unsigned mode; - const unsigned char *sha1; + const struct object_id *oid; - sha1 = tree_entry_extract(&desc, &name, &mode); + oid = tree_entry_extract(&desc, &name, &mode); if (strlen(name) == toplen && !memcmp(name, prefix, toplen)) { if (!S_ISDIR(mode)) die("entry %s in tree %s is not a tree", name, sha1_to_hex(hash1)); - rewrite_here = (unsigned char *) sha1; + rewrite_here = (unsigned char *) oid->hash; break; } update_tree_entry(&desc); @@ -229,9 +229,9 @@ static int splice_tree(const unsigned char *hash1, * other hand, it could cover tree one and we might need to pick a * subtree of it. */ -void shift_tree(const unsigned char *hash1, - const unsigned char *hash2, - unsigned char *shifted, +void shift_tree(const struct object_id *hash1, + const struct object_id *hash2, + struct object_id *shifted, int depth_limit) { char *add_prefix; @@ -262,7 +262,7 @@ void shift_tree(const unsigned char *hash1, match_trees(hash2, hash1, &del_score, &del_prefix, "", depth_limit); /* Assume we do not have to do any shifting */ - hashcpy(shifted, hash2); + oidcpy(shifted, hash2); if (add_score < del_score) { /* We need to pick a subtree of two */ @@ -271,16 +271,16 @@ void shift_tree(const unsigned char *hash1, if (!*del_prefix) return; - if (get_tree_entry(hash2, del_prefix, shifted, &mode)) + if (get_tree_entry(hash2->hash, del_prefix, shifted->hash, &mode)) die("cannot find path %s in tree %s", - del_prefix, sha1_to_hex(hash2)); + del_prefix, oid_to_hex(hash2)); return; } if (!*add_prefix) return; - splice_tree(hash1, add_prefix, hash2, shifted); + splice_tree(hash1->hash, add_prefix, hash2->hash, shifted->hash); } /* @@ -288,22 +288,22 @@ void shift_tree(const unsigned char *hash1, * Unfortunately we cannot fundamentally tell which one to * be prefixed, as recursive merge can work in either direction. */ -void shift_tree_by(const unsigned char *hash1, - const unsigned char *hash2, - unsigned char *shifted, +void shift_tree_by(const struct object_id *hash1, + const struct object_id *hash2, + struct object_id *shifted, const char *shift_prefix) { - unsigned char sub1[20], sub2[20]; + struct object_id sub1, sub2; unsigned mode1, mode2; unsigned candidate = 0; /* Can hash2 be a tree at shift_prefix in tree hash1? */ - if (!get_tree_entry(hash1, shift_prefix, sub1, &mode1) && + if (!get_tree_entry(hash1->hash, shift_prefix, sub1.hash, &mode1) && S_ISDIR(mode1)) candidate |= 1; /* Can hash1 be a tree at shift_prefix in tree hash2? */ - if (!get_tree_entry(hash2, shift_prefix, sub2, &mode2) && + if (!get_tree_entry(hash2->hash, shift_prefix, sub2.hash, &mode2) && S_ISDIR(mode2)) candidate |= 2; @@ -313,19 +313,19 @@ void shift_tree_by(const unsigned char *hash1, int score; candidate = 0; - score = score_trees(sub1, hash2); + score = score_trees(&sub1, hash2); if (score > best_score) { candidate = 1; best_score = score; } - score = score_trees(sub2, hash1); + score = score_trees(&sub2, hash1); if (score > best_score) candidate = 2; } if (!candidate) { /* Neither is plausible -- do not shift */ - hashcpy(shifted, hash2); + oidcpy(shifted, hash2); return; } @@ -334,11 +334,11 @@ void shift_tree_by(const unsigned char *hash1, * shift tree2 down by adding shift_prefix above it * to match tree1. */ - splice_tree(hash1, shift_prefix, hash2, shifted); + splice_tree(hash1->hash, shift_prefix, hash2->hash, shifted->hash); else /* * shift tree2 up by removing shift_prefix from it * to match tree1. */ - hashcpy(shifted, sub2); + oidcpy(shifted, &sub2); } diff --git a/merge-recursive.c b/merge-recursive.c index b880ae50e7..65cb5d6c1f 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -29,9 +29,9 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two, struct object_id shifted; if (!*subtree_shift) { - shift_tree(one->object.oid.hash, two->object.oid.hash, shifted.hash, 0); + shift_tree(&one->object.oid, &two->object.oid, &shifted, 0); } else { - shift_tree_by(one->object.oid.hash, two->object.oid.hash, shifted.hash, + shift_tree_by(&one->object.oid, &two->object.oid, &shifted, subtree_shift); } if (!oidcmp(&two->object.oid, &shifted)) @@ -622,7 +622,7 @@ static char *unique_path(struct merge_options *o, const char *path, const char * base_len = newpath.len; while (string_list_has_string(&o->current_file_set, newpath.buf) || string_list_has_string(&o->current_directory_set, newpath.buf) || - file_exists(newpath.buf)) { + (!o->call_depth && file_exists(newpath.buf))) { strbuf_setlen(&newpath, base_len); strbuf_addf(&newpath, "_%d", suffix++); } @@ -1234,8 +1234,8 @@ static void conflict_rename_rename_2to1(struct merge_options *o, a->path, c1->path, ci->branch1, b->path, c2->path, ci->branch2); - remove_file(o, 1, a->path, would_lose_untracked(a->path)); - remove_file(o, 1, b->path, would_lose_untracked(b->path)); + remove_file(o, 1, a->path, o->call_depth || would_lose_untracked(a->path)); + remove_file(o, 1, b->path, o->call_depth || would_lose_untracked(b->path)); mfi_c1 = merge_file_special_markers(o, a, c1, &ci->ren1_other, o->branch1, c1->path, @@ -1773,8 +1773,6 @@ static int process_entry(struct merge_options *o, output(o, 1, _("CONFLICT (%s): There is a directory with name %s in %s. " "Adding %s as %s"), conf, path, other_branch, path, new_path); - if (o->call_depth) - remove_file_from_cache(path); update_file(o, 0, sha, mode, new_path); if (o->call_depth) remove_file_from_cache(path); diff --git a/mergetools/examdiff b/mergetools/examdiff new file mode 100644 index 0000000000..7b524d4088 --- /dev/null +++ b/mergetools/examdiff @@ -0,0 +1,18 @@ +diff_cmd () { + "$merge_tool_path" "$LOCAL" "$REMOTE" -nh +} + +merge_cmd () { + touch "$BACKUP" + if $base_present + then + "$merge_tool_path" -merge "$LOCAL" "$BASE" "$REMOTE" -o:"$MERGED" -nh + else + "$merge_tool_path" -merge "$LOCAL" "$REMOTE" -o:"$MERGED" -nh + fi + check_unchanged +} + +translate_merge_tool_path() { + mergetool_find_win32_cmd "ExamDiff.com" "ExamDiff Pro" +} diff --git a/mergetools/winmerge b/mergetools/winmerge index 74a66d4e8d..f3819d316a 100644 --- a/mergetools/winmerge +++ b/mergetools/winmerge @@ -13,24 +13,5 @@ merge_cmd () { } translate_merge_tool_path() { - # Use WinMergeU.exe if it exists in $PATH - if type -p WinMergeU.exe >/dev/null 2>&1 - then - printf WinMergeU.exe - return - fi - - # Look for WinMergeU.exe in the typical locations - winmerge_exe="WinMerge/WinMergeU.exe" - for directory in $(env | grep -Ei '^PROGRAM(FILES(\(X86\))?|W6432)=' | - cut -d '=' -f 2- | sort -u) - do - if test -n "$directory" && test -x "$directory/$winmerge_exe" - then - printf '%s' "$directory/$winmerge_exe" - return - fi - done - - printf WinMergeU.exe + mergetool_find_win32_cmd "WinMergeU.exe" "WinMerge" } diff --git a/notes.c b/notes.c index 88cf4747c1..e4e4854d69 100644 --- a/notes.c +++ b/notes.c @@ -446,7 +446,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree, l = (struct leaf_node *) xcalloc(1, sizeof(struct leaf_node)); hashcpy(l->key_sha1, object_sha1); - hashcpy(l->val_sha1, entry.sha1); + hashcpy(l->val_sha1, entry.oid->hash); if (len < 20) { if (!S_ISDIR(entry.mode) || path_len != 2) goto handle_non_note; /* not subtree */ @@ -493,7 +493,7 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree, } strbuf_addstr(&non_note_path, entry.path); add_non_note(t, strbuf_detach(&non_note_path, NULL), - entry.mode, entry.sha1); + entry.mode, entry.oid->hash); } } free(buf); diff --git a/parse-options.c b/parse-options.c index 47a9192060..312a85dbde 100644 --- a/parse-options.c +++ b/parse-options.c @@ -110,6 +110,8 @@ static int get_value(struct parse_opt_ctx_t *p, return 0; case OPTION_COUNTUP: + if (*(int *)opt->value < 0) + *(int *)opt->value = 0; *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; return 0; diff --git a/patch-ids.c b/patch-ids.c index b7b3e5a1a7..a4d0016664 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -4,7 +4,7 @@ #include "sha1-lookup.h" #include "patch-ids.h" -static int commit_patch_id(struct commit *commit, struct diff_options *options, +int commit_patch_id(struct commit *commit, struct diff_options *options, unsigned char *sha1) { if (commit->parents) diff --git a/patch-ids.h b/patch-ids.h index c8c7ca110a..eeb56b307f 100644 --- a/patch-ids.h +++ b/patch-ids.h @@ -13,6 +13,8 @@ struct patch_ids { struct patch_id_bucket *patches; }; +int commit_patch_id(struct commit *commit, struct diff_options *options, + unsigned char *sha1); int init_patch_ids(struct patch_ids *); int free_patch_ids(struct patch_ids *); struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *); diff --git a/path.c b/path.c index 969b494d72..259aeed846 100644 --- a/path.c +++ b/path.c @@ -5,6 +5,7 @@ #include "strbuf.h" #include "string-list.h" #include "dir.h" +#include "worktree.h" static int get_st_mode_bits(const char *path, int *mode) { @@ -134,7 +135,7 @@ static struct common_dir common_list[] = { * definite * definition * - * The trie would look look like: + * The trie would look like: * root: len = 0, children a and d non-NULL, value = NULL. * a: len = 2, contents = bc, value = (data for "abc") * d: len = 2, contents = ef, children i non-NULL, value = (data for "def") @@ -383,10 +384,11 @@ static void adjust_git_path(struct strbuf *buf, int git_dir_len) update_common_dir(buf, git_dir_len, NULL); } -static void do_git_path(struct strbuf *buf, const char *fmt, va_list args) +static void do_git_path(const struct worktree *wt, struct strbuf *buf, + const char *fmt, va_list args) { int gitdir_len; - strbuf_addstr(buf, get_git_dir()); + strbuf_addstr(buf, get_worktree_git_dir(wt)); if (buf->len && !is_dir_sep(buf->buf[buf->len - 1])) strbuf_addch(buf, '/'); gitdir_len = buf->len; @@ -400,7 +402,7 @@ char *git_path_buf(struct strbuf *buf, const char *fmt, ...) va_list args; strbuf_reset(buf); va_start(args, fmt); - do_git_path(buf, fmt, args); + do_git_path(NULL, buf, fmt, args); va_end(args); return buf->buf; } @@ -409,7 +411,7 @@ void strbuf_git_path(struct strbuf *sb, const char *fmt, ...) { va_list args; va_start(args, fmt); - do_git_path(sb, fmt, args); + do_git_path(NULL, sb, fmt, args); va_end(args); } @@ -418,7 +420,7 @@ const char *git_path(const char *fmt, ...) struct strbuf *pathname = get_pathname(); va_list args; va_start(args, fmt); - do_git_path(pathname, fmt, args); + do_git_path(NULL, pathname, fmt, args); va_end(args); return pathname->buf; } @@ -428,7 +430,7 @@ char *git_pathdup(const char *fmt, ...) struct strbuf path = STRBUF_INIT; va_list args; va_start(args, fmt); - do_git_path(&path, fmt, args); + do_git_path(NULL, &path, fmt, args); va_end(args); return strbuf_detach(&path, NULL); } @@ -454,6 +456,16 @@ const char *mkpath(const char *fmt, ...) return cleanup_path(pathname->buf); } +const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...) +{ + struct strbuf *pathname = get_pathname(); + va_list args; + va_start(args, fmt); + do_git_path(wt, pathname, fmt, args); + va_end(args); + return pathname->buf; +} + static void do_submodule_path(struct strbuf *buf, const char *path, const char *fmt, va_list args) { @@ -503,6 +515,35 @@ void strbuf_git_path_submodule(struct strbuf *buf, const char *path, va_end(args); } +static void do_git_common_path(struct strbuf *buf, + const char *fmt, + va_list args) +{ + strbuf_addstr(buf, get_git_common_dir()); + if (buf->len && !is_dir_sep(buf->buf[buf->len - 1])) + strbuf_addch(buf, '/'); + strbuf_vaddf(buf, fmt, args); + strbuf_cleanup_path(buf); +} + +const char *git_common_path(const char *fmt, ...) +{ + struct strbuf *pathname = get_pathname(); + va_list args; + va_start(args, fmt); + do_git_common_path(pathname, fmt, args); + va_end(args); + return pathname->buf; +} + +void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + do_git_common_path(sb, fmt, args); + va_end(args); +} + int validate_headref(const char *path) { struct stat st; @@ -702,17 +743,17 @@ static int calc_shared_perm(int mode) { int tweak; - if (shared_repository < 0) - tweak = -shared_repository; + if (get_shared_repository() < 0) + tweak = -get_shared_repository(); else - tweak = shared_repository; + tweak = get_shared_repository(); if (!(mode & S_IWUSR)) tweak &= ~0222; if (mode & S_IXUSR) /* Copy read bits to execute bits */ tweak |= (tweak & 0444) >> 2; - if (shared_repository < 0) + if (get_shared_repository() < 0) mode = (mode & ~0777) | tweak; else mode |= tweak; @@ -725,7 +766,7 @@ int adjust_shared_perm(const char *path) { int old_mode, new_mode; - if (!shared_repository) + if (!get_shared_repository()) return 0; if (get_st_mode_bits(path, &old_mode) < 0) return -1; diff --git a/perl/Git.pm b/perl/Git.pm index 49eb88af8d..ce7e4e8da3 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -393,7 +393,7 @@ sub command_close_pipe { Execute the given C in the same way as command_output_pipe() does but return both an input pipe filehandle and an output pipe filehandle. -The function will return return C<($pid, $pipe_in, $pipe_out, $ctx)>. +The function will return C<($pid, $pipe_in, $pipe_out, $ctx)>. See C for details. =cut diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index b2c14e2ff5..d94d01cfdc 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -97,7 +97,8 @@ sub resolve_local_globs { "existing: $existing\n", " globbed: $refname\n"; } - my $u = (::cmt_metadata("$refname"))[0]; + my $u = (::cmt_metadata("$refname"))[0] or die + "$refname: no associated commit metadata\n"; $u =~ s!^\Q$url\E(/|$)!! or die "$refname: '$url' not found in '$u'\n"; if ($pathname ne $u) { diff --git a/po/bg.po b/po/bg.po index ac6f103e4d..ce75f39936 100644 --- a/po/bg.po +++ b/po/bg.po @@ -65,6 +65,9 @@ # term управляваща дума (за git-bisect) # mergetag етикет при сливане # delta - разлика, делта, обект-разлика +# peeled tag - проследен етикет - когато етикет сочи към друг етикет, а не подаване и проследяваме подобно на символна връзка +# strip - премахвам (за компонент при филтриране) +# unrelated histories - независими истории # ---- # „$var“ - може да не сработва за shell има gettext и eval_gettext - проверка - намират се лесно по „$ # ======================== @@ -109,8 +112,8 @@ msgid "" msgstr "" "Project-Id-Version: git master\n" "Report-Msgid-Bugs-To: Git Mailing List \n" -"POT-Creation-Date: 2015-12-22 22:50+0800\n" -"PO-Revision-Date: 2015-12-28 11:32+0200\n" +"POT-Creation-Date: 2016-05-24 23:42+0800\n" +"PO-Revision-Date: 2016-05-29 15:23+0300\n" "Last-Translator: Alexander Shopov \n" "Language-Team: Bulgarian \n" "Language: bg\n" @@ -133,7 +136,7 @@ msgstr "" "Редактирайте ги в работното дърво, и тогава ползвайте „git add/rm ФАЙЛ“\n" "за да отбележите коригирането им. След това извършете подаването." -#: advice.c:101 builtin/merge.c:1225 +#: advice.c:101 builtin/merge.c:1238 msgid "You have not concluded your merge (MERGE_HEAD exists)." msgstr "Не сте завършили сливане. (Указателят „MERGE_HEAD“ съществува)." @@ -177,25 +180,25 @@ msgstr "ФОРМАТ" msgid "archive format" msgstr "ФОРМАТ на архива" -#: archive.c:430 builtin/log.c:1229 +#: archive.c:430 builtin/log.c:1395 msgid "prefix" -msgstr "префикс" +msgstr "ПРЕФИКС" #: archive.c:431 msgid "prepend prefix to each pathname in the archive" -msgstr "добавяне на този префикс към всеки път в архива" +msgstr "добавяне на този ПРЕФИКС към всеки път в архива" -#: archive.c:432 builtin/archive.c:88 builtin/blame.c:2535 builtin/blame.c:2536 -#: builtin/config.c:58 builtin/fast-export.c:987 builtin/fast-export.c:989 -#: builtin/grep.c:707 builtin/hash-object.c:99 builtin/ls-files.c:446 -#: builtin/ls-files.c:449 builtin/notes.c:395 builtin/notes.c:558 +#: archive.c:432 builtin/archive.c:88 builtin/blame.c:2548 builtin/blame.c:2549 +#: builtin/config.c:60 builtin/fast-export.c:987 builtin/fast-export.c:989 +#: builtin/grep.c:722 builtin/hash-object.c:100 builtin/ls-files.c:459 +#: builtin/ls-files.c:462 builtin/notes.c:398 builtin/notes.c:561 #: builtin/read-tree.c:109 parse-options.h:153 msgid "file" -msgstr "файл" +msgstr "ФАЙЛ" #: archive.c:433 builtin/archive.c:89 msgid "write the archive to this file" -msgstr "запазване на архива в този файл" +msgstr "запазване на архива в този ФАЙЛ" #: archive.c:435 msgid "read .gitattributes in working directory" @@ -221,7 +224,8 @@ msgstr "добро компресиране" msgid "list supported archive formats" msgstr "извеждане на списъка с поддържаните формати" -#: archive.c:451 builtin/archive.c:90 builtin/clone.c:77 +#: archive.c:451 builtin/archive.c:90 builtin/clone.c:82 +#: builtin/submodule--helper.c:776 msgid "repo" msgstr "хранилище" @@ -229,7 +233,7 @@ msgstr "хранилище" msgid "retrieve the archive from remote repository " msgstr "изтегляне на архива от отдалеченото ХРАНИЛИЩЕ" -#: archive.c:453 builtin/archive.c:92 builtin/notes.c:479 +#: archive.c:453 builtin/archive.c:92 builtin/notes.c:482 msgid "command" msgstr "команда" @@ -237,7 +241,7 @@ msgstr "команда" msgid "path to the remote git-upload-archive command" msgstr "път към отдалечената команда „git-upload-archive“" -#: attr.c:265 +#: attr.c:263 msgid "" "Negative patterns are ignored in git attributes\n" "Use '\\!' for literal leading exclamation." @@ -245,85 +249,102 @@ msgstr "" "Отрицателните шаблони се игнорират в атрибутите на git.\n" "Ако ви трябва начална удивителна, ползвайте „\\!“." -#: branch.c:61 +#: branch.c:53 +#, c-format +msgid "" +"\n" +"After fixing the error cause you may try to fix up\n" +"the remote tracking information by invoking\n" +"\"git branch --set-upstream-to=%s%s%s\"." +msgstr "" +"\n" +"След корекция на грешката, можете да обновите\n" +"информацията за следения клон чрез:\n" +"git branch --set-upstream-to=%s%s%s" + +#: branch.c:67 #, c-format msgid "Not setting branch %s as its own upstream." msgstr "" "Клонът „%s“ не може да служи като източник за собствената си синхронизация." -#: branch.c:84 +#: branch.c:93 #, c-format msgid "Branch %s set up to track remote branch %s from %s by rebasing." msgstr "" "Клонът „%s“ ще следи клона „%s“ от отдалеченото хранилище „%s“ чрез " "пребазиране." -#: branch.c:85 +#: branch.c:94 #, c-format msgid "Branch %s set up to track remote branch %s from %s." msgstr "Клонът „%s“ ще следи клона „%s“ от отдалеченото хранилище „%s“." -#: branch.c:89 +#: branch.c:98 #, c-format msgid "Branch %s set up to track local branch %s by rebasing." msgstr "" "Клонът „%s“ ще следи клона „%s“ от локалното хранилище чрез пребазиране." -#: branch.c:90 +#: branch.c:99 #, c-format msgid "Branch %s set up to track local branch %s." msgstr "Клонът „%s“ ще следи клона „%s“ от локалното хранилище." -#: branch.c:95 +#: branch.c:104 #, c-format msgid "Branch %s set up to track remote ref %s by rebasing." msgstr "Клонът „%s“ ще следи отдалечения указател „%s“ чрез пребазиране." -#: branch.c:96 +#: branch.c:105 #, c-format msgid "Branch %s set up to track remote ref %s." msgstr "Клонът „%s“ ще следи отдалечения указател „%s“." -#: branch.c:100 +#: branch.c:109 #, c-format msgid "Branch %s set up to track local ref %s by rebasing." msgstr "Клонът „%s“ ще следи локалния указател „%s“ чрез пребазиране." -#: branch.c:101 +#: branch.c:110 #, c-format msgid "Branch %s set up to track local ref %s." msgstr "Клонът „%s“ ще следи локалния указател „%s“." -#: branch.c:134 +#: branch.c:119 +msgid "Unable to write upstream branch configuration" +msgstr "Настройките за следения клон не могат да бъдат записани" + +#: branch.c:156 #, c-format msgid "Not tracking: ambiguous information for ref %s" msgstr "Няма следене: двусмислена информация за указателя „%s“" -#: branch.c:163 +#: branch.c:185 #, c-format msgid "'%s' is not a valid branch name." msgstr "„%s“ не е позволено име за клон." -#: branch.c:168 +#: branch.c:190 #, c-format msgid "A branch named '%s' already exists." msgstr "Вече съществува клон с име „%s“." -#: branch.c:176 +#: branch.c:198 msgid "Cannot force update the current branch." msgstr "Текущият клон не може да бъде принудително обновен." -#: branch.c:196 +#: branch.c:218 #, c-format msgid "Cannot setup tracking information; starting point '%s' is not a branch." msgstr "Зададените настройки за следенето са грешни — началото „%s“ не е клон." -#: branch.c:198 +#: branch.c:220 #, c-format msgid "the requested upstream branch '%s' does not exist" msgstr "заявеният отдалечен клон „%s“ не съществува" -#: branch.c:200 +#: branch.c:222 msgid "" "\n" "If you are planning on basing your work on an upstream\n" @@ -342,26 +363,31 @@ msgstr "" "може да използвате „git push -u“, за да настроите към кой клон да се " "изтласква." -#: branch.c:244 +#: branch.c:266 #, c-format msgid "Not a valid object name: '%s'." msgstr "Неправилно име на обект: „%s“" -#: branch.c:264 +#: branch.c:286 #, c-format msgid "Ambiguous object name: '%s'." msgstr "Двусмислено име на обект: „%s“" -#: branch.c:269 +#: branch.c:291 #, c-format msgid "Not a valid branch point: '%s'." msgstr "Неправилно място за начало на клон: „%s“" -#: branch.c:322 +#: branch.c:345 #, c-format msgid "'%s' is already checked out at '%s'" msgstr "„%s“ вече е изтеглен в „%s“" +#: branch.c:364 +#, c-format +msgid "HEAD of working tree %s is not updated" +msgstr "Указателят „HEAD“ на работното дърво „%s“ не е обновен" + #: bundle.c:34 #, c-format msgid "'%s' does not look like a v2 bundle file" @@ -372,7 +398,7 @@ msgstr "Файлът „%s“ не изглежда да е пратка на gi msgid "unrecognized header: %s%s (%d)" msgstr "непозната заглавна част: %s%s (%d)" -#: bundle.c:87 builtin/commit.c:766 +#: bundle.c:87 builtin/commit.c:777 #, c-format msgid "could not open '%s'" msgstr "„%s“ не може да се отвори" @@ -381,10 +407,10 @@ msgstr "„%s“ не може да се отвори" msgid "Repository lacks these prerequisite commits:" msgstr "В хранилището липсват следните необходими подавания:" -#: bundle.c:163 ref-filter.c:1372 sequencer.c:636 sequencer.c:1083 -#: builtin/blame.c:2734 builtin/commit.c:1045 builtin/log.c:334 -#: builtin/log.c:849 builtin/log.c:1461 builtin/log.c:1694 builtin/merge.c:358 -#: builtin/shortlog.c:158 +#: bundle.c:163 ref-filter.c:1462 sequencer.c:627 sequencer.c:1073 +#: builtin/blame.c:2755 builtin/commit.c:1056 builtin/log.c:340 +#: builtin/log.c:863 builtin/log.c:1308 builtin/log.c:1633 builtin/log.c:1875 +#: builtin/merge.c:361 builtin/shortlog.c:170 msgid "revision walk setup failed" msgstr "неуспешно настройване на обхождането на версиите" @@ -424,21 +450,21 @@ msgid "ref '%s' is excluded by the rev-list options" msgstr "" "указателят „%s“ не е бил включен поради опциите зададени на „git rev-list“" -#: bundle.c:443 builtin/log.c:157 builtin/log.c:1369 builtin/shortlog.c:261 +#: bundle.c:443 builtin/log.c:163 builtin/log.c:1538 builtin/shortlog.c:273 #, c-format msgid "unrecognized argument: %s" msgstr "непознат аргумент: %s" -#: bundle.c:449 +#: bundle.c:451 msgid "Refusing to create empty bundle." msgstr "Създаването на празна пратка е невъзможно." -#: bundle.c:459 +#: bundle.c:463 #, c-format msgid "cannot create '%s'" msgstr "Файлът „%s“ не може да бъде създаден" -#: bundle.c:480 +#: bundle.c:491 msgid "index-pack died" msgstr "Командата „git index-pack“ не завърши успешно" @@ -447,8 +473,8 @@ msgstr "Командата „git index-pack“ не завърши успешн msgid "invalid color value: %.*s" msgstr "неправилна стойност за цвят: %.*s" -#: commit.c:40 builtin/am.c:452 builtin/am.c:488 builtin/am.c:1520 -#: builtin/am.c:2149 +#: commit.c:40 builtin/am.c:437 builtin/am.c:473 builtin/am.c:1504 +#: builtin/am.c:2134 #, c-format msgid "could not parse %s" msgstr "„%s“ не може да се анализира" @@ -462,28 +488,27 @@ msgstr "%s %s не е подаване!" msgid "memory exhausted" msgstr "паметта свърши" -#: config.c:474 config.c:476 +#: config.c:475 config.c:477 #, c-format -msgid "bad config file line %d in %s" -msgstr "неправилен ред %d в „%s“" +msgid "bad config line %d in %s %s" +msgstr "неправилен ред %d в настройката %s „%s“" -#: config.c:592 +#: config.c:593 #, c-format -msgid "bad numeric config value '%s' for '%s' in %s: %s" -msgstr "" -"неправилна числова стойност „%s“ за настройката „%s“ в раздела „%s“: %s" +msgid "bad numeric config value '%s' for '%s' in %s %s: %s" +msgstr "неправилна числова стойност „%s“ за настройката „%s“ в %s „%s“: %s" -#: config.c:594 +#: config.c:595 #, c-format msgid "bad numeric config value '%s' for '%s': %s" msgstr "неправилна числова стойност „%s“ за настройката „%s“: %s" -#: config.c:679 +#: config.c:680 #, c-format msgid "failed to expand user dir in: '%s'" msgstr "домашната папка на потребителя не може да бъде открита: „%s“" -#: config.c:757 config.c:768 +#: config.c:761 config.c:772 #, c-format msgid "bad zlib compression level %d" msgstr "неправилно ниво на компресиране: %d" @@ -493,42 +518,50 @@ msgstr "неправилно ниво на компресиране: %d" msgid "invalid mode for object creation: %s" msgstr "неправилен режим за създаването на обекти: %s" -#: config.c:1216 +#: config.c:1228 msgid "unable to parse command-line config" msgstr "неправилни настройки от командния ред" -#: config.c:1277 +#: config.c:1284 msgid "unknown error occured while reading the configuration files" msgstr "неочаквана грешка при изчитането на конфигурационните файлове" -#: config.c:1601 +#: config.c:1629 #, c-format msgid "unable to parse '%s' from command-line config" msgstr "неразпозната стойност „%s“ от командния ред" -#: config.c:1603 +#: config.c:1631 #, c-format msgid "bad config variable '%s' in file '%s' at line %d" msgstr "неправилна настройка „%s“ във файла „%s“ на ред №%d" -#: config.c:1662 +#: config.c:1690 #, c-format msgid "%s has multiple values" msgstr "зададени са няколко стойности за „%s“" +#: config.c:2224 +#, c-format +msgid "could not set '%s' to '%s'" +msgstr "„%s“ не може да се зададе да е „%s“" + +#: config.c:2226 +#, c-format +msgid "could not unset '%s'" +msgstr "„%s“ не може да се премахне" + #: connected.c:69 msgid "Could not run 'git rev-list'" msgstr "Командата „git rev-list“ не може да бъде изпълнена." #: connected.c:89 -#, c-format -msgid "failed write to rev-list: %s" -msgstr "неуспешен запис на списъка с версиите: %s" +msgid "failed write to rev-list" +msgstr "неуспешен запис на списъка с версиите" -#: connected.c:97 -#, c-format -msgid "failed to close rev-list's stdin: %s" -msgstr "стандартният вход на списъка с версиите не може да бъде затворен: %s" +#: connected.c:96 +msgid "failed to close rev-list's stdin" +msgstr "стандартният вход на списъка с версиите не може да бъде затворен" #: date.c:95 msgid "in the future" @@ -603,28 +636,28 @@ msgstr[1] "преди %lu години" msgid "failed to read orderfile '%s'" msgstr "файлът с подредбата на съответствията „%s“ не може да бъде прочетен" -#: diffcore-rename.c:536 +#: diffcore-rename.c:538 msgid "Performing inexact rename detection" msgstr "Търсене на преименувания на обекти съчетани с промени" -#: diff.c:115 +#: diff.c:116 #, c-format msgid " Failed to parse dirstat cut-off percentage '%s'\n" msgstr "" " Неуспешно разпознаване на „%s“ като процент-праг за статистиката по " "директории\n" -#: diff.c:120 +#: diff.c:121 #, c-format msgid " Unknown dirstat parameter '%s'\n" msgstr " Непознат параметър „%s“ за статистиката по директории'\n" -#: diff.c:215 +#: diff.c:225 #, c-format msgid "Unknown value for 'diff.submodule' config variable: '%s'" msgstr "Непозната стойност „%s“ за настройката „diff.submodule“" -#: diff.c:267 +#: diff.c:277 #, c-format msgid "" "Found errors in 'diff.dirstat' config variable:\n" @@ -633,17 +666,17 @@ msgstr "" "Грешки в настройката „diff.dirstat“:\n" "%s" -#: diff.c:3000 +#: diff.c:3007 #, c-format msgid "external diff died, stopping at %s" msgstr "" "външната програма за разлики завърши неуспешно. Спиране на работата при „%s“" -#: diff.c:3396 +#: diff.c:3405 msgid "--follow requires exactly one pathspec" msgstr "Опцията „--follow“ изисква точно един път" -#: diff.c:3559 +#: diff.c:3568 #, c-format msgid "" "Failed to parse --dirstat/-X option parameter:\n" @@ -652,20 +685,21 @@ msgstr "" "Неразпознат параметър към опцията „--dirstat/-X“:\n" "%s" -#: diff.c:3573 +#: diff.c:3582 #, c-format msgid "Failed to parse --submodule option parameter: '%s'" msgstr "Неразпознат параметър към опцията „--submodule“: „%s“" -#: dir.c:1915 +#: dir.c:1823 msgid "failed to get kernel name and information" msgstr "името и версията на ядрото не бяха получени" -#: dir.c:1998 -msgid "Untracked cache is disabled on this system." -msgstr "Кеша за неследените файлове е изключен на тази система" +#: dir.c:1942 +msgid "Untracked cache is disabled on this system or location." +msgstr "" +"Кеша за неследените файлове е изключен на тази система или местоположение." -#: gpg-interface.c:166 gpg-interface.c:237 +#: gpg-interface.c:166 gpg-interface.c:235 msgid "could not run gpg." msgstr "Програмата „gpg“ не може да бъде стартирана." @@ -679,43 +713,43 @@ msgstr "Програмата „gpg“ не подписа данните." #: gpg-interface.c:222 #, c-format -msgid "could not create temporary file '%s': %s" -msgstr "Програмата „gpg“ не успя да създаде временния файл „%s“: %s" +msgid "could not create temporary file '%s'" +msgstr "Програмата не успя да създаде временния файл „%s“" -#: gpg-interface.c:225 +#: gpg-interface.c:224 #, c-format -msgid "failed writing detached signature to '%s': %s" -msgstr "Програмата „gpg“ не успя да запише самостоятелния подпис към „%s“: %s" +msgid "failed writing detached signature to '%s'" +msgstr "Програмата не успя да запише самостоятелния подпис в „%s“" #: grep.c:1718 #, c-format msgid "'%s': unable to read %s" msgstr "„%s“: файлът сочен от „%s“ не може да бъде прочетен" -#: grep.c:1735 +#: grep.c:1735 builtin/clone.c:382 builtin/diff.c:84 builtin/rm.c:155 #, c-format -msgid "'%s': %s" -msgstr "„%s“: „%s“" +msgid "failed to stat '%s'" +msgstr "не може да бъде получена информация чрез „stat“ за „%s“" #: grep.c:1746 #, c-format -msgid "'%s': short read %s" -msgstr "„%s“: изчитането на „%s“ върна по-малко байтове от заявените" +msgid "'%s': short read" +msgstr "„%s“: изчитането върна по-малко байтове от заявените" -#: help.c:207 +#: help.c:205 #, c-format msgid "available git commands in '%s'" msgstr "налични команди на git от „%s“" -#: help.c:214 +#: help.c:212 msgid "git commands available from elsewhere on your $PATH" msgstr "команди на git от други директории от „$PATH“" -#: help.c:246 +#: help.c:244 msgid "These are common Git commands used in various situations:" msgstr "Това са най-често използваните команди на Git:" -#: help.c:311 +#: help.c:309 #, c-format msgid "" "'%s' appears to be a git command, but we were not\n" @@ -724,11 +758,11 @@ msgstr "" "Изглежда, че „%s“ е команда на git, но тя не може да\n" "бъде изпълнена. Вероятно пакетът „git-%s“ е повреден." -#: help.c:368 +#: help.c:366 msgid "Uh oh. Your system reports no Git commands at all." msgstr "Странно, изглежда, че на системата ви няма нито една команда на git." -#: help.c:390 +#: help.c:388 #, c-format msgid "" "WARNING: You called a Git command named '%s', which does not exist.\n" @@ -739,17 +773,17 @@ msgstr "" "съществува. Изпълнението автоматично продължава, като се счита, че имате " "предвид „%s“" -#: help.c:395 +#: help.c:393 #, c-format msgid "in %0.1f seconds automatically..." msgstr "след %0.1f секунди…" -#: help.c:402 +#: help.c:400 #, c-format msgid "git: '%s' is not a git command. See 'git --help'." msgstr "git: „%s“ не е команда на git. Погледнете изхода от „git --help“." -#: help.c:406 help.c:466 +#: help.c:404 help.c:464 msgid "" "\n" "Did you mean this?" @@ -763,17 +797,41 @@ msgstr[1] "" "\n" "Команди с подобно име са:" -#: help.c:462 +#: help.c:460 #, c-format msgid "%s: %s - %s" msgstr "%s: %s — %s" +#: lockfile.c:152 +#, c-format +msgid "" +"Unable to create '%s.lock': %s.\n" +"\n" +"Another git process seems to be running in this repository, e.g.\n" +"an editor opened by 'git commit'. Please make sure all processes\n" +"are terminated then try again. If it still fails, a git process\n" +"may have crashed in this repository earlier:\n" +"remove the file manually to continue." +msgstr "" +"Файлът-ключалка „%s.lock“ не може да бъде създаден: %s\n" +"\n" +"Изглежда, че и друг процес на git е пуснат в това хранилище, напр.\n" +"редактор, стартиран с „git commit“. Уверете се, че всички подобни\n" +"процеси са спрени и опитайте отново. Ако това не помогне, вероятната\n" +"причина е, че някой процес на git в това хранилище е забил. За да\n" +"продължите работа, ще трябва ръчно да изтриете файла:" + +#: lockfile.c:160 +#, c-format +msgid "Unable to create '%s.lock': %s" +msgstr "Файлът-ключалка „%s.lock“ не може да бъде създаден: %s" + #: merge.c:41 msgid "failed to read the cache" msgstr "кешът не може да бъде прочетен" -#: merge.c:94 builtin/am.c:2022 builtin/am.c:2057 builtin/checkout.c:376 -#: builtin/checkout.c:587 builtin/clone.c:722 +#: merge.c:94 builtin/am.c:2007 builtin/am.c:2042 builtin/checkout.c:375 +#: builtin/checkout.c:586 builtin/clone.c:732 msgid "unable to write new index file" msgstr "неуспешно записване на новия индекс" @@ -791,66 +849,66 @@ msgstr "неуспешно изпълнение на „addinfo_cache“ за п msgid "error building trees" msgstr "грешка при изграждане на дърветата" -#: merge-recursive.c:686 +#: merge-recursive.c:689 #, c-format msgid "failed to create path '%s'%s" msgstr "грешка при създаването на пътя „%s“%s" -#: merge-recursive.c:697 +#: merge-recursive.c:700 #, c-format msgid "Removing %s to make room for subdirectory\n" msgstr "Изтриване на „%s“, за да се освободи място за поддиректория\n" -#: merge-recursive.c:711 merge-recursive.c:732 +#: merge-recursive.c:714 merge-recursive.c:735 msgid ": perhaps a D/F conflict?" msgstr ": възможно е да има конфликт директория/файл." -#: merge-recursive.c:722 +#: merge-recursive.c:725 #, c-format msgid "refusing to lose untracked file at '%s'" msgstr "" "преустановяване на действието, за да не се изтрие неследеният файл „%s“" -#: merge-recursive.c:762 +#: merge-recursive.c:765 #, c-format msgid "cannot read object %s '%s'" msgstr "обектът „%s“ (%s) не може да бъде прочетен" -#: merge-recursive.c:764 +#: merge-recursive.c:767 #, c-format msgid "blob expected for %s '%s'" msgstr "обектът „%s“ (%s) се очакваше да е BLOB, а не е" -#: merge-recursive.c:787 builtin/clone.c:369 +#: merge-recursive.c:790 builtin/clone.c:376 #, c-format msgid "failed to open '%s'" msgstr "директорията „%s“ не може да бъде отворена" -#: merge-recursive.c:795 +#: merge-recursive.c:798 #, c-format msgid "failed to symlink '%s'" msgstr "неуспешно създаване на символната връзка „%s“" -#: merge-recursive.c:798 +#: merge-recursive.c:801 #, c-format msgid "do not know what to do with %06o %s '%s'" msgstr "" "не е ясно какво да се прави с обекта „%2$s“ (%3$s) с права за достъп „%1$06o“" -#: merge-recursive.c:936 +#: merge-recursive.c:939 msgid "Failed to execute internal merge" msgstr "Неуспешно вътрешно сливане" -#: merge-recursive.c:940 +#: merge-recursive.c:943 #, c-format msgid "Unable to add %s to database" msgstr "„%s“ не може да се добави в базата с данни" -#: merge-recursive.c:956 +#: merge-recursive.c:959 msgid "unsupported object type in the tree" msgstr "в дървото има неподдържан вид обект" -#: merge-recursive.c:1031 merge-recursive.c:1045 +#: merge-recursive.c:1034 merge-recursive.c:1048 #, c-format msgid "" "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " @@ -859,7 +917,7 @@ msgstr "" "КОНФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ в %s. Версия %s на „%s“ " "е оставена в дървото." -#: merge-recursive.c:1037 merge-recursive.c:1050 +#: merge-recursive.c:1040 merge-recursive.c:1053 #, c-format msgid "" "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left " @@ -868,20 +926,20 @@ msgstr "" "КОНФЛИКТ (%s/изтриване): „%s“ е изтрит в %s, а „%s“ в %s. Версия %s на „%s“ " "е оставена в дървото: %s." -#: merge-recursive.c:1091 +#: merge-recursive.c:1094 msgid "rename" msgstr "преименуване" -#: merge-recursive.c:1091 +#: merge-recursive.c:1094 msgid "renamed" msgstr "преименуван" -#: merge-recursive.c:1147 +#: merge-recursive.c:1150 #, c-format msgid "%s is a directory in %s adding as %s instead" msgstr "„%s“ е директория в „%s“, затова се добавя като „%s“" -#: merge-recursive.c:1169 +#: merge-recursive.c:1172 #, c-format msgid "" "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s" @@ -890,150 +948,150 @@ msgstr "" "КОНФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " "„%s“, а „%s“ е преименуван на „%s“ в „%s“/%s." -#: merge-recursive.c:1174 +#: merge-recursive.c:1177 msgid " (left unresolved)" msgstr " (некоригиран конфликт)" -#: merge-recursive.c:1228 +#: merge-recursive.c:1231 #, c-format msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s" msgstr "" "КОНФЛИКТ (преименуване/преименуване): „%s“ е преименуван на „%s“ в клон " "„%s“, а „%s“ е преименуван на „%s“ в „%s“" -#: merge-recursive.c:1258 +#: merge-recursive.c:1261 #, c-format msgid "Renaming %s to %s and %s to %s instead" msgstr "Преименуване на „%s“ на „%s“, а „%s“ на „%s“" -#: merge-recursive.c:1457 +#: merge-recursive.c:1460 #, c-format msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s" msgstr "" "КОНФЛИКТ (преименуване/добавяне): „%s“ е преименуван на „%s“ в клон „%s“, а " "„%s“ е добавен в „%s“" -#: merge-recursive.c:1467 +#: merge-recursive.c:1470 #, c-format msgid "Adding merged %s" msgstr "Добавяне на слетия „%s“" -#: merge-recursive.c:1472 merge-recursive.c:1674 +#: merge-recursive.c:1475 merge-recursive.c:1677 #, c-format msgid "Adding as %s instead" msgstr "Добавяне като „%s“" -#: merge-recursive.c:1523 +#: merge-recursive.c:1526 #, c-format msgid "cannot read object %s" msgstr "обектът „%s“ не може да се прочете" -#: merge-recursive.c:1526 +#: merge-recursive.c:1529 #, c-format msgid "object %s is not a blob" msgstr "обектът „%s“ не е BLOB" -#: merge-recursive.c:1578 +#: merge-recursive.c:1581 msgid "modify" msgstr "промяна" -#: merge-recursive.c:1578 +#: merge-recursive.c:1581 msgid "modified" msgstr "променен" -#: merge-recursive.c:1588 +#: merge-recursive.c:1591 msgid "content" msgstr "съдържание" -#: merge-recursive.c:1595 +#: merge-recursive.c:1598 msgid "add/add" msgstr "добавяне/добавяне" -#: merge-recursive.c:1629 +#: merge-recursive.c:1632 #, c-format msgid "Skipped %s (merged same as existing)" msgstr "Прескачане на „%s“ (слетият резултат е идентичен със сегашния)" -#: merge-recursive.c:1643 +#: merge-recursive.c:1646 #, c-format msgid "Auto-merging %s" msgstr "Автоматично сливане на „%s“" -#: merge-recursive.c:1647 git-submodule.sh:1025 +#: merge-recursive.c:1650 git-submodule.sh:941 msgid "submodule" msgstr "ПОДМОДУЛ" -#: merge-recursive.c:1648 +#: merge-recursive.c:1651 #, c-format msgid "CONFLICT (%s): Merge conflict in %s" msgstr "КОНФЛИКТ (%s): Конфликт при сливане на „%s“" -#: merge-recursive.c:1734 +#: merge-recursive.c:1737 #, c-format msgid "Removing %s" msgstr "Изтриване на „%s“" -#: merge-recursive.c:1759 +#: merge-recursive.c:1762 msgid "file/directory" msgstr "файл/директория" -#: merge-recursive.c:1765 +#: merge-recursive.c:1768 msgid "directory/file" msgstr "директория/файл" -#: merge-recursive.c:1770 +#: merge-recursive.c:1773 #, c-format msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s" msgstr "" "КОНФЛИКТ (%s): Съществува директория на име „%s“ в „%s“. Добавяне на „%s“ " "като „%s“" -#: merge-recursive.c:1780 +#: merge-recursive.c:1781 #, c-format msgid "Adding %s" msgstr "Добавяне на „%s“" -#: merge-recursive.c:1797 +#: merge-recursive.c:1798 msgid "Fatal merge failure, shouldn't happen." msgstr "Фатална грешка при сливане, а такава не трябва да възниква!" -#: merge-recursive.c:1816 +#: merge-recursive.c:1817 msgid "Already up-to-date!" msgstr "Вече е обновено!" -#: merge-recursive.c:1825 +#: merge-recursive.c:1826 #, c-format msgid "merging of trees %s and %s failed" msgstr "неуспешно сливане на дърветата „%s“ и „%s“" -#: merge-recursive.c:1855 +#: merge-recursive.c:1856 #, c-format msgid "Unprocessed path??? %s" msgstr "" "Пътят „%s“ не е обработен, това е грешка в Git, докладвайте я на " "разработчиците, като пратите е-писмо на адрес: „git@vger.kernel.org“." -#: merge-recursive.c:1903 +#: merge-recursive.c:1904 msgid "Merging:" msgstr "Сливане:" -#: merge-recursive.c:1916 +#: merge-recursive.c:1917 #, c-format msgid "found %u common ancestor:" msgid_plural "found %u common ancestors:" msgstr[0] "открит е %u общ предшественик:" msgstr[1] "открити са %u общи предшественици:" -#: merge-recursive.c:1953 +#: merge-recursive.c:1954 msgid "merge returned no commit" msgstr "сливането не върна подаване" -#: merge-recursive.c:2010 +#: merge-recursive.c:2011 #, c-format msgid "Could not parse object '%s'" msgstr "Неуспешен анализ на обекта „%s“" -#: merge-recursive.c:2021 builtin/merge.c:645 +#: merge-recursive.c:2022 builtin/merge.c:649 builtin/merge.c:831 msgid "Unable to write index." msgstr "Индексът не може да бъде прочетен" @@ -1065,28 +1123,28 @@ msgstr "Зададена е лоша стойност на променлива msgid "unable to parse object: %s" msgstr "обектът „%s“ не може да бъде анализиран" -#: parse-options.c:570 +#: parse-options.c:572 msgid "..." msgstr "…" -#: parse-options.c:588 +#: parse-options.c:590 #, c-format msgid "usage: %s" msgstr "употреба: %s" #. TRANSLATORS: the colon here should align with the #. one in "usage: %s" translation -#: parse-options.c:592 +#: parse-options.c:594 #, c-format msgid " or: %s" msgstr " или: %s" -#: parse-options.c:595 +#: parse-options.c:597 #, c-format msgid " %s" msgstr " %s" -#: parse-options.c:629 +#: parse-options.c:631 msgid "-NUM" msgstr "-ЧИСЛО" @@ -1095,7 +1153,7 @@ msgstr "-ЧИСЛО" msgid "malformed object name '%s'" msgstr "неправилно име на обект „%s“" -#: path.c:752 +#: path.c:796 #, c-format msgid "Could not make %s writable by group" msgstr "Не могат да се дадат права за запис в директорията „%s“ на групата" @@ -1151,12 +1209,12 @@ msgstr "Пътят „%s“ е в подмодула „%.*s“" msgid "%s: pathspec magic not supported by this command: %s" msgstr "%s: магическите пътища не се поддържат от командата „%s“" -#: pathspec.c:432 +#: pathspec.c:433 #, c-format msgid "pathspec '%s' is beyond a symbolic link" msgstr "пътят „%s“ е след символна връзка" -#: pathspec.c:441 +#: pathspec.c:442 msgid "" "There is nothing to exclude from by :(exclude) patterns.\n" "Perhaps you forgot to add either ':/' or '.' ?" @@ -1164,7 +1222,7 @@ msgstr "" "Нищо не се изключва от шаблоните за изключване.\n" "Това често се случва, ако сте забравили да добавите „:/“ или „.“." -#: pretty.c:969 +#: pretty.c:971 msgid "unable to parse --pretty format" msgstr "аргументът към опцията „--pretty“ не може да се анализира" @@ -1191,165 +1249,250 @@ msgstr "" "„GIT_INDEX_VERSION“.\n" "Ще се ползва версия %i" -#: refs.c:543 builtin/merge.c:760 builtin/merge.c:871 builtin/merge.c:973 -#: builtin/merge.c:983 +#: refs.c:543 builtin/merge.c:764 builtin/merge.c:883 builtin/merge.c:985 +#: builtin/merge.c:995 #, c-format msgid "Could not open '%s' for writing" msgstr "„%s“ не може да бъде отворен за запис" -#: refs/files-backend.c:2359 +#: refs/files-backend.c:2243 #, c-format msgid "could not delete reference %s: %s" msgstr "Указателят „%s“ не може да бъде изтрит: %s" -#: refs/files-backend.c:2362 +#: refs/files-backend.c:2246 #, c-format msgid "could not delete references: %s" msgstr "Указателите не може да бъдат изтрити: %s" -#: refs/files-backend.c:2371 +#: refs/files-backend.c:2255 #, c-format msgid "could not remove reference %s" msgstr "Указателят „%s“ не може да бъде изтрит" -#: ref-filter.c:245 +#: ref-filter.c:55 #, c-format -msgid "format: %%(end) atom used without corresponding atom" -msgstr "грешка във форма̀та: лексемата %%(end) е използвана без съответната ѝ" +msgid "expected format: %%(color:)" +msgstr "очакван формат: %%(color:ЦВЯТ)" -#: ref-filter.c:704 +#: ref-filter.c:57 +#, c-format +msgid "unrecognized color: %%(color:%s)" +msgstr "непознат цвят: %%(color:%s)" + +#: ref-filter.c:71 +#, c-format +msgid "unrecognized format: %%(%s)" +msgstr "непознат формат: %%(%s)" + +#: ref-filter.c:77 +#, c-format +msgid "%%(body) does not take arguments" +msgstr "%%(body) не приема аргументи" + +#: ref-filter.c:84 +#, c-format +msgid "%%(subject) does not take arguments" +msgstr "%%(subject) не приема аргументи" + +#: ref-filter.c:101 #, c-format msgid "positive value expected contents:lines=%s" msgstr "очаква се положителна стойност за „contents:lines=%s“" -#: ref-filter.c:833 +#: ref-filter.c:103 #, c-format -msgid "expected format: %%(color:)" -msgstr "очакван формат: %%(color:ЦВЯТ)" +msgid "unrecognized %%(contents) argument: %s" +msgstr "непознат аргумент за %%(contents): %s" -#: ref-filter.c:835 -msgid "unable to parse format" -msgstr "форматът не може да бъде анализиран" +#: ref-filter.c:113 +#, c-format +msgid "unrecognized %%(objectname) argument: %s" +msgstr "непознат аргумент за %%(objectname): %s" -#: ref-filter.c:870 +#: ref-filter.c:135 #, c-format msgid "expected format: %%(align:,)" msgstr "очакван формат: %%(align:ШИРОЧИНА,ПОЗИЦИЯ)" -#: ref-filter.c:893 +#: ref-filter.c:147 #, c-format -msgid "improper format entered align:%s" -msgstr "въведен е неправилен формат align:%s" +msgid "unrecognized position:%s" +msgstr "непозната позиция: %s" -#: ref-filter.c:898 +#: ref-filter.c:151 +#, c-format +msgid "unrecognized width:%s" +msgstr "непозната широчина: %s" + +#: ref-filter.c:157 +#, c-format +msgid "unrecognized %%(align) argument: %s" +msgstr "непознат аргумент за %%(align): %s" + +#: ref-filter.c:161 #, c-format msgid "positive width expected with the %%(align) atom" msgstr "очаква се положителна широчина с лексемата „%%(align)“" -#: ref-filter.c:1219 +#: ref-filter.c:244 +#, c-format +msgid "malformed field name: %.*s" +msgstr "неправилно име на обект: „%.*s“" + +#: ref-filter.c:270 +#, c-format +msgid "unknown field name: %.*s" +msgstr "непознато име на обект: „%.*s“" + +#: ref-filter.c:372 +#, c-format +msgid "format: %%(end) atom used without corresponding atom" +msgstr "грешка във форма̀та: лексемата %%(end) е използвана без съответната ѝ" + +#: ref-filter.c:424 +#, c-format +msgid "malformed format string %s" +msgstr "неправилен низ за форматиране „%s“" + +#: ref-filter.c:878 +msgid ":strip= requires a positive integer argument" +msgstr "„:strip=“ изисква аргумент цяло, положително число" + +#: ref-filter.c:883 +#, c-format +msgid "ref '%s' does not have %ld components to :strip" +msgstr "указателят „%s“ не разполага с %ld компоненти за премахване (:strip)" + +#: ref-filter.c:1046 +#, c-format +msgid "unknown %.*s format %s" +msgstr "непознато „%.*s“, формат „%s“" + +#: ref-filter.c:1066 ref-filter.c:1097 +#, c-format +msgid "missing object %s for %s" +msgstr "обектът „%s“ липсва за „%s“" + +#: ref-filter.c:1069 ref-filter.c:1100 +#, c-format +msgid "parse_object_buffer failed on %s for %s" +msgstr "неуспешно анализиране чрез „parse_object_buffer“ на „%s“ за „%s“" + +#: ref-filter.c:1311 #, c-format msgid "malformed object at '%s'" msgstr "обект със сгрешен формат при „%s“" -#: ref-filter.c:1561 +#: ref-filter.c:1373 +#, c-format +msgid "ignoring ref with broken name %s" +msgstr "игнориране на указателя с грешно име „%s“" + +#: ref-filter.c:1378 +#, c-format +msgid "ignoring broken ref %s" +msgstr "игнориране на повредения указател „%s“" + +#: ref-filter.c:1651 #, c-format msgid "format: %%(end) atom missing" msgstr "грешка във форма̀та: липсва лексемата %%(end)" -#: ref-filter.c:1615 +#: ref-filter.c:1705 #, c-format msgid "malformed object name %s" msgstr "неправилно име на обект „%s“" -#: remote.c:756 +#: remote.c:746 #, c-format msgid "Cannot fetch both %s and %s to %s" msgstr "Невъзможно е да се доставят едновременно и „%s“, и „%s“ към „%s“" -#: remote.c:760 +#: remote.c:750 #, c-format msgid "%s usually tracks %s, not %s" msgstr "„%s“ обикновено следи „%s“, а не „%s“" -#: remote.c:764 +#: remote.c:754 #, c-format msgid "%s tracks both %s and %s" msgstr "„%s“ следи както „%s“, така и „%s“" -#: remote.c:772 +#: remote.c:762 msgid "Internal error" msgstr "Вътрешна грешка" -#: remote.c:1687 remote.c:1730 +#: remote.c:1678 remote.c:1721 msgid "HEAD does not point to a branch" msgstr "Указателят „HEAD“ не сочи към клон" -#: remote.c:1696 +#: remote.c:1687 #, c-format msgid "no such branch: '%s'" msgstr "няма клон на име „%s“" -#: remote.c:1699 +#: remote.c:1690 #, c-format msgid "no upstream configured for branch '%s'" msgstr "не е зададен клон-източник за клона „%s“" -#: remote.c:1705 +#: remote.c:1696 #, c-format msgid "upstream branch '%s' not stored as a remote-tracking branch" msgstr "клонът-източник „%s“ не е съхранен като следящ клон" -#: remote.c:1720 +#: remote.c:1711 #, c-format msgid "push destination '%s' on remote '%s' has no local tracking branch" msgstr "" "липсва локален следящ клон за местоположението за изтласкване „%s“ в " "хранилището „%s“" -#: remote.c:1735 +#: remote.c:1726 #, c-format msgid "branch '%s' has no remote for pushing" msgstr "няма информация клонът „%s“ да следи някой друг" -#: remote.c:1746 +#: remote.c:1737 #, c-format msgid "push refspecs for '%s' do not include '%s'" msgstr "указателят за изтласкване на „%s“ не включва „%s“" -#: remote.c:1759 +#: remote.c:1750 msgid "push has no destination (push.default is 'nothing')" msgstr "указателят за изтласкване не включва цел („push.default“ е „nothing“)" -#: remote.c:1781 +#: remote.c:1772 msgid "cannot resolve 'simple' push to a single destination" msgstr "простото (simple) изтласкване не съответства на една цел" -#: remote.c:2083 +#: remote.c:2074 #, c-format msgid "Your branch is based on '%s', but the upstream is gone.\n" msgstr "Този клон следи „%s“, но следеният клон е изтрит.\n" -#: remote.c:2087 +#: remote.c:2078 msgid " (use \"git branch --unset-upstream\" to fixup)\n" msgstr " (за да коригирате това, използвайте „git branch --unset-upstream“)\n" -#: remote.c:2090 +#: remote.c:2081 #, c-format msgid "Your branch is up-to-date with '%s'.\n" msgstr "Клонът е актуализиран към „%s“.\n" -#: remote.c:2094 +#: remote.c:2085 #, c-format msgid "Your branch is ahead of '%s' by %d commit.\n" msgid_plural "Your branch is ahead of '%s' by %d commits.\n" msgstr[0] "Клонът ви е с %2$d подаване пред „%1$s“.\n" msgstr[1] "Клонът ви е с %2$d подавания пред „%1$s“.\n" -#: remote.c:2100 +#: remote.c:2091 msgid " (use \"git push\" to publish your local commits)\n" msgstr " (публикувайте локалните си промени чрез „git push“)\n" -#: remote.c:2103 +#: remote.c:2094 #, c-format msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n" msgid_plural "" @@ -1359,11 +1502,11 @@ msgstr[0] "" msgstr[1] "" "Клонът ви е с %2$d подавания зад „%1$s“ и може да бъде тривиално слят.\n" -#: remote.c:2111 +#: remote.c:2102 msgid " (use \"git pull\" to update your local branch)\n" msgstr " (обновете локалния си клон чрез „git pull“)\n" -#: remote.c:2114 +#: remote.c:2105 #, c-format msgid "" "Your branch and '%s' have diverged,\n" @@ -1378,28 +1521,28 @@ msgstr[1] "" "Текущият клон се е отделил от „%s“,\n" "двата имат съответно по %d и %d несъвпадащи подавания.\n" -#: remote.c:2124 +#: remote.c:2115 msgid " (use \"git pull\" to merge the remote branch into yours)\n" msgstr " (слейте отдалечения клон в локалния чрез „git pull“)\n" -#: revision.c:2193 +#: revision.c:2142 msgid "your current branch appears to be broken" msgstr "Текущият клон е повреден" -#: revision.c:2196 +#: revision.c:2145 #, c-format msgid "your current branch '%s' does not have any commits yet" msgstr "Текущият клон „%s“ е без подавания " -#: revision.c:2390 +#: revision.c:2339 msgid "--first-parent is incompatible with --bisect" msgstr "опциите „--first-parent“ и „--bisect“ са несъвместими" -#: run-command.c:90 +#: run-command.c:92 msgid "open /dev/null failed" msgstr "неуспешно отваряне на „/dev/null“" -#: run-command.c:92 +#: run-command.c:94 #, c-format msgid "dup2(%d,%d) failed" msgstr "неуспешно изпълнение на dup2(%d,%d)" @@ -1425,7 +1568,7 @@ msgid "the receiving end does not support --atomic push" msgstr "получаващата страна не поддържа изтласкване с опцията „--atomic“" # FIXME git add for consistence -#: sequencer.c:183 +#: sequencer.c:174 msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add ' or 'git rm '" @@ -1433,7 +1576,7 @@ msgstr "" "след коригирането на конфликтите, отбележете съответните\n" "пътища с „git add ПЪТ…“ или „git rm ПЪТ…“." -#: sequencer.c:186 +#: sequencer.c:177 msgid "" "after resolving the conflicts, mark the corrected paths\n" "with 'git add ' or 'git rm '\n" @@ -1444,227 +1587,227 @@ msgstr "" "подайте резултата с командата „git commit'“." # FIXME - must be the same as Could not write to '%s' above -#: sequencer.c:199 sequencer.c:842 sequencer.c:922 +#: sequencer.c:190 sequencer.c:833 sequencer.c:912 #, c-format msgid "Could not write to %s" msgstr "„%s“ не може да бъде записан" -#: sequencer.c:202 +#: sequencer.c:193 #, c-format msgid "Error wrapping up %s" msgstr "Обработката на „%s“ не завърши успешно." -#: sequencer.c:217 +#: sequencer.c:208 msgid "Your local changes would be overwritten by cherry-pick." msgstr "Локалните ви промени ще бъдат презаписани при отбирането на подавания." -#: sequencer.c:219 +#: sequencer.c:210 msgid "Your local changes would be overwritten by revert." msgstr "Локалните ви промени ще бъдат презаписани при отмяната на подавания." -#: sequencer.c:222 +#: sequencer.c:213 msgid "Commit your changes or stash them to proceed." msgstr "Подайте или скатайте промените, за да продължите" #. TRANSLATORS: %s will be "revert" or "cherry-pick" -#: sequencer.c:309 +#: sequencer.c:300 #, c-format msgid "%s: Unable to write new index file" msgstr "%s: новият индекс не може да бъде запазен" -#: sequencer.c:327 +#: sequencer.c:318 msgid "Could not resolve HEAD commit\n" msgstr "Подаването сочено от указателя „HEAD“ не може да бъде открито\n" -#: sequencer.c:347 +#: sequencer.c:338 msgid "Unable to update cache tree\n" msgstr "Дървото на кеша не може да бъде обновено\n" -#: sequencer.c:399 +#: sequencer.c:390 #, c-format msgid "Could not parse commit %s\n" msgstr "Подаването „%s“ не може да бъде анализирано\n" -#: sequencer.c:404 +#: sequencer.c:395 #, c-format msgid "Could not parse parent commit %s\n" msgstr "Родителското подаване „%s“ не може да бъде анализирано\n" -#: sequencer.c:469 +#: sequencer.c:460 msgid "Your index file is unmerged." msgstr "Индексът не е слят." -#: sequencer.c:488 +#: sequencer.c:479 #, c-format msgid "Commit %s is a merge but no -m option was given." msgstr "Подаването „%s“ е сливане, но не е дадена опцията „-m“" -#: sequencer.c:496 +#: sequencer.c:487 #, c-format msgid "Commit %s does not have parent %d" msgstr "Подаването „%s“ няма родител %d" -#: sequencer.c:500 +#: sequencer.c:491 #, c-format msgid "Mainline was specified but commit %s is not a merge." msgstr "Указано е базово подаване, но подаването „%s“ не е сливане." #. TRANSLATORS: The first %s will be "revert" or #. "cherry-pick", the second %s a SHA1 -#: sequencer.c:513 +#: sequencer.c:504 #, c-format msgid "%s: cannot parse parent commit %s" msgstr "%s: неразпозната стойност за родителското подаване „%s“" -#: sequencer.c:517 +#: sequencer.c:508 #, c-format msgid "Cannot get commit message for %s" msgstr "Неуспешно извличане на съобщението за подаване на „%s“" -#: sequencer.c:603 +#: sequencer.c:594 #, c-format msgid "could not revert %s... %s" msgstr "подаването „%s“… не може да бъде отменено: „%s“" -#: sequencer.c:604 +#: sequencer.c:595 #, c-format msgid "could not apply %s... %s" msgstr "подаването „%s“… не може да бъде приложено: „%s“" -#: sequencer.c:639 +#: sequencer.c:630 msgid "empty commit set passed" msgstr "зададено е празно множество от подавания" -#: sequencer.c:647 +#: sequencer.c:638 #, c-format msgid "git %s: failed to read the index" msgstr "git %s: неуспешно изчитане на индекса" -#: sequencer.c:651 +#: sequencer.c:642 #, c-format msgid "git %s: failed to refresh the index" msgstr "git %s: неуспешно обновяване на индекса" -#: sequencer.c:711 +#: sequencer.c:702 #, c-format msgid "Cannot %s during a %s" msgstr "По време на „%1$s“ не може да се извърши „%2$s“" -#: sequencer.c:733 +#: sequencer.c:724 #, c-format msgid "Could not parse line %d." msgstr "%d-ят ред не може да се анализира." -#: sequencer.c:738 +#: sequencer.c:729 msgid "No commits parsed." msgstr "Никое от подаванията не може да се разпознае." # FIXME Could not open %s. - full stop for consistence with next message -#: sequencer.c:750 +#: sequencer.c:741 #, c-format msgid "Could not open %s" msgstr "„%s“ не може да се прочете." -#: sequencer.c:754 +#: sequencer.c:745 #, c-format msgid "Could not read %s." msgstr "„%s“ не може да се отвори." -#: sequencer.c:761 +#: sequencer.c:752 #, c-format msgid "Unusable instruction sheet: %s" msgstr "Файлът с описание на предстоящите действия — „%s“ не може да се ползва" -#: sequencer.c:791 +#: sequencer.c:782 #, c-format msgid "Invalid key: %s" msgstr "Неправилен ключ: „%s“" -#: sequencer.c:794 builtin/pull.c:47 builtin/pull.c:49 +#: sequencer.c:785 builtin/pull.c:50 builtin/pull.c:52 #, c-format msgid "Invalid value for %s: %s" msgstr "Неправилна стойност за „%s“: „%s“" -#: sequencer.c:804 +#: sequencer.c:795 #, c-format msgid "Malformed options sheet: %s" msgstr "Неправилно съдържание на файла с опции: „%s“" -#: sequencer.c:823 +#: sequencer.c:814 msgid "a cherry-pick or revert is already in progress" msgstr "" "в момента вече се извършва отбиране на подавания или пребазиране на клона" -#: sequencer.c:824 +#: sequencer.c:815 msgid "try \"git cherry-pick (--continue | --quit | --abort)\"" msgstr "използвайте „git cherry-pick (--continue | --quit | --abort)“" -#: sequencer.c:828 +#: sequencer.c:819 #, c-format msgid "Could not create sequencer directory %s" msgstr "Директорията за секвенсора „%s“ не може да бъде създадена" -#: sequencer.c:844 sequencer.c:926 +#: sequencer.c:835 sequencer.c:916 #, c-format msgid "Error wrapping up %s." msgstr "Обработката на „%s“ не завърши успешно." -#: sequencer.c:863 sequencer.c:996 +#: sequencer.c:854 sequencer.c:986 msgid "no cherry-pick or revert in progress" msgstr "" "в момента не се извършва отбиране на подавания или пребазиране на клона" -#: sequencer.c:865 +#: sequencer.c:856 msgid "cannot resolve HEAD" msgstr "Подаването сочено от указателя „HEAD“ не може да бъде открито" -#: sequencer.c:867 +#: sequencer.c:858 msgid "cannot abort from a branch yet to be born" msgstr "" "действието не може да бъде преустановено, когато сте на клон, който тепърва " "предстои да бъде създаден" -#: sequencer.c:887 builtin/apply.c:4287 +#: sequencer.c:878 builtin/fetch.c:610 builtin/fetch.c:851 #, c-format -msgid "cannot open %s: %s" -msgstr "файлът „%s“ не може да бъде отворен: %s" +msgid "cannot open %s" +msgstr "„%s“ не може да бъде отворен" -#: sequencer.c:890 +#: sequencer.c:880 #, c-format msgid "cannot read %s: %s" msgstr "файлът „%s“ не може да бъде прочетен: %s" -#: sequencer.c:891 +#: sequencer.c:881 msgid "unexpected end of file" msgstr "неочакван край на файл" -#: sequencer.c:897 +#: sequencer.c:887 #, c-format msgid "stored pre-cherry-pick HEAD file '%s' is corrupt" msgstr "" "запазеният преди започването на отбирането файл за указателя „HEAD“ — „%s“ е " "повреден" -#: sequencer.c:919 +#: sequencer.c:909 #, c-format msgid "Could not format %s." msgstr "Файлът „%s“ не може да се форматира по подходящия начин." -#: sequencer.c:1064 +#: sequencer.c:1054 #, c-format msgid "%s: can't cherry-pick a %s" msgstr "%s: не може да се отбере „%s“" -#: sequencer.c:1067 +#: sequencer.c:1057 #, c-format msgid "%s: bad revision" msgstr "%s: неправилна версия" -#: sequencer.c:1101 +#: sequencer.c:1091 msgid "Can't revert as initial commit" msgstr "Първоначалното подаване не може да бъде отменено" -#: sequencer.c:1102 +#: sequencer.c:1092 msgid "Can't cherry-pick into empty head" msgstr "При празен връх не могат да се отбират подавания" @@ -1673,7 +1816,35 @@ msgstr "При празен връх не могат да се отбират п msgid "failed to read %s" msgstr "файлът „%s“ не може да бъде прочетен" -#: sha1_name.c:463 +#: setup.c:468 +#, c-format +msgid "Expected git repo version <= %d, found %d" +msgstr "Очаква се версия на хранилището на git <= %d, а не %d" + +#: setup.c:476 +msgid "unknown repository extensions found:" +msgstr "открити са непознати разширения в хранилището:" + +#: sha1_file.c:1080 +msgid "offset before end of packfile (broken .idx?)" +msgstr "" +"отместване преди края на пакетния файл (възможно е индексът да е повреден)" + +#: sha1_file.c:2458 +#, c-format +msgid "offset before start of pack index for %s (corrupt index?)" +msgstr "" +"отместване преди началото на индекса на пакетния файл „%s“ (възможно е " +"индексът да е повреден)" + +#: sha1_file.c:2462 +#, c-format +msgid "offset beyond end of pack index for %s (truncated index?)" +msgstr "" +"отместване преди края на индекса на пакетния файл „%s“ (възможно е индексът " +"да е отрязан)" + +#: sha1_name.c:462 msgid "" "Git normally never creates a ref that ends with 40 hex characters\n" "because it will be ignored when you just specify 40-hex. These refs\n" @@ -1697,67 +1868,315 @@ msgstr "" "спрете това съобщение като изпълните командата:\n" "„git config advice.objectNameWarning false“" -#: submodule.c:61 submodule.c:95 +#: submodule.c:64 submodule.c:98 msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first" msgstr "" "Неслетите файлове „.gitmodules“ не могат да бъдат променяни. Първо " "коригирайте конфликтите" -#: submodule.c:65 submodule.c:99 +#: submodule.c:68 submodule.c:102 #, c-format msgid "Could not find section in .gitmodules where path=%s" msgstr "Във файла „.gitmodules“ липсва раздел за директория „path=%s“" -#: submodule.c:73 +#: submodule.c:76 #, c-format msgid "Could not update .gitmodules entry %s" msgstr "Записът „%s“ във файла „.gitmodules“ не може да бъде променен" -#: submodule.c:106 +#: submodule.c:109 #, c-format msgid "Could not remove .gitmodules entry for %s" msgstr "Записът „%s“ във файла „.gitmodules“ не може да бъде изтрит" -#: submodule.c:117 +#: submodule.c:120 msgid "staging updated .gitmodules failed" msgstr "неуспешно добавяне на променения файл „.gitmodules“ в индекса" -#: submodule.c:1040 +#: submodule.c:177 +msgid "negative values not allowed for submodule.fetchJobs" +msgstr "Настройката „submodule.fetchJobs“ не приема отрицателни стойности" + +#: submodule-config.c:355 #, c-format -msgid "Could not set core.worktree in %s" -msgstr "Настройката „core.worktree“ не може да се зададе в „%s“" +msgid "invalid value for %s" +msgstr "Неправилна стойност за „%s“" -#: trailer.c:491 trailer.c:495 trailer.c:499 trailer.c:553 trailer.c:557 -#: trailer.c:561 +#: trailer.c:237 +#, c-format +msgid "running trailer command '%s' failed" +msgstr "неуспешно изпълнение на завършващата команда „%s“" + +#: trailer.c:492 trailer.c:496 trailer.c:500 trailer.c:554 trailer.c:558 +#: trailer.c:562 #, c-format msgid "unknown value '%s' for key '%s'" msgstr "неправилна стойност „%s“ за настройката „%s“" -#: trailer.c:543 trailer.c:548 builtin/remote.c:296 +#: trailer.c:544 trailer.c:549 builtin/remote.c:289 #, c-format msgid "more than one %s" msgstr "стойността „%s“ се повтаря в настройките" -#: trailer.c:581 +#: trailer.c:582 #, c-format msgid "empty trailer token in trailer '%.*s'" msgstr "празна завършваща лексема в епилога „%.*s“" -#: trailer.c:701 +#: trailer.c:702 #, c-format msgid "could not read input file '%s'" msgstr "входният файл „%s“ не може да бъде прочетен" -#: trailer.c:704 +#: trailer.c:705 msgid "could not read from stdin" msgstr "от стандартния вход не може да се чете" -#: transport-helper.c:1025 +#: trailer.c:857 builtin/am.c:42 +#, c-format +msgid "could not stat %s" +msgstr "Не може да се получи информация чрез „stat“ за „%s“" + +#: trailer.c:859 +#, c-format +msgid "file %s is not a regular file" +msgstr "„%s“ не е обикновен файл" + +#: trailer.c:861 +#, c-format +msgid "file %s is not writable by user" +msgstr "„%s“: няма права за записване на файла" + +#: trailer.c:873 +msgid "could not open temporary file" +msgstr "временният файл не може да се отвори" + +#: trailer.c:912 +#, c-format +msgid "could not rename temporary file to %s" +msgstr "временният файл не може да се преименува на „%s“" + +#: transport-helper.c:1041 #, c-format msgid "Could not read ref %s" msgstr "Указателят „%s“ не може да се прочете." -#: unpack-trees.c:203 +#: unpack-trees.c:64 +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by checkout:\n" +"%%sPlease commit your changes or stash them before you can switch branches." +msgstr "" +"Изтеглянето ще презапише локалните промени на тези файлове:\n" +"%%sПодайте или скатайте промените, за да преминете към нов клон." + +#: unpack-trees.c:66 +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by checkout:\n" +"%%s" +msgstr "" +"Изтеглянето ще презапише локалните промени на тези файлове:\n" +"%%s" + +#: unpack-trees.c:69 +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by merge:\n" +"%%sPlease commit your changes or stash them before you can merge." +msgstr "" +"Сливането ще презапише локалните промени на тези файлове:\n" +"%%sПодайте или скатайте промените, за да слеете." + +#: unpack-trees.c:71 +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by merge:\n" +"%%s" +msgstr "" +"Сливането ще презапише локалните промени на тези файлове:\n" +"%%s" + +#: unpack-trees.c:74 +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by %s:\n" +"%%sPlease commit your changes or stash them before you can %s." +msgstr "" +"„%s“ ще презапише локалните промени на тези файлове:\n" +"%%sПодайте или скатайте промените, за да извършите „%s“." + +#: unpack-trees.c:76 +#, c-format +msgid "" +"Your local changes to the following files would be overwritten by %s:\n" +"%%s" +msgstr "" +"„%s“ ще презапише локалните промени на тези файлове:\n" +"%%s" + +#: unpack-trees.c:81 +#, c-format +msgid "" +"Updating the following directories would lose untracked files in it:\n" +"%s" +msgstr "" +"Обновяването на тези директории ще изтрие неследените файлове в тях:\n" +"%s" + +#: unpack-trees.c:85 +#, c-format +msgid "" +"The following untracked working tree files would be removed by checkout:\n" +"%%sPlease move or remove them before you can switch branches." +msgstr "" +"Изтеглянето ще изтрие тези неследени файлове в работното дърво:\n" +"%%sПреместете ги или ги изтрийте, за да преминете на друг клон." + +#: unpack-trees.c:87 +#, c-format +msgid "" +"The following untracked working tree files would be removed by checkout:\n" +"%%s" +msgstr "" +"Изтеглянето ще изтрие тези неследени файлове в работното дърво:\n" +"%%s" + +#: unpack-trees.c:90 +#, c-format +msgid "" +"The following untracked working tree files would be removed by merge:\n" +"%%sPlease move or remove them before you can merge." +msgstr "" +"Сливането ще изтрие тези неследени файлове в работното дърво:\n" +"%%sПреместете ги или ги изтрийте, за да слеете." + +#: unpack-trees.c:92 +#, c-format +msgid "" +"The following untracked working tree files would be removed by merge:\n" +"%%s" +msgstr "" +"Сливането ще изтрие тези неследени файлове в работното дърво:\n" +"%%s" + +#: unpack-trees.c:95 +#, c-format +msgid "" +"The following untracked working tree files would be removed by %s:\n" +"%%sPlease move or remove them before you can %s." +msgstr "" +"„%s“ ще изтрие тези неследени файлове в работното дърво:\n" +"%%sПреместете ги или ги изтрийте, за да извършите „%s“." + +#: unpack-trees.c:97 +#, c-format +msgid "" +"The following untracked working tree files would be removed by %s:\n" +"%%s" +msgstr "" +"„%s“ ще изтрие тези неследени файлове в работното дърво:\n" +"%%s" + +#: unpack-trees.c:102 +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by " +"checkout:\n" +"%%sPlease move or remove them before you can switch branches." +msgstr "" +"Изтеглянето ще презапише тези неследени файлове в работното дърво:\n" +"%%sПреместете ги или ги изтрийте, за да смените клон." + +#: unpack-trees.c:104 +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by " +"checkout:\n" +"%%s" +msgstr "" +"Изтеглянето ще презапише тези неследени файлове в работното дърво:\n" +"%%s" + +#: unpack-trees.c:107 +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by merge:\n" +"%%sPlease move or remove them before you can merge." +msgstr "" +"Сливането ще презапише тези неследени файлове в работното дърво:\n" +"%%sПреместете ги или ги изтрийте, за да слеете." + +#: unpack-trees.c:109 +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by merge:\n" +"%%s" +msgstr "" +"Сливането ще презапише тези неследени файлове в работното дърво:\n" +"%%s" + +#: unpack-trees.c:112 +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by %s:\n" +"%%sPlease move or remove them before you can %s." +msgstr "" +"„%s“ ще презапише тези неследени файлове в работното дърво:\n" +"%%sПреместете ги или ги изтрийте, за да извършите „%s“." + +#: unpack-trees.c:114 +#, c-format +msgid "" +"The following untracked working tree files would be overwritten by %s:\n" +"%%s" +msgstr "" +"„%s“ ще презапише тези неследени файлове в работното дърво:\n" +"%%s" + +#: unpack-trees.c:121 +#, c-format +msgid "Entry '%s' overlaps with '%s'. Cannot bind." +msgstr "Записът за „%s“ съвпада с този за „%s“. Не може да се присвои." + +#: unpack-trees.c:124 +#, c-format +msgid "" +"Cannot update sparse checkout: the following entries are not up-to-date:\n" +"%s" +msgstr "" +"Частичното изтегляне не може да бъде обновено: следните записи не са " +"актуални:\n" +"%s" + +#: unpack-trees.c:126 +#, c-format +msgid "" +"The following Working tree files would be overwritten by sparse checkout " +"update:\n" +"%s" +msgstr "" +"Обновяването на частичното изтегляне ще презапише тези файлове в работното " +"дърво:\n" +"%s" + +#: unpack-trees.c:128 +#, c-format +msgid "" +"The following Working tree files would be removed by sparse checkout " +"update:\n" +"%s" +msgstr "" +"Обновяването на частичното изтегляне ще изтрие тези файлове в работното " +"дърво:\n" +"%s" + +#: unpack-trees.c:205 +#, c-format +msgid "Aborting\n" +msgstr "Преустановяване на действието\n" + +#: unpack-trees.c:237 msgid "Checking out files" msgstr "Изтегляне на файлове" @@ -1790,210 +2209,206 @@ msgstr "неправилен номер на порт" msgid "invalid '..' path segment" msgstr "неправилна част от пътя „..“" -#: wrapper.c:219 wrapper.c:362 +#: wrapper.c:222 wrapper.c:381 #, c-format msgid "could not open '%s' for reading and writing" msgstr "„%s“ не може да бъде отворен и за четене, и за запис" -#: wrapper.c:221 wrapper.c:364 +#: wrapper.c:224 wrapper.c:383 builtin/am.c:779 #, c-format msgid "could not open '%s' for writing" msgstr "„%s“ не може да бъде отворен за запис" -#: wrapper.c:223 wrapper.c:366 builtin/am.c:338 builtin/commit.c:1691 -#: builtin/merge.c:1074 builtin/pull.c:380 +#: wrapper.c:226 wrapper.c:385 builtin/am.c:323 builtin/am.c:772 +#: builtin/am.c:860 builtin/commit.c:1711 builtin/merge.c:1086 +#: builtin/pull.c:407 #, c-format msgid "could not open '%s' for reading" msgstr "файлът не може да бъде прочетен: „%s“" -#: wrapper.c:579 -#, c-format -msgid "unable to access '%s': %s" -msgstr "няма достъп до „%s“: %s" - -#: wrapper.c:600 +#: wrapper.c:594 wrapper.c:615 #, c-format msgid "unable to access '%s'" msgstr "няма достъп до „%s“" -#: wrapper.c:608 +#: wrapper.c:623 msgid "unable to get current working directory" msgstr "текущата работна директория е недостъпна" -#: wrapper.c:635 +#: wrapper.c:650 #, c-format msgid "could not open %s for writing" msgstr "„%s“ не може да бъде отворен за запис" # FIXME - must be the same as Could not write to '%s' above -#: wrapper.c:646 builtin/am.c:425 +#: wrapper.c:661 builtin/am.c:410 #, c-format msgid "could not write to %s" msgstr "„%s“ не може да бъде записан" -#: wrapper.c:652 +#: wrapper.c:667 #, c-format msgid "could not close %s" msgstr "„%s“ не може да се затвори" -#: wt-status.c:149 +#: wt-status.c:150 msgid "Unmerged paths:" msgstr "Неслети пътища:" -#: wt-status.c:176 wt-status.c:203 +#: wt-status.c:177 wt-status.c:204 #, c-format msgid " (use \"git reset %s ...\" to unstage)" msgstr " (използвайте „git reset %s ФАЙЛ…“, за да извадите ФАЙЛа от индекса)" -#: wt-status.c:178 wt-status.c:205 +#: wt-status.c:179 wt-status.c:206 msgid " (use \"git rm --cached ...\" to unstage)" msgstr "" " (използвайте „git rm --cached %s ФАЙЛ…“, за да извадите ФАЙЛа от индекса)" -#: wt-status.c:182 +#: wt-status.c:183 msgid " (use \"git add ...\" to mark resolution)" msgstr "" " (използвайте „git add ФАЙЛ…“, за да укажете разрешаването на конфликта)" -#: wt-status.c:184 wt-status.c:188 +#: wt-status.c:185 wt-status.c:189 msgid " (use \"git add/rm ...\" as appropriate to mark resolution)" msgstr "" " (използвайте „git add/rm ФАЙЛ…“, според решението, което избирате за " "конфликта)" -#: wt-status.c:186 +#: wt-status.c:187 msgid " (use \"git rm ...\" to mark resolution)" msgstr "" " (използвайте „git rm ФАЙЛ…“, за да укажете разрешаването на конфликта)" -#: wt-status.c:197 wt-status.c:880 +#: wt-status.c:198 wt-status.c:881 msgid "Changes to be committed:" msgstr "Промени, които ще бъдат подадени:" -#: wt-status.c:215 wt-status.c:889 +#: wt-status.c:216 wt-status.c:890 msgid "Changes not staged for commit:" msgstr "Промени, които не са в индекса за подаване:" -#: wt-status.c:219 +#: wt-status.c:220 msgid " (use \"git add ...\" to update what will be committed)" msgstr "" " (използвайте „git add ФАЙЛ…“, за да обновите съдържанието за подаване)" -#: wt-status.c:221 +#: wt-status.c:222 msgid " (use \"git add/rm ...\" to update what will be committed)" msgstr "" " (използвайте „git add/rm ФАЙЛ…“, за да обновите съдържанието за подаване)" -#: wt-status.c:222 +#: wt-status.c:223 msgid "" " (use \"git checkout -- ...\" to discard changes in working directory)" msgstr "" " (използвайте „git checkout -- ФАЙЛ…“, за да отхвърлите промените в " "работното дърво)" -#: wt-status.c:224 +#: wt-status.c:225 msgid " (commit or discard the untracked or modified content in submodules)" msgstr "" " (подайте или отхвърлете неследеното или промененото съдържание в " "подмодулите)" -#: wt-status.c:236 +#: wt-status.c:237 #, c-format msgid " (use \"git %s ...\" to include in what will be committed)" msgstr "" " (използвайте „git %s ФАЙЛ…“, за да определите какво включвате в подаването)" -#: wt-status.c:251 +#: wt-status.c:252 msgid "both deleted:" msgstr "изтрити в двата случая:" -#: wt-status.c:253 +#: wt-status.c:254 msgid "added by us:" msgstr "добавени от вас:" -#: wt-status.c:255 +#: wt-status.c:256 msgid "deleted by them:" msgstr "изтрити от тях:" -#: wt-status.c:257 +#: wt-status.c:258 msgid "added by them:" msgstr "добавени от тях:" -#: wt-status.c:259 +#: wt-status.c:260 msgid "deleted by us:" msgstr "изтрити от вас:" -#: wt-status.c:261 +#: wt-status.c:262 msgid "both added:" msgstr "добавени и в двата случая:" -#: wt-status.c:263 +#: wt-status.c:264 msgid "both modified:" msgstr "променени и в двата случая:" -#: wt-status.c:265 +#: wt-status.c:266 #, c-format msgid "bug: unhandled unmerged status %x" msgstr "грешка: състоянието на промяната „%x“ не може да бъде обработено" -#: wt-status.c:273 +#: wt-status.c:274 msgid "new file:" msgstr "нов файл:" -#: wt-status.c:275 +#: wt-status.c:276 msgid "copied:" msgstr "копиран:" -#: wt-status.c:277 +#: wt-status.c:278 msgid "deleted:" msgstr "изтрит:" -#: wt-status.c:279 +#: wt-status.c:280 msgid "modified:" msgstr "променен:" -#: wt-status.c:281 +#: wt-status.c:282 msgid "renamed:" msgstr "преименуван:" -#: wt-status.c:283 +#: wt-status.c:284 msgid "typechange:" msgstr "смяна на вида:" -#: wt-status.c:285 +#: wt-status.c:286 msgid "unknown:" msgstr "непозната промяна:" -#: wt-status.c:287 +#: wt-status.c:288 msgid "unmerged:" msgstr "неслят:" -#: wt-status.c:369 +#: wt-status.c:370 msgid "new commits, " msgstr "нови подавания, " -#: wt-status.c:371 +#: wt-status.c:372 msgid "modified content, " msgstr "променено съдържание, " -#: wt-status.c:373 +#: wt-status.c:374 msgid "untracked content, " msgstr "неследено съдържание, " -#: wt-status.c:390 +#: wt-status.c:391 #, c-format msgid "bug: unhandled diff status %c" msgstr "грешка: състоянието на промяната „%c“ не може да бъде обработено" -#: wt-status.c:754 +#: wt-status.c:755 msgid "Submodules changed but not updated:" msgstr "Подмодулите са променени, но не са обновени:" -#: wt-status.c:756 +#: wt-status.c:757 msgid "Submodule changes to be committed:" msgstr "Промени в подмодулите за подаване:" -#: wt-status.c:837 +#: wt-status.c:838 msgid "" "Do not touch the line above.\n" "Everything below will be removed." @@ -2001,39 +2416,39 @@ msgstr "" "Не променяйте горния ред.\n" "Всичко отдолу ще бъде изтрито." -#: wt-status.c:948 +#: wt-status.c:949 msgid "You have unmerged paths." msgstr "Някои пътища не са слети." -#: wt-status.c:951 +#: wt-status.c:952 msgid " (fix conflicts and run \"git commit\")" msgstr " (коригирайте конфликтите и изпълнете „git commit“)" -#: wt-status.c:954 +#: wt-status.c:956 msgid "All conflicts fixed but you are still merging." msgstr "Всички конфликти са решени, но продължавате сливането." -#: wt-status.c:957 +#: wt-status.c:959 msgid " (use \"git commit\" to conclude merge)" msgstr " (използвайте „git commit“, за да завършите сливането)" -#: wt-status.c:967 +#: wt-status.c:969 msgid "You are in the middle of an am session." msgstr "В момента прилагате поредица от кръпки чрез „git am“." -#: wt-status.c:970 +#: wt-status.c:972 msgid "The current patch is empty." msgstr "Текущата кръпка е празна." -#: wt-status.c:974 +#: wt-status.c:976 msgid " (fix conflicts and then run \"git am --continue\")" msgstr " (коригирайте конфликтите и изпълнете „git am --continue“)" -#: wt-status.c:976 +#: wt-status.c:978 msgid " (use \"git am --skip\" to skip this patch)" msgstr " (използвайте „git am --skip“, за да пропуснете тази кръпка)" -#: wt-status.c:978 +#: wt-status.c:980 msgid " (use \"git am --abort\" to restore the original branch)" msgstr "" " (използвайте „git am --abort“, за да възстановите първоначалния клон)" @@ -2187,43 +2602,43 @@ msgstr "" " (използвайте „git bisect reset“, за да се върнете към първоначалното " "състояние и клон)" -#: wt-status.c:1438 +#: wt-status.c:1460 msgid "On branch " msgstr "На клон " -#: wt-status.c:1444 +#: wt-status.c:1466 msgid "interactive rebase in progress; onto " msgstr "извършвате интерактивно пребазиране върху " -#: wt-status.c:1446 +#: wt-status.c:1468 msgid "rebase in progress; onto " msgstr "извършвате пребазиране върху " -#: wt-status.c:1451 +#: wt-status.c:1473 msgid "HEAD detached at " msgstr "Указателят „HEAD“ не е свързан и е при " -#: wt-status.c:1453 +#: wt-status.c:1475 msgid "HEAD detached from " msgstr "Указателят „HEAD“ не е свързан и е отделѐн от " -#: wt-status.c:1456 +#: wt-status.c:1478 msgid "Not currently on any branch." msgstr "Извън всички клони." -#: wt-status.c:1474 +#: wt-status.c:1496 msgid "Initial commit" msgstr "Първоначално подаване" -#: wt-status.c:1488 +#: wt-status.c:1510 msgid "Untracked files" msgstr "Неследени файлове" -#: wt-status.c:1490 +#: wt-status.c:1512 msgid "Ignored files" msgstr "Игнорирани файлове" -#: wt-status.c:1494 +#: wt-status.c:1516 #, c-format msgid "" "It took %.2f seconds to enumerate untracked files. 'status -uno'\n" @@ -2235,32 +2650,32 @@ msgstr "" "изпълнението, но не трябва да забравяте ръчно да добавяте новите файлове.\n" "За повече подробности погледнете „git status help“." -#: wt-status.c:1500 +#: wt-status.c:1522 #, c-format msgid "Untracked files not listed%s" msgstr "Неследените файлове не са изведени%s" -#: wt-status.c:1502 +#: wt-status.c:1524 msgid " (use -u option to show untracked files)" msgstr " (използвайте опцията „-u“, за да изведете неследените файлове)" -#: wt-status.c:1508 +#: wt-status.c:1530 msgid "No changes" msgstr "Няма промени" -#: wt-status.c:1513 +#: wt-status.c:1535 #, c-format msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n" msgstr "" "към индекса за подаване не са добавени промени (използвайте „git add“ и/или " "„git commit -a“)\n" -#: wt-status.c:1516 +#: wt-status.c:1538 #, c-format msgid "no changes added to commit\n" msgstr "към индекса за подаване не са добавени промени\n" -#: wt-status.c:1519 +#: wt-status.c:1541 #, c-format msgid "" "nothing added to commit but untracked files present (use \"git add\" to " @@ -2269,52 +2684,56 @@ msgstr "" "към индекса за подаване не са добавени промени, но има нови файлове " "(използвайте „git add“, за да започне тяхното следене)\n" -#: wt-status.c:1522 +#: wt-status.c:1544 #, c-format msgid "nothing added to commit but untracked files present\n" msgstr "към индекса за подаване не са добавени промени, но има нови файлове\n" -#: wt-status.c:1525 +#: wt-status.c:1547 #, c-format msgid "nothing to commit (create/copy files and use \"git add\" to track)\n" msgstr "" "липсват каквито и да е промени (създайте или копирайте файлове и използвайте " "„git add“, за да започне тяхното следене)\n" -#: wt-status.c:1528 wt-status.c:1533 +#: wt-status.c:1550 wt-status.c:1555 #, c-format msgid "nothing to commit\n" msgstr "липсват каквито и да е промени\n" -#: wt-status.c:1531 +#: wt-status.c:1553 #, c-format msgid "nothing to commit (use -u to show untracked files)\n" msgstr "" "липсват каквито и да е промени (използвайте опцията „-u“, за да се изведат и " "неследените файлове)\n" -#: wt-status.c:1535 +#: wt-status.c:1557 #, c-format msgid "nothing to commit, working directory clean\n" msgstr "липсват каквито и да е промени, работното дърво е чисто\n" -#: wt-status.c:1642 +#: wt-status.c:1664 msgid "Initial commit on " msgstr "Първоначално подаване на клон" -#: wt-status.c:1646 +#: wt-status.c:1668 msgid "HEAD (no branch)" msgstr "HEAD (извън клон)" -#: wt-status.c:1675 +#: wt-status.c:1697 msgid "gone" msgstr "изтрит" -#: wt-status.c:1677 wt-status.c:1685 +#: wt-status.c:1699 wt-status.c:1707 msgid "behind " msgstr "назад с " -#: compat/precompose_utf8.c:56 builtin/clone.c:408 +#: wt-status.c:1702 wt-status.c:1705 +msgid "ahead " +msgstr "напред с " + +#: compat/precompose_utf8.c:57 builtin/clone.c:415 #, c-format msgid "failed to unlink '%s'" msgstr "неуспешно изтриване на „%s“" @@ -2328,7 +2747,7 @@ msgstr "git add [ОПЦИЯ…] [--] ПЪТ…" msgid "unexpected diff status %c" msgstr "неочакван изходен код при генериране на разлика: %c" -#: builtin/add.c:70 builtin/commit.c:278 +#: builtin/add.c:70 builtin/commit.c:280 msgid "updating files failed" msgstr "неуспешно обновяване на файловете" @@ -2341,7 +2760,7 @@ msgstr "изтриване на „%s“\n" msgid "Unstaged changes after refreshing the index:" msgstr "Промени, които и след обновяването на индекса не са добавени към него:" -#: builtin/add.c:194 builtin/rev-parse.c:796 +#: builtin/add.c:194 builtin/rev-parse.c:811 msgid "Could not read the index" msgstr "Индексът не може да бъде прочетен" @@ -2377,15 +2796,15 @@ msgid "The following paths are ignored by one of your .gitignore files:\n" msgstr "" "Следните пътища ще бъдат игнорирани според някой от файловете „.gitignore“:\n" -#: builtin/add.c:249 builtin/clean.c:894 builtin/fetch.c:108 builtin/mv.c:110 -#: builtin/prune-packed.c:55 builtin/pull.c:182 builtin/push.c:543 -#: builtin/remote.c:1345 builtin/rm.c:268 builtin/send-pack.c:162 +#: builtin/add.c:249 builtin/clean.c:870 builtin/fetch.c:112 builtin/mv.c:111 +#: builtin/prune-packed.c:55 builtin/pull.c:197 builtin/push.c:511 +#: builtin/remote.c:1332 builtin/rm.c:268 builtin/send-pack.c:162 msgid "dry run" msgstr "пробно изпълнeние" -#: builtin/add.c:250 builtin/apply.c:4571 builtin/check-ignore.c:19 -#: builtin/commit.c:1322 builtin/count-objects.c:85 builtin/fsck.c:558 -#: builtin/log.c:1645 builtin/mv.c:109 builtin/read-tree.c:114 +#: builtin/add.c:250 builtin/apply.c:4563 builtin/check-ignore.c:19 +#: builtin/commit.c:1333 builtin/count-objects.c:85 builtin/fsck.c:557 +#: builtin/log.c:1826 builtin/mv.c:110 builtin/read-tree.c:114 msgid "be verbose" msgstr "повече подробности" @@ -2393,7 +2812,7 @@ msgstr "повече подробности" msgid "interactive picking" msgstr "интерактивно отбиране на промени" -#: builtin/add.c:253 builtin/checkout.c:1153 builtin/reset.c:286 +#: builtin/add.c:253 builtin/checkout.c:1154 builtin/reset.c:286 msgid "select hunks interactively" msgstr "интерактивен избор на парчета код" @@ -2465,138 +2884,123 @@ msgstr "Нищо не е зададено и нищо не е добавено.\ msgid "Maybe you wanted to say 'git add .'?\n" msgstr "Вероятно искахте да използвате „git add .“?\n" -#: builtin/add.c:358 builtin/check-ignore.c:172 builtin/clean.c:938 -#: builtin/commit.c:337 builtin/mv.c:130 builtin/reset.c:235 builtin/rm.c:298 -#: builtin/submodule--helper.c:40 +#: builtin/add.c:358 builtin/check-ignore.c:172 builtin/clean.c:914 +#: builtin/commit.c:339 builtin/mv.c:131 builtin/reset.c:235 builtin/rm.c:298 +#: builtin/submodule--helper.c:240 msgid "index file corrupt" msgstr "файлът с индекса е повреден" -#: builtin/add.c:439 builtin/apply.c:4669 builtin/mv.c:279 builtin/rm.c:430 +#: builtin/add.c:439 builtin/apply.c:4661 builtin/mv.c:283 builtin/rm.c:430 msgid "Unable to write new index file" msgstr "Новият индекс не може да бъде записан" -#: builtin/am.c:42 -#, c-format -msgid "could not stat %s" -msgstr "Не може да се получи информация чрез „stat“ за „%s“" - -#: builtin/am.c:271 builtin/commit.c:738 builtin/merge.c:1077 +#: builtin/am.c:256 builtin/commit.c:749 builtin/merge.c:1089 #, c-format msgid "could not read '%s'" msgstr "файлът „%s“ не може да бъде прочетен" -#: builtin/am.c:445 +#: builtin/am.c:430 msgid "could not parse author script" msgstr "скриптът за автор не може да се анализира" -#: builtin/am.c:522 +#: builtin/am.c:507 #, c-format msgid "'%s' was deleted by the applypatch-msg hook" msgstr "„%s“ бе изтрит от куката „applypatch-msg“" -#: builtin/am.c:563 builtin/notes.c:300 +#: builtin/am.c:548 builtin/notes.c:300 #, c-format msgid "Malformed input line: '%s'." msgstr "Даденият входен ред е с неправилен формат: „%s“." -#: builtin/am.c:600 builtin/notes.c:315 +#: builtin/am.c:585 builtin/notes.c:315 #, c-format msgid "Failed to copy notes from '%s' to '%s'" msgstr "Бележката не може да се копира от „%s“ към „%s“" -#: builtin/am.c:626 +#: builtin/am.c:611 msgid "fseek failed" msgstr "неуспешно изпълнение на „fseek“" -#: builtin/am.c:787 builtin/am.c:875 -#, c-format -msgid "could not open '%s' for reading: %s" -msgstr "„%s“ не може да бъде отворен за четене: %s" - -#: builtin/am.c:794 -#, c-format -msgid "could not open '%s' for writing: %s" -msgstr "„%s“ не може да бъде отворен за запис: %s" - -#: builtin/am.c:803 +#: builtin/am.c:788 #, c-format msgid "could not parse patch '%s'" msgstr "кръпката „%s“ не може да се анализира" -#: builtin/am.c:868 +#: builtin/am.c:853 msgid "Only one StGIT patch series can be applied at once" msgstr "" "Само една серия кръпки от „StGIT“ може да бъде прилагана в даден момент" -#: builtin/am.c:916 +#: builtin/am.c:900 msgid "invalid timestamp" msgstr "неправилна стойност за време" -#: builtin/am.c:919 builtin/am.c:927 +#: builtin/am.c:903 builtin/am.c:911 msgid "invalid Date line" msgstr "неправилен ред за дата „Date“" -#: builtin/am.c:924 +#: builtin/am.c:908 msgid "invalid timezone offset" msgstr "неправилно отместване на часовия пояс" -#: builtin/am.c:1011 +#: builtin/am.c:995 msgid "Patch format detection failed." msgstr "Форматът на кръпката не може да бъде определен." -#: builtin/am.c:1016 builtin/clone.c:373 +#: builtin/am.c:1000 builtin/clone.c:380 #, c-format msgid "failed to create directory '%s'" msgstr "директорията „%s“ не може да бъде създадена" -#: builtin/am.c:1020 +#: builtin/am.c:1004 msgid "Failed to split patches." msgstr "Кръпките не могат да бъдат разделени." -#: builtin/am.c:1152 builtin/commit.c:363 +#: builtin/am.c:1136 builtin/commit.c:365 msgid "unable to write index file" msgstr "индексът не може да бъде записан" -#: builtin/am.c:1203 +#: builtin/am.c:1187 #, c-format msgid "When you have resolved this problem, run \"%s --continue\"." msgstr "След коригирането на този проблем изпълнете „%s --continue“." -#: builtin/am.c:1204 +#: builtin/am.c:1188 #, c-format msgid "If you prefer to skip this patch, run \"%s --skip\" instead." msgstr "Ако предпочитате да прескочите тази кръпка, изпълнете „%s --skip“." -#: builtin/am.c:1205 +#: builtin/am.c:1189 #, c-format msgid "To restore the original branch and stop patching, run \"%s --abort\"." msgstr "За да се върнете към първоначалното състояние, изпълнете „%s --abort“." -#: builtin/am.c:1343 +#: builtin/am.c:1327 msgid "Patch is empty. Was it split wrong?" msgstr "Празна кръпка. Дали не е разделена погрешно?" -#: builtin/am.c:1417 builtin/log.c:1347 +#: builtin/am.c:1401 builtin/log.c:1516 #, c-format msgid "invalid ident line: %s" msgstr "грешна идентичност: %s" -#: builtin/am.c:1444 +#: builtin/am.c:1428 #, c-format msgid "unable to parse commit %s" msgstr "подаването не може да бъде анализирано: %s" -#: builtin/am.c:1646 +#: builtin/am.c:1630 msgid "Repository lacks necessary blobs to fall back on 3-way merge." msgstr "" "В хранилището липсват необходимите обекти BLOB, за да се премине към тройно " "сливане." -#: builtin/am.c:1648 +#: builtin/am.c:1632 msgid "Using index info to reconstruct a base tree..." msgstr "Базовото дърво се реконструира от информацията в индекса…" -#: builtin/am.c:1667 +#: builtin/am.c:1651 msgid "" "Did you hand edit your patch?\n" "It does not apply to blobs recorded in its index." @@ -2604,39 +3008,39 @@ msgstr "" "Кръпката не може да се приложи към обектите BLOB в индекса.\n" "Да не би да сте я редактирали на ръка?" -#: builtin/am.c:1673 +#: builtin/am.c:1657 msgid "Falling back to patching base and 3-way merge..." msgstr "Преминаване към прилагане на кръпка към базата и тройно сливане…" -#: builtin/am.c:1688 +#: builtin/am.c:1672 msgid "Failed to merge in the changes." msgstr "Неуспешно сливане на промените." -#: builtin/am.c:1712 builtin/merge.c:632 +#: builtin/am.c:1696 builtin/merge.c:636 msgid "git write-tree failed to write a tree" msgstr "Командата „git write-tree“ не успя да запише обект-дърво" -#: builtin/am.c:1719 +#: builtin/am.c:1703 msgid "applying to an empty history" msgstr "прилагане върху празна история" -#: builtin/am.c:1732 builtin/commit.c:1755 builtin/merge.c:829 -#: builtin/merge.c:854 +#: builtin/am.c:1716 builtin/commit.c:1775 builtin/merge.c:841 +#: builtin/merge.c:866 msgid "failed to write commit object" msgstr "обектът за подаването не може да бъде записан" -#: builtin/am.c:1764 builtin/am.c:1768 +#: builtin/am.c:1748 builtin/am.c:1752 #, c-format msgid "cannot resume: %s does not exist." msgstr "не може да се продължи — „%s“ не съществува." -#: builtin/am.c:1784 +#: builtin/am.c:1768 msgid "cannot be interactive without stdin connected to a terminal." msgstr "" "За интерактивно изпълнение е необходимо стандартният\n" "изход да е свързан с терминал, а в момента не е." -#: builtin/am.c:1789 +#: builtin/am.c:1773 msgid "Commit Body is:" msgstr "Тялото на кръпката за прилагане е:" @@ -2644,38 +3048,38 @@ msgstr "Тялото на кръпката за прилагане е:" #. in your translation. The program will only accept English #. input at this point. #. -#: builtin/am.c:1799 +#: builtin/am.c:1783 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: " msgstr "" "Прилагане? „y“ — да/„n“ — не/„e“ — редактиране/„v“ — преглед/„a“ — приемане " "на всичко:" -#: builtin/am.c:1849 +#: builtin/am.c:1833 #, c-format msgid "Dirty index: cannot apply patches (dirty: %s)" msgstr "" "Индексът не е чист: кръпките не могат да бъдат приложени (замърсени са: %s)" -#: builtin/am.c:1884 builtin/am.c:1955 +#: builtin/am.c:1868 builtin/am.c:1940 #, c-format msgid "Applying: %.*s" msgstr "Прилагане: %.*s" -#: builtin/am.c:1900 +#: builtin/am.c:1884 msgid "No changes -- Patch already applied." msgstr "Без промени — кръпката вече е приложена." -#: builtin/am.c:1908 +#: builtin/am.c:1892 #, c-format msgid "Patch failed at %s %.*s" msgstr "Неуспешно прилагане на кръпка при %s %.*s“" -#: builtin/am.c:1914 +#: builtin/am.c:1898 #, c-format msgid "The copy of the patch that failed is found in: %s" msgstr "Дубликат на проблемната кръпка се намира в: %s" -#: builtin/am.c:1958 +#: builtin/am.c:1943 msgid "" "No changes - did you forget to use 'git add'?\n" "If there is nothing left to stage, chances are that something else\n" @@ -2685,7 +3089,7 @@ msgstr "" "Ако няма друга промяна за включване в индекса, най-вероятно някоя друга\n" "кръпка е довела до същите промени и в такъв случай просто пропуснете тази." -#: builtin/am.c:1965 +#: builtin/am.c:1950 msgid "" "You still have unmerged paths in your index.\n" "Did you forget to use 'git add'?" @@ -2693,17 +3097,17 @@ msgstr "" "Индексът все още съдържа неслети промени.\n" "Възможно е да не сте изпълнили „git add“." -#: builtin/am.c:2073 builtin/am.c:2077 builtin/am.c:2089 builtin/reset.c:308 +#: builtin/am.c:2058 builtin/am.c:2062 builtin/am.c:2074 builtin/reset.c:308 #: builtin/reset.c:316 #, c-format msgid "Could not parse object '%s'." msgstr "„%s“ не е разпознат като обект." -#: builtin/am.c:2125 +#: builtin/am.c:2110 msgid "failed to clean index" msgstr "индексът не може да бъде изчистен" -#: builtin/am.c:2159 +#: builtin/am.c:2144 msgid "" "You seem to have moved HEAD since the last 'am' failure.\n" "Not rewinding to ORIG_HEAD" @@ -2714,157 +3118,159 @@ msgstr "" "към\n" "„ORIG_HEAD“" -#: builtin/am.c:2220 +#: builtin/am.c:2205 #, c-format msgid "Invalid value for --patch-format: %s" msgstr "Неправилна стойност за „--patch-format“: „%s“" -#: builtin/am.c:2253 +#: builtin/am.c:2238 msgid "git am [] [(|)...]" msgstr "git am [ОПЦИЯ…] [ФАЙЛ_С_ПОЩА|ДИРЕКТОРИЯ_С_ПОЩА]…" -#: builtin/am.c:2254 +#: builtin/am.c:2239 msgid "git am [] (--continue | --skip | --abort)" msgstr "git am [ОПЦИЯ…] (--continue | --quit | --abort)" -#: builtin/am.c:2260 +#: builtin/am.c:2245 msgid "run interactively" msgstr "интерактивна работа" -#: builtin/am.c:2262 +#: builtin/am.c:2247 msgid "historical option -- no-op" msgstr "изоставена опция, съществува по исторически причини, нищо не прави" -#: builtin/am.c:2264 +#: builtin/am.c:2249 msgid "allow fall back on 3way merging if needed" msgstr "да се преминава към тройно сливане при нужда." -#: builtin/am.c:2265 builtin/init-db.c:474 builtin/prune-packed.c:57 +#: builtin/am.c:2250 builtin/init-db.c:478 builtin/prune-packed.c:57 #: builtin/repack.c:171 msgid "be quiet" msgstr "без извеждане на информация" -#: builtin/am.c:2267 +#: builtin/am.c:2252 msgid "add a Signed-off-by line to the commit message" msgstr "добавяне на ред за подпис „Signed-off-by“ в съобщението за подаване" -#: builtin/am.c:2270 +#: builtin/am.c:2255 msgid "recode into utf8 (default)" msgstr "прекодиране в UTF-8 (стандартно)" -#: builtin/am.c:2272 +#: builtin/am.c:2257 msgid "pass -k flag to git-mailinfo" msgstr "подаване на опцията „-k“ на командата „git-mailinfo“" -#: builtin/am.c:2274 +#: builtin/am.c:2259 msgid "pass -b flag to git-mailinfo" msgstr "подаване на опцията „-b“ на командата „git-mailinfo“" -#: builtin/am.c:2276 +#: builtin/am.c:2261 msgid "pass -m flag to git-mailinfo" msgstr "подаване на опцията „-m“ на командата „git-mailinfo“" -#: builtin/am.c:2278 +#: builtin/am.c:2263 msgid "pass --keep-cr flag to git-mailsplit for mbox format" msgstr "" "подаване на опцията „--keep-cr“ на командата „git-mailsplit“ за формат „mbox“" -#: builtin/am.c:2281 +#: builtin/am.c:2266 msgid "do not pass --keep-cr flag to git-mailsplit independent of am.keepcr" msgstr "" "без подаване на опцията „--keep-cr“ на командата „git-mailsplit“ независимо " "от „am.keepcr“" -#: builtin/am.c:2284 +#: builtin/am.c:2269 msgid "strip everything before a scissors line" msgstr "пропускане на всичко преди реда за отрязване" -#: builtin/am.c:2285 builtin/apply.c:4554 +#: builtin/am.c:2270 builtin/apply.c:4546 msgid "action" msgstr "действие" -#: builtin/am.c:2286 builtin/am.c:2289 builtin/am.c:2292 builtin/am.c:2295 -#: builtin/am.c:2298 builtin/am.c:2301 builtin/am.c:2304 builtin/am.c:2307 -#: builtin/am.c:2313 +#: builtin/am.c:2271 builtin/am.c:2274 builtin/am.c:2277 builtin/am.c:2280 +#: builtin/am.c:2283 builtin/am.c:2286 builtin/am.c:2289 builtin/am.c:2292 +#: builtin/am.c:2298 msgid "pass it through git-apply" msgstr "прекарване през „git-apply“" -#: builtin/am.c:2294 builtin/apply.c:4578 +#: builtin/am.c:2279 builtin/apply.c:4570 msgid "root" msgstr "НАЧАЛНА_ДИРЕКТОРИЯ" -#: builtin/am.c:2297 builtin/am.c:2300 builtin/apply.c:4516 -#: builtin/apply.c:4519 builtin/clone.c:85 builtin/fetch.c:93 -#: builtin/pull.c:167 builtin/submodule--helper.c:78 -#: builtin/submodule--helper.c:166 builtin/submodule--helper.c:169 +#: builtin/am.c:2282 builtin/am.c:2285 builtin/apply.c:4508 +#: builtin/apply.c:4511 builtin/clone.c:90 builtin/fetch.c:95 +#: builtin/pull.c:179 builtin/submodule--helper.c:277 +#: builtin/submodule--helper.c:404 builtin/submodule--helper.c:485 +#: builtin/submodule--helper.c:488 builtin/submodule--helper.c:767 +#: builtin/submodule--helper.c:770 msgid "path" msgstr "път" -#: builtin/am.c:2303 builtin/fmt-merge-msg.c:666 builtin/fmt-merge-msg.c:669 -#: builtin/grep.c:693 builtin/merge.c:198 builtin/pull.c:127 +#: builtin/am.c:2288 builtin/fmt-merge-msg.c:666 builtin/fmt-merge-msg.c:669 +#: builtin/grep.c:706 builtin/merge.c:199 builtin/pull.c:134 builtin/pull.c:193 #: builtin/repack.c:178 builtin/repack.c:182 builtin/show-branch.c:645 #: builtin/show-ref.c:175 builtin/tag.c:340 parse-options.h:132 #: parse-options.h:134 parse-options.h:244 msgid "n" msgstr "БРОЙ" -#: builtin/am.c:2306 builtin/apply.c:4522 +#: builtin/am.c:2291 builtin/apply.c:4514 msgid "num" msgstr "БРОЙ" -#: builtin/am.c:2309 builtin/for-each-ref.c:37 builtin/replace.c:438 +#: builtin/am.c:2294 builtin/for-each-ref.c:37 builtin/replace.c:438 #: builtin/tag.c:372 msgid "format" msgstr "ФОРМАТ" -#: builtin/am.c:2310 +#: builtin/am.c:2295 msgid "format the patch(es) are in" msgstr "формат на кръпките" -#: builtin/am.c:2316 +#: builtin/am.c:2301 msgid "override error message when patch failure occurs" msgstr "избрано от вас съобщение за грешка при прилагане на кръпки" -#: builtin/am.c:2318 +#: builtin/am.c:2303 msgid "continue applying patches after resolving a conflict" msgstr "продължаване на прилагането на кръпки след коригирането на конфликт" -#: builtin/am.c:2321 +#: builtin/am.c:2306 msgid "synonyms for --continue" msgstr "синоними на „--continue“" -#: builtin/am.c:2324 +#: builtin/am.c:2309 msgid "skip the current patch" msgstr "прескачане на текущата кръпка" -#: builtin/am.c:2327 +#: builtin/am.c:2312 msgid "restore the original branch and abort the patching operation." msgstr "" "възстановяване на първоначалното състояние на клона и преустановяване на " "прилагането на кръпката." -#: builtin/am.c:2331 +#: builtin/am.c:2316 msgid "lie about committer date" -msgstr "дата за подаване различна от първоначалнота" +msgstr "дата за подаване различна от първоначалната" -#: builtin/am.c:2333 +#: builtin/am.c:2318 msgid "use current timestamp for author date" msgstr "използване на текущото време като това за автор" -#: builtin/am.c:2335 builtin/commit.c:1593 builtin/merge.c:225 -#: builtin/pull.c:155 builtin/revert.c:92 builtin/tag.c:355 +#: builtin/am.c:2320 builtin/commit.c:1609 builtin/merge.c:228 +#: builtin/pull.c:164 builtin/revert.c:92 builtin/tag.c:355 msgid "key-id" msgstr "ИДЕНТИФИКАТОР_НА_КЛЮЧ" -#: builtin/am.c:2336 +#: builtin/am.c:2321 msgid "GPG-sign commits" msgstr "подписване на подаванията с GPG" -#: builtin/am.c:2339 +#: builtin/am.c:2324 msgid "(internal use for git-rebase)" msgstr "(ползва се вътрешно за „git-rebase“)" -#: builtin/am.c:2354 +#: builtin/am.c:2339 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." @@ -2872,18 +3278,18 @@ msgstr "" "Опциите „-b“/„--binary“ отдавна не правят нищо и\n" "ще бъдат премахнати в бъдеще. Не ги ползвайте." -#: builtin/am.c:2361 +#: builtin/am.c:2346 msgid "failed to read the index" msgstr "неуспешно изчитане на индекса" -#: builtin/am.c:2376 +#: builtin/am.c:2361 #, c-format msgid "previous rebase directory %s still exists but mbox given." msgstr "" "предишната директория за пребазиране „%s“ все още съществува, а е зададен " "файл „mbox“." -#: builtin/am.c:2400 +#: builtin/am.c:2385 #, c-format msgid "" "Stray %s directory found.\n" @@ -2892,7 +3298,7 @@ msgstr "" "Открита е излишна директория „%s“.\n" "Можете да я изтриете с командата „git am --abort“." -#: builtin/am.c:2406 +#: builtin/am.c:2391 msgid "Resolve operation not in progress, we are not resuming." msgstr "В момента не тече операция по коригиране и няма как да се продължи." @@ -2925,45 +3331,45 @@ msgstr "Регулярният израз върна %d при подадена msgid "unable to find filename in patch at line %d" msgstr "Липсва име на файл на ред %d от кръпката" -#: builtin/apply.c:940 +#: builtin/apply.c:937 #, c-format msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d" msgstr "" "git apply: лош изход от командата „git-diff“ — на ред %2$d се очакваше „/dev/" "null“, а бе получен „%1$s“" -#: builtin/apply.c:944 +#: builtin/apply.c:942 #, c-format msgid "git apply: bad git-diff - inconsistent new filename on line %d" msgstr "" "git apply: лош изход от командата „git-diff“ — на ред %d бе получено " "неправилно име на нов файл" -#: builtin/apply.c:945 +#: builtin/apply.c:943 #, c-format msgid "git apply: bad git-diff - inconsistent old filename on line %d" msgstr "" "git apply: лош изход от командата „git-diff“ — на ред %d бе получено " "неправилно име на стар файл" -#: builtin/apply.c:952 +#: builtin/apply.c:949 #, c-format msgid "git apply: bad git-diff - expected /dev/null on line %d" msgstr "" "git apply: лош изход от командата „git-diff“ — на ред %d се очакваше „/dev/" "null“" -#: builtin/apply.c:1415 +#: builtin/apply.c:1406 #, c-format msgid "recount: unexpected line: %.*s" msgstr "при повторното преброяване бе получен неочакван ред: „%.*s“" -#: builtin/apply.c:1472 +#: builtin/apply.c:1463 #, c-format msgid "patch fragment without header at line %d: %.*s" msgstr "част от кръпка без заглавна част на ред %d: %.*s" -#: builtin/apply.c:1489 +#: builtin/apply.c:1480 #, c-format msgid "" "git diff header lacks filename information when removing %d leading pathname " @@ -2978,65 +3384,65 @@ msgstr[1] "" "След съкращаването на първите %d части от компонентите на пътя, в заглавната " "част на „git diff“ липсва информация за име на файл (ред: %d)" -#: builtin/apply.c:1655 +#: builtin/apply.c:1646 msgid "new file depends on old contents" msgstr "новият файл зависи от старото съдържание на файла" -#: builtin/apply.c:1657 +#: builtin/apply.c:1648 msgid "deleted file still has contents" msgstr "изтритият файл не е празен" -#: builtin/apply.c:1683 +#: builtin/apply.c:1674 #, c-format msgid "corrupt patch at line %d" msgstr "грешка в кръпката на ред %d" -#: builtin/apply.c:1719 +#: builtin/apply.c:1710 #, c-format msgid "new file %s depends on old contents" msgstr "новият файл „%s“ зависи от старото съдържание на файла" -#: builtin/apply.c:1721 +#: builtin/apply.c:1712 #, c-format msgid "deleted file %s still has contents" msgstr "изтритият файл „%s“ не е празен" -#: builtin/apply.c:1724 +#: builtin/apply.c:1715 #, c-format msgid "** warning: file %s becomes empty but is not deleted" msgstr "● предупреждение: файлът „%s“ вече е празен, но не е изтрит" -#: builtin/apply.c:1870 +#: builtin/apply.c:1861 #, c-format msgid "corrupt binary patch at line %d: %.*s" msgstr "грешка в двоичната кръпка на ред %d: %.*s" -#: builtin/apply.c:1899 +#: builtin/apply.c:1895 #, c-format msgid "unrecognized binary patch at line %d" msgstr "неразпозната двоичната кръпка на ред %d" -#: builtin/apply.c:2050 +#: builtin/apply.c:2048 #, c-format msgid "patch with only garbage at line %d" msgstr "кръпката е с изцяло повредени данни на ред %d" -#: builtin/apply.c:2140 +#: builtin/apply.c:2138 #, c-format msgid "unable to read symlink %s" msgstr "символната връзка „%s“ не може да бъде прочетена" -#: builtin/apply.c:2144 +#: builtin/apply.c:2142 #, c-format msgid "unable to open or read %s" msgstr "файлът „%s“ не може да бъде отворен или прочетен" -#: builtin/apply.c:2777 +#: builtin/apply.c:2775 #, c-format msgid "invalid start of line: '%c'" msgstr "неправилно начало на ред: „%c“" -#: builtin/apply.c:2896 +#: builtin/apply.c:2894 #, c-format msgid "Hunk #%d succeeded at %d (offset %d line)." msgid_plural "Hunk #%d succeeded at %d (offset %d lines)." @@ -3045,13 +3451,13 @@ msgstr[0] "" msgstr[1] "" "%d-то парче код бе успешно приложено на ред %d (отместване от %d реда)." -#: builtin/apply.c:2908 +#: builtin/apply.c:2906 #, c-format msgid "Context reduced to (%ld/%ld) to apply fragment at %d" msgstr "" "Контекстът е намален на (%ld/%ld) за прилагането на парчето код на ред %d" -#: builtin/apply.c:2914 +#: builtin/apply.c:2912 #, c-format msgid "" "while searching for:\n" @@ -3060,328 +3466,338 @@ msgstr "" "при търсене за:\n" "%.*s" -#: builtin/apply.c:2934 +#: builtin/apply.c:2932 #, c-format msgid "missing binary patch data for '%s'" msgstr "липсват данните за двоичната кръпка за „%s“" -#: builtin/apply.c:3035 +#: builtin/apply.c:3033 #, c-format msgid "binary patch does not apply to '%s'" msgstr "двоичната кръпка не може да бъде приложена върху „%s“" -#: builtin/apply.c:3041 +#: builtin/apply.c:3039 #, c-format msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)" msgstr "" "двоичната кръпка за „%s“ води до неправилни резултати (очакваше се SHA1: " "„%s“, а бе получено: „%s“)" -#: builtin/apply.c:3062 +#: builtin/apply.c:3060 #, c-format msgid "patch failed: %s:%ld" msgstr "неуспешно прилагане на кръпка: „%s:%ld“" -#: builtin/apply.c:3186 +#: builtin/apply.c:3184 #, c-format msgid "cannot checkout %s" msgstr "„%s“ не може да се изтегли" -#: builtin/apply.c:3231 builtin/apply.c:3242 builtin/apply.c:3287 +#: builtin/apply.c:3229 builtin/apply.c:3240 builtin/apply.c:3285 #, c-format msgid "read of %s failed" msgstr "неуспешно прочитане на „%s“" -#: builtin/apply.c:3239 +#: builtin/apply.c:3237 #, c-format msgid "reading from '%s' beyond a symbolic link" msgstr "изчитане на „%s“ след проследяване на символна връзка" -#: builtin/apply.c:3267 builtin/apply.c:3489 +#: builtin/apply.c:3265 builtin/apply.c:3487 #, c-format msgid "path %s has been renamed/deleted" msgstr "обектът с път „%s“ е преименуван или изтрит" -#: builtin/apply.c:3348 builtin/apply.c:3503 +#: builtin/apply.c:3346 builtin/apply.c:3501 #, c-format msgid "%s: does not exist in index" msgstr "„%s“ не съществува в индекса" -#: builtin/apply.c:3352 builtin/apply.c:3495 builtin/apply.c:3517 +#: builtin/apply.c:3350 builtin/apply.c:3493 builtin/apply.c:3515 #, c-format msgid "%s: %s" msgstr "„%s“: %s" -#: builtin/apply.c:3357 builtin/apply.c:3511 +#: builtin/apply.c:3355 builtin/apply.c:3509 #, c-format msgid "%s: does not match index" msgstr "„%s“ не съответства на индекса" -#: builtin/apply.c:3459 +#: builtin/apply.c:3457 msgid "removal patch leaves file contents" msgstr "изтриващата кръпка оставя файла непразен" -#: builtin/apply.c:3528 +#: builtin/apply.c:3526 #, c-format msgid "%s: wrong type" msgstr "„%s“: неправилен вид" -#: builtin/apply.c:3530 +#: builtin/apply.c:3528 #, c-format msgid "%s has type %o, expected %o" msgstr "„%s“ е от вид „%o“, а се очакваше „%o“" -#: builtin/apply.c:3689 builtin/apply.c:3691 +#: builtin/apply.c:3687 builtin/apply.c:3689 #, c-format msgid "invalid path '%s'" msgstr "неправилен път: „%s“" -#: builtin/apply.c:3746 +#: builtin/apply.c:3744 #, c-format msgid "%s: already exists in index" msgstr "„%s“: вече съществува в индекса" -#: builtin/apply.c:3749 +#: builtin/apply.c:3747 #, c-format msgid "%s: already exists in working directory" msgstr "„%s“: вече съществува в работното дърво" -#: builtin/apply.c:3769 +#: builtin/apply.c:3767 #, c-format msgid "new mode (%o) of %s does not match old mode (%o)" msgstr "новите права за достъп (%o) на „%s“ не съвпадат със старите (%o)" -#: builtin/apply.c:3774 +#: builtin/apply.c:3772 #, c-format msgid "new mode (%o) of %s does not match old mode (%o) of %s" msgstr "" "новите права за достъп (%o) на „%s“ не съвпадат със старите (%o) на „%s“" -#: builtin/apply.c:3794 +#: builtin/apply.c:3792 #, c-format msgid "affected file '%s' is beyond a symbolic link" msgstr "засегнатият файл „%s“ е след символна връзка" -#: builtin/apply.c:3798 +#: builtin/apply.c:3796 #, c-format msgid "%s: patch does not apply" msgstr "Кръпката „%s“ не може да бъде приложена" -#: builtin/apply.c:3812 +#: builtin/apply.c:3810 #, c-format msgid "Checking patch %s..." msgstr "Проверяване на кръпката „%s“…" -#: builtin/apply.c:3905 builtin/checkout.c:233 builtin/reset.c:135 +#: builtin/apply.c:3903 builtin/checkout.c:233 builtin/reset.c:135 #, c-format msgid "make_cache_entry failed for path '%s'" msgstr "неуспешно създаване на запис в кеша чрез „make_cache_entry“ за „%s“" -#: builtin/apply.c:4048 +#: builtin/apply.c:4046 #, c-format msgid "unable to remove %s from index" msgstr "„%s“ не може да се извади от индекса" -#: builtin/apply.c:4077 +#: builtin/apply.c:4075 #, c-format msgid "corrupt patch for submodule %s" msgstr "повредена кръпка за модула „%s“" -#: builtin/apply.c:4081 +#: builtin/apply.c:4079 #, c-format msgid "unable to stat newly created file '%s'" msgstr "" "не може да се получи информация чрез „stat“ за новосъздадения файл „%s“" -#: builtin/apply.c:4086 +#: builtin/apply.c:4084 #, c-format msgid "unable to create backing store for newly created file %s" msgstr "" "не може да се за създаде мястото за съхранение на новосъздадения файл „%s“" -#: builtin/apply.c:4089 builtin/apply.c:4197 +#: builtin/apply.c:4087 builtin/apply.c:4195 #, c-format msgid "unable to add cache entry for %s" msgstr "не може да се добави запис в кеша за „%s“" -#: builtin/apply.c:4122 +#: builtin/apply.c:4120 #, c-format msgid "closing file '%s'" msgstr "затваряне на файла „%s“" -#: builtin/apply.c:4171 +#: builtin/apply.c:4169 #, c-format msgid "unable to write file '%s' mode %o" msgstr "файлът „%s“ не може да се запише с режим на достъп „%o“" -#: builtin/apply.c:4258 +#: builtin/apply.c:4256 #, c-format msgid "Applied patch %s cleanly." msgstr "Кръпката „%s“ бе приложена чисто." -#: builtin/apply.c:4266 +#: builtin/apply.c:4264 msgid "internal error" msgstr "вътрешна грешка" -#: builtin/apply.c:4269 +#: builtin/apply.c:4267 #, c-format msgid "Applying patch %%s with %d reject..." msgid_plural "Applying patch %%s with %d rejects..." msgstr[0] "Прилагане на кръпката „%%s“ с %d отхвърлено парче…" msgstr[1] "Прилагане на кръпката „%%s“ с %d отхвърлени парчета…" -#: builtin/apply.c:4279 +#: builtin/apply.c:4277 #, c-format msgid "truncating .rej filename to %.*s.rej" msgstr "съкращаване на името на файла с отхвърлените парчета на „ %.*s.rej“" -#: builtin/apply.c:4300 +#: builtin/apply.c:4285 +#, c-format +msgid "cannot open %s: %s" +msgstr "файлът „%s“ не може да бъде отворен: %s" + +#: builtin/apply.c:4298 #, c-format msgid "Hunk #%d applied cleanly." msgstr "%d-то парче бе успешно приложено." -#: builtin/apply.c:4303 +#: builtin/apply.c:4301 #, c-format msgid "Rejected hunk #%d." msgstr "%d-то парче бе отхвърлено." -#: builtin/apply.c:4393 +#: builtin/apply.c:4387 +#, c-format +msgid "Skipped patch '%s'." +msgstr "Пропусната кръпка: „%s“" + +#: builtin/apply.c:4395 msgid "unrecognized input" msgstr "непознат вход" -#: builtin/apply.c:4404 +#: builtin/apply.c:4406 msgid "unable to read index file" msgstr "индексът не може да бъде записан" -#: builtin/apply.c:4517 +#: builtin/apply.c:4509 msgid "don't apply changes matching the given path" msgstr "без прилагане на промените напасващи на дадения път" -#: builtin/apply.c:4520 +#: builtin/apply.c:4512 msgid "apply changes matching the given path" msgstr "прилагане на промените напасващи на дадения път" -#: builtin/apply.c:4523 +#: builtin/apply.c:4515 msgid "remove leading slashes from traditional diff paths" msgstr "премахване на този БРОЙ водещи елементи от пътищата в разликата" -#: builtin/apply.c:4526 +#: builtin/apply.c:4518 msgid "ignore additions made by the patch" msgstr "игнориране на редовете добавени от тази кръпка" -#: builtin/apply.c:4528 +#: builtin/apply.c:4520 msgid "instead of applying the patch, output diffstat for the input" msgstr "извеждане на статистика на промените без прилагане на кръпката" -#: builtin/apply.c:4532 +#: builtin/apply.c:4524 msgid "show number of added and deleted lines in decimal notation" msgstr "извеждане на броя на добавените и изтритите редове" -#: builtin/apply.c:4534 +#: builtin/apply.c:4526 msgid "instead of applying the patch, output a summary for the input" msgstr "извеждане на статистика на входните данни без прилагане на кръпката" -#: builtin/apply.c:4536 +#: builtin/apply.c:4528 msgid "instead of applying the patch, see if the patch is applicable" msgstr "проверка дали кръпката може да се приложи, без действително прилагане" -#: builtin/apply.c:4538 +#: builtin/apply.c:4530 msgid "make sure the patch is applicable to the current index" msgstr "проверка дали кръпката може да бъде приложена към текущия индекс" -#: builtin/apply.c:4540 +#: builtin/apply.c:4532 msgid "apply a patch without touching the working tree" msgstr "прилагане на кръпката без промяна на работното дърво" -#: builtin/apply.c:4542 +#: builtin/apply.c:4534 msgid "accept a patch that touches outside the working area" msgstr "прилагане на кръпка, която променя и файлове извън работното дърво" -#: builtin/apply.c:4544 +#: builtin/apply.c:4536 msgid "also apply the patch (use with --stat/--summary/--check)" msgstr "" "кръпката да бъде приложена. Опцията се комбинира с „--check“/„--stat“/„--" "summary“" -#: builtin/apply.c:4546 +#: builtin/apply.c:4538 msgid "attempt three-way merge if a patch does not apply" msgstr "пробване с тройно сливане, ако кръпката не може да се приложи директно" -#: builtin/apply.c:4548 +#: builtin/apply.c:4540 msgid "build a temporary index based on embedded index information" msgstr "" "създаване на временен индекс на база на включената информация за индекса" -#: builtin/apply.c:4550 builtin/checkout-index.c:198 builtin/ls-files.c:412 +#: builtin/apply.c:4543 builtin/checkout-index.c:169 builtin/ls-files.c:425 msgid "paths are separated with NUL character" msgstr "разделяне на пътищата с нулевия знак „NUL“" -#: builtin/apply.c:4553 +#: builtin/apply.c:4545 msgid "ensure at least lines of context match" msgstr "да се осигури контекст от поне такъв БРОЙ съвпадащи редове" -#: builtin/apply.c:4555 +#: builtin/apply.c:4547 msgid "detect new or modified lines that have whitespace errors" msgstr "засичане на нови или променени редове с грешки в знаците за интервали" -#: builtin/apply.c:4558 builtin/apply.c:4561 +#: builtin/apply.c:4550 builtin/apply.c:4553 msgid "ignore changes in whitespace when finding context" msgstr "" "игнориране на промените в знаците за интервали при откриване на контекста" -#: builtin/apply.c:4564 +#: builtin/apply.c:4556 msgid "apply the patch in reverse" msgstr "прилагане на кръпката в обратна посока" -#: builtin/apply.c:4566 +#: builtin/apply.c:4558 msgid "don't expect at least one line of context" msgstr "без изискване на дори и един ред контекст" -#: builtin/apply.c:4568 +#: builtin/apply.c:4560 msgid "leave the rejected hunks in corresponding *.rej files" msgstr "оставяне на отхвърлените парчета във файлове с разширение „.rej“" -#: builtin/apply.c:4570 +#: builtin/apply.c:4562 msgid "allow overlapping hunks" msgstr "позволяване на застъпващи се парчета" -#: builtin/apply.c:4573 +#: builtin/apply.c:4565 msgid "tolerate incorrectly detected missing new-line at the end of file" msgstr "пренебрегване на неправилно липсващ знак за нов ред в края на файл" -#: builtin/apply.c:4576 +#: builtin/apply.c:4568 msgid "do not trust the line counts in the hunk headers" msgstr "без доверяване на номерата на редовете в заглавните части на парчетата" -#: builtin/apply.c:4579 +#: builtin/apply.c:4571 msgid "prepend to all filenames" msgstr "добавяне на тази НАЧАЛНА_ДИРЕКТОРИЯ към имената на всички файлове" -#: builtin/apply.c:4601 +#: builtin/apply.c:4593 msgid "--3way outside a repository" msgstr "като „--3way“, но извън хранилище" -#: builtin/apply.c:4609 +#: builtin/apply.c:4601 msgid "--index outside a repository" msgstr "като „--index“, но извън хранилище" -#: builtin/apply.c:4612 +#: builtin/apply.c:4604 msgid "--cached outside a repository" msgstr "като „--cached“, но извън хранилище" -#: builtin/apply.c:4631 +#: builtin/apply.c:4623 #, c-format msgid "can't open patch '%s'" msgstr "кръпката „%s“ не може да бъде отворена" -#: builtin/apply.c:4645 +#: builtin/apply.c:4637 #, c-format msgid "squelched %d whitespace error" msgid_plural "squelched %d whitespace errors" msgstr[0] "пренебрегната е %d грешка в знаците за интервали" msgstr[1] "пренебрегнати са %d грешки в знаците за интервали" -#: builtin/apply.c:4651 builtin/apply.c:4661 +#: builtin/apply.c:4643 builtin/apply.c:4653 #, c-format msgid "%d line adds whitespace errors." msgid_plural "%d lines add whitespace errors." @@ -3436,120 +3852,128 @@ msgid "update BISECT_HEAD instead of checking out the current commit" msgstr "" "обновяване на указателя „BISECT_HEAD“ вместо да се използва текущото подаване" -#: builtin/blame.c:32 +#: builtin/blame.c:33 msgid "git blame [] [] [] [--] " msgstr "git blame [ОПЦИЯ…] [ОПЦИЯ_ЗА_ВЕРСИЯТА…] [ВЕРСИЯ] [--] ФАЙЛ" -#: builtin/blame.c:37 +#: builtin/blame.c:38 msgid " are documented in git-rev-list(1)" msgstr "ОПЦИИте_ЗА_ВЕРСИЯТА са документирани в ръководството git-rev-list(1)" -#: builtin/blame.c:2519 +#: builtin/blame.c:1782 +msgid "Blaming lines" +msgstr "Анотирани редове" + +#: builtin/blame.c:2531 msgid "Show blame entries as we find them, incrementally" msgstr "Извеждане на анотациите с намирането им, последователно" # FIXME SHA-1 -> SHA1 -#: builtin/blame.c:2520 +#: builtin/blame.c:2532 msgid "Show blank SHA-1 for boundary commits (Default: off)" msgstr "" "Извеждане на празни суми по SHA1 за граничните подавания (стандартно опцията " "е изключена)" -#: builtin/blame.c:2521 +#: builtin/blame.c:2533 msgid "Do not treat root commits as boundaries (Default: off)" msgstr "" "Началните подавания да не се считат за гранични (стандартно опцията е " "изключена)" -#: builtin/blame.c:2522 +#: builtin/blame.c:2534 msgid "Show work cost statistics" msgstr "Извеждане на статистика за извършените действия" -#: builtin/blame.c:2523 +#: builtin/blame.c:2535 +msgid "Force progress reporting" +msgstr "Принудително извеждане на напредъка" + +#: builtin/blame.c:2536 msgid "Show output score for blame entries" msgstr "Извеждане на допълнителна информация за определянето на анотациите" -#: builtin/blame.c:2524 +#: builtin/blame.c:2537 msgid "Show original filename (Default: auto)" msgstr "" "Извеждане на първоначалното име на файл (стандартно това е автоматично)" -#: builtin/blame.c:2525 +#: builtin/blame.c:2538 msgid "Show original linenumber (Default: off)" msgstr "" "Извеждане на първоначалният номер на ред (стандартно опцията е изключена)" -#: builtin/blame.c:2526 +#: builtin/blame.c:2539 msgid "Show in a format designed for machine consumption" msgstr "Извеждане във формат за по-нататъшна обработка" -#: builtin/blame.c:2527 +#: builtin/blame.c:2540 msgid "Show porcelain format with per-line commit information" msgstr "" "Извеждане във формат за команди от потребителско ниво с информация на всеки " "ред" -#: builtin/blame.c:2528 +#: builtin/blame.c:2541 msgid "Use the same output mode as git-annotate (Default: off)" msgstr "" "Използване на същия формат като „git-annotate“ (стандартно опцията е " "изключена)" -#: builtin/blame.c:2529 +#: builtin/blame.c:2542 msgid "Show raw timestamp (Default: off)" msgstr "Извеждане на неформатирани времена (стандартно опцията е изключена)" -#: builtin/blame.c:2530 +#: builtin/blame.c:2543 msgid "Show long commit SHA1 (Default: off)" msgstr "Извеждане на пълните суми по SHA1 (стандартно опцията е изключена)" -#: builtin/blame.c:2531 +#: builtin/blame.c:2544 msgid "Suppress author name and timestamp (Default: off)" msgstr "Без име на автор и време на промяна (стандартно опцията е изключена)" -#: builtin/blame.c:2532 +#: builtin/blame.c:2545 msgid "Show author email instead of name (Default: off)" msgstr "" "Извеждане на е-пощата на автора, а не името му (стандартно опцията е " "изключена)" -#: builtin/blame.c:2533 +#: builtin/blame.c:2546 msgid "Ignore whitespace differences" msgstr "Без разлики в знаците за интервали" -#: builtin/blame.c:2534 +#: builtin/blame.c:2547 msgid "Spend extra cycles to find better match" msgstr "Допълнителни изчисления за по-добри резултати" -#: builtin/blame.c:2535 +#: builtin/blame.c:2548 msgid "Use revisions from instead of calling git-rev-list" msgstr "Изчитане на версиите от ФАЙЛ, а не чрез изпълнение на „git-rev-list“" -#: builtin/blame.c:2536 +#: builtin/blame.c:2549 msgid "Use 's contents as the final image" msgstr "Използване на съдържанието на ФАЙЛа като крайно положение" -#: builtin/blame.c:2537 builtin/blame.c:2538 +#: builtin/blame.c:2550 builtin/blame.c:2551 msgid "score" msgstr "напасване на редовете" -#: builtin/blame.c:2537 +#: builtin/blame.c:2550 msgid "Find line copies within and across files" msgstr "" "Търсене на копирани редове както в рамките на един файл, така и от един файл " "към друг" -#: builtin/blame.c:2538 +#: builtin/blame.c:2551 msgid "Find line movements within and across files" msgstr "" "Търсене на преместени редове както в рамките на един файл, така и от един " "файл към друг" -#: builtin/blame.c:2539 +#: builtin/blame.c:2552 msgid "n,m" msgstr "n,m" -#: builtin/blame.c:2539 +#: builtin/blame.c:2552 msgid "Process only line range n,m, counting from 1" msgstr "" "Информация само за редовете в интервала от n до m включително. Броенето " @@ -3561,31 +3985,31 @@ msgstr "" #. 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:2620 +#: builtin/blame.c:2641 msgid "4 years, 11 months ago" msgstr "преди 4 години и 11 месеца" -#: builtin/branch.c:25 +#: builtin/branch.c:26 msgid "git branch [] [-r | -a] [--merged | --no-merged]" msgstr "git branch [ОПЦИЯ…] [-r | -a] [--merged | --no-merged]" -#: builtin/branch.c:26 +#: builtin/branch.c:27 msgid "git branch [] [-l] [-f] []" msgstr "git branch [ОПЦИЯ…] [-l] [-f] ИМЕ_НА_КЛОН [НАЧАЛО]" -#: builtin/branch.c:27 +#: builtin/branch.c:28 msgid "git branch [] [-r] (-d | -D) ..." msgstr "git branch [ОПЦИЯ…] [-r] (-d | -D) ИМЕ_НА_КЛОН…" -#: builtin/branch.c:28 +#: builtin/branch.c:29 msgid "git branch [] (-m | -M) [] " msgstr "git branch [ОПЦИЯ…] (-m | -M) [СТАР_КЛОН] НОВ_КЛОН" -#: builtin/branch.c:29 +#: builtin/branch.c:30 msgid "git branch [] [-r | -a] [--points-at]" msgstr "git branch [ОПЦИЯ…] [-r | -a] [--points-at]" -#: builtin/branch.c:142 +#: builtin/branch.c:143 #, c-format msgid "" "deleting branch '%s' that has been merged to\n" @@ -3594,7 +4018,7 @@ msgstr "" "изтриване на клона „%s“, който е слят към „%s“,\n" " но още не е слят към върха „HEAD“." -#: builtin/branch.c:146 +#: builtin/branch.c:147 #, c-format msgid "" "not deleting branch '%s' that is not yet merged to\n" @@ -3603,12 +4027,12 @@ msgstr "" "отказване на изтриване на клона „%s“, който не е слят към\n" " „%s“, но е слят към върха „HEAD“." -#: builtin/branch.c:160 +#: builtin/branch.c:161 #, c-format msgid "Couldn't look up commit object for '%s'" msgstr "Обектът-подаване за „%s“ не може да бъде открит" -#: builtin/branch.c:164 +#: builtin/branch.c:165 #, c-format msgid "" "The branch '%s' is not fully merged.\n" @@ -3617,301 +4041,322 @@ msgstr "" "Клонът „%s“ не е слят напълно. Ако сте сигурни, че искате\n" "да го изтриете, изпълнете „git branch -D %s“." -#: builtin/branch.c:177 +#: builtin/branch.c:178 msgid "Update of config-file failed" msgstr "Неуспешно обновяване на конфигурационния файл" -#: builtin/branch.c:205 +#: builtin/branch.c:206 msgid "cannot use -a with -d" msgstr "Опцията „-a“ е несъвместима с опцията „-d“" -#: builtin/branch.c:211 +#: builtin/branch.c:212 msgid "Couldn't look up commit object for HEAD" msgstr "Обектът-подаване, сочен от указателя „HEAD“, не може да бъде открит" -#: builtin/branch.c:219 +#: builtin/branch.c:226 #, c-format -msgid "Cannot delete the branch '%s' which you are currently on." -msgstr "Не можете да изтриете текущия клон „%s“" +msgid "Cannot delete branch '%s' checked out at '%s'" +msgstr "Не можете да изтриете клона „%s“, който е изтеглен в пътя „%s“" -#: builtin/branch.c:235 +#: builtin/branch.c:241 #, c-format msgid "remote-tracking branch '%s' not found." msgstr "следящият клон „%s“ не може да бъде открит." -#: builtin/branch.c:236 +#: builtin/branch.c:242 #, c-format msgid "branch '%s' not found." msgstr "клонът „%s“ не може да бъде открит." -#: builtin/branch.c:251 +#: builtin/branch.c:257 #, c-format msgid "Error deleting remote-tracking branch '%s'" msgstr "Грешка при изтриването на следящия клон „%s“" -#: builtin/branch.c:252 +#: builtin/branch.c:258 #, c-format msgid "Error deleting branch '%s'" msgstr "Грешка при изтриването на клона „%s“" -#: builtin/branch.c:259 +#: builtin/branch.c:265 #, c-format msgid "Deleted remote-tracking branch %s (was %s).\n" msgstr "Изтрит следящ клон „%s“ (той сочеше към „%s“).\n" -#: builtin/branch.c:260 +#: builtin/branch.c:266 #, c-format msgid "Deleted branch %s (was %s).\n" msgstr "Изтрит клон „%s“ (той сочеше към „%s“).\n" -#: builtin/branch.c:303 +#: builtin/branch.c:309 #, c-format msgid "[%s: gone]" msgstr "[%s: изтрит]" -#: builtin/branch.c:308 +#: builtin/branch.c:314 #, c-format msgid "[%s]" msgstr "[%s]" -#: builtin/branch.c:313 +#: builtin/branch.c:319 #, c-format msgid "[%s: behind %d]" msgstr "[%s: назад с %d]" -#: builtin/branch.c:315 +#: builtin/branch.c:321 #, c-format msgid "[behind %d]" msgstr "[назад с %d]" -#: builtin/branch.c:319 +#: builtin/branch.c:325 #, c-format msgid "[%s: ahead %d]" msgstr "[%s: напред с %d]" -#: builtin/branch.c:321 +#: builtin/branch.c:327 #, c-format msgid "[ahead %d]" msgstr "[напред с %d]" -#: builtin/branch.c:324 +#: builtin/branch.c:330 #, c-format msgid "[%s: ahead %d, behind %d]" msgstr "[%s: напред с %d, назад с %d]" -#: builtin/branch.c:327 +#: builtin/branch.c:333 #, c-format msgid "[ahead %d, behind %d]" msgstr "[напред с %d, назад с %d]" -#: builtin/branch.c:340 +#: builtin/branch.c:346 msgid " **** invalid ref ****" msgstr " ●●● неправилен указател ●●●" -#: builtin/branch.c:366 +#: builtin/branch.c:372 #, c-format msgid "(no branch, rebasing %s)" msgstr "(извън клон, пребазиране на „%s“)" -#: builtin/branch.c:369 +#: builtin/branch.c:375 #, c-format msgid "(no branch, bisect started on %s)" msgstr "(извън клон, двоично търсене от „%s“)" -#: builtin/branch.c:375 +#. TRANSLATORS: make sure this matches +#. "HEAD detached at " in wt-status.c +#: builtin/branch.c:381 #, c-format msgid "(HEAD detached at %s)" msgstr "(Указателят „HEAD“ не е свързан и е при „%s“)" -#: builtin/branch.c:378 +#. TRANSLATORS: make sure this matches +#. "HEAD detached from " in wt-status.c +#: builtin/branch.c:386 #, c-format msgid "(HEAD detached from %s)" msgstr "Указателят „HEAD“ не е свързан и е отделѐн от „%s“" -#: builtin/branch.c:382 +#: builtin/branch.c:390 msgid "(no branch)" msgstr "(извън клон)" -#: builtin/branch.c:524 +#: builtin/branch.c:541 +#, c-format +msgid "Branch %s is being rebased at %s" +msgstr "Клонът „%s“ се пребазира върху „%s“" + +#: builtin/branch.c:545 +#, c-format +msgid "Branch %s is being bisected at %s" +msgstr "Търси се двоично в клона „%s“ при „%s“" + +#: builtin/branch.c:560 msgid "cannot rename the current branch while not on any." msgstr "" "не можете да преименувате текущия клон, защото сте извън който и да е клон" -#: builtin/branch.c:534 +#: builtin/branch.c:570 #, c-format msgid "Invalid branch name: '%s'" msgstr "Неправилно име на клон: „%s“" -#: builtin/branch.c:549 +#: builtin/branch.c:587 msgid "Branch rename failed" msgstr "Неуспешно преименуване на клон" -#: builtin/branch.c:553 +#: builtin/branch.c:591 #, c-format msgid "Renamed a misnamed branch '%s' away" msgstr "На клона с неправилно име „%s“ е дадено служебно име" -#: builtin/branch.c:557 +#: builtin/branch.c:594 #, c-format msgid "Branch renamed to %s, but HEAD is not updated!" msgstr "Клонът е преименуван на „%s“, но указателят „HEAD“ не е обновен" -#: builtin/branch.c:564 +#: builtin/branch.c:601 msgid "Branch is renamed, but update of config-file failed" msgstr "Клонът е преименуван, но конфигурационният файл не е обновен" -#: builtin/branch.c:587 -#, c-format -msgid "could not write branch description template: %s" -msgstr "шаблонът за описание на клон не бе записан: „%s“" +#: builtin/branch.c:623 +msgid "could not write branch description template" +msgstr "шаблонът за описание на клон не бе записан" -#: builtin/branch.c:616 +#: builtin/branch.c:651 msgid "Generic options" msgstr "Общи настройки" -#: builtin/branch.c:618 +#: builtin/branch.c:653 msgid "show hash and subject, give twice for upstream branch" msgstr "" "извеждане на хеша и темата. Повтарянето на опцията прибавя отдалечените клони" -#: builtin/branch.c:619 +#: builtin/branch.c:654 msgid "suppress informational messages" msgstr "без информационни съобщения" -#: builtin/branch.c:620 +#: builtin/branch.c:655 msgid "set up tracking mode (see git-pull(1))" msgstr "задаване на режима на следене (виж git-pull(1))" -#: builtin/branch.c:622 +#: builtin/branch.c:657 msgid "change upstream info" msgstr "смяна на следения клон" -#: builtin/branch.c:626 +#: builtin/branch.c:659 +msgid "upstream" +msgstr "клон-източник" + +#: builtin/branch.c:659 +msgid "change the upstream info" +msgstr "смяна на клона-източник" + +#: builtin/branch.c:661 msgid "use colored output" msgstr "цветен изход" -#: builtin/branch.c:627 +#: builtin/branch.c:662 msgid "act on remote-tracking branches" msgstr "действие върху следящите клони" -#: builtin/branch.c:629 builtin/branch.c:630 +#: builtin/branch.c:664 builtin/branch.c:665 msgid "print only branches that contain the commit" -msgstr "извеждане само на клоните, които съдържат това подаване" +msgstr "извеждане само на клоните, които съдържат това ПОДАВАНЕ" -#: builtin/branch.c:633 +#: builtin/branch.c:668 msgid "Specific git-branch actions:" msgstr "Специални действия на „git-branch“:" -#: builtin/branch.c:634 +#: builtin/branch.c:669 msgid "list both remote-tracking and local branches" msgstr "извеждане както на следящите, така и на локалните клони" -#: builtin/branch.c:636 +#: builtin/branch.c:671 msgid "delete fully merged branch" msgstr "изтриване на клони, които са напълно слети" -#: builtin/branch.c:637 +#: builtin/branch.c:672 msgid "delete branch (even if not merged)" msgstr "изтриване и на клони, които не са напълно слети" -#: builtin/branch.c:638 +#: builtin/branch.c:673 msgid "move/rename a branch and its reflog" msgstr "" "преместване/преименуване на клон и принадлежащият му журнал на указателите" -#: builtin/branch.c:639 +#: builtin/branch.c:674 msgid "move/rename a branch, even if target exists" msgstr "преместване/преименуване на клон, дори ако има вече клон с такова име" -#: builtin/branch.c:640 +#: builtin/branch.c:675 msgid "list branch names" msgstr "извеждане на имената на клоните" -#: builtin/branch.c:641 +#: builtin/branch.c:676 msgid "create the branch's reflog" msgstr "създаване на журнала на указателите на клона" -#: builtin/branch.c:643 +#: builtin/branch.c:678 msgid "edit the description for the branch" msgstr "редактиране на описанието на клона" -#: builtin/branch.c:644 +#: builtin/branch.c:679 msgid "force creation, move/rename, deletion" msgstr "принудително създаване, преместване, преименуване, изтриване" -#: builtin/branch.c:645 +#: builtin/branch.c:680 msgid "print only branches that are merged" msgstr "извеждане само на слетите клони" -#: builtin/branch.c:646 +#: builtin/branch.c:681 msgid "print only branches that are not merged" msgstr "извеждане само на неслетите клони" -#: builtin/branch.c:647 +#: builtin/branch.c:682 msgid "list branches in columns" msgstr "извеждане по колони" -#: builtin/branch.c:648 builtin/for-each-ref.c:38 builtin/tag.c:366 +#: builtin/branch.c:683 builtin/for-each-ref.c:38 builtin/tag.c:366 msgid "key" -msgstr "ключ" +msgstr "КЛЮЧ" -#: builtin/branch.c:649 builtin/for-each-ref.c:39 builtin/tag.c:367 +#: builtin/branch.c:684 builtin/for-each-ref.c:39 builtin/tag.c:367 msgid "field name to sort on" msgstr "име на полето, по което да е подредбата" -#: builtin/branch.c:651 builtin/for-each-ref.c:41 builtin/notes.c:398 -#: builtin/notes.c:401 builtin/notes.c:561 builtin/notes.c:564 +#: builtin/branch.c:686 builtin/for-each-ref.c:41 builtin/notes.c:401 +#: builtin/notes.c:404 builtin/notes.c:564 builtin/notes.c:567 #: builtin/tag.c:369 msgid "object" -msgstr "обект" +msgstr "ОБЕКТ" -#: builtin/branch.c:652 +#: builtin/branch.c:687 msgid "print only branches of the object" -msgstr "извеждане само на клоните на обекта" +msgstr "извеждане само на клоните на ОБЕКТА" -#: builtin/branch.c:670 +#: builtin/branch.c:705 msgid "Failed to resolve HEAD as a valid ref." msgstr "Не може да се открие към какво сочи указателят „HEAD“" -#: builtin/branch.c:674 builtin/clone.c:697 +#: builtin/branch.c:709 builtin/clone.c:707 msgid "HEAD not found below refs/heads!" msgstr "В директорията „refs/heads“ липсва файл „HEAD“" -#: builtin/branch.c:694 +#: builtin/branch.c:729 msgid "--column and --verbose are incompatible" msgstr "Опциите „--column“ и „--verbose“ са несъвместими" -#: builtin/branch.c:705 builtin/branch.c:747 +#: builtin/branch.c:740 builtin/branch.c:782 msgid "branch name required" msgstr "Необходимо е име на клон" -#: builtin/branch.c:723 +#: builtin/branch.c:758 msgid "Cannot give description to detached HEAD" msgstr "Не може да зададете описание на „HEAD“ извън клон" -#: builtin/branch.c:728 +#: builtin/branch.c:763 msgid "cannot edit description of more than one branch" msgstr "Не може да редактирате описанието на повече от един клон едновременно" -#: builtin/branch.c:735 +#: builtin/branch.c:770 #, c-format msgid "No commit on branch '%s' yet." msgstr "В клона „%s“ все още няма подавания." -#: builtin/branch.c:738 +#: builtin/branch.c:773 #, c-format msgid "No branch named '%s'." msgstr "Липсва клон на име „%s“." -#: builtin/branch.c:753 +#: builtin/branch.c:788 msgid "too many branches for a rename operation" msgstr "Прекалено много клони за преименуване" -#: builtin/branch.c:758 +#: builtin/branch.c:793 msgid "too many branches to set new upstream" msgstr "Зададени са прекалено много клони за следене" -#: builtin/branch.c:762 +#: builtin/branch.c:797 #, c-format msgid "" "could not set upstream of HEAD to %s when it does not point to any branch." @@ -3919,39 +4364,39 @@ msgstr "" "Следеното от „HEAD“ не може да се зададе да е „%s“, защото то не сочи към " "никой клон." -#: builtin/branch.c:765 builtin/branch.c:787 builtin/branch.c:808 +#: builtin/branch.c:800 builtin/branch.c:822 builtin/branch.c:843 #, c-format msgid "no such branch '%s'" msgstr "Няма клон на име „%s“." -#: builtin/branch.c:769 +#: builtin/branch.c:804 #, c-format msgid "branch '%s' does not exist" msgstr "Не съществува клон на име „%s“." -#: builtin/branch.c:781 +#: builtin/branch.c:816 msgid "too many branches to unset upstream" msgstr "Прекалено много клони за махане на следене" -#: builtin/branch.c:785 +#: builtin/branch.c:820 msgid "could not unset upstream of HEAD when it does not point to any branch." msgstr "" "Следеното от „HEAD“ не може да махне, защото то не сочи към никой клон." -#: builtin/branch.c:791 +#: builtin/branch.c:826 #, c-format msgid "Branch '%s' has no upstream information" msgstr "Няма информация клонът „%s“ да следи някой друг" -#: builtin/branch.c:805 +#: builtin/branch.c:840 msgid "it does not make sense to create 'HEAD' manually" msgstr "Няма никакъв смисъл ръчно да създавате „HEAD“." -#: builtin/branch.c:811 +#: builtin/branch.c:846 msgid "-a and -r options to 'git branch' do not make sense with a branch name" msgstr "Опциите „-a“ и „-r“ на „git branch“ са несъвместими с име на клон" -#: builtin/branch.c:814 +#: builtin/branch.c:849 #, c-format msgid "" "The --set-upstream flag is deprecated and will be removed. Consider using --" @@ -3960,7 +4405,7 @@ msgstr "" "Опцията „--set-upstream“ вече е остаряла и предстои да бъде махната. " "Използвайте „--track“ или „--set-upstream-to“\n" -#: builtin/branch.c:831 +#: builtin/branch.c:866 #, c-format msgid "" "\n" @@ -3971,16 +4416,6 @@ msgstr "" "За да накарате „%s“ да следи „%s“, изпълнете следната команда:\n" "\n" -#: builtin/branch.c:832 -#, c-format -msgid " git branch -d %s\n" -msgstr " git branch -d %s\n" - -#: builtin/branch.c:833 -#, c-format -msgid " git branch --set-upstream-to %s\n" -msgstr " git branch --set-upstream-to %s\n" - #: builtin/bundle.c:51 #, c-format msgid "%s is okay\n" @@ -4077,7 +4512,7 @@ msgstr "извеждане на всички атрибути, зададени msgid "use .gitattributes only from the index" msgstr "използване на файла „.gitattributes“ само от индекса" -#: builtin/check-attr.c:21 builtin/check-ignore.c:22 builtin/hash-object.c:96 +#: builtin/check-attr.c:21 builtin/check-ignore.c:22 builtin/hash-object.c:97 msgid "read file names from stdin" msgstr "изчитане на имената на файловете от стандартния вход" @@ -4085,7 +4520,7 @@ msgstr "изчитане на имената на файловете от ста msgid "terminate input and output records by a NUL character" msgstr "разделяне на входните и изходните записи с нулевия знак „NUL“" -#: builtin/check-ignore.c:18 builtin/checkout.c:1134 builtin/gc.c:325 +#: builtin/check-ignore.c:18 builtin/checkout.c:1135 builtin/gc.c:325 msgid "suppress progress reporting" msgstr "без показване на напредъка" @@ -4138,49 +4573,54 @@ msgstr "контактът не може да бъде анализиран: %s" msgid "no contacts specified" msgstr "не са указани контакти" -#: builtin/checkout-index.c:126 +#: builtin/checkout-index.c:127 msgid "git checkout-index [] [--] [...]" msgstr "git checkout-index [ОПЦИЯ…] [--] [ФАЙЛ…]" -#: builtin/checkout-index.c:188 +#: builtin/checkout-index.c:144 +msgid "stage should be between 1 and 3 or all" +msgstr "етапът трябва да е „1“, „2“, „3“ или „all“ (всички)" + +#: builtin/checkout-index.c:160 msgid "check out all files in the index" msgstr "изтегляне на всички файлове в индекса" -#: builtin/checkout-index.c:189 +#: builtin/checkout-index.c:161 msgid "force overwrite of existing files" msgstr "презаписване на файловете, дори и да съществуват" -#: builtin/checkout-index.c:191 +#: builtin/checkout-index.c:163 msgid "no warning for existing files and files not in index" msgstr "без предупреждения при липсващи файлове и файлове не в индекса" -#: builtin/checkout-index.c:193 +#: builtin/checkout-index.c:165 msgid "don't checkout new files" msgstr "без изтегляне на нови файлове" -#: builtin/checkout-index.c:195 +#: builtin/checkout-index.c:167 msgid "update stat information in the index file" msgstr "обновяване на информацията получена чрез „stat“ за файловете в индекса" -#: builtin/checkout-index.c:201 +#: builtin/checkout-index.c:171 msgid "read list of paths from the standard input" msgstr "изчитане на пътищата от стандартния вход" -#: builtin/checkout-index.c:203 +#: builtin/checkout-index.c:173 msgid "write the content to temporary files" msgstr "записване на съдържанието във временни файлове" -#: builtin/checkout-index.c:204 builtin/column.c:30 -#: builtin/submodule--helper.c:172 builtin/submodule--helper.c:175 -#: builtin/submodule--helper.c:178 builtin/submodule--helper.c:181 +#: builtin/checkout-index.c:174 builtin/column.c:30 +#: builtin/submodule--helper.c:491 builtin/submodule--helper.c:494 +#: builtin/submodule--helper.c:497 builtin/submodule--helper.c:500 +#: builtin/submodule--helper.c:774 msgid "string" msgstr "НИЗ" -#: builtin/checkout-index.c:205 +#: builtin/checkout-index.c:175 msgid "when creating files, prepend " msgstr "при създаването на нови файлове да се добавя префикса НИЗ" -#: builtin/checkout-index.c:208 +#: builtin/checkout-index.c:177 msgid "copy out the files from named stage" msgstr "копиране на файловете от това състояние на сливане" @@ -4222,45 +4662,49 @@ msgstr "пътят „%s“ не може да бъде слян" msgid "Unable to add merge result for '%s'" msgstr "Резултатът за „%s“ не може да бъде слян" -#: builtin/checkout.c:251 builtin/checkout.c:254 builtin/checkout.c:257 -#: builtin/checkout.c:260 +#: builtin/checkout.c:250 builtin/checkout.c:253 builtin/checkout.c:256 +#: builtin/checkout.c:259 #, c-format msgid "'%s' cannot be used with updating paths" msgstr "Опцията „%s“ е несъвместима с обновяването на пътища" -#: builtin/checkout.c:263 builtin/checkout.c:266 +#: builtin/checkout.c:262 builtin/checkout.c:265 #, c-format msgid "'%s' cannot be used with %s" msgstr "Опцията „%s“ е несъвместима с „%s“" -#: builtin/checkout.c:269 +#: builtin/checkout.c:268 #, c-format msgid "Cannot update paths and switch to branch '%s' at the same time." msgstr "" "Невъзможно е едновременно да обновявате пътища и да преминете към клона „%s“." -#: builtin/checkout.c:280 builtin/checkout.c:474 +#: builtin/checkout.c:279 builtin/checkout.c:473 msgid "corrupt index file" msgstr "повреден файл на индекса" -#: builtin/checkout.c:340 builtin/checkout.c:347 +#: builtin/checkout.c:339 builtin/checkout.c:346 #, c-format msgid "path '%s' is unmerged" msgstr "пътят „%s“ не е слят" -#: builtin/checkout.c:496 +#: builtin/checkout.c:495 msgid "you need to resolve your current index first" msgstr "първо трябва да коригирате индекса си" -#: builtin/checkout.c:623 +#: builtin/checkout.c:622 #, c-format msgid "Can not do reflog for '%s': %s\n" msgstr "Журналът на указателите за „%s“ не може да се проследи: %s\n" -#: builtin/checkout.c:661 +#: builtin/checkout.c:660 msgid "HEAD is now at" msgstr "Указателят „HEAD“ в момента сочи към" +#: builtin/checkout.c:664 builtin/clone.c:661 +msgid "unable to update HEAD" +msgstr "Указателят „HEAD“ не може да бъде обновен" + #: builtin/checkout.c:668 #, c-format msgid "Reset branch '%s'\n" @@ -4276,7 +4720,7 @@ msgstr "Вече сте на „%s“\n" msgid "Switched to and reset branch '%s'\n" msgstr "Преминаване към клона „%s“ и зануляване на промените\n" -#: builtin/checkout.c:677 builtin/checkout.c:1066 +#: builtin/checkout.c:677 builtin/checkout.c:1067 #, c-format msgid "Switched to a new branch '%s'\n" msgstr "Преминахте към новия клон „%s“\n" @@ -4348,7 +4792,7 @@ msgstr "вътрешна грешка при обхождането на вер msgid "Previous HEAD position was" msgstr "Преди това „HEAD“ сочеше към" -#: builtin/checkout.c:823 builtin/checkout.c:1061 +#: builtin/checkout.c:823 builtin/checkout.c:1062 msgid "You are on a branch yet to be born" msgstr "В момента сте на клон, който предстои да бъде създаден" @@ -4357,137 +4801,137 @@ msgstr "В момента сте на клон, който предстои да msgid "only one reference expected, %d given." msgstr "очакваше се един указател, а сте подали %d." -#: builtin/checkout.c:1007 builtin/worktree.c:213 +#: builtin/checkout.c:1008 builtin/worktree.c:212 #, c-format msgid "invalid reference: %s" msgstr "неправилен указател: %s" -#: builtin/checkout.c:1036 +#: builtin/checkout.c:1037 #, c-format msgid "reference is not a tree: %s" msgstr "указателят не сочи към обект-дърво: %s" -#: builtin/checkout.c:1075 +#: builtin/checkout.c:1076 msgid "paths cannot be used with switching branches" msgstr "задаването на път е несъвместимо с преминаването от един клон към друг" -#: builtin/checkout.c:1078 builtin/checkout.c:1082 +#: builtin/checkout.c:1079 builtin/checkout.c:1083 #, c-format msgid "'%s' cannot be used with switching branches" msgstr "опцията „%s“ е несъвместима с преминаването от един клон към друг" -#: builtin/checkout.c:1086 builtin/checkout.c:1089 builtin/checkout.c:1094 -#: builtin/checkout.c:1097 +#: builtin/checkout.c:1087 builtin/checkout.c:1090 builtin/checkout.c:1095 +#: builtin/checkout.c:1098 #, c-format msgid "'%s' cannot be used with '%s'" msgstr "опцията „%s“ е несъвместима с „%s“" -#: builtin/checkout.c:1102 +#: builtin/checkout.c:1103 #, c-format msgid "Cannot switch branch to a non-commit '%s'" msgstr "" "За да преминете към клон, подайте указател, който сочи към подаване. „%s“ не " "е такъв" -#: builtin/checkout.c:1135 builtin/checkout.c:1137 builtin/clone.c:83 -#: builtin/remote.c:165 builtin/remote.c:167 builtin/worktree.c:320 -#: builtin/worktree.c:322 +#: builtin/checkout.c:1136 builtin/checkout.c:1138 builtin/clone.c:88 +#: builtin/remote.c:165 builtin/remote.c:167 builtin/worktree.c:323 +#: builtin/worktree.c:325 msgid "branch" msgstr "клон" -#: builtin/checkout.c:1136 +#: builtin/checkout.c:1137 msgid "create and checkout a new branch" msgstr "създаване и преминаване към нов клон" -#: builtin/checkout.c:1138 +#: builtin/checkout.c:1139 msgid "create/reset and checkout a branch" msgstr "създаване/зануляване на клон и преминаване към него" -#: builtin/checkout.c:1139 +#: builtin/checkout.c:1140 msgid "create reflog for new branch" msgstr "създаване на журнал на указателите за нов клон" -#: builtin/checkout.c:1140 +#: builtin/checkout.c:1141 msgid "detach the HEAD at named commit" msgstr "отделяне на указателя „HEAD“ към указаното подаване" -#: builtin/checkout.c:1141 +#: builtin/checkout.c:1142 msgid "set upstream info for new branch" msgstr "задаване на кой клон бива следен при създаването на новия клон" -#: builtin/checkout.c:1143 +#: builtin/checkout.c:1144 msgid "new-branch" msgstr "НОВ_КЛОН" -#: builtin/checkout.c:1143 +#: builtin/checkout.c:1144 msgid "new unparented branch" msgstr "нов клон без родител" -#: builtin/checkout.c:1144 +#: builtin/checkout.c:1145 msgid "checkout our version for unmerged files" msgstr "изтегляне на вашата версия на неслетите файлове" -#: builtin/checkout.c:1146 +#: builtin/checkout.c:1147 msgid "checkout their version for unmerged files" msgstr "изтегляне на чуждата версия на неслетите файлове" -#: builtin/checkout.c:1148 +#: builtin/checkout.c:1149 msgid "force checkout (throw away local modifications)" msgstr "принудително изтегляне (вашите промени ще бъдат занулени)" -#: builtin/checkout.c:1149 +#: builtin/checkout.c:1150 msgid "perform a 3-way merge with the new branch" msgstr "извършване на тройно сливане с новия клон" -#: builtin/checkout.c:1150 builtin/merge.c:227 +#: builtin/checkout.c:1151 builtin/merge.c:230 msgid "update ignored files (default)" msgstr "обновяване на игнорираните файлове (стандартно)" -#: builtin/checkout.c:1151 builtin/log.c:1266 parse-options.h:250 +#: builtin/checkout.c:1152 builtin/log.c:1432 parse-options.h:250 msgid "style" -msgstr "стил" +msgstr "СТИЛ" -#: builtin/checkout.c:1152 +#: builtin/checkout.c:1153 msgid "conflict style (merge or diff3)" msgstr "действие при конфликт (сливане или тройна разлика)" -#: builtin/checkout.c:1155 +#: builtin/checkout.c:1156 msgid "do not limit pathspecs to sparse entries only" msgstr "без ограничаване на изброените пътища само до частично изтеглените" -#: builtin/checkout.c:1157 +#: builtin/checkout.c:1158 msgid "second guess 'git checkout '" msgstr "" "опит за отгатване на име на клон след неуспешен опит с „git checkout " "НЕСЪЩЕСТВУВАЩ_КЛОН“" -#: builtin/checkout.c:1159 +#: builtin/checkout.c:1160 msgid "do not check if another worktree is holding the given ref" msgstr "без проверка дали друго работно дърво държи указателя" -#: builtin/checkout.c:1160 builtin/clone.c:57 builtin/fetch.c:112 -#: builtin/merge.c:224 builtin/pull.c:109 builtin/push.c:558 +#: builtin/checkout.c:1161 builtin/clone.c:60 builtin/fetch.c:116 +#: builtin/merge.c:227 builtin/pull.c:116 builtin/push.c:526 #: builtin/send-pack.c:168 msgid "force progress reporting" msgstr "извеждане на напредъка" -#: builtin/checkout.c:1191 +#: builtin/checkout.c:1192 msgid "-b, -B and --orphan are mutually exclusive" msgstr "Опциите „-b“, „-B“ и „--orphan“ са несъвместими една с друга" -#: builtin/checkout.c:1208 +#: builtin/checkout.c:1209 msgid "--track needs a branch name" msgstr "опцията „--track“ изисква име на клон" -#: builtin/checkout.c:1213 +#: builtin/checkout.c:1214 msgid "Missing branch name; try -b" msgstr "Липсва име на клон, използвайте опцията „-b“" -#: builtin/checkout.c:1249 +#: builtin/checkout.c:1250 msgid "invalid path specification" msgstr "указан е неправилен път" -#: builtin/checkout.c:1256 +#: builtin/checkout.c:1257 #, c-format msgid "" "Cannot update paths and switch to branch '%s' at the same time.\n" @@ -4496,12 +4940,12 @@ msgstr "" "Не можете едновременно да обновявате пътища и да преминете към клона „%s“.\n" "Дали не искате да изтеглите „%s“, който не сочи към подаване?" -#: builtin/checkout.c:1261 +#: builtin/checkout.c:1262 #, c-format msgid "git checkout: --detach does not take a path argument '%s'" msgstr "git checkout: опцията „--detach“ не приема аргумент-път „%s“" -#: builtin/checkout.c:1265 +#: builtin/checkout.c:1266 msgid "" "git checkout: --ours/--theirs, --force and --merge are incompatible when\n" "checking out of the index." @@ -4539,7 +4983,7 @@ msgstr "Хранилището „%s“ ще бъде прескочено\n" msgid "failed to remove %s" msgstr "файлът „%s“ не може да бъде изтрит" -#: builtin/clean.c:315 +#: builtin/clean.c:291 msgid "" "Prompt help:\n" "1 - select a numbered item\n" @@ -4551,7 +4995,7 @@ msgstr "" "ПРЕФИКС — избор на единствен обект по този уникален префикс\n" " — (празно) нищо да не се избира" -#: builtin/clean.c:319 +#: builtin/clean.c:295 msgid "" "Prompt help:\n" "1 - select a single item\n" @@ -4571,38 +5015,38 @@ msgstr "" "* — избиране на всички обекти\n" " — (празно) завършване на избирането" -#: builtin/clean.c:535 +#: builtin/clean.c:511 #, c-format msgid "Huh (%s)?" msgstr "Неправилен избор (%s). Изберете отново." # FIXME - should we use >> or sth else -#: builtin/clean.c:677 +#: builtin/clean.c:653 #, c-format msgid "Input ignore patterns>> " msgstr "Шаблони за игнорирани елементи≫ " -#: builtin/clean.c:714 +#: builtin/clean.c:690 #, c-format msgid "WARNING: Cannot find items matched by: %s" msgstr "ПРЕДУПРЕЖДЕНИЕ: Никой обект не напасва на „%s“" -#: builtin/clean.c:735 +#: builtin/clean.c:711 msgid "Select items to delete" msgstr "Избиране на обекти за изтриване" #. TRANSLATORS: Make sure to keep [y/N] as is -#: builtin/clean.c:776 +#: builtin/clean.c:752 #, c-format msgid "Remove %s [y/N]? " msgstr "Да се изтрие ли „%s“? „y“ — да, „N“ — НЕ" # FIXME improve message -#: builtin/clean.c:801 +#: builtin/clean.c:777 msgid "Bye." msgstr "Изход." -#: builtin/clean.c:809 +#: builtin/clean.c:785 msgid "" "clean - start cleaning\n" "filter by pattern - exclude items from deletion\n" @@ -4620,63 +5064,63 @@ msgstr "" "help — този край\n" "? — подсказка за шаблоните" -#: builtin/clean.c:836 +#: builtin/clean.c:812 msgid "*** Commands ***" msgstr "●●● Команди ●●●" # FIXME improve message -#: builtin/clean.c:837 +#: builtin/clean.c:813 msgid "What now" msgstr "Избор на следващо действие" -#: builtin/clean.c:845 +#: builtin/clean.c:821 msgid "Would remove the following item:" msgid_plural "Would remove the following items:" msgstr[0] "Следният обект ще бъде изтрит:" msgstr[1] "Следните обекти ще бъдат изтрити:" -#: builtin/clean.c:862 +#: builtin/clean.c:838 msgid "No more files to clean, exiting." msgstr "Файловете за изчистване свършиха. Изход от програмата." -#: builtin/clean.c:893 +#: builtin/clean.c:869 msgid "do not print names of files removed" msgstr "без извеждане на имената на файловете, които ще бъдат изтрити" -#: builtin/clean.c:895 +#: builtin/clean.c:871 msgid "force" msgstr "принудително изтриване" -#: builtin/clean.c:896 +#: builtin/clean.c:872 msgid "interactive cleaning" msgstr "интерактивно изтриване" -#: builtin/clean.c:898 +#: builtin/clean.c:874 msgid "remove whole directories" msgstr "изтриване на цели директории" -#: builtin/clean.c:899 builtin/describe.c:407 builtin/grep.c:709 -#: builtin/ls-files.c:443 builtin/name-rev.c:307 builtin/show-ref.c:182 +#: builtin/clean.c:875 builtin/describe.c:407 builtin/grep.c:724 +#: builtin/ls-files.c:456 builtin/name-rev.c:314 builtin/show-ref.c:182 msgid "pattern" -msgstr "шаблон" +msgstr "ШАБЛОН" -#: builtin/clean.c:900 +#: builtin/clean.c:876 msgid "add to ignore rules" msgstr "добавяне на ШАБЛОН от файлове, които да не се трият" -#: builtin/clean.c:901 +#: builtin/clean.c:877 msgid "remove ignored files, too" msgstr "изтриване и на игнорираните файлове" -#: builtin/clean.c:903 +#: builtin/clean.c:879 msgid "remove only ignored files" msgstr "изтриване само на игнорирани файлове" -#: builtin/clean.c:921 +#: builtin/clean.c:897 msgid "-x and -X cannot be used together" msgstr "опциите „-x“ и „-X“ са несъвместими" -#: builtin/clean.c:925 +#: builtin/clean.c:901 msgid "" "clean.requireForce set to true and neither -i, -n, nor -f given; refusing to " "clean" @@ -4684,7 +5128,7 @@ msgstr "" "Настройката „clean.requireForce“ е зададена като истина, което изисква някоя " "от опциите „-i“, „-n“ или „-f“. Няма да се извърши изчистване" -#: builtin/clean.c:928 +#: builtin/clean.c:904 msgid "" "clean.requireForce defaults to true and neither -i, -n, nor -f given; " "refusing to clean" @@ -4697,148 +5141,168 @@ msgstr "" msgid "git clone [] [--] []" msgstr "git clone [ОПЦИЯ…] [--] ХРАНИЛИЩЕ [ДИРЕКТОРИЯ]" -#: builtin/clone.c:59 +#: builtin/clone.c:62 msgid "don't create a checkout" msgstr "без създаване на работно дърво" -#: builtin/clone.c:60 builtin/clone.c:62 builtin/init-db.c:469 +#: builtin/clone.c:63 builtin/clone.c:65 builtin/init-db.c:473 msgid "create a bare repository" msgstr "създаване на голо хранилище" -#: builtin/clone.c:64 +#: builtin/clone.c:67 msgid "create a mirror repository (implies bare)" msgstr "" "създаване на хранилище-огледало (включва опцията „--bare“ за голо хранилище)" -#: builtin/clone.c:66 +#: builtin/clone.c:69 msgid "to clone from a local repository" msgstr "клониране от локално хранилище" -#: builtin/clone.c:68 +#: builtin/clone.c:71 msgid "don't use local hardlinks, always copy" msgstr "без твърди връзки, файловете винаги да се копират" -#: builtin/clone.c:70 +#: builtin/clone.c:73 msgid "setup as shared repository" msgstr "настройване за споделено хранилище" -#: builtin/clone.c:72 builtin/clone.c:74 +#: builtin/clone.c:75 builtin/clone.c:77 msgid "initialize submodules in the clone" msgstr "инициализиране на подмодулите при това клониране" -#: builtin/clone.c:75 builtin/init-db.c:466 +#: builtin/clone.c:79 +msgid "number of submodules cloned in parallel" +msgstr "брой подмодули, клонирани паралелно" + +#: builtin/clone.c:80 builtin/init-db.c:470 msgid "template-directory" msgstr "директория с шаблони" -#: builtin/clone.c:76 builtin/init-db.c:467 +#: builtin/clone.c:81 builtin/init-db.c:471 msgid "directory from which templates will be used" msgstr "директория, която съдържа шаблоните, които да се ползват" -#: builtin/clone.c:78 builtin/submodule--helper.c:179 +#: builtin/clone.c:83 builtin/submodule--helper.c:498 +#: builtin/submodule--helper.c:777 msgid "reference repository" msgstr "еталонно хранилище" -#: builtin/clone.c:80 +#: builtin/clone.c:85 msgid "use --reference only while cloning" msgstr "опцията „--reference“ може да се използва само при клониране" -#: builtin/clone.c:81 builtin/column.c:26 builtin/merge-file.c:44 +#: builtin/clone.c:86 builtin/column.c:26 builtin/merge-file.c:44 msgid "name" msgstr "ИМЕ" -#: builtin/clone.c:82 +#: builtin/clone.c:87 msgid "use instead of 'origin' to track upstream" msgstr "използване на това ИМЕ вместо „origin“ при проследяване на клони" -#: builtin/clone.c:84 +#: builtin/clone.c:89 msgid "checkout instead of the remote's HEAD" msgstr "изтегляне на този КЛОН, а не соченият от отдалечения указател „HEAD“" -#: builtin/clone.c:86 +#: builtin/clone.c:91 msgid "path to git-upload-pack on the remote" msgstr "път към командата „git-upload-pack“ на отдалеченото хранилище" -#: builtin/clone.c:87 builtin/fetch.c:113 builtin/grep.c:654 builtin/pull.c:186 +#: builtin/clone.c:92 builtin/fetch.c:117 builtin/grep.c:667 builtin/pull.c:201 msgid "depth" msgstr "ДЪЛБОЧИНА" -#: builtin/clone.c:88 +#: builtin/clone.c:93 msgid "create a shallow clone of that depth" msgstr "плитко клониране до тази ДЪЛБОЧИНА" -#: builtin/clone.c:90 +#: builtin/clone.c:95 msgid "clone only one branch, HEAD or --branch" msgstr "" "клониране само на един клон — или сочения от отдалечения „HEAD“, или изрично " "зададения с „--branch“" -#: builtin/clone.c:91 builtin/init-db.c:475 +#: builtin/clone.c:97 +msgid "any cloned submodules will be shallow" +msgstr "всички клонирани подмодули ще са плитки" + +#: builtin/clone.c:98 builtin/init-db.c:479 msgid "gitdir" msgstr "СЛУЖЕБНА_ДИРЕКТОРИЯ" -#: builtin/clone.c:92 builtin/init-db.c:476 +#: builtin/clone.c:99 builtin/init-db.c:480 msgid "separate git dir from working tree" msgstr "отделна СЛУЖЕБНА_ДИРЕКТОРИЯ за git извън работното дърво" -#: builtin/clone.c:93 +#: builtin/clone.c:100 msgid "key=value" msgstr "КЛЮЧ=СТОЙНОСТ" -#: builtin/clone.c:94 +#: builtin/clone.c:101 msgid "set config inside the new repository" msgstr "задаване на настройките на новото хранилище" -#: builtin/clone.c:300 +#: builtin/clone.c:102 builtin/fetch.c:131 builtin/push.c:536 +msgid "use IPv4 addresses only" +msgstr "само адреси IPv4" + +#: builtin/clone.c:104 builtin/fetch.c:133 builtin/push.c:538 +msgid "use IPv6 addresses only" +msgstr "само адреси IPv6" + +#: builtin/clone.c:241 +msgid "" +"No directory name could be guessed.\n" +"Please specify a directory on the command line" +msgstr "" +"Името на директорията не може да бъде отгатнато.\n" +"Задайте директорията изрично на командния ред" + +#: builtin/clone.c:307 #, c-format msgid "reference repository '%s' as a linked checkout is not supported yet." msgstr "все още не се поддържа еталонно хранилище „%s“ като свързано." -#: builtin/clone.c:302 +#: builtin/clone.c:309 #, c-format msgid "reference repository '%s' is not a local repository." msgstr "еталонното хранилище „%s“ не е локално" -#: builtin/clone.c:307 +#: builtin/clone.c:314 #, c-format msgid "reference repository '%s' is shallow" msgstr "еталонното хранилище „%s“ е плитко" -#: builtin/clone.c:310 +#: builtin/clone.c:317 #, c-format msgid "reference repository '%s' is grafted" msgstr "еталонното хранилище „%s“ е с присаждане" -#: builtin/clone.c:375 builtin/diff.c:84 -#, c-format -msgid "failed to stat '%s'" -msgstr "не може да бъде получена информация чрез „stat“ за „%s“" - -#: builtin/clone.c:377 +#: builtin/clone.c:384 #, c-format msgid "%s exists and is not a directory" msgstr "„%s“ съществува и не е директория" -#: builtin/clone.c:391 +#: builtin/clone.c:398 #, c-format msgid "failed to stat %s\n" msgstr "не може да бъде получена информация чрез „stat“ за „%s“\n" -#: builtin/clone.c:413 +#: builtin/clone.c:420 #, c-format msgid "failed to create link '%s'" msgstr "връзката „%s“ не може да бъде създадена" -#: builtin/clone.c:417 +#: builtin/clone.c:424 #, c-format msgid "failed to copy file to '%s'" msgstr "файлът не може да бъде копиран като „%s“" -#: builtin/clone.c:442 builtin/clone.c:626 +#: builtin/clone.c:449 builtin/clone.c:633 #, c-format msgid "done.\n" msgstr "действието завърши.\n" -#: builtin/clone.c:454 +#: builtin/clone.c:461 msgid "" "Clone succeeded, but checkout failed.\n" "You can inspect what was checked out with 'git status'\n" @@ -4849,7 +5313,7 @@ msgstr "" "клон в момента са изтеглени с командата „git status“. Можете да\n" "завършите изтеглянето на клона с командата „git checkout -f HEAD“.\n" -#: builtin/clone.c:531 +#: builtin/clone.c:538 #, c-format msgid "Could not find remote branch %s to clone." msgstr "" @@ -4857,116 +5321,126 @@ msgstr "" "и който следва да бъде изтеглен, не съществува." # FIXME translator note that the space at end is necesssary -#: builtin/clone.c:621 +#: builtin/clone.c:628 #, c-format msgid "Checking connectivity... " msgstr "Проверка на връзката… " -#: builtin/clone.c:624 +#: builtin/clone.c:631 msgid "remote did not send all necessary objects" msgstr "отдалеченото хранилище не изпрати всички необходими обекти." -#: builtin/clone.c:688 +# FIXME merge with next? +#: builtin/clone.c:649 +#, c-format +msgid "unable to update %s" +msgstr "обектът „%s“ не може да бъде обновен" + +#: builtin/clone.c:698 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n" msgstr "" "указателят „HEAD“ от отдалеченото хранилище сочи към нещо,\n" "което не съществува. Не може да се изтегли определен клон.\n" -#: builtin/clone.c:719 +#: builtin/clone.c:729 msgid "unable to checkout working tree" msgstr "работното дърво не може да бъде подготвено" -#: builtin/clone.c:808 +#: builtin/clone.c:767 +msgid "unable to write parameters to config file" +msgstr "настройките не могат да бъдат записани в конфигурационния файл" + +#: builtin/clone.c:830 msgid "cannot repack to clean up" msgstr "не може да се извърши пакетиране за изчистване на файловете" -#: builtin/clone.c:810 +#: builtin/clone.c:832 msgid "cannot unlink temporary alternates file" msgstr "временният файл за алтернативни обекти не може да бъде изтрит" -#: builtin/clone.c:842 +#: builtin/clone.c:864 builtin/receive-pack.c:1731 msgid "Too many arguments." msgstr "Прекалено много аргументи." -#: builtin/clone.c:846 +#: builtin/clone.c:868 msgid "You must specify a repository to clone." msgstr "Трябва да укажете кое хранилище искате да клонирате." -#: builtin/clone.c:857 +#: builtin/clone.c:879 #, c-format msgid "--bare and --origin %s options are incompatible." msgstr "опциите „--bare“ и „--origin %s“ са несъвместими." -#: builtin/clone.c:860 +#: builtin/clone.c:882 msgid "--bare and --separate-git-dir are incompatible." msgstr "опциите „--bare“ и „--separate-git-dir“ са несъвместими." -#: builtin/clone.c:873 +#: builtin/clone.c:895 #, c-format msgid "repository '%s' does not exist" msgstr "не съществува хранилище „%s“" -#: builtin/clone.c:879 builtin/fetch.c:1166 +#: builtin/clone.c:901 builtin/fetch.c:1174 #, c-format msgid "depth %s is not a positive number" msgstr "дълбочината трябва да е положително цяло число, а не „%s“" -#: builtin/clone.c:889 +#: builtin/clone.c:911 #, c-format msgid "destination path '%s' already exists and is not an empty directory." msgstr "целевият път „%s“ съществува и не е празна директория." -#: builtin/clone.c:899 +#: builtin/clone.c:921 #, c-format msgid "working tree '%s' already exists." msgstr "в „%s“ вече съществува работно дърво." -#: builtin/clone.c:914 builtin/clone.c:925 builtin/submodule--helper.c:224 -#: builtin/worktree.c:221 builtin/worktree.c:248 +#: builtin/clone.c:936 builtin/clone.c:947 builtin/submodule--helper.c:547 +#: builtin/worktree.c:220 builtin/worktree.c:247 #, c-format msgid "could not create leading directories of '%s'" msgstr "родителските директории на „%s“ не могат да бъдат създадени" -#: builtin/clone.c:917 +#: builtin/clone.c:939 #, c-format msgid "could not create work tree dir '%s'" msgstr "работното дърво в „%s“ не може да бъде създадено." -#: builtin/clone.c:935 +#: builtin/clone.c:957 #, c-format msgid "Cloning into bare repository '%s'...\n" msgstr "Клониране и създаване на голо хранилище в „%s“…\n" -#: builtin/clone.c:937 +#: builtin/clone.c:959 #, c-format msgid "Cloning into '%s'...\n" msgstr "Клониране и създаване на хранилище в „%s“…\n" -#: builtin/clone.c:975 +#: builtin/clone.c:998 msgid "--depth is ignored in local clones; use file:// instead." msgstr "" "При локално клониране опцията „--depth“ се игнорира. Ползвайте схемата " "„file://“." -#: builtin/clone.c:978 +#: builtin/clone.c:1001 msgid "source repository is shallow, ignoring --local" msgstr "клонираното хранилище е плитко, затова опцията „--local“ се игнорира" -#: builtin/clone.c:983 +#: builtin/clone.c:1006 msgid "--local is ignored" msgstr "опцията „--local“ се игнорира" -#: builtin/clone.c:987 +#: builtin/clone.c:1010 #, c-format msgid "Don't know how to clone %s" msgstr "Не се поддържа клониране на връзки от вида „%s“ " -#: builtin/clone.c:1036 builtin/clone.c:1044 +#: builtin/clone.c:1059 builtin/clone.c:1067 #, c-format msgid "Remote branch %s not found in upstream %s" msgstr "Отдалеченият клон „%s“ липсва в клонираното хранилище „%s“" -#: builtin/clone.c:1047 +#: builtin/clone.c:1070 msgid "You appear to have cloned an empty repository." msgstr "Изглежда клонирахте празно хранилище." @@ -5110,66 +5584,66 @@ msgstr "" "Чрез командата „git cherry-pick --continue“ ще продължите отбирането на\n" "останалите подавания.\n" -#: builtin/commit.c:305 +#: builtin/commit.c:307 msgid "failed to unpack HEAD tree object" msgstr "върховото дърво (HEAD tree object) не може да бъде извадено от пакет" -#: builtin/commit.c:346 +#: builtin/commit.c:348 msgid "unable to create temporary index" msgstr "временният индекс не може да бъде създаден" -#: builtin/commit.c:352 +#: builtin/commit.c:354 msgid "interactive add failed" msgstr "неуспешно интерактивно добавяне" -#: builtin/commit.c:365 +#: builtin/commit.c:367 msgid "unable to update temporary index" msgstr "временният индекс не може да бъде обновен" -#: builtin/commit.c:367 +#: builtin/commit.c:369 msgid "Failed to update main cache tree" msgstr "Дървото на основния кеш не може да бъде обновено" -#: builtin/commit.c:391 builtin/commit.c:414 builtin/commit.c:463 +#: builtin/commit.c:393 builtin/commit.c:416 builtin/commit.c:465 msgid "unable to write new_index file" msgstr "новият индекс не може да бъде записан" -#: builtin/commit.c:445 +#: builtin/commit.c:447 msgid "cannot do a partial commit during a merge." msgstr "по време на сливане не може да се извърши частично подаване." -#: builtin/commit.c:447 +#: builtin/commit.c:449 msgid "cannot do a partial commit during a cherry-pick." msgstr "по време на отбиране не може да се извърши частично подаване." -#: builtin/commit.c:456 +#: builtin/commit.c:458 msgid "cannot read the index" msgstr "индексът не може да бъде прочетен" -#: builtin/commit.c:475 +#: builtin/commit.c:477 msgid "unable to write temporary index file" msgstr "временният индекс не може да бъде записан" -#: builtin/commit.c:580 +#: builtin/commit.c:582 #, c-format msgid "commit '%s' lacks author header" msgstr "заглавната част за автор в подаването „%s“ липсва" -#: builtin/commit.c:582 +#: builtin/commit.c:584 #, c-format msgid "commit '%s' has malformed author line" msgstr "заглавната част за автор в подаването „%s“ е неправилна" -#: builtin/commit.c:601 +#: builtin/commit.c:603 msgid "malformed --author parameter" msgstr "неправилен параметър към опцията „--author“" -#: builtin/commit.c:609 +#: builtin/commit.c:611 #, c-format msgid "invalid date format: %s" msgstr "неправилен формат на дата: %s" -#: builtin/commit.c:653 +#: builtin/commit.c:655 msgid "" "unable to select a comment character that is not used\n" "in the current commit message" @@ -5177,39 +5651,39 @@ msgstr "" "не може да се избере знак за коментар — в текущото съобщение за подаване са " "използвани всички подобни знаци" -#: builtin/commit.c:690 builtin/commit.c:723 builtin/commit.c:1080 +#: builtin/commit.c:692 builtin/commit.c:725 builtin/commit.c:1091 #, c-format msgid "could not lookup commit %s" msgstr "следното подаване не може да бъде открито: %s" -#: builtin/commit.c:702 builtin/shortlog.c:273 +#: builtin/commit.c:704 builtin/shortlog.c:285 #, c-format msgid "(reading log message from standard input)\n" msgstr "(изчитане на съобщението за подаване от стандартния вход)\n" -#: builtin/commit.c:704 +#: builtin/commit.c:706 msgid "could not read log from standard input" msgstr "съобщението за подаване не бе прочетено стандартния вход" -#: builtin/commit.c:708 +#: builtin/commit.c:710 #, c-format msgid "could not read log file '%s'" msgstr "файлът със съобщението за подаване „%s“ не може да бъде прочетен" -#: builtin/commit.c:730 -msgid "could not read MERGE_MSG" -msgstr "съобщението за сливане MERGE_MSG не може да бъде прочетено" - -#: builtin/commit.c:734 +#: builtin/commit.c:737 builtin/commit.c:745 msgid "could not read SQUASH_MSG" msgstr "съобщението за смачкване SQUASH_MSG не може да бъде прочетено" -#: builtin/commit.c:785 +#: builtin/commit.c:742 +msgid "could not read MERGE_MSG" +msgstr "съобщението за сливане MERGE_MSG не може да бъде прочетено" + +#: builtin/commit.c:796 msgid "could not write commit template" msgstr "шаблонът за подаване не може да бъде запазен" # FIXME -#: builtin/commit.c:803 +#: builtin/commit.c:814 #, c-format msgid "" "\n" @@ -5225,7 +5699,7 @@ msgstr "" "и опитайте отново.\n" # FIXME -#: builtin/commit.c:808 +#: builtin/commit.c:819 #, c-format msgid "" "\n" @@ -5241,7 +5715,7 @@ msgstr "" " %s\n" "и опитайте отново.\n" -#: builtin/commit.c:821 +#: builtin/commit.c:832 #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" @@ -5250,7 +5724,7 @@ msgstr "" "Въведете съобщението за подаване на промените. Редовете, които започват\n" "с „%c“, ще бъдат пропуснати, а празно съобщение преустановява подаването.\n" -#: builtin/commit.c:828 +#: builtin/commit.c:839 #, c-format msgid "" "Please enter the commit message for your changes. Lines starting\n" @@ -5261,96 +5735,96 @@ msgstr "" "с „%c“, също ще бъдат включени — може да ги изтриете вие. Празно \n" "съобщение преустановява подаването.\n" -#: builtin/commit.c:848 +#: builtin/commit.c:859 #, c-format msgid "%sAuthor: %.*s <%.*s>" msgstr "%sАвтор: %.*s <%.*s>" -#: builtin/commit.c:856 +#: builtin/commit.c:867 #, c-format msgid "%sDate: %s" msgstr "%sДата: %s" -#: builtin/commit.c:863 +#: builtin/commit.c:874 #, c-format msgid "%sCommitter: %.*s <%.*s>" msgstr "%sПодаващ: %.*s <%.*s>" -#: builtin/commit.c:881 +#: builtin/commit.c:892 msgid "Cannot read index" msgstr "Индексът не може да бъде прочетен" -#: builtin/commit.c:938 +#: builtin/commit.c:949 msgid "Error building trees" msgstr "Грешка при изграждане на дърветата" -#: builtin/commit.c:953 builtin/tag.c:266 +#: builtin/commit.c:964 builtin/tag.c:266 #, c-format msgid "Please supply the message using either -m or -F option.\n" msgstr "Подайте съобщението с някоя от опциите „-m“ или „-F“.\n" -#: builtin/commit.c:1055 +#: builtin/commit.c:1066 #, c-format msgid "--author '%s' is not 'Name ' and matches no existing author" msgstr "" "Опцията „--author '%s'“ не отговаря на форма̀та „Име <е-поща>“ и не съвпада с " "никой автор" -#: builtin/commit.c:1070 builtin/commit.c:1310 +#: builtin/commit.c:1081 builtin/commit.c:1321 #, c-format msgid "Invalid untracked files mode '%s'" msgstr "Неправилна стойност за неследените файлове: „%s“" -#: builtin/commit.c:1107 +#: builtin/commit.c:1118 msgid "--long and -z are incompatible" msgstr "Опциите „--long“ и „-z“ са несъвместими." -#: builtin/commit.c:1137 +#: builtin/commit.c:1148 msgid "Using both --reset-author and --author does not make sense" msgstr "Опциите „--reset-author“ и „--author“ са несъвместими." -#: builtin/commit.c:1146 +#: builtin/commit.c:1157 msgid "You have nothing to amend." msgstr "Няма какво да бъде поправено." -#: builtin/commit.c:1149 +#: builtin/commit.c:1160 msgid "You are in the middle of a merge -- cannot amend." msgstr "В момента се извършва сливане, не можете да поправяте." -#: builtin/commit.c:1151 +#: builtin/commit.c:1162 msgid "You are in the middle of a cherry-pick -- cannot amend." msgstr "В момента се извършва отбиране на подаване, не можете да поправяте." -#: builtin/commit.c:1154 +#: builtin/commit.c:1165 msgid "Options --squash and --fixup cannot be used together" msgstr "Опциите „--squash“ и „--fixup“ са несъвместими." -#: builtin/commit.c:1164 +#: builtin/commit.c:1175 msgid "Only one of -c/-C/-F/--fixup can be used." msgstr "Опциите „-c“, „-C“, „-F“ и „--fixup““ са несъвместими." -#: builtin/commit.c:1166 +#: builtin/commit.c:1177 msgid "Option -m cannot be combined with -c/-C/-F/--fixup." msgstr "Опцията „-m“ е несъвместима с „-c“, „-C“, „-F“ и „--fixup“." -#: builtin/commit.c:1174 +#: builtin/commit.c:1185 msgid "--reset-author can be used only with -C, -c or --amend." msgstr "" "Опцията „--reset-author“ може да се използва само заедно с „-C“, „-c“ или\n" "„--amend“." -#: builtin/commit.c:1191 +#: builtin/commit.c:1202 msgid "Only one of --include/--only/--all/--interactive/--patch can be used." msgstr "" "Опциите „--include“, „--only“, „--all“, „--interactive“ и „--patch“ са\n" "несъвместими." -#: builtin/commit.c:1193 +#: builtin/commit.c:1204 msgid "No paths with --include/--only does not make sense." msgstr "Опциите „--include“ и „--only“ изискват аргументи." # FIXME bad message -#: builtin/commit.c:1195 +#: builtin/commit.c:1206 msgid "Clever... amending the last one with dirty index." msgstr "" "Чудесно сте се сетили как да поправите съобщението на последното подаване " @@ -5358,271 +5832,269 @@ msgstr "" "променен индекс. Споделете и с друг потребител трика с „git commit --amend -" "o“." -#: builtin/commit.c:1197 +#: builtin/commit.c:1208 msgid "Explicit paths specified without -i or -o; assuming --only paths..." msgstr "" "Зададени са изрични пътища без опциите „-i“ или „-o“. Приема се, че все едно " "сте\n" "ползвали опцията „--only“ с ПЪТища…" -#: builtin/commit.c:1209 builtin/tag.c:475 +#: builtin/commit.c:1220 builtin/tag.c:474 #, c-format msgid "Invalid cleanup mode %s" msgstr "Несъществуващ режим на изчистване „%s“" -#: builtin/commit.c:1214 +#: builtin/commit.c:1225 msgid "Paths with -a does not make sense." msgstr "Опцията „-a“ е несъвместима със задаването на пътища." -#: builtin/commit.c:1324 builtin/commit.c:1605 +#: builtin/commit.c:1335 builtin/commit.c:1621 msgid "show status concisely" msgstr "кратка информация за състоянието" -#: builtin/commit.c:1326 builtin/commit.c:1607 +#: builtin/commit.c:1337 builtin/commit.c:1623 msgid "show branch information" msgstr "информация за клоните" -#: builtin/commit.c:1328 builtin/commit.c:1609 builtin/push.c:544 -#: builtin/worktree.c:423 +#: builtin/commit.c:1339 builtin/commit.c:1625 builtin/push.c:512 +#: builtin/worktree.c:437 msgid "machine-readable output" msgstr "формат на изхода за четене от програма" -#: builtin/commit.c:1331 builtin/commit.c:1611 +#: builtin/commit.c:1342 builtin/commit.c:1627 msgid "show status in long format (default)" msgstr "подробна информация за състоянието (стандартно)" -#: builtin/commit.c:1334 builtin/commit.c:1614 +#: builtin/commit.c:1345 builtin/commit.c:1630 msgid "terminate entries with NUL" msgstr "разделяне на елементите с нулевия знак „NUL“" -#: builtin/commit.c:1336 builtin/commit.c:1617 builtin/fast-export.c:981 +#: builtin/commit.c:1347 builtin/commit.c:1633 builtin/fast-export.c:981 #: builtin/fast-export.c:984 builtin/tag.c:353 msgid "mode" -msgstr "режим" +msgstr "РЕЖИМ" -#: builtin/commit.c:1337 builtin/commit.c:1617 +#: builtin/commit.c:1348 builtin/commit.c:1633 msgid "show untracked files, optional modes: all, normal, no. (Default: all)" msgstr "" -"извеждане на неследените файлове. Възможните режими са „all“ (подробна\n" -"информация), „normal“ (кратка информация), „no“ (без неследените файлове).\n" -"Стандартният режим е: „all“." +"извеждане на неследените файлове. Възможните РЕЖИМи са „all“ (подробна " +"информация), „normal“ (кратка информация), „no“ (без неследените файлове). " +"Стандартният РЕЖИМ е: „all“." -#: builtin/commit.c:1340 +#: builtin/commit.c:1351 msgid "show ignored files" msgstr "извеждане на игнорираните файлове" -#: builtin/commit.c:1341 parse-options.h:155 +#: builtin/commit.c:1352 parse-options.h:155 msgid "when" -msgstr "кога" +msgstr "КОГА" -#: builtin/commit.c:1342 +#: builtin/commit.c:1353 msgid "" "ignore changes to submodules, optional when: all, dirty, untracked. " "(Default: all)" msgstr "" "игнориране на промените в подмодулите. Опция с незадължителна стойност — " -"една от\n" -"„all“ (всички), „dirty“ (тези с неподадени промени), „untracked“ (неследени)" +"една от „all“ (всички), „dirty“ (тези с неподадени промени), " +"„untracked“ (неследени)" -#: builtin/commit.c:1344 +#: builtin/commit.c:1355 msgid "list untracked files in columns" msgstr "извеждане на неследените файлове в колони" -#: builtin/commit.c:1430 +#: builtin/commit.c:1441 msgid "couldn't look up newly created commit" msgstr "току що създаденото подаване не може да бъде открито" -#: builtin/commit.c:1432 +#: builtin/commit.c:1443 msgid "could not parse newly created commit" msgstr "току що създаденото подаване не може да бъде анализирано" -#: builtin/commit.c:1477 +#: builtin/commit.c:1488 msgid "detached HEAD" msgstr "несвързан връх „HEAD“" -#: builtin/commit.c:1480 +#: builtin/commit.c:1491 msgid " (root-commit)" msgstr " (начално подаване)" -#: builtin/commit.c:1575 +#: builtin/commit.c:1591 msgid "suppress summary after successful commit" msgstr "без информация след успешно подаване" -#: builtin/commit.c:1576 +#: builtin/commit.c:1592 msgid "show diff in commit message template" msgstr "добавяне на разликата към шаблона за съобщението при подаване" -#: builtin/commit.c:1578 +#: builtin/commit.c:1594 msgid "Commit message options" msgstr "Опции за съобщението при подаване" -#: builtin/commit.c:1579 builtin/tag.c:351 +#: builtin/commit.c:1595 builtin/tag.c:351 msgid "read message from file" -msgstr "взимане на съобщението от файл" +msgstr "взимане на съобщението от ФАЙЛ" -#: builtin/commit.c:1580 +#: builtin/commit.c:1596 msgid "author" -msgstr "автор" +msgstr "АВТОР" -#: builtin/commit.c:1580 +#: builtin/commit.c:1596 msgid "override author for commit" -msgstr "задаване на автор за подаването" +msgstr "задаване на АВТОР за подаването" -#: builtin/commit.c:1581 builtin/gc.c:326 +#: builtin/commit.c:1597 builtin/gc.c:326 msgid "date" -msgstr "дата" +msgstr "ДАТА" -#: builtin/commit.c:1581 +#: builtin/commit.c:1597 msgid "override date for commit" -msgstr "задаване на дата за подаването" +msgstr "задаване на ДАТА за подаването" -#: builtin/commit.c:1582 builtin/merge.c:218 builtin/notes.c:392 -#: builtin/notes.c:555 builtin/tag.c:349 +#: builtin/commit.c:1598 builtin/merge.c:219 builtin/notes.c:395 +#: builtin/notes.c:558 builtin/tag.c:349 msgid "message" -msgstr "съобщение" +msgstr "СЪОБЩЕНИЕ" -#: builtin/commit.c:1582 +#: builtin/commit.c:1598 msgid "commit message" -msgstr "съобщение при подаване" +msgstr "СЪОБЩЕНИЕ при подаване" -#: builtin/commit.c:1583 builtin/commit.c:1584 builtin/commit.c:1585 -#: builtin/commit.c:1586 parse-options.h:256 ref-filter.h:79 +#: builtin/commit.c:1599 builtin/commit.c:1600 builtin/commit.c:1601 +#: builtin/commit.c:1602 parse-options.h:256 ref-filter.h:79 msgid "commit" -msgstr "подаване" +msgstr "ПОДАВАНЕ" -#: builtin/commit.c:1583 +#: builtin/commit.c:1599 msgid "reuse and edit message from specified commit" -msgstr "преизползване и редактиране на съобщението от указаното подаване" +msgstr "преизползване и редактиране на съобщението от указаното ПОДАВАНЕ" -#: builtin/commit.c:1584 +#: builtin/commit.c:1600 msgid "reuse message from specified commit" -msgstr "преизползване на съобщението от указаното подаване" +msgstr "преизползване на съобщението от указаното ПОДАВАНЕ" -#: builtin/commit.c:1585 +#: builtin/commit.c:1601 msgid "use autosquash formatted message to fixup specified commit" msgstr "" -"използване на автоматичното съобщение при смачкване за вкарване на " -"указаното\n" -"подаване в предното без следа" +"използване на автоматичното съобщение при смачкване за вкарване на указаното " +"ПОДАВАНЕ в предното без следа" -#: builtin/commit.c:1586 +#: builtin/commit.c:1602 msgid "use autosquash formatted message to squash specified commit" msgstr "" "използване на автоматичното съобщение при смачкване за смачкване на " -"указаното\n" -"подаване в предното" +"указаното ПОДАВАНЕ в предното" -#: builtin/commit.c:1587 +#: builtin/commit.c:1603 msgid "the commit is authored by me now (used with -C/-c/--amend)" msgstr "" "смяна на автора да съвпада с подаващия (използва се с „-C“/„-c“/„--amend“)" -#: builtin/commit.c:1588 builtin/log.c:1216 builtin/revert.c:86 +#: builtin/commit.c:1604 builtin/log.c:1382 builtin/revert.c:86 msgid "add Signed-off-by:" msgstr "добавяне на поле за подпис — „Signed-off-by:“" -#: builtin/commit.c:1589 +#: builtin/commit.c:1605 msgid "use specified template file" -msgstr "използване на указания шаблонен файл" +msgstr "използване на указания шаблонен ФАЙЛ" -#: builtin/commit.c:1590 +#: builtin/commit.c:1606 msgid "force edit of commit" msgstr "редактиране на подаване" -#: builtin/commit.c:1591 +#: builtin/commit.c:1607 msgid "default" msgstr "стандартно" -#: builtin/commit.c:1591 builtin/tag.c:354 +#: builtin/commit.c:1607 builtin/tag.c:354 msgid "how to strip spaces and #comments from message" msgstr "кои празни знаци и #коментари да се махат от съобщенията" -#: builtin/commit.c:1592 +#: builtin/commit.c:1608 msgid "include status in commit message template" msgstr "вмъкване на състоянието в шаблона за съобщението при подаване" -#: builtin/commit.c:1594 builtin/merge.c:226 builtin/pull.c:156 +#: builtin/commit.c:1610 builtin/merge.c:229 builtin/pull.c:165 #: builtin/revert.c:93 msgid "GPG sign commit" msgstr "подписване на подаването с GPG" -#: builtin/commit.c:1597 +#: builtin/commit.c:1613 msgid "Commit contents options" msgstr "Опции за избор на файлове при подаване" -#: builtin/commit.c:1598 +#: builtin/commit.c:1614 msgid "commit all changed files" msgstr "подаване на всички променени файлове" -#: builtin/commit.c:1599 +#: builtin/commit.c:1615 msgid "add specified files to index for commit" msgstr "добавяне на указаните файлове към индекса за подаване" -#: builtin/commit.c:1600 +#: builtin/commit.c:1616 msgid "interactively add files" msgstr "интерактивно добавяне на файлове" -#: builtin/commit.c:1601 +#: builtin/commit.c:1617 msgid "interactively add changes" msgstr "интерактивно добавяне на промени" -#: builtin/commit.c:1602 +#: builtin/commit.c:1618 msgid "commit only specified files" msgstr "подаване само на указаните файлове" -#: builtin/commit.c:1603 +#: builtin/commit.c:1619 msgid "bypass pre-commit hook" msgstr "без изпълнение на куката преди подаване (pre-commit)" -#: builtin/commit.c:1604 +#: builtin/commit.c:1620 msgid "show what would be committed" msgstr "отпечатване на това, което би било подадено" -#: builtin/commit.c:1615 +#: builtin/commit.c:1631 msgid "amend previous commit" msgstr "поправяне на предишното подаване" -#: builtin/commit.c:1616 +#: builtin/commit.c:1632 msgid "bypass post-rewrite hook" msgstr "без изпълнение на куката след презаписване (post-rewrite)" -#: builtin/commit.c:1621 +#: builtin/commit.c:1637 msgid "ok to record an empty change" msgstr "позволяване на празни подавания" -#: builtin/commit.c:1623 +#: builtin/commit.c:1639 msgid "ok to record a change with an empty message" msgstr "позволяване на подавания с празни съобщения" -#: builtin/commit.c:1652 +#: builtin/commit.c:1668 msgid "could not parse HEAD commit" msgstr "върховото подаване „HEAD“ не може да бъде прочетено" -#: builtin/commit.c:1698 +#: builtin/commit.c:1718 #, c-format msgid "Corrupt MERGE_HEAD file (%s)" msgstr "Повреден файл за върха за сливането „MERGE_HEAD“ (%s)" -#: builtin/commit.c:1705 +#: builtin/commit.c:1725 msgid "could not read MERGE_MODE" msgstr "режимът на сливане „MERGE_MODE“ не може да бъде прочетен" -#: builtin/commit.c:1724 +#: builtin/commit.c:1744 #, c-format msgid "could not read commit message: %s" msgstr "съобщението за подаване не може да бъде прочетено: %s" -#: builtin/commit.c:1735 +#: builtin/commit.c:1755 #, c-format msgid "Aborting commit; you did not edit the message.\n" msgstr "Неизвършване на подаване поради нередактирано съобщение.\n" -#: builtin/commit.c:1740 +#: builtin/commit.c:1760 #, c-format msgid "Aborting commit due to empty commit message.\n" msgstr "Неизвършване на подаване поради празно съобщение.\n" -#: builtin/commit.c:1788 +#: builtin/commit.c:1808 msgid "" "Repository has been updated, but unable to write\n" "new_index file. Check that disk is not full and quota is\n" @@ -5632,145 +6104,151 @@ msgstr "" "не е записан. Проверете дали дискът не е препълнен или не сте\n" "превишили дисковата си квота. След това изпълнете „git reset HEAD“." -#: builtin/config.c:8 +#: builtin/config.c:9 msgid "git config []" msgstr "git config [ОПЦИЯ…]" -#: builtin/config.c:54 +#: builtin/config.c:56 msgid "Config file location" msgstr "Местоположение на конфигурационния файл" -#: builtin/config.c:55 +#: builtin/config.c:57 msgid "use global config file" msgstr "използване на глобалния конфигурационен файл" -#: builtin/config.c:56 +#: builtin/config.c:58 msgid "use system config file" msgstr "използване на системния конфигурационен файл" -#: builtin/config.c:57 +#: builtin/config.c:59 msgid "use repository config file" msgstr "използване на конфигурационния файл на хранилището" -#: builtin/config.c:58 +#: builtin/config.c:60 msgid "use given config file" -msgstr "използване на зададения конфигурационен файл" +msgstr "използване на зададения конфигурационен ФАЙЛ" -#: builtin/config.c:59 +#: builtin/config.c:61 msgid "blob-id" -msgstr "идентификатор на BLOB" +msgstr "ИДЕНТИФИКАТОР" -#: builtin/config.c:59 +#: builtin/config.c:61 msgid "read config from given blob object" msgstr "" -"изчитане на конфигурацията от BLOB с този идентификатор на съдържанието" +"изчитане на конфигурацията от BLOB с този ИДЕНТИФИКАТОР на съдържанието" -#: builtin/config.c:60 +#: builtin/config.c:62 msgid "Action" msgstr "Действие" -#: builtin/config.c:61 +#: builtin/config.c:63 msgid "get value: name [value-regex]" msgstr "извеждане на стойност: ИМЕ [РЕГУЛЯРЕН_ИЗРАЗ_ЗА_СТОЙНОСТТА]" -#: builtin/config.c:62 +#: builtin/config.c:64 msgid "get all values: key [value-regex]" msgstr "извеждане на всички стойности: ключ [РЕГУЛЯРЕН_ИЗРАЗ_ЗА_СТОЙНОСТТА]" -#: builtin/config.c:63 +#: builtin/config.c:65 msgid "get values for regexp: name-regex [value-regex]" msgstr "" "извеждане на стойностите за РЕГУЛЯРНия_ИЗРАЗ: РЕГУЛЯРЕН_ИЗРАЗ_ЗА_ИМЕТО " "[РЕГУЛЯРЕН_ИЗРАЗ_ЗА_СТОЙНОСТТА]" -#: builtin/config.c:64 +#: builtin/config.c:66 msgid "get value specific for the URL: section[.var] URL" msgstr "извеждане на стойността за указания адрес: РАЗДЕЛ[.ПРОМЕНЛИВА] АДРЕС" -#: builtin/config.c:65 +#: builtin/config.c:67 msgid "replace all matching variables: name value [value_regex]" msgstr "" "замяна на всички съвпадащи променливи: ИМЕ СТОЙНОСТ " "[РЕГУЛЯРЕН_ИЗРАЗ_ЗА_СТОЙНОСТТА]" -#: builtin/config.c:66 +#: builtin/config.c:68 msgid "add a new variable: name value" msgstr "добавяне на нова променлива: ИМЕ СТОЙНОСТ" -#: builtin/config.c:67 +#: builtin/config.c:69 msgid "remove a variable: name [value-regex]" msgstr "изтриване на променлива: ИМЕ [РЕГУЛЯРЕН_ИЗРАЗ_ЗА_СТОЙНОСТТА]" -#: builtin/config.c:68 +#: builtin/config.c:70 msgid "remove all matches: name [value-regex]" msgstr "изтриване на всички съвпадащи: ИМЕ [РЕГУЛЯРЕН_ИЗРАЗ_ЗА_СТОЙНОСТТА]" -#: builtin/config.c:69 +#: builtin/config.c:71 msgid "rename section: old-name new-name" msgstr "преименуване на раздел: СТАРО_ИМЕ НОВО_ИМЕ" -#: builtin/config.c:70 +#: builtin/config.c:72 msgid "remove a section: name" msgstr "изтриване на раздел: ИМЕ" -#: builtin/config.c:71 +#: builtin/config.c:73 msgid "list all" msgstr "изброяване на всички" -#: builtin/config.c:72 +#: builtin/config.c:74 msgid "open an editor" msgstr "отваряне на редактор" -#: builtin/config.c:73 +#: builtin/config.c:75 msgid "find the color configured: slot [default]" msgstr "извеждане на зададения цвят: номер [стандартно]" -#: builtin/config.c:74 +#: builtin/config.c:76 msgid "find the color setting: slot [stdout-is-tty]" msgstr "извеждане на зададения цвят: номер [стандартният изход е терминал]" -#: builtin/config.c:75 +#: builtin/config.c:77 msgid "Type" msgstr "Вид" -#: builtin/config.c:76 +#: builtin/config.c:78 msgid "value is \"true\" or \"false\"" msgstr "СТОЙНОСТТА е „true“ (истина) или „false“ (лъжа)" -#: builtin/config.c:77 +#: builtin/config.c:79 msgid "value is decimal number" msgstr "СТОЙНОСТТА е цяло, десетично число" -#: builtin/config.c:78 +#: builtin/config.c:80 msgid "value is --bool or --int" msgstr "СТОЙНОСТТА е „--bool“ (булева) или „--int“ (десетично цяло число)" -#: builtin/config.c:79 +#: builtin/config.c:81 msgid "value is a path (file or directory name)" msgstr "СТОЙНОСТТА е път (до файл или директория)" -#: builtin/config.c:80 +#: builtin/config.c:82 msgid "Other" msgstr "Други" # FIXME NUL byte to null char, terminate -> razdelitel - da stane ednakvo -#: builtin/config.c:81 +#: builtin/config.c:83 msgid "terminate values with NUL byte" msgstr "разделяне на стойностите с нулевия знак „NUL“" -#: builtin/config.c:82 +#: builtin/config.c:84 msgid "show variable names only" msgstr "извеждане на имената на променливите" -#: builtin/config.c:83 +#: builtin/config.c:85 msgid "respect include directives on lookup" msgstr "при търсене да се уважат и директивите за включване" -#: builtin/config.c:303 +#: builtin/config.c:86 +msgid "show origin of config (file, standard input, blob, command line)" +msgstr "" +"извеждане на мястото на задаване на настройката (файл, стандартен вход, " +"обект BLOB, команден ред)" + +#: builtin/config.c:328 msgid "unable to parse default color value" msgstr "неразпозната стойност на стандартния цвят" -#: builtin/config.c:441 +#: builtin/config.c:472 #, c-format msgid "" "# This is Git's per-user configuration file.\n" @@ -5785,7 +6263,7 @@ msgstr "" "#\tname = %s\n" "#\temail = %s\n" -#: builtin/config.c:575 +#: builtin/config.c:614 #, c-format msgid "cannot create configuration file %s" msgstr "конфигурационният файл „%s“ не може да бъде създаден" @@ -5822,7 +6300,7 @@ msgstr "в анотирания етикет „%s“ липсва вграде msgid "tag '%s' is really '%s' here" msgstr "етикетът „%s“ тук е всъщност „%s“" -#: builtin/describe.c:250 builtin/log.c:459 +#: builtin/describe.c:250 builtin/log.c:465 #, c-format msgid "Not a valid object name %s" msgstr "Неправилно име на обект „%s“" @@ -5918,7 +6396,7 @@ msgstr "да се търси само в този БРОЙ последни ет msgid "only consider tags matching " msgstr "да се търси само измежду етикетите напасващи този ШАБЛОН" -#: builtin/describe.c:410 builtin/name-rev.c:314 +#: builtin/describe.c:410 builtin/name-rev.c:321 msgid "show abbreviated commit object as fallback" msgstr "извеждане на съкратено име на обект като резервен вариант" @@ -5952,21 +6430,21 @@ msgstr "„%s“: не е нито обикновен файл, нито сим msgid "invalid option: %s" msgstr "неправилна опция: %s" -#: builtin/diff.c:358 +#: builtin/diff.c:360 msgid "Not a git repository" msgstr "Не е хранилище на Git" -#: builtin/diff.c:401 +#: builtin/diff.c:403 #, c-format msgid "invalid object '%s' given." msgstr "зададен е неправилен обект „%s“." -#: builtin/diff.c:410 +#: builtin/diff.c:412 #, c-format msgid "more than two blobs given: '%s'" msgstr "зададени са повече от 2 обекта BLOB: „%s“" -#: builtin/diff.c:417 +#: builtin/diff.c:419 #, c-format msgid "unhandled object '%s' given." msgstr "зададен е неподдържан обект „%s“." @@ -5989,11 +6467,11 @@ msgstr "Как да се обработват етикетите на филтр #: builtin/fast-export.c:988 msgid "Dump marks to this file" -msgstr "Запазване на маркерите в този файл" +msgstr "Запазване на маркерите в този ФАЙЛ" #: builtin/fast-export.c:990 msgid "Import marks from this file" -msgstr "Внасяне на маркерите от този файл" +msgstr "Внасяне на маркерите от този ФАЙЛ" #: builtin/fast-export.c:992 msgid "Fake a tagger when tags lack one" @@ -6013,11 +6491,11 @@ msgstr "Без извеждане на съдържанието на обект #: builtin/fast-export.c:998 msgid "refspec" -msgstr "указател на версия" +msgstr "УКАЗАТЕЛ_НА_ВЕРСИЯ" #: builtin/fast-export.c:999 msgid "Apply refspec to exported refs" -msgstr "Прилагане на указателя на версия към изнесените указатели" +msgstr "Прилагане на УКАЗАТЕЛя_НА_ВЕРСИЯ към изнесените указатели" #: builtin/fast-export.c:1000 msgid "anonymize output" @@ -6039,164 +6517,163 @@ msgstr "git fetch --multiple [ОПЦИЯ…] [(ХРАНИЛИЩЕ | ГРУПА) msgid "git fetch --all []" msgstr "git fetch --all [ОПЦИЯ…]" -#: builtin/fetch.c:90 builtin/pull.c:162 +#: builtin/fetch.c:92 builtin/pull.c:174 msgid "fetch from all remotes" msgstr "доставяне от всички отдалечени хранилища" -#: builtin/fetch.c:92 builtin/pull.c:165 +#: builtin/fetch.c:94 builtin/pull.c:177 msgid "append to .git/FETCH_HEAD instead of overwriting" msgstr "добавяне към „.git/FETCH_HEAD“ вместо замяна" -#: builtin/fetch.c:94 builtin/pull.c:168 +#: builtin/fetch.c:96 builtin/pull.c:180 msgid "path to upload pack on remote end" msgstr "отдалечен път, където да се качи пакетът" -#: builtin/fetch.c:95 builtin/pull.c:170 +#: builtin/fetch.c:97 builtin/pull.c:182 msgid "force overwrite of local branch" msgstr "принудително презаписване на локалния клон" -#: builtin/fetch.c:97 +#: builtin/fetch.c:99 msgid "fetch from multiple remotes" msgstr "доставяне от множество отдалечени хранилища" -#: builtin/fetch.c:99 builtin/pull.c:172 +#: builtin/fetch.c:101 builtin/pull.c:184 msgid "fetch all tags and associated objects" msgstr "доставяне на всички етикети и принадлежащи обекти" -#: builtin/fetch.c:101 +#: builtin/fetch.c:103 msgid "do not fetch all tags (--no-tags)" msgstr "без доставянето на всички етикети „--no-tags“" -#: builtin/fetch.c:103 builtin/pull.c:175 +#: builtin/fetch.c:105 +msgid "number of submodules fetched in parallel" +msgstr "брой подмодули доставени паралелно" + +#: builtin/fetch.c:107 builtin/pull.c:187 msgid "prune remote-tracking branches no longer on remote" msgstr "окастряне на клоните следящи вече несъществуващи отдалечени клони" -#: builtin/fetch.c:104 builtin/pull.c:178 +#: builtin/fetch.c:108 builtin/pull.c:190 msgid "on-demand" -msgstr "при нужда" +msgstr "ПРИ НУЖДА" -#: builtin/fetch.c:105 builtin/pull.c:179 +#: builtin/fetch.c:109 builtin/pull.c:191 msgid "control recursive fetching of submodules" msgstr "управление на рекурсивното доставяне на подмодулите" -#: builtin/fetch.c:109 builtin/pull.c:184 +#: builtin/fetch.c:113 builtin/pull.c:199 msgid "keep downloaded pack" msgstr "запазване на изтеглените пакети с обекти" -#: builtin/fetch.c:111 +#: builtin/fetch.c:115 msgid "allow updating of HEAD ref" msgstr "позволяване на обновяването на указателя „HEAD“" -#: builtin/fetch.c:114 builtin/pull.c:187 +#: builtin/fetch.c:118 builtin/pull.c:202 msgid "deepen history of shallow clone" msgstr "задълбочаване на историята на плитко хранилище" -#: builtin/fetch.c:116 builtin/pull.c:190 +#: builtin/fetch.c:120 builtin/pull.c:205 msgid "convert to a complete repository" msgstr "превръщане в пълно хранилище" -#: builtin/fetch.c:118 builtin/log.c:1233 +#: builtin/fetch.c:122 builtin/log.c:1399 msgid "dir" msgstr "директория" -#: builtin/fetch.c:119 +#: builtin/fetch.c:123 msgid "prepend this to submodule path output" msgstr "добавяне на това пред пътя на подмодула" -#: builtin/fetch.c:122 +#: builtin/fetch.c:126 msgid "default mode for recursion" msgstr "стандартен режим на рекурсия" -#: builtin/fetch.c:124 builtin/pull.c:193 +#: builtin/fetch.c:128 builtin/pull.c:208 msgid "accept refs that update .git/shallow" msgstr "приемане на указатели, които обновяват „.git/shallow“" -#: builtin/fetch.c:125 builtin/pull.c:195 +#: builtin/fetch.c:129 builtin/pull.c:210 msgid "refmap" -msgstr "карта с указатели" +msgstr "КАРТА_С_УКАЗАТЕЛИ" -#: builtin/fetch.c:126 builtin/pull.c:196 +#: builtin/fetch.c:130 builtin/pull.c:211 msgid "specify fetch refmap" -msgstr "указване на картата с указатели за доставяне" +msgstr "указване на КАРТАта_С_УКАЗАТЕЛИ за доставяне" -#: builtin/fetch.c:378 +#: builtin/fetch.c:386 msgid "Couldn't find remote ref HEAD" msgstr "Указателят „HEAD“ в отдалеченото хранилище не може да бъде открит" -#: builtin/fetch.c:458 +#: builtin/fetch.c:466 #, c-format msgid "object %s not found" msgstr "обектът „%s“ липсва" -#: builtin/fetch.c:463 +#: builtin/fetch.c:471 msgid "[up to date]" msgstr "[актуализиран]" -#: builtin/fetch.c:477 +#: builtin/fetch.c:485 #, c-format msgid "! %-*s %-*s -> %s (can't fetch in current branch)" msgstr "! %-*s %-*s → %s (в текущия клон не може да се доставя)" -#: builtin/fetch.c:478 builtin/fetch.c:566 +#: builtin/fetch.c:486 builtin/fetch.c:574 msgid "[rejected]" msgstr "[отхвърлен]" -#: builtin/fetch.c:489 +#: builtin/fetch.c:497 msgid "[tag update]" msgstr "[обновяване на етикетите]" -#: builtin/fetch.c:491 builtin/fetch.c:526 builtin/fetch.c:544 +#: builtin/fetch.c:499 builtin/fetch.c:534 builtin/fetch.c:552 msgid " (unable to update local ref)" msgstr " (локалните указатели не могат да бъдат обновени)" -#: builtin/fetch.c:509 +#: builtin/fetch.c:517 msgid "[new tag]" msgstr "[нов етикет]" -#: builtin/fetch.c:512 +#: builtin/fetch.c:520 msgid "[new branch]" msgstr "[нов клон]" -#: builtin/fetch.c:515 +#: builtin/fetch.c:523 msgid "[new ref]" msgstr "[нов указател]" -#: builtin/fetch.c:561 +#: builtin/fetch.c:569 msgid "unable to update local ref" msgstr "локален указател не може да бъде обновен" -#: builtin/fetch.c:561 +#: builtin/fetch.c:569 msgid "forced update" msgstr "принудително обновяване" -#: builtin/fetch.c:568 +#: builtin/fetch.c:576 msgid "(non-fast-forward)" msgstr "(сливането не е тривиално)" -#: builtin/fetch.c:602 builtin/fetch.c:843 -#, c-format -msgid "cannot open %s: %s\n" -msgstr "файлът „%s“ не може да бъде отворен: %s\n" - -#: builtin/fetch.c:611 +#: builtin/fetch.c:619 #, c-format msgid "%s did not send all necessary objects\n" msgstr "хранилището „%s“ не изпрати всички необходими обекти\n" -#: builtin/fetch.c:629 +#: builtin/fetch.c:637 #, c-format msgid "reject %s because shallow roots are not allowed to be updated" msgstr "" "отхвърляне на върха „%s“, защото плитките хранилища не могат да бъдат " "обновявани" -#: builtin/fetch.c:716 builtin/fetch.c:808 +#: builtin/fetch.c:724 builtin/fetch.c:816 #, c-format msgid "From %.*s\n" msgstr "От %.*s\n" # FIXME - is the space necessary -#: builtin/fetch.c:727 +#: builtin/fetch.c:735 #, c-format msgid "" "some local refs could not be updated; try running\n" @@ -6206,55 +6683,55 @@ msgstr "" "„git remote prune %s“, за да премахнете остарелите клони, които\n" "предизвикват конфликта" -#: builtin/fetch.c:779 +#: builtin/fetch.c:787 #, c-format msgid " (%s will become dangling)" msgstr " (обектът „%s“ ще се окаже извън клон)" -#: builtin/fetch.c:780 +#: builtin/fetch.c:788 #, c-format msgid " (%s has become dangling)" msgstr " (обектът „%s“ вече е извън клон)" -#: builtin/fetch.c:812 +#: builtin/fetch.c:820 msgid "[deleted]" msgstr "[изтрит]" -#: builtin/fetch.c:813 builtin/remote.c:1040 +#: builtin/fetch.c:821 builtin/remote.c:1025 msgid "(none)" msgstr "(нищо)" -#: builtin/fetch.c:833 +#: builtin/fetch.c:841 #, c-format msgid "Refusing to fetch into current branch %s of non-bare repository" msgstr "Не може да доставите в текущия клон „%s“ на хранилище, което не е голо" -#: builtin/fetch.c:852 +#: builtin/fetch.c:860 #, c-format msgid "Option \"%s\" value \"%s\" is not valid for %s" msgstr "Стойността „%2$s“ за опцията „%1$s“ не е съвместима с „%3$s“" -#: builtin/fetch.c:855 +#: builtin/fetch.c:863 #, c-format msgid "Option \"%s\" is ignored for %s\n" msgstr "Опцията „%s“ се игнорира при „%s“\n" -#: builtin/fetch.c:911 +#: builtin/fetch.c:920 #, c-format msgid "Don't know how to fetch from %s" msgstr "Не се поддържа доставяне от „%s“" -#: builtin/fetch.c:1072 +#: builtin/fetch.c:1080 #, c-format msgid "Fetching %s\n" msgstr "Доставяне на „%s“\n" -#: builtin/fetch.c:1074 builtin/remote.c:96 +#: builtin/fetch.c:1082 builtin/remote.c:96 #, c-format msgid "Could not fetch %s" msgstr "„%s“ не може да се достави" -#: builtin/fetch.c:1092 +#: builtin/fetch.c:1100 msgid "" "No remote repository specified. Please, specify either a URL or a\n" "remote name from which new revisions should be fetched." @@ -6262,33 +6739,33 @@ msgstr "" "Не сте указали отдалечено хранилище. Задайте или адрес, или име\n" "на отдалечено хранилище, откъдето да се доставят новите версии." -#: builtin/fetch.c:1115 +#: builtin/fetch.c:1123 msgid "You need to specify a tag name." msgstr "Трябва да укажете име на етикет." -#: builtin/fetch.c:1157 +#: builtin/fetch.c:1165 msgid "--depth and --unshallow cannot be used together" msgstr "опциите „--depth“ и „--unshallow“ са несъвместими" -#: builtin/fetch.c:1159 +#: builtin/fetch.c:1167 msgid "--unshallow on a complete repository does not make sense" msgstr "не можете да използвате опцията „--unshallow“ върху пълно хранилище" -#: builtin/fetch.c:1179 +#: builtin/fetch.c:1187 msgid "fetch --all does not take a repository argument" msgstr "към „git fetch --all“ не можете да добавите аргумент — хранилище" -#: builtin/fetch.c:1181 +#: builtin/fetch.c:1189 msgid "fetch --all does not make sense with refspecs" msgstr "" "към „git fetch --all“ не можете да добавите аргумент — указател на версия" -#: builtin/fetch.c:1192 +#: builtin/fetch.c:1200 #, c-format msgid "No such remote or remote group: %s" msgstr "Няма нито отдалечено хранилище, нито група от хранилища на име „%s“" -#: builtin/fetch.c:1200 +#: builtin/fetch.c:1208 msgid "Fetching a group and specifying refspecs does not make sense" msgstr "Указването на група и указването на версия са несъвместими" @@ -6362,7 +6839,7 @@ msgstr "ФОРМАТ за изхода" #: builtin/for-each-ref.c:41 msgid "print only refs which points at the given object" -msgstr "извеждане само на указателите, сочещи към обекта" +msgstr "извеждане само на указателите, сочещи към ОБЕКТА" #: builtin/for-each-ref.c:43 msgid "print only refs that are merged" @@ -6374,7 +6851,7 @@ msgstr "извеждане само на неслетите указатели" #: builtin/for-each-ref.c:45 msgid "print only refs which contain the commit" -msgstr "извеждане само на указателите, които съдържат това подаване" +msgstr "извеждане само на указателите, които съдържат това ПОДАВАНЕ" #: builtin/fsck.c:156 builtin/prune.c:140 msgid "Checking connectivity" @@ -6384,56 +6861,56 @@ msgstr "Проверка на връзката" msgid "Checking object directories" msgstr "Проверка на директориите с обекти" -#: builtin/fsck.c:553 +#: builtin/fsck.c:552 msgid "git fsck [] [...]" msgstr "git fsck [ОПЦИЯ…] [ОБЕКТ…]" -#: builtin/fsck.c:559 +#: builtin/fsck.c:558 msgid "show unreachable objects" msgstr "показване на недостижимите обекти" -#: builtin/fsck.c:560 +#: builtin/fsck.c:559 msgid "show dangling objects" msgstr "показване на обектите извън клоните" -#: builtin/fsck.c:561 +#: builtin/fsck.c:560 msgid "report tags" msgstr "показване на етикетите" -#: builtin/fsck.c:562 +#: builtin/fsck.c:561 msgid "report root nodes" msgstr "показване на кореновите възли" -#: builtin/fsck.c:563 +#: builtin/fsck.c:562 msgid "make index objects head nodes" msgstr "задаване на обекти от индекса да са коренови" # FIXME bad message -#: builtin/fsck.c:564 +#: builtin/fsck.c:563 msgid "make reflogs head nodes (default)" msgstr "проследяване на указателите от журнала като глави (стандартно)" -#: builtin/fsck.c:565 +#: builtin/fsck.c:564 msgid "also consider packs and alternate objects" msgstr "допълнително да се проверяват пакетите и алтернативните обекти" -#: builtin/fsck.c:566 +#: builtin/fsck.c:565 msgid "check only connectivity" msgstr "проверка само на връзката" -#: builtin/fsck.c:567 +#: builtin/fsck.c:566 msgid "enable more strict checking" msgstr "по-строги проверки" -#: builtin/fsck.c:569 +#: builtin/fsck.c:568 msgid "write dangling objects in .git/lost-found" msgstr "запазване на обектите извън клоните в директорията „.git/lost-found“" -#: builtin/fsck.c:570 builtin/prune.c:107 +#: builtin/fsck.c:569 builtin/prune.c:107 msgid "show progress" msgstr "показване на напредъка" -#: builtin/fsck.c:631 +#: builtin/fsck.c:630 msgid "Checking objects" msgstr "Проверка на обектите" @@ -6527,239 +7004,253 @@ msgstr "" msgid "git grep [] [-e] [...] [[--] ...]" msgstr "git grep [ОПЦИЯ…] [-e] ШАБЛОН [ВЕРСИЯ…] [[--] ПЪТ…]" -#: builtin/grep.c:218 +#: builtin/grep.c:219 #, c-format msgid "grep: failed to create thread: %s" msgstr "grep: неуспешно създаване на нишка: %s" -#: builtin/grep.c:441 builtin/grep.c:476 +#: builtin/grep.c:277 +#, c-format +msgid "invalid number of threads specified (%d) for %s" +msgstr "зададен е неправилен брой нишки (%d) за %s" + +#: builtin/grep.c:452 builtin/grep.c:487 #, c-format msgid "unable to read tree (%s)" msgstr "дървото не може да бъде прочетено (%s)" -#: builtin/grep.c:491 +#: builtin/grep.c:502 #, c-format msgid "unable to grep from object of type %s" msgstr "не може да се изпълни „grep“ от обект от вида %s" -#: builtin/grep.c:547 +#: builtin/grep.c:560 #, c-format msgid "switch `%c' expects a numerical value" msgstr "опцията „%c“ очаква число за аргумент" -#: builtin/grep.c:564 +#: builtin/grep.c:577 #, c-format msgid "cannot open '%s'" msgstr "„%s“ не може да бъде отворен" -#: builtin/grep.c:633 +#: builtin/grep.c:646 msgid "search in index instead of in the work tree" msgstr "търсене в индекса, а не в работното дърво" -#: builtin/grep.c:635 +#: builtin/grep.c:648 msgid "find in contents not managed by git" msgstr "търсене и във файловете, които не са под управлението на git" -#: builtin/grep.c:637 +#: builtin/grep.c:650 msgid "search in both tracked and untracked files" msgstr "търсене и в следените, и в неследените файлове" -#: builtin/grep.c:639 +#: builtin/grep.c:652 msgid "ignore files specified via '.gitignore'" msgstr "игнориране на файловете указани в „.gitignore“" -#: builtin/grep.c:642 +#: builtin/grep.c:655 msgid "show non-matching lines" msgstr "извеждане на редовете, които не съвпадат" -#: builtin/grep.c:644 +#: builtin/grep.c:657 msgid "case insensitive matching" msgstr "без значение на регистъра на буквите (главни/малки)" -#: builtin/grep.c:646 +#: builtin/grep.c:659 msgid "match patterns only at word boundaries" msgstr "напасване на шаблоните само по границите на думите" -#: builtin/grep.c:648 +#: builtin/grep.c:661 msgid "process binary files as text" msgstr "обработване на двоичните файлове като текстови" -#: builtin/grep.c:650 +#: builtin/grep.c:663 msgid "don't match patterns in binary files" msgstr "прескачане на двоичните файлове" -#: builtin/grep.c:653 +#: builtin/grep.c:666 msgid "process binary files with textconv filters" msgstr "" "обработване на двоичните файлове чрез филтри за преобразуване към текст" -#: builtin/grep.c:655 +#: builtin/grep.c:668 msgid "descend at most levels" msgstr "навлизане максимално на тази ДЪЛБОЧИНА в дървото" -#: builtin/grep.c:659 +#: builtin/grep.c:672 msgid "use extended POSIX regular expressions" msgstr "разширени регулярни изрази по POSIX" -#: builtin/grep.c:662 +#: builtin/grep.c:675 msgid "use basic POSIX regular expressions (default)" msgstr "основни регулярни изрази по POSIX (стандартно)" -#: builtin/grep.c:665 +#: builtin/grep.c:678 msgid "interpret patterns as fixed strings" msgstr "шаблоните са дословни низове" -#: builtin/grep.c:668 +#: builtin/grep.c:681 msgid "use Perl-compatible regular expressions" msgstr "регулярни изрази на Perl" -#: builtin/grep.c:671 +#: builtin/grep.c:684 msgid "show line numbers" msgstr "извеждане на номерата на редовете" -#: builtin/grep.c:672 +#: builtin/grep.c:685 msgid "don't show filenames" msgstr "без извеждане на имената на файловете" -#: builtin/grep.c:673 +#: builtin/grep.c:686 msgid "show filenames" msgstr "извеждане на имената на файловете" -#: builtin/grep.c:675 +#: builtin/grep.c:688 msgid "show filenames relative to top directory" msgstr "" "извеждане на относителните имена на файловете спрямо основната директория на " "хранилището" -#: builtin/grep.c:677 +#: builtin/grep.c:690 msgid "show only filenames instead of matching lines" msgstr "извеждане само на имената на файловете без напасващите редове" -#: builtin/grep.c:679 +#: builtin/grep.c:692 msgid "synonym for --files-with-matches" msgstr "синоним на „--files-with-matches“" -#: builtin/grep.c:682 +#: builtin/grep.c:695 msgid "show only the names of files without match" msgstr "" "извеждане само на имената на файловете, които не съдържат ред, напасващ на " "шаблона" -#: builtin/grep.c:684 +#: builtin/grep.c:697 msgid "print NUL after filenames" msgstr "извеждане на нулевия знак „NUL“ след всяко име на файл" -#: builtin/grep.c:686 +#: builtin/grep.c:699 msgid "show the number of matches instead of matching lines" msgstr "извеждане на броя на съвпаденията вместо напасващите редове" -#: builtin/grep.c:687 +#: builtin/grep.c:700 msgid "highlight matches" msgstr "оцветяване на напасванията" -#: builtin/grep.c:689 +#: builtin/grep.c:702 msgid "print empty line between matches from different files" msgstr "извеждане на празен ред между напасванията от различни файлове" -#: builtin/grep.c:691 +#: builtin/grep.c:704 msgid "show filename only once above matches from same file" msgstr "" "извеждане на името на файла само веднъж за всички напасвания от този файл" -#: builtin/grep.c:694 +#: builtin/grep.c:707 msgid "show context lines before and after matches" msgstr "извеждане на такъв БРОЙ редове преди и след напасванията" -#: builtin/grep.c:697 +#: builtin/grep.c:710 msgid "show context lines before matches" msgstr "извеждане на такъв БРОЙ редове преди напасванията" -#: builtin/grep.c:699 +#: builtin/grep.c:712 msgid "show context lines after matches" msgstr "извеждане на такъв БРОЙ редове след напасванията" -#: builtin/grep.c:700 +#: builtin/grep.c:714 +msgid "use worker threads" +msgstr "използване на такъв БРОЙ работещи нишки" + +#: builtin/grep.c:715 msgid "shortcut for -C NUM" msgstr "синоним на „-C БРОЙ“" -#: builtin/grep.c:703 +#: builtin/grep.c:718 msgid "show a line with the function name before matches" msgstr "извеждане на ред с името на функцията, в която е напаснат шаблона" -#: builtin/grep.c:705 +#: builtin/grep.c:720 msgid "show the surrounding function" msgstr "извеждане на обхващащата функция" -#: builtin/grep.c:708 +#: builtin/grep.c:723 msgid "read patterns from file" -msgstr "изчитане на шаблоните от файл" +msgstr "изчитане на шаблоните от ФАЙЛ" -#: builtin/grep.c:710 +#: builtin/grep.c:725 msgid "match " msgstr "напасване на ШАБЛОН" -#: builtin/grep.c:712 +#: builtin/grep.c:727 msgid "combine patterns specified with -e" msgstr "комбиниране на шаблоните указани с опцията „-e“" -#: builtin/grep.c:724 +#: builtin/grep.c:739 msgid "indicate hit with exit status without output" msgstr "" "без извеждане на стандартния изход. Изходният код указва наличието на " "напасване" -#: builtin/grep.c:726 +#: builtin/grep.c:741 msgid "show only matches from files that match all patterns" msgstr "" "извеждане на редове само от файловете, които напасват на всички шаблони" -#: builtin/grep.c:728 +#: builtin/grep.c:743 msgid "show parse tree for grep expression" msgstr "извеждане на дървото за анализ на регулярния израз" -#: builtin/grep.c:732 +#: builtin/grep.c:747 msgid "pager" msgstr "програма за преглед по страници" -#: builtin/grep.c:732 +#: builtin/grep.c:747 msgid "show matching files in the pager" msgstr "извеждане на съвпадащите файлове в програма за преглед по страници" -#: builtin/grep.c:735 +#: builtin/grep.c:750 msgid "allow calling of grep(1) (ignored by this build)" msgstr "" "позволяване на стартирането на grep(1) (текущият компилат пренебрегва тази " "опция)" -#: builtin/grep.c:793 +#: builtin/grep.c:813 msgid "no pattern given." msgstr "липсва шаблон." -#: builtin/grep.c:851 +#: builtin/grep.c:845 builtin/index-pack.c:1477 +#, c-format +msgid "invalid number of threads specified (%d)" +msgstr "зададен е неправилен брой нишки: %d" + +#: builtin/grep.c:875 msgid "--open-files-in-pager only works on the worktree" msgstr "" "опцията „--open-files-in-pager“ е съвместима само с търсене в работното дърво" -#: builtin/grep.c:877 +#: builtin/grep.c:901 msgid "--cached or --untracked cannot be used with --no-index." msgstr "опциите „--cached“ и „--untracked“ са несъвместими с „--no-index“." -#: builtin/grep.c:882 +#: builtin/grep.c:906 msgid "--no-index or --untracked cannot be used with revs." msgstr "" "опциите „--cached“ и „--untracked“ са несъвместими с търсене във версии." -#: builtin/grep.c:885 +#: builtin/grep.c:909 msgid "--[no-]exclude-standard cannot be used for tracked contents." msgstr "" "опциите „--(no-)exclude-standard“ са несъвместими с търсене по следени " "файлове." -#: builtin/grep.c:893 +#: builtin/grep.c:917 msgid "both --cached and trees are given." msgstr "опцията „--cached“ е несъвместима със задаване на дърво." -#: builtin/hash-object.c:80 +#: builtin/hash-object.c:81 msgid "" "git hash-object [-t ] [-w] [--path= | --no-filters] [--stdin] " "[--] ..." @@ -6767,40 +7258,40 @@ msgstr "" "git hash-object [-t ВИД] [-w] [--path=ФАЙЛ | --no-filters] [--stdin] [--] " "ФАЙЛ…" -#: builtin/hash-object.c:81 +#: builtin/hash-object.c:82 msgid "git hash-object --stdin-paths" msgstr "git hash-object --stdin-paths" -#: builtin/hash-object.c:92 +#: builtin/hash-object.c:93 msgid "type" msgstr "ВИД" -#: builtin/hash-object.c:92 +#: builtin/hash-object.c:93 msgid "object type" -msgstr "вид на обекта" +msgstr "ВИД на обекта" -#: builtin/hash-object.c:93 +#: builtin/hash-object.c:94 msgid "write the object into the object database" msgstr "записване на обекта в базата от данни за обектите" -#: builtin/hash-object.c:95 +#: builtin/hash-object.c:96 msgid "read the object from stdin" msgstr "изчитане на обекта от стандартния вход" -#: builtin/hash-object.c:97 +#: builtin/hash-object.c:98 msgid "store file as is without filters" msgstr "запазване на файла както е — без филтри" -#: builtin/hash-object.c:98 +#: builtin/hash-object.c:99 msgid "" "just hash any random garbage to create corrupt objects for debugging Git" msgstr "" "създаване и хеширане на произволни данни за повредени обекти за трасиране на " "Git" -#: builtin/hash-object.c:99 +#: builtin/hash-object.c:100 msgid "process file as it were from this path" -msgstr "обработване на файла все едно е с този път" +msgstr "обработване на ФАЙЛа все едно е с този път" #: builtin/help.c:41 msgid "print all available commands" @@ -6846,10 +7337,10 @@ msgstr "Прекалено стара версия на „emacsclient“ — %d #: builtin/help.c:130 builtin/help.c:151 builtin/help.c:160 builtin/help.c:168 #, c-format -msgid "failed to exec '%s': %s" -msgstr "неуспешно изпълнение на „%s“: %s" +msgid "failed to exec '%s'" +msgstr "неуспешно изпълнение на „%s“" -#: builtin/help.c:208 +#: builtin/help.c:205 #, c-format msgid "" "'%s': path for unsupported man viewer.\n" @@ -6858,7 +7349,7 @@ msgstr "" "„%s“: път към неподдържана програма за преглед на\n" " ръководството. Вместо нея пробвайте „man..cmd“." -#: builtin/help.c:220 +#: builtin/help.c:217 #, c-format msgid "" "'%s': cmd for supported man viewer.\n" @@ -6867,63 +7358,63 @@ msgstr "" "„%s“: команда за поддържана програма за преглед на\n" " ръководството. Вместо нея пробвайте „man..path“." -#: builtin/help.c:337 +#: builtin/help.c:334 #, c-format msgid "'%s': unknown man viewer." msgstr "„%s“: непозната програма за преглед на ръководството." -#: builtin/help.c:354 +#: builtin/help.c:351 msgid "no man viewer handled the request" msgstr "никоя програма за преглед на ръководство не успя да обработи заявката" -#: builtin/help.c:362 +#: builtin/help.c:359 msgid "no info viewer handled the request" msgstr "" "никоя програма за преглед на информационните страници не успя да обработи " "заявката" -#: builtin/help.c:411 +#: builtin/help.c:408 msgid "Defining attributes per path" msgstr "Указване на атрибути към път" -#: builtin/help.c:412 +#: builtin/help.c:409 msgid "Everyday Git With 20 Commands Or So" msgstr "Ежедневието в Git в рамките на 20-ина команди" -#: builtin/help.c:413 +#: builtin/help.c:410 msgid "A Git glossary" msgstr "Речник с термините на Git" -#: builtin/help.c:414 +#: builtin/help.c:411 msgid "Specifies intentionally untracked files to ignore" msgstr "Указване на неследени файлове, които да бъдат нарочно пренебрегвани" -#: builtin/help.c:415 +#: builtin/help.c:412 msgid "Defining submodule properties" msgstr "Дефиниране на свойствата на подмодулите" -#: builtin/help.c:416 +#: builtin/help.c:413 msgid "Specifying revisions and ranges for Git" msgstr "Указване на версии и интервали в Git" -#: builtin/help.c:417 +#: builtin/help.c:414 msgid "A tutorial introduction to Git (for version 1.5.1 or newer)" msgstr "Въвеждащ урок за Git (версии поне 1.5.1)" -#: builtin/help.c:418 +#: builtin/help.c:415 msgid "An overview of recommended workflows with Git" msgstr "Общ преглед на препоръчваните начини за работа с Git" -#: builtin/help.c:430 +#: builtin/help.c:427 msgid "The common Git guides are:\n" msgstr "Популярните пътеводители в Git са:\n" -#: builtin/help.c:451 builtin/help.c:468 +#: builtin/help.c:448 builtin/help.c:465 #, c-format msgid "usage: %s%s" msgstr "употреба: %s%s" -#: builtin/help.c:484 +#: builtin/help.c:481 #, c-format msgid "`git %s' is aliased to `%s'" msgstr "„git %s“ е синоним на „%s“" @@ -7119,118 +7610,115 @@ msgstr "" #: builtin/index-pack.c:1253 #, c-format -msgid "completed with %d local objects" -msgstr "действието завърши с %d локални обекта" +msgid "completed with %d local object" +msgid_plural "completed with %d local objects" +msgstr[0] "действието завърши с %d локален обект" +msgstr[1] "действието завърши с %d локални обекта" -#: builtin/index-pack.c:1263 +#: builtin/index-pack.c:1265 #, c-format msgid "Unexpected tail checksum for %s (disk corruption?)" msgstr "" "Неочаквана последваща сума за грешки за „%s“ (причината може да е грешка в " "диска)" -#: builtin/index-pack.c:1267 +#: builtin/index-pack.c:1269 #, c-format msgid "pack has %d unresolved delta" msgid_plural "pack has %d unresolved deltas" msgstr[0] "в пакета има %d ненапасваща разлика" msgstr[1] "в пакета има %d ненапасващи разлики" -#: builtin/index-pack.c:1291 +#: builtin/index-pack.c:1293 #, c-format msgid "unable to deflate appended object (%d)" msgstr "добавеният обект не може да се компресира с „deflate“: %d" -#: builtin/index-pack.c:1367 +#: builtin/index-pack.c:1369 #, c-format msgid "local object %s is corrupt" msgstr "локалният обект „%s“ е повреден" -#: builtin/index-pack.c:1391 +#: builtin/index-pack.c:1393 msgid "error while closing pack file" msgstr "грешка при затварянето на пакетния файл" -#: builtin/index-pack.c:1404 +#: builtin/index-pack.c:1406 #, c-format msgid "cannot write keep file '%s'" msgstr "" "грешка при записването на файла „%s“, осигуряващ запазване на директория" -#: builtin/index-pack.c:1412 +#: builtin/index-pack.c:1414 #, c-format msgid "cannot close written keep file '%s'" msgstr "" "грешка при затварянето на записания файл „%s“, осигуряващ запазване на " "директория" -#: builtin/index-pack.c:1425 +#: builtin/index-pack.c:1427 msgid "cannot store pack file" msgstr "пакетният файл не може да бъде запазен" -#: builtin/index-pack.c:1436 +#: builtin/index-pack.c:1438 msgid "cannot store index file" msgstr "файлът за индекса не може да бъде съхранен" -#: builtin/index-pack.c:1469 +#: builtin/index-pack.c:1471 #, c-format msgid "bad pack.indexversion=%" msgstr "зададена е неправилна версия пакетиране: „pack.indexversion=%“" -#: builtin/index-pack.c:1475 -#, c-format -msgid "invalid number of threads specified (%d)" -msgstr "зададен е неправилен брой нишки: %d" - -#: builtin/index-pack.c:1479 builtin/index-pack.c:1663 +#: builtin/index-pack.c:1481 builtin/index-pack.c:1678 #, c-format msgid "no threads support, ignoring %s" msgstr "липсва поддръжка за нишки. „%s“ ще се пренебрегне" -#: builtin/index-pack.c:1537 +#: builtin/index-pack.c:1540 #, c-format msgid "Cannot open existing pack file '%s'" msgstr "Съществуващият пакетен файл „%s“ не може да бъде отворен" -#: builtin/index-pack.c:1539 +#: builtin/index-pack.c:1542 #, c-format msgid "Cannot open existing pack idx file for '%s'" msgstr "Съществуващият индекс за пакетния файл „%s“ не може да бъде отворен" -#: builtin/index-pack.c:1586 +#: builtin/index-pack.c:1589 #, c-format msgid "non delta: %d object" msgid_plural "non delta: %d objects" msgstr[0] "%d обект не е разлика" msgstr[1] "%d обекта не са разлика" -#: builtin/index-pack.c:1593 +#: builtin/index-pack.c:1596 #, c-format msgid "chain length = %d: %lu object" msgid_plural "chain length = %d: %lu objects" msgstr[0] "дължината на веригата е %d: %lu обект" msgstr[1] "дължината на веригата е %d: %lu обекта" +#: builtin/index-pack.c:1609 +#, c-format +msgid "packfile name '%s' does not end with '.pack'" +msgstr "името на пакетния файл „%s“ не завършва на „.pack“" + # FIXME it is not the cwd it is the previous cwd -#: builtin/index-pack.c:1623 +#: builtin/index-pack.c:1638 msgid "Cannot come back to cwd" msgstr "Процесът не може да се върне към предишната работна директория" -#: builtin/index-pack.c:1675 builtin/index-pack.c:1678 -#: builtin/index-pack.c:1690 builtin/index-pack.c:1694 +#: builtin/index-pack.c:1690 builtin/index-pack.c:1693 +#: builtin/index-pack.c:1705 builtin/index-pack.c:1709 #, c-format msgid "bad %s" msgstr "неправилна стойност „%s“" -#: builtin/index-pack.c:1708 +#: builtin/index-pack.c:1723 msgid "--fix-thin cannot be used without --stdin" msgstr "опцията „--fix-thin“ изисква „--stdin“" -#: builtin/index-pack.c:1712 builtin/index-pack.c:1721 -#, c-format -msgid "packfile name '%s' does not end with '.pack'" -msgstr "името на пакетния файл „%s“ не завършва на „.pack“" - -#: builtin/index-pack.c:1729 +#: builtin/index-pack.c:1731 msgid "--verify with no packfile name given" msgstr "опцията „--verify“ изисква име на пакетен файл" @@ -7269,28 +7757,27 @@ msgstr "„%s“ не може да се копира в „%s“" msgid "ignoring template %s" msgstr "игнориране на шаблона „%s“" -#: builtin/init-db.c:118 +#: builtin/init-db.c:120 #, c-format msgid "templates not found %s" msgstr "директорията с шаблоните не е открита: „%s“" -#: builtin/init-db.c:131 +#: builtin/init-db.c:135 #, c-format -msgid "not copying templates of a wrong format version %d from '%s'" -msgstr "" -"шаблоните с неправилен номер на форма̀та %d няма да бъдат копирани от „%s“" +msgid "not copying templates from '%s': %s" +msgstr "шаблоните няма да бъдат копирани от „%s“: „%s“" -#: builtin/init-db.c:309 builtin/init-db.c:312 +#: builtin/init-db.c:312 builtin/init-db.c:315 #, c-format msgid "%s already exists" msgstr "Директорията „%s“ вече съществува" -#: builtin/init-db.c:340 +#: builtin/init-db.c:344 #, c-format msgid "unable to handle file type %d" msgstr "файлове от вид %d не се поддържат" -#: builtin/init-db.c:343 +#: builtin/init-db.c:347 #, c-format msgid "unable to move %s to %s" msgstr "„%s“ не може да се премести в „%s“" @@ -7298,24 +7785,24 @@ msgstr "„%s“ не може да се премести в „%s“" #. TRANSLATORS: The first '%s' is either "Reinitialized #. existing" or "Initialized empty", the second " shared" or #. "", and the last '%s%s' is the verbatim directory name. -#: builtin/init-db.c:399 +#: builtin/init-db.c:403 #, c-format msgid "%s%s Git repository in %s%s\n" msgstr "%s%s хранилище на Git в „%s%s“\n" -#: builtin/init-db.c:400 +#: builtin/init-db.c:404 msgid "Reinitialized existing" msgstr "Наново инициализирано, съществуващо" -#: builtin/init-db.c:400 +#: builtin/init-db.c:404 msgid "Initialized empty" msgstr "Инициализирано празно" -#: builtin/init-db.c:401 +#: builtin/init-db.c:405 msgid " shared" msgstr ", споделено" -#: builtin/init-db.c:448 +#: builtin/init-db.c:452 msgid "" "git init [-q | --quiet] [--bare] [--template=] [--" "shared[=]] []" @@ -7323,27 +7810,27 @@ msgstr "" "git init [-q | --quiet] [--bare] [--template=ДИРЕКТОРИЯ_С_ШАБЛОНИ] [--" "shared[=ПРАВА]] [ДИРЕКТОРИЯ]" -#: builtin/init-db.c:471 +#: builtin/init-db.c:475 msgid "permissions" msgstr "права" -#: builtin/init-db.c:472 +#: builtin/init-db.c:476 msgid "specify that the git repository is to be shared amongst several users" msgstr "" "указване, че хранилището на Git ще бъде споделено от повече от един " "потребител" -#: builtin/init-db.c:506 builtin/init-db.c:511 +#: builtin/init-db.c:510 builtin/init-db.c:515 #, c-format msgid "cannot mkdir %s" msgstr "директорията „%s“ не може да бъде създадена" -#: builtin/init-db.c:515 +#: builtin/init-db.c:519 #, c-format msgid "cannot chdir to %s" msgstr "не може да се влезе в директорията „%s“" -#: builtin/init-db.c:536 +#: builtin/init-db.c:540 #, c-format msgid "" "%s (or --work-tree=) not allowed without specifying %s (or --git-" @@ -7352,31 +7839,39 @@ msgstr "" "%s (или --work-tree=ДИРЕКТОРИЯ) изисква указването на %s (или --git-" "dir=ДИРЕКТОРИЯ)" -#: builtin/init-db.c:564 +#: builtin/init-db.c:568 #, c-format msgid "Cannot access work tree '%s'" msgstr "Работното дърво в „%s“ е недостъпно" #: builtin/interpret-trailers.c:15 msgid "" -"git interpret-trailers [--trim-empty] [(--trailer [(=|:)])...] " -"[...]" +"git interpret-trailers [--in-place] [--trim-empty] [(--trailer " +"[(=|:)])...] [...]" msgstr "" -"git interpret-trailers [--trim-empty] [(--trailer ЛЕКСЕМА[(=|:)СТОЙНОСТ])…] " -"[ФАЙЛ…]" +"git interpret-trailers [--in-place] [--trim-empty] [(--trailer " +"ЛЕКСЕМА[(=|:)СТОЙНОСТ])…] [ФАЙЛ…]" + +#: builtin/interpret-trailers.c:26 +msgid "edit files in place" +msgstr "директно редактиране на файловете" -#: builtin/interpret-trailers.c:25 +#: builtin/interpret-trailers.c:27 msgid "trim empty trailers" msgstr "изчистване на празните епилози" -#: builtin/interpret-trailers.c:26 +#: builtin/interpret-trailers.c:28 msgid "trailer" msgstr "епилог" -#: builtin/interpret-trailers.c:27 +#: builtin/interpret-trailers.c:29 msgid "trailer(s) to add" msgstr "епилог(зи) за добавяне" +#: builtin/interpret-trailers.c:42 +msgid "no input file given for in-place editing" +msgstr "не е зададен входен файл за редактиране на място" + #: builtin/log.c:43 msgid "git log [] [] [[--] ...]" msgstr "git log [ОПЦИЯ…] [ДИАПАЗОН_НА_ВЕРСИИТЕ] [[--] ПЪТ…]" @@ -7390,277 +7885,327 @@ msgstr "git show [ОПЦИЯ…] ОБЕКТ…" msgid "invalid --decorate option: %s" msgstr "неправилна опция „--decorate“: %s" -#: builtin/log.c:131 +#: builtin/log.c:137 msgid "suppress diff output" msgstr "без извеждане на разликите" -#: builtin/log.c:132 +#: builtin/log.c:138 msgid "show source" msgstr "извеждане на изходния код" -#: builtin/log.c:133 +#: builtin/log.c:139 msgid "Use mail map file" msgstr "" "Използване на файл за съответствията на имената и адресите на е-поща („." "mailmap“)" -#: builtin/log.c:134 +#: builtin/log.c:140 msgid "decorate options" msgstr "настройки на форма̀та на извежданата информация" -#: builtin/log.c:137 +#: builtin/log.c:143 msgid "Process line range n,m in file, counting from 1" msgstr "" "Обработване само на редовете във файла в интервала от n до m включително. " "Броенето започва от 1" -#: builtin/log.c:233 +#: builtin/log.c:239 #, c-format msgid "Final output: %d %s\n" msgstr "Резултат: %d %s\n" -#: builtin/log.c:465 +#: builtin/log.c:471 #, c-format msgid "git show %s: bad file" msgstr "git show %s: повреден файл" -#: builtin/log.c:479 builtin/log.c:572 +#: builtin/log.c:485 builtin/log.c:578 #, c-format msgid "Could not read object %s" msgstr "Обектът не може да бъде прочетен: %s" -#: builtin/log.c:596 +#: builtin/log.c:602 #, c-format msgid "Unknown type: %d" msgstr "Неизвестен вид: %d" -#: builtin/log.c:714 +#: builtin/log.c:722 msgid "format.headers without value" msgstr "не е зададена стойност на „format.headers“" -#: builtin/log.c:798 +#: builtin/log.c:812 msgid "name of output directory is too long" msgstr "прекалено дълго име на директорията за изходната информация" -#: builtin/log.c:813 +#: builtin/log.c:827 #, c-format msgid "Cannot open patch file %s" msgstr "Файлът-кръпка „%s“ не може да бъде отворен" -#: builtin/log.c:827 +#: builtin/log.c:841 msgid "Need exactly one range." msgstr "Трябва да зададете точно един диапазон." -#: builtin/log.c:837 +#: builtin/log.c:851 msgid "Not a range." msgstr "Не е диапазон." -#: builtin/log.c:943 +#: builtin/log.c:957 msgid "Cover letter needs email format" msgstr "Придружаващото писмо трябва да е форматирано като е-писмо" # FIXME bad wording insanely -#: builtin/log.c:1022 +#: builtin/log.c:1036 #, c-format msgid "insane in-reply-to: %s" msgstr "неправилен формат на заглавната част за отговор „in-reply-to“: %s" -#: builtin/log.c:1050 +#: builtin/log.c:1064 msgid "git format-patch [] [ | ]" msgstr "git format-patch [ОПЦИЯ…] [ОТ | ДИАПАЗОН_НА_ВЕРСИИТЕ]" -# FIXME message WTF why ask it -#: builtin/log.c:1095 +#: builtin/log.c:1109 msgid "Two output directories?" msgstr "Можете да укажете максимум една директория за изход." -#: builtin/log.c:1211 +#: builtin/log.c:1216 builtin/log.c:1857 builtin/log.c:1859 builtin/log.c:1871 +#, c-format +msgid "Unknown commit %s" +msgstr "Непознато подаване „%s“" + +#: builtin/log.c:1226 builtin/notes.c:253 builtin/notes.c:304 +#: builtin/notes.c:306 builtin/notes.c:369 builtin/notes.c:424 +#: builtin/notes.c:510 builtin/notes.c:515 builtin/notes.c:593 +#: builtin/notes.c:656 builtin/notes.c:881 builtin/tag.c:455 +#, c-format +msgid "Failed to resolve '%s' as a valid ref." +msgstr "Не може да се открие към какво сочи „%s“." + +#: builtin/log.c:1231 +msgid "Could not find exact merge base." +msgstr "Точната база за сливане не може да се открие." + +#: builtin/log.c:1235 +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" +"зададете, използвайте „git branch --set-upstream-to“.\n" +"Можете ръчно да зададете базово подаване чрез „--base=“." + +#: builtin/log.c:1255 +msgid "Failed to find exact merge base" +msgstr "Точната база при сливане не може да бъде открита" + +#: builtin/log.c:1266 +msgid "base commit should be the ancestor of revision list" +msgstr "базовото подаване трябва да е предшественикът на списъка с версиите" + +#: builtin/log.c:1270 +msgid "base commit shouldn't be in revision list" +msgstr "базовото подаване не може да е в списъка с версиите" + +#: builtin/log.c:1319 +msgid "cannot get patch id" +msgstr "идентификаторът на кръпката не може да бъде получен" + +#: builtin/log.c:1377 msgid "use [PATCH n/m] even with a single patch" msgstr "номерация „[PATCH n/m]“ дори и при единствена кръпка" -#: builtin/log.c:1214 +#: builtin/log.c:1380 msgid "use [PATCH] even with multiple patches" msgstr "номерация „[PATCH]“ дори и при множество кръпки" -#: builtin/log.c:1218 +#: builtin/log.c:1384 msgid "print patches to standard out" msgstr "извеждане на кръпките на стандартния изход" -#: builtin/log.c:1220 +#: builtin/log.c:1386 msgid "generate a cover letter" msgstr "създаване на придружаващо писмо" -#: builtin/log.c:1222 +#: builtin/log.c:1388 msgid "use simple number sequence for output file names" msgstr "проста числова последователност за имената на файловете-кръпки" -#: builtin/log.c:1223 +#: builtin/log.c:1389 msgid "sfx" msgstr "ЗНАЦИ" -#: builtin/log.c:1224 +#: builtin/log.c:1390 msgid "use instead of '.patch'" msgstr "използване на тези ЗНАЦИ за суфикс вместо „.patch“" -#: builtin/log.c:1226 +#: builtin/log.c:1392 msgid "start numbering patches at instead of 1" msgstr "номерирането на кръпките да започва от този БРОЙ, а не с 1" -#: builtin/log.c:1228 +#: builtin/log.c:1394 msgid "mark the series as Nth re-roll" msgstr "отбелязване, че това е N-тата поредна редакция на поредицата от кръпки" -#: builtin/log.c:1230 +#: builtin/log.c:1396 msgid "Use [] instead of [PATCH]" msgstr "Използване на този „[ПРЕФИКС]“ вместо „[PATCH]“" -#: builtin/log.c:1233 +#: builtin/log.c:1399 msgid "store resulting files in " msgstr "запазване на изходните файлове в тази ДИРЕКТОРИЯ" -#: builtin/log.c:1236 +#: builtin/log.c:1402 msgid "don't strip/add [PATCH]" msgstr "без добавяне/махане на префикса „[PATCH]“" -#: builtin/log.c:1239 +#: builtin/log.c:1405 msgid "don't output binary diffs" msgstr "без извеждане на разлики между двоични файлове" -#: builtin/log.c:1241 +#: builtin/log.c:1407 msgid "output all-zero hash in From header" msgstr "в заглавната част „From:“ (от) хешът да е само от нули" -#: builtin/log.c:1243 +#: builtin/log.c:1409 msgid "don't include a patch matching a commit upstream" msgstr "да не се включват кръпки, които присъстват в следения клон" -#: builtin/log.c:1245 +#: builtin/log.c:1411 msgid "show patch format instead of default (patch + stat)" msgstr "" "извеждане във формат за кръпки, а на в стандартния (кръпка и статистика)" -#: builtin/log.c:1247 +#: builtin/log.c:1413 msgid "Messaging" msgstr "Опции при изпращане" -#: builtin/log.c:1248 +#: builtin/log.c:1414 msgid "header" msgstr "ЗАГЛАВНА_ЧАСТ" -#: builtin/log.c:1249 +#: builtin/log.c:1415 msgid "add email header" msgstr "добавяне на тази ЗАГЛАВНА_ЧАСТ" -#: builtin/log.c:1250 builtin/log.c:1252 +#: builtin/log.c:1416 builtin/log.c:1418 msgid "email" msgstr "Е-ПОЩА" -#: builtin/log.c:1250 +#: builtin/log.c:1416 msgid "add To: header" msgstr "добавяне на заглавна част „To:“ (до)" -#: builtin/log.c:1252 +#: builtin/log.c:1418 msgid "add Cc: header" msgstr "добавяне на заглавна част „Cc:“ (и до)" -#: builtin/log.c:1254 +#: builtin/log.c:1420 msgid "ident" msgstr "ИДЕНТИЧНОСТ" -#: builtin/log.c:1255 +#: builtin/log.c:1421 msgid "set From address to (or committer ident if absent)" msgstr "" "задаване на адреса в заглавната част „From“ (от) да е тази ИДЕНТИЧНОСТ. Ако " "не е зададена такава, се взима адреса на подаващия" -#: builtin/log.c:1257 +#: builtin/log.c:1423 msgid "message-id" msgstr "ИДЕНТИФИКАТОР_НА_СЪОБЩЕНИЕ" -#: builtin/log.c:1258 +#: builtin/log.c:1424 msgid "make first mail a reply to " msgstr "" "първото съобщение да е в отговор на е-писмото с този " "ИДЕНТИФИКАТОР_НА_СЪОБЩЕНИЕ" -#: builtin/log.c:1259 builtin/log.c:1262 +#: builtin/log.c:1425 builtin/log.c:1428 msgid "boundary" msgstr "граница" -#: builtin/log.c:1260 +#: builtin/log.c:1426 msgid "attach the patch" msgstr "прикрепяне на кръпката" -#: builtin/log.c:1263 +#: builtin/log.c:1429 msgid "inline the patch" msgstr "включване на кръпката в текста на писмата" -#: builtin/log.c:1267 +#: builtin/log.c:1433 msgid "enable message threading, styles: shallow, deep" msgstr "" -"използване на нишки за съобщенията. Стилът е „shallow“ (плитък) или " +"използване на нишки за съобщенията. СТИЛът е „shallow“ (плитък) или " "„deep“ (дълбок)" -#: builtin/log.c:1269 +#: builtin/log.c:1435 msgid "signature" msgstr "подпис" -#: builtin/log.c:1270 +#: builtin/log.c:1436 msgid "add a signature" msgstr "добавяне на поле за подпис" -#: builtin/log.c:1272 +#: builtin/log.c:1437 +msgid "base-commit" +msgstr "БАЗОВО_ПОДАВАНЕ" + +#: builtin/log.c:1438 +msgid "add prerequisite tree info to the patch series" +msgstr "добавяне на необходимото БАЗово дърво към серията кръпки" + +#: builtin/log.c:1440 msgid "add a signature from a file" msgstr "добавяне на подпис от файл" -#: builtin/log.c:1273 +#: builtin/log.c:1441 msgid "don't print the patch filenames" msgstr "без извеждане на имената на кръпките" -#: builtin/log.c:1362 +#: builtin/log.c:1531 msgid "-n and -k are mutually exclusive." msgstr "опциите „-n“ и „-k“ са несъвместими." -#: builtin/log.c:1364 +#: builtin/log.c:1533 msgid "--subject-prefix and -k are mutually exclusive." msgstr "опциите „--subject-prefix“ и „-k“ са несъвместими." -#: builtin/log.c:1372 +#: builtin/log.c:1541 msgid "--name-only does not make sense" msgstr "опцията „--name-only“ е несъвместима с генерирането на кръпки" -#: builtin/log.c:1374 +#: builtin/log.c:1543 msgid "--name-status does not make sense" msgstr "опцията „--name-status“ е несъвместима с генерирането на кръпки" -#: builtin/log.c:1376 +#: builtin/log.c:1545 msgid "--check does not make sense" msgstr "опцията „--check“ е несъвместима с генерирането на кръпки" -#: builtin/log.c:1401 +#: builtin/log.c:1573 msgid "standard output, or directory, which one?" msgstr "" "изходът може да или стандартният, или да е в директория, но не и двете." -#: builtin/log.c:1403 +#: builtin/log.c:1575 #, c-format msgid "Could not create directory '%s'" msgstr "Директорията „%s“ не може да бъде създадена" -#: builtin/log.c:1500 +#: builtin/log.c:1672 #, c-format msgid "unable to read signature file '%s'" msgstr "файлът „%s“ с подпис не може да бъде прочетен" -#: builtin/log.c:1563 +#: builtin/log.c:1743 msgid "Failed to create output files" msgstr "Изходните файлове не могат да бъдат създадени" -#: builtin/log.c:1611 +#: builtin/log.c:1792 msgid "git cherry [-v] [ [ []]]" msgstr "git cherry [-v] [ОТДАЛЕЧЕН_КЛОН [ВРЪХ [ПРЕДЕЛ]]]" -#: builtin/log.c:1665 +#: builtin/log.c:1846 #, c-format msgid "" "Could not find a tracked remote branch, please specify manually.\n" @@ -7668,106 +8213,151 @@ msgstr "" "Следеният отдалечен клон не бе открит, затова изрично задайте " "ОТДАЛЕЧЕН_КЛОН.\n" -#: builtin/log.c:1676 builtin/log.c:1678 builtin/log.c:1690 -#, c-format -msgid "Unknown commit %s" -msgstr "Непознато подаване „%s“" - -#: builtin/ls-files.c:358 +#: builtin/ls-files.c:378 msgid "git ls-files [] [...]" msgstr "git ls-files [ОПЦИЯ…] [ФАЙЛ…]" -#: builtin/ls-files.c:415 +#: builtin/ls-files.c:427 msgid "identify the file status with tags" msgstr "извеждане на състоянието на файловете с еднобуквени флагове" -#: builtin/ls-files.c:417 +#: builtin/ls-files.c:429 msgid "use lowercase letters for 'assume unchanged' files" msgstr "малки букви за файловете, които да се счетат за непроменени" -#: builtin/ls-files.c:419 +#: builtin/ls-files.c:431 msgid "show cached files in the output (default)" msgstr "извеждане на кешираните файлове (стандартно)" -#: builtin/ls-files.c:421 +#: builtin/ls-files.c:433 msgid "show deleted files in the output" msgstr "извеждане на изтритите файлове" -#: builtin/ls-files.c:423 +#: builtin/ls-files.c:435 msgid "show modified files in the output" msgstr "извеждане на променените файлове" -#: builtin/ls-files.c:425 +#: builtin/ls-files.c:437 msgid "show other files in the output" msgstr "извеждане на другите файлове" -#: builtin/ls-files.c:427 +#: builtin/ls-files.c:439 msgid "show ignored files in the output" msgstr "извеждане на игнорираните файлове" -#: builtin/ls-files.c:430 +#: builtin/ls-files.c:442 msgid "show staged contents' object name in the output" msgstr "извеждане на името на обекта за съдържанието на индекса" -#: builtin/ls-files.c:432 +#: builtin/ls-files.c:444 msgid "show files on the filesystem that need to be removed" msgstr "извеждане на файловете, които трябва да бъдат изтрити" -#: builtin/ls-files.c:434 +#: builtin/ls-files.c:446 msgid "show 'other' directories' names only" msgstr "извеждане само на името на другите (неследените) директории" -#: builtin/ls-files.c:437 +#: builtin/ls-files.c:448 +msgid "show line endings of files" +msgstr "извеждане на знаците за край на ред във файловете" + +#: builtin/ls-files.c:450 msgid "don't show empty directories" msgstr "без извеждане на празните директории" -#: builtin/ls-files.c:440 +#: builtin/ls-files.c:453 msgid "show unmerged files in the output" msgstr "извеждане на неслетите файлове" # FIXME not clear about what this option does -#: builtin/ls-files.c:442 +#: builtin/ls-files.c:455 msgid "show resolve-undo information" msgstr "извеждане на информацията за отмяна на разрешените подавания" -#: builtin/ls-files.c:444 +#: builtin/ls-files.c:457 msgid "skip files matching pattern" msgstr "прескачане на файловете напасващи ШАБЛОНа" -#: builtin/ls-files.c:447 +#: builtin/ls-files.c:460 msgid "exclude patterns are read from " msgstr "шаблоните за игнориране да се прочетат от този ФАЙЛ" -#: builtin/ls-files.c:450 +#: builtin/ls-files.c:463 msgid "read additional per-directory exclude patterns in " msgstr "" "изчитане на допълнителните шаблони за игнориране по директория от този ФАЙЛ" -#: builtin/ls-files.c:452 +#: builtin/ls-files.c:465 msgid "add the standard git exclusions" msgstr "добавяне на стандартно игнорираните от Git файлове" -#: builtin/ls-files.c:455 +#: builtin/ls-files.c:468 msgid "make the output relative to the project top directory" msgstr "пътищата да са относителни спрямо основната директория на проекта" -#: builtin/ls-files.c:458 +#: builtin/ls-files.c:471 msgid "if any is not in the index, treat this as an error" msgstr "грешка, ако някой от тези ФАЙЛове не е в индекса" -#: builtin/ls-files.c:459 +#: builtin/ls-files.c:472 msgid "tree-ish" msgstr "УКАЗАТЕЛ_КЪМ_ДЪРВО" -#: builtin/ls-files.c:460 +#: builtin/ls-files.c:473 msgid "pretend that paths removed since are still present" msgstr "" "считане, че пътищата изтрити след УКАЗАТЕЛя_КЪМ_ДЪРВО все още съществуват" -#: builtin/ls-files.c:462 +#: builtin/ls-files.c:475 msgid "show debugging data" msgstr "извеждане на информацията за изчистване на грешки" +#: builtin/ls-remote.c:7 +msgid "" +"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=]\n" +" [-q | --quiet] [--exit-code] [--get-url]\n" +" [--symref] [ [...]]" +msgstr "" +"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=КОМАНДА]\n" +" [-q | --quiet] [--exit-code] [--get-url]\n" +" [--symref] [ХРАНИЛИЩЕ [УКАЗАТЕЛ…]]" + +#: builtin/ls-remote.c:50 +msgid "do not print remote URL" +msgstr "без извеждане на адресите на отдалечените хранилища" + +#: builtin/ls-remote.c:51 builtin/ls-remote.c:53 +msgid "exec" +msgstr "КОМАНДА" + +#: builtin/ls-remote.c:52 builtin/ls-remote.c:54 +msgid "path of git-upload-pack on the remote host" +msgstr "път към командата „git-upload-pack“ на отдалечената машина" + +#: builtin/ls-remote.c:56 +msgid "limit to tags" +msgstr "само етикетите" + +#: builtin/ls-remote.c:57 +msgid "limit to heads" +msgstr "само върховете" + +#: builtin/ls-remote.c:58 +msgid "do not show peeled tags" +msgstr "без извеждане на проследените етикети" + +#: builtin/ls-remote.c:60 +msgid "take url..insteadOf into account" +msgstr "взимане предвид на „url.БАЗА.insteadOf“" + +#: builtin/ls-remote.c:62 +msgid "exit with exit code 2 if no matching refs are found" +msgstr "изход с код 2, ако не се открият съвпадащи указатели" + +#: builtin/ls-remote.c:64 +msgid "show underlying ref in addition to the object pointed by it" +msgstr "извеждане на указателя заедно с обекта сочен от него" + #: builtin/ls-tree.c:28 msgid "git ls-tree [] [...]" msgstr "git ls-tree [ОПЦИЯ…] УКАЗАТЕЛ_КЪМ_ДЪРВО [ПЪТ…]" @@ -7819,175 +8409,179 @@ msgid "git merge --abort" msgstr "git merge --abort" # FIXME -m rather than just m -#: builtin/merge.c:100 +#: builtin/merge.c:101 msgid "switch `m' requires a value" msgstr "опцията „-m“ изисква стойност" -#: builtin/merge.c:137 +#: builtin/merge.c:138 #, c-format msgid "Could not find merge strategy '%s'.\n" msgstr "Няма такава стратегия за сливане: „%s“.\n" -#: builtin/merge.c:138 +#: builtin/merge.c:139 #, c-format msgid "Available strategies are:" msgstr "Наличните стратегии са:" -#: builtin/merge.c:143 +#: builtin/merge.c:144 #, c-format msgid "Available custom strategies are:" msgstr "Допълнителните стратегии са:" -#: builtin/merge.c:193 builtin/pull.c:119 +#: builtin/merge.c:194 builtin/pull.c:126 msgid "do not show a diffstat at the end of the merge" msgstr "без извеждане на статистиката след завършване на сливане" -#: builtin/merge.c:196 builtin/pull.c:122 +#: builtin/merge.c:197 builtin/pull.c:129 msgid "show a diffstat at the end of the merge" msgstr "извеждане на статистиката след завършване на сливане" -#: builtin/merge.c:197 builtin/pull.c:125 +#: builtin/merge.c:198 builtin/pull.c:132 msgid "(synonym to --stat)" msgstr "(синоним на „--stat“)" -#: builtin/merge.c:199 builtin/pull.c:128 +#: builtin/merge.c:200 builtin/pull.c:135 msgid "add (at most ) entries from shortlog to merge commit message" msgstr "" "добавяне (на максимум такъв БРОЙ) записи от съкратения журнал в съобщението " "за подаване" -#: builtin/merge.c:202 builtin/pull.c:131 +#: builtin/merge.c:203 builtin/pull.c:138 msgid "create a single commit instead of doing a merge" msgstr "създаване на едно подаване вместо извършване на сливане" -#: builtin/merge.c:204 builtin/pull.c:134 +#: builtin/merge.c:205 builtin/pull.c:141 msgid "perform a commit if the merge succeeds (default)" msgstr "извършване на подаване при успешно сливане (стандартно действие)" -#: builtin/merge.c:206 builtin/pull.c:137 +#: builtin/merge.c:207 builtin/pull.c:144 msgid "edit message before committing" msgstr "редактиране на съобщението преди подаване" -#: builtin/merge.c:207 +#: builtin/merge.c:208 msgid "allow fast-forward (default)" msgstr "позволяване на тривиално сливане (стандартно действие)" -#: builtin/merge.c:209 builtin/pull.c:143 +#: builtin/merge.c:210 builtin/pull.c:150 msgid "abort if fast-forward is not possible" msgstr "преустановяване, ако сливането не е тривиално" -#: builtin/merge.c:213 +#: builtin/merge.c:214 msgid "Verify that the named commit has a valid GPG signature" msgstr "Проверка, че именуваното подаване е с правилен подпис на GPG" -#: builtin/merge.c:214 builtin/notes.c:767 builtin/pull.c:148 +#: builtin/merge.c:215 builtin/notes.c:771 builtin/pull.c:157 #: builtin/revert.c:89 msgid "strategy" -msgstr "стратегия" +msgstr "СТРАТЕГИЯ" -#: builtin/merge.c:215 builtin/pull.c:149 +#: builtin/merge.c:216 builtin/pull.c:158 msgid "merge strategy to use" -msgstr "стратегия за сливане, която да се ползва" +msgstr "СТРАТЕГИЯ за сливане, която да се ползва" -#: builtin/merge.c:216 builtin/pull.c:152 +#: builtin/merge.c:217 builtin/pull.c:161 msgid "option=value" -msgstr "опция=стойност" +msgstr "ОПЦИЯ=СТОЙНОСТ" -#: builtin/merge.c:217 builtin/pull.c:153 +#: builtin/merge.c:218 builtin/pull.c:162 msgid "option for selected merge strategy" -msgstr "опция за избраната стратегия за сливане" +msgstr "ОПЦИЯ за избраната стратегия за сливане" -#: builtin/merge.c:219 +#: builtin/merge.c:220 msgid "merge commit message (for a non-fast-forward merge)" -msgstr "съобщение при подаването със сливане (при нетривиални сливания)" +msgstr "СЪОБЩЕНИЕ при подаването със сливане (при нетривиални сливания)" -#: builtin/merge.c:223 +#: builtin/merge.c:224 msgid "abort the current in-progress merge" msgstr "преустановяване на текущото сливане" -#: builtin/merge.c:251 +#: builtin/merge.c:226 builtin/pull.c:169 +msgid "allow merging unrelated histories" +msgstr "позволяване на сливане на независими истории" + +#: builtin/merge.c:254 msgid "could not run stash." msgstr "не може да се извърши скатаване" -#: builtin/merge.c:256 +#: builtin/merge.c:259 msgid "stash failed" msgstr "неуспешно скатаване" -#: builtin/merge.c:261 +#: builtin/merge.c:264 #, c-format msgid "not a valid object: %s" msgstr "неправилен обект: „%s“" -#: builtin/merge.c:280 builtin/merge.c:297 +#: builtin/merge.c:283 builtin/merge.c:300 msgid "read-tree failed" msgstr "неуспешно прочитане на обект-дърво" -#: builtin/merge.c:327 +#: builtin/merge.c:330 msgid " (nothing to squash)" msgstr " (няма какво да се смачка)" -#: builtin/merge.c:340 +#: builtin/merge.c:343 #, c-format msgid "Squash commit -- not updating HEAD\n" msgstr "Подаване със смачкване — указателят „HEAD“ няма да бъде обновен\n" -#: builtin/merge.c:344 builtin/merge.c:763 builtin/merge.c:975 -#: builtin/merge.c:988 +#: builtin/merge.c:347 builtin/merge.c:767 builtin/merge.c:987 +#: builtin/merge.c:1000 #, c-format msgid "Could not write to '%s'" msgstr "„%s“ не може да бъде записан" -#: builtin/merge.c:372 +#: builtin/merge.c:375 msgid "Writing SQUASH_MSG" msgstr "Записване на съобщението за смачкване SQUASH_MSG" -#: builtin/merge.c:374 +#: builtin/merge.c:377 msgid "Finishing SQUASH_MSG" msgstr "Завършване на съобщението за смачкване SQUASH_MSG" -#: builtin/merge.c:397 +#: builtin/merge.c:400 #, c-format msgid "No merge message -- not updating HEAD\n" msgstr "" "Липсва съобщение при подаване — указателят „HEAD“ няма да бъде обновен\n" -#: builtin/merge.c:447 +#: builtin/merge.c:451 #, c-format msgid "'%s' does not point to a commit" msgstr "„%s“ не сочи към подаване" -#: builtin/merge.c:537 +#: builtin/merge.c:541 #, c-format msgid "Bad branch.%s.mergeoptions string: %s" msgstr "Неправилен низ за настройката „branch.%s.mergeoptions“: „%s“" -#: builtin/merge.c:656 +#: builtin/merge.c:660 msgid "Not handling anything other than two heads merge." msgstr "Поддържа се само сливане на точно две истории." -#: builtin/merge.c:670 +#: builtin/merge.c:674 #, c-format msgid "Unknown option for merge-recursive: -X%s" msgstr "Непозната опция за рекурсивното сливане „merge-recursive“: „-X%s“" -#: builtin/merge.c:683 +#: builtin/merge.c:687 #, c-format msgid "unable to write %s" msgstr "„%s“ не може да бъде записан" -#: builtin/merge.c:772 +#: builtin/merge.c:776 #, c-format msgid "Could not read from '%s'" msgstr "От „%s“ не може да се чете" -#: builtin/merge.c:781 +#: builtin/merge.c:785 #, c-format msgid "Not committing merge; use 'git commit' to complete the merge.\n" msgstr "" "Сливането няма да бъде подадено. За завършването му и подаването му " "използвайте командата „git commit“.\n" -#: builtin/merge.c:787 +#: builtin/merge.c:791 #, c-format msgid "" "Please enter a commit message to explain why this merge is necessary,\n" @@ -8002,55 +8596,55 @@ msgstr "" "Редовете, които започват с „%c“ ще бъдат пропуснати, а празно съобщение\n" "преустановява подаването.\n" -#: builtin/merge.c:811 +#: builtin/merge.c:815 msgid "Empty commit message." msgstr "Празно съобщение при подаване." # FIXME - WTF is wonderful. -#: builtin/merge.c:823 +#: builtin/merge.c:835 #, c-format msgid "Wonderful.\n" msgstr "Първият етап на тривиалното сливане завърши.\n" -#: builtin/merge.c:878 +#: builtin/merge.c:890 #, c-format msgid "Automatic merge failed; fix conflicts and then commit the result.\n" msgstr "Неуспешно сливане — коригирайте конфликтите и подайте резултата.\n" -#: builtin/merge.c:894 +#: builtin/merge.c:906 #, c-format msgid "'%s' is not a commit" msgstr "„%s“ не е подаване" -#: builtin/merge.c:935 +#: builtin/merge.c:947 msgid "No current branch." msgstr "Няма текущ клон." -#: builtin/merge.c:937 +#: builtin/merge.c:949 msgid "No remote for the current branch." msgstr "Текущият клон не следи никой." -#: builtin/merge.c:939 +#: builtin/merge.c:951 msgid "No default upstream defined for the current branch." msgstr "Текущият клон не следи никой клон." -#: builtin/merge.c:944 +#: builtin/merge.c:956 #, c-format msgid "No remote-tracking branch for %s from %s" msgstr "Никой клон не следи клона „%s“ от хранилището „%s“" -#: builtin/merge.c:1079 +#: builtin/merge.c:1091 #, c-format msgid "could not close '%s'" msgstr "„%s“ не може да се затвори" -#: builtin/merge.c:1206 +#: builtin/merge.c:1219 msgid "There is no merge to abort (MERGE_HEAD missing)." msgstr "" "Не може да преустановите сливане, защото в момента не се извършва такова " "(липсва указател „MERGE_HEAD“)." -#: builtin/merge.c:1222 +#: builtin/merge.c:1235 msgid "" "You have not concluded your merge (MERGE_HEAD exists).\n" "Please, commit your changes before you merge." @@ -8058,7 +8652,7 @@ msgstr "" "Не сте завършили сливане. (Указателят „MERGE_HEAD“ съществува).\n" "Подайте промените си, преди да започнете ново сливане." -#: builtin/merge.c:1229 +#: builtin/merge.c:1242 msgid "" "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n" "Please, commit your changes before you merge." @@ -8066,111 +8660,115 @@ msgstr "" "Не сте завършили отбиране на подаване (указателят „CHERRY_PICK_HEAD“\n" "съществува). Подайте промените си, преди да започнете ново сливане." -#: builtin/merge.c:1232 +#: builtin/merge.c:1245 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)." msgstr "" "Не сте завършили отбиране на подаване (указателят „CHERRY_PICK_HEAD“\n" "съществува)." -#: builtin/merge.c:1241 +#: builtin/merge.c:1254 msgid "You cannot combine --squash with --no-ff." msgstr "Опцията „--squash“ е несъвместима с „--no-ff“." -#: builtin/merge.c:1249 +#: builtin/merge.c:1262 msgid "No commit specified and merge.defaultToUpstream not set." msgstr "" "Не е указано подаване и настройката „merge.defaultToUpstream“ не е зададена." -#: builtin/merge.c:1266 +#: builtin/merge.c:1279 msgid "Squash commit into empty head not supported yet" msgstr "Подаване със смачкване във връх без история все още не се поддържа" -#: builtin/merge.c:1268 +#: builtin/merge.c:1281 msgid "Non-fast-forward commit does not make sense into an empty head" msgstr "" "Понеже върхът е без история, всички сливания са тривиални, не може да се " "извърши нетривиално сливане изисквано от опцията „--no-ff“" -#: builtin/merge.c:1274 +#: builtin/merge.c:1286 #, c-format msgid "%s - not something we can merge" msgstr "„%s“ — не е нещо, което може да се слее" -#: builtin/merge.c:1276 +#: builtin/merge.c:1288 msgid "Can merge only exactly one commit into empty head" msgstr "Можете да слеете точно едно подаване във връх без история" -#: builtin/merge.c:1331 +#: builtin/merge.c:1344 #, c-format msgid "Commit %s has an untrusted GPG signature, allegedly by %s." msgstr "" "Подаването „%s“ е с недоверен подпис от GPG, който твърди, че е на „%s“." -#: builtin/merge.c:1334 +#: builtin/merge.c:1347 #, c-format msgid "Commit %s has a bad GPG signature allegedly by %s." msgstr "" "Подаването „%s“ е с неправилен подпис от GPG, който твърди, че е на „%s“." -#: builtin/merge.c:1337 +#: builtin/merge.c:1350 #, c-format msgid "Commit %s does not have a GPG signature." msgstr "Подаването „%s“ е без подпис от GPG." -#: builtin/merge.c:1340 +#: builtin/merge.c:1353 #, c-format msgid "Commit %s has a good GPG signature by %s\n" msgstr "Подаването „%s“ е с коректен подпис от GPG на „%s“.\n" -#: builtin/merge.c:1423 +#: builtin/merge.c:1415 +msgid "refusing to merge unrelated histories" +msgstr "независими истории не може да се слеят" + +#: builtin/merge.c:1439 #, c-format msgid "Updating %s..%s\n" msgstr "Обновяване „%s..%s“\n" -#: builtin/merge.c:1460 +#: builtin/merge.c:1476 #, c-format msgid "Trying really trivial in-index merge...\n" msgstr "Проба с най-тривиалното сливане в рамките на индекса…\n" # FIXME WTF message -#: builtin/merge.c:1467 +#: builtin/merge.c:1483 #, c-format msgid "Nope.\n" msgstr "Неуспешно сливане.\n" -#: builtin/merge.c:1499 +#: builtin/merge.c:1515 msgid "Not possible to fast-forward, aborting." msgstr "" "Не може да се извърши тривиално сливане, преустановяване на действието." -#: builtin/merge.c:1522 builtin/merge.c:1601 +#: builtin/merge.c:1538 builtin/merge.c:1617 #, c-format msgid "Rewinding the tree to pristine...\n" msgstr "Привеждане на дървото към първоначалното…\n" -#: builtin/merge.c:1526 +#: builtin/merge.c:1542 #, c-format msgid "Trying merge strategy %s...\n" msgstr "Пробване със стратегията за сливане „%s“…\n" -#: builtin/merge.c:1592 +#: builtin/merge.c:1608 #, c-format msgid "No merge strategy handled the merge.\n" msgstr "Никоя стратегия за сливане не може да извърши сливането.\n" -#: builtin/merge.c:1594 +#: builtin/merge.c:1610 #, c-format msgid "Merge with strategy %s failed.\n" msgstr "Неуспешно сливане със стратегия „%s“.\n" -#: builtin/merge.c:1603 +#: builtin/merge.c:1619 #, c-format msgid "Using the %s to prepare resolving by hand.\n" msgstr "" "Ползва се стратегията „%s“, която ще подготви дървото за коригиране на " "ръка.\n" -#: builtin/merge.c:1615 +#: builtin/merge.c:1631 #, c-format msgid "Automatic merge went well; stopped before committing as requested\n" msgstr "" @@ -8258,19 +8856,19 @@ msgstr "без предупреждения при конфликти" msgid "set labels for file1/orig-file/file2" msgstr "задаване на етикети за ФАЙЛ_1/ОРИГИНАЛ/ФАЙЛ_2" -#: builtin/mktree.c:64 +#: builtin/mktree.c:65 msgid "git mktree [-z] [--missing] [--batch]" msgstr "git mktree [-z] [--missing] [--batch]" -#: builtin/mktree.c:150 +#: builtin/mktree.c:152 msgid "input is NUL terminated" msgstr "входните записи са разделени с нулевия знак „NUL“" -#: builtin/mktree.c:151 builtin/write-tree.c:24 +#: builtin/mktree.c:153 builtin/write-tree.c:24 msgid "allow missing objects" msgstr "разрешаване на липсващи обекти" -#: builtin/mktree.c:152 +#: builtin/mktree.c:154 msgid "allow creation of more than one tree" msgstr "разрешаване на създаването на повече от едно дърво" @@ -8278,138 +8876,136 @@ msgstr "разрешаване на създаването на повече о msgid "git mv [] ... " msgstr "git mv [ОПЦИЯ…] ОБЕКТ… ЦЕЛ" -# FIXME message< -#: builtin/mv.c:69 +#: builtin/mv.c:70 #, c-format msgid "Directory %s is in index and no submodule?" msgstr "Директорията „%s“ е в индекса, но не е подмодул" -#: builtin/mv.c:71 +#: builtin/mv.c:72 builtin/rm.c:317 msgid "Please stage your changes to .gitmodules or stash them to proceed" msgstr "" "За да продължите, или вкарайте промените по файла „.gitmodules“ в индекса,\n" "или ги скатайте" -# FIXME message -#: builtin/mv.c:89 +#: builtin/mv.c:90 #, c-format msgid "%.*s is in index" msgstr "„%.*s“ вече е в индекса" -#: builtin/mv.c:111 +#: builtin/mv.c:112 msgid "force move/rename even if target exists" msgstr "принудително преместване/преименуване дори целта да съществува" -#: builtin/mv.c:112 +#: builtin/mv.c:113 msgid "skip move/rename errors" msgstr "прескачане на грешките при преместване/преименуване" -#: builtin/mv.c:151 +#: builtin/mv.c:152 #, c-format msgid "destination '%s' is not a directory" msgstr "целта „%s“ съществува и не е директория" -#: builtin/mv.c:162 +#: builtin/mv.c:163 #, c-format msgid "Checking rename of '%s' to '%s'\n" msgstr "Проверка на преименуването на обект от „%s“ на „%s“\n" -#: builtin/mv.c:166 +#: builtin/mv.c:167 msgid "bad source" msgstr "неправилен обект" -#: builtin/mv.c:169 +#: builtin/mv.c:170 msgid "can not move directory into itself" msgstr "директория не може да се премести в себе си" -#: builtin/mv.c:172 +#: builtin/mv.c:173 msgid "cannot move directory over file" msgstr "директория не може да се премести върху файл" -#: builtin/mv.c:181 +#: builtin/mv.c:182 msgid "source directory is empty" msgstr "първоначалната директория е празна" -#: builtin/mv.c:206 +#: builtin/mv.c:207 msgid "not under version control" msgstr "не е под контрола на Git" -#: builtin/mv.c:209 +#: builtin/mv.c:210 msgid "destination exists" msgstr "целта съществува" -#: builtin/mv.c:217 +#: builtin/mv.c:218 #, c-format msgid "overwriting '%s'" msgstr "презаписване на „%s“" -#: builtin/mv.c:220 +#: builtin/mv.c:221 msgid "Cannot overwrite" msgstr "Презаписването е невъзможно" -#: builtin/mv.c:223 +#: builtin/mv.c:224 msgid "multiple sources for the same target" msgstr "множество източници за една цел" -#: builtin/mv.c:225 +#: builtin/mv.c:226 msgid "destination directory does not exist" msgstr "целевата директория не съществува" -#: builtin/mv.c:232 +#: builtin/mv.c:233 #, c-format msgid "%s, source=%s, destination=%s" msgstr "%s, обект: „%s“, цел: „%s“" -#: builtin/mv.c:253 +#: builtin/mv.c:254 #, c-format msgid "Renaming %s to %s\n" msgstr "Преименуване на „%s“ на „%s“\n" -#: builtin/mv.c:256 builtin/remote.c:728 builtin/repack.c:365 +#: builtin/mv.c:260 builtin/remote.c:714 builtin/repack.c:365 #, c-format msgid "renaming '%s' failed" msgstr "неуспешно преименуване на „%s“" -#: builtin/name-rev.c:251 +#: builtin/name-rev.c:258 msgid "git name-rev [] ..." msgstr "git name-rev [ОПЦИЯ…] ПОДАВАНЕ…" -#: builtin/name-rev.c:252 +#: builtin/name-rev.c:259 msgid "git name-rev [] --all" msgstr "git name-rev [ОПЦИЯ…] --all" -#: builtin/name-rev.c:253 +#: builtin/name-rev.c:260 msgid "git name-rev [] --stdin" msgstr "git name-rev [ОПЦИЯ…] --stdin" # FIXME sha -#: builtin/name-rev.c:305 +#: builtin/name-rev.c:312 msgid "print only names (no SHA-1)" msgstr "извеждане само на имената (без сумите по SHA1)" -#: builtin/name-rev.c:306 +#: builtin/name-rev.c:313 msgid "only use tags to name the commits" msgstr "използване само на етикетите за именуване на подаванията" -#: builtin/name-rev.c:308 +#: builtin/name-rev.c:315 msgid "only use refs matching " -msgstr "използване само на шаблоните напасващи на ШАБЛОНа" +msgstr "използване само на указателите напасващи на ШАБЛОНа" -#: builtin/name-rev.c:310 +#: builtin/name-rev.c:317 msgid "list all commits reachable from all refs" msgstr "" "извеждане на всички подавания, които могат да бъдат достигнати от всички " "указатели" -#: builtin/name-rev.c:311 +#: builtin/name-rev.c:318 msgid "read from stdin" msgstr "четене от стандартния вход" -#: builtin/name-rev.c:312 +#: builtin/name-rev.c:319 msgid "allow to print `undefined` names (default)" msgstr "да се извеждат и недефинираните имена (стандартна стойност на опцията)" -#: builtin/name-rev.c:318 +#: builtin/name-rev.c:325 msgid "dereference tags in the input (internal use)" msgstr "извеждане на идентификаторите на обекти-етикети (за вътрешни нужди)" @@ -8557,24 +9153,16 @@ msgstr "обектът-бележка не може да бъде записан msgid "The note contents have been left in %s" msgstr "Съдържанието на бележката е във файла „%s“" -#: builtin/notes.c:232 builtin/tag.c:440 +#: builtin/notes.c:232 builtin/tag.c:439 #, c-format msgid "cannot read '%s'" msgstr "файлът „%s“ не може да бъде прочетен" -#: builtin/notes.c:234 builtin/tag.c:443 +#: builtin/notes.c:234 builtin/tag.c:442 #, c-format msgid "could not open or read '%s'" msgstr "файлът „%s“ не може да бъде отворен или прочетен" -#: builtin/notes.c:253 builtin/notes.c:304 builtin/notes.c:306 -#: builtin/notes.c:366 builtin/notes.c:421 builtin/notes.c:507 -#: builtin/notes.c:512 builtin/notes.c:590 builtin/notes.c:653 -#: builtin/notes.c:877 builtin/tag.c:456 -#, c-format -msgid "Failed to resolve '%s' as a valid ref." -msgstr "Не може да се открие към какво сочи „%s“." - #: builtin/notes.c:256 #, c-format msgid "Failed to read object '%s'." @@ -8586,42 +9174,42 @@ msgid "Cannot read note data from non-blob object '%s'." msgstr "" "Съдържанието на бележка не може да се вземе от обект, който не е BLOB: „%s“." -#: builtin/notes.c:359 builtin/notes.c:414 builtin/notes.c:490 -#: builtin/notes.c:502 builtin/notes.c:578 builtin/notes.c:646 -#: builtin/notes.c:942 +#: builtin/notes.c:362 builtin/notes.c:417 builtin/notes.c:493 +#: builtin/notes.c:505 builtin/notes.c:581 builtin/notes.c:649 +#: builtin/notes.c:946 msgid "too many parameters" msgstr "прекалено много параметри" -#: builtin/notes.c:372 builtin/notes.c:659 +#: builtin/notes.c:375 builtin/notes.c:662 #, c-format msgid "No note found for object %s." msgstr "Няма бележки за обекта „%s“." -#: builtin/notes.c:393 builtin/notes.c:556 +#: builtin/notes.c:396 builtin/notes.c:559 msgid "note contents as a string" msgstr "низ, който е съдържанието на бележката" -#: builtin/notes.c:396 builtin/notes.c:559 +#: builtin/notes.c:399 builtin/notes.c:562 msgid "note contents in a file" -msgstr "файл със съдържанието на бележката" +msgstr "ФАЙЛ със съдържанието на бележката" -#: builtin/notes.c:399 builtin/notes.c:562 +#: builtin/notes.c:402 builtin/notes.c:565 msgid "reuse and edit specified note object" -msgstr "преизползване и редактиране на указания обект-бележка" +msgstr "преизползване и редактиране на указания ОБЕКТ-бележка" -#: builtin/notes.c:402 builtin/notes.c:565 +#: builtin/notes.c:405 builtin/notes.c:568 msgid "reuse specified note object" -msgstr "преизползване на указания обект-бележка" +msgstr "преизползване на указания ОБЕКТ-бележка" -#: builtin/notes.c:405 builtin/notes.c:568 +#: builtin/notes.c:408 builtin/notes.c:571 msgid "allow storing empty note" msgstr "приемане и на празни бележки" -#: builtin/notes.c:406 builtin/notes.c:477 +#: builtin/notes.c:409 builtin/notes.c:480 msgid "replace existing notes" msgstr "замяна на съществуващите бележки" -#: builtin/notes.c:431 +#: builtin/notes.c:434 #, c-format msgid "" "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -8630,32 +9218,32 @@ msgstr "" "Не може да се добави бележка, защото такава вече съществува за обекта „%s“. " "Използвайте опцията „-f“, за да презапишете съществуващи бележки." -#: builtin/notes.c:446 builtin/notes.c:525 +#: builtin/notes.c:449 builtin/notes.c:528 #, c-format msgid "Overwriting existing notes for object %s\n" msgstr "Презаписване на съществуващите бележки за обекта „%s“\n" -#: builtin/notes.c:457 builtin/notes.c:618 builtin/notes.c:882 +#: builtin/notes.c:460 builtin/notes.c:621 builtin/notes.c:886 #, c-format msgid "Removing note for object %s\n" msgstr "Изтриване на бележката за обекта „%s“\n" -#: builtin/notes.c:478 +#: builtin/notes.c:481 msgid "read objects from stdin" msgstr "изчитане на обектите от стандартния вход" # FIXME imporve message -#: builtin/notes.c:480 +#: builtin/notes.c:483 msgid "load rewriting config for (implies --stdin)" msgstr "" "зареждане на настройките за КОМАНДАта, която презаписва подавания (включва " "опцията „--stdin“)" -#: builtin/notes.c:498 +#: builtin/notes.c:501 msgid "too few parameters" msgstr "прекалено малко параметри" -#: builtin/notes.c:519 +#: builtin/notes.c:522 #, c-format msgid "" "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite " @@ -8664,14 +9252,14 @@ msgstr "" "Не може да се копира бележка, защото такава вече съществува за обекта „%s“. " "Използвайте опцията „-f“, за да презапишете съществуващи бележки." -#: builtin/notes.c:531 +#: builtin/notes.c:534 #, c-format msgid "Missing notes on source object %s. Cannot copy." msgstr "" "Не може да се копира бележка, която не съществува — няма бележки за обекта-" "източник „%s“." -#: builtin/notes.c:583 +#: builtin/notes.c:586 #, c-format msgid "" "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n" @@ -8682,67 +9270,67 @@ msgstr "" "Вместо това ги използвайте с подкомандата „add“: „git notes add -f -m/-F/-c/-" "C“.\n" -#: builtin/notes.c:764 +#: builtin/notes.c:768 msgid "General options" msgstr "Общи опции" -#: builtin/notes.c:766 +#: builtin/notes.c:770 msgid "Merge options" msgstr "Опции при сливане" -#: builtin/notes.c:768 +#: builtin/notes.c:772 msgid "" "resolve notes conflicts using the given strategy (manual/ours/theirs/union/" "cat_sort_uniq)" msgstr "" -"коригиране на конфликтите при сливане на бележките чрез тази стратегия — " +"коригиране на конфликтите при сливане на бележките чрез тази СТРАТЕГИЯ — " "„manual“ (ръчно), „ours“ (вашата версия), „theirs“ (чуждата версия), " "„union“ (обединяване), „cat_sort_uniq“ (обединяване, подреждане, уникални " "резултати)" -#: builtin/notes.c:770 +#: builtin/notes.c:774 msgid "Committing unmerged notes" msgstr "Подаване на неслети бележки" -#: builtin/notes.c:772 +#: builtin/notes.c:776 msgid "finalize notes merge by committing unmerged notes" msgstr "завършване на сливането чрез подаване на неслети бележки" -#: builtin/notes.c:774 +#: builtin/notes.c:778 msgid "Aborting notes merge resolution" msgstr "Преустановяване на корекцията при сливането на бележки" -#: builtin/notes.c:776 +#: builtin/notes.c:780 msgid "abort notes merge" msgstr "преустановяване на сливането на бележки" -#: builtin/notes.c:853 +#: builtin/notes.c:857 #, c-format msgid "A notes merge into %s is already in-progress at %s" msgstr "В момента се извършва сливане на бележките в „%s“ при „%s“" -#: builtin/notes.c:880 +#: builtin/notes.c:884 #, c-format msgid "Object %s has no note\n" msgstr "Няма бележки за обекта „%s“\n" -#: builtin/notes.c:892 +#: builtin/notes.c:896 msgid "attempt to remove non-existent note is not an error" msgstr "опитът за изтриването на несъществуваща бележка не се счита за грешка" -#: builtin/notes.c:895 +#: builtin/notes.c:899 msgid "read object names from the standard input" msgstr "изчитане на имената на обектите от стандартния вход" -#: builtin/notes.c:976 +#: builtin/notes.c:980 msgid "notes-ref" msgstr "УКАЗАТЕЛ_ЗА_БЕЛЕЖКА" -#: builtin/notes.c:977 +#: builtin/notes.c:981 msgid "use notes from " msgstr "да се използва бележката сочена от този УКАЗАТЕЛ_ЗА_БЕЛЕЖКА" -#: builtin/notes.c:1012 builtin/remote.c:1647 +#: builtin/notes.c:1016 builtin/remote.c:1628 #, c-format msgid "Unknown subcommand: %s" msgstr "Непозната подкоманда: %s" @@ -8766,181 +9354,187 @@ msgstr "" msgid "deflate error (%d)" msgstr "грешка при декомпресиране с „deflate“ (%d)" -#: builtin/pack-objects.c:771 +#: builtin/pack-objects.c:763 +msgid "disabling bitmap writing, packs are split due to pack.packSizeLimit" +msgstr "" +"изключване на записването на битовата маска, пакетите са разделени поради " +"стойността на „pack.packSizeLimit“" + +#: builtin/pack-objects.c:776 msgid "Writing objects" msgstr "Записване на обектите" -#: builtin/pack-objects.c:1011 +#: builtin/pack-objects.c:1017 msgid "disabling bitmap writing, as some objects are not being packed" msgstr "" "изключване на записването на битовата маска, защото някои обекти няма да се " "пакетират" -#: builtin/pack-objects.c:2171 +#: builtin/pack-objects.c:2177 msgid "Compressing objects" msgstr "Компресиране на обектите" -#: builtin/pack-objects.c:2568 +#: builtin/pack-objects.c:2563 #, c-format msgid "unsupported index version %s" msgstr "неподдържана версия на индекса „%s“" -#: builtin/pack-objects.c:2572 +#: builtin/pack-objects.c:2567 #, c-format msgid "bad index version '%s'" msgstr "неправилна версия на индекса „%s“" -#: builtin/pack-objects.c:2602 +#: builtin/pack-objects.c:2597 msgid "do not show progress meter" msgstr "без извеждане на напредъка" -#: builtin/pack-objects.c:2604 +#: builtin/pack-objects.c:2599 msgid "show progress meter" msgstr "извеждане на напредъка" -#: builtin/pack-objects.c:2606 +#: builtin/pack-objects.c:2601 msgid "show progress meter during object writing phase" msgstr "извеждане на напредъка във фазата на запазване на обектите" -#: builtin/pack-objects.c:2609 +#: builtin/pack-objects.c:2604 msgid "similar to --all-progress when progress meter is shown" msgstr "" "същото действие като опцията „--all-progress“ при извеждането на напредъка" -#: builtin/pack-objects.c:2610 +#: builtin/pack-objects.c:2605 msgid "version[,offset]" msgstr "ВЕРСИЯ[,ОТМЕСТВАНЕ]" -#: builtin/pack-objects.c:2611 +#: builtin/pack-objects.c:2606 msgid "write the pack index file in the specified idx format version" msgstr "" "запазване на индекса на пакетните файлове във форма̀та с указаната версия" -#: builtin/pack-objects.c:2614 +#: builtin/pack-objects.c:2609 msgid "maximum size of each output pack file" msgstr "максимален размер на всеки пакетен файл" -#: builtin/pack-objects.c:2616 +#: builtin/pack-objects.c:2611 msgid "ignore borrowed objects from alternate object store" msgstr "игнориране на обектите заети от други хранилища на обекти" -#: builtin/pack-objects.c:2618 +#: builtin/pack-objects.c:2613 msgid "ignore packed objects" msgstr "игнориране на пакетираните обекти" -#: builtin/pack-objects.c:2620 +#: builtin/pack-objects.c:2615 msgid "limit pack window by objects" msgstr "ограничаване на прозореца за пакетиране по брой обекти" -#: builtin/pack-objects.c:2622 +#: builtin/pack-objects.c:2617 msgid "limit pack window by memory in addition to object limit" msgstr "" "ограничаване на прозореца за пакетиране и по памет освен по брой обекти" -#: builtin/pack-objects.c:2624 +#: builtin/pack-objects.c:2619 msgid "maximum length of delta chain allowed in the resulting pack" msgstr "" "максимална дължина на веригата от разлики, която е позволена в пакетния файл" -#: builtin/pack-objects.c:2626 +#: builtin/pack-objects.c:2621 msgid "reuse existing deltas" msgstr "преизползване на съществуващите разлики" -#: builtin/pack-objects.c:2628 +#: builtin/pack-objects.c:2623 msgid "reuse existing objects" msgstr "преизползване на съществуващите обекти" -#: builtin/pack-objects.c:2630 +#: builtin/pack-objects.c:2625 msgid "use OFS_DELTA objects" msgstr "използване на обекти „OFS_DELTA“" -#: builtin/pack-objects.c:2632 +#: builtin/pack-objects.c:2627 msgid "use threads when searching for best delta matches" msgstr "" "стартиране на нишки за претърсване на най-добрите съвпадения на разликите" -#: builtin/pack-objects.c:2634 +#: builtin/pack-objects.c:2629 msgid "do not create an empty pack output" msgstr "без създаване на празен пакетен файл" -#: builtin/pack-objects.c:2636 +#: builtin/pack-objects.c:2631 msgid "read revision arguments from standard input" msgstr "изчитане на версиите от стандартния вход" -#: builtin/pack-objects.c:2638 +#: builtin/pack-objects.c:2633 msgid "limit the objects to those that are not yet packed" msgstr "ограничаване до все още непакетираните обекти" -#: builtin/pack-objects.c:2641 +#: builtin/pack-objects.c:2636 msgid "include objects reachable from any reference" msgstr "" "включване на всички обекти, които могат да се достигнат от произволен " "указател" -#: builtin/pack-objects.c:2644 +#: builtin/pack-objects.c:2639 msgid "include objects referred by reflog entries" msgstr "включване и на обектите сочени от записите в журнала на указателите" -#: builtin/pack-objects.c:2647 +#: builtin/pack-objects.c:2642 msgid "include objects referred to by the index" msgstr "включване и на обектите сочени от индекса" -#: builtin/pack-objects.c:2650 +#: builtin/pack-objects.c:2645 msgid "output pack to stdout" msgstr "извеждане на пакета на стандартния изход" -#: builtin/pack-objects.c:2652 +#: builtin/pack-objects.c:2647 msgid "include tag objects that refer to objects to be packed" msgstr "" "включване и на обектите-етикети, които сочат към обектите, които ще бъдат " "пакетирани" -#: builtin/pack-objects.c:2654 +#: builtin/pack-objects.c:2649 msgid "keep unreachable objects" msgstr "запазване на недостижимите обекти" -#: builtin/pack-objects.c:2655 parse-options.h:142 +#: builtin/pack-objects.c:2650 parse-options.h:142 msgid "time" msgstr "ВРЕМЕ" -#: builtin/pack-objects.c:2656 +#: builtin/pack-objects.c:2651 msgid "unpack unreachable objects newer than